]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
Add top level changes for moxie
[mirror_qemu.git] / target-i386 / translate.c
CommitLineData
2c0262af
FB
1/*
2 * i386 translation
5fafdf24 3 *
2c0262af
FB
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2c0262af
FB
18 */
19#include <stdarg.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <inttypes.h>
24#include <signal.h>
2c0262af 25
bec93d72 26#include "qemu/host-utils.h"
2c0262af 27#include "cpu.h"
76cad711 28#include "disas/disas.h"
57fec1fe 29#include "tcg-op.h"
2c0262af 30
a7812ae4
PB
31#include "helper.h"
32#define GEN_HELPER 1
33#include "helper.h"
34
2c0262af
FB
35#define PREFIX_REPZ 0x01
36#define PREFIX_REPNZ 0x02
37#define PREFIX_LOCK 0x04
38#define PREFIX_DATA 0x08
39#define PREFIX_ADR 0x10
701ed211 40#define PREFIX_VEX 0x20
2c0262af 41
14ce26e7 42#ifdef TARGET_X86_64
14ce26e7
FB
43#define CODE64(s) ((s)->code64)
44#define REX_X(s) ((s)->rex_x)
45#define REX_B(s) ((s)->rex_b)
14ce26e7 46#else
14ce26e7
FB
47#define CODE64(s) 0
48#define REX_X(s) 0
49#define REX_B(s) 0
50#endif
51
bec93d72
RH
52#ifdef TARGET_X86_64
53# define ctztl ctz64
54# define clztl clz64
55#else
56# define ctztl ctz32
57# define clztl clz32
58#endif
59
57fec1fe
FB
60//#define MACRO_TEST 1
61
57fec1fe 62/* global register indexes */
a7812ae4 63static TCGv_ptr cpu_env;
a3251186 64static TCGv cpu_A0;
988c3eb0 65static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
a7812ae4 66static TCGv_i32 cpu_cc_op;
cc739bb0 67static TCGv cpu_regs[CPU_NB_REGS];
1e4840bf 68/* local temps */
3b9d3cf1 69static TCGv cpu_T[2];
57fec1fe 70/* local register indexes (only used inside old micro ops) */
a7812ae4
PB
71static TCGv cpu_tmp0, cpu_tmp4;
72static TCGv_ptr cpu_ptr0, cpu_ptr1;
73static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
74static TCGv_i64 cpu_tmp1_i64;
57fec1fe 75
1a7ff922
PB
76static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
77
022c62cb 78#include "exec/gen-icount.h"
2e70f6ef 79
57fec1fe
FB
80#ifdef TARGET_X86_64
81static int x86_64_hregs;
ae063a68
FB
82#endif
83
2c0262af
FB
84typedef struct DisasContext {
85 /* current insn context */
86 int override; /* -1 if no override */
87 int prefix;
88 int aflag, dflag;
14ce26e7 89 target_ulong pc; /* pc = eip + cs_base */
2c0262af
FB
90 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
91 static state change (stop translation) */
92 /* current block context */
14ce26e7 93 target_ulong cs_base; /* base of CS segment */
2c0262af
FB
94 int pe; /* protected mode */
95 int code32; /* 32 bit code segment */
14ce26e7
FB
96#ifdef TARGET_X86_64
97 int lma; /* long mode active */
98 int code64; /* 64 bit code segment */
99 int rex_x, rex_b;
100#endif
701ed211
RH
101 int vex_l; /* vex vector length */
102 int vex_v; /* vex vvvv register, without 1's compliment. */
2c0262af 103 int ss32; /* 32 bit stack segment */
fee71888 104 CCOp cc_op; /* current CC operation */
e207582f 105 bool cc_op_dirty;
2c0262af
FB
106 int addseg; /* non zero if either DS/ES/SS have a non zero base */
107 int f_st; /* currently unused */
108 int vm86; /* vm86 mode */
109 int cpl;
110 int iopl;
111 int tf; /* TF cpu flag */
34865134 112 int singlestep_enabled; /* "hardware" single step enabled */
2c0262af
FB
113 int jmp_opt; /* use direct block chaining for direct jumps */
114 int mem_index; /* select memory access functions */
c068688b 115 uint64_t flags; /* all execution flags */
2c0262af
FB
116 struct TranslationBlock *tb;
117 int popl_esp_hack; /* for correct popl with esp base handling */
14ce26e7
FB
118 int rip_offset; /* only used in x86_64, but left for simplicity */
119 int cpuid_features;
3d7374c5 120 int cpuid_ext_features;
e771edab 121 int cpuid_ext2_features;
12e26b75 122 int cpuid_ext3_features;
a9321a4d 123 int cpuid_7_0_ebx_features;
2c0262af
FB
124} DisasContext;
125
126static void gen_eob(DisasContext *s);
14ce26e7
FB
127static void gen_jmp(DisasContext *s, target_ulong eip);
128static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
63633fe6 129static void gen_op(DisasContext *s1, int op, int ot, int d);
2c0262af
FB
130
131/* i386 arith/logic operations */
132enum {
5fafdf24
TS
133 OP_ADDL,
134 OP_ORL,
135 OP_ADCL,
2c0262af 136 OP_SBBL,
5fafdf24
TS
137 OP_ANDL,
138 OP_SUBL,
139 OP_XORL,
2c0262af
FB
140 OP_CMPL,
141};
142
143/* i386 shift ops */
144enum {
5fafdf24
TS
145 OP_ROL,
146 OP_ROR,
147 OP_RCL,
148 OP_RCR,
149 OP_SHL,
150 OP_SHR,
2c0262af
FB
151 OP_SHL1, /* undocumented */
152 OP_SAR = 7,
153};
154
8e1c85e3
FB
155enum {
156 JCC_O,
157 JCC_B,
158 JCC_Z,
159 JCC_BE,
160 JCC_S,
161 JCC_P,
162 JCC_L,
163 JCC_LE,
164};
165
2c0262af
FB
166/* operand size */
167enum {
168 OT_BYTE = 0,
169 OT_WORD,
5fafdf24 170 OT_LONG,
2c0262af
FB
171 OT_QUAD,
172};
173
174enum {
175 /* I386 int registers */
176 OR_EAX, /* MUST be even numbered */
177 OR_ECX,
178 OR_EDX,
179 OR_EBX,
180 OR_ESP,
181 OR_EBP,
182 OR_ESI,
183 OR_EDI,
14ce26e7
FB
184
185 OR_TMP0 = 16, /* temporary operand register */
2c0262af
FB
186 OR_TMP1,
187 OR_A0, /* temporary register used when doing address evaluation */
2c0262af
FB
188};
189
b666265b 190enum {
a3251186
RH
191 USES_CC_DST = 1,
192 USES_CC_SRC = 2,
988c3eb0
RH
193 USES_CC_SRC2 = 4,
194 USES_CC_SRCT = 8,
b666265b
RH
195};
196
197/* Bit set if the global variable is live after setting CC_OP to X. */
198static const uint8_t cc_op_live[CC_OP_NB] = {
988c3eb0 199 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
b666265b
RH
200 [CC_OP_EFLAGS] = USES_CC_SRC,
201 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
202 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
988c3eb0 203 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
a3251186 204 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
988c3eb0 205 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
b666265b
RH
206 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
207 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
208 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
209 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
210 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
bc4b43dc 211 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
cd7f97ca
RH
212 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
213 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
214 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
436ff2d2 215 [CC_OP_CLR] = 0,
b666265b
RH
216};
217
e207582f 218static void set_cc_op(DisasContext *s, CCOp op)
3ca51d07 219{
b666265b
RH
220 int dead;
221
222 if (s->cc_op == op) {
223 return;
224 }
225
226 /* Discard CC computation that will no longer be used. */
227 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
228 if (dead & USES_CC_DST) {
229 tcg_gen_discard_tl(cpu_cc_dst);
e207582f 230 }
b666265b
RH
231 if (dead & USES_CC_SRC) {
232 tcg_gen_discard_tl(cpu_cc_src);
233 }
988c3eb0
RH
234 if (dead & USES_CC_SRC2) {
235 tcg_gen_discard_tl(cpu_cc_src2);
236 }
a3251186
RH
237 if (dead & USES_CC_SRCT) {
238 tcg_gen_discard_tl(cpu_cc_srcT);
239 }
b666265b 240
e2f515cf
RH
241 if (op == CC_OP_DYNAMIC) {
242 /* The DYNAMIC setting is translator only, and should never be
243 stored. Thus we always consider it clean. */
244 s->cc_op_dirty = false;
245 } else {
246 /* Discard any computed CC_OP value (see shifts). */
247 if (s->cc_op == CC_OP_DYNAMIC) {
248 tcg_gen_discard_i32(cpu_cc_op);
249 }
250 s->cc_op_dirty = true;
251 }
b666265b 252 s->cc_op = op;
e207582f
RH
253}
254
e207582f
RH
255static void gen_update_cc_op(DisasContext *s)
256{
257 if (s->cc_op_dirty) {
773cdfcc 258 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
e207582f
RH
259 s->cc_op_dirty = false;
260 }
3ca51d07
RH
261}
262
57fec1fe
FB
263static inline void gen_op_movl_T0_0(void)
264{
265 tcg_gen_movi_tl(cpu_T[0], 0);
266}
267
268static inline void gen_op_movl_T0_im(int32_t val)
269{
270 tcg_gen_movi_tl(cpu_T[0], val);
271}
272
273static inline void gen_op_movl_T0_imu(uint32_t val)
274{
275 tcg_gen_movi_tl(cpu_T[0], val);
276}
277
278static inline void gen_op_movl_T1_im(int32_t val)
279{
280 tcg_gen_movi_tl(cpu_T[1], val);
281}
282
283static inline void gen_op_movl_T1_imu(uint32_t val)
284{
285 tcg_gen_movi_tl(cpu_T[1], val);
286}
287
288static inline void gen_op_movl_A0_im(uint32_t val)
289{
290 tcg_gen_movi_tl(cpu_A0, val);
291}
292
293#ifdef TARGET_X86_64
294static inline void gen_op_movq_A0_im(int64_t val)
295{
296 tcg_gen_movi_tl(cpu_A0, val);
297}
298#endif
299
300static inline void gen_movtl_T0_im(target_ulong val)
301{
302 tcg_gen_movi_tl(cpu_T[0], val);
303}
304
305static inline void gen_movtl_T1_im(target_ulong val)
306{
307 tcg_gen_movi_tl(cpu_T[1], val);
308}
309
310static inline void gen_op_andl_T0_ffff(void)
311{
312 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
313}
314
315static inline void gen_op_andl_T0_im(uint32_t val)
316{
317 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
318}
319
320static inline void gen_op_movl_T0_T1(void)
321{
322 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
323}
324
325static inline void gen_op_andl_A0_ffff(void)
326{
327 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
328}
329
14ce26e7
FB
330#ifdef TARGET_X86_64
331
332#define NB_OP_SIZES 4
333
14ce26e7
FB
334#else /* !TARGET_X86_64 */
335
336#define NB_OP_SIZES 3
337
14ce26e7
FB
338#endif /* !TARGET_X86_64 */
339
e2542fe2 340#if defined(HOST_WORDS_BIGENDIAN)
57fec1fe
FB
341#define REG_B_OFFSET (sizeof(target_ulong) - 1)
342#define REG_H_OFFSET (sizeof(target_ulong) - 2)
343#define REG_W_OFFSET (sizeof(target_ulong) - 2)
344#define REG_L_OFFSET (sizeof(target_ulong) - 4)
345#define REG_LH_OFFSET (sizeof(target_ulong) - 8)
14ce26e7 346#else
57fec1fe
FB
347#define REG_B_OFFSET 0
348#define REG_H_OFFSET 1
349#define REG_W_OFFSET 0
350#define REG_L_OFFSET 0
351#define REG_LH_OFFSET 4
14ce26e7 352#endif
57fec1fe 353
96d7073f
PM
354/* In instruction encodings for byte register accesses the
355 * register number usually indicates "low 8 bits of register N";
356 * however there are some special cases where N 4..7 indicates
357 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
358 * true for this special case, false otherwise.
359 */
360static inline bool byte_reg_is_xH(int reg)
361{
362 if (reg < 4) {
363 return false;
364 }
365#ifdef TARGET_X86_64
366 if (reg >= 8 || x86_64_hregs) {
367 return false;
368 }
369#endif
370 return true;
371}
372
1e4840bf 373static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
57fec1fe
FB
374{
375 switch(ot) {
376 case OT_BYTE:
96d7073f 377 if (!byte_reg_is_xH(reg)) {
c832e3de 378 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
57fec1fe 379 } else {
c832e3de 380 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
57fec1fe
FB
381 }
382 break;
383 case OT_WORD:
c832e3de 384 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
57fec1fe 385 break;
cc739bb0 386 default: /* XXX this shouldn't be reached; abort? */
57fec1fe 387 case OT_LONG:
cc739bb0
LD
388 /* For x86_64, this sets the higher half of register to zero.
389 For i386, this is equivalent to a mov. */
390 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
57fec1fe 391 break;
cc739bb0 392#ifdef TARGET_X86_64
57fec1fe 393 case OT_QUAD:
cc739bb0 394 tcg_gen_mov_tl(cpu_regs[reg], t0);
57fec1fe 395 break;
14ce26e7 396#endif
57fec1fe
FB
397 }
398}
2c0262af 399
57fec1fe
FB
400static inline void gen_op_mov_reg_T0(int ot, int reg)
401{
1e4840bf 402 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
57fec1fe
FB
403}
404
405static inline void gen_op_mov_reg_T1(int ot, int reg)
406{
1e4840bf 407 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
57fec1fe
FB
408}
409
410static inline void gen_op_mov_reg_A0(int size, int reg)
411{
412 switch(size) {
93ab25d7 413 case OT_BYTE:
c832e3de 414 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
57fec1fe 415 break;
cc739bb0 416 default: /* XXX this shouldn't be reached; abort? */
93ab25d7 417 case OT_WORD:
cc739bb0
LD
418 /* For x86_64, this sets the higher half of register to zero.
419 For i386, this is equivalent to a mov. */
420 tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
57fec1fe 421 break;
cc739bb0 422#ifdef TARGET_X86_64
93ab25d7 423 case OT_LONG:
cc739bb0 424 tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
57fec1fe 425 break;
14ce26e7 426#endif
57fec1fe
FB
427 }
428}
429
1e4840bf 430static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
57fec1fe 431{
96d7073f
PM
432 if (ot == OT_BYTE && byte_reg_is_xH(reg)) {
433 tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
434 tcg_gen_ext8u_tl(t0, t0);
435 } else {
cc739bb0 436 tcg_gen_mov_tl(t0, cpu_regs[reg]);
57fec1fe
FB
437 }
438}
439
1e4840bf
FB
440static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
441{
442 gen_op_mov_v_reg(ot, cpu_T[t_index], reg);
443}
444
57fec1fe
FB
445static inline void gen_op_movl_A0_reg(int reg)
446{
cc739bb0 447 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
57fec1fe
FB
448}
449
450static inline void gen_op_addl_A0_im(int32_t val)
451{
452 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
14ce26e7 453#ifdef TARGET_X86_64
57fec1fe 454 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
14ce26e7 455#endif
57fec1fe 456}
2c0262af 457
14ce26e7 458#ifdef TARGET_X86_64
57fec1fe
FB
459static inline void gen_op_addq_A0_im(int64_t val)
460{
461 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
462}
14ce26e7 463#endif
57fec1fe
FB
464
465static void gen_add_A0_im(DisasContext *s, int val)
466{
467#ifdef TARGET_X86_64
468 if (CODE64(s))
469 gen_op_addq_A0_im(val);
470 else
471#endif
472 gen_op_addl_A0_im(val);
473}
2c0262af 474
57fec1fe 475static inline void gen_op_addl_T0_T1(void)
2c0262af 476{
57fec1fe
FB
477 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
478}
479
480static inline void gen_op_jmp_T0(void)
481{
317ac620 482 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
57fec1fe
FB
483}
484
6e0d8677 485static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
57fec1fe 486{
6e0d8677 487 switch(size) {
93ab25d7 488 case OT_BYTE:
cc739bb0 489 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
c832e3de 490 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
6e0d8677 491 break;
93ab25d7 492 case OT_WORD:
cc739bb0
LD
493 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
494 /* For x86_64, this sets the higher half of register to zero.
495 For i386, this is equivalent to a nop. */
496 tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
497 tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
6e0d8677
FB
498 break;
499#ifdef TARGET_X86_64
93ab25d7 500 case OT_LONG:
cc739bb0 501 tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
6e0d8677
FB
502 break;
503#endif
504 }
57fec1fe
FB
505}
506
6e0d8677 507static inline void gen_op_add_reg_T0(int size, int reg)
57fec1fe 508{
6e0d8677 509 switch(size) {
93ab25d7 510 case OT_BYTE:
cc739bb0 511 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
c832e3de 512 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
6e0d8677 513 break;
93ab25d7 514 case OT_WORD:
cc739bb0
LD
515 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
516 /* For x86_64, this sets the higher half of register to zero.
517 For i386, this is equivalent to a nop. */
518 tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
519 tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
6e0d8677 520 break;
14ce26e7 521#ifdef TARGET_X86_64
93ab25d7 522 case OT_LONG:
cc739bb0 523 tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
6e0d8677 524 break;
14ce26e7 525#endif
6e0d8677
FB
526 }
527}
57fec1fe 528
57fec1fe
FB
529static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
530{
cc739bb0
LD
531 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
532 if (shift != 0)
57fec1fe
FB
533 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
534 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
cc739bb0
LD
535 /* For x86_64, this sets the higher half of register to zero.
536 For i386, this is equivalent to a nop. */
537 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
57fec1fe 538}
2c0262af 539
57fec1fe
FB
540static inline void gen_op_movl_A0_seg(int reg)
541{
317ac620 542 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
57fec1fe 543}
2c0262af 544
7162ab21 545static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
57fec1fe 546{
317ac620 547 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
57fec1fe 548#ifdef TARGET_X86_64
7162ab21
VC
549 if (CODE64(s)) {
550 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
551 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
552 } else {
553 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
554 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
555 }
556#else
557 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
57fec1fe
FB
558#endif
559}
2c0262af 560
14ce26e7 561#ifdef TARGET_X86_64
57fec1fe
FB
562static inline void gen_op_movq_A0_seg(int reg)
563{
317ac620 564 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
57fec1fe 565}
14ce26e7 566
57fec1fe
FB
567static inline void gen_op_addq_A0_seg(int reg)
568{
317ac620 569 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
57fec1fe
FB
570 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
571}
572
573static inline void gen_op_movq_A0_reg(int reg)
574{
cc739bb0 575 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
57fec1fe
FB
576}
577
578static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
579{
cc739bb0
LD
580 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
581 if (shift != 0)
57fec1fe
FB
582 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
583 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
584}
14ce26e7
FB
585#endif
586
57fec1fe
FB
587static inline void gen_op_lds_T0_A0(int idx)
588{
589 int mem_index = (idx >> 2) - 1;
590 switch(idx & 3) {
93ab25d7 591 case OT_BYTE:
57fec1fe
FB
592 tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index);
593 break;
93ab25d7 594 case OT_WORD:
57fec1fe
FB
595 tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index);
596 break;
597 default:
93ab25d7 598 case OT_LONG:
57fec1fe
FB
599 tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index);
600 break;
601 }
602}
2c0262af 603
1e4840bf 604static inline void gen_op_ld_v(int idx, TCGv t0, TCGv a0)
57fec1fe
FB
605{
606 int mem_index = (idx >> 2) - 1;
607 switch(idx & 3) {
93ab25d7 608 case OT_BYTE:
1e4840bf 609 tcg_gen_qemu_ld8u(t0, a0, mem_index);
57fec1fe 610 break;
93ab25d7 611 case OT_WORD:
1e4840bf 612 tcg_gen_qemu_ld16u(t0, a0, mem_index);
57fec1fe 613 break;
93ab25d7 614 case OT_LONG:
1e4840bf 615 tcg_gen_qemu_ld32u(t0, a0, mem_index);
57fec1fe
FB
616 break;
617 default:
93ab25d7 618 case OT_QUAD:
a7812ae4
PB
619 /* Should never happen on 32-bit targets. */
620#ifdef TARGET_X86_64
1e4840bf 621 tcg_gen_qemu_ld64(t0, a0, mem_index);
a7812ae4 622#endif
57fec1fe
FB
623 break;
624 }
625}
2c0262af 626
1e4840bf
FB
627/* XXX: always use ldu or lds */
628static inline void gen_op_ld_T0_A0(int idx)
629{
630 gen_op_ld_v(idx, cpu_T[0], cpu_A0);
631}
632
57fec1fe
FB
633static inline void gen_op_ldu_T0_A0(int idx)
634{
1e4840bf 635 gen_op_ld_v(idx, cpu_T[0], cpu_A0);
57fec1fe 636}
2c0262af 637
57fec1fe 638static inline void gen_op_ld_T1_A0(int idx)
1e4840bf
FB
639{
640 gen_op_ld_v(idx, cpu_T[1], cpu_A0);
641}
642
643static inline void gen_op_st_v(int idx, TCGv t0, TCGv a0)
57fec1fe
FB
644{
645 int mem_index = (idx >> 2) - 1;
646 switch(idx & 3) {
93ab25d7 647 case OT_BYTE:
1e4840bf 648 tcg_gen_qemu_st8(t0, a0, mem_index);
57fec1fe 649 break;
93ab25d7 650 case OT_WORD:
1e4840bf 651 tcg_gen_qemu_st16(t0, a0, mem_index);
57fec1fe 652 break;
93ab25d7 653 case OT_LONG:
1e4840bf 654 tcg_gen_qemu_st32(t0, a0, mem_index);
57fec1fe
FB
655 break;
656 default:
93ab25d7 657 case OT_QUAD:
a7812ae4
PB
658 /* Should never happen on 32-bit targets. */
659#ifdef TARGET_X86_64
1e4840bf 660 tcg_gen_qemu_st64(t0, a0, mem_index);
a7812ae4 661#endif
57fec1fe
FB
662 break;
663 }
664}
4f31916f 665
57fec1fe
FB
666static inline void gen_op_st_T0_A0(int idx)
667{
1e4840bf 668 gen_op_st_v(idx, cpu_T[0], cpu_A0);
57fec1fe 669}
4f31916f 670
57fec1fe
FB
671static inline void gen_op_st_T1_A0(int idx)
672{
1e4840bf 673 gen_op_st_v(idx, cpu_T[1], cpu_A0);
57fec1fe 674}
4f31916f 675
14ce26e7
FB
676static inline void gen_jmp_im(target_ulong pc)
677{
57fec1fe 678 tcg_gen_movi_tl(cpu_tmp0, pc);
317ac620 679 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, eip));
14ce26e7
FB
680}
681
2c0262af
FB
682static inline void gen_string_movl_A0_ESI(DisasContext *s)
683{
684 int override;
685
686 override = s->override;
14ce26e7
FB
687#ifdef TARGET_X86_64
688 if (s->aflag == 2) {
689 if (override >= 0) {
57fec1fe
FB
690 gen_op_movq_A0_seg(override);
691 gen_op_addq_A0_reg_sN(0, R_ESI);
14ce26e7 692 } else {
57fec1fe 693 gen_op_movq_A0_reg(R_ESI);
14ce26e7
FB
694 }
695 } else
696#endif
2c0262af
FB
697 if (s->aflag) {
698 /* 32 bit address */
699 if (s->addseg && override < 0)
700 override = R_DS;
701 if (override >= 0) {
57fec1fe
FB
702 gen_op_movl_A0_seg(override);
703 gen_op_addl_A0_reg_sN(0, R_ESI);
2c0262af 704 } else {
57fec1fe 705 gen_op_movl_A0_reg(R_ESI);
2c0262af
FB
706 }
707 } else {
708 /* 16 address, always override */
709 if (override < 0)
710 override = R_DS;
57fec1fe 711 gen_op_movl_A0_reg(R_ESI);
2c0262af 712 gen_op_andl_A0_ffff();
7162ab21 713 gen_op_addl_A0_seg(s, override);
2c0262af
FB
714 }
715}
716
717static inline void gen_string_movl_A0_EDI(DisasContext *s)
718{
14ce26e7
FB
719#ifdef TARGET_X86_64
720 if (s->aflag == 2) {
57fec1fe 721 gen_op_movq_A0_reg(R_EDI);
14ce26e7
FB
722 } else
723#endif
2c0262af
FB
724 if (s->aflag) {
725 if (s->addseg) {
57fec1fe
FB
726 gen_op_movl_A0_seg(R_ES);
727 gen_op_addl_A0_reg_sN(0, R_EDI);
2c0262af 728 } else {
57fec1fe 729 gen_op_movl_A0_reg(R_EDI);
2c0262af
FB
730 }
731 } else {
57fec1fe 732 gen_op_movl_A0_reg(R_EDI);
2c0262af 733 gen_op_andl_A0_ffff();
7162ab21 734 gen_op_addl_A0_seg(s, R_ES);
2c0262af
FB
735 }
736}
737
6e0d8677
FB
738static inline void gen_op_movl_T0_Dshift(int ot)
739{
317ac620 740 tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
6e0d8677 741 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
2c0262af
FB
742};
743
d824df34 744static TCGv gen_ext_tl(TCGv dst, TCGv src, int size, bool sign)
6e0d8677 745{
d824df34 746 switch (size) {
6e0d8677 747 case OT_BYTE:
d824df34
PB
748 if (sign) {
749 tcg_gen_ext8s_tl(dst, src);
750 } else {
751 tcg_gen_ext8u_tl(dst, src);
752 }
753 return dst;
6e0d8677 754 case OT_WORD:
d824df34
PB
755 if (sign) {
756 tcg_gen_ext16s_tl(dst, src);
757 } else {
758 tcg_gen_ext16u_tl(dst, src);
759 }
760 return dst;
761#ifdef TARGET_X86_64
6e0d8677 762 case OT_LONG:
d824df34
PB
763 if (sign) {
764 tcg_gen_ext32s_tl(dst, src);
765 } else {
766 tcg_gen_ext32u_tl(dst, src);
767 }
768 return dst;
769#endif
6e0d8677 770 default:
d824df34 771 return src;
6e0d8677
FB
772 }
773}
3b46e624 774
d824df34
PB
775static void gen_extu(int ot, TCGv reg)
776{
777 gen_ext_tl(reg, reg, ot, false);
778}
779
6e0d8677
FB
780static void gen_exts(int ot, TCGv reg)
781{
d824df34 782 gen_ext_tl(reg, reg, ot, true);
6e0d8677 783}
2c0262af 784
6e0d8677
FB
785static inline void gen_op_jnz_ecx(int size, int label1)
786{
cc739bb0 787 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
6e0d8677 788 gen_extu(size + 1, cpu_tmp0);
cb63669a 789 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
6e0d8677
FB
790}
791
792static inline void gen_op_jz_ecx(int size, int label1)
793{
cc739bb0 794 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
6e0d8677 795 gen_extu(size + 1, cpu_tmp0);
cb63669a 796 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
6e0d8677 797}
2c0262af 798
a7812ae4
PB
799static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
800{
801 switch (ot) {
93ab25d7
PB
802 case OT_BYTE:
803 gen_helper_inb(v, n);
804 break;
805 case OT_WORD:
806 gen_helper_inw(v, n);
807 break;
808 case OT_LONG:
809 gen_helper_inl(v, n);
810 break;
a7812ae4 811 }
a7812ae4 812}
2c0262af 813
a7812ae4
PB
814static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
815{
816 switch (ot) {
93ab25d7
PB
817 case OT_BYTE:
818 gen_helper_outb(v, n);
819 break;
820 case OT_WORD:
821 gen_helper_outw(v, n);
822 break;
823 case OT_LONG:
824 gen_helper_outl(v, n);
825 break;
a7812ae4 826 }
a7812ae4 827}
f115e911 828
b8b6a50b
FB
829static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
830 uint32_t svm_flags)
f115e911 831{
b8b6a50b
FB
832 int state_saved;
833 target_ulong next_eip;
834
835 state_saved = 0;
f115e911 836 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
773cdfcc 837 gen_update_cc_op(s);
14ce26e7 838 gen_jmp_im(cur_eip);
b8b6a50b 839 state_saved = 1;
b6abf97d 840 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 841 switch (ot) {
93ab25d7 842 case OT_BYTE:
4a7443be
BS
843 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
844 break;
93ab25d7 845 case OT_WORD:
4a7443be
BS
846 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
847 break;
93ab25d7 848 case OT_LONG:
4a7443be
BS
849 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
850 break;
a7812ae4 851 }
b8b6a50b 852 }
872929aa 853 if(s->flags & HF_SVMI_MASK) {
b8b6a50b 854 if (!state_saved) {
773cdfcc 855 gen_update_cc_op(s);
b8b6a50b 856 gen_jmp_im(cur_eip);
b8b6a50b
FB
857 }
858 svm_flags |= (1 << (4 + ot));
859 next_eip = s->pc - s->cs_base;
b6abf97d 860 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
052e80d5
BS
861 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
862 tcg_const_i32(svm_flags),
a7812ae4 863 tcg_const_i32(next_eip - cur_eip));
f115e911
FB
864 }
865}
866
2c0262af
FB
867static inline void gen_movs(DisasContext *s, int ot)
868{
869 gen_string_movl_A0_ESI(s);
57fec1fe 870 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 871 gen_string_movl_A0_EDI(s);
57fec1fe 872 gen_op_st_T0_A0(ot + s->mem_index);
6e0d8677
FB
873 gen_op_movl_T0_Dshift(ot);
874 gen_op_add_reg_T0(s->aflag, R_ESI);
875 gen_op_add_reg_T0(s->aflag, R_EDI);
2c0262af
FB
876}
877
b6abf97d
FB
878static void gen_op_update1_cc(void)
879{
b6abf97d
FB
880 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
881}
882
883static void gen_op_update2_cc(void)
884{
885 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
886 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
887}
888
988c3eb0
RH
889static void gen_op_update3_cc(TCGv reg)
890{
891 tcg_gen_mov_tl(cpu_cc_src2, reg);
892 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
893 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
894}
895
b6abf97d
FB
896static inline void gen_op_testl_T0_T1_cc(void)
897{
b6abf97d
FB
898 tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
899}
900
901static void gen_op_update_neg_cc(void)
902{
b6abf97d 903 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
a3251186
RH
904 tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]);
905 tcg_gen_movi_tl(cpu_cc_srcT, 0);
b6abf97d
FB
906}
907
d229edce
RH
908/* compute all eflags to cc_src */
909static void gen_compute_eflags(DisasContext *s)
8e1c85e3 910{
988c3eb0 911 TCGv zero, dst, src1, src2;
db9f2597
RH
912 int live, dead;
913
d229edce
RH
914 if (s->cc_op == CC_OP_EFLAGS) {
915 return;
916 }
436ff2d2
RH
917 if (s->cc_op == CC_OP_CLR) {
918 tcg_gen_movi_tl(cpu_cc_src, CC_Z);
919 set_cc_op(s, CC_OP_EFLAGS);
920 return;
921 }
db9f2597
RH
922
923 TCGV_UNUSED(zero);
924 dst = cpu_cc_dst;
925 src1 = cpu_cc_src;
988c3eb0 926 src2 = cpu_cc_src2;
db9f2597
RH
927
928 /* Take care to not read values that are not live. */
929 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
988c3eb0 930 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
db9f2597
RH
931 if (dead) {
932 zero = tcg_const_tl(0);
933 if (dead & USES_CC_DST) {
934 dst = zero;
935 }
936 if (dead & USES_CC_SRC) {
937 src1 = zero;
938 }
988c3eb0
RH
939 if (dead & USES_CC_SRC2) {
940 src2 = zero;
941 }
db9f2597
RH
942 }
943
773cdfcc 944 gen_update_cc_op(s);
988c3eb0 945 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
d229edce 946 set_cc_op(s, CC_OP_EFLAGS);
db9f2597
RH
947
948 if (dead) {
949 tcg_temp_free(zero);
950 }
8e1c85e3
FB
951}
952
bec93d72
RH
953typedef struct CCPrepare {
954 TCGCond cond;
955 TCGv reg;
956 TCGv reg2;
957 target_ulong imm;
958 target_ulong mask;
959 bool use_reg2;
960 bool no_setcond;
961} CCPrepare;
962
06847f1f 963/* compute eflags.C to reg */
bec93d72 964static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
06847f1f
RH
965{
966 TCGv t0, t1;
bec93d72 967 int size, shift;
06847f1f
RH
968
969 switch (s->cc_op) {
970 case CC_OP_SUBB ... CC_OP_SUBQ:
a3251186 971 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
06847f1f
RH
972 size = s->cc_op - CC_OP_SUBB;
973 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
974 /* If no temporary was used, be careful not to alias t1 and t0. */
975 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
a3251186 976 tcg_gen_mov_tl(t0, cpu_cc_srcT);
06847f1f
RH
977 gen_extu(size, t0);
978 goto add_sub;
979
980 case CC_OP_ADDB ... CC_OP_ADDQ:
981 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
982 size = s->cc_op - CC_OP_ADDB;
983 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
984 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
985 add_sub:
bec93d72
RH
986 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
987 .reg2 = t1, .mask = -1, .use_reg2 = true };
06847f1f 988
06847f1f 989 case CC_OP_LOGICB ... CC_OP_LOGICQ:
436ff2d2 990 case CC_OP_CLR:
bec93d72 991 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
06847f1f
RH
992
993 case CC_OP_INCB ... CC_OP_INCQ:
994 case CC_OP_DECB ... CC_OP_DECQ:
bec93d72
RH
995 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
996 .mask = -1, .no_setcond = true };
06847f1f
RH
997
998 case CC_OP_SHLB ... CC_OP_SHLQ:
999 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
1000 size = s->cc_op - CC_OP_SHLB;
bec93d72
RH
1001 shift = (8 << size) - 1;
1002 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1003 .mask = (target_ulong)1 << shift };
06847f1f
RH
1004
1005 case CC_OP_MULB ... CC_OP_MULQ:
bec93d72
RH
1006 return (CCPrepare) { .cond = TCG_COND_NE,
1007 .reg = cpu_cc_src, .mask = -1 };
06847f1f 1008
bc4b43dc
RH
1009 case CC_OP_BMILGB ... CC_OP_BMILGQ:
1010 size = s->cc_op - CC_OP_BMILGB;
1011 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
1012 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
1013
cd7f97ca
RH
1014 case CC_OP_ADCX:
1015 case CC_OP_ADCOX:
1016 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
1017 .mask = -1, .no_setcond = true };
1018
06847f1f
RH
1019 case CC_OP_EFLAGS:
1020 case CC_OP_SARB ... CC_OP_SARQ:
1021 /* CC_SRC & 1 */
bec93d72
RH
1022 return (CCPrepare) { .cond = TCG_COND_NE,
1023 .reg = cpu_cc_src, .mask = CC_C };
06847f1f
RH
1024
1025 default:
1026 /* The need to compute only C from CC_OP_DYNAMIC is important
1027 in efficiently implementing e.g. INC at the start of a TB. */
1028 gen_update_cc_op(s);
988c3eb0
RH
1029 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
1030 cpu_cc_src2, cpu_cc_op);
bec93d72
RH
1031 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1032 .mask = -1, .no_setcond = true };
06847f1f
RH
1033 }
1034}
1035
1608ecca 1036/* compute eflags.P to reg */
bec93d72 1037static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
1608ecca 1038{
d229edce 1039 gen_compute_eflags(s);
bec93d72
RH
1040 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1041 .mask = CC_P };
1608ecca
PB
1042}
1043
1044/* compute eflags.S to reg */
bec93d72 1045static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
1608ecca 1046{
086c4077
RH
1047 switch (s->cc_op) {
1048 case CC_OP_DYNAMIC:
1049 gen_compute_eflags(s);
1050 /* FALLTHRU */
1051 case CC_OP_EFLAGS:
cd7f97ca
RH
1052 case CC_OP_ADCX:
1053 case CC_OP_ADOX:
1054 case CC_OP_ADCOX:
bec93d72
RH
1055 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1056 .mask = CC_S };
436ff2d2
RH
1057 case CC_OP_CLR:
1058 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
086c4077
RH
1059 default:
1060 {
1061 int size = (s->cc_op - CC_OP_ADDB) & 3;
1062 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
bec93d72 1063 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
086c4077 1064 }
086c4077 1065 }
1608ecca
PB
1066}
1067
1068/* compute eflags.O to reg */
bec93d72 1069static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
1608ecca 1070{
cd7f97ca
RH
1071 switch (s->cc_op) {
1072 case CC_OP_ADOX:
1073 case CC_OP_ADCOX:
1074 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
1075 .mask = -1, .no_setcond = true };
436ff2d2
RH
1076 case CC_OP_CLR:
1077 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
cd7f97ca
RH
1078 default:
1079 gen_compute_eflags(s);
1080 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1081 .mask = CC_O };
1082 }
1608ecca
PB
1083}
1084
1085/* compute eflags.Z to reg */
bec93d72 1086static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
1608ecca 1087{
086c4077
RH
1088 switch (s->cc_op) {
1089 case CC_OP_DYNAMIC:
1090 gen_compute_eflags(s);
1091 /* FALLTHRU */
1092 case CC_OP_EFLAGS:
cd7f97ca
RH
1093 case CC_OP_ADCX:
1094 case CC_OP_ADOX:
1095 case CC_OP_ADCOX:
bec93d72
RH
1096 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1097 .mask = CC_Z };
436ff2d2
RH
1098 case CC_OP_CLR:
1099 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
086c4077
RH
1100 default:
1101 {
1102 int size = (s->cc_op - CC_OP_ADDB) & 3;
1103 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
bec93d72 1104 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
086c4077 1105 }
bec93d72
RH
1106 }
1107}
1108
c365395e
PB
1109/* perform a conditional store into register 'reg' according to jump opcode
1110 value 'b'. In the fast case, T0 is guaranted not to be used. */
276e6b5f 1111static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
8e1c85e3 1112{
c365395e 1113 int inv, jcc_op, size, cond;
276e6b5f 1114 CCPrepare cc;
c365395e
PB
1115 TCGv t0;
1116
1117 inv = b & 1;
8e1c85e3 1118 jcc_op = (b >> 1) & 7;
c365395e
PB
1119
1120 switch (s->cc_op) {
69d1aa31
RH
1121 case CC_OP_SUBB ... CC_OP_SUBQ:
1122 /* We optimize relational operators for the cmp/jcc case. */
c365395e
PB
1123 size = s->cc_op - CC_OP_SUBB;
1124 switch (jcc_op) {
1125 case JCC_BE:
a3251186 1126 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
c365395e
PB
1127 gen_extu(size, cpu_tmp4);
1128 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
276e6b5f
RH
1129 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
1130 .reg2 = t0, .mask = -1, .use_reg2 = true };
c365395e 1131 break;
8e1c85e3 1132
c365395e 1133 case JCC_L:
276e6b5f 1134 cond = TCG_COND_LT;
c365395e
PB
1135 goto fast_jcc_l;
1136 case JCC_LE:
276e6b5f 1137 cond = TCG_COND_LE;
c365395e 1138 fast_jcc_l:
a3251186 1139 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
c365395e
PB
1140 gen_exts(size, cpu_tmp4);
1141 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
276e6b5f
RH
1142 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
1143 .reg2 = t0, .mask = -1, .use_reg2 = true };
c365395e 1144 break;
8e1c85e3 1145
c365395e 1146 default:
8e1c85e3 1147 goto slow_jcc;
c365395e 1148 }
8e1c85e3 1149 break;
c365395e 1150
8e1c85e3
FB
1151 default:
1152 slow_jcc:
69d1aa31
RH
1153 /* This actually generates good code for JC, JZ and JS. */
1154 switch (jcc_op) {
1155 case JCC_O:
1156 cc = gen_prepare_eflags_o(s, reg);
1157 break;
1158 case JCC_B:
1159 cc = gen_prepare_eflags_c(s, reg);
1160 break;
1161 case JCC_Z:
1162 cc = gen_prepare_eflags_z(s, reg);
1163 break;
1164 case JCC_BE:
1165 gen_compute_eflags(s);
1166 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1167 .mask = CC_Z | CC_C };
1168 break;
1169 case JCC_S:
1170 cc = gen_prepare_eflags_s(s, reg);
1171 break;
1172 case JCC_P:
1173 cc = gen_prepare_eflags_p(s, reg);
1174 break;
1175 case JCC_L:
1176 gen_compute_eflags(s);
1177 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1178 reg = cpu_tmp0;
1179 }
1180 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1181 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1182 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1183 .mask = CC_S };
1184 break;
1185 default:
1186 case JCC_LE:
1187 gen_compute_eflags(s);
1188 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1189 reg = cpu_tmp0;
1190 }
1191 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1192 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1193 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1194 .mask = CC_S | CC_Z };
1195 break;
1196 }
c365395e 1197 break;
8e1c85e3 1198 }
276e6b5f
RH
1199
1200 if (inv) {
1201 cc.cond = tcg_invert_cond(cc.cond);
1202 }
1203 return cc;
8e1c85e3
FB
1204}
1205
cc8b6f5b
PB
1206static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1207{
1208 CCPrepare cc = gen_prepare_cc(s, b, reg);
1209
1210 if (cc.no_setcond) {
1211 if (cc.cond == TCG_COND_EQ) {
1212 tcg_gen_xori_tl(reg, cc.reg, 1);
1213 } else {
1214 tcg_gen_mov_tl(reg, cc.reg);
1215 }
1216 return;
1217 }
1218
1219 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1220 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1221 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1222 tcg_gen_andi_tl(reg, reg, 1);
1223 return;
1224 }
1225 if (cc.mask != -1) {
1226 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1227 cc.reg = reg;
1228 }
1229 if (cc.use_reg2) {
1230 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1231 } else {
1232 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1233 }
1234}
1235
1236static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1237{
1238 gen_setcc1(s, JCC_B << 1, reg);
1239}
276e6b5f 1240
8e1c85e3
FB
1241/* generate a conditional jump to label 'l1' according to jump opcode
1242 value 'b'. In the fast case, T0 is guaranted not to be used. */
dc259201
RH
1243static inline void gen_jcc1_noeob(DisasContext *s, int b, int l1)
1244{
1245 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1246
1247 if (cc.mask != -1) {
1248 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1249 cc.reg = cpu_T[0];
1250 }
1251 if (cc.use_reg2) {
1252 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1253 } else {
1254 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1255 }
1256}
1257
1258/* Generate a conditional jump to label 'l1' according to jump opcode
1259 value 'b'. In the fast case, T0 is guaranted not to be used.
1260 A translation block must end soon. */
b27fc131 1261static inline void gen_jcc1(DisasContext *s, int b, int l1)
8e1c85e3 1262{
943131ca 1263 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
8e1c85e3 1264
dc259201 1265 gen_update_cc_op(s);
943131ca
PB
1266 if (cc.mask != -1) {
1267 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1268 cc.reg = cpu_T[0];
1269 }
dc259201 1270 set_cc_op(s, CC_OP_DYNAMIC);
943131ca
PB
1271 if (cc.use_reg2) {
1272 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1273 } else {
1274 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
8e1c85e3
FB
1275 }
1276}
1277
14ce26e7
FB
1278/* XXX: does not work with gdbstub "ice" single step - not a
1279 serious problem */
1280static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
2c0262af 1281{
14ce26e7
FB
1282 int l1, l2;
1283
1284 l1 = gen_new_label();
1285 l2 = gen_new_label();
6e0d8677 1286 gen_op_jnz_ecx(s->aflag, l1);
14ce26e7
FB
1287 gen_set_label(l2);
1288 gen_jmp_tb(s, next_eip, 1);
1289 gen_set_label(l1);
1290 return l2;
2c0262af
FB
1291}
1292
1293static inline void gen_stos(DisasContext *s, int ot)
1294{
57fec1fe 1295 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
2c0262af 1296 gen_string_movl_A0_EDI(s);
57fec1fe 1297 gen_op_st_T0_A0(ot + s->mem_index);
6e0d8677
FB
1298 gen_op_movl_T0_Dshift(ot);
1299 gen_op_add_reg_T0(s->aflag, R_EDI);
2c0262af
FB
1300}
1301
1302static inline void gen_lods(DisasContext *s, int ot)
1303{
1304 gen_string_movl_A0_ESI(s);
57fec1fe
FB
1305 gen_op_ld_T0_A0(ot + s->mem_index);
1306 gen_op_mov_reg_T0(ot, R_EAX);
6e0d8677
FB
1307 gen_op_movl_T0_Dshift(ot);
1308 gen_op_add_reg_T0(s->aflag, R_ESI);
2c0262af
FB
1309}
1310
1311static inline void gen_scas(DisasContext *s, int ot)
1312{
2c0262af 1313 gen_string_movl_A0_EDI(s);
57fec1fe 1314 gen_op_ld_T1_A0(ot + s->mem_index);
63633fe6 1315 gen_op(s, OP_CMPL, ot, R_EAX);
6e0d8677
FB
1316 gen_op_movl_T0_Dshift(ot);
1317 gen_op_add_reg_T0(s->aflag, R_EDI);
2c0262af
FB
1318}
1319
1320static inline void gen_cmps(DisasContext *s, int ot)
1321{
2c0262af 1322 gen_string_movl_A0_EDI(s);
57fec1fe 1323 gen_op_ld_T1_A0(ot + s->mem_index);
63633fe6
RH
1324 gen_string_movl_A0_ESI(s);
1325 gen_op(s, OP_CMPL, ot, OR_TMP0);
6e0d8677
FB
1326 gen_op_movl_T0_Dshift(ot);
1327 gen_op_add_reg_T0(s->aflag, R_ESI);
1328 gen_op_add_reg_T0(s->aflag, R_EDI);
2c0262af
FB
1329}
1330
1331static inline void gen_ins(DisasContext *s, int ot)
1332{
2e70f6ef
PB
1333 if (use_icount)
1334 gen_io_start();
2c0262af 1335 gen_string_movl_A0_EDI(s);
6e0d8677
FB
1336 /* Note: we must do this dummy write first to be restartable in
1337 case of page fault. */
9772c73b 1338 gen_op_movl_T0_0();
57fec1fe 1339 gen_op_st_T0_A0(ot + s->mem_index);
b8b6a50b 1340 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
b6abf97d
FB
1341 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1342 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
a7812ae4 1343 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
57fec1fe 1344 gen_op_st_T0_A0(ot + s->mem_index);
6e0d8677
FB
1345 gen_op_movl_T0_Dshift(ot);
1346 gen_op_add_reg_T0(s->aflag, R_EDI);
2e70f6ef
PB
1347 if (use_icount)
1348 gen_io_end();
2c0262af
FB
1349}
1350
1351static inline void gen_outs(DisasContext *s, int ot)
1352{
2e70f6ef
PB
1353 if (use_icount)
1354 gen_io_start();
2c0262af 1355 gen_string_movl_A0_ESI(s);
57fec1fe 1356 gen_op_ld_T0_A0(ot + s->mem_index);
b8b6a50b
FB
1357
1358 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
b6abf97d
FB
1359 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1360 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1361 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
a7812ae4 1362 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
b8b6a50b 1363
6e0d8677
FB
1364 gen_op_movl_T0_Dshift(ot);
1365 gen_op_add_reg_T0(s->aflag, R_ESI);
2e70f6ef
PB
1366 if (use_icount)
1367 gen_io_end();
2c0262af
FB
1368}
1369
1370/* same method as Valgrind : we generate jumps to current or next
1371 instruction */
1372#define GEN_REPZ(op) \
1373static inline void gen_repz_ ## op(DisasContext *s, int ot, \
14ce26e7 1374 target_ulong cur_eip, target_ulong next_eip) \
2c0262af 1375{ \
14ce26e7 1376 int l2;\
2c0262af 1377 gen_update_cc_op(s); \
14ce26e7 1378 l2 = gen_jz_ecx_string(s, next_eip); \
2c0262af 1379 gen_ ## op(s, ot); \
6e0d8677 1380 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
2c0262af
FB
1381 /* a loop would cause two single step exceptions if ECX = 1 \
1382 before rep string_insn */ \
1383 if (!s->jmp_opt) \
6e0d8677 1384 gen_op_jz_ecx(s->aflag, l2); \
2c0262af
FB
1385 gen_jmp(s, cur_eip); \
1386}
1387
1388#define GEN_REPZ2(op) \
1389static inline void gen_repz_ ## op(DisasContext *s, int ot, \
14ce26e7
FB
1390 target_ulong cur_eip, \
1391 target_ulong next_eip, \
2c0262af
FB
1392 int nz) \
1393{ \
14ce26e7 1394 int l2;\
2c0262af 1395 gen_update_cc_op(s); \
14ce26e7 1396 l2 = gen_jz_ecx_string(s, next_eip); \
2c0262af 1397 gen_ ## op(s, ot); \
6e0d8677 1398 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
773cdfcc 1399 gen_update_cc_op(s); \
b27fc131 1400 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
2c0262af 1401 if (!s->jmp_opt) \
6e0d8677 1402 gen_op_jz_ecx(s->aflag, l2); \
2c0262af
FB
1403 gen_jmp(s, cur_eip); \
1404}
1405
1406GEN_REPZ(movs)
1407GEN_REPZ(stos)
1408GEN_REPZ(lods)
1409GEN_REPZ(ins)
1410GEN_REPZ(outs)
1411GEN_REPZ2(scas)
1412GEN_REPZ2(cmps)
1413
a7812ae4
PB
1414static void gen_helper_fp_arith_ST0_FT0(int op)
1415{
1416 switch (op) {
d3eb5eae
BS
1417 case 0:
1418 gen_helper_fadd_ST0_FT0(cpu_env);
1419 break;
1420 case 1:
1421 gen_helper_fmul_ST0_FT0(cpu_env);
1422 break;
1423 case 2:
1424 gen_helper_fcom_ST0_FT0(cpu_env);
1425 break;
1426 case 3:
1427 gen_helper_fcom_ST0_FT0(cpu_env);
1428 break;
1429 case 4:
1430 gen_helper_fsub_ST0_FT0(cpu_env);
1431 break;
1432 case 5:
1433 gen_helper_fsubr_ST0_FT0(cpu_env);
1434 break;
1435 case 6:
1436 gen_helper_fdiv_ST0_FT0(cpu_env);
1437 break;
1438 case 7:
1439 gen_helper_fdivr_ST0_FT0(cpu_env);
1440 break;
a7812ae4
PB
1441 }
1442}
2c0262af
FB
1443
1444/* NOTE the exception in "r" op ordering */
a7812ae4
PB
1445static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1446{
1447 TCGv_i32 tmp = tcg_const_i32(opreg);
1448 switch (op) {
d3eb5eae
BS
1449 case 0:
1450 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1451 break;
1452 case 1:
1453 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1454 break;
1455 case 4:
1456 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1457 break;
1458 case 5:
1459 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1460 break;
1461 case 6:
1462 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1463 break;
1464 case 7:
1465 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1466 break;
a7812ae4
PB
1467 }
1468}
2c0262af
FB
1469
1470/* if d == OR_TMP0, it means memory operand (address in A0) */
1471static void gen_op(DisasContext *s1, int op, int ot, int d)
1472{
2c0262af 1473 if (d != OR_TMP0) {
57fec1fe 1474 gen_op_mov_TN_reg(ot, 0, d);
2c0262af 1475 } else {
57fec1fe 1476 gen_op_ld_T0_A0(ot + s1->mem_index);
2c0262af
FB
1477 }
1478 switch(op) {
1479 case OP_ADCL:
cc8b6f5b 1480 gen_compute_eflags_c(s1, cpu_tmp4);
cad3a37d
FB
1481 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1482 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1483 if (d != OR_TMP0)
1484 gen_op_mov_reg_T0(ot, d);
1485 else
1486 gen_op_st_T0_A0(ot + s1->mem_index);
988c3eb0
RH
1487 gen_op_update3_cc(cpu_tmp4);
1488 set_cc_op(s1, CC_OP_ADCB + ot);
cad3a37d 1489 break;
2c0262af 1490 case OP_SBBL:
cc8b6f5b 1491 gen_compute_eflags_c(s1, cpu_tmp4);
cad3a37d
FB
1492 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1493 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1494 if (d != OR_TMP0)
57fec1fe 1495 gen_op_mov_reg_T0(ot, d);
cad3a37d
FB
1496 else
1497 gen_op_st_T0_A0(ot + s1->mem_index);
988c3eb0
RH
1498 gen_op_update3_cc(cpu_tmp4);
1499 set_cc_op(s1, CC_OP_SBBB + ot);
cad3a37d 1500 break;
2c0262af
FB
1501 case OP_ADDL:
1502 gen_op_addl_T0_T1();
cad3a37d
FB
1503 if (d != OR_TMP0)
1504 gen_op_mov_reg_T0(ot, d);
1505 else
1506 gen_op_st_T0_A0(ot + s1->mem_index);
1507 gen_op_update2_cc();
3ca51d07 1508 set_cc_op(s1, CC_OP_ADDB + ot);
2c0262af
FB
1509 break;
1510 case OP_SUBL:
a3251186 1511 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
57fec1fe 1512 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
cad3a37d
FB
1513 if (d != OR_TMP0)
1514 gen_op_mov_reg_T0(ot, d);
1515 else
1516 gen_op_st_T0_A0(ot + s1->mem_index);
1517 gen_op_update2_cc();
3ca51d07 1518 set_cc_op(s1, CC_OP_SUBB + ot);
2c0262af
FB
1519 break;
1520 default:
1521 case OP_ANDL:
57fec1fe 1522 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
cad3a37d
FB
1523 if (d != OR_TMP0)
1524 gen_op_mov_reg_T0(ot, d);
1525 else
1526 gen_op_st_T0_A0(ot + s1->mem_index);
1527 gen_op_update1_cc();
3ca51d07 1528 set_cc_op(s1, CC_OP_LOGICB + ot);
57fec1fe 1529 break;
2c0262af 1530 case OP_ORL:
57fec1fe 1531 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
cad3a37d
FB
1532 if (d != OR_TMP0)
1533 gen_op_mov_reg_T0(ot, d);
1534 else
1535 gen_op_st_T0_A0(ot + s1->mem_index);
1536 gen_op_update1_cc();
3ca51d07 1537 set_cc_op(s1, CC_OP_LOGICB + ot);
57fec1fe 1538 break;
2c0262af 1539 case OP_XORL:
57fec1fe 1540 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
cad3a37d
FB
1541 if (d != OR_TMP0)
1542 gen_op_mov_reg_T0(ot, d);
1543 else
1544 gen_op_st_T0_A0(ot + s1->mem_index);
1545 gen_op_update1_cc();
3ca51d07 1546 set_cc_op(s1, CC_OP_LOGICB + ot);
2c0262af
FB
1547 break;
1548 case OP_CMPL:
63633fe6 1549 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
a3251186 1550 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
63633fe6 1551 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
3ca51d07 1552 set_cc_op(s1, CC_OP_SUBB + ot);
2c0262af
FB
1553 break;
1554 }
b6abf97d
FB
1555}
1556
2c0262af
FB
1557/* if d == OR_TMP0, it means memory operand (address in A0) */
1558static void gen_inc(DisasContext *s1, int ot, int d, int c)
1559{
1560 if (d != OR_TMP0)
57fec1fe 1561 gen_op_mov_TN_reg(ot, 0, d);
2c0262af 1562 else
57fec1fe 1563 gen_op_ld_T0_A0(ot + s1->mem_index);
cc8b6f5b 1564 gen_compute_eflags_c(s1, cpu_cc_src);
2c0262af 1565 if (c > 0) {
b6abf97d 1566 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
3ca51d07 1567 set_cc_op(s1, CC_OP_INCB + ot);
2c0262af 1568 } else {
b6abf97d 1569 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
3ca51d07 1570 set_cc_op(s1, CC_OP_DECB + ot);
2c0262af
FB
1571 }
1572 if (d != OR_TMP0)
57fec1fe 1573 gen_op_mov_reg_T0(ot, d);
2c0262af 1574 else
57fec1fe 1575 gen_op_st_T0_A0(ot + s1->mem_index);
cd31fefa 1576 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
2c0262af
FB
1577}
1578
f437d0a3
RH
1579static void gen_shift_flags(DisasContext *s, int ot, TCGv result, TCGv shm1,
1580 TCGv count, bool is_right)
1581{
1582 TCGv_i32 z32, s32, oldop;
1583 TCGv z_tl;
1584
1585 /* Store the results into the CC variables. If we know that the
1586 variable must be dead, store unconditionally. Otherwise we'll
1587 need to not disrupt the current contents. */
1588 z_tl = tcg_const_tl(0);
1589 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1590 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1591 result, cpu_cc_dst);
1592 } else {
1593 tcg_gen_mov_tl(cpu_cc_dst, result);
1594 }
1595 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1596 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1597 shm1, cpu_cc_src);
1598 } else {
1599 tcg_gen_mov_tl(cpu_cc_src, shm1);
1600 }
1601 tcg_temp_free(z_tl);
1602
1603 /* Get the two potential CC_OP values into temporaries. */
1604 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1605 if (s->cc_op == CC_OP_DYNAMIC) {
1606 oldop = cpu_cc_op;
1607 } else {
1608 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1609 oldop = cpu_tmp3_i32;
1610 }
1611
1612 /* Conditionally store the CC_OP value. */
1613 z32 = tcg_const_i32(0);
1614 s32 = tcg_temp_new_i32();
1615 tcg_gen_trunc_tl_i32(s32, count);
1616 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1617 tcg_temp_free_i32(z32);
1618 tcg_temp_free_i32(s32);
1619
1620 /* The CC_OP value is no longer predictable. */
1621 set_cc_op(s, CC_OP_DYNAMIC);
1622}
1623
b6abf97d
FB
1624static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
1625 int is_right, int is_arith)
2c0262af 1626{
a41f62f5 1627 target_ulong mask = (ot == OT_QUAD ? 0x3f : 0x1f);
3b46e624 1628
b6abf97d 1629 /* load */
82786041 1630 if (op1 == OR_TMP0) {
b6abf97d 1631 gen_op_ld_T0_A0(ot + s->mem_index);
82786041 1632 } else {
b6abf97d 1633 gen_op_mov_TN_reg(ot, 0, op1);
82786041 1634 }
b6abf97d 1635
a41f62f5
RH
1636 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1637 tcg_gen_subi_tl(cpu_tmp0, cpu_T[1], 1);
b6abf97d
FB
1638
1639 if (is_right) {
1640 if (is_arith) {
f484d386 1641 gen_exts(ot, cpu_T[0]);
a41f62f5
RH
1642 tcg_gen_sar_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1643 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
b6abf97d 1644 } else {
cad3a37d 1645 gen_extu(ot, cpu_T[0]);
a41f62f5
RH
1646 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1647 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
b6abf97d
FB
1648 }
1649 } else {
a41f62f5
RH
1650 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1651 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
b6abf97d
FB
1652 }
1653
1654 /* store */
82786041 1655 if (op1 == OR_TMP0) {
b6abf97d 1656 gen_op_st_T0_A0(ot + s->mem_index);
82786041 1657 } else {
b6abf97d 1658 gen_op_mov_reg_T0(ot, op1);
82786041
RH
1659 }
1660
f437d0a3 1661 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, cpu_T[1], is_right);
b6abf97d
FB
1662}
1663
c1c37968
FB
1664static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
1665 int is_right, int is_arith)
1666{
a41f62f5 1667 int mask = (ot == OT_QUAD ? 0x3f : 0x1f);
c1c37968
FB
1668
1669 /* load */
1670 if (op1 == OR_TMP0)
1671 gen_op_ld_T0_A0(ot + s->mem_index);
1672 else
1673 gen_op_mov_TN_reg(ot, 0, op1);
1674
1675 op2 &= mask;
1676 if (op2 != 0) {
1677 if (is_right) {
1678 if (is_arith) {
1679 gen_exts(ot, cpu_T[0]);
2a449d14 1680 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
c1c37968
FB
1681 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
1682 } else {
1683 gen_extu(ot, cpu_T[0]);
2a449d14 1684 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
c1c37968
FB
1685 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
1686 }
1687 } else {
2a449d14 1688 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
c1c37968
FB
1689 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
1690 }
1691 }
1692
1693 /* store */
1694 if (op1 == OR_TMP0)
1695 gen_op_st_T0_A0(ot + s->mem_index);
1696 else
1697 gen_op_mov_reg_T0(ot, op1);
1698
1699 /* update eflags if non zero shift */
1700 if (op2 != 0) {
2a449d14 1701 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
c1c37968 1702 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
3ca51d07 1703 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
c1c37968
FB
1704 }
1705}
1706
b6abf97d
FB
1707static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2)
1708{
1709 if (arg2 >= 0)
1710 tcg_gen_shli_tl(ret, arg1, arg2);
1711 else
1712 tcg_gen_shri_tl(ret, arg1, -arg2);
1713}
1714
34d80a55 1715static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
b6abf97d 1716{
34d80a55
RH
1717 target_ulong mask = (ot == OT_QUAD ? 0x3f : 0x1f);
1718 TCGv_i32 t0, t1;
b6abf97d
FB
1719
1720 /* load */
1e4840bf 1721 if (op1 == OR_TMP0) {
34d80a55 1722 gen_op_ld_T0_A0(ot + s->mem_index);
1e4840bf 1723 } else {
34d80a55 1724 gen_op_mov_TN_reg(ot, 0, op1);
1e4840bf 1725 }
b6abf97d 1726
34d80a55 1727 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
b6abf97d 1728
34d80a55
RH
1729 switch (ot) {
1730 case OT_BYTE:
1731 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1732 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
1733 tcg_gen_muli_tl(cpu_T[0], cpu_T[0], 0x01010101);
1734 goto do_long;
1735 case OT_WORD:
1736 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1737 tcg_gen_deposit_tl(cpu_T[0], cpu_T[0], cpu_T[0], 16, 16);
1738 goto do_long;
1739 do_long:
1740#ifdef TARGET_X86_64
1741 case OT_LONG:
1742 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1743 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
1744 if (is_right) {
1745 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1746 } else {
1747 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1748 }
1749 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1750 break;
1751#endif
1752 default:
1753 if (is_right) {
1754 tcg_gen_rotr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1755 } else {
1756 tcg_gen_rotl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1757 }
1758 break;
b6abf97d 1759 }
b6abf97d 1760
b6abf97d 1761 /* store */
1e4840bf 1762 if (op1 == OR_TMP0) {
34d80a55 1763 gen_op_st_T0_A0(ot + s->mem_index);
1e4840bf 1764 } else {
34d80a55 1765 gen_op_mov_reg_T0(ot, op1);
1e4840bf 1766 }
b6abf97d 1767
34d80a55
RH
1768 /* We'll need the flags computed into CC_SRC. */
1769 gen_compute_eflags(s);
b6abf97d 1770
34d80a55
RH
1771 /* The value that was "rotated out" is now present at the other end
1772 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1773 since we've computed the flags into CC_SRC, these variables are
1774 currently dead. */
b6abf97d 1775 if (is_right) {
34d80a55
RH
1776 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1777 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1778 } else {
1779 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1780 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
b6abf97d 1781 }
34d80a55
RH
1782 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1783 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1784
1785 /* Now conditionally store the new CC_OP value. If the shift count
1786 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1787 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1788 exactly as we computed above. */
1789 t0 = tcg_const_i32(0);
1790 t1 = tcg_temp_new_i32();
1791 tcg_gen_trunc_tl_i32(t1, cpu_T[1]);
1792 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1793 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1794 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1795 cpu_tmp2_i32, cpu_tmp3_i32);
1796 tcg_temp_free_i32(t0);
1797 tcg_temp_free_i32(t1);
1798
1799 /* The CC_OP value is no longer predictable. */
1800 set_cc_op(s, CC_OP_DYNAMIC);
b6abf97d
FB
1801}
1802
8cd6345d 1803static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
1804 int is_right)
1805{
34d80a55
RH
1806 int mask = (ot == OT_QUAD ? 0x3f : 0x1f);
1807 int shift;
8cd6345d 1808
1809 /* load */
1810 if (op1 == OR_TMP0) {
34d80a55 1811 gen_op_ld_T0_A0(ot + s->mem_index);
8cd6345d 1812 } else {
34d80a55 1813 gen_op_mov_TN_reg(ot, 0, op1);
8cd6345d 1814 }
1815
8cd6345d 1816 op2 &= mask;
8cd6345d 1817 if (op2 != 0) {
34d80a55
RH
1818 switch (ot) {
1819#ifdef TARGET_X86_64
1820 case OT_LONG:
1821 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1822 if (is_right) {
1823 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1824 } else {
1825 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1826 }
1827 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1828 break;
1829#endif
1830 default:
1831 if (is_right) {
1832 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], op2);
1833 } else {
1834 tcg_gen_rotli_tl(cpu_T[0], cpu_T[0], op2);
1835 }
1836 break;
1837 case OT_BYTE:
1838 mask = 7;
1839 goto do_shifts;
1840 case OT_WORD:
1841 mask = 15;
1842 do_shifts:
1843 shift = op2 & mask;
1844 if (is_right) {
1845 shift = mask + 1 - shift;
1846 }
1847 gen_extu(ot, cpu_T[0]);
1848 tcg_gen_shli_tl(cpu_tmp0, cpu_T[0], shift);
1849 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], mask + 1 - shift);
1850 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
1851 break;
8cd6345d 1852 }
8cd6345d 1853 }
1854
1855 /* store */
1856 if (op1 == OR_TMP0) {
34d80a55 1857 gen_op_st_T0_A0(ot + s->mem_index);
8cd6345d 1858 } else {
34d80a55 1859 gen_op_mov_reg_T0(ot, op1);
8cd6345d 1860 }
1861
1862 if (op2 != 0) {
34d80a55 1863 /* Compute the flags into CC_SRC. */
d229edce 1864 gen_compute_eflags(s);
0ff6addd 1865
34d80a55
RH
1866 /* The value that was "rotated out" is now present at the other end
1867 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1868 since we've computed the flags into CC_SRC, these variables are
1869 currently dead. */
8cd6345d 1870 if (is_right) {
34d80a55
RH
1871 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1872 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1873 } else {
1874 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1875 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
8cd6345d 1876 }
34d80a55
RH
1877 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1878 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1879 set_cc_op(s, CC_OP_ADCOX);
8cd6345d 1880 }
8cd6345d 1881}
1882
b6abf97d
FB
1883/* XXX: add faster immediate = 1 case */
1884static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
1885 int is_right)
1886{
d229edce 1887 gen_compute_eflags(s);
c7b3c873 1888 assert(s->cc_op == CC_OP_EFLAGS);
b6abf97d
FB
1889
1890 /* load */
1891 if (op1 == OR_TMP0)
1892 gen_op_ld_T0_A0(ot + s->mem_index);
1893 else
1894 gen_op_mov_TN_reg(ot, 0, op1);
1895
a7812ae4
PB
1896 if (is_right) {
1897 switch (ot) {
93ab25d7 1898 case OT_BYTE:
7923057b
BS
1899 gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1900 break;
93ab25d7 1901 case OT_WORD:
7923057b
BS
1902 gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1903 break;
93ab25d7 1904 case OT_LONG:
7923057b
BS
1905 gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1906 break;
a7812ae4 1907#ifdef TARGET_X86_64
93ab25d7 1908 case OT_QUAD:
7923057b
BS
1909 gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1910 break;
a7812ae4
PB
1911#endif
1912 }
1913 } else {
1914 switch (ot) {
93ab25d7 1915 case OT_BYTE:
7923057b
BS
1916 gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1917 break;
93ab25d7 1918 case OT_WORD:
7923057b
BS
1919 gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1920 break;
93ab25d7 1921 case OT_LONG:
7923057b
BS
1922 gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1923 break;
a7812ae4 1924#ifdef TARGET_X86_64
93ab25d7 1925 case OT_QUAD:
7923057b
BS
1926 gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1927 break;
a7812ae4
PB
1928#endif
1929 }
1930 }
b6abf97d
FB
1931 /* store */
1932 if (op1 == OR_TMP0)
1933 gen_op_st_T0_A0(ot + s->mem_index);
1934 else
1935 gen_op_mov_reg_T0(ot, op1);
b6abf97d
FB
1936}
1937
1938/* XXX: add faster immediate case */
3b9d3cf1 1939static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
f437d0a3 1940 bool is_right, TCGv count_in)
b6abf97d 1941{
f437d0a3
RH
1942 target_ulong mask = (ot == OT_QUAD ? 63 : 31);
1943 TCGv count;
b6abf97d
FB
1944
1945 /* load */
1e4840bf 1946 if (op1 == OR_TMP0) {
f437d0a3 1947 gen_op_ld_T0_A0(ot + s->mem_index);
1e4840bf 1948 } else {
f437d0a3 1949 gen_op_mov_TN_reg(ot, 0, op1);
1e4840bf 1950 }
b6abf97d 1951
f437d0a3
RH
1952 count = tcg_temp_new();
1953 tcg_gen_andi_tl(count, count_in, mask);
1e4840bf 1954
f437d0a3
RH
1955 switch (ot) {
1956 case OT_WORD:
1957 /* Note: we implement the Intel behaviour for shift count > 16.
1958 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1959 portion by constructing it as a 32-bit value. */
b6abf97d 1960 if (is_right) {
f437d0a3
RH
1961 tcg_gen_deposit_tl(cpu_tmp0, cpu_T[0], cpu_T[1], 16, 16);
1962 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1963 tcg_gen_mov_tl(cpu_T[0], cpu_tmp0);
b6abf97d 1964 } else {
f437d0a3 1965 tcg_gen_deposit_tl(cpu_T[1], cpu_T[0], cpu_T[1], 16, 16);
b6abf97d 1966 }
f437d0a3
RH
1967 /* FALLTHRU */
1968#ifdef TARGET_X86_64
1969 case OT_LONG:
1970 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1971 tcg_gen_subi_tl(cpu_tmp0, count, 1);
b6abf97d 1972 if (is_right) {
f437d0a3
RH
1973 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
1974 tcg_gen_shr_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1975 tcg_gen_shr_i64(cpu_T[0], cpu_T[0], count);
1976 } else {
1977 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[1], cpu_T[0]);
1978 tcg_gen_shl_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1979 tcg_gen_shl_i64(cpu_T[0], cpu_T[0], count);
1980 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1981 tcg_gen_shri_i64(cpu_T[0], cpu_T[0], 32);
1982 }
1983 break;
1984#endif
1985 default:
1986 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1987 if (is_right) {
1988 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
b6abf97d 1989
f437d0a3
RH
1990 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1991 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], count);
1992 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
b6abf97d 1993 } else {
f437d0a3
RH
1994 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1995 if (ot == OT_WORD) {
1996 /* Only needed if count > 16, for Intel behaviour. */
1997 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1998 tcg_gen_shr_tl(cpu_tmp4, cpu_T[1], cpu_tmp4);
1999 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
2000 }
2001
2002 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
2003 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], count);
2004 tcg_gen_shr_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
b6abf97d 2005 }
f437d0a3
RH
2006 tcg_gen_movi_tl(cpu_tmp4, 0);
2007 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[1], count, cpu_tmp4,
2008 cpu_tmp4, cpu_T[1]);
2009 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
2010 break;
b6abf97d 2011 }
b6abf97d 2012
b6abf97d 2013 /* store */
1e4840bf 2014 if (op1 == OR_TMP0) {
f437d0a3 2015 gen_op_st_T0_A0(ot + s->mem_index);
b6abf97d 2016 } else {
f437d0a3 2017 gen_op_mov_reg_T0(ot, op1);
b6abf97d 2018 }
1e4840bf 2019
f437d0a3
RH
2020 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, count, is_right);
2021 tcg_temp_free(count);
b6abf97d
FB
2022}
2023
2024static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
2025{
2026 if (s != OR_TMP1)
2027 gen_op_mov_TN_reg(ot, 1, s);
2028 switch(op) {
2029 case OP_ROL:
2030 gen_rot_rm_T1(s1, ot, d, 0);
2031 break;
2032 case OP_ROR:
2033 gen_rot_rm_T1(s1, ot, d, 1);
2034 break;
2035 case OP_SHL:
2036 case OP_SHL1:
2037 gen_shift_rm_T1(s1, ot, d, 0, 0);
2038 break;
2039 case OP_SHR:
2040 gen_shift_rm_T1(s1, ot, d, 1, 0);
2041 break;
2042 case OP_SAR:
2043 gen_shift_rm_T1(s1, ot, d, 1, 1);
2044 break;
2045 case OP_RCL:
2046 gen_rotc_rm_T1(s1, ot, d, 0);
2047 break;
2048 case OP_RCR:
2049 gen_rotc_rm_T1(s1, ot, d, 1);
2050 break;
2051 }
2c0262af
FB
2052}
2053
2054static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
2055{
c1c37968 2056 switch(op) {
8cd6345d 2057 case OP_ROL:
2058 gen_rot_rm_im(s1, ot, d, c, 0);
2059 break;
2060 case OP_ROR:
2061 gen_rot_rm_im(s1, ot, d, c, 1);
2062 break;
c1c37968
FB
2063 case OP_SHL:
2064 case OP_SHL1:
2065 gen_shift_rm_im(s1, ot, d, c, 0, 0);
2066 break;
2067 case OP_SHR:
2068 gen_shift_rm_im(s1, ot, d, c, 1, 0);
2069 break;
2070 case OP_SAR:
2071 gen_shift_rm_im(s1, ot, d, c, 1, 1);
2072 break;
2073 default:
2074 /* currently not optimized */
2075 gen_op_movl_T1_im(c);
2076 gen_shift(s1, op, ot, d, OR_TMP1);
2077 break;
2078 }
2c0262af
FB
2079}
2080
0af10c86
BS
2081static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm,
2082 int *reg_ptr, int *offset_ptr)
2c0262af 2083{
14ce26e7 2084 target_long disp;
2c0262af 2085 int havesib;
14ce26e7 2086 int base;
2c0262af
FB
2087 int index;
2088 int scale;
2089 int opreg;
2090 int mod, rm, code, override, must_add_seg;
2091
2092 override = s->override;
2093 must_add_seg = s->addseg;
2094 if (override >= 0)
2095 must_add_seg = 1;
2096 mod = (modrm >> 6) & 3;
2097 rm = modrm & 7;
2098
2099 if (s->aflag) {
2100
2101 havesib = 0;
2102 base = rm;
2103 index = 0;
2104 scale = 0;
3b46e624 2105
2c0262af
FB
2106 if (base == 4) {
2107 havesib = 1;
0af10c86 2108 code = cpu_ldub_code(env, s->pc++);
2c0262af 2109 scale = (code >> 6) & 3;
14ce26e7
FB
2110 index = ((code >> 3) & 7) | REX_X(s);
2111 base = (code & 7);
2c0262af 2112 }
14ce26e7 2113 base |= REX_B(s);
2c0262af
FB
2114
2115 switch (mod) {
2116 case 0:
14ce26e7 2117 if ((base & 7) == 5) {
2c0262af 2118 base = -1;
0af10c86 2119 disp = (int32_t)cpu_ldl_code(env, s->pc);
2c0262af 2120 s->pc += 4;
14ce26e7
FB
2121 if (CODE64(s) && !havesib) {
2122 disp += s->pc + s->rip_offset;
2123 }
2c0262af
FB
2124 } else {
2125 disp = 0;
2126 }
2127 break;
2128 case 1:
0af10c86 2129 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2c0262af
FB
2130 break;
2131 default:
2132 case 2:
0af10c86 2133 disp = (int32_t)cpu_ldl_code(env, s->pc);
2c0262af
FB
2134 s->pc += 4;
2135 break;
2136 }
3b46e624 2137
2c0262af
FB
2138 if (base >= 0) {
2139 /* for correct popl handling with esp */
2140 if (base == 4 && s->popl_esp_hack)
2141 disp += s->popl_esp_hack;
14ce26e7
FB
2142#ifdef TARGET_X86_64
2143 if (s->aflag == 2) {
57fec1fe 2144 gen_op_movq_A0_reg(base);
14ce26e7 2145 if (disp != 0) {
57fec1fe 2146 gen_op_addq_A0_im(disp);
14ce26e7 2147 }
5fafdf24 2148 } else
14ce26e7
FB
2149#endif
2150 {
57fec1fe 2151 gen_op_movl_A0_reg(base);
14ce26e7
FB
2152 if (disp != 0)
2153 gen_op_addl_A0_im(disp);
2154 }
2c0262af 2155 } else {
14ce26e7
FB
2156#ifdef TARGET_X86_64
2157 if (s->aflag == 2) {
57fec1fe 2158 gen_op_movq_A0_im(disp);
5fafdf24 2159 } else
14ce26e7
FB
2160#endif
2161 {
2162 gen_op_movl_A0_im(disp);
2163 }
2c0262af 2164 }
b16f827b
AJ
2165 /* index == 4 means no index */
2166 if (havesib && (index != 4)) {
14ce26e7
FB
2167#ifdef TARGET_X86_64
2168 if (s->aflag == 2) {
57fec1fe 2169 gen_op_addq_A0_reg_sN(scale, index);
5fafdf24 2170 } else
14ce26e7
FB
2171#endif
2172 {
57fec1fe 2173 gen_op_addl_A0_reg_sN(scale, index);
14ce26e7 2174 }
2c0262af
FB
2175 }
2176 if (must_add_seg) {
2177 if (override < 0) {
2178 if (base == R_EBP || base == R_ESP)
2179 override = R_SS;
2180 else
2181 override = R_DS;
2182 }
14ce26e7
FB
2183#ifdef TARGET_X86_64
2184 if (s->aflag == 2) {
57fec1fe 2185 gen_op_addq_A0_seg(override);
5fafdf24 2186 } else
14ce26e7
FB
2187#endif
2188 {
7162ab21 2189 gen_op_addl_A0_seg(s, override);
14ce26e7 2190 }
2c0262af
FB
2191 }
2192 } else {
2193 switch (mod) {
2194 case 0:
2195 if (rm == 6) {
0af10c86 2196 disp = cpu_lduw_code(env, s->pc);
2c0262af
FB
2197 s->pc += 2;
2198 gen_op_movl_A0_im(disp);
2199 rm = 0; /* avoid SS override */
2200 goto no_rm;
2201 } else {
2202 disp = 0;
2203 }
2204 break;
2205 case 1:
0af10c86 2206 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2c0262af
FB
2207 break;
2208 default:
2209 case 2:
0af10c86 2210 disp = cpu_lduw_code(env, s->pc);
2c0262af
FB
2211 s->pc += 2;
2212 break;
2213 }
2214 switch(rm) {
2215 case 0:
57fec1fe
FB
2216 gen_op_movl_A0_reg(R_EBX);
2217 gen_op_addl_A0_reg_sN(0, R_ESI);
2c0262af
FB
2218 break;
2219 case 1:
57fec1fe
FB
2220 gen_op_movl_A0_reg(R_EBX);
2221 gen_op_addl_A0_reg_sN(0, R_EDI);
2c0262af
FB
2222 break;
2223 case 2:
57fec1fe
FB
2224 gen_op_movl_A0_reg(R_EBP);
2225 gen_op_addl_A0_reg_sN(0, R_ESI);
2c0262af
FB
2226 break;
2227 case 3:
57fec1fe
FB
2228 gen_op_movl_A0_reg(R_EBP);
2229 gen_op_addl_A0_reg_sN(0, R_EDI);
2c0262af
FB
2230 break;
2231 case 4:
57fec1fe 2232 gen_op_movl_A0_reg(R_ESI);
2c0262af
FB
2233 break;
2234 case 5:
57fec1fe 2235 gen_op_movl_A0_reg(R_EDI);
2c0262af
FB
2236 break;
2237 case 6:
57fec1fe 2238 gen_op_movl_A0_reg(R_EBP);
2c0262af
FB
2239 break;
2240 default:
2241 case 7:
57fec1fe 2242 gen_op_movl_A0_reg(R_EBX);
2c0262af
FB
2243 break;
2244 }
2245 if (disp != 0)
2246 gen_op_addl_A0_im(disp);
2247 gen_op_andl_A0_ffff();
2248 no_rm:
2249 if (must_add_seg) {
2250 if (override < 0) {
2251 if (rm == 2 || rm == 3 || rm == 6)
2252 override = R_SS;
2253 else
2254 override = R_DS;
2255 }
7162ab21 2256 gen_op_addl_A0_seg(s, override);
2c0262af
FB
2257 }
2258 }
2259
2260 opreg = OR_A0;
2261 disp = 0;
2262 *reg_ptr = opreg;
2263 *offset_ptr = disp;
2264}
2265
0af10c86 2266static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
e17a36ce
FB
2267{
2268 int mod, rm, base, code;
2269
2270 mod = (modrm >> 6) & 3;
2271 if (mod == 3)
2272 return;
2273 rm = modrm & 7;
2274
2275 if (s->aflag) {
2276
2277 base = rm;
3b46e624 2278
e17a36ce 2279 if (base == 4) {
0af10c86 2280 code = cpu_ldub_code(env, s->pc++);
e17a36ce
FB
2281 base = (code & 7);
2282 }
3b46e624 2283
e17a36ce
FB
2284 switch (mod) {
2285 case 0:
2286 if (base == 5) {
2287 s->pc += 4;
2288 }
2289 break;
2290 case 1:
2291 s->pc++;
2292 break;
2293 default:
2294 case 2:
2295 s->pc += 4;
2296 break;
2297 }
2298 } else {
2299 switch (mod) {
2300 case 0:
2301 if (rm == 6) {
2302 s->pc += 2;
2303 }
2304 break;
2305 case 1:
2306 s->pc++;
2307 break;
2308 default:
2309 case 2:
2310 s->pc += 2;
2311 break;
2312 }
2313 }
2314}
2315
664e0f19
FB
2316/* used for LEA and MOV AX, mem */
2317static void gen_add_A0_ds_seg(DisasContext *s)
2318{
2319 int override, must_add_seg;
2320 must_add_seg = s->addseg;
2321 override = R_DS;
2322 if (s->override >= 0) {
2323 override = s->override;
2324 must_add_seg = 1;
664e0f19
FB
2325 }
2326 if (must_add_seg) {
8f091a59
FB
2327#ifdef TARGET_X86_64
2328 if (CODE64(s)) {
57fec1fe 2329 gen_op_addq_A0_seg(override);
5fafdf24 2330 } else
8f091a59
FB
2331#endif
2332 {
7162ab21 2333 gen_op_addl_A0_seg(s, override);
8f091a59 2334 }
664e0f19
FB
2335 }
2336}
2337
222a3336 2338/* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2c0262af 2339 OR_TMP0 */
0af10c86
BS
2340static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2341 int ot, int reg, int is_store)
2c0262af
FB
2342{
2343 int mod, rm, opreg, disp;
2344
2345 mod = (modrm >> 6) & 3;
14ce26e7 2346 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2347 if (mod == 3) {
2348 if (is_store) {
2349 if (reg != OR_TMP0)
57fec1fe
FB
2350 gen_op_mov_TN_reg(ot, 0, reg);
2351 gen_op_mov_reg_T0(ot, rm);
2c0262af 2352 } else {
57fec1fe 2353 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af 2354 if (reg != OR_TMP0)
57fec1fe 2355 gen_op_mov_reg_T0(ot, reg);
2c0262af
FB
2356 }
2357 } else {
0af10c86 2358 gen_lea_modrm(env, s, modrm, &opreg, &disp);
2c0262af
FB
2359 if (is_store) {
2360 if (reg != OR_TMP0)
57fec1fe
FB
2361 gen_op_mov_TN_reg(ot, 0, reg);
2362 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 2363 } else {
57fec1fe 2364 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 2365 if (reg != OR_TMP0)
57fec1fe 2366 gen_op_mov_reg_T0(ot, reg);
2c0262af
FB
2367 }
2368 }
2369}
2370
0af10c86 2371static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
2c0262af
FB
2372{
2373 uint32_t ret;
2374
2375 switch(ot) {
2376 case OT_BYTE:
0af10c86 2377 ret = cpu_ldub_code(env, s->pc);
2c0262af
FB
2378 s->pc++;
2379 break;
2380 case OT_WORD:
0af10c86 2381 ret = cpu_lduw_code(env, s->pc);
2c0262af
FB
2382 s->pc += 2;
2383 break;
2384 default:
2385 case OT_LONG:
0af10c86 2386 ret = cpu_ldl_code(env, s->pc);
2c0262af
FB
2387 s->pc += 4;
2388 break;
2389 }
2390 return ret;
2391}
2392
14ce26e7
FB
2393static inline int insn_const_size(unsigned int ot)
2394{
2395 if (ot <= OT_LONG)
2396 return 1 << ot;
2397 else
2398 return 4;
2399}
2400
6e256c93
FB
2401static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2402{
2403 TranslationBlock *tb;
2404 target_ulong pc;
2405
2406 pc = s->cs_base + eip;
2407 tb = s->tb;
2408 /* NOTE: we handle the case where the TB spans two pages here */
2409 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2410 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2411 /* jump to same page: we can use a direct jump */
57fec1fe 2412 tcg_gen_goto_tb(tb_num);
6e256c93 2413 gen_jmp_im(eip);
4b4a72e5 2414 tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
6e256c93
FB
2415 } else {
2416 /* jump to another page: currently not optimized */
2417 gen_jmp_im(eip);
2418 gen_eob(s);
2419 }
2420}
2421
5fafdf24 2422static inline void gen_jcc(DisasContext *s, int b,
14ce26e7 2423 target_ulong val, target_ulong next_eip)
2c0262af 2424{
b27fc131 2425 int l1, l2;
3b46e624 2426
2c0262af 2427 if (s->jmp_opt) {
14ce26e7 2428 l1 = gen_new_label();
b27fc131 2429 gen_jcc1(s, b, l1);
dc259201 2430
6e256c93 2431 gen_goto_tb(s, 0, next_eip);
14ce26e7
FB
2432
2433 gen_set_label(l1);
6e256c93 2434 gen_goto_tb(s, 1, val);
5779406a 2435 s->is_jmp = DISAS_TB_JUMP;
2c0262af 2436 } else {
14ce26e7
FB
2437 l1 = gen_new_label();
2438 l2 = gen_new_label();
b27fc131 2439 gen_jcc1(s, b, l1);
8e1c85e3 2440
14ce26e7 2441 gen_jmp_im(next_eip);
8e1c85e3
FB
2442 tcg_gen_br(l2);
2443
14ce26e7
FB
2444 gen_set_label(l1);
2445 gen_jmp_im(val);
2446 gen_set_label(l2);
2c0262af
FB
2447 gen_eob(s);
2448 }
2449}
2450
f32d3781
PB
2451static void gen_cmovcc1(CPUX86State *env, DisasContext *s, int ot, int b,
2452 int modrm, int reg)
2453{
57eb0cc8 2454 CCPrepare cc;
f32d3781 2455
57eb0cc8 2456 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
f32d3781 2457
57eb0cc8
RH
2458 cc = gen_prepare_cc(s, b, cpu_T[1]);
2459 if (cc.mask != -1) {
2460 TCGv t0 = tcg_temp_new();
2461 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2462 cc.reg = t0;
2463 }
2464 if (!cc.use_reg2) {
2465 cc.reg2 = tcg_const_tl(cc.imm);
f32d3781
PB
2466 }
2467
57eb0cc8
RH
2468 tcg_gen_movcond_tl(cc.cond, cpu_T[0], cc.reg, cc.reg2,
2469 cpu_T[0], cpu_regs[reg]);
2470 gen_op_mov_reg_T0(ot, reg);
2471
2472 if (cc.mask != -1) {
2473 tcg_temp_free(cc.reg);
2474 }
2475 if (!cc.use_reg2) {
2476 tcg_temp_free(cc.reg2);
2477 }
f32d3781
PB
2478}
2479
3bd7da9e
FB
2480static inline void gen_op_movl_T0_seg(int seg_reg)
2481{
2482 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
2483 offsetof(CPUX86State,segs[seg_reg].selector));
2484}
2485
2486static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2487{
2488 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
2489 tcg_gen_st32_tl(cpu_T[0], cpu_env,
2490 offsetof(CPUX86State,segs[seg_reg].selector));
2491 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
2492 tcg_gen_st_tl(cpu_T[0], cpu_env,
2493 offsetof(CPUX86State,segs[seg_reg].base));
2494}
2495
2c0262af
FB
2496/* move T0 to seg_reg and compute if the CPU state may change. Never
2497 call this function with seg_reg == R_CS */
14ce26e7 2498static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2c0262af 2499{
3415a4dd
FB
2500 if (s->pe && !s->vm86) {
2501 /* XXX: optimize by finding processor state dynamically */
773cdfcc 2502 gen_update_cc_op(s);
14ce26e7 2503 gen_jmp_im(cur_eip);
b6abf97d 2504 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 2505 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
dc196a57
FB
2506 /* abort translation because the addseg value may change or
2507 because ss32 may change. For R_SS, translation must always
2508 stop as a special handling must be done to disable hardware
2509 interrupts for the next instruction */
2510 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
5779406a 2511 s->is_jmp = DISAS_TB_JUMP;
3415a4dd 2512 } else {
3bd7da9e 2513 gen_op_movl_seg_T0_vm(seg_reg);
dc196a57 2514 if (seg_reg == R_SS)
5779406a 2515 s->is_jmp = DISAS_TB_JUMP;
3415a4dd 2516 }
2c0262af
FB
2517}
2518
0573fbfc
TS
2519static inline int svm_is_rep(int prefixes)
2520{
2521 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2522}
2523
872929aa 2524static inline void
0573fbfc 2525gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
b8b6a50b 2526 uint32_t type, uint64_t param)
0573fbfc 2527{
872929aa
FB
2528 /* no SVM activated; fast case */
2529 if (likely(!(s->flags & HF_SVMI_MASK)))
2530 return;
773cdfcc 2531 gen_update_cc_op(s);
872929aa 2532 gen_jmp_im(pc_start - s->cs_base);
052e80d5 2533 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
a7812ae4 2534 tcg_const_i64(param));
0573fbfc
TS
2535}
2536
872929aa 2537static inline void
0573fbfc
TS
2538gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2539{
872929aa 2540 gen_svm_check_intercept_param(s, pc_start, type, 0);
0573fbfc
TS
2541}
2542
4f31916f
FB
2543static inline void gen_stack_update(DisasContext *s, int addend)
2544{
14ce26e7
FB
2545#ifdef TARGET_X86_64
2546 if (CODE64(s)) {
6e0d8677 2547 gen_op_add_reg_im(2, R_ESP, addend);
14ce26e7
FB
2548 } else
2549#endif
4f31916f 2550 if (s->ss32) {
6e0d8677 2551 gen_op_add_reg_im(1, R_ESP, addend);
4f31916f 2552 } else {
6e0d8677 2553 gen_op_add_reg_im(0, R_ESP, addend);
4f31916f
FB
2554 }
2555}
2556
2c0262af
FB
2557/* generate a push. It depends on ss32, addseg and dflag */
2558static void gen_push_T0(DisasContext *s)
2559{
14ce26e7
FB
2560#ifdef TARGET_X86_64
2561 if (CODE64(s)) {
57fec1fe 2562 gen_op_movq_A0_reg(R_ESP);
8f091a59 2563 if (s->dflag) {
57fec1fe
FB
2564 gen_op_addq_A0_im(-8);
2565 gen_op_st_T0_A0(OT_QUAD + s->mem_index);
8f091a59 2566 } else {
57fec1fe
FB
2567 gen_op_addq_A0_im(-2);
2568 gen_op_st_T0_A0(OT_WORD + s->mem_index);
8f091a59 2569 }
57fec1fe 2570 gen_op_mov_reg_A0(2, R_ESP);
5fafdf24 2571 } else
14ce26e7
FB
2572#endif
2573 {
57fec1fe 2574 gen_op_movl_A0_reg(R_ESP);
14ce26e7 2575 if (!s->dflag)
57fec1fe 2576 gen_op_addl_A0_im(-2);
14ce26e7 2577 else
57fec1fe 2578 gen_op_addl_A0_im(-4);
14ce26e7
FB
2579 if (s->ss32) {
2580 if (s->addseg) {
bbf662ee 2581 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
7162ab21 2582 gen_op_addl_A0_seg(s, R_SS);
14ce26e7
FB
2583 }
2584 } else {
2585 gen_op_andl_A0_ffff();
bbf662ee 2586 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
7162ab21 2587 gen_op_addl_A0_seg(s, R_SS);
2c0262af 2588 }
57fec1fe 2589 gen_op_st_T0_A0(s->dflag + 1 + s->mem_index);
14ce26e7 2590 if (s->ss32 && !s->addseg)
57fec1fe 2591 gen_op_mov_reg_A0(1, R_ESP);
14ce26e7 2592 else
57fec1fe 2593 gen_op_mov_reg_T1(s->ss32 + 1, R_ESP);
2c0262af
FB
2594 }
2595}
2596
4f31916f
FB
2597/* generate a push. It depends on ss32, addseg and dflag */
2598/* slower version for T1, only used for call Ev */
2599static void gen_push_T1(DisasContext *s)
2c0262af 2600{
14ce26e7
FB
2601#ifdef TARGET_X86_64
2602 if (CODE64(s)) {
57fec1fe 2603 gen_op_movq_A0_reg(R_ESP);
8f091a59 2604 if (s->dflag) {
57fec1fe
FB
2605 gen_op_addq_A0_im(-8);
2606 gen_op_st_T1_A0(OT_QUAD + s->mem_index);
8f091a59 2607 } else {
57fec1fe
FB
2608 gen_op_addq_A0_im(-2);
2609 gen_op_st_T0_A0(OT_WORD + s->mem_index);
8f091a59 2610 }
57fec1fe 2611 gen_op_mov_reg_A0(2, R_ESP);
5fafdf24 2612 } else
14ce26e7
FB
2613#endif
2614 {
57fec1fe 2615 gen_op_movl_A0_reg(R_ESP);
14ce26e7 2616 if (!s->dflag)
57fec1fe 2617 gen_op_addl_A0_im(-2);
14ce26e7 2618 else
57fec1fe 2619 gen_op_addl_A0_im(-4);
14ce26e7
FB
2620 if (s->ss32) {
2621 if (s->addseg) {
7162ab21 2622 gen_op_addl_A0_seg(s, R_SS);
14ce26e7
FB
2623 }
2624 } else {
2625 gen_op_andl_A0_ffff();
7162ab21 2626 gen_op_addl_A0_seg(s, R_SS);
2c0262af 2627 }
57fec1fe 2628 gen_op_st_T1_A0(s->dflag + 1 + s->mem_index);
3b46e624 2629
14ce26e7 2630 if (s->ss32 && !s->addseg)
57fec1fe 2631 gen_op_mov_reg_A0(1, R_ESP);
14ce26e7
FB
2632 else
2633 gen_stack_update(s, (-2) << s->dflag);
2c0262af
FB
2634 }
2635}
2636
4f31916f
FB
2637/* two step pop is necessary for precise exceptions */
2638static void gen_pop_T0(DisasContext *s)
2c0262af 2639{
14ce26e7
FB
2640#ifdef TARGET_X86_64
2641 if (CODE64(s)) {
57fec1fe
FB
2642 gen_op_movq_A0_reg(R_ESP);
2643 gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index);
5fafdf24 2644 } else
14ce26e7
FB
2645#endif
2646 {
57fec1fe 2647 gen_op_movl_A0_reg(R_ESP);
14ce26e7
FB
2648 if (s->ss32) {
2649 if (s->addseg)
7162ab21 2650 gen_op_addl_A0_seg(s, R_SS);
14ce26e7
FB
2651 } else {
2652 gen_op_andl_A0_ffff();
7162ab21 2653 gen_op_addl_A0_seg(s, R_SS);
14ce26e7 2654 }
57fec1fe 2655 gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index);
2c0262af
FB
2656 }
2657}
2658
2659static void gen_pop_update(DisasContext *s)
2660{
14ce26e7 2661#ifdef TARGET_X86_64
8f091a59 2662 if (CODE64(s) && s->dflag) {
14ce26e7
FB
2663 gen_stack_update(s, 8);
2664 } else
2665#endif
2666 {
2667 gen_stack_update(s, 2 << s->dflag);
2668 }
2c0262af
FB
2669}
2670
2671static void gen_stack_A0(DisasContext *s)
2672{
57fec1fe 2673 gen_op_movl_A0_reg(R_ESP);
2c0262af
FB
2674 if (!s->ss32)
2675 gen_op_andl_A0_ffff();
bbf662ee 2676 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2c0262af 2677 if (s->addseg)
7162ab21 2678 gen_op_addl_A0_seg(s, R_SS);
2c0262af
FB
2679}
2680
2681/* NOTE: wrap around in 16 bit not fully handled */
2682static void gen_pusha(DisasContext *s)
2683{
2684 int i;
57fec1fe 2685 gen_op_movl_A0_reg(R_ESP);
2c0262af
FB
2686 gen_op_addl_A0_im(-16 << s->dflag);
2687 if (!s->ss32)
2688 gen_op_andl_A0_ffff();
bbf662ee 2689 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2c0262af 2690 if (s->addseg)
7162ab21 2691 gen_op_addl_A0_seg(s, R_SS);
2c0262af 2692 for(i = 0;i < 8; i++) {
57fec1fe
FB
2693 gen_op_mov_TN_reg(OT_LONG, 0, 7 - i);
2694 gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index);
2c0262af
FB
2695 gen_op_addl_A0_im(2 << s->dflag);
2696 }
57fec1fe 2697 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2c0262af
FB
2698}
2699
2700/* NOTE: wrap around in 16 bit not fully handled */
2701static void gen_popa(DisasContext *s)
2702{
2703 int i;
57fec1fe 2704 gen_op_movl_A0_reg(R_ESP);
2c0262af
FB
2705 if (!s->ss32)
2706 gen_op_andl_A0_ffff();
bbf662ee
FB
2707 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2708 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 << s->dflag);
2c0262af 2709 if (s->addseg)
7162ab21 2710 gen_op_addl_A0_seg(s, R_SS);
2c0262af
FB
2711 for(i = 0;i < 8; i++) {
2712 /* ESP is not reloaded */
2713 if (i != 3) {
57fec1fe
FB
2714 gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index);
2715 gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i);
2c0262af
FB
2716 }
2717 gen_op_addl_A0_im(2 << s->dflag);
2718 }
57fec1fe 2719 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2c0262af
FB
2720}
2721
2c0262af
FB
2722static void gen_enter(DisasContext *s, int esp_addend, int level)
2723{
61a8c4ec 2724 int ot, opsize;
2c0262af 2725
2c0262af 2726 level &= 0x1f;
8f091a59
FB
2727#ifdef TARGET_X86_64
2728 if (CODE64(s)) {
2729 ot = s->dflag ? OT_QUAD : OT_WORD;
2730 opsize = 1 << ot;
3b46e624 2731
57fec1fe 2732 gen_op_movl_A0_reg(R_ESP);
8f091a59 2733 gen_op_addq_A0_im(-opsize);
bbf662ee 2734 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
8f091a59
FB
2735
2736 /* push bp */
57fec1fe
FB
2737 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2738 gen_op_st_T0_A0(ot + s->mem_index);
8f091a59 2739 if (level) {
b5b38f61 2740 /* XXX: must save state */
2999a0b2 2741 gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
a7812ae4
PB
2742 tcg_const_i32((ot == OT_QUAD)),
2743 cpu_T[1]);
8f091a59 2744 }
57fec1fe 2745 gen_op_mov_reg_T1(ot, R_EBP);
bbf662ee 2746 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
57fec1fe 2747 gen_op_mov_reg_T1(OT_QUAD, R_ESP);
5fafdf24 2748 } else
8f091a59
FB
2749#endif
2750 {
2751 ot = s->dflag + OT_WORD;
2752 opsize = 2 << s->dflag;
3b46e624 2753
57fec1fe 2754 gen_op_movl_A0_reg(R_ESP);
8f091a59
FB
2755 gen_op_addl_A0_im(-opsize);
2756 if (!s->ss32)
2757 gen_op_andl_A0_ffff();
bbf662ee 2758 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
8f091a59 2759 if (s->addseg)
7162ab21 2760 gen_op_addl_A0_seg(s, R_SS);
8f091a59 2761 /* push bp */
57fec1fe
FB
2762 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2763 gen_op_st_T0_A0(ot + s->mem_index);
8f091a59 2764 if (level) {
b5b38f61 2765 /* XXX: must save state */
2999a0b2 2766 gen_helper_enter_level(cpu_env, tcg_const_i32(level),
a7812ae4
PB
2767 tcg_const_i32(s->dflag),
2768 cpu_T[1]);
8f091a59 2769 }
57fec1fe 2770 gen_op_mov_reg_T1(ot, R_EBP);
bbf662ee 2771 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
57fec1fe 2772 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2c0262af 2773 }
2c0262af
FB
2774}
2775
14ce26e7 2776static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2c0262af 2777{
773cdfcc 2778 gen_update_cc_op(s);
14ce26e7 2779 gen_jmp_im(cur_eip);
77b2bc2c 2780 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
5779406a 2781 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
2782}
2783
2784/* an interrupt is different from an exception because of the
7f75ffd3 2785 privilege checks */
5fafdf24 2786static void gen_interrupt(DisasContext *s, int intno,
14ce26e7 2787 target_ulong cur_eip, target_ulong next_eip)
2c0262af 2788{
773cdfcc 2789 gen_update_cc_op(s);
14ce26e7 2790 gen_jmp_im(cur_eip);
77b2bc2c 2791 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
a7812ae4 2792 tcg_const_i32(next_eip - cur_eip));
5779406a 2793 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
2794}
2795
14ce26e7 2796static void gen_debug(DisasContext *s, target_ulong cur_eip)
2c0262af 2797{
773cdfcc 2798 gen_update_cc_op(s);
14ce26e7 2799 gen_jmp_im(cur_eip);
4a7443be 2800 gen_helper_debug(cpu_env);
5779406a 2801 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
2802}
2803
2804/* generate a generic end of block. Trace exception is also generated
2805 if needed */
2806static void gen_eob(DisasContext *s)
2807{
773cdfcc 2808 gen_update_cc_op(s);
a2cc3b24 2809 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
f0967a1a 2810 gen_helper_reset_inhibit_irq(cpu_env);
a2cc3b24 2811 }
a2397807 2812 if (s->tb->flags & HF_RF_MASK) {
f0967a1a 2813 gen_helper_reset_rf(cpu_env);
a2397807 2814 }
34865134 2815 if (s->singlestep_enabled) {
4a7443be 2816 gen_helper_debug(cpu_env);
34865134 2817 } else if (s->tf) {
4a7443be 2818 gen_helper_single_step(cpu_env);
2c0262af 2819 } else {
57fec1fe 2820 tcg_gen_exit_tb(0);
2c0262af 2821 }
5779406a 2822 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
2823}
2824
2825/* generate a jump to eip. No segment change must happen before as a
2826 direct call to the next block may occur */
14ce26e7 2827static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2c0262af 2828{
a3251186
RH
2829 gen_update_cc_op(s);
2830 set_cc_op(s, CC_OP_DYNAMIC);
2c0262af 2831 if (s->jmp_opt) {
6e256c93 2832 gen_goto_tb(s, tb_num, eip);
5779406a 2833 s->is_jmp = DISAS_TB_JUMP;
2c0262af 2834 } else {
14ce26e7 2835 gen_jmp_im(eip);
2c0262af
FB
2836 gen_eob(s);
2837 }
2838}
2839
14ce26e7
FB
2840static void gen_jmp(DisasContext *s, target_ulong eip)
2841{
2842 gen_jmp_tb(s, eip, 0);
2843}
2844
8686c490
FB
2845static inline void gen_ldq_env_A0(int idx, int offset)
2846{
2847 int mem_index = (idx >> 2) - 1;
b6abf97d
FB
2848 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
2849 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
8686c490 2850}
664e0f19 2851
8686c490
FB
2852static inline void gen_stq_env_A0(int idx, int offset)
2853{
2854 int mem_index = (idx >> 2) - 1;
b6abf97d
FB
2855 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2856 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
8686c490 2857}
664e0f19 2858
8686c490
FB
2859static inline void gen_ldo_env_A0(int idx, int offset)
2860{
2861 int mem_index = (idx >> 2) - 1;
b6abf97d
FB
2862 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
2863 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
8686c490 2864 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
b6abf97d
FB
2865 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_tmp0, mem_index);
2866 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
8686c490 2867}
14ce26e7 2868
8686c490
FB
2869static inline void gen_sto_env_A0(int idx, int offset)
2870{
2871 int mem_index = (idx >> 2) - 1;
b6abf97d
FB
2872 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2873 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
8686c490 2874 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
b6abf97d
FB
2875 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2876 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_tmp0, mem_index);
8686c490 2877}
14ce26e7 2878
5af45186
FB
2879static inline void gen_op_movo(int d_offset, int s_offset)
2880{
b6abf97d
FB
2881 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2882 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2883 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8);
2884 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8);
5af45186
FB
2885}
2886
2887static inline void gen_op_movq(int d_offset, int s_offset)
2888{
b6abf97d
FB
2889 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2890 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
5af45186
FB
2891}
2892
2893static inline void gen_op_movl(int d_offset, int s_offset)
2894{
b6abf97d
FB
2895 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2896 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
5af45186
FB
2897}
2898
2899static inline void gen_op_movq_env_0(int d_offset)
2900{
b6abf97d
FB
2901 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2902 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
5af45186 2903}
664e0f19 2904
d3eb5eae
BS
2905typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2906typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2907typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2908typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2909typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2910typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2911 TCGv_i32 val);
c4baa050 2912typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
d3eb5eae
BS
2913typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2914 TCGv val);
c4baa050 2915
5af45186
FB
2916#define SSE_SPECIAL ((void *)1)
2917#define SSE_DUMMY ((void *)2)
664e0f19 2918
a7812ae4
PB
2919#define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2920#define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2921 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
5af45186 2922
d3eb5eae 2923static const SSEFunc_0_epp sse_op_table1[256][4] = {
a35f3ec7
AJ
2924 /* 3DNow! extensions */
2925 [0x0e] = { SSE_DUMMY }, /* femms */
2926 [0x0f] = { SSE_DUMMY }, /* pf... */
664e0f19
FB
2927 /* pure SSE operations */
2928 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2929 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
465e9838 2930 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
664e0f19 2931 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
a7812ae4
PB
2932 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2933 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
664e0f19
FB
2934 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2935 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2936
2937 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2938 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2939 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
d9f4bb27 2940 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
664e0f19
FB
2941 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2942 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
a7812ae4
PB
2943 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2944 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
664e0f19
FB
2945 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2946 [0x51] = SSE_FOP(sqrt),
a7812ae4
PB
2947 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2948 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2949 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2950 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2951 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2952 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
664e0f19
FB
2953 [0x58] = SSE_FOP(add),
2954 [0x59] = SSE_FOP(mul),
a7812ae4
PB
2955 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2956 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2957 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
664e0f19
FB
2958 [0x5c] = SSE_FOP(sub),
2959 [0x5d] = SSE_FOP(min),
2960 [0x5e] = SSE_FOP(div),
2961 [0x5f] = SSE_FOP(max),
2962
2963 [0xc2] = SSE_FOP(cmpeq),
d3eb5eae
BS
2964 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2965 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
664e0f19 2966
7073fbad
RH
2967 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2968 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2969 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
4242b1bd 2970
664e0f19
FB
2971 /* MMX ops and their SSE extensions */
2972 [0x60] = MMX_OP2(punpcklbw),
2973 [0x61] = MMX_OP2(punpcklwd),
2974 [0x62] = MMX_OP2(punpckldq),
2975 [0x63] = MMX_OP2(packsswb),
2976 [0x64] = MMX_OP2(pcmpgtb),
2977 [0x65] = MMX_OP2(pcmpgtw),
2978 [0x66] = MMX_OP2(pcmpgtl),
2979 [0x67] = MMX_OP2(packuswb),
2980 [0x68] = MMX_OP2(punpckhbw),
2981 [0x69] = MMX_OP2(punpckhwd),
2982 [0x6a] = MMX_OP2(punpckhdq),
2983 [0x6b] = MMX_OP2(packssdw),
a7812ae4
PB
2984 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2985 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
664e0f19
FB
2986 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2987 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
d3eb5eae
BS
2988 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2989 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2990 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2991 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
664e0f19
FB
2992 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2993 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2994 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2995 [0x74] = MMX_OP2(pcmpeqb),
2996 [0x75] = MMX_OP2(pcmpeqw),
2997 [0x76] = MMX_OP2(pcmpeql),
a35f3ec7 2998 [0x77] = { SSE_DUMMY }, /* emms */
d9f4bb27
AP
2999 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
3000 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
a7812ae4
PB
3001 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
3002 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
664e0f19
FB
3003 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
3004 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
3005 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
3006 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
a7812ae4 3007 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
664e0f19
FB
3008 [0xd1] = MMX_OP2(psrlw),
3009 [0xd2] = MMX_OP2(psrld),
3010 [0xd3] = MMX_OP2(psrlq),
3011 [0xd4] = MMX_OP2(paddq),
3012 [0xd5] = MMX_OP2(pmullw),
3013 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
3014 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
3015 [0xd8] = MMX_OP2(psubusb),
3016 [0xd9] = MMX_OP2(psubusw),
3017 [0xda] = MMX_OP2(pminub),
3018 [0xdb] = MMX_OP2(pand),
3019 [0xdc] = MMX_OP2(paddusb),
3020 [0xdd] = MMX_OP2(paddusw),
3021 [0xde] = MMX_OP2(pmaxub),
3022 [0xdf] = MMX_OP2(pandn),
3023 [0xe0] = MMX_OP2(pavgb),
3024 [0xe1] = MMX_OP2(psraw),
3025 [0xe2] = MMX_OP2(psrad),
3026 [0xe3] = MMX_OP2(pavgw),
3027 [0xe4] = MMX_OP2(pmulhuw),
3028 [0xe5] = MMX_OP2(pmulhw),
a7812ae4 3029 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
664e0f19
FB
3030 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
3031 [0xe8] = MMX_OP2(psubsb),
3032 [0xe9] = MMX_OP2(psubsw),
3033 [0xea] = MMX_OP2(pminsw),
3034 [0xeb] = MMX_OP2(por),
3035 [0xec] = MMX_OP2(paddsb),
3036 [0xed] = MMX_OP2(paddsw),
3037 [0xee] = MMX_OP2(pmaxsw),
3038 [0xef] = MMX_OP2(pxor),
465e9838 3039 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
664e0f19
FB
3040 [0xf1] = MMX_OP2(psllw),
3041 [0xf2] = MMX_OP2(pslld),
3042 [0xf3] = MMX_OP2(psllq),
3043 [0xf4] = MMX_OP2(pmuludq),
3044 [0xf5] = MMX_OP2(pmaddwd),
3045 [0xf6] = MMX_OP2(psadbw),
d3eb5eae
BS
3046 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
3047 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
664e0f19
FB
3048 [0xf8] = MMX_OP2(psubb),
3049 [0xf9] = MMX_OP2(psubw),
3050 [0xfa] = MMX_OP2(psubl),
3051 [0xfb] = MMX_OP2(psubq),
3052 [0xfc] = MMX_OP2(paddb),
3053 [0xfd] = MMX_OP2(paddw),
3054 [0xfe] = MMX_OP2(paddl),
3055};
3056
d3eb5eae 3057static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
664e0f19
FB
3058 [0 + 2] = MMX_OP2(psrlw),
3059 [0 + 4] = MMX_OP2(psraw),
3060 [0 + 6] = MMX_OP2(psllw),
3061 [8 + 2] = MMX_OP2(psrld),
3062 [8 + 4] = MMX_OP2(psrad),
3063 [8 + 6] = MMX_OP2(pslld),
3064 [16 + 2] = MMX_OP2(psrlq),
a7812ae4 3065 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
664e0f19 3066 [16 + 6] = MMX_OP2(psllq),
a7812ae4 3067 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
664e0f19
FB
3068};
3069
d3eb5eae 3070static const SSEFunc_0_epi sse_op_table3ai[] = {
a7812ae4 3071 gen_helper_cvtsi2ss,
11f8cdbc 3072 gen_helper_cvtsi2sd
c4baa050 3073};
a7812ae4 3074
11f8cdbc 3075#ifdef TARGET_X86_64
d3eb5eae 3076static const SSEFunc_0_epl sse_op_table3aq[] = {
11f8cdbc
SW
3077 gen_helper_cvtsq2ss,
3078 gen_helper_cvtsq2sd
3079};
3080#endif
3081
d3eb5eae 3082static const SSEFunc_i_ep sse_op_table3bi[] = {
a7812ae4 3083 gen_helper_cvttss2si,
a7812ae4 3084 gen_helper_cvtss2si,
bedc2ac1 3085 gen_helper_cvttsd2si,
11f8cdbc 3086 gen_helper_cvtsd2si
664e0f19 3087};
3b46e624 3088
11f8cdbc 3089#ifdef TARGET_X86_64
d3eb5eae 3090static const SSEFunc_l_ep sse_op_table3bq[] = {
11f8cdbc 3091 gen_helper_cvttss2sq,
11f8cdbc 3092 gen_helper_cvtss2sq,
bedc2ac1 3093 gen_helper_cvttsd2sq,
11f8cdbc
SW
3094 gen_helper_cvtsd2sq
3095};
3096#endif
3097
d3eb5eae 3098static const SSEFunc_0_epp sse_op_table4[8][4] = {
664e0f19
FB
3099 SSE_FOP(cmpeq),
3100 SSE_FOP(cmplt),
3101 SSE_FOP(cmple),
3102 SSE_FOP(cmpunord),
3103 SSE_FOP(cmpneq),
3104 SSE_FOP(cmpnlt),
3105 SSE_FOP(cmpnle),
3106 SSE_FOP(cmpord),
3107};
3b46e624 3108
d3eb5eae 3109static const SSEFunc_0_epp sse_op_table5[256] = {
a7812ae4
PB
3110 [0x0c] = gen_helper_pi2fw,
3111 [0x0d] = gen_helper_pi2fd,
3112 [0x1c] = gen_helper_pf2iw,
3113 [0x1d] = gen_helper_pf2id,
3114 [0x8a] = gen_helper_pfnacc,
3115 [0x8e] = gen_helper_pfpnacc,
3116 [0x90] = gen_helper_pfcmpge,
3117 [0x94] = gen_helper_pfmin,
3118 [0x96] = gen_helper_pfrcp,
3119 [0x97] = gen_helper_pfrsqrt,
3120 [0x9a] = gen_helper_pfsub,
3121 [0x9e] = gen_helper_pfadd,
3122 [0xa0] = gen_helper_pfcmpgt,
3123 [0xa4] = gen_helper_pfmax,
3124 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
3125 [0xa7] = gen_helper_movq, /* pfrsqit1 */
3126 [0xaa] = gen_helper_pfsubr,
3127 [0xae] = gen_helper_pfacc,
3128 [0xb0] = gen_helper_pfcmpeq,
3129 [0xb4] = gen_helper_pfmul,
3130 [0xb6] = gen_helper_movq, /* pfrcpit2 */
3131 [0xb7] = gen_helper_pmulhrw_mmx,
3132 [0xbb] = gen_helper_pswapd,
3133 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
a35f3ec7
AJ
3134};
3135
d3eb5eae
BS
3136struct SSEOpHelper_epp {
3137 SSEFunc_0_epp op[2];
c4baa050
BS
3138 uint32_t ext_mask;
3139};
3140
d3eb5eae
BS
3141struct SSEOpHelper_eppi {
3142 SSEFunc_0_eppi op[2];
c4baa050 3143 uint32_t ext_mask;
222a3336 3144};
c4baa050 3145
222a3336 3146#define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
a7812ae4
PB
3147#define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
3148#define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
222a3336 3149#define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
c4baa050 3150
d3eb5eae 3151static const struct SSEOpHelper_epp sse_op_table6[256] = {
222a3336
AZ
3152 [0x00] = SSSE3_OP(pshufb),
3153 [0x01] = SSSE3_OP(phaddw),
3154 [0x02] = SSSE3_OP(phaddd),
3155 [0x03] = SSSE3_OP(phaddsw),
3156 [0x04] = SSSE3_OP(pmaddubsw),
3157 [0x05] = SSSE3_OP(phsubw),
3158 [0x06] = SSSE3_OP(phsubd),
3159 [0x07] = SSSE3_OP(phsubsw),
3160 [0x08] = SSSE3_OP(psignb),
3161 [0x09] = SSSE3_OP(psignw),
3162 [0x0a] = SSSE3_OP(psignd),
3163 [0x0b] = SSSE3_OP(pmulhrsw),
3164 [0x10] = SSE41_OP(pblendvb),
3165 [0x14] = SSE41_OP(blendvps),
3166 [0x15] = SSE41_OP(blendvpd),
3167 [0x17] = SSE41_OP(ptest),
3168 [0x1c] = SSSE3_OP(pabsb),
3169 [0x1d] = SSSE3_OP(pabsw),
3170 [0x1e] = SSSE3_OP(pabsd),
3171 [0x20] = SSE41_OP(pmovsxbw),
3172 [0x21] = SSE41_OP(pmovsxbd),
3173 [0x22] = SSE41_OP(pmovsxbq),
3174 [0x23] = SSE41_OP(pmovsxwd),
3175 [0x24] = SSE41_OP(pmovsxwq),
3176 [0x25] = SSE41_OP(pmovsxdq),
3177 [0x28] = SSE41_OP(pmuldq),
3178 [0x29] = SSE41_OP(pcmpeqq),
3179 [0x2a] = SSE41_SPECIAL, /* movntqda */
3180 [0x2b] = SSE41_OP(packusdw),
3181 [0x30] = SSE41_OP(pmovzxbw),
3182 [0x31] = SSE41_OP(pmovzxbd),
3183 [0x32] = SSE41_OP(pmovzxbq),
3184 [0x33] = SSE41_OP(pmovzxwd),
3185 [0x34] = SSE41_OP(pmovzxwq),
3186 [0x35] = SSE41_OP(pmovzxdq),
3187 [0x37] = SSE42_OP(pcmpgtq),
3188 [0x38] = SSE41_OP(pminsb),
3189 [0x39] = SSE41_OP(pminsd),
3190 [0x3a] = SSE41_OP(pminuw),
3191 [0x3b] = SSE41_OP(pminud),
3192 [0x3c] = SSE41_OP(pmaxsb),
3193 [0x3d] = SSE41_OP(pmaxsd),
3194 [0x3e] = SSE41_OP(pmaxuw),
3195 [0x3f] = SSE41_OP(pmaxud),
3196 [0x40] = SSE41_OP(pmulld),
3197 [0x41] = SSE41_OP(phminposuw),
4242b1bd
AZ
3198};
3199
d3eb5eae 3200static const struct SSEOpHelper_eppi sse_op_table7[256] = {
222a3336
AZ
3201 [0x08] = SSE41_OP(roundps),
3202 [0x09] = SSE41_OP(roundpd),
3203 [0x0a] = SSE41_OP(roundss),
3204 [0x0b] = SSE41_OP(roundsd),
3205 [0x0c] = SSE41_OP(blendps),
3206 [0x0d] = SSE41_OP(blendpd),
3207 [0x0e] = SSE41_OP(pblendw),
3208 [0x0f] = SSSE3_OP(palignr),
3209 [0x14] = SSE41_SPECIAL, /* pextrb */
3210 [0x15] = SSE41_SPECIAL, /* pextrw */
3211 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3212 [0x17] = SSE41_SPECIAL, /* extractps */
3213 [0x20] = SSE41_SPECIAL, /* pinsrb */
3214 [0x21] = SSE41_SPECIAL, /* insertps */
3215 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3216 [0x40] = SSE41_OP(dpps),
3217 [0x41] = SSE41_OP(dppd),
3218 [0x42] = SSE41_OP(mpsadbw),
3219 [0x60] = SSE42_OP(pcmpestrm),
3220 [0x61] = SSE42_OP(pcmpestri),
3221 [0x62] = SSE42_OP(pcmpistrm),
3222 [0x63] = SSE42_OP(pcmpistri),
4242b1bd
AZ
3223};
3224
0af10c86
BS
3225static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3226 target_ulong pc_start, int rex_r)
664e0f19
FB
3227{
3228 int b1, op1_offset, op2_offset, is_xmm, val, ot;
3229 int modrm, mod, rm, reg, reg_addr, offset_addr;
d3eb5eae
BS
3230 SSEFunc_0_epp sse_fn_epp;
3231 SSEFunc_0_eppi sse_fn_eppi;
c4baa050 3232 SSEFunc_0_ppi sse_fn_ppi;
d3eb5eae 3233 SSEFunc_0_eppt sse_fn_eppt;
664e0f19
FB
3234
3235 b &= 0xff;
5fafdf24 3236 if (s->prefix & PREFIX_DATA)
664e0f19 3237 b1 = 1;
5fafdf24 3238 else if (s->prefix & PREFIX_REPZ)
664e0f19 3239 b1 = 2;
5fafdf24 3240 else if (s->prefix & PREFIX_REPNZ)
664e0f19
FB
3241 b1 = 3;
3242 else
3243 b1 = 0;
d3eb5eae
BS
3244 sse_fn_epp = sse_op_table1[b][b1];
3245 if (!sse_fn_epp) {
664e0f19 3246 goto illegal_op;
c4baa050 3247 }
a35f3ec7 3248 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
664e0f19
FB
3249 is_xmm = 1;
3250 } else {
3251 if (b1 == 0) {
3252 /* MMX case */
3253 is_xmm = 0;
3254 } else {
3255 is_xmm = 1;
3256 }
3257 }
3258 /* simple MMX/SSE operation */
3259 if (s->flags & HF_TS_MASK) {
3260 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3261 return;
3262 }
3263 if (s->flags & HF_EM_MASK) {
3264 illegal_op:
3265 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
3266 return;
3267 }
3268 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
4242b1bd
AZ
3269 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
3270 goto illegal_op;
e771edab
AJ
3271 if (b == 0x0e) {
3272 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3273 goto illegal_op;
3274 /* femms */
d3eb5eae 3275 gen_helper_emms(cpu_env);
e771edab
AJ
3276 return;
3277 }
3278 if (b == 0x77) {
3279 /* emms */
d3eb5eae 3280 gen_helper_emms(cpu_env);
664e0f19
FB
3281 return;
3282 }
3283 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3284 the static cpu state) */
3285 if (!is_xmm) {
d3eb5eae 3286 gen_helper_enter_mmx(cpu_env);
664e0f19
FB
3287 }
3288
0af10c86 3289 modrm = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3290 reg = ((modrm >> 3) & 7);
3291 if (is_xmm)
3292 reg |= rex_r;
3293 mod = (modrm >> 6) & 3;
d3eb5eae 3294 if (sse_fn_epp == SSE_SPECIAL) {
664e0f19
FB
3295 b |= (b1 << 8);
3296 switch(b) {
3297 case 0x0e7: /* movntq */
5fafdf24 3298 if (mod == 3)
664e0f19 3299 goto illegal_op;
0af10c86 3300 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3301 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
664e0f19
FB
3302 break;
3303 case 0x1e7: /* movntdq */
3304 case 0x02b: /* movntps */
3305 case 0x12b: /* movntps */
2e21e749
T
3306 if (mod == 3)
3307 goto illegal_op;
0af10c86 3308 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2e21e749
T
3309 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3310 break;
465e9838
FB
3311 case 0x3f0: /* lddqu */
3312 if (mod == 3)
664e0f19 3313 goto illegal_op;
0af10c86 3314 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
c2254920 3315 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
664e0f19 3316 break;
d9f4bb27
AP
3317 case 0x22b: /* movntss */
3318 case 0x32b: /* movntsd */
3319 if (mod == 3)
3320 goto illegal_op;
0af10c86 3321 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
d9f4bb27
AP
3322 if (b1 & 1) {
3323 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,
3324 xmm_regs[reg]));
3325 } else {
3326 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3327 xmm_regs[reg].XMM_L(0)));
3328 gen_op_st_T0_A0(OT_LONG + s->mem_index);
3329 }
3330 break;
664e0f19 3331 case 0x6e: /* movd mm, ea */
dabd98dd
FB
3332#ifdef TARGET_X86_64
3333 if (s->dflag == 2) {
0af10c86 3334 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
5af45186 3335 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
5fafdf24 3336 } else
dabd98dd
FB
3337#endif
3338 {
0af10c86 3339 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
5af45186
FB
3340 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3341 offsetof(CPUX86State,fpregs[reg].mmx));
a7812ae4
PB
3342 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3343 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
dabd98dd 3344 }
664e0f19
FB
3345 break;
3346 case 0x16e: /* movd xmm, ea */
dabd98dd
FB
3347#ifdef TARGET_X86_64
3348 if (s->dflag == 2) {
0af10c86 3349 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
5af45186
FB
3350 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3351 offsetof(CPUX86State,xmm_regs[reg]));
a7812ae4 3352 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
5fafdf24 3353 } else
dabd98dd
FB
3354#endif
3355 {
0af10c86 3356 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
5af45186
FB
3357 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3358 offsetof(CPUX86State,xmm_regs[reg]));
b6abf97d 3359 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 3360 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
dabd98dd 3361 }
664e0f19
FB
3362 break;
3363 case 0x6f: /* movq mm, ea */
3364 if (mod != 3) {
0af10c86 3365 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3366 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
664e0f19
FB
3367 } else {
3368 rm = (modrm & 7);
b6abf97d 3369 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
5af45186 3370 offsetof(CPUX86State,fpregs[rm].mmx));
b6abf97d 3371 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
5af45186 3372 offsetof(CPUX86State,fpregs[reg].mmx));
664e0f19
FB
3373 }
3374 break;
3375 case 0x010: /* movups */
3376 case 0x110: /* movupd */
3377 case 0x028: /* movaps */
3378 case 0x128: /* movapd */
3379 case 0x16f: /* movdqa xmm, ea */
3380 case 0x26f: /* movdqu xmm, ea */
3381 if (mod != 3) {
0af10c86 3382 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3383 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
664e0f19
FB
3384 } else {
3385 rm = (modrm & 7) | REX_B(s);
3386 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3387 offsetof(CPUX86State,xmm_regs[rm]));
3388 }
3389 break;
3390 case 0x210: /* movss xmm, ea */
3391 if (mod != 3) {
0af10c86 3392 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 3393 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
651ba608 3394 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
664e0f19 3395 gen_op_movl_T0_0();
651ba608
FB
3396 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3397 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3398 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
664e0f19
FB
3399 } else {
3400 rm = (modrm & 7) | REX_B(s);
3401 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3402 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3403 }
3404 break;
3405 case 0x310: /* movsd xmm, ea */
3406 if (mod != 3) {
0af10c86 3407 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3408 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
664e0f19 3409 gen_op_movl_T0_0();
651ba608
FB
3410 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3411 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
664e0f19
FB
3412 } else {
3413 rm = (modrm & 7) | REX_B(s);
3414 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3415 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3416 }
3417 break;
3418 case 0x012: /* movlps */
3419 case 0x112: /* movlpd */
3420 if (mod != 3) {
0af10c86 3421 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3422 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3423 } else {
3424 /* movhlps */
3425 rm = (modrm & 7) | REX_B(s);
3426 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3427 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3428 }
3429 break;
465e9838
FB
3430 case 0x212: /* movsldup */
3431 if (mod != 3) {
0af10c86 3432 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3433 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
465e9838
FB
3434 } else {
3435 rm = (modrm & 7) | REX_B(s);
3436 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3437 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3438 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3439 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3440 }
3441 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3442 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3443 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3444 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3445 break;
3446 case 0x312: /* movddup */
3447 if (mod != 3) {
0af10c86 3448 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3449 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
465e9838
FB
3450 } else {
3451 rm = (modrm & 7) | REX_B(s);
3452 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3453 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3454 }
3455 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
ba6526df 3456 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
465e9838 3457 break;
664e0f19
FB
3458 case 0x016: /* movhps */
3459 case 0x116: /* movhpd */
3460 if (mod != 3) {
0af10c86 3461 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3462 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3463 } else {
3464 /* movlhps */
3465 rm = (modrm & 7) | REX_B(s);
3466 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3467 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3468 }
3469 break;
3470 case 0x216: /* movshdup */
3471 if (mod != 3) {
0af10c86 3472 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3473 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
664e0f19
FB
3474 } else {
3475 rm = (modrm & 7) | REX_B(s);
3476 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3477 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3478 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3479 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3480 }
3481 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3482 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3483 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3484 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3485 break;
d9f4bb27
AP
3486 case 0x178:
3487 case 0x378:
3488 {
3489 int bit_index, field_length;
3490
3491 if (b1 == 1 && reg != 0)
3492 goto illegal_op;
0af10c86
BS
3493 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3494 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
d9f4bb27
AP
3495 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3496 offsetof(CPUX86State,xmm_regs[reg]));
3497 if (b1 == 1)
d3eb5eae
BS
3498 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3499 tcg_const_i32(bit_index),
3500 tcg_const_i32(field_length));
d9f4bb27 3501 else
d3eb5eae
BS
3502 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3503 tcg_const_i32(bit_index),
3504 tcg_const_i32(field_length));
d9f4bb27
AP
3505 }
3506 break;
664e0f19 3507 case 0x7e: /* movd ea, mm */
dabd98dd
FB
3508#ifdef TARGET_X86_64
3509 if (s->dflag == 2) {
5af45186
FB
3510 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3511 offsetof(CPUX86State,fpregs[reg].mmx));
0af10c86 3512 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
5fafdf24 3513 } else
dabd98dd
FB
3514#endif
3515 {
5af45186
FB
3516 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3517 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
0af10c86 3518 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
dabd98dd 3519 }
664e0f19
FB
3520 break;
3521 case 0x17e: /* movd ea, xmm */
dabd98dd
FB
3522#ifdef TARGET_X86_64
3523 if (s->dflag == 2) {
5af45186
FB
3524 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3525 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
0af10c86 3526 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
5fafdf24 3527 } else
dabd98dd
FB
3528#endif
3529 {
5af45186
FB
3530 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3531 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
0af10c86 3532 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
dabd98dd 3533 }
664e0f19
FB
3534 break;
3535 case 0x27e: /* movq xmm, ea */
3536 if (mod != 3) {
0af10c86 3537 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3538 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3539 } else {
3540 rm = (modrm & 7) | REX_B(s);
3541 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3542 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3543 }
3544 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3545 break;
3546 case 0x7f: /* movq ea, mm */
3547 if (mod != 3) {
0af10c86 3548 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3549 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
664e0f19
FB
3550 } else {
3551 rm = (modrm & 7);
3552 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3553 offsetof(CPUX86State,fpregs[reg].mmx));
3554 }
3555 break;
3556 case 0x011: /* movups */
3557 case 0x111: /* movupd */
3558 case 0x029: /* movaps */
3559 case 0x129: /* movapd */
3560 case 0x17f: /* movdqa ea, xmm */
3561 case 0x27f: /* movdqu ea, xmm */
3562 if (mod != 3) {
0af10c86 3563 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3564 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
664e0f19
FB
3565 } else {
3566 rm = (modrm & 7) | REX_B(s);
3567 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3568 offsetof(CPUX86State,xmm_regs[reg]));
3569 }
3570 break;
3571 case 0x211: /* movss ea, xmm */
3572 if (mod != 3) {
0af10c86 3573 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
651ba608 3574 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
57fec1fe 3575 gen_op_st_T0_A0(OT_LONG + s->mem_index);
664e0f19
FB
3576 } else {
3577 rm = (modrm & 7) | REX_B(s);
3578 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3579 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3580 }
3581 break;
3582 case 0x311: /* movsd ea, xmm */
3583 if (mod != 3) {
0af10c86 3584 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3585 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3586 } else {
3587 rm = (modrm & 7) | REX_B(s);
3588 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3589 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3590 }
3591 break;
3592 case 0x013: /* movlps */
3593 case 0x113: /* movlpd */
3594 if (mod != 3) {
0af10c86 3595 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3596 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3597 } else {
3598 goto illegal_op;
3599 }
3600 break;
3601 case 0x017: /* movhps */
3602 case 0x117: /* movhpd */
3603 if (mod != 3) {
0af10c86 3604 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3605 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3606 } else {
3607 goto illegal_op;
3608 }
3609 break;
3610 case 0x71: /* shift mm, im */
3611 case 0x72:
3612 case 0x73:
3613 case 0x171: /* shift xmm, im */
3614 case 0x172:
3615 case 0x173:
c045af25
AK
3616 if (b1 >= 2) {
3617 goto illegal_op;
3618 }
0af10c86 3619 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3620 if (is_xmm) {
3621 gen_op_movl_T0_im(val);
651ba608 3622 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
664e0f19 3623 gen_op_movl_T0_0();
651ba608 3624 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
664e0f19
FB
3625 op1_offset = offsetof(CPUX86State,xmm_t0);
3626 } else {
3627 gen_op_movl_T0_im(val);
651ba608 3628 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
664e0f19 3629 gen_op_movl_T0_0();
651ba608 3630 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
664e0f19
FB
3631 op1_offset = offsetof(CPUX86State,mmx_t0);
3632 }
d3eb5eae
BS
3633 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3634 (((modrm >> 3)) & 7)][b1];
3635 if (!sse_fn_epp) {
664e0f19 3636 goto illegal_op;
c4baa050 3637 }
664e0f19
FB
3638 if (is_xmm) {
3639 rm = (modrm & 7) | REX_B(s);
3640 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3641 } else {
3642 rm = (modrm & 7);
3643 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3644 }
5af45186
FB
3645 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3646 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
d3eb5eae 3647 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3648 break;
3649 case 0x050: /* movmskps */
664e0f19 3650 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3651 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3652 offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3653 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
b6abf97d 3654 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
57fec1fe 3655 gen_op_mov_reg_T0(OT_LONG, reg);
664e0f19
FB
3656 break;
3657 case 0x150: /* movmskpd */
664e0f19 3658 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3659 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3660 offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3661 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
b6abf97d 3662 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
57fec1fe 3663 gen_op_mov_reg_T0(OT_LONG, reg);
664e0f19
FB
3664 break;
3665 case 0x02a: /* cvtpi2ps */
3666 case 0x12a: /* cvtpi2pd */
d3eb5eae 3667 gen_helper_enter_mmx(cpu_env);
664e0f19 3668 if (mod != 3) {
0af10c86 3669 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
664e0f19 3670 op2_offset = offsetof(CPUX86State,mmx_t0);
8686c490 3671 gen_ldq_env_A0(s->mem_index, op2_offset);
664e0f19
FB
3672 } else {
3673 rm = (modrm & 7);
3674 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3675 }
3676 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
5af45186
FB
3677 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3678 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
664e0f19
FB
3679 switch(b >> 8) {
3680 case 0x0:
d3eb5eae 3681 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3682 break;
3683 default:
3684 case 0x1:
d3eb5eae 3685 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3686 break;
3687 }
3688 break;
3689 case 0x22a: /* cvtsi2ss */
3690 case 0x32a: /* cvtsi2sd */
3691 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
0af10c86 3692 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
664e0f19 3693 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
5af45186 3694 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
28e10711 3695 if (ot == OT_LONG) {
d3eb5eae 3696 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
28e10711 3697 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 3698 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
28e10711 3699 } else {
11f8cdbc 3700#ifdef TARGET_X86_64
d3eb5eae
BS
3701 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3702 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T[0]);
11f8cdbc
SW
3703#else
3704 goto illegal_op;
3705#endif
28e10711 3706 }
664e0f19
FB
3707 break;
3708 case 0x02c: /* cvttps2pi */
3709 case 0x12c: /* cvttpd2pi */
3710 case 0x02d: /* cvtps2pi */
3711 case 0x12d: /* cvtpd2pi */
d3eb5eae 3712 gen_helper_enter_mmx(cpu_env);
664e0f19 3713 if (mod != 3) {
0af10c86 3714 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
664e0f19 3715 op2_offset = offsetof(CPUX86State,xmm_t0);
8686c490 3716 gen_ldo_env_A0(s->mem_index, op2_offset);
664e0f19
FB
3717 } else {
3718 rm = (modrm & 7) | REX_B(s);
3719 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3720 }
3721 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
5af45186
FB
3722 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3723 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
664e0f19
FB
3724 switch(b) {
3725 case 0x02c:
d3eb5eae 3726 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3727 break;
3728 case 0x12c:
d3eb5eae 3729 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3730 break;
3731 case 0x02d:
d3eb5eae 3732 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3733 break;
3734 case 0x12d:
d3eb5eae 3735 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3736 break;
3737 }
3738 break;
3739 case 0x22c: /* cvttss2si */
3740 case 0x32c: /* cvttsd2si */
3741 case 0x22d: /* cvtss2si */
3742 case 0x32d: /* cvtsd2si */
3743 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
31313213 3744 if (mod != 3) {
0af10c86 3745 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
31313213 3746 if ((b >> 8) & 1) {
8686c490 3747 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
31313213 3748 } else {
57fec1fe 3749 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
651ba608 3750 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
31313213
FB
3751 }
3752 op2_offset = offsetof(CPUX86State,xmm_t0);
3753 } else {
3754 rm = (modrm & 7) | REX_B(s);
3755 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3756 }
5af45186
FB
3757 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3758 if (ot == OT_LONG) {
d3eb5eae 3759 SSEFunc_i_ep sse_fn_i_ep =
bedc2ac1 3760 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
d3eb5eae 3761 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
b6abf97d 3762 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5af45186 3763 } else {
11f8cdbc 3764#ifdef TARGET_X86_64
d3eb5eae 3765 SSEFunc_l_ep sse_fn_l_ep =
bedc2ac1 3766 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
d3eb5eae 3767 sse_fn_l_ep(cpu_T[0], cpu_env, cpu_ptr0);
11f8cdbc
SW
3768#else
3769 goto illegal_op;
3770#endif
5af45186 3771 }
57fec1fe 3772 gen_op_mov_reg_T0(ot, reg);
664e0f19
FB
3773 break;
3774 case 0xc4: /* pinsrw */
5fafdf24 3775 case 0x1c4:
d1e42c5c 3776 s->rip_offset = 1;
0af10c86
BS
3777 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
3778 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3779 if (b1) {
3780 val &= 7;
5af45186
FB
3781 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3782 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
664e0f19
FB
3783 } else {
3784 val &= 3;
5af45186
FB
3785 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3786 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
664e0f19
FB
3787 }
3788 break;
3789 case 0xc5: /* pextrw */
5fafdf24 3790 case 0x1c5:
664e0f19
FB
3791 if (mod != 3)
3792 goto illegal_op;
6dc2d0da 3793 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
0af10c86 3794 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3795 if (b1) {
3796 val &= 7;
3797 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3798 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3799 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
664e0f19
FB
3800 } else {
3801 val &= 3;
3802 rm = (modrm & 7);
5af45186
FB
3803 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3804 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
664e0f19
FB
3805 }
3806 reg = ((modrm >> 3) & 7) | rex_r;
6dc2d0da 3807 gen_op_mov_reg_T0(ot, reg);
664e0f19
FB
3808 break;
3809 case 0x1d6: /* movq ea, xmm */
3810 if (mod != 3) {
0af10c86 3811 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8686c490 3812 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3813 } else {
3814 rm = (modrm & 7) | REX_B(s);
3815 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3816 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3817 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3818 }
3819 break;
3820 case 0x2d6: /* movq2dq */
d3eb5eae 3821 gen_helper_enter_mmx(cpu_env);
480c1cdb
FB
3822 rm = (modrm & 7);
3823 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3824 offsetof(CPUX86State,fpregs[rm].mmx));
3825 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3826 break;
3827 case 0x3d6: /* movdq2q */
d3eb5eae 3828 gen_helper_enter_mmx(cpu_env);
480c1cdb
FB
3829 rm = (modrm & 7) | REX_B(s);
3830 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3831 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
664e0f19
FB
3832 break;
3833 case 0xd7: /* pmovmskb */
3834 case 0x1d7:
3835 if (mod != 3)
3836 goto illegal_op;
3837 if (b1) {
3838 rm = (modrm & 7) | REX_B(s);
5af45186 3839 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3840 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
664e0f19
FB
3841 } else {
3842 rm = (modrm & 7);
5af45186 3843 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
d3eb5eae 3844 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
664e0f19 3845 }
b6abf97d 3846 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
664e0f19 3847 reg = ((modrm >> 3) & 7) | rex_r;
57fec1fe 3848 gen_op_mov_reg_T0(OT_LONG, reg);
664e0f19 3849 break;
111994ee 3850
4242b1bd 3851 case 0x138:
000cacf6 3852 case 0x038:
4242b1bd 3853 b = modrm;
111994ee
RH
3854 if ((b & 0xf0) == 0xf0) {
3855 goto do_0f_38_fx;
3856 }
0af10c86 3857 modrm = cpu_ldub_code(env, s->pc++);
4242b1bd
AZ
3858 rm = modrm & 7;
3859 reg = ((modrm >> 3) & 7) | rex_r;
3860 mod = (modrm >> 6) & 3;
c045af25
AK
3861 if (b1 >= 2) {
3862 goto illegal_op;
3863 }
4242b1bd 3864
d3eb5eae
BS
3865 sse_fn_epp = sse_op_table6[b].op[b1];
3866 if (!sse_fn_epp) {
4242b1bd 3867 goto illegal_op;
c4baa050 3868 }
222a3336
AZ
3869 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3870 goto illegal_op;
4242b1bd
AZ
3871
3872 if (b1) {
3873 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3874 if (mod == 3) {
3875 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3876 } else {
3877 op2_offset = offsetof(CPUX86State,xmm_t0);
0af10c86 3878 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
222a3336
AZ
3879 switch (b) {
3880 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3881 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3882 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3883 gen_ldq_env_A0(s->mem_index, op2_offset +
3884 offsetof(XMMReg, XMM_Q(0)));
3885 break;
3886 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3887 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
a7812ae4 3888 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
222a3336 3889 (s->mem_index >> 2) - 1);
a7812ae4 3890 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
222a3336
AZ
3891 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3892 offsetof(XMMReg, XMM_L(0)));
3893 break;
3894 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3895 tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0,
3896 (s->mem_index >> 2) - 1);
3897 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3898 offsetof(XMMReg, XMM_W(0)));
3899 break;
3900 case 0x2a: /* movntqda */
3901 gen_ldo_env_A0(s->mem_index, op1_offset);
3902 return;
3903 default:
3904 gen_ldo_env_A0(s->mem_index, op2_offset);
3905 }
4242b1bd
AZ
3906 }
3907 } else {
3908 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3909 if (mod == 3) {
3910 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3911 } else {
3912 op2_offset = offsetof(CPUX86State,mmx_t0);
0af10c86 3913 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4242b1bd
AZ
3914 gen_ldq_env_A0(s->mem_index, op2_offset);
3915 }
3916 }
d3eb5eae 3917 if (sse_fn_epp == SSE_SPECIAL) {
222a3336 3918 goto illegal_op;
c4baa050 3919 }
222a3336 3920
4242b1bd
AZ
3921 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3922 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 3923 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
222a3336 3924
3ca51d07
RH
3925 if (b == 0x17) {
3926 set_cc_op(s, CC_OP_EFLAGS);
3927 }
4242b1bd 3928 break;
111994ee
RH
3929
3930 case 0x238:
3931 case 0x338:
3932 do_0f_38_fx:
3933 /* Various integer extensions at 0f 38 f[0-f]. */
3934 b = modrm | (b1 << 8);
0af10c86 3935 modrm = cpu_ldub_code(env, s->pc++);
222a3336
AZ
3936 reg = ((modrm >> 3) & 7) | rex_r;
3937
111994ee
RH
3938 switch (b) {
3939 case 0x3f0: /* crc32 Gd,Eb */
3940 case 0x3f1: /* crc32 Gd,Ey */
3941 do_crc32:
3942 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3943 goto illegal_op;
3944 }
3945 if ((b & 0xff) == 0xf0) {
3946 ot = OT_BYTE;
3947 } else if (s->dflag != 2) {
3948 ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
3949 } else {
3950 ot = OT_QUAD;
3951 }
4242b1bd 3952
111994ee
RH
3953 gen_op_mov_TN_reg(OT_LONG, 0, reg);
3954 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3955 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3956 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
3957 cpu_T[0], tcg_const_i32(8 << ot));
222a3336 3958
111994ee
RH
3959 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3960 gen_op_mov_reg_T0(ot, reg);
3961 break;
222a3336 3962
111994ee
RH
3963 case 0x1f0: /* crc32 or movbe */
3964 case 0x1f1:
3965 /* For these insns, the f3 prefix is supposed to have priority
3966 over the 66 prefix, but that's not what we implement above
3967 setting b1. */
3968 if (s->prefix & PREFIX_REPNZ) {
3969 goto do_crc32;
3970 }
3971 /* FALLTHRU */
3972 case 0x0f0: /* movbe Gy,My */
3973 case 0x0f1: /* movbe My,Gy */
3974 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3975 goto illegal_op;
3976 }
3977 if (s->dflag != 2) {
3978 ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
3979 } else {
3980 ot = OT_QUAD;
3981 }
3982
3983 /* Load the data incoming to the bswap. Note that the TCG
3984 implementation of bswap requires the input be zero
3985 extended. In the case of the loads, we simply know that
3986 gen_op_ld_v via gen_ldst_modrm does that already. */
3987 if ((b & 1) == 0) {
3988 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3989 } else {
3990 switch (ot) {
3991 case OT_WORD:
3992 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[reg]);
3993 break;
3994 default:
3995 tcg_gen_ext32u_tl(cpu_T[0], cpu_regs[reg]);
3996 break;
3997 case OT_QUAD:
3998 tcg_gen_mov_tl(cpu_T[0], cpu_regs[reg]);
3999 break;
4000 }
4001 }
4002
4003 switch (ot) {
4004 case OT_WORD:
4005 tcg_gen_bswap16_tl(cpu_T[0], cpu_T[0]);
4006 break;
4007 default:
4008 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
4009 break;
4010#ifdef TARGET_X86_64
4011 case OT_QUAD:
4012 tcg_gen_bswap64_tl(cpu_T[0], cpu_T[0]);
4013 break;
4014#endif
4015 }
4016
4017 if ((b & 1) == 0) {
4018 gen_op_mov_reg_T0(ot, reg);
4019 } else {
4020 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
4021 }
4022 break;
4023
7073fbad
RH
4024 case 0x0f2: /* andn Gy, By, Ey */
4025 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4026 || !(s->prefix & PREFIX_VEX)
4027 || s->vex_l != 0) {
4028 goto illegal_op;
4029 }
4030 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4031 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4032 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
4033 gen_op_mov_reg_T0(ot, reg);
4034 gen_op_update1_cc();
4035 set_cc_op(s, CC_OP_LOGICB + ot);
4036 break;
4037
c7ab7565
RH
4038 case 0x0f7: /* bextr Gy, Ey, By */
4039 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4040 || !(s->prefix & PREFIX_VEX)
4041 || s->vex_l != 0) {
4042 goto illegal_op;
4043 }
4044 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4045 {
4046 TCGv bound, zero;
4047
4048 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4049 /* Extract START, and shift the operand.
4050 Shifts larger than operand size get zeros. */
4051 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
4052 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_A0);
4053
4054 bound = tcg_const_tl(ot == OT_QUAD ? 63 : 31);
4055 zero = tcg_const_tl(0);
4056 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T[0], cpu_A0, bound,
4057 cpu_T[0], zero);
4058 tcg_temp_free(zero);
4059
4060 /* Extract the LEN into a mask. Lengths larger than
4061 operand size get all ones. */
4062 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
4063 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
4064 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
4065 cpu_A0, bound);
4066 tcg_temp_free(bound);
4067 tcg_gen_movi_tl(cpu_T[1], 1);
4068 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_A0);
4069 tcg_gen_subi_tl(cpu_T[1], cpu_T[1], 1);
4070 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4071
4072 gen_op_mov_reg_T0(ot, reg);
4073 gen_op_update1_cc();
4074 set_cc_op(s, CC_OP_LOGICB + ot);
4075 }
4076 break;
4077
02ea1e6b
RH
4078 case 0x0f5: /* bzhi Gy, Ey, By */
4079 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4080 || !(s->prefix & PREFIX_VEX)
4081 || s->vex_l != 0) {
4082 goto illegal_op;
4083 }
4084 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4085 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4086 tcg_gen_ext8u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4087 {
4088 TCGv bound = tcg_const_tl(ot == OT_QUAD ? 63 : 31);
4089 /* Note that since we're using BMILG (in order to get O
4090 cleared) we need to store the inverse into C. */
4091 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
4092 cpu_T[1], bound);
4093 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T[1], cpu_T[1],
4094 bound, bound, cpu_T[1]);
4095 tcg_temp_free(bound);
4096 }
4097 tcg_gen_movi_tl(cpu_A0, -1);
4098 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T[1]);
4099 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_A0);
4100 gen_op_mov_reg_T0(ot, reg);
4101 gen_op_update1_cc();
4102 set_cc_op(s, CC_OP_BMILGB + ot);
4103 break;
4104
5f1f4b17
RH
4105 case 0x3f6: /* mulx By, Gy, rdx, Ey */
4106 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4107 || !(s->prefix & PREFIX_VEX)
4108 || s->vex_l != 0) {
4109 goto illegal_op;
4110 }
4111 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4112 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4113 switch (ot) {
5f1f4b17 4114 default:
a4bcea3d
RH
4115 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4116 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
4117 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4118 cpu_tmp2_i32, cpu_tmp3_i32);
4119 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
4120 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
5f1f4b17
RH
4121 break;
4122#ifdef TARGET_X86_64
4123 case OT_QUAD:
a4bcea3d
RH
4124 tcg_gen_mulu2_i64(cpu_regs[s->vex_v], cpu_regs[reg],
4125 cpu_T[0], cpu_regs[R_EDX]);
5f1f4b17
RH
4126 break;
4127#endif
4128 }
4129 break;
4130
0592f74a
RH
4131 case 0x3f5: /* pdep Gy, By, Ey */
4132 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4133 || !(s->prefix & PREFIX_VEX)
4134 || s->vex_l != 0) {
4135 goto illegal_op;
4136 }
4137 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4138 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4139 /* Note that by zero-extending the mask operand, we
4140 automatically handle zero-extending the result. */
4141 if (s->dflag == 2) {
4142 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
4143 } else {
4144 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4145 }
4146 gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]);
4147 break;
4148
4149 case 0x2f5: /* pext Gy, By, Ey */
4150 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4151 || !(s->prefix & PREFIX_VEX)
4152 || s->vex_l != 0) {
4153 goto illegal_op;
4154 }
4155 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4156 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4157 /* Note that by zero-extending the mask operand, we
4158 automatically handle zero-extending the result. */
4159 if (s->dflag == 2) {
4160 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
4161 } else {
4162 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4163 }
4164 gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]);
4165 break;
4166
cd7f97ca
RH
4167 case 0x1f6: /* adcx Gy, Ey */
4168 case 0x2f6: /* adox Gy, Ey */
4169 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
4170 goto illegal_op;
4171 } else {
76f13133 4172 TCGv carry_in, carry_out, zero;
cd7f97ca
RH
4173 int end_op;
4174
4175 ot = (s->dflag == 2 ? OT_QUAD : OT_LONG);
4176 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4177
4178 /* Re-use the carry-out from a previous round. */
4179 TCGV_UNUSED(carry_in);
4180 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
4181 switch (s->cc_op) {
4182 case CC_OP_ADCX:
4183 if (b == 0x1f6) {
4184 carry_in = cpu_cc_dst;
4185 end_op = CC_OP_ADCX;
4186 } else {
4187 end_op = CC_OP_ADCOX;
4188 }
4189 break;
4190 case CC_OP_ADOX:
4191 if (b == 0x1f6) {
4192 end_op = CC_OP_ADCOX;
4193 } else {
4194 carry_in = cpu_cc_src2;
4195 end_op = CC_OP_ADOX;
4196 }
4197 break;
4198 case CC_OP_ADCOX:
4199 end_op = CC_OP_ADCOX;
4200 carry_in = carry_out;
4201 break;
4202 default:
4203 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADCOX);
4204 break;
4205 }
4206 /* If we can't reuse carry-out, get it out of EFLAGS. */
4207 if (TCGV_IS_UNUSED(carry_in)) {
4208 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4209 gen_compute_eflags(s);
4210 }
4211 carry_in = cpu_tmp0;
4212 tcg_gen_shri_tl(carry_in, cpu_cc_src,
4213 ctz32(b == 0x1f6 ? CC_C : CC_O));
4214 tcg_gen_andi_tl(carry_in, carry_in, 1);
4215 }
4216
4217 switch (ot) {
4218#ifdef TARGET_X86_64
4219 case OT_LONG:
4220 /* If we know TL is 64-bit, and we want a 32-bit
4221 result, just do everything in 64-bit arithmetic. */
4222 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4223 tcg_gen_ext32u_i64(cpu_T[0], cpu_T[0]);
4224 tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_regs[reg]);
4225 tcg_gen_add_i64(cpu_T[0], cpu_T[0], carry_in);
4226 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T[0]);
4227 tcg_gen_shri_i64(carry_out, cpu_T[0], 32);
4228 break;
4229#endif
4230 default:
4231 /* Otherwise compute the carry-out in two steps. */
76f13133
RH
4232 zero = tcg_const_tl(0);
4233 tcg_gen_add2_tl(cpu_T[0], carry_out,
4234 cpu_T[0], zero,
4235 carry_in, zero);
4236 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4237 cpu_regs[reg], carry_out,
4238 cpu_T[0], zero);
4239 tcg_temp_free(zero);
cd7f97ca
RH
4240 break;
4241 }
cd7f97ca
RH
4242 set_cc_op(s, end_op);
4243 }
4244 break;
4245
4a554890
RH
4246 case 0x1f7: /* shlx Gy, Ey, By */
4247 case 0x2f7: /* sarx Gy, Ey, By */
4248 case 0x3f7: /* shrx Gy, Ey, By */
4249 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4250 || !(s->prefix & PREFIX_VEX)
4251 || s->vex_l != 0) {
4252 goto illegal_op;
4253 }
4254 ot = (s->dflag == 2 ? OT_QUAD : OT_LONG);
4255 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4256 if (ot == OT_QUAD) {
4257 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
4258 } else {
4259 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
4260 }
4261 if (b == 0x1f7) {
4262 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4263 } else if (b == 0x2f7) {
4264 if (ot != OT_QUAD) {
4265 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4266 }
4267 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4268 } else {
4269 if (ot != OT_QUAD) {
4270 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
4271 }
4272 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4273 }
4274 gen_op_mov_reg_T0(ot, reg);
4275 break;
4276
bc4b43dc
RH
4277 case 0x0f3:
4278 case 0x1f3:
4279 case 0x2f3:
4280 case 0x3f3: /* Group 17 */
4281 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4282 || !(s->prefix & PREFIX_VEX)
4283 || s->vex_l != 0) {
4284 goto illegal_op;
4285 }
4286 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4287 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4288
4289 switch (reg & 7) {
4290 case 1: /* blsr By,Ey */
4291 tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
4292 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4293 gen_op_mov_reg_T0(ot, s->vex_v);
4294 gen_op_update2_cc();
4295 set_cc_op(s, CC_OP_BMILGB + ot);
4296 break;
4297
4298 case 2: /* blsmsk By,Ey */
4299 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4300 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4301 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4302 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4303 set_cc_op(s, CC_OP_BMILGB + ot);
4304 break;
4305
4306 case 3: /* blsi By, Ey */
4307 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4308 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4309 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4310 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4311 set_cc_op(s, CC_OP_BMILGB + ot);
4312 break;
4313
4314 default:
4315 goto illegal_op;
4316 }
4317 break;
4318
111994ee
RH
4319 default:
4320 goto illegal_op;
4321 }
222a3336 4322 break;
111994ee 4323
222a3336
AZ
4324 case 0x03a:
4325 case 0x13a:
4242b1bd 4326 b = modrm;
0af10c86 4327 modrm = cpu_ldub_code(env, s->pc++);
4242b1bd
AZ
4328 rm = modrm & 7;
4329 reg = ((modrm >> 3) & 7) | rex_r;
4330 mod = (modrm >> 6) & 3;
c045af25
AK
4331 if (b1 >= 2) {
4332 goto illegal_op;
4333 }
4242b1bd 4334
d3eb5eae
BS
4335 sse_fn_eppi = sse_op_table7[b].op[b1];
4336 if (!sse_fn_eppi) {
4242b1bd 4337 goto illegal_op;
c4baa050 4338 }
222a3336
AZ
4339 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4340 goto illegal_op;
4341
d3eb5eae 4342 if (sse_fn_eppi == SSE_SPECIAL) {
222a3336
AZ
4343 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
4344 rm = (modrm & 7) | REX_B(s);
4345 if (mod != 3)
0af10c86 4346 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
222a3336 4347 reg = ((modrm >> 3) & 7) | rex_r;
0af10c86 4348 val = cpu_ldub_code(env, s->pc++);
222a3336
AZ
4349 switch (b) {
4350 case 0x14: /* pextrb */
4351 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4352 xmm_regs[reg].XMM_B(val & 15)));
4353 if (mod == 3)
4354 gen_op_mov_reg_T0(ot, rm);
4355 else
4356 tcg_gen_qemu_st8(cpu_T[0], cpu_A0,
4357 (s->mem_index >> 2) - 1);
4358 break;
4359 case 0x15: /* pextrw */
4360 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4361 xmm_regs[reg].XMM_W(val & 7)));
4362 if (mod == 3)
4363 gen_op_mov_reg_T0(ot, rm);
4364 else
4365 tcg_gen_qemu_st16(cpu_T[0], cpu_A0,
4366 (s->mem_index >> 2) - 1);
4367 break;
4368 case 0x16:
4369 if (ot == OT_LONG) { /* pextrd */
4370 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4371 offsetof(CPUX86State,
4372 xmm_regs[reg].XMM_L(val & 3)));
a7812ae4 4373 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
222a3336 4374 if (mod == 3)
a7812ae4 4375 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
222a3336 4376 else
a7812ae4 4377 tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
222a3336
AZ
4378 (s->mem_index >> 2) - 1);
4379 } else { /* pextrq */
a7812ae4 4380#ifdef TARGET_X86_64
222a3336
AZ
4381 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4382 offsetof(CPUX86State,
4383 xmm_regs[reg].XMM_Q(val & 1)));
4384 if (mod == 3)
4385 gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
4386 else
4387 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
4388 (s->mem_index >> 2) - 1);
a7812ae4
PB
4389#else
4390 goto illegal_op;
4391#endif
222a3336
AZ
4392 }
4393 break;
4394 case 0x17: /* extractps */
4395 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4396 xmm_regs[reg].XMM_L(val & 3)));
4397 if (mod == 3)
4398 gen_op_mov_reg_T0(ot, rm);
4399 else
4400 tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
4401 (s->mem_index >> 2) - 1);
4402 break;
4403 case 0x20: /* pinsrb */
4404 if (mod == 3)
4405 gen_op_mov_TN_reg(OT_LONG, 0, rm);
4406 else
a7812ae4 4407 tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0,
222a3336 4408 (s->mem_index >> 2) - 1);
a7812ae4 4409 tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State,
222a3336
AZ
4410 xmm_regs[reg].XMM_B(val & 15)));
4411 break;
4412 case 0x21: /* insertps */
a7812ae4 4413 if (mod == 3) {
222a3336
AZ
4414 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4415 offsetof(CPUX86State,xmm_regs[rm]
4416 .XMM_L((val >> 6) & 3)));
a7812ae4
PB
4417 } else {
4418 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
222a3336 4419 (s->mem_index >> 2) - 1);
a7812ae4
PB
4420 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
4421 }
222a3336
AZ
4422 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4423 offsetof(CPUX86State,xmm_regs[reg]
4424 .XMM_L((val >> 4) & 3)));
4425 if ((val >> 0) & 1)
4426 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4427 cpu_env, offsetof(CPUX86State,
4428 xmm_regs[reg].XMM_L(0)));
4429 if ((val >> 1) & 1)
4430 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4431 cpu_env, offsetof(CPUX86State,
4432 xmm_regs[reg].XMM_L(1)));
4433 if ((val >> 2) & 1)
4434 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4435 cpu_env, offsetof(CPUX86State,
4436 xmm_regs[reg].XMM_L(2)));
4437 if ((val >> 3) & 1)
4438 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4439 cpu_env, offsetof(CPUX86State,
4440 xmm_regs[reg].XMM_L(3)));
4441 break;
4442 case 0x22:
4443 if (ot == OT_LONG) { /* pinsrd */
4444 if (mod == 3)
a7812ae4 4445 gen_op_mov_v_reg(ot, cpu_tmp0, rm);
222a3336 4446 else
a7812ae4 4447 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
222a3336 4448 (s->mem_index >> 2) - 1);
a7812ae4 4449 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
222a3336
AZ
4450 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4451 offsetof(CPUX86State,
4452 xmm_regs[reg].XMM_L(val & 3)));
4453 } else { /* pinsrq */
a7812ae4 4454#ifdef TARGET_X86_64
222a3336
AZ
4455 if (mod == 3)
4456 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4457 else
4458 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
4459 (s->mem_index >> 2) - 1);
4460 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4461 offsetof(CPUX86State,
4462 xmm_regs[reg].XMM_Q(val & 1)));
a7812ae4
PB
4463#else
4464 goto illegal_op;
4465#endif
222a3336
AZ
4466 }
4467 break;
4468 }
4469 return;
4470 }
4242b1bd
AZ
4471
4472 if (b1) {
4473 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4474 if (mod == 3) {
4475 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4476 } else {
4477 op2_offset = offsetof(CPUX86State,xmm_t0);
0af10c86 4478 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4242b1bd
AZ
4479 gen_ldo_env_A0(s->mem_index, op2_offset);
4480 }
4481 } else {
4482 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4483 if (mod == 3) {
4484 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4485 } else {
4486 op2_offset = offsetof(CPUX86State,mmx_t0);
0af10c86 4487 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4242b1bd
AZ
4488 gen_ldq_env_A0(s->mem_index, op2_offset);
4489 }
4490 }
0af10c86 4491 val = cpu_ldub_code(env, s->pc++);
4242b1bd 4492
222a3336 4493 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
3ca51d07 4494 set_cc_op(s, CC_OP_EFLAGS);
222a3336
AZ
4495
4496 if (s->dflag == 2)
4497 /* The helper must use entire 64-bit gp registers */
4498 val |= 1 << 8;
4499 }
4500
4242b1bd
AZ
4501 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4502 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4503 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4242b1bd 4504 break;
e2c3c2c5
RH
4505
4506 case 0x33a:
4507 /* Various integer extensions at 0f 3a f[0-f]. */
4508 b = modrm | (b1 << 8);
4509 modrm = cpu_ldub_code(env, s->pc++);
4510 reg = ((modrm >> 3) & 7) | rex_r;
4511
4512 switch (b) {
4513 case 0x3f0: /* rorx Gy,Ey, Ib */
4514 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4515 || !(s->prefix & PREFIX_VEX)
4516 || s->vex_l != 0) {
4517 goto illegal_op;
4518 }
4519 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4520 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4521 b = cpu_ldub_code(env, s->pc++);
4522 if (ot == OT_QUAD) {
4523 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
4524 } else {
4525 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4526 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4527 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4528 }
4529 gen_op_mov_reg_T0(ot, reg);
4530 break;
4531
4532 default:
4533 goto illegal_op;
4534 }
4535 break;
4536
664e0f19
FB
4537 default:
4538 goto illegal_op;
4539 }
4540 } else {
4541 /* generic MMX or SSE operation */
d1e42c5c 4542 switch(b) {
d1e42c5c
FB
4543 case 0x70: /* pshufx insn */
4544 case 0xc6: /* pshufx insn */
4545 case 0xc2: /* compare insns */
4546 s->rip_offset = 1;
4547 break;
4548 default:
4549 break;
664e0f19
FB
4550 }
4551 if (is_xmm) {
4552 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4553 if (mod != 3) {
0af10c86 4554 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
664e0f19 4555 op2_offset = offsetof(CPUX86State,xmm_t0);
480c1cdb 4556 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
664e0f19
FB
4557 b == 0xc2)) {
4558 /* specific case for SSE single instructions */
4559 if (b1 == 2) {
4560 /* 32 bit access */
57fec1fe 4561 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
651ba608 4562 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
664e0f19
FB
4563 } else {
4564 /* 64 bit access */
8686c490 4565 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
664e0f19
FB
4566 }
4567 } else {
8686c490 4568 gen_ldo_env_A0(s->mem_index, op2_offset);
664e0f19
FB
4569 }
4570 } else {
4571 rm = (modrm & 7) | REX_B(s);
4572 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4573 }
4574 } else {
4575 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4576 if (mod != 3) {
0af10c86 4577 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
664e0f19 4578 op2_offset = offsetof(CPUX86State,mmx_t0);
8686c490 4579 gen_ldq_env_A0(s->mem_index, op2_offset);
664e0f19
FB
4580 } else {
4581 rm = (modrm & 7);
4582 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4583 }
4584 }
4585 switch(b) {
a35f3ec7 4586 case 0x0f: /* 3DNow! data insns */
e771edab
AJ
4587 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4588 goto illegal_op;
0af10c86 4589 val = cpu_ldub_code(env, s->pc++);
d3eb5eae
BS
4590 sse_fn_epp = sse_op_table5[val];
4591 if (!sse_fn_epp) {
a35f3ec7 4592 goto illegal_op;
c4baa050 4593 }
5af45186
FB
4594 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4595 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4596 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
a35f3ec7 4597 break;
664e0f19
FB
4598 case 0x70: /* pshufx insn */
4599 case 0xc6: /* pshufx insn */
0af10c86 4600 val = cpu_ldub_code(env, s->pc++);
5af45186
FB
4601 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4602 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4603 /* XXX: introduce a new table? */
d3eb5eae 4604 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
c4baa050 4605 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
664e0f19
FB
4606 break;
4607 case 0xc2:
4608 /* compare insns */
0af10c86 4609 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
4610 if (val >= 8)
4611 goto illegal_op;
d3eb5eae 4612 sse_fn_epp = sse_op_table4[val][b1];
c4baa050 4613
5af45186
FB
4614 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4615 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4616 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19 4617 break;
b8b6a50b
FB
4618 case 0xf7:
4619 /* maskmov : we must prepare A0 */
4620 if (mod != 3)
4621 goto illegal_op;
4622#ifdef TARGET_X86_64
4623 if (s->aflag == 2) {
4624 gen_op_movq_A0_reg(R_EDI);
4625 } else
4626#endif
4627 {
4628 gen_op_movl_A0_reg(R_EDI);
4629 if (s->aflag == 0)
4630 gen_op_andl_A0_ffff();
4631 }
4632 gen_add_A0_ds_seg(s);
4633
4634 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4635 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4636 /* XXX: introduce a new table? */
d3eb5eae
BS
4637 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4638 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
b8b6a50b 4639 break;
664e0f19 4640 default:
5af45186
FB
4641 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4642 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4643 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
4644 break;
4645 }
4646 if (b == 0x2e || b == 0x2f) {
3ca51d07 4647 set_cc_op(s, CC_OP_EFLAGS);
664e0f19
FB
4648 }
4649 }
4650}
4651
2c0262af
FB
4652/* convert one instruction. s->is_jmp is set if the translation must
4653 be stopped. Return the next pc value */
0af10c86
BS
4654static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4655 target_ulong pc_start)
2c0262af
FB
4656{
4657 int b, prefixes, aflag, dflag;
4658 int shift, ot;
4659 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
14ce26e7
FB
4660 target_ulong next_eip, tval;
4661 int rex_w, rex_r;
2c0262af 4662
fdefe51c 4663 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
70cff25e 4664 tcg_gen_debug_insn_start(pc_start);
fdefe51c 4665 }
2c0262af
FB
4666 s->pc = pc_start;
4667 prefixes = 0;
4668 aflag = s->code32;
4669 dflag = s->code32;
4670 s->override = -1;
14ce26e7
FB
4671 rex_w = -1;
4672 rex_r = 0;
4673#ifdef TARGET_X86_64
4674 s->rex_x = 0;
4675 s->rex_b = 0;
5fafdf24 4676 x86_64_hregs = 0;
14ce26e7
FB
4677#endif
4678 s->rip_offset = 0; /* for relative ip address */
701ed211
RH
4679 s->vex_l = 0;
4680 s->vex_v = 0;
2c0262af 4681 next_byte:
0af10c86 4682 b = cpu_ldub_code(env, s->pc);
2c0262af 4683 s->pc++;
4a6fd938
RH
4684 /* Collect prefixes. */
4685 switch (b) {
4686 case 0xf3:
4687 prefixes |= PREFIX_REPZ;
4688 goto next_byte;
4689 case 0xf2:
4690 prefixes |= PREFIX_REPNZ;
4691 goto next_byte;
4692 case 0xf0:
4693 prefixes |= PREFIX_LOCK;
4694 goto next_byte;
4695 case 0x2e:
4696 s->override = R_CS;
4697 goto next_byte;
4698 case 0x36:
4699 s->override = R_SS;
4700 goto next_byte;
4701 case 0x3e:
4702 s->override = R_DS;
4703 goto next_byte;
4704 case 0x26:
4705 s->override = R_ES;
4706 goto next_byte;
4707 case 0x64:
4708 s->override = R_FS;
4709 goto next_byte;
4710 case 0x65:
4711 s->override = R_GS;
4712 goto next_byte;
4713 case 0x66:
4714 prefixes |= PREFIX_DATA;
4715 goto next_byte;
4716 case 0x67:
4717 prefixes |= PREFIX_ADR;
4718 goto next_byte;
14ce26e7 4719#ifdef TARGET_X86_64
4a6fd938
RH
4720 case 0x40 ... 0x4f:
4721 if (CODE64(s)) {
14ce26e7
FB
4722 /* REX prefix */
4723 rex_w = (b >> 3) & 1;
4724 rex_r = (b & 0x4) << 1;
4725 s->rex_x = (b & 0x2) << 2;
4726 REX_B(s) = (b & 0x1) << 3;
4727 x86_64_hregs = 1; /* select uniform byte register addressing */
4728 goto next_byte;
4729 }
4a6fd938
RH
4730 break;
4731#endif
701ed211
RH
4732 case 0xc5: /* 2-byte VEX */
4733 case 0xc4: /* 3-byte VEX */
4734 /* VEX prefixes cannot be used except in 32-bit mode.
4735 Otherwise the instruction is LES or LDS. */
4736 if (s->code32 && !s->vm86) {
4737 static const int pp_prefix[4] = {
4738 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4739 };
4740 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4741
4742 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4743 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4744 otherwise the instruction is LES or LDS. */
4745 break;
4746 }
4747 s->pc++;
4748
085d8134 4749 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
701ed211
RH
4750 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4751 | PREFIX_LOCK | PREFIX_DATA)) {
4752 goto illegal_op;
4753 }
4754#ifdef TARGET_X86_64
4755 if (x86_64_hregs) {
4756 goto illegal_op;
4757 }
4758#endif
4759 rex_r = (~vex2 >> 4) & 8;
4760 if (b == 0xc5) {
4761 vex3 = vex2;
4762 b = cpu_ldub_code(env, s->pc++);
4763 } else {
4764#ifdef TARGET_X86_64
4765 s->rex_x = (~vex2 >> 3) & 8;
4766 s->rex_b = (~vex2 >> 2) & 8;
4767#endif
4768 vex3 = cpu_ldub_code(env, s->pc++);
4769 rex_w = (vex3 >> 7) & 1;
4770 switch (vex2 & 0x1f) {
4771 case 0x01: /* Implied 0f leading opcode bytes. */
4772 b = cpu_ldub_code(env, s->pc++) | 0x100;
4773 break;
4774 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4775 b = 0x138;
4776 break;
4777 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4778 b = 0x13a;
4779 break;
4780 default: /* Reserved for future use. */
4781 goto illegal_op;
4782 }
4783 }
4784 s->vex_v = (~vex3 >> 3) & 0xf;
4785 s->vex_l = (vex3 >> 2) & 1;
4786 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4787 }
4788 break;
4a6fd938
RH
4789 }
4790
4791 /* Post-process prefixes. */
4792 if (prefixes & PREFIX_DATA) {
4793 dflag ^= 1;
4794 }
4795 if (prefixes & PREFIX_ADR) {
4796 aflag ^= 1;
4797 }
4798#ifdef TARGET_X86_64
4799 if (CODE64(s)) {
14ce26e7
FB
4800 if (rex_w == 1) {
4801 /* 0x66 is ignored if rex.w is set */
4802 dflag = 2;
14ce26e7 4803 }
4a6fd938 4804 if (!(prefixes & PREFIX_ADR)) {
14ce26e7 4805 aflag = 2;
14ce26e7 4806 }
2c0262af 4807 }
4a6fd938 4808#endif
2c0262af 4809
2c0262af
FB
4810 s->prefix = prefixes;
4811 s->aflag = aflag;
4812 s->dflag = dflag;
4813
4814 /* lock generation */
4815 if (prefixes & PREFIX_LOCK)
a7812ae4 4816 gen_helper_lock();
2c0262af
FB
4817
4818 /* now check op code */
4819 reswitch:
4820 switch(b) {
4821 case 0x0f:
4822 /**************************/
4823 /* extended op code */
0af10c86 4824 b = cpu_ldub_code(env, s->pc++) | 0x100;
2c0262af 4825 goto reswitch;
3b46e624 4826
2c0262af
FB
4827 /**************************/
4828 /* arith & logic */
4829 case 0x00 ... 0x05:
4830 case 0x08 ... 0x0d:
4831 case 0x10 ... 0x15:
4832 case 0x18 ... 0x1d:
4833 case 0x20 ... 0x25:
4834 case 0x28 ... 0x2d:
4835 case 0x30 ... 0x35:
4836 case 0x38 ... 0x3d:
4837 {
4838 int op, f, val;
4839 op = (b >> 3) & 7;
4840 f = (b >> 1) & 3;
4841
4842 if ((b & 1) == 0)
4843 ot = OT_BYTE;
4844 else
14ce26e7 4845 ot = dflag + OT_WORD;
3b46e624 4846
2c0262af
FB
4847 switch(f) {
4848 case 0: /* OP Ev, Gv */
0af10c86 4849 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 4850 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4851 mod = (modrm >> 6) & 3;
14ce26e7 4852 rm = (modrm & 7) | REX_B(s);
2c0262af 4853 if (mod != 3) {
0af10c86 4854 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
4855 opreg = OR_TMP0;
4856 } else if (op == OP_XORL && rm == reg) {
4857 xor_zero:
4858 /* xor reg, reg optimisation */
436ff2d2 4859 set_cc_op(s, CC_OP_CLR);
2c0262af 4860 gen_op_movl_T0_0();
57fec1fe 4861 gen_op_mov_reg_T0(ot, reg);
2c0262af
FB
4862 break;
4863 } else {
4864 opreg = rm;
4865 }
57fec1fe 4866 gen_op_mov_TN_reg(ot, 1, reg);
2c0262af
FB
4867 gen_op(s, op, ot, opreg);
4868 break;
4869 case 1: /* OP Gv, Ev */
0af10c86 4870 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4871 mod = (modrm >> 6) & 3;
14ce26e7
FB
4872 reg = ((modrm >> 3) & 7) | rex_r;
4873 rm = (modrm & 7) | REX_B(s);
2c0262af 4874 if (mod != 3) {
0af10c86 4875 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 4876 gen_op_ld_T1_A0(ot + s->mem_index);
2c0262af
FB
4877 } else if (op == OP_XORL && rm == reg) {
4878 goto xor_zero;
4879 } else {
57fec1fe 4880 gen_op_mov_TN_reg(ot, 1, rm);
2c0262af
FB
4881 }
4882 gen_op(s, op, ot, reg);
4883 break;
4884 case 2: /* OP A, Iv */
0af10c86 4885 val = insn_get(env, s, ot);
2c0262af
FB
4886 gen_op_movl_T1_im(val);
4887 gen_op(s, op, ot, OR_EAX);
4888 break;
4889 }
4890 }
4891 break;
4892
ec9d6075
FB
4893 case 0x82:
4894 if (CODE64(s))
4895 goto illegal_op;
2c0262af
FB
4896 case 0x80: /* GRP1 */
4897 case 0x81:
4898 case 0x83:
4899 {
4900 int val;
4901
4902 if ((b & 1) == 0)
4903 ot = OT_BYTE;
4904 else
14ce26e7 4905 ot = dflag + OT_WORD;
3b46e624 4906
0af10c86 4907 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4908 mod = (modrm >> 6) & 3;
14ce26e7 4909 rm = (modrm & 7) | REX_B(s);
2c0262af 4910 op = (modrm >> 3) & 7;
3b46e624 4911
2c0262af 4912 if (mod != 3) {
14ce26e7
FB
4913 if (b == 0x83)
4914 s->rip_offset = 1;
4915 else
4916 s->rip_offset = insn_const_size(ot);
0af10c86 4917 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
4918 opreg = OR_TMP0;
4919 } else {
14ce26e7 4920 opreg = rm;
2c0262af
FB
4921 }
4922
4923 switch(b) {
4924 default:
4925 case 0x80:
4926 case 0x81:
d64477af 4927 case 0x82:
0af10c86 4928 val = insn_get(env, s, ot);
2c0262af
FB
4929 break;
4930 case 0x83:
0af10c86 4931 val = (int8_t)insn_get(env, s, OT_BYTE);
2c0262af
FB
4932 break;
4933 }
4934 gen_op_movl_T1_im(val);
4935 gen_op(s, op, ot, opreg);
4936 }
4937 break;
4938
4939 /**************************/
4940 /* inc, dec, and other misc arith */
4941 case 0x40 ... 0x47: /* inc Gv */
4942 ot = dflag ? OT_LONG : OT_WORD;
4943 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4944 break;
4945 case 0x48 ... 0x4f: /* dec Gv */
4946 ot = dflag ? OT_LONG : OT_WORD;
4947 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4948 break;
4949 case 0xf6: /* GRP3 */
4950 case 0xf7:
4951 if ((b & 1) == 0)
4952 ot = OT_BYTE;
4953 else
14ce26e7 4954 ot = dflag + OT_WORD;
2c0262af 4955
0af10c86 4956 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4957 mod = (modrm >> 6) & 3;
14ce26e7 4958 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4959 op = (modrm >> 3) & 7;
4960 if (mod != 3) {
14ce26e7
FB
4961 if (op == 0)
4962 s->rip_offset = insn_const_size(ot);
0af10c86 4963 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 4964 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 4965 } else {
57fec1fe 4966 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af
FB
4967 }
4968
4969 switch(op) {
4970 case 0: /* test */
0af10c86 4971 val = insn_get(env, s, ot);
2c0262af
FB
4972 gen_op_movl_T1_im(val);
4973 gen_op_testl_T0_T1_cc();
3ca51d07 4974 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af
FB
4975 break;
4976 case 2: /* not */
b6abf97d 4977 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
2c0262af 4978 if (mod != 3) {
57fec1fe 4979 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 4980 } else {
57fec1fe 4981 gen_op_mov_reg_T0(ot, rm);
2c0262af
FB
4982 }
4983 break;
4984 case 3: /* neg */
b6abf97d 4985 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
2c0262af 4986 if (mod != 3) {
57fec1fe 4987 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 4988 } else {
57fec1fe 4989 gen_op_mov_reg_T0(ot, rm);
2c0262af
FB
4990 }
4991 gen_op_update_neg_cc();
3ca51d07 4992 set_cc_op(s, CC_OP_SUBB + ot);
2c0262af
FB
4993 break;
4994 case 4: /* mul */
4995 switch(ot) {
4996 case OT_BYTE:
0211e5af
FB
4997 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
4998 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4999 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
5000 /* XXX: use 32 bit mul which could be faster */
5001 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5002 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5003 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5004 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
3ca51d07 5005 set_cc_op(s, CC_OP_MULB);
2c0262af
FB
5006 break;
5007 case OT_WORD:
0211e5af
FB
5008 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
5009 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
5010 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
5011 /* XXX: use 32 bit mul which could be faster */
5012 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5013 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5014 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5015 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
5016 gen_op_mov_reg_T0(OT_WORD, R_EDX);
5017 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
3ca51d07 5018 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
5019 break;
5020 default:
5021 case OT_LONG:
a4bcea3d
RH
5022 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5023 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
5024 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5025 cpu_tmp2_i32, cpu_tmp3_i32);
5026 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
5027 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
5028 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5029 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 5030 set_cc_op(s, CC_OP_MULL);
2c0262af 5031 break;
14ce26e7
FB
5032#ifdef TARGET_X86_64
5033 case OT_QUAD:
a4bcea3d
RH
5034 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5035 cpu_T[0], cpu_regs[R_EAX]);
5036 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5037 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 5038 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
5039 break;
5040#endif
2c0262af 5041 }
2c0262af
FB
5042 break;
5043 case 5: /* imul */
5044 switch(ot) {
5045 case OT_BYTE:
0211e5af
FB
5046 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
5047 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5048 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
5049 /* XXX: use 32 bit mul which could be faster */
5050 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5051 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5052 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5053 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
5054 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
3ca51d07 5055 set_cc_op(s, CC_OP_MULB);
2c0262af
FB
5056 break;
5057 case OT_WORD:
0211e5af
FB
5058 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
5059 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5060 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5061 /* XXX: use 32 bit mul which could be faster */
5062 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5063 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5064 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5065 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5066 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5067 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
5068 gen_op_mov_reg_T0(OT_WORD, R_EDX);
3ca51d07 5069 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
5070 break;
5071 default:
5072 case OT_LONG:
a4bcea3d
RH
5073 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5074 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
5075 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5076 cpu_tmp2_i32, cpu_tmp3_i32);
5077 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
5078 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
5079 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5080 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5081 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5082 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
3ca51d07 5083 set_cc_op(s, CC_OP_MULL);
2c0262af 5084 break;
14ce26e7
FB
5085#ifdef TARGET_X86_64
5086 case OT_QUAD:
a4bcea3d
RH
5087 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5088 cpu_T[0], cpu_regs[R_EAX]);
5089 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5090 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
5091 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 5092 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
5093 break;
5094#endif
2c0262af 5095 }
2c0262af
FB
5096 break;
5097 case 6: /* div */
5098 switch(ot) {
5099 case OT_BYTE:
14ce26e7 5100 gen_jmp_im(pc_start - s->cs_base);
7923057b 5101 gen_helper_divb_AL(cpu_env, cpu_T[0]);
2c0262af
FB
5102 break;
5103 case OT_WORD:
14ce26e7 5104 gen_jmp_im(pc_start - s->cs_base);
7923057b 5105 gen_helper_divw_AX(cpu_env, cpu_T[0]);
2c0262af
FB
5106 break;
5107 default:
5108 case OT_LONG:
14ce26e7 5109 gen_jmp_im(pc_start - s->cs_base);
7923057b 5110 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
14ce26e7
FB
5111 break;
5112#ifdef TARGET_X86_64
5113 case OT_QUAD:
5114 gen_jmp_im(pc_start - s->cs_base);
7923057b 5115 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
2c0262af 5116 break;
14ce26e7 5117#endif
2c0262af
FB
5118 }
5119 break;
5120 case 7: /* idiv */
5121 switch(ot) {
5122 case OT_BYTE:
14ce26e7 5123 gen_jmp_im(pc_start - s->cs_base);
7923057b 5124 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
2c0262af
FB
5125 break;
5126 case OT_WORD:
14ce26e7 5127 gen_jmp_im(pc_start - s->cs_base);
7923057b 5128 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
2c0262af
FB
5129 break;
5130 default:
5131 case OT_LONG:
14ce26e7 5132 gen_jmp_im(pc_start - s->cs_base);
7923057b 5133 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
14ce26e7
FB
5134 break;
5135#ifdef TARGET_X86_64
5136 case OT_QUAD:
5137 gen_jmp_im(pc_start - s->cs_base);
7923057b 5138 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
2c0262af 5139 break;
14ce26e7 5140#endif
2c0262af
FB
5141 }
5142 break;
5143 default:
5144 goto illegal_op;
5145 }
5146 break;
5147
5148 case 0xfe: /* GRP4 */
5149 case 0xff: /* GRP5 */
5150 if ((b & 1) == 0)
5151 ot = OT_BYTE;
5152 else
14ce26e7 5153 ot = dflag + OT_WORD;
2c0262af 5154
0af10c86 5155 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5156 mod = (modrm >> 6) & 3;
14ce26e7 5157 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
5158 op = (modrm >> 3) & 7;
5159 if (op >= 2 && b == 0xfe) {
5160 goto illegal_op;
5161 }
14ce26e7 5162 if (CODE64(s)) {
aba9d61e 5163 if (op == 2 || op == 4) {
14ce26e7
FB
5164 /* operand size for jumps is 64 bit */
5165 ot = OT_QUAD;
aba9d61e 5166 } else if (op == 3 || op == 5) {
41b1e61f 5167 ot = dflag ? OT_LONG + (rex_w == 1) : OT_WORD;
14ce26e7
FB
5168 } else if (op == 6) {
5169 /* default push size is 64 bit */
5170 ot = dflag ? OT_QUAD : OT_WORD;
5171 }
5172 }
2c0262af 5173 if (mod != 3) {
0af10c86 5174 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af 5175 if (op >= 2 && op != 3 && op != 5)
57fec1fe 5176 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 5177 } else {
57fec1fe 5178 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af
FB
5179 }
5180
5181 switch(op) {
5182 case 0: /* inc Ev */
5183 if (mod != 3)
5184 opreg = OR_TMP0;
5185 else
5186 opreg = rm;
5187 gen_inc(s, ot, opreg, 1);
5188 break;
5189 case 1: /* dec Ev */
5190 if (mod != 3)
5191 opreg = OR_TMP0;
5192 else
5193 opreg = rm;
5194 gen_inc(s, ot, opreg, -1);
5195 break;
5196 case 2: /* call Ev */
4f31916f 5197 /* XXX: optimize if memory (no 'and' is necessary) */
2c0262af
FB
5198 if (s->dflag == 0)
5199 gen_op_andl_T0_ffff();
2c0262af 5200 next_eip = s->pc - s->cs_base;
1ef38687 5201 gen_movtl_T1_im(next_eip);
4f31916f
FB
5202 gen_push_T1(s);
5203 gen_op_jmp_T0();
2c0262af
FB
5204 gen_eob(s);
5205 break;
61382a50 5206 case 3: /* lcall Ev */
57fec1fe 5207 gen_op_ld_T1_A0(ot + s->mem_index);
aba9d61e 5208 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
57fec1fe 5209 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
5210 do_lcall:
5211 if (s->pe && !s->vm86) {
773cdfcc 5212 gen_update_cc_op(s);
14ce26e7 5213 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 5214 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2
BS
5215 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
5216 tcg_const_i32(dflag),
a7812ae4 5217 tcg_const_i32(s->pc - pc_start));
2c0262af 5218 } else {
b6abf97d 5219 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2
BS
5220 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
5221 tcg_const_i32(dflag),
a7812ae4 5222 tcg_const_i32(s->pc - s->cs_base));
2c0262af
FB
5223 }
5224 gen_eob(s);
5225 break;
5226 case 4: /* jmp Ev */
5227 if (s->dflag == 0)
5228 gen_op_andl_T0_ffff();
5229 gen_op_jmp_T0();
5230 gen_eob(s);
5231 break;
5232 case 5: /* ljmp Ev */
57fec1fe 5233 gen_op_ld_T1_A0(ot + s->mem_index);
aba9d61e 5234 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
57fec1fe 5235 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
5236 do_ljmp:
5237 if (s->pe && !s->vm86) {
773cdfcc 5238 gen_update_cc_op(s);
14ce26e7 5239 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 5240 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 5241 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
a7812ae4 5242 tcg_const_i32(s->pc - pc_start));
2c0262af 5243 } else {
3bd7da9e 5244 gen_op_movl_seg_T0_vm(R_CS);
2c0262af
FB
5245 gen_op_movl_T0_T1();
5246 gen_op_jmp_T0();
5247 }
5248 gen_eob(s);
5249 break;
5250 case 6: /* push Ev */
5251 gen_push_T0(s);
5252 break;
5253 default:
5254 goto illegal_op;
5255 }
5256 break;
5257
5258 case 0x84: /* test Ev, Gv */
5fafdf24 5259 case 0x85:
2c0262af
FB
5260 if ((b & 1) == 0)
5261 ot = OT_BYTE;
5262 else
14ce26e7 5263 ot = dflag + OT_WORD;
2c0262af 5264
0af10c86 5265 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5266 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5267
0af10c86 5268 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
57fec1fe 5269 gen_op_mov_TN_reg(ot, 1, reg);
2c0262af 5270 gen_op_testl_T0_T1_cc();
3ca51d07 5271 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5272 break;
3b46e624 5273
2c0262af
FB
5274 case 0xa8: /* test eAX, Iv */
5275 case 0xa9:
5276 if ((b & 1) == 0)
5277 ot = OT_BYTE;
5278 else
14ce26e7 5279 ot = dflag + OT_WORD;
0af10c86 5280 val = insn_get(env, s, ot);
2c0262af 5281
57fec1fe 5282 gen_op_mov_TN_reg(ot, 0, OR_EAX);
2c0262af
FB
5283 gen_op_movl_T1_im(val);
5284 gen_op_testl_T0_T1_cc();
3ca51d07 5285 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5286 break;
3b46e624 5287
2c0262af 5288 case 0x98: /* CWDE/CBW */
14ce26e7
FB
5289#ifdef TARGET_X86_64
5290 if (dflag == 2) {
e108dd01
FB
5291 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5292 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5293 gen_op_mov_reg_T0(OT_QUAD, R_EAX);
14ce26e7
FB
5294 } else
5295#endif
e108dd01
FB
5296 if (dflag == 1) {
5297 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
5298 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5299 gen_op_mov_reg_T0(OT_LONG, R_EAX);
5300 } else {
5301 gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX);
5302 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5303 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5304 }
2c0262af
FB
5305 break;
5306 case 0x99: /* CDQ/CWD */
14ce26e7
FB
5307#ifdef TARGET_X86_64
5308 if (dflag == 2) {
e108dd01
FB
5309 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5310 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
5311 gen_op_mov_reg_T0(OT_QUAD, R_EDX);
14ce26e7
FB
5312 } else
5313#endif
e108dd01
FB
5314 if (dflag == 1) {
5315 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5316 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5317 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
5318 gen_op_mov_reg_T0(OT_LONG, R_EDX);
5319 } else {
5320 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
5321 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5322 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
5323 gen_op_mov_reg_T0(OT_WORD, R_EDX);
5324 }
2c0262af
FB
5325 break;
5326 case 0x1af: /* imul Gv, Ev */
5327 case 0x69: /* imul Gv, Ev, I */
5328 case 0x6b:
14ce26e7 5329 ot = dflag + OT_WORD;
0af10c86 5330 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
5331 reg = ((modrm >> 3) & 7) | rex_r;
5332 if (b == 0x69)
5333 s->rip_offset = insn_const_size(ot);
5334 else if (b == 0x6b)
5335 s->rip_offset = 1;
0af10c86 5336 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2c0262af 5337 if (b == 0x69) {
0af10c86 5338 val = insn_get(env, s, ot);
2c0262af
FB
5339 gen_op_movl_T1_im(val);
5340 } else if (b == 0x6b) {
0af10c86 5341 val = (int8_t)insn_get(env, s, OT_BYTE);
2c0262af
FB
5342 gen_op_movl_T1_im(val);
5343 } else {
57fec1fe 5344 gen_op_mov_TN_reg(ot, 1, reg);
2c0262af 5345 }
a4bcea3d 5346 switch (ot) {
0211e5af 5347#ifdef TARGET_X86_64
a4bcea3d
RH
5348 case OT_QUAD:
5349 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
5350 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5351 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5352 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
5353 break;
0211e5af 5354#endif
a4bcea3d
RH
5355 case OT_LONG:
5356 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5357 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5358 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5359 cpu_tmp2_i32, cpu_tmp3_i32);
5360 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5361 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5362 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5363 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5364 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5365 break;
5366 default:
0211e5af
FB
5367 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5368 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5369 /* XXX: use 32 bit mul which could be faster */
5370 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5371 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5372 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5373 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
a4bcea3d
RH
5374 gen_op_mov_reg_T0(ot, reg);
5375 break;
2c0262af 5376 }
3ca51d07 5377 set_cc_op(s, CC_OP_MULB + ot);
2c0262af
FB
5378 break;
5379 case 0x1c0:
5380 case 0x1c1: /* xadd Ev, Gv */
5381 if ((b & 1) == 0)
5382 ot = OT_BYTE;
5383 else
14ce26e7 5384 ot = dflag + OT_WORD;
0af10c86 5385 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5386 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5387 mod = (modrm >> 6) & 3;
5388 if (mod == 3) {
14ce26e7 5389 rm = (modrm & 7) | REX_B(s);
57fec1fe
FB
5390 gen_op_mov_TN_reg(ot, 0, reg);
5391 gen_op_mov_TN_reg(ot, 1, rm);
2c0262af 5392 gen_op_addl_T0_T1();
57fec1fe
FB
5393 gen_op_mov_reg_T1(ot, reg);
5394 gen_op_mov_reg_T0(ot, rm);
2c0262af 5395 } else {
0af10c86 5396 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe
FB
5397 gen_op_mov_TN_reg(ot, 0, reg);
5398 gen_op_ld_T1_A0(ot + s->mem_index);
2c0262af 5399 gen_op_addl_T0_T1();
57fec1fe
FB
5400 gen_op_st_T0_A0(ot + s->mem_index);
5401 gen_op_mov_reg_T1(ot, reg);
2c0262af
FB
5402 }
5403 gen_op_update2_cc();
3ca51d07 5404 set_cc_op(s, CC_OP_ADDB + ot);
2c0262af
FB
5405 break;
5406 case 0x1b0:
5407 case 0x1b1: /* cmpxchg Ev, Gv */
cad3a37d 5408 {
1130328e 5409 int label1, label2;
1e4840bf 5410 TCGv t0, t1, t2, a0;
cad3a37d
FB
5411
5412 if ((b & 1) == 0)
5413 ot = OT_BYTE;
5414 else
5415 ot = dflag + OT_WORD;
0af10c86 5416 modrm = cpu_ldub_code(env, s->pc++);
cad3a37d
FB
5417 reg = ((modrm >> 3) & 7) | rex_r;
5418 mod = (modrm >> 6) & 3;
a7812ae4
PB
5419 t0 = tcg_temp_local_new();
5420 t1 = tcg_temp_local_new();
5421 t2 = tcg_temp_local_new();
5422 a0 = tcg_temp_local_new();
1e4840bf 5423 gen_op_mov_v_reg(ot, t1, reg);
cad3a37d
FB
5424 if (mod == 3) {
5425 rm = (modrm & 7) | REX_B(s);
1e4840bf 5426 gen_op_mov_v_reg(ot, t0, rm);
cad3a37d 5427 } else {
0af10c86 5428 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
1e4840bf
FB
5429 tcg_gen_mov_tl(a0, cpu_A0);
5430 gen_op_ld_v(ot + s->mem_index, t0, a0);
cad3a37d
FB
5431 rm = 0; /* avoid warning */
5432 }
5433 label1 = gen_new_label();
a3251186
RH
5434 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5435 gen_extu(ot, t0);
1e4840bf 5436 gen_extu(ot, t2);
a3251186 5437 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
f7e80adf 5438 label2 = gen_new_label();
cad3a37d 5439 if (mod == 3) {
1e4840bf 5440 gen_op_mov_reg_v(ot, R_EAX, t0);
1130328e
FB
5441 tcg_gen_br(label2);
5442 gen_set_label(label1);
1e4840bf 5443 gen_op_mov_reg_v(ot, rm, t1);
cad3a37d 5444 } else {
f7e80adf
AG
5445 /* perform no-op store cycle like physical cpu; must be
5446 before changing accumulator to ensure idempotency if
5447 the store faults and the instruction is restarted */
5448 gen_op_st_v(ot + s->mem_index, t0, a0);
1e4840bf 5449 gen_op_mov_reg_v(ot, R_EAX, t0);
f7e80adf 5450 tcg_gen_br(label2);
1130328e 5451 gen_set_label(label1);
1e4840bf 5452 gen_op_st_v(ot + s->mem_index, t1, a0);
cad3a37d 5453 }
f7e80adf 5454 gen_set_label(label2);
1e4840bf 5455 tcg_gen_mov_tl(cpu_cc_src, t0);
a3251186
RH
5456 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5457 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
3ca51d07 5458 set_cc_op(s, CC_OP_SUBB + ot);
1e4840bf
FB
5459 tcg_temp_free(t0);
5460 tcg_temp_free(t1);
5461 tcg_temp_free(t2);
5462 tcg_temp_free(a0);
2c0262af 5463 }
2c0262af
FB
5464 break;
5465 case 0x1c7: /* cmpxchg8b */
0af10c86 5466 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5467 mod = (modrm >> 6) & 3;
71c3558e 5468 if ((mod == 3) || ((modrm & 0x38) != 0x8))
2c0262af 5469 goto illegal_op;
1b9d9ebb
FB
5470#ifdef TARGET_X86_64
5471 if (dflag == 2) {
5472 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5473 goto illegal_op;
5474 gen_jmp_im(pc_start - s->cs_base);
773cdfcc 5475 gen_update_cc_op(s);
0af10c86 5476 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
92fc4b58 5477 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
1b9d9ebb
FB
5478 } else
5479#endif
5480 {
5481 if (!(s->cpuid_features & CPUID_CX8))
5482 goto illegal_op;
5483 gen_jmp_im(pc_start - s->cs_base);
773cdfcc 5484 gen_update_cc_op(s);
0af10c86 5485 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
92fc4b58 5486 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
1b9d9ebb 5487 }
3ca51d07 5488 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 5489 break;
3b46e624 5490
2c0262af
FB
5491 /**************************/
5492 /* push/pop */
5493 case 0x50 ... 0x57: /* push */
57fec1fe 5494 gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
2c0262af
FB
5495 gen_push_T0(s);
5496 break;
5497 case 0x58 ... 0x5f: /* pop */
14ce26e7
FB
5498 if (CODE64(s)) {
5499 ot = dflag ? OT_QUAD : OT_WORD;
5500 } else {
5501 ot = dflag + OT_WORD;
5502 }
2c0262af 5503 gen_pop_T0(s);
77729c24 5504 /* NOTE: order is important for pop %sp */
2c0262af 5505 gen_pop_update(s);
57fec1fe 5506 gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
2c0262af
FB
5507 break;
5508 case 0x60: /* pusha */
14ce26e7
FB
5509 if (CODE64(s))
5510 goto illegal_op;
2c0262af
FB
5511 gen_pusha(s);
5512 break;
5513 case 0x61: /* popa */
14ce26e7
FB
5514 if (CODE64(s))
5515 goto illegal_op;
2c0262af
FB
5516 gen_popa(s);
5517 break;
5518 case 0x68: /* push Iv */
5519 case 0x6a:
14ce26e7
FB
5520 if (CODE64(s)) {
5521 ot = dflag ? OT_QUAD : OT_WORD;
5522 } else {
5523 ot = dflag + OT_WORD;
5524 }
2c0262af 5525 if (b == 0x68)
0af10c86 5526 val = insn_get(env, s, ot);
2c0262af 5527 else
0af10c86 5528 val = (int8_t)insn_get(env, s, OT_BYTE);
2c0262af
FB
5529 gen_op_movl_T0_im(val);
5530 gen_push_T0(s);
5531 break;
5532 case 0x8f: /* pop Ev */
14ce26e7
FB
5533 if (CODE64(s)) {
5534 ot = dflag ? OT_QUAD : OT_WORD;
5535 } else {
5536 ot = dflag + OT_WORD;
5537 }
0af10c86 5538 modrm = cpu_ldub_code(env, s->pc++);
77729c24 5539 mod = (modrm >> 6) & 3;
2c0262af 5540 gen_pop_T0(s);
77729c24
FB
5541 if (mod == 3) {
5542 /* NOTE: order is important for pop %sp */
5543 gen_pop_update(s);
14ce26e7 5544 rm = (modrm & 7) | REX_B(s);
57fec1fe 5545 gen_op_mov_reg_T0(ot, rm);
77729c24
FB
5546 } else {
5547 /* NOTE: order is important too for MMU exceptions */
14ce26e7 5548 s->popl_esp_hack = 1 << ot;
0af10c86 5549 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
77729c24
FB
5550 s->popl_esp_hack = 0;
5551 gen_pop_update(s);
5552 }
2c0262af
FB
5553 break;
5554 case 0xc8: /* enter */
5555 {
5556 int level;
0af10c86 5557 val = cpu_lduw_code(env, s->pc);
2c0262af 5558 s->pc += 2;
0af10c86 5559 level = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5560 gen_enter(s, val, level);
5561 }
5562 break;
5563 case 0xc9: /* leave */
5564 /* XXX: exception not precise (ESP is updated before potential exception) */
14ce26e7 5565 if (CODE64(s)) {
57fec1fe
FB
5566 gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
5567 gen_op_mov_reg_T0(OT_QUAD, R_ESP);
14ce26e7 5568 } else if (s->ss32) {
57fec1fe
FB
5569 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
5570 gen_op_mov_reg_T0(OT_LONG, R_ESP);
2c0262af 5571 } else {
57fec1fe
FB
5572 gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
5573 gen_op_mov_reg_T0(OT_WORD, R_ESP);
2c0262af
FB
5574 }
5575 gen_pop_T0(s);
14ce26e7
FB
5576 if (CODE64(s)) {
5577 ot = dflag ? OT_QUAD : OT_WORD;
5578 } else {
5579 ot = dflag + OT_WORD;
5580 }
57fec1fe 5581 gen_op_mov_reg_T0(ot, R_EBP);
2c0262af
FB
5582 gen_pop_update(s);
5583 break;
5584 case 0x06: /* push es */
5585 case 0x0e: /* push cs */
5586 case 0x16: /* push ss */
5587 case 0x1e: /* push ds */
14ce26e7
FB
5588 if (CODE64(s))
5589 goto illegal_op;
2c0262af
FB
5590 gen_op_movl_T0_seg(b >> 3);
5591 gen_push_T0(s);
5592 break;
5593 case 0x1a0: /* push fs */
5594 case 0x1a8: /* push gs */
5595 gen_op_movl_T0_seg((b >> 3) & 7);
5596 gen_push_T0(s);
5597 break;
5598 case 0x07: /* pop es */
5599 case 0x17: /* pop ss */
5600 case 0x1f: /* pop ds */
14ce26e7
FB
5601 if (CODE64(s))
5602 goto illegal_op;
2c0262af
FB
5603 reg = b >> 3;
5604 gen_pop_T0(s);
5605 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5606 gen_pop_update(s);
5607 if (reg == R_SS) {
a2cc3b24
FB
5608 /* if reg == SS, inhibit interrupts/trace. */
5609 /* If several instructions disable interrupts, only the
5610 _first_ does it */
5611 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 5612 gen_helper_set_inhibit_irq(cpu_env);
2c0262af
FB
5613 s->tf = 0;
5614 }
5615 if (s->is_jmp) {
14ce26e7 5616 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5617 gen_eob(s);
5618 }
5619 break;
5620 case 0x1a1: /* pop fs */
5621 case 0x1a9: /* pop gs */
5622 gen_pop_T0(s);
5623 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
5624 gen_pop_update(s);
5625 if (s->is_jmp) {
14ce26e7 5626 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5627 gen_eob(s);
5628 }
5629 break;
5630
5631 /**************************/
5632 /* mov */
5633 case 0x88:
5634 case 0x89: /* mov Gv, Ev */
5635 if ((b & 1) == 0)
5636 ot = OT_BYTE;
5637 else
14ce26e7 5638 ot = dflag + OT_WORD;
0af10c86 5639 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5640 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5641
2c0262af 5642 /* generate a generic store */
0af10c86 5643 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
2c0262af
FB
5644 break;
5645 case 0xc6:
5646 case 0xc7: /* mov Ev, Iv */
5647 if ((b & 1) == 0)
5648 ot = OT_BYTE;
5649 else
14ce26e7 5650 ot = dflag + OT_WORD;
0af10c86 5651 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5652 mod = (modrm >> 6) & 3;
14ce26e7
FB
5653 if (mod != 3) {
5654 s->rip_offset = insn_const_size(ot);
0af10c86 5655 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
14ce26e7 5656 }
0af10c86 5657 val = insn_get(env, s, ot);
2c0262af
FB
5658 gen_op_movl_T0_im(val);
5659 if (mod != 3)
57fec1fe 5660 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 5661 else
57fec1fe 5662 gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
2c0262af
FB
5663 break;
5664 case 0x8a:
5665 case 0x8b: /* mov Ev, Gv */
5666 if ((b & 1) == 0)
5667 ot = OT_BYTE;
5668 else
14ce26e7 5669 ot = OT_WORD + dflag;
0af10c86 5670 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5671 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5672
0af10c86 5673 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
57fec1fe 5674 gen_op_mov_reg_T0(ot, reg);
2c0262af
FB
5675 break;
5676 case 0x8e: /* mov seg, Gv */
0af10c86 5677 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5678 reg = (modrm >> 3) & 7;
5679 if (reg >= 6 || reg == R_CS)
5680 goto illegal_op;
0af10c86 5681 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
2c0262af
FB
5682 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5683 if (reg == R_SS) {
5684 /* if reg == SS, inhibit interrupts/trace */
a2cc3b24
FB
5685 /* If several instructions disable interrupts, only the
5686 _first_ does it */
5687 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 5688 gen_helper_set_inhibit_irq(cpu_env);
2c0262af
FB
5689 s->tf = 0;
5690 }
5691 if (s->is_jmp) {
14ce26e7 5692 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5693 gen_eob(s);
5694 }
5695 break;
5696 case 0x8c: /* mov Gv, seg */
0af10c86 5697 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5698 reg = (modrm >> 3) & 7;
5699 mod = (modrm >> 6) & 3;
5700 if (reg >= 6)
5701 goto illegal_op;
5702 gen_op_movl_T0_seg(reg);
14ce26e7
FB
5703 if (mod == 3)
5704 ot = OT_WORD + dflag;
5705 else
5706 ot = OT_WORD;
0af10c86 5707 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
5708 break;
5709
5710 case 0x1b6: /* movzbS Gv, Eb */
5711 case 0x1b7: /* movzwS Gv, Eb */
5712 case 0x1be: /* movsbS Gv, Eb */
5713 case 0x1bf: /* movswS Gv, Eb */
5714 {
5715 int d_ot;
5716 /* d_ot is the size of destination */
5717 d_ot = dflag + OT_WORD;
5718 /* ot is the size of source */
5719 ot = (b & 1) + OT_BYTE;
0af10c86 5720 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5721 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5722 mod = (modrm >> 6) & 3;
14ce26e7 5723 rm = (modrm & 7) | REX_B(s);
3b46e624 5724
2c0262af 5725 if (mod == 3) {
57fec1fe 5726 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af
FB
5727 switch(ot | (b & 8)) {
5728 case OT_BYTE:
e108dd01 5729 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5730 break;
5731 case OT_BYTE | 8:
e108dd01 5732 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5733 break;
5734 case OT_WORD:
e108dd01 5735 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5736 break;
5737 default:
5738 case OT_WORD | 8:
e108dd01 5739 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5740 break;
5741 }
57fec1fe 5742 gen_op_mov_reg_T0(d_ot, reg);
2c0262af 5743 } else {
0af10c86 5744 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af 5745 if (b & 8) {
57fec1fe 5746 gen_op_lds_T0_A0(ot + s->mem_index);
2c0262af 5747 } else {
57fec1fe 5748 gen_op_ldu_T0_A0(ot + s->mem_index);
2c0262af 5749 }
57fec1fe 5750 gen_op_mov_reg_T0(d_ot, reg);
2c0262af
FB
5751 }
5752 }
5753 break;
5754
5755 case 0x8d: /* lea */
14ce26e7 5756 ot = dflag + OT_WORD;
0af10c86 5757 modrm = cpu_ldub_code(env, s->pc++);
3a1d9b8b
FB
5758 mod = (modrm >> 6) & 3;
5759 if (mod == 3)
5760 goto illegal_op;
14ce26e7 5761 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5762 /* we must ensure that no segment is added */
5763 s->override = -1;
5764 val = s->addseg;
5765 s->addseg = 0;
0af10c86 5766 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af 5767 s->addseg = val;
57fec1fe 5768 gen_op_mov_reg_A0(ot - OT_WORD, reg);
2c0262af 5769 break;
3b46e624 5770
2c0262af
FB
5771 case 0xa0: /* mov EAX, Ov */
5772 case 0xa1:
5773 case 0xa2: /* mov Ov, EAX */
5774 case 0xa3:
2c0262af 5775 {
14ce26e7
FB
5776 target_ulong offset_addr;
5777
5778 if ((b & 1) == 0)
5779 ot = OT_BYTE;
5780 else
5781 ot = dflag + OT_WORD;
5782#ifdef TARGET_X86_64
8f091a59 5783 if (s->aflag == 2) {
0af10c86 5784 offset_addr = cpu_ldq_code(env, s->pc);
14ce26e7 5785 s->pc += 8;
57fec1fe 5786 gen_op_movq_A0_im(offset_addr);
5fafdf24 5787 } else
14ce26e7
FB
5788#endif
5789 {
5790 if (s->aflag) {
0af10c86 5791 offset_addr = insn_get(env, s, OT_LONG);
14ce26e7 5792 } else {
0af10c86 5793 offset_addr = insn_get(env, s, OT_WORD);
14ce26e7
FB
5794 }
5795 gen_op_movl_A0_im(offset_addr);
5796 }
664e0f19 5797 gen_add_A0_ds_seg(s);
14ce26e7 5798 if ((b & 2) == 0) {
57fec1fe
FB
5799 gen_op_ld_T0_A0(ot + s->mem_index);
5800 gen_op_mov_reg_T0(ot, R_EAX);
14ce26e7 5801 } else {
57fec1fe
FB
5802 gen_op_mov_TN_reg(ot, 0, R_EAX);
5803 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af
FB
5804 }
5805 }
2c0262af
FB
5806 break;
5807 case 0xd7: /* xlat */
14ce26e7 5808#ifdef TARGET_X86_64
8f091a59 5809 if (s->aflag == 2) {
57fec1fe 5810 gen_op_movq_A0_reg(R_EBX);
bbf662ee
FB
5811 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5812 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5813 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5fafdf24 5814 } else
14ce26e7
FB
5815#endif
5816 {
57fec1fe 5817 gen_op_movl_A0_reg(R_EBX);
bbf662ee
FB
5818 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5819 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5820 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
14ce26e7
FB
5821 if (s->aflag == 0)
5822 gen_op_andl_A0_ffff();
bbf662ee
FB
5823 else
5824 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
14ce26e7 5825 }
664e0f19 5826 gen_add_A0_ds_seg(s);
57fec1fe
FB
5827 gen_op_ldu_T0_A0(OT_BYTE + s->mem_index);
5828 gen_op_mov_reg_T0(OT_BYTE, R_EAX);
2c0262af
FB
5829 break;
5830 case 0xb0 ... 0xb7: /* mov R, Ib */
0af10c86 5831 val = insn_get(env, s, OT_BYTE);
2c0262af 5832 gen_op_movl_T0_im(val);
57fec1fe 5833 gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
2c0262af
FB
5834 break;
5835 case 0xb8 ... 0xbf: /* mov R, Iv */
14ce26e7
FB
5836#ifdef TARGET_X86_64
5837 if (dflag == 2) {
5838 uint64_t tmp;
5839 /* 64 bit case */
0af10c86 5840 tmp = cpu_ldq_code(env, s->pc);
14ce26e7
FB
5841 s->pc += 8;
5842 reg = (b & 7) | REX_B(s);
5843 gen_movtl_T0_im(tmp);
57fec1fe 5844 gen_op_mov_reg_T0(OT_QUAD, reg);
5fafdf24 5845 } else
14ce26e7
FB
5846#endif
5847 {
5848 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 5849 val = insn_get(env, s, ot);
14ce26e7
FB
5850 reg = (b & 7) | REX_B(s);
5851 gen_op_movl_T0_im(val);
57fec1fe 5852 gen_op_mov_reg_T0(ot, reg);
14ce26e7 5853 }
2c0262af
FB
5854 break;
5855
5856 case 0x91 ... 0x97: /* xchg R, EAX */
7418027e 5857 do_xchg_reg_eax:
14ce26e7
FB
5858 ot = dflag + OT_WORD;
5859 reg = (b & 7) | REX_B(s);
2c0262af
FB
5860 rm = R_EAX;
5861 goto do_xchg_reg;
5862 case 0x86:
5863 case 0x87: /* xchg Ev, Gv */
5864 if ((b & 1) == 0)
5865 ot = OT_BYTE;
5866 else
14ce26e7 5867 ot = dflag + OT_WORD;
0af10c86 5868 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5869 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5870 mod = (modrm >> 6) & 3;
5871 if (mod == 3) {
14ce26e7 5872 rm = (modrm & 7) | REX_B(s);
2c0262af 5873 do_xchg_reg:
57fec1fe
FB
5874 gen_op_mov_TN_reg(ot, 0, reg);
5875 gen_op_mov_TN_reg(ot, 1, rm);
5876 gen_op_mov_reg_T0(ot, rm);
5877 gen_op_mov_reg_T1(ot, reg);
2c0262af 5878 } else {
0af10c86 5879 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 5880 gen_op_mov_TN_reg(ot, 0, reg);
2c0262af
FB
5881 /* for xchg, lock is implicit */
5882 if (!(prefixes & PREFIX_LOCK))
a7812ae4 5883 gen_helper_lock();
57fec1fe
FB
5884 gen_op_ld_T1_A0(ot + s->mem_index);
5885 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 5886 if (!(prefixes & PREFIX_LOCK))
a7812ae4 5887 gen_helper_unlock();
57fec1fe 5888 gen_op_mov_reg_T1(ot, reg);
2c0262af
FB
5889 }
5890 break;
5891 case 0xc4: /* les Gv */
701ed211 5892 /* In CODE64 this is VEX3; see above. */
2c0262af
FB
5893 op = R_ES;
5894 goto do_lxx;
5895 case 0xc5: /* lds Gv */
701ed211 5896 /* In CODE64 this is VEX2; see above. */
2c0262af
FB
5897 op = R_DS;
5898 goto do_lxx;
5899 case 0x1b2: /* lss Gv */
5900 op = R_SS;
5901 goto do_lxx;
5902 case 0x1b4: /* lfs Gv */
5903 op = R_FS;
5904 goto do_lxx;
5905 case 0x1b5: /* lgs Gv */
5906 op = R_GS;
5907 do_lxx:
5908 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 5909 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5910 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5911 mod = (modrm >> 6) & 3;
5912 if (mod == 3)
5913 goto illegal_op;
0af10c86 5914 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 5915 gen_op_ld_T1_A0(ot + s->mem_index);
aba9d61e 5916 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
2c0262af 5917 /* load the segment first to handle exceptions properly */
57fec1fe 5918 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
5919 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5920 /* then put the data */
57fec1fe 5921 gen_op_mov_reg_T1(ot, reg);
2c0262af 5922 if (s->is_jmp) {
14ce26e7 5923 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5924 gen_eob(s);
5925 }
5926 break;
3b46e624 5927
2c0262af
FB
5928 /************************/
5929 /* shifts */
5930 case 0xc0:
5931 case 0xc1:
5932 /* shift Ev,Ib */
5933 shift = 2;
5934 grp2:
5935 {
5936 if ((b & 1) == 0)
5937 ot = OT_BYTE;
5938 else
14ce26e7 5939 ot = dflag + OT_WORD;
3b46e624 5940
0af10c86 5941 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5942 mod = (modrm >> 6) & 3;
2c0262af 5943 op = (modrm >> 3) & 7;
3b46e624 5944
2c0262af 5945 if (mod != 3) {
14ce26e7
FB
5946 if (shift == 2) {
5947 s->rip_offset = 1;
5948 }
0af10c86 5949 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
5950 opreg = OR_TMP0;
5951 } else {
14ce26e7 5952 opreg = (modrm & 7) | REX_B(s);
2c0262af
FB
5953 }
5954
5955 /* simpler op */
5956 if (shift == 0) {
5957 gen_shift(s, op, ot, opreg, OR_ECX);
5958 } else {
5959 if (shift == 2) {
0af10c86 5960 shift = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5961 }
5962 gen_shifti(s, op, ot, opreg, shift);
5963 }
5964 }
5965 break;
5966 case 0xd0:
5967 case 0xd1:
5968 /* shift Ev,1 */
5969 shift = 1;
5970 goto grp2;
5971 case 0xd2:
5972 case 0xd3:
5973 /* shift Ev,cl */
5974 shift = 0;
5975 goto grp2;
5976
5977 case 0x1a4: /* shld imm */
5978 op = 0;
5979 shift = 1;
5980 goto do_shiftd;
5981 case 0x1a5: /* shld cl */
5982 op = 0;
5983 shift = 0;
5984 goto do_shiftd;
5985 case 0x1ac: /* shrd imm */
5986 op = 1;
5987 shift = 1;
5988 goto do_shiftd;
5989 case 0x1ad: /* shrd cl */
5990 op = 1;
5991 shift = 0;
5992 do_shiftd:
14ce26e7 5993 ot = dflag + OT_WORD;
0af10c86 5994 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5995 mod = (modrm >> 6) & 3;
14ce26e7
FB
5996 rm = (modrm & 7) | REX_B(s);
5997 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5998 if (mod != 3) {
0af10c86 5999 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
b6abf97d 6000 opreg = OR_TMP0;
2c0262af 6001 } else {
b6abf97d 6002 opreg = rm;
2c0262af 6003 }
57fec1fe 6004 gen_op_mov_TN_reg(ot, 1, reg);
3b46e624 6005
2c0262af 6006 if (shift) {
3b9d3cf1
PB
6007 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
6008 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
6009 tcg_temp_free(imm);
2c0262af 6010 } else {
3b9d3cf1 6011 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
2c0262af
FB
6012 }
6013 break;
6014
6015 /************************/
6016 /* floats */
5fafdf24 6017 case 0xd8 ... 0xdf:
7eee2a50
FB
6018 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
6019 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
6020 /* XXX: what to do if illegal op ? */
6021 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6022 break;
6023 }
0af10c86 6024 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
6025 mod = (modrm >> 6) & 3;
6026 rm = modrm & 7;
6027 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2c0262af
FB
6028 if (mod != 3) {
6029 /* memory op */
0af10c86 6030 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
6031 switch(op) {
6032 case 0x00 ... 0x07: /* fxxxs */
6033 case 0x10 ... 0x17: /* fixxxl */
6034 case 0x20 ... 0x27: /* fxxxl */
6035 case 0x30 ... 0x37: /* fixxx */
6036 {
6037 int op1;
6038 op1 = op & 7;
6039
6040 switch(op >> 4) {
6041 case 0:
ba7cd150 6042 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
b6abf97d 6043 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 6044 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
6045 break;
6046 case 1:
ba7cd150 6047 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
b6abf97d 6048 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 6049 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
6050 break;
6051 case 2:
b6abf97d 6052 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 6053 (s->mem_index >> 2) - 1);
d3eb5eae 6054 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
6055 break;
6056 case 3:
6057 default:
ba7cd150 6058 gen_op_lds_T0_A0(OT_WORD + s->mem_index);
b6abf97d 6059 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 6060 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
6061 break;
6062 }
3b46e624 6063
a7812ae4 6064 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
6065 if (op1 == 3) {
6066 /* fcomp needs pop */
d3eb5eae 6067 gen_helper_fpop(cpu_env);
2c0262af
FB
6068 }
6069 }
6070 break;
6071 case 0x08: /* flds */
6072 case 0x0a: /* fsts */
6073 case 0x0b: /* fstps */
465e9838
FB
6074 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
6075 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
6076 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
2c0262af
FB
6077 switch(op & 7) {
6078 case 0:
6079 switch(op >> 4) {
6080 case 0:
ba7cd150 6081 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
b6abf97d 6082 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 6083 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
6084 break;
6085 case 1:
ba7cd150 6086 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
b6abf97d 6087 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 6088 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
6089 break;
6090 case 2:
b6abf97d 6091 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 6092 (s->mem_index >> 2) - 1);
d3eb5eae 6093 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
6094 break;
6095 case 3:
6096 default:
ba7cd150 6097 gen_op_lds_T0_A0(OT_WORD + s->mem_index);
b6abf97d 6098 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 6099 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
6100 break;
6101 }
6102 break;
465e9838 6103 case 1:
19e6c4b8 6104 /* XXX: the corresponding CPUID bit must be tested ! */
465e9838
FB
6105 switch(op >> 4) {
6106 case 1:
d3eb5eae 6107 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 6108 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 6109 gen_op_st_T0_A0(OT_LONG + s->mem_index);
465e9838
FB
6110 break;
6111 case 2:
d3eb5eae 6112 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
b6abf97d 6113 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 6114 (s->mem_index >> 2) - 1);
465e9838
FB
6115 break;
6116 case 3:
6117 default:
d3eb5eae 6118 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 6119 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 6120 gen_op_st_T0_A0(OT_WORD + s->mem_index);
19e6c4b8 6121 break;
465e9838 6122 }
d3eb5eae 6123 gen_helper_fpop(cpu_env);
465e9838 6124 break;
2c0262af
FB
6125 default:
6126 switch(op >> 4) {
6127 case 0:
d3eb5eae 6128 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 6129 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 6130 gen_op_st_T0_A0(OT_LONG + s->mem_index);
2c0262af
FB
6131 break;
6132 case 1:
d3eb5eae 6133 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 6134 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 6135 gen_op_st_T0_A0(OT_LONG + s->mem_index);
2c0262af
FB
6136 break;
6137 case 2:
d3eb5eae 6138 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
b6abf97d 6139 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 6140 (s->mem_index >> 2) - 1);
2c0262af
FB
6141 break;
6142 case 3:
6143 default:
d3eb5eae 6144 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 6145 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 6146 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
6147 break;
6148 }
6149 if ((op & 7) == 3)
d3eb5eae 6150 gen_helper_fpop(cpu_env);
2c0262af
FB
6151 break;
6152 }
6153 break;
6154 case 0x0c: /* fldenv mem */
773cdfcc 6155 gen_update_cc_op(s);
19e6c4b8 6156 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6157 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
2c0262af
FB
6158 break;
6159 case 0x0d: /* fldcw mem */
19e6c4b8 6160 gen_op_ld_T0_A0(OT_WORD + s->mem_index);
b6abf97d 6161 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 6162 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
2c0262af
FB
6163 break;
6164 case 0x0e: /* fnstenv mem */
773cdfcc 6165 gen_update_cc_op(s);
19e6c4b8 6166 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6167 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
2c0262af
FB
6168 break;
6169 case 0x0f: /* fnstcw mem */
d3eb5eae 6170 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
b6abf97d 6171 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
19e6c4b8 6172 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
6173 break;
6174 case 0x1d: /* fldt mem */
773cdfcc 6175 gen_update_cc_op(s);
19e6c4b8 6176 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6177 gen_helper_fldt_ST0(cpu_env, cpu_A0);
2c0262af
FB
6178 break;
6179 case 0x1f: /* fstpt mem */
773cdfcc 6180 gen_update_cc_op(s);
19e6c4b8 6181 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
6182 gen_helper_fstt_ST0(cpu_env, cpu_A0);
6183 gen_helper_fpop(cpu_env);
2c0262af
FB
6184 break;
6185 case 0x2c: /* frstor mem */
773cdfcc 6186 gen_update_cc_op(s);
19e6c4b8 6187 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6188 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
2c0262af
FB
6189 break;
6190 case 0x2e: /* fnsave mem */
773cdfcc 6191 gen_update_cc_op(s);
19e6c4b8 6192 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6193 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
2c0262af
FB
6194 break;
6195 case 0x2f: /* fnstsw mem */
d3eb5eae 6196 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
b6abf97d 6197 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
19e6c4b8 6198 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
6199 break;
6200 case 0x3c: /* fbld */
773cdfcc 6201 gen_update_cc_op(s);
19e6c4b8 6202 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6203 gen_helper_fbld_ST0(cpu_env, cpu_A0);
2c0262af
FB
6204 break;
6205 case 0x3e: /* fbstp */
773cdfcc 6206 gen_update_cc_op(s);
19e6c4b8 6207 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
6208 gen_helper_fbst_ST0(cpu_env, cpu_A0);
6209 gen_helper_fpop(cpu_env);
2c0262af
FB
6210 break;
6211 case 0x3d: /* fildll */
b6abf97d 6212 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 6213 (s->mem_index >> 2) - 1);
d3eb5eae 6214 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
6215 break;
6216 case 0x3f: /* fistpll */
d3eb5eae 6217 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
b6abf97d 6218 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 6219 (s->mem_index >> 2) - 1);
d3eb5eae 6220 gen_helper_fpop(cpu_env);
2c0262af
FB
6221 break;
6222 default:
6223 goto illegal_op;
6224 }
6225 } else {
6226 /* register float ops */
6227 opreg = rm;
6228
6229 switch(op) {
6230 case 0x08: /* fld sti */
d3eb5eae
BS
6231 gen_helper_fpush(cpu_env);
6232 gen_helper_fmov_ST0_STN(cpu_env,
6233 tcg_const_i32((opreg + 1) & 7));
2c0262af
FB
6234 break;
6235 case 0x09: /* fxchg sti */
c169c906
FB
6236 case 0x29: /* fxchg4 sti, undocumented op */
6237 case 0x39: /* fxchg7 sti, undocumented op */
d3eb5eae 6238 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
6239 break;
6240 case 0x0a: /* grp d9/2 */
6241 switch(rm) {
6242 case 0: /* fnop */
023fe10d 6243 /* check exceptions (FreeBSD FPU probe) */
773cdfcc 6244 gen_update_cc_op(s);
14ce26e7 6245 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6246 gen_helper_fwait(cpu_env);
2c0262af
FB
6247 break;
6248 default:
6249 goto illegal_op;
6250 }
6251 break;
6252 case 0x0c: /* grp d9/4 */
6253 switch(rm) {
6254 case 0: /* fchs */
d3eb5eae 6255 gen_helper_fchs_ST0(cpu_env);
2c0262af
FB
6256 break;
6257 case 1: /* fabs */
d3eb5eae 6258 gen_helper_fabs_ST0(cpu_env);
2c0262af
FB
6259 break;
6260 case 4: /* ftst */
d3eb5eae
BS
6261 gen_helper_fldz_FT0(cpu_env);
6262 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
6263 break;
6264 case 5: /* fxam */
d3eb5eae 6265 gen_helper_fxam_ST0(cpu_env);
2c0262af
FB
6266 break;
6267 default:
6268 goto illegal_op;
6269 }
6270 break;
6271 case 0x0d: /* grp d9/5 */
6272 {
6273 switch(rm) {
6274 case 0:
d3eb5eae
BS
6275 gen_helper_fpush(cpu_env);
6276 gen_helper_fld1_ST0(cpu_env);
2c0262af
FB
6277 break;
6278 case 1:
d3eb5eae
BS
6279 gen_helper_fpush(cpu_env);
6280 gen_helper_fldl2t_ST0(cpu_env);
2c0262af
FB
6281 break;
6282 case 2:
d3eb5eae
BS
6283 gen_helper_fpush(cpu_env);
6284 gen_helper_fldl2e_ST0(cpu_env);
2c0262af
FB
6285 break;
6286 case 3:
d3eb5eae
BS
6287 gen_helper_fpush(cpu_env);
6288 gen_helper_fldpi_ST0(cpu_env);
2c0262af
FB
6289 break;
6290 case 4:
d3eb5eae
BS
6291 gen_helper_fpush(cpu_env);
6292 gen_helper_fldlg2_ST0(cpu_env);
2c0262af
FB
6293 break;
6294 case 5:
d3eb5eae
BS
6295 gen_helper_fpush(cpu_env);
6296 gen_helper_fldln2_ST0(cpu_env);
2c0262af
FB
6297 break;
6298 case 6:
d3eb5eae
BS
6299 gen_helper_fpush(cpu_env);
6300 gen_helper_fldz_ST0(cpu_env);
2c0262af
FB
6301 break;
6302 default:
6303 goto illegal_op;
6304 }
6305 }
6306 break;
6307 case 0x0e: /* grp d9/6 */
6308 switch(rm) {
6309 case 0: /* f2xm1 */
d3eb5eae 6310 gen_helper_f2xm1(cpu_env);
2c0262af
FB
6311 break;
6312 case 1: /* fyl2x */
d3eb5eae 6313 gen_helper_fyl2x(cpu_env);
2c0262af
FB
6314 break;
6315 case 2: /* fptan */
d3eb5eae 6316 gen_helper_fptan(cpu_env);
2c0262af
FB
6317 break;
6318 case 3: /* fpatan */
d3eb5eae 6319 gen_helper_fpatan(cpu_env);
2c0262af
FB
6320 break;
6321 case 4: /* fxtract */
d3eb5eae 6322 gen_helper_fxtract(cpu_env);
2c0262af
FB
6323 break;
6324 case 5: /* fprem1 */
d3eb5eae 6325 gen_helper_fprem1(cpu_env);
2c0262af
FB
6326 break;
6327 case 6: /* fdecstp */
d3eb5eae 6328 gen_helper_fdecstp(cpu_env);
2c0262af
FB
6329 break;
6330 default:
6331 case 7: /* fincstp */
d3eb5eae 6332 gen_helper_fincstp(cpu_env);
2c0262af
FB
6333 break;
6334 }
6335 break;
6336 case 0x0f: /* grp d9/7 */
6337 switch(rm) {
6338 case 0: /* fprem */
d3eb5eae 6339 gen_helper_fprem(cpu_env);
2c0262af
FB
6340 break;
6341 case 1: /* fyl2xp1 */
d3eb5eae 6342 gen_helper_fyl2xp1(cpu_env);
2c0262af
FB
6343 break;
6344 case 2: /* fsqrt */
d3eb5eae 6345 gen_helper_fsqrt(cpu_env);
2c0262af
FB
6346 break;
6347 case 3: /* fsincos */
d3eb5eae 6348 gen_helper_fsincos(cpu_env);
2c0262af
FB
6349 break;
6350 case 5: /* fscale */
d3eb5eae 6351 gen_helper_fscale(cpu_env);
2c0262af
FB
6352 break;
6353 case 4: /* frndint */
d3eb5eae 6354 gen_helper_frndint(cpu_env);
2c0262af
FB
6355 break;
6356 case 6: /* fsin */
d3eb5eae 6357 gen_helper_fsin(cpu_env);
2c0262af
FB
6358 break;
6359 default:
6360 case 7: /* fcos */
d3eb5eae 6361 gen_helper_fcos(cpu_env);
2c0262af
FB
6362 break;
6363 }
6364 break;
6365 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6366 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6367 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6368 {
6369 int op1;
3b46e624 6370
2c0262af
FB
6371 op1 = op & 7;
6372 if (op >= 0x20) {
a7812ae4 6373 gen_helper_fp_arith_STN_ST0(op1, opreg);
2c0262af 6374 if (op >= 0x30)
d3eb5eae 6375 gen_helper_fpop(cpu_env);
2c0262af 6376 } else {
d3eb5eae 6377 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
a7812ae4 6378 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
6379 }
6380 }
6381 break;
6382 case 0x02: /* fcom */
c169c906 6383 case 0x22: /* fcom2, undocumented op */
d3eb5eae
BS
6384 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6385 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
6386 break;
6387 case 0x03: /* fcomp */
c169c906
FB
6388 case 0x23: /* fcomp3, undocumented op */
6389 case 0x32: /* fcomp5, undocumented op */
d3eb5eae
BS
6390 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6391 gen_helper_fcom_ST0_FT0(cpu_env);
6392 gen_helper_fpop(cpu_env);
2c0262af
FB
6393 break;
6394 case 0x15: /* da/5 */
6395 switch(rm) {
6396 case 1: /* fucompp */
d3eb5eae
BS
6397 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6398 gen_helper_fucom_ST0_FT0(cpu_env);
6399 gen_helper_fpop(cpu_env);
6400 gen_helper_fpop(cpu_env);
2c0262af
FB
6401 break;
6402 default:
6403 goto illegal_op;
6404 }
6405 break;
6406 case 0x1c:
6407 switch(rm) {
6408 case 0: /* feni (287 only, just do nop here) */
6409 break;
6410 case 1: /* fdisi (287 only, just do nop here) */
6411 break;
6412 case 2: /* fclex */
d3eb5eae 6413 gen_helper_fclex(cpu_env);
2c0262af
FB
6414 break;
6415 case 3: /* fninit */
d3eb5eae 6416 gen_helper_fninit(cpu_env);
2c0262af
FB
6417 break;
6418 case 4: /* fsetpm (287 only, just do nop here) */
6419 break;
6420 default:
6421 goto illegal_op;
6422 }
6423 break;
6424 case 0x1d: /* fucomi */
773cdfcc 6425 gen_update_cc_op(s);
d3eb5eae
BS
6426 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6427 gen_helper_fucomi_ST0_FT0(cpu_env);
3ca51d07 6428 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6429 break;
6430 case 0x1e: /* fcomi */
773cdfcc 6431 gen_update_cc_op(s);
d3eb5eae
BS
6432 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6433 gen_helper_fcomi_ST0_FT0(cpu_env);
3ca51d07 6434 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6435 break;
658c8bda 6436 case 0x28: /* ffree sti */
d3eb5eae 6437 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
5fafdf24 6438 break;
2c0262af 6439 case 0x2a: /* fst sti */
d3eb5eae 6440 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
6441 break;
6442 case 0x2b: /* fstp sti */
c169c906
FB
6443 case 0x0b: /* fstp1 sti, undocumented op */
6444 case 0x3a: /* fstp8 sti, undocumented op */
6445 case 0x3b: /* fstp9 sti, undocumented op */
d3eb5eae
BS
6446 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6447 gen_helper_fpop(cpu_env);
2c0262af
FB
6448 break;
6449 case 0x2c: /* fucom st(i) */
d3eb5eae
BS
6450 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6451 gen_helper_fucom_ST0_FT0(cpu_env);
2c0262af
FB
6452 break;
6453 case 0x2d: /* fucomp st(i) */
d3eb5eae
BS
6454 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6455 gen_helper_fucom_ST0_FT0(cpu_env);
6456 gen_helper_fpop(cpu_env);
2c0262af
FB
6457 break;
6458 case 0x33: /* de/3 */
6459 switch(rm) {
6460 case 1: /* fcompp */
d3eb5eae
BS
6461 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6462 gen_helper_fcom_ST0_FT0(cpu_env);
6463 gen_helper_fpop(cpu_env);
6464 gen_helper_fpop(cpu_env);
2c0262af
FB
6465 break;
6466 default:
6467 goto illegal_op;
6468 }
6469 break;
c169c906 6470 case 0x38: /* ffreep sti, undocumented op */
d3eb5eae
BS
6471 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6472 gen_helper_fpop(cpu_env);
c169c906 6473 break;
2c0262af
FB
6474 case 0x3c: /* df/4 */
6475 switch(rm) {
6476 case 0:
d3eb5eae 6477 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
b6abf97d 6478 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
19e6c4b8 6479 gen_op_mov_reg_T0(OT_WORD, R_EAX);
2c0262af
FB
6480 break;
6481 default:
6482 goto illegal_op;
6483 }
6484 break;
6485 case 0x3d: /* fucomip */
773cdfcc 6486 gen_update_cc_op(s);
d3eb5eae
BS
6487 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6488 gen_helper_fucomi_ST0_FT0(cpu_env);
6489 gen_helper_fpop(cpu_env);
3ca51d07 6490 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6491 break;
6492 case 0x3e: /* fcomip */
773cdfcc 6493 gen_update_cc_op(s);
d3eb5eae
BS
6494 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6495 gen_helper_fcomi_ST0_FT0(cpu_env);
6496 gen_helper_fpop(cpu_env);
3ca51d07 6497 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6498 break;
a2cc3b24
FB
6499 case 0x10 ... 0x13: /* fcmovxx */
6500 case 0x18 ... 0x1b:
6501 {
19e6c4b8 6502 int op1, l1;
d70040bc 6503 static const uint8_t fcmov_cc[8] = {
a2cc3b24
FB
6504 (JCC_B << 1),
6505 (JCC_Z << 1),
6506 (JCC_BE << 1),
6507 (JCC_P << 1),
6508 };
1e4840bf 6509 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
19e6c4b8 6510 l1 = gen_new_label();
dc259201 6511 gen_jcc1_noeob(s, op1, l1);
d3eb5eae 6512 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
19e6c4b8 6513 gen_set_label(l1);
a2cc3b24
FB
6514 }
6515 break;
2c0262af
FB
6516 default:
6517 goto illegal_op;
6518 }
6519 }
6520 break;
6521 /************************/
6522 /* string ops */
6523
6524 case 0xa4: /* movsS */
6525 case 0xa5:
6526 if ((b & 1) == 0)
6527 ot = OT_BYTE;
6528 else
14ce26e7 6529 ot = dflag + OT_WORD;
2c0262af
FB
6530
6531 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6532 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6533 } else {
6534 gen_movs(s, ot);
6535 }
6536 break;
3b46e624 6537
2c0262af
FB
6538 case 0xaa: /* stosS */
6539 case 0xab:
6540 if ((b & 1) == 0)
6541 ot = OT_BYTE;
6542 else
14ce26e7 6543 ot = dflag + OT_WORD;
2c0262af
FB
6544
6545 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6546 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6547 } else {
6548 gen_stos(s, ot);
6549 }
6550 break;
6551 case 0xac: /* lodsS */
6552 case 0xad:
6553 if ((b & 1) == 0)
6554 ot = OT_BYTE;
6555 else
14ce26e7 6556 ot = dflag + OT_WORD;
2c0262af
FB
6557 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6558 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6559 } else {
6560 gen_lods(s, ot);
6561 }
6562 break;
6563 case 0xae: /* scasS */
6564 case 0xaf:
6565 if ((b & 1) == 0)
6566 ot = OT_BYTE;
6567 else
14ce26e7 6568 ot = dflag + OT_WORD;
2c0262af
FB
6569 if (prefixes & PREFIX_REPNZ) {
6570 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6571 } else if (prefixes & PREFIX_REPZ) {
6572 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6573 } else {
6574 gen_scas(s, ot);
2c0262af
FB
6575 }
6576 break;
6577
6578 case 0xa6: /* cmpsS */
6579 case 0xa7:
6580 if ((b & 1) == 0)
6581 ot = OT_BYTE;
6582 else
14ce26e7 6583 ot = dflag + OT_WORD;
2c0262af
FB
6584 if (prefixes & PREFIX_REPNZ) {
6585 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6586 } else if (prefixes & PREFIX_REPZ) {
6587 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6588 } else {
6589 gen_cmps(s, ot);
2c0262af
FB
6590 }
6591 break;
6592 case 0x6c: /* insS */
6593 case 0x6d:
f115e911
FB
6594 if ((b & 1) == 0)
6595 ot = OT_BYTE;
6596 else
6597 ot = dflag ? OT_LONG : OT_WORD;
57fec1fe 6598 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
0573fbfc 6599 gen_op_andl_T0_ffff();
b8b6a50b
FB
6600 gen_check_io(s, ot, pc_start - s->cs_base,
6601 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
f115e911
FB
6602 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6603 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 6604 } else {
f115e911 6605 gen_ins(s, ot);
2e70f6ef
PB
6606 if (use_icount) {
6607 gen_jmp(s, s->pc - s->cs_base);
6608 }
2c0262af
FB
6609 }
6610 break;
6611 case 0x6e: /* outsS */
6612 case 0x6f:
f115e911
FB
6613 if ((b & 1) == 0)
6614 ot = OT_BYTE;
6615 else
6616 ot = dflag ? OT_LONG : OT_WORD;
57fec1fe 6617 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
0573fbfc 6618 gen_op_andl_T0_ffff();
b8b6a50b
FB
6619 gen_check_io(s, ot, pc_start - s->cs_base,
6620 svm_is_rep(prefixes) | 4);
f115e911
FB
6621 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6622 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 6623 } else {
f115e911 6624 gen_outs(s, ot);
2e70f6ef
PB
6625 if (use_icount) {
6626 gen_jmp(s, s->pc - s->cs_base);
6627 }
2c0262af
FB
6628 }
6629 break;
6630
6631 /************************/
6632 /* port I/O */
0573fbfc 6633
2c0262af
FB
6634 case 0xe4:
6635 case 0xe5:
f115e911
FB
6636 if ((b & 1) == 0)
6637 ot = OT_BYTE;
6638 else
6639 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 6640 val = cpu_ldub_code(env, s->pc++);
f115e911 6641 gen_op_movl_T0_im(val);
b8b6a50b
FB
6642 gen_check_io(s, ot, pc_start - s->cs_base,
6643 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
2e70f6ef
PB
6644 if (use_icount)
6645 gen_io_start();
b6abf97d 6646 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 6647 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
57fec1fe 6648 gen_op_mov_reg_T1(ot, R_EAX);
2e70f6ef
PB
6649 if (use_icount) {
6650 gen_io_end();
6651 gen_jmp(s, s->pc - s->cs_base);
6652 }
2c0262af
FB
6653 break;
6654 case 0xe6:
6655 case 0xe7:
f115e911
FB
6656 if ((b & 1) == 0)
6657 ot = OT_BYTE;
6658 else
6659 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 6660 val = cpu_ldub_code(env, s->pc++);
f115e911 6661 gen_op_movl_T0_im(val);
b8b6a50b
FB
6662 gen_check_io(s, ot, pc_start - s->cs_base,
6663 svm_is_rep(prefixes));
57fec1fe 6664 gen_op_mov_TN_reg(ot, 1, R_EAX);
b8b6a50b 6665
2e70f6ef
PB
6666 if (use_icount)
6667 gen_io_start();
b6abf97d 6668 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
b6abf97d 6669 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
a7812ae4 6670 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
2e70f6ef
PB
6671 if (use_icount) {
6672 gen_io_end();
6673 gen_jmp(s, s->pc - s->cs_base);
6674 }
2c0262af
FB
6675 break;
6676 case 0xec:
6677 case 0xed:
f115e911
FB
6678 if ((b & 1) == 0)
6679 ot = OT_BYTE;
6680 else
6681 ot = dflag ? OT_LONG : OT_WORD;
57fec1fe 6682 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
4f31916f 6683 gen_op_andl_T0_ffff();
b8b6a50b
FB
6684 gen_check_io(s, ot, pc_start - s->cs_base,
6685 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
2e70f6ef
PB
6686 if (use_icount)
6687 gen_io_start();
b6abf97d 6688 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 6689 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
57fec1fe 6690 gen_op_mov_reg_T1(ot, R_EAX);
2e70f6ef
PB
6691 if (use_icount) {
6692 gen_io_end();
6693 gen_jmp(s, s->pc - s->cs_base);
6694 }
2c0262af
FB
6695 break;
6696 case 0xee:
6697 case 0xef:
f115e911
FB
6698 if ((b & 1) == 0)
6699 ot = OT_BYTE;
6700 else
6701 ot = dflag ? OT_LONG : OT_WORD;
57fec1fe 6702 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
4f31916f 6703 gen_op_andl_T0_ffff();
b8b6a50b
FB
6704 gen_check_io(s, ot, pc_start - s->cs_base,
6705 svm_is_rep(prefixes));
57fec1fe 6706 gen_op_mov_TN_reg(ot, 1, R_EAX);
b8b6a50b 6707
2e70f6ef
PB
6708 if (use_icount)
6709 gen_io_start();
b6abf97d 6710 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
b6abf97d 6711 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
a7812ae4 6712 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
2e70f6ef
PB
6713 if (use_icount) {
6714 gen_io_end();
6715 gen_jmp(s, s->pc - s->cs_base);
6716 }
2c0262af
FB
6717 break;
6718
6719 /************************/
6720 /* control */
6721 case 0xc2: /* ret im */
0af10c86 6722 val = cpu_ldsw_code(env, s->pc);
2c0262af
FB
6723 s->pc += 2;
6724 gen_pop_T0(s);
8f091a59
FB
6725 if (CODE64(s) && s->dflag)
6726 s->dflag = 2;
2c0262af
FB
6727 gen_stack_update(s, val + (2 << s->dflag));
6728 if (s->dflag == 0)
6729 gen_op_andl_T0_ffff();
6730 gen_op_jmp_T0();
6731 gen_eob(s);
6732 break;
6733 case 0xc3: /* ret */
6734 gen_pop_T0(s);
6735 gen_pop_update(s);
6736 if (s->dflag == 0)
6737 gen_op_andl_T0_ffff();
6738 gen_op_jmp_T0();
6739 gen_eob(s);
6740 break;
6741 case 0xca: /* lret im */
0af10c86 6742 val = cpu_ldsw_code(env, s->pc);
2c0262af
FB
6743 s->pc += 2;
6744 do_lret:
6745 if (s->pe && !s->vm86) {
773cdfcc 6746 gen_update_cc_op(s);
14ce26e7 6747 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 6748 gen_helper_lret_protected(cpu_env, tcg_const_i32(s->dflag),
a7812ae4 6749 tcg_const_i32(val));
2c0262af
FB
6750 } else {
6751 gen_stack_A0(s);
6752 /* pop offset */
57fec1fe 6753 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
2c0262af
FB
6754 if (s->dflag == 0)
6755 gen_op_andl_T0_ffff();
6756 /* NOTE: keeping EIP updated is not a problem in case of
6757 exception */
6758 gen_op_jmp_T0();
6759 /* pop selector */
6760 gen_op_addl_A0_im(2 << s->dflag);
57fec1fe 6761 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
3bd7da9e 6762 gen_op_movl_seg_T0_vm(R_CS);
2c0262af
FB
6763 /* add stack offset */
6764 gen_stack_update(s, val + (4 << s->dflag));
6765 }
6766 gen_eob(s);
6767 break;
6768 case 0xcb: /* lret */
6769 val = 0;
6770 goto do_lret;
6771 case 0xcf: /* iret */
872929aa 6772 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
2c0262af
FB
6773 if (!s->pe) {
6774 /* real mode */
2999a0b2 6775 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
3ca51d07 6776 set_cc_op(s, CC_OP_EFLAGS);
f115e911
FB
6777 } else if (s->vm86) {
6778 if (s->iopl != 3) {
6779 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6780 } else {
2999a0b2 6781 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
3ca51d07 6782 set_cc_op(s, CC_OP_EFLAGS);
f115e911 6783 }
2c0262af 6784 } else {
773cdfcc 6785 gen_update_cc_op(s);
14ce26e7 6786 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 6787 gen_helper_iret_protected(cpu_env, tcg_const_i32(s->dflag),
a7812ae4 6788 tcg_const_i32(s->pc - s->cs_base));
3ca51d07 6789 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6790 }
6791 gen_eob(s);
6792 break;
6793 case 0xe8: /* call im */
6794 {
14ce26e7 6795 if (dflag)
0af10c86 6796 tval = (int32_t)insn_get(env, s, OT_LONG);
14ce26e7 6797 else
0af10c86 6798 tval = (int16_t)insn_get(env, s, OT_WORD);
2c0262af 6799 next_eip = s->pc - s->cs_base;
14ce26e7 6800 tval += next_eip;
2c0262af 6801 if (s->dflag == 0)
14ce26e7 6802 tval &= 0xffff;
99596385
AJ
6803 else if(!CODE64(s))
6804 tval &= 0xffffffff;
14ce26e7 6805 gen_movtl_T0_im(next_eip);
2c0262af 6806 gen_push_T0(s);
14ce26e7 6807 gen_jmp(s, tval);
2c0262af
FB
6808 }
6809 break;
6810 case 0x9a: /* lcall im */
6811 {
6812 unsigned int selector, offset;
3b46e624 6813
14ce26e7
FB
6814 if (CODE64(s))
6815 goto illegal_op;
2c0262af 6816 ot = dflag ? OT_LONG : OT_WORD;
0af10c86
BS
6817 offset = insn_get(env, s, ot);
6818 selector = insn_get(env, s, OT_WORD);
3b46e624 6819
2c0262af 6820 gen_op_movl_T0_im(selector);
14ce26e7 6821 gen_op_movl_T1_imu(offset);
2c0262af
FB
6822 }
6823 goto do_lcall;
ecada8a2 6824 case 0xe9: /* jmp im */
14ce26e7 6825 if (dflag)
0af10c86 6826 tval = (int32_t)insn_get(env, s, OT_LONG);
14ce26e7 6827 else
0af10c86 6828 tval = (int16_t)insn_get(env, s, OT_WORD);
14ce26e7 6829 tval += s->pc - s->cs_base;
2c0262af 6830 if (s->dflag == 0)
14ce26e7 6831 tval &= 0xffff;
32938e12
AJ
6832 else if(!CODE64(s))
6833 tval &= 0xffffffff;
14ce26e7 6834 gen_jmp(s, tval);
2c0262af
FB
6835 break;
6836 case 0xea: /* ljmp im */
6837 {
6838 unsigned int selector, offset;
6839
14ce26e7
FB
6840 if (CODE64(s))
6841 goto illegal_op;
2c0262af 6842 ot = dflag ? OT_LONG : OT_WORD;
0af10c86
BS
6843 offset = insn_get(env, s, ot);
6844 selector = insn_get(env, s, OT_WORD);
3b46e624 6845
2c0262af 6846 gen_op_movl_T0_im(selector);
14ce26e7 6847 gen_op_movl_T1_imu(offset);
2c0262af
FB
6848 }
6849 goto do_ljmp;
6850 case 0xeb: /* jmp Jb */
0af10c86 6851 tval = (int8_t)insn_get(env, s, OT_BYTE);
14ce26e7 6852 tval += s->pc - s->cs_base;
2c0262af 6853 if (s->dflag == 0)
14ce26e7
FB
6854 tval &= 0xffff;
6855 gen_jmp(s, tval);
2c0262af
FB
6856 break;
6857 case 0x70 ... 0x7f: /* jcc Jb */
0af10c86 6858 tval = (int8_t)insn_get(env, s, OT_BYTE);
2c0262af
FB
6859 goto do_jcc;
6860 case 0x180 ... 0x18f: /* jcc Jv */
6861 if (dflag) {
0af10c86 6862 tval = (int32_t)insn_get(env, s, OT_LONG);
2c0262af 6863 } else {
0af10c86 6864 tval = (int16_t)insn_get(env, s, OT_WORD);
2c0262af
FB
6865 }
6866 do_jcc:
6867 next_eip = s->pc - s->cs_base;
14ce26e7 6868 tval += next_eip;
2c0262af 6869 if (s->dflag == 0)
14ce26e7
FB
6870 tval &= 0xffff;
6871 gen_jcc(s, b, tval, next_eip);
2c0262af
FB
6872 break;
6873
6874 case 0x190 ... 0x19f: /* setcc Gv */
0af10c86 6875 modrm = cpu_ldub_code(env, s->pc++);
cc8b6f5b 6876 gen_setcc1(s, b, cpu_T[0]);
0af10c86 6877 gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1);
2c0262af
FB
6878 break;
6879 case 0x140 ... 0x14f: /* cmov Gv, Ev */
f32d3781
PB
6880 ot = dflag + OT_WORD;
6881 modrm = cpu_ldub_code(env, s->pc++);
6882 reg = ((modrm >> 3) & 7) | rex_r;
6883 gen_cmovcc1(env, s, ot, b, modrm, reg);
2c0262af 6884 break;
3b46e624 6885
2c0262af
FB
6886 /************************/
6887 /* flags */
6888 case 0x9c: /* pushf */
872929aa 6889 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
2c0262af
FB
6890 if (s->vm86 && s->iopl != 3) {
6891 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6892 } else {
773cdfcc 6893 gen_update_cc_op(s);
f0967a1a 6894 gen_helper_read_eflags(cpu_T[0], cpu_env);
2c0262af
FB
6895 gen_push_T0(s);
6896 }
6897 break;
6898 case 0x9d: /* popf */
872929aa 6899 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
2c0262af
FB
6900 if (s->vm86 && s->iopl != 3) {
6901 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6902 } else {
6903 gen_pop_T0(s);
6904 if (s->cpl == 0) {
6905 if (s->dflag) {
f0967a1a
BS
6906 gen_helper_write_eflags(cpu_env, cpu_T[0],
6907 tcg_const_i32((TF_MASK | AC_MASK |
6908 ID_MASK | NT_MASK |
6909 IF_MASK |
6910 IOPL_MASK)));
2c0262af 6911 } else {
f0967a1a
BS
6912 gen_helper_write_eflags(cpu_env, cpu_T[0],
6913 tcg_const_i32((TF_MASK | AC_MASK |
6914 ID_MASK | NT_MASK |
6915 IF_MASK | IOPL_MASK)
6916 & 0xffff));
2c0262af
FB
6917 }
6918 } else {
4136f33c
FB
6919 if (s->cpl <= s->iopl) {
6920 if (s->dflag) {
f0967a1a
BS
6921 gen_helper_write_eflags(cpu_env, cpu_T[0],
6922 tcg_const_i32((TF_MASK |
6923 AC_MASK |
6924 ID_MASK |
6925 NT_MASK |
6926 IF_MASK)));
4136f33c 6927 } else {
f0967a1a
BS
6928 gen_helper_write_eflags(cpu_env, cpu_T[0],
6929 tcg_const_i32((TF_MASK |
6930 AC_MASK |
6931 ID_MASK |
6932 NT_MASK |
6933 IF_MASK)
6934 & 0xffff));
4136f33c 6935 }
2c0262af 6936 } else {
4136f33c 6937 if (s->dflag) {
f0967a1a
BS
6938 gen_helper_write_eflags(cpu_env, cpu_T[0],
6939 tcg_const_i32((TF_MASK | AC_MASK |
6940 ID_MASK | NT_MASK)));
4136f33c 6941 } else {
f0967a1a
BS
6942 gen_helper_write_eflags(cpu_env, cpu_T[0],
6943 tcg_const_i32((TF_MASK | AC_MASK |
6944 ID_MASK | NT_MASK)
6945 & 0xffff));
4136f33c 6946 }
2c0262af
FB
6947 }
6948 }
6949 gen_pop_update(s);
3ca51d07 6950 set_cc_op(s, CC_OP_EFLAGS);
a9321a4d 6951 /* abort translation because TF/AC flag may change */
14ce26e7 6952 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6953 gen_eob(s);
6954 }
6955 break;
6956 case 0x9e: /* sahf */
12e26b75 6957 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
14ce26e7 6958 goto illegal_op;
57fec1fe 6959 gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
d229edce 6960 gen_compute_eflags(s);
bd7a7b33
FB
6961 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6962 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6963 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
2c0262af
FB
6964 break;
6965 case 0x9f: /* lahf */
12e26b75 6966 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
14ce26e7 6967 goto illegal_op;
d229edce 6968 gen_compute_eflags(s);
bd7a7b33 6969 /* Note: gen_compute_eflags() only gives the condition codes */
d229edce 6970 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
57fec1fe 6971 gen_op_mov_reg_T0(OT_BYTE, R_AH);
2c0262af
FB
6972 break;
6973 case 0xf5: /* cmc */
d229edce 6974 gen_compute_eflags(s);
bd7a7b33 6975 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
2c0262af
FB
6976 break;
6977 case 0xf8: /* clc */
d229edce 6978 gen_compute_eflags(s);
bd7a7b33 6979 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
2c0262af
FB
6980 break;
6981 case 0xf9: /* stc */
d229edce 6982 gen_compute_eflags(s);
bd7a7b33 6983 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
2c0262af
FB
6984 break;
6985 case 0xfc: /* cld */
b6abf97d 6986 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
317ac620 6987 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
2c0262af
FB
6988 break;
6989 case 0xfd: /* std */
b6abf97d 6990 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
317ac620 6991 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
2c0262af
FB
6992 break;
6993
6994 /************************/
6995 /* bit operations */
6996 case 0x1ba: /* bt/bts/btr/btc Gv, im */
14ce26e7 6997 ot = dflag + OT_WORD;
0af10c86 6998 modrm = cpu_ldub_code(env, s->pc++);
33698e5f 6999 op = (modrm >> 3) & 7;
2c0262af 7000 mod = (modrm >> 6) & 3;
14ce26e7 7001 rm = (modrm & 7) | REX_B(s);
2c0262af 7002 if (mod != 3) {
14ce26e7 7003 s->rip_offset = 1;
0af10c86 7004 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 7005 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 7006 } else {
57fec1fe 7007 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af
FB
7008 }
7009 /* load shift */
0af10c86 7010 val = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7011 gen_op_movl_T1_im(val);
7012 if (op < 4)
7013 goto illegal_op;
7014 op -= 4;
f484d386 7015 goto bt_op;
2c0262af
FB
7016 case 0x1a3: /* bt Gv, Ev */
7017 op = 0;
7018 goto do_btx;
7019 case 0x1ab: /* bts */
7020 op = 1;
7021 goto do_btx;
7022 case 0x1b3: /* btr */
7023 op = 2;
7024 goto do_btx;
7025 case 0x1bb: /* btc */
7026 op = 3;
7027 do_btx:
14ce26e7 7028 ot = dflag + OT_WORD;
0af10c86 7029 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 7030 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 7031 mod = (modrm >> 6) & 3;
14ce26e7 7032 rm = (modrm & 7) | REX_B(s);
57fec1fe 7033 gen_op_mov_TN_reg(OT_LONG, 1, reg);
2c0262af 7034 if (mod != 3) {
0af10c86 7035 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af 7036 /* specific case: we need to add a displacement */
f484d386
FB
7037 gen_exts(ot, cpu_T[1]);
7038 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
7039 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
7040 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
57fec1fe 7041 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 7042 } else {
57fec1fe 7043 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af 7044 }
f484d386
FB
7045 bt_op:
7046 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
7047 switch(op) {
7048 case 0:
7049 tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
7050 tcg_gen_movi_tl(cpu_cc_dst, 0);
7051 break;
7052 case 1:
7053 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7054 tcg_gen_movi_tl(cpu_tmp0, 1);
7055 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7056 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7057 break;
7058 case 2:
7059 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7060 tcg_gen_movi_tl(cpu_tmp0, 1);
7061 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7062 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
7063 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7064 break;
7065 default:
7066 case 3:
7067 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7068 tcg_gen_movi_tl(cpu_tmp0, 1);
7069 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7070 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7071 break;
7072 }
3ca51d07 7073 set_cc_op(s, CC_OP_SARB + ot);
2c0262af
FB
7074 if (op != 0) {
7075 if (mod != 3)
57fec1fe 7076 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 7077 else
57fec1fe 7078 gen_op_mov_reg_T0(ot, rm);
f484d386
FB
7079 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
7080 tcg_gen_movi_tl(cpu_cc_dst, 0);
2c0262af
FB
7081 }
7082 break;
321c5351
RH
7083 case 0x1bc: /* bsf / tzcnt */
7084 case 0x1bd: /* bsr / lzcnt */
7085 ot = dflag + OT_WORD;
7086 modrm = cpu_ldub_code(env, s->pc++);
7087 reg = ((modrm >> 3) & 7) | rex_r;
7088 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7089 gen_extu(ot, cpu_T[0]);
7090
7091 /* Note that lzcnt and tzcnt are in different extensions. */
7092 if ((prefixes & PREFIX_REPZ)
7093 && (b & 1
7094 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
7095 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
7096 int size = 8 << ot;
7097 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
7098 if (b & 1) {
7099 /* For lzcnt, reduce the target_ulong result by the
7100 number of zeros that we expect to find at the top. */
7101 gen_helper_clz(cpu_T[0], cpu_T[0]);
7102 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - size);
6191b059 7103 } else {
321c5351
RH
7104 /* For tzcnt, a zero input must return the operand size:
7105 force all bits outside the operand size to 1. */
7106 target_ulong mask = (target_ulong)-2 << (size - 1);
7107 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], mask);
7108 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6191b059 7109 }
321c5351
RH
7110 /* For lzcnt/tzcnt, C and Z bits are defined and are
7111 related to the result. */
7112 gen_op_update1_cc();
7113 set_cc_op(s, CC_OP_BMILGB + ot);
7114 } else {
7115 /* For bsr/bsf, only the Z bit is defined and it is related
7116 to the input and not the result. */
7117 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
7118 set_cc_op(s, CC_OP_LOGICB + ot);
7119 if (b & 1) {
7120 /* For bsr, return the bit index of the first 1 bit,
7121 not the count of leading zeros. */
7122 gen_helper_clz(cpu_T[0], cpu_T[0]);
7123 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - 1);
7124 } else {
7125 gen_helper_ctz(cpu_T[0], cpu_T[0]);
7126 }
7127 /* ??? The manual says that the output is undefined when the
7128 input is zero, but real hardware leaves it unchanged, and
7129 real programs appear to depend on that. */
7130 tcg_gen_movi_tl(cpu_tmp0, 0);
7131 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[0], cpu_cc_dst, cpu_tmp0,
7132 cpu_regs[reg], cpu_T[0]);
6191b059 7133 }
321c5351 7134 gen_op_mov_reg_T0(ot, reg);
2c0262af
FB
7135 break;
7136 /************************/
7137 /* bcd */
7138 case 0x27: /* daa */
14ce26e7
FB
7139 if (CODE64(s))
7140 goto illegal_op;
773cdfcc 7141 gen_update_cc_op(s);
7923057b 7142 gen_helper_daa(cpu_env);
3ca51d07 7143 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
7144 break;
7145 case 0x2f: /* das */
14ce26e7
FB
7146 if (CODE64(s))
7147 goto illegal_op;
773cdfcc 7148 gen_update_cc_op(s);
7923057b 7149 gen_helper_das(cpu_env);
3ca51d07 7150 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
7151 break;
7152 case 0x37: /* aaa */
14ce26e7
FB
7153 if (CODE64(s))
7154 goto illegal_op;
773cdfcc 7155 gen_update_cc_op(s);
7923057b 7156 gen_helper_aaa(cpu_env);
3ca51d07 7157 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
7158 break;
7159 case 0x3f: /* aas */
14ce26e7
FB
7160 if (CODE64(s))
7161 goto illegal_op;
773cdfcc 7162 gen_update_cc_op(s);
7923057b 7163 gen_helper_aas(cpu_env);
3ca51d07 7164 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
7165 break;
7166 case 0xd4: /* aam */
14ce26e7
FB
7167 if (CODE64(s))
7168 goto illegal_op;
0af10c86 7169 val = cpu_ldub_code(env, s->pc++);
b6d7c3db
TS
7170 if (val == 0) {
7171 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7172 } else {
7923057b 7173 gen_helper_aam(cpu_env, tcg_const_i32(val));
3ca51d07 7174 set_cc_op(s, CC_OP_LOGICB);
b6d7c3db 7175 }
2c0262af
FB
7176 break;
7177 case 0xd5: /* aad */
14ce26e7
FB
7178 if (CODE64(s))
7179 goto illegal_op;
0af10c86 7180 val = cpu_ldub_code(env, s->pc++);
7923057b 7181 gen_helper_aad(cpu_env, tcg_const_i32(val));
3ca51d07 7182 set_cc_op(s, CC_OP_LOGICB);
2c0262af
FB
7183 break;
7184 /************************/
7185 /* misc */
7186 case 0x90: /* nop */
ab1f142b 7187 /* XXX: correct lock test for all insn */
7418027e 7188 if (prefixes & PREFIX_LOCK) {
ab1f142b 7189 goto illegal_op;
7418027e
RH
7190 }
7191 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
7192 if (REX_B(s)) {
7193 goto do_xchg_reg_eax;
7194 }
0573fbfc
TS
7195 if (prefixes & PREFIX_REPZ) {
7196 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
7197 }
2c0262af
FB
7198 break;
7199 case 0x9b: /* fwait */
5fafdf24 7200 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7eee2a50
FB
7201 (HF_MP_MASK | HF_TS_MASK)) {
7202 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2ee73ac3 7203 } else {
773cdfcc 7204 gen_update_cc_op(s);
14ce26e7 7205 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 7206 gen_helper_fwait(cpu_env);
7eee2a50 7207 }
2c0262af
FB
7208 break;
7209 case 0xcc: /* int3 */
7210 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7211 break;
7212 case 0xcd: /* int N */
0af10c86 7213 val = cpu_ldub_code(env, s->pc++);
f115e911 7214 if (s->vm86 && s->iopl != 3) {
5fafdf24 7215 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
7216 } else {
7217 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7218 }
2c0262af
FB
7219 break;
7220 case 0xce: /* into */
14ce26e7
FB
7221 if (CODE64(s))
7222 goto illegal_op;
773cdfcc 7223 gen_update_cc_op(s);
a8ede8ba 7224 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7225 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
2c0262af 7226 break;
0b97134b 7227#ifdef WANT_ICEBP
2c0262af 7228 case 0xf1: /* icebp (undocumented, exits to external debugger) */
872929aa 7229 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
aba9d61e 7230#if 1
2c0262af 7231 gen_debug(s, pc_start - s->cs_base);
aba9d61e
FB
7232#else
7233 /* start debug */
0af10c86 7234 tb_flush(env);
24537a01 7235 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
aba9d61e 7236#endif
2c0262af 7237 break;
0b97134b 7238#endif
2c0262af
FB
7239 case 0xfa: /* cli */
7240 if (!s->vm86) {
7241 if (s->cpl <= s->iopl) {
f0967a1a 7242 gen_helper_cli(cpu_env);
2c0262af
FB
7243 } else {
7244 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7245 }
7246 } else {
7247 if (s->iopl == 3) {
f0967a1a 7248 gen_helper_cli(cpu_env);
2c0262af
FB
7249 } else {
7250 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7251 }
7252 }
7253 break;
7254 case 0xfb: /* sti */
7255 if (!s->vm86) {
7256 if (s->cpl <= s->iopl) {
7257 gen_sti:
f0967a1a 7258 gen_helper_sti(cpu_env);
2c0262af 7259 /* interruptions are enabled only the first insn after sti */
a2cc3b24
FB
7260 /* If several instructions disable interrupts, only the
7261 _first_ does it */
7262 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 7263 gen_helper_set_inhibit_irq(cpu_env);
2c0262af 7264 /* give a chance to handle pending irqs */
14ce26e7 7265 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7266 gen_eob(s);
7267 } else {
7268 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7269 }
7270 } else {
7271 if (s->iopl == 3) {
7272 goto gen_sti;
7273 } else {
7274 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7275 }
7276 }
7277 break;
7278 case 0x62: /* bound */
14ce26e7
FB
7279 if (CODE64(s))
7280 goto illegal_op;
2c0262af 7281 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 7282 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7283 reg = (modrm >> 3) & 7;
7284 mod = (modrm >> 6) & 3;
7285 if (mod == 3)
7286 goto illegal_op;
57fec1fe 7287 gen_op_mov_TN_reg(ot, 0, reg);
0af10c86 7288 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
14ce26e7 7289 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 7290 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
92fc4b58
BS
7291 if (ot == OT_WORD) {
7292 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
7293 } else {
7294 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
7295 }
2c0262af
FB
7296 break;
7297 case 0x1c8 ... 0x1cf: /* bswap reg */
14ce26e7
FB
7298 reg = (b & 7) | REX_B(s);
7299#ifdef TARGET_X86_64
7300 if (dflag == 2) {
57fec1fe 7301 gen_op_mov_TN_reg(OT_QUAD, 0, reg);
66896cb8 7302 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
57fec1fe 7303 gen_op_mov_reg_T0(OT_QUAD, reg);
5fafdf24 7304 } else
8777643e 7305#endif
57fec1fe
FB
7306 {
7307 gen_op_mov_TN_reg(OT_LONG, 0, reg);
8777643e
AJ
7308 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
7309 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
57fec1fe 7310 gen_op_mov_reg_T0(OT_LONG, reg);
14ce26e7 7311 }
2c0262af
FB
7312 break;
7313 case 0xd6: /* salc */
14ce26e7
FB
7314 if (CODE64(s))
7315 goto illegal_op;
cc8b6f5b 7316 gen_compute_eflags_c(s, cpu_T[0]);
bd7a7b33
FB
7317 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
7318 gen_op_mov_reg_T0(OT_BYTE, R_EAX);
2c0262af
FB
7319 break;
7320 case 0xe0: /* loopnz */
7321 case 0xe1: /* loopz */
2c0262af
FB
7322 case 0xe2: /* loop */
7323 case 0xe3: /* jecxz */
14ce26e7 7324 {
6e0d8677 7325 int l1, l2, l3;
14ce26e7 7326
0af10c86 7327 tval = (int8_t)insn_get(env, s, OT_BYTE);
14ce26e7
FB
7328 next_eip = s->pc - s->cs_base;
7329 tval += next_eip;
7330 if (s->dflag == 0)
7331 tval &= 0xffff;
3b46e624 7332
14ce26e7
FB
7333 l1 = gen_new_label();
7334 l2 = gen_new_label();
6e0d8677 7335 l3 = gen_new_label();
14ce26e7 7336 b &= 3;
6e0d8677
FB
7337 switch(b) {
7338 case 0: /* loopnz */
7339 case 1: /* loopz */
6e0d8677
FB
7340 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7341 gen_op_jz_ecx(s->aflag, l3);
5bdb91b0 7342 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
6e0d8677
FB
7343 break;
7344 case 2: /* loop */
7345 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7346 gen_op_jnz_ecx(s->aflag, l1);
7347 break;
7348 default:
7349 case 3: /* jcxz */
7350 gen_op_jz_ecx(s->aflag, l1);
7351 break;
14ce26e7
FB
7352 }
7353
6e0d8677 7354 gen_set_label(l3);
14ce26e7 7355 gen_jmp_im(next_eip);
8e1c85e3 7356 tcg_gen_br(l2);
6e0d8677 7357
14ce26e7
FB
7358 gen_set_label(l1);
7359 gen_jmp_im(tval);
7360 gen_set_label(l2);
7361 gen_eob(s);
7362 }
2c0262af
FB
7363 break;
7364 case 0x130: /* wrmsr */
7365 case 0x132: /* rdmsr */
7366 if (s->cpl != 0) {
7367 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7368 } else {
773cdfcc 7369 gen_update_cc_op(s);
872929aa 7370 gen_jmp_im(pc_start - s->cs_base);
0573fbfc 7371 if (b & 2) {
4a7443be 7372 gen_helper_rdmsr(cpu_env);
0573fbfc 7373 } else {
4a7443be 7374 gen_helper_wrmsr(cpu_env);
0573fbfc 7375 }
2c0262af
FB
7376 }
7377 break;
7378 case 0x131: /* rdtsc */
773cdfcc 7379 gen_update_cc_op(s);
ecada8a2 7380 gen_jmp_im(pc_start - s->cs_base);
efade670
PB
7381 if (use_icount)
7382 gen_io_start();
4a7443be 7383 gen_helper_rdtsc(cpu_env);
efade670
PB
7384 if (use_icount) {
7385 gen_io_end();
7386 gen_jmp(s, s->pc - s->cs_base);
7387 }
2c0262af 7388 break;
df01e0fc 7389 case 0x133: /* rdpmc */
773cdfcc 7390 gen_update_cc_op(s);
df01e0fc 7391 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7392 gen_helper_rdpmc(cpu_env);
df01e0fc 7393 break;
023fe10d 7394 case 0x134: /* sysenter */
2436b61a 7395 /* For Intel SYSENTER is valid on 64-bit */
0af10c86 7396 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
14ce26e7 7397 goto illegal_op;
023fe10d
FB
7398 if (!s->pe) {
7399 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7400 } else {
728d803b 7401 gen_update_cc_op(s);
14ce26e7 7402 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7403 gen_helper_sysenter(cpu_env);
023fe10d
FB
7404 gen_eob(s);
7405 }
7406 break;
7407 case 0x135: /* sysexit */
2436b61a 7408 /* For Intel SYSEXIT is valid on 64-bit */
0af10c86 7409 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
14ce26e7 7410 goto illegal_op;
023fe10d
FB
7411 if (!s->pe) {
7412 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7413 } else {
728d803b 7414 gen_update_cc_op(s);
14ce26e7 7415 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7416 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag));
023fe10d
FB
7417 gen_eob(s);
7418 }
7419 break;
14ce26e7
FB
7420#ifdef TARGET_X86_64
7421 case 0x105: /* syscall */
7422 /* XXX: is it usable in real mode ? */
728d803b 7423 gen_update_cc_op(s);
14ce26e7 7424 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7425 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
14ce26e7
FB
7426 gen_eob(s);
7427 break;
7428 case 0x107: /* sysret */
7429 if (!s->pe) {
7430 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7431 } else {
728d803b 7432 gen_update_cc_op(s);
14ce26e7 7433 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7434 gen_helper_sysret(cpu_env, tcg_const_i32(s->dflag));
aba9d61e 7435 /* condition codes are modified only in long mode */
3ca51d07
RH
7436 if (s->lma) {
7437 set_cc_op(s, CC_OP_EFLAGS);
7438 }
14ce26e7
FB
7439 gen_eob(s);
7440 }
7441 break;
7442#endif
2c0262af 7443 case 0x1a2: /* cpuid */
773cdfcc 7444 gen_update_cc_op(s);
9575cb94 7445 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7446 gen_helper_cpuid(cpu_env);
2c0262af
FB
7447 break;
7448 case 0xf4: /* hlt */
7449 if (s->cpl != 0) {
7450 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7451 } else {
773cdfcc 7452 gen_update_cc_op(s);
94451178 7453 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7454 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
5779406a 7455 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
7456 }
7457 break;
7458 case 0x100:
0af10c86 7459 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7460 mod = (modrm >> 6) & 3;
7461 op = (modrm >> 3) & 7;
7462 switch(op) {
7463 case 0: /* sldt */
f115e911
FB
7464 if (!s->pe || s->vm86)
7465 goto illegal_op;
872929aa 7466 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
651ba608 7467 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
2c0262af
FB
7468 ot = OT_WORD;
7469 if (mod == 3)
7470 ot += s->dflag;
0af10c86 7471 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
7472 break;
7473 case 2: /* lldt */
f115e911
FB
7474 if (!s->pe || s->vm86)
7475 goto illegal_op;
2c0262af
FB
7476 if (s->cpl != 0) {
7477 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7478 } else {
872929aa 7479 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
0af10c86 7480 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 7481 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 7482 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 7483 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
2c0262af
FB
7484 }
7485 break;
7486 case 1: /* str */
f115e911
FB
7487 if (!s->pe || s->vm86)
7488 goto illegal_op;
872929aa 7489 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
651ba608 7490 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
2c0262af
FB
7491 ot = OT_WORD;
7492 if (mod == 3)
7493 ot += s->dflag;
0af10c86 7494 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
7495 break;
7496 case 3: /* ltr */
f115e911
FB
7497 if (!s->pe || s->vm86)
7498 goto illegal_op;
2c0262af
FB
7499 if (s->cpl != 0) {
7500 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7501 } else {
872929aa 7502 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
0af10c86 7503 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 7504 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 7505 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 7506 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
2c0262af
FB
7507 }
7508 break;
7509 case 4: /* verr */
7510 case 5: /* verw */
f115e911
FB
7511 if (!s->pe || s->vm86)
7512 goto illegal_op;
0af10c86 7513 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
773cdfcc 7514 gen_update_cc_op(s);
2999a0b2
BS
7515 if (op == 4) {
7516 gen_helper_verr(cpu_env, cpu_T[0]);
7517 } else {
7518 gen_helper_verw(cpu_env, cpu_T[0]);
7519 }
3ca51d07 7520 set_cc_op(s, CC_OP_EFLAGS);
f115e911 7521 break;
2c0262af
FB
7522 default:
7523 goto illegal_op;
7524 }
7525 break;
7526 case 0x101:
0af10c86 7527 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7528 mod = (modrm >> 6) & 3;
7529 op = (modrm >> 3) & 7;
3d7374c5 7530 rm = modrm & 7;
2c0262af
FB
7531 switch(op) {
7532 case 0: /* sgdt */
2c0262af
FB
7533 if (mod == 3)
7534 goto illegal_op;
872929aa 7535 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
0af10c86 7536 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
651ba608 7537 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
57fec1fe 7538 gen_op_st_T0_A0(OT_WORD + s->mem_index);
aba9d61e 7539 gen_add_A0_im(s, 2);
651ba608 7540 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
2c0262af
FB
7541 if (!s->dflag)
7542 gen_op_andl_T0_im(0xffffff);
57fec1fe 7543 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
2c0262af 7544 break;
3d7374c5
FB
7545 case 1:
7546 if (mod == 3) {
7547 switch (rm) {
7548 case 0: /* monitor */
7549 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7550 s->cpl != 0)
7551 goto illegal_op;
773cdfcc 7552 gen_update_cc_op(s);
3d7374c5
FB
7553 gen_jmp_im(pc_start - s->cs_base);
7554#ifdef TARGET_X86_64
7555 if (s->aflag == 2) {
bbf662ee 7556 gen_op_movq_A0_reg(R_EAX);
5fafdf24 7557 } else
3d7374c5
FB
7558#endif
7559 {
bbf662ee 7560 gen_op_movl_A0_reg(R_EAX);
3d7374c5
FB
7561 if (s->aflag == 0)
7562 gen_op_andl_A0_ffff();
7563 }
7564 gen_add_A0_ds_seg(s);
4a7443be 7565 gen_helper_monitor(cpu_env, cpu_A0);
3d7374c5
FB
7566 break;
7567 case 1: /* mwait */
7568 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7569 s->cpl != 0)
7570 goto illegal_op;
728d803b 7571 gen_update_cc_op(s);
94451178 7572 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7573 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
3d7374c5
FB
7574 gen_eob(s);
7575 break;
a9321a4d
PA
7576 case 2: /* clac */
7577 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7578 s->cpl != 0) {
7579 goto illegal_op;
7580 }
7581 gen_helper_clac(cpu_env);
7582 gen_jmp_im(s->pc - s->cs_base);
7583 gen_eob(s);
7584 break;
7585 case 3: /* stac */
7586 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7587 s->cpl != 0) {
7588 goto illegal_op;
7589 }
7590 gen_helper_stac(cpu_env);
7591 gen_jmp_im(s->pc - s->cs_base);
7592 gen_eob(s);
7593 break;
3d7374c5
FB
7594 default:
7595 goto illegal_op;
7596 }
7597 } else { /* sidt */
872929aa 7598 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
0af10c86 7599 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
651ba608 7600 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
57fec1fe 7601 gen_op_st_T0_A0(OT_WORD + s->mem_index);
3d7374c5 7602 gen_add_A0_im(s, 2);
651ba608 7603 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
3d7374c5
FB
7604 if (!s->dflag)
7605 gen_op_andl_T0_im(0xffffff);
57fec1fe 7606 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
3d7374c5
FB
7607 }
7608 break;
2c0262af
FB
7609 case 2: /* lgdt */
7610 case 3: /* lidt */
0573fbfc 7611 if (mod == 3) {
773cdfcc 7612 gen_update_cc_op(s);
872929aa 7613 gen_jmp_im(pc_start - s->cs_base);
0573fbfc
TS
7614 switch(rm) {
7615 case 0: /* VMRUN */
872929aa
FB
7616 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7617 goto illegal_op;
7618 if (s->cpl != 0) {
7619 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
0573fbfc 7620 break;
872929aa 7621 } else {
052e80d5 7622 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag),
a7812ae4 7623 tcg_const_i32(s->pc - pc_start));
db620f46 7624 tcg_gen_exit_tb(0);
5779406a 7625 s->is_jmp = DISAS_TB_JUMP;
872929aa 7626 }
0573fbfc
TS
7627 break;
7628 case 1: /* VMMCALL */
872929aa
FB
7629 if (!(s->flags & HF_SVME_MASK))
7630 goto illegal_op;
052e80d5 7631 gen_helper_vmmcall(cpu_env);
0573fbfc
TS
7632 break;
7633 case 2: /* VMLOAD */
872929aa
FB
7634 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7635 goto illegal_op;
7636 if (s->cpl != 0) {
7637 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7638 break;
7639 } else {
052e80d5 7640 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag));
872929aa 7641 }
0573fbfc
TS
7642 break;
7643 case 3: /* VMSAVE */
872929aa
FB
7644 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7645 goto illegal_op;
7646 if (s->cpl != 0) {
7647 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7648 break;
7649 } else {
052e80d5 7650 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag));
872929aa 7651 }
0573fbfc
TS
7652 break;
7653 case 4: /* STGI */
872929aa
FB
7654 if ((!(s->flags & HF_SVME_MASK) &&
7655 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7656 !s->pe)
7657 goto illegal_op;
7658 if (s->cpl != 0) {
7659 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7660 break;
7661 } else {
052e80d5 7662 gen_helper_stgi(cpu_env);
872929aa 7663 }
0573fbfc
TS
7664 break;
7665 case 5: /* CLGI */
872929aa
FB
7666 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7667 goto illegal_op;
7668 if (s->cpl != 0) {
7669 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7670 break;
7671 } else {
052e80d5 7672 gen_helper_clgi(cpu_env);
872929aa 7673 }
0573fbfc
TS
7674 break;
7675 case 6: /* SKINIT */
872929aa
FB
7676 if ((!(s->flags & HF_SVME_MASK) &&
7677 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7678 !s->pe)
7679 goto illegal_op;
052e80d5 7680 gen_helper_skinit(cpu_env);
0573fbfc
TS
7681 break;
7682 case 7: /* INVLPGA */
872929aa
FB
7683 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7684 goto illegal_op;
7685 if (s->cpl != 0) {
7686 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7687 break;
7688 } else {
052e80d5 7689 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag));
872929aa 7690 }
0573fbfc
TS
7691 break;
7692 default:
7693 goto illegal_op;
7694 }
7695 } else if (s->cpl != 0) {
2c0262af
FB
7696 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7697 } else {
872929aa
FB
7698 gen_svm_check_intercept(s, pc_start,
7699 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
0af10c86 7700 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 7701 gen_op_ld_T1_A0(OT_WORD + s->mem_index);
aba9d61e 7702 gen_add_A0_im(s, 2);
57fec1fe 7703 gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
2c0262af
FB
7704 if (!s->dflag)
7705 gen_op_andl_T0_im(0xffffff);
7706 if (op == 2) {
651ba608
FB
7707 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7708 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
2c0262af 7709 } else {
651ba608
FB
7710 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7711 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
2c0262af
FB
7712 }
7713 }
7714 break;
7715 case 4: /* smsw */
872929aa 7716 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
e2542fe2 7717#if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
f60d2728 7718 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7719#else
651ba608 7720 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
f60d2728 7721#endif
0af10c86 7722 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 1);
2c0262af
FB
7723 break;
7724 case 6: /* lmsw */
7725 if (s->cpl != 0) {
7726 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7727 } else {
872929aa 7728 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
0af10c86 7729 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
4a7443be 7730 gen_helper_lmsw(cpu_env, cpu_T[0]);
14ce26e7 7731 gen_jmp_im(s->pc - s->cs_base);
d71b9a8b 7732 gen_eob(s);
2c0262af
FB
7733 }
7734 break;
1b050077
AP
7735 case 7:
7736 if (mod != 3) { /* invlpg */
7737 if (s->cpl != 0) {
7738 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7739 } else {
773cdfcc 7740 gen_update_cc_op(s);
1b050077 7741 gen_jmp_im(pc_start - s->cs_base);
0af10c86 7742 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4a7443be 7743 gen_helper_invlpg(cpu_env, cpu_A0);
1b050077
AP
7744 gen_jmp_im(s->pc - s->cs_base);
7745 gen_eob(s);
7746 }
2c0262af 7747 } else {
1b050077
AP
7748 switch (rm) {
7749 case 0: /* swapgs */
14ce26e7 7750#ifdef TARGET_X86_64
1b050077
AP
7751 if (CODE64(s)) {
7752 if (s->cpl != 0) {
7753 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7754 } else {
7755 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7756 offsetof(CPUX86State,segs[R_GS].base));
7757 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7758 offsetof(CPUX86State,kernelgsbase));
7759 tcg_gen_st_tl(cpu_T[1], cpu_env,
7760 offsetof(CPUX86State,segs[R_GS].base));
7761 tcg_gen_st_tl(cpu_T[0], cpu_env,
7762 offsetof(CPUX86State,kernelgsbase));
7763 }
5fafdf24 7764 } else
14ce26e7
FB
7765#endif
7766 {
7767 goto illegal_op;
7768 }
1b050077
AP
7769 break;
7770 case 1: /* rdtscp */
7771 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7772 goto illegal_op;
773cdfcc 7773 gen_update_cc_op(s);
9575cb94 7774 gen_jmp_im(pc_start - s->cs_base);
1b050077
AP
7775 if (use_icount)
7776 gen_io_start();
4a7443be 7777 gen_helper_rdtscp(cpu_env);
1b050077
AP
7778 if (use_icount) {
7779 gen_io_end();
7780 gen_jmp(s, s->pc - s->cs_base);
7781 }
7782 break;
7783 default:
7784 goto illegal_op;
14ce26e7 7785 }
2c0262af
FB
7786 }
7787 break;
7788 default:
7789 goto illegal_op;
7790 }
7791 break;
3415a4dd
FB
7792 case 0x108: /* invd */
7793 case 0x109: /* wbinvd */
7794 if (s->cpl != 0) {
7795 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7796 } else {
872929aa 7797 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
3415a4dd
FB
7798 /* nothing to do */
7799 }
7800 break;
14ce26e7
FB
7801 case 0x63: /* arpl or movslS (x86_64) */
7802#ifdef TARGET_X86_64
7803 if (CODE64(s)) {
7804 int d_ot;
7805 /* d_ot is the size of destination */
7806 d_ot = dflag + OT_WORD;
7807
0af10c86 7808 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
7809 reg = ((modrm >> 3) & 7) | rex_r;
7810 mod = (modrm >> 6) & 3;
7811 rm = (modrm & 7) | REX_B(s);
3b46e624 7812
14ce26e7 7813 if (mod == 3) {
57fec1fe 7814 gen_op_mov_TN_reg(OT_LONG, 0, rm);
14ce26e7
FB
7815 /* sign extend */
7816 if (d_ot == OT_QUAD)
e108dd01 7817 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
57fec1fe 7818 gen_op_mov_reg_T0(d_ot, reg);
14ce26e7 7819 } else {
0af10c86 7820 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
14ce26e7 7821 if (d_ot == OT_QUAD) {
57fec1fe 7822 gen_op_lds_T0_A0(OT_LONG + s->mem_index);
14ce26e7 7823 } else {
57fec1fe 7824 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
14ce26e7 7825 }
57fec1fe 7826 gen_op_mov_reg_T0(d_ot, reg);
14ce26e7 7827 }
5fafdf24 7828 } else
14ce26e7
FB
7829#endif
7830 {
3bd7da9e 7831 int label1;
49d9fdcc 7832 TCGv t0, t1, t2, a0;
1e4840bf 7833
14ce26e7
FB
7834 if (!s->pe || s->vm86)
7835 goto illegal_op;
a7812ae4
PB
7836 t0 = tcg_temp_local_new();
7837 t1 = tcg_temp_local_new();
7838 t2 = tcg_temp_local_new();
3bd7da9e 7839 ot = OT_WORD;
0af10c86 7840 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
7841 reg = (modrm >> 3) & 7;
7842 mod = (modrm >> 6) & 3;
7843 rm = modrm & 7;
7844 if (mod != 3) {
0af10c86 7845 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
1e4840bf 7846 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
49d9fdcc
LD
7847 a0 = tcg_temp_local_new();
7848 tcg_gen_mov_tl(a0, cpu_A0);
14ce26e7 7849 } else {
1e4840bf 7850 gen_op_mov_v_reg(ot, t0, rm);
49d9fdcc 7851 TCGV_UNUSED(a0);
14ce26e7 7852 }
1e4840bf
FB
7853 gen_op_mov_v_reg(ot, t1, reg);
7854 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7855 tcg_gen_andi_tl(t1, t1, 3);
7856 tcg_gen_movi_tl(t2, 0);
3bd7da9e 7857 label1 = gen_new_label();
1e4840bf
FB
7858 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7859 tcg_gen_andi_tl(t0, t0, ~3);
7860 tcg_gen_or_tl(t0, t0, t1);
7861 tcg_gen_movi_tl(t2, CC_Z);
3bd7da9e 7862 gen_set_label(label1);
14ce26e7 7863 if (mod != 3) {
49d9fdcc
LD
7864 gen_op_st_v(ot + s->mem_index, t0, a0);
7865 tcg_temp_free(a0);
7866 } else {
1e4840bf 7867 gen_op_mov_reg_v(ot, rm, t0);
14ce26e7 7868 }
d229edce 7869 gen_compute_eflags(s);
3bd7da9e 7870 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
1e4840bf 7871 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
1e4840bf
FB
7872 tcg_temp_free(t0);
7873 tcg_temp_free(t1);
7874 tcg_temp_free(t2);
f115e911 7875 }
f115e911 7876 break;
2c0262af
FB
7877 case 0x102: /* lar */
7878 case 0x103: /* lsl */
cec6843e
FB
7879 {
7880 int label1;
1e4840bf 7881 TCGv t0;
cec6843e
FB
7882 if (!s->pe || s->vm86)
7883 goto illegal_op;
7884 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 7885 modrm = cpu_ldub_code(env, s->pc++);
cec6843e 7886 reg = ((modrm >> 3) & 7) | rex_r;
0af10c86 7887 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
a7812ae4 7888 t0 = tcg_temp_local_new();
773cdfcc 7889 gen_update_cc_op(s);
2999a0b2
BS
7890 if (b == 0x102) {
7891 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7892 } else {
7893 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7894 }
cec6843e
FB
7895 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7896 label1 = gen_new_label();
cb63669a 7897 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
1e4840bf 7898 gen_op_mov_reg_v(ot, reg, t0);
cec6843e 7899 gen_set_label(label1);
3ca51d07 7900 set_cc_op(s, CC_OP_EFLAGS);
1e4840bf 7901 tcg_temp_free(t0);
cec6843e 7902 }
2c0262af
FB
7903 break;
7904 case 0x118:
0af10c86 7905 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7906 mod = (modrm >> 6) & 3;
7907 op = (modrm >> 3) & 7;
7908 switch(op) {
7909 case 0: /* prefetchnta */
7910 case 1: /* prefetchnt0 */
7911 case 2: /* prefetchnt0 */
7912 case 3: /* prefetchnt0 */
7913 if (mod == 3)
7914 goto illegal_op;
0af10c86 7915 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
7916 /* nothing more to do */
7917 break;
e17a36ce 7918 default: /* nop (multi byte) */
0af10c86 7919 gen_nop_modrm(env, s, modrm);
e17a36ce 7920 break;
2c0262af
FB
7921 }
7922 break;
e17a36ce 7923 case 0x119 ... 0x11f: /* nop (multi byte) */
0af10c86
BS
7924 modrm = cpu_ldub_code(env, s->pc++);
7925 gen_nop_modrm(env, s, modrm);
e17a36ce 7926 break;
2c0262af
FB
7927 case 0x120: /* mov reg, crN */
7928 case 0x122: /* mov crN, reg */
7929 if (s->cpl != 0) {
7930 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7931 } else {
0af10c86 7932 modrm = cpu_ldub_code(env, s->pc++);
5c73b757
MO
7933 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7934 * AMD documentation (24594.pdf) and testing of
7935 * intel 386 and 486 processors all show that the mod bits
7936 * are assumed to be 1's, regardless of actual values.
7937 */
14ce26e7
FB
7938 rm = (modrm & 7) | REX_B(s);
7939 reg = ((modrm >> 3) & 7) | rex_r;
7940 if (CODE64(s))
7941 ot = OT_QUAD;
7942 else
7943 ot = OT_LONG;
ccd59d09
AP
7944 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7945 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7946 reg = 8;
7947 }
2c0262af
FB
7948 switch(reg) {
7949 case 0:
7950 case 2:
7951 case 3:
7952 case 4:
9230e66e 7953 case 8:
773cdfcc 7954 gen_update_cc_op(s);
872929aa 7955 gen_jmp_im(pc_start - s->cs_base);
2c0262af 7956 if (b & 2) {
57fec1fe 7957 gen_op_mov_TN_reg(ot, 0, rm);
4a7443be
BS
7958 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7959 cpu_T[0]);
14ce26e7 7960 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7961 gen_eob(s);
7962 } else {
4a7443be 7963 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
57fec1fe 7964 gen_op_mov_reg_T0(ot, rm);
2c0262af
FB
7965 }
7966 break;
7967 default:
7968 goto illegal_op;
7969 }
7970 }
7971 break;
7972 case 0x121: /* mov reg, drN */
7973 case 0x123: /* mov drN, reg */
7974 if (s->cpl != 0) {
7975 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7976 } else {
0af10c86 7977 modrm = cpu_ldub_code(env, s->pc++);
5c73b757
MO
7978 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7979 * AMD documentation (24594.pdf) and testing of
7980 * intel 386 and 486 processors all show that the mod bits
7981 * are assumed to be 1's, regardless of actual values.
7982 */
14ce26e7
FB
7983 rm = (modrm & 7) | REX_B(s);
7984 reg = ((modrm >> 3) & 7) | rex_r;
7985 if (CODE64(s))
7986 ot = OT_QUAD;
7987 else
7988 ot = OT_LONG;
2c0262af 7989 /* XXX: do it dynamically with CR4.DE bit */
14ce26e7 7990 if (reg == 4 || reg == 5 || reg >= 8)
2c0262af
FB
7991 goto illegal_op;
7992 if (b & 2) {
0573fbfc 7993 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
57fec1fe 7994 gen_op_mov_TN_reg(ot, 0, rm);
4a7443be 7995 gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]);
14ce26e7 7996 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7997 gen_eob(s);
7998 } else {
0573fbfc 7999 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
651ba608 8000 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
57fec1fe 8001 gen_op_mov_reg_T0(ot, rm);
2c0262af
FB
8002 }
8003 }
8004 break;
8005 case 0x106: /* clts */
8006 if (s->cpl != 0) {
8007 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8008 } else {
0573fbfc 8009 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
f0967a1a 8010 gen_helper_clts(cpu_env);
7eee2a50 8011 /* abort block because static cpu state changed */
14ce26e7 8012 gen_jmp_im(s->pc - s->cs_base);
7eee2a50 8013 gen_eob(s);
2c0262af
FB
8014 }
8015 break;
222a3336 8016 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
664e0f19
FB
8017 case 0x1c3: /* MOVNTI reg, mem */
8018 if (!(s->cpuid_features & CPUID_SSE2))
14ce26e7 8019 goto illegal_op;
664e0f19 8020 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
0af10c86 8021 modrm = cpu_ldub_code(env, s->pc++);
664e0f19
FB
8022 mod = (modrm >> 6) & 3;
8023 if (mod == 3)
8024 goto illegal_op;
8025 reg = ((modrm >> 3) & 7) | rex_r;
8026 /* generate a generic store */
0af10c86 8027 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
14ce26e7 8028 break;
664e0f19 8029 case 0x1ae:
0af10c86 8030 modrm = cpu_ldub_code(env, s->pc++);
664e0f19
FB
8031 mod = (modrm >> 6) & 3;
8032 op = (modrm >> 3) & 7;
8033 switch(op) {
8034 case 0: /* fxsave */
5fafdf24 8035 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
09d85fb8 8036 (s->prefix & PREFIX_LOCK))
14ce26e7 8037 goto illegal_op;
09d85fb8 8038 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
0fd14b72
FB
8039 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8040 break;
8041 }
0af10c86 8042 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
773cdfcc 8043 gen_update_cc_op(s);
19e6c4b8 8044 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 8045 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32((s->dflag == 2)));
664e0f19
FB
8046 break;
8047 case 1: /* fxrstor */
5fafdf24 8048 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
09d85fb8 8049 (s->prefix & PREFIX_LOCK))
14ce26e7 8050 goto illegal_op;
09d85fb8 8051 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
0fd14b72
FB
8052 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8053 break;
8054 }
0af10c86 8055 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
773cdfcc 8056 gen_update_cc_op(s);
19e6c4b8 8057 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
8058 gen_helper_fxrstor(cpu_env, cpu_A0,
8059 tcg_const_i32((s->dflag == 2)));
664e0f19
FB
8060 break;
8061 case 2: /* ldmxcsr */
8062 case 3: /* stmxcsr */
8063 if (s->flags & HF_TS_MASK) {
8064 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8065 break;
14ce26e7 8066 }
664e0f19
FB
8067 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
8068 mod == 3)
14ce26e7 8069 goto illegal_op;
0af10c86 8070 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
664e0f19 8071 if (op == 2) {
57fec1fe 8072 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
20f8bd48 8073 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 8074 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
14ce26e7 8075 } else {
651ba608 8076 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
57fec1fe 8077 gen_op_st_T0_A0(OT_LONG + s->mem_index);
14ce26e7 8078 }
664e0f19
FB
8079 break;
8080 case 5: /* lfence */
8081 case 6: /* mfence */
8001c294 8082 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
664e0f19
FB
8083 goto illegal_op;
8084 break;
8f091a59
FB
8085 case 7: /* sfence / clflush */
8086 if ((modrm & 0xc7) == 0xc0) {
8087 /* sfence */
a35f3ec7 8088 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
8f091a59
FB
8089 if (!(s->cpuid_features & CPUID_SSE))
8090 goto illegal_op;
8091 } else {
8092 /* clflush */
8093 if (!(s->cpuid_features & CPUID_CLFLUSH))
8094 goto illegal_op;
0af10c86 8095 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8f091a59
FB
8096 }
8097 break;
664e0f19 8098 default:
14ce26e7
FB
8099 goto illegal_op;
8100 }
8101 break;
a35f3ec7 8102 case 0x10d: /* 3DNow! prefetch(w) */
0af10c86 8103 modrm = cpu_ldub_code(env, s->pc++);
a35f3ec7
AJ
8104 mod = (modrm >> 6) & 3;
8105 if (mod == 3)
8106 goto illegal_op;
0af10c86 8107 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8f091a59
FB
8108 /* ignore for now */
8109 break;
3b21e03e 8110 case 0x1aa: /* rsm */
872929aa 8111 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
3b21e03e
FB
8112 if (!(s->flags & HF_SMM_MASK))
8113 goto illegal_op;
728d803b 8114 gen_update_cc_op(s);
3b21e03e 8115 gen_jmp_im(s->pc - s->cs_base);
608badfc 8116 gen_helper_rsm(cpu_env);
3b21e03e
FB
8117 gen_eob(s);
8118 break;
222a3336
AZ
8119 case 0x1b8: /* SSE4.2 popcnt */
8120 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8121 PREFIX_REPZ)
8122 goto illegal_op;
8123 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8124 goto illegal_op;
8125
0af10c86 8126 modrm = cpu_ldub_code(env, s->pc++);
8b4a3df8 8127 reg = ((modrm >> 3) & 7) | rex_r;
222a3336
AZ
8128
8129 if (s->prefix & PREFIX_DATA)
8130 ot = OT_WORD;
8131 else if (s->dflag != 2)
8132 ot = OT_LONG;
8133 else
8134 ot = OT_QUAD;
8135
0af10c86 8136 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
d3eb5eae 8137 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
222a3336 8138 gen_op_mov_reg_T0(ot, reg);
fdb0d09d 8139
3ca51d07 8140 set_cc_op(s, CC_OP_EFLAGS);
222a3336 8141 break;
a35f3ec7
AJ
8142 case 0x10e ... 0x10f:
8143 /* 3DNow! instructions, ignore prefixes */
8144 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
664e0f19
FB
8145 case 0x110 ... 0x117:
8146 case 0x128 ... 0x12f:
4242b1bd 8147 case 0x138 ... 0x13a:
d9f4bb27 8148 case 0x150 ... 0x179:
664e0f19
FB
8149 case 0x17c ... 0x17f:
8150 case 0x1c2:
8151 case 0x1c4 ... 0x1c6:
8152 case 0x1d0 ... 0x1fe:
0af10c86 8153 gen_sse(env, s, b, pc_start, rex_r);
664e0f19 8154 break;
2c0262af
FB
8155 default:
8156 goto illegal_op;
8157 }
8158 /* lock generation */
8159 if (s->prefix & PREFIX_LOCK)
a7812ae4 8160 gen_helper_unlock();
2c0262af
FB
8161 return s->pc;
8162 illegal_op:
ab1f142b 8163 if (s->prefix & PREFIX_LOCK)
a7812ae4 8164 gen_helper_unlock();
2c0262af
FB
8165 /* XXX: ensure that no lock was generated */
8166 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
8167 return s->pc;
8168}
8169
2c0262af
FB
8170void optimize_flags_init(void)
8171{
a7812ae4
PB
8172 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8173 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8174 offsetof(CPUX86State, cc_op), "cc_op");
317ac620 8175 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
a7812ae4 8176 "cc_dst");
a3251186
RH
8177 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
8178 "cc_src");
988c3eb0
RH
8179 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
8180 "cc_src2");
437a88a5 8181
cc739bb0
LD
8182#ifdef TARGET_X86_64
8183 cpu_regs[R_EAX] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8184 offsetof(CPUX86State, regs[R_EAX]), "rax");
cc739bb0 8185 cpu_regs[R_ECX] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8186 offsetof(CPUX86State, regs[R_ECX]), "rcx");
cc739bb0 8187 cpu_regs[R_EDX] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8188 offsetof(CPUX86State, regs[R_EDX]), "rdx");
cc739bb0 8189 cpu_regs[R_EBX] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8190 offsetof(CPUX86State, regs[R_EBX]), "rbx");
cc739bb0 8191 cpu_regs[R_ESP] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8192 offsetof(CPUX86State, regs[R_ESP]), "rsp");
cc739bb0 8193 cpu_regs[R_EBP] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8194 offsetof(CPUX86State, regs[R_EBP]), "rbp");
cc739bb0 8195 cpu_regs[R_ESI] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8196 offsetof(CPUX86State, regs[R_ESI]), "rsi");
cc739bb0 8197 cpu_regs[R_EDI] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8198 offsetof(CPUX86State, regs[R_EDI]), "rdi");
cc739bb0 8199 cpu_regs[8] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8200 offsetof(CPUX86State, regs[8]), "r8");
cc739bb0 8201 cpu_regs[9] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8202 offsetof(CPUX86State, regs[9]), "r9");
cc739bb0 8203 cpu_regs[10] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8204 offsetof(CPUX86State, regs[10]), "r10");
cc739bb0 8205 cpu_regs[11] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8206 offsetof(CPUX86State, regs[11]), "r11");
cc739bb0 8207 cpu_regs[12] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8208 offsetof(CPUX86State, regs[12]), "r12");
cc739bb0 8209 cpu_regs[13] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8210 offsetof(CPUX86State, regs[13]), "r13");
cc739bb0 8211 cpu_regs[14] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8212 offsetof(CPUX86State, regs[14]), "r14");
cc739bb0 8213 cpu_regs[15] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 8214 offsetof(CPUX86State, regs[15]), "r15");
cc739bb0
LD
8215#else
8216 cpu_regs[R_EAX] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8217 offsetof(CPUX86State, regs[R_EAX]), "eax");
cc739bb0 8218 cpu_regs[R_ECX] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8219 offsetof(CPUX86State, regs[R_ECX]), "ecx");
cc739bb0 8220 cpu_regs[R_EDX] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8221 offsetof(CPUX86State, regs[R_EDX]), "edx");
cc739bb0 8222 cpu_regs[R_EBX] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8223 offsetof(CPUX86State, regs[R_EBX]), "ebx");
cc739bb0 8224 cpu_regs[R_ESP] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8225 offsetof(CPUX86State, regs[R_ESP]), "esp");
cc739bb0 8226 cpu_regs[R_EBP] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8227 offsetof(CPUX86State, regs[R_EBP]), "ebp");
cc739bb0 8228 cpu_regs[R_ESI] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8229 offsetof(CPUX86State, regs[R_ESI]), "esi");
cc739bb0 8230 cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 8231 offsetof(CPUX86State, regs[R_EDI]), "edi");
cc739bb0
LD
8232#endif
8233
437a88a5 8234 /* register helpers */
a7812ae4 8235#define GEN_HELPER 2
437a88a5 8236#include "helper.h"
2c0262af
FB
8237}
8238
8239/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8240 basic block 'tb'. If search_pc is TRUE, also generate PC
8241 information for each intermediate instruction. */
317ac620 8242static inline void gen_intermediate_code_internal(CPUX86State *env,
2cfc5f17
TS
8243 TranslationBlock *tb,
8244 int search_pc)
2c0262af
FB
8245{
8246 DisasContext dc1, *dc = &dc1;
14ce26e7 8247 target_ulong pc_ptr;
2c0262af 8248 uint16_t *gen_opc_end;
a1d1bb31 8249 CPUBreakpoint *bp;
7f5b7d3e 8250 int j, lj;
c068688b 8251 uint64_t flags;
14ce26e7
FB
8252 target_ulong pc_start;
8253 target_ulong cs_base;
2e70f6ef
PB
8254 int num_insns;
8255 int max_insns;
3b46e624 8256
2c0262af 8257 /* generate intermediate code */
14ce26e7
FB
8258 pc_start = tb->pc;
8259 cs_base = tb->cs_base;
2c0262af 8260 flags = tb->flags;
3a1d9b8b 8261
4f31916f 8262 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
8263 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8264 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8265 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8266 dc->f_st = 0;
8267 dc->vm86 = (flags >> VM_SHIFT) & 1;
8268 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8269 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8270 dc->tf = (flags >> TF_SHIFT) & 1;
34865134 8271 dc->singlestep_enabled = env->singlestep_enabled;
2c0262af 8272 dc->cc_op = CC_OP_DYNAMIC;
e207582f 8273 dc->cc_op_dirty = false;
2c0262af
FB
8274 dc->cs_base = cs_base;
8275 dc->tb = tb;
8276 dc->popl_esp_hack = 0;
8277 /* select memory access functions */
8278 dc->mem_index = 0;
8279 if (flags & HF_SOFTMMU_MASK) {
a9321a4d 8280 dc->mem_index = (cpu_mmu_index(env) + 1) << 2;
2c0262af 8281 }
14ce26e7 8282 dc->cpuid_features = env->cpuid_features;
3d7374c5 8283 dc->cpuid_ext_features = env->cpuid_ext_features;
e771edab 8284 dc->cpuid_ext2_features = env->cpuid_ext2_features;
12e26b75 8285 dc->cpuid_ext3_features = env->cpuid_ext3_features;
a9321a4d 8286 dc->cpuid_7_0_ebx_features = env->cpuid_7_0_ebx_features;
14ce26e7
FB
8287#ifdef TARGET_X86_64
8288 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8289 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8290#endif
7eee2a50 8291 dc->flags = flags;
a2cc3b24
FB
8292 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
8293 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 8294#ifndef CONFIG_SOFTMMU
2c0262af
FB
8295 || (flags & HF_SOFTMMU_MASK)
8296#endif
8297 );
4f31916f
FB
8298#if 0
8299 /* check addseg logic */
dc196a57 8300 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
8301 printf("ERROR addseg\n");
8302#endif
8303
a7812ae4
PB
8304 cpu_T[0] = tcg_temp_new();
8305 cpu_T[1] = tcg_temp_new();
8306 cpu_A0 = tcg_temp_new();
a7812ae4
PB
8307
8308 cpu_tmp0 = tcg_temp_new();
8309 cpu_tmp1_i64 = tcg_temp_new_i64();
8310 cpu_tmp2_i32 = tcg_temp_new_i32();
8311 cpu_tmp3_i32 = tcg_temp_new_i32();
8312 cpu_tmp4 = tcg_temp_new();
a7812ae4
PB
8313 cpu_ptr0 = tcg_temp_new_ptr();
8314 cpu_ptr1 = tcg_temp_new_ptr();
a3251186 8315 cpu_cc_srcT = tcg_temp_local_new();
57fec1fe 8316
92414b31 8317 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
2c0262af
FB
8318
8319 dc->is_jmp = DISAS_NEXT;
8320 pc_ptr = pc_start;
8321 lj = -1;
2e70f6ef
PB
8322 num_insns = 0;
8323 max_insns = tb->cflags & CF_COUNT_MASK;
8324 if (max_insns == 0)
8325 max_insns = CF_COUNT_MASK;
2c0262af 8326
806f352d 8327 gen_tb_start();
2c0262af 8328 for(;;) {
72cf2d4f
BS
8329 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8330 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a2397807
JK
8331 if (bp->pc == pc_ptr &&
8332 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
2c0262af
FB
8333 gen_debug(dc, pc_ptr - dc->cs_base);
8334 break;
8335 }
8336 }
8337 }
8338 if (search_pc) {
92414b31 8339 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2c0262af
FB
8340 if (lj < j) {
8341 lj++;
8342 while (lj < j)
ab1103de 8343 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2c0262af 8344 }
25983cad 8345 tcg_ctx.gen_opc_pc[lj] = pc_ptr;
2c0262af 8346 gen_opc_cc_op[lj] = dc->cc_op;
ab1103de 8347 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 8348 tcg_ctx.gen_opc_icount[lj] = num_insns;
2c0262af 8349 }
2e70f6ef
PB
8350 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8351 gen_io_start();
8352
0af10c86 8353 pc_ptr = disas_insn(env, dc, pc_ptr);
2e70f6ef 8354 num_insns++;
2c0262af
FB
8355 /* stop translation if indicated */
8356 if (dc->is_jmp)
8357 break;
8358 /* if single step mode, we generate only one instruction and
8359 generate an exception */
a2cc3b24
FB
8360 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8361 the flag and abort the translation to give the irqs a
8362 change to be happen */
5fafdf24 8363 if (dc->tf || dc->singlestep_enabled ||
2e70f6ef 8364 (flags & HF_INHIBIT_IRQ_MASK)) {
14ce26e7 8365 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
8366 gen_eob(dc);
8367 break;
8368 }
8369 /* if too long translation, stop generation too */
efd7f486 8370 if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
2e70f6ef
PB
8371 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8372 num_insns >= max_insns) {
14ce26e7 8373 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
8374 gen_eob(dc);
8375 break;
8376 }
1b530a6d
AJ
8377 if (singlestep) {
8378 gen_jmp_im(pc_ptr - dc->cs_base);
8379 gen_eob(dc);
8380 break;
8381 }
2c0262af 8382 }
2e70f6ef
PB
8383 if (tb->cflags & CF_LAST_IO)
8384 gen_io_end();
806f352d 8385 gen_tb_end(tb, num_insns);
efd7f486 8386 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
2c0262af
FB
8387 /* we don't forget to fill the last values */
8388 if (search_pc) {
92414b31 8389 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2c0262af
FB
8390 lj++;
8391 while (lj <= j)
ab1103de 8392 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2c0262af 8393 }
3b46e624 8394
2c0262af 8395#ifdef DEBUG_DISAS
8fec2b8c 8396 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
14ce26e7 8397 int disas_flags;
93fcfe39
AL
8398 qemu_log("----------------\n");
8399 qemu_log("IN: %s\n", lookup_symbol(pc_start));
14ce26e7
FB
8400#ifdef TARGET_X86_64
8401 if (dc->code64)
8402 disas_flags = 2;
8403 else
8404#endif
8405 disas_flags = !dc->code32;
f4359b9f 8406 log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags);
93fcfe39 8407 qemu_log("\n");
2c0262af
FB
8408 }
8409#endif
8410
2e70f6ef 8411 if (!search_pc) {
2c0262af 8412 tb->size = pc_ptr - pc_start;
2e70f6ef
PB
8413 tb->icount = num_insns;
8414 }
2c0262af
FB
8415}
8416
317ac620 8417void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
2c0262af 8418{
2cfc5f17 8419 gen_intermediate_code_internal(env, tb, 0);
2c0262af
FB
8420}
8421
317ac620 8422void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
2c0262af 8423{
2cfc5f17 8424 gen_intermediate_code_internal(env, tb, 1);
2c0262af
FB
8425}
8426
317ac620 8427void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
d2856f1a
AJ
8428{
8429 int cc_op;
8430#ifdef DEBUG_DISAS
8fec2b8c 8431 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
d2856f1a 8432 int i;
93fcfe39 8433 qemu_log("RESTORE:\n");
d2856f1a 8434 for(i = 0;i <= pc_pos; i++) {
ab1103de 8435 if (tcg_ctx.gen_opc_instr_start[i]) {
25983cad
EV
8436 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
8437 tcg_ctx.gen_opc_pc[i]);
d2856f1a
AJ
8438 }
8439 }
e87b7cb0 8440 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
25983cad 8441 pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
d2856f1a
AJ
8442 (uint32_t)tb->cs_base);
8443 }
8444#endif
25983cad 8445 env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
d2856f1a
AJ
8446 cc_op = gen_opc_cc_op[pc_pos];
8447 if (cc_op != CC_OP_DYNAMIC)
8448 env->cc_op = cc_op;
8449}