ipxe: update binaries
[qemu/ar7.git] / target / i386 / translate.c
blobcaea6f5fb11fdd54e9e6164907283a092300b228
1 /*
2 * i386 translation
4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include "qemu/host-utils.h"
22 #include "cpu.h"
23 #include "disas/disas.h"
24 #include "exec/exec-all.h"
25 #include "tcg/tcg-op.h"
26 #include "exec/cpu_ldst.h"
27 #include "exec/translator.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
32 #include "trace-tcg.h"
33 #include "exec/log.h"
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
40 #define PREFIX_VEX 0x20
42 #ifdef TARGET_X86_64
43 #define CODE64(s) ((s)->code64)
44 #define REX_X(s) ((s)->rex_x)
45 #define REX_B(s) ((s)->rex_b)
46 #else
47 #define CODE64(s) 0
48 #define REX_X(s) 0
49 #define REX_B(s) 0
50 #endif
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
60 /* For a switch indexed by MODRM, match all memory operands for a given OP. */
61 #define CASE_MODRM_MEM_OP(OP) \
62 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
63 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
64 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
66 #define CASE_MODRM_OP(OP) \
67 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
68 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
69 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
70 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
72 //#define MACRO_TEST 1
74 /* global register indexes */
75 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
76 static TCGv_i32 cpu_cc_op;
77 static TCGv cpu_regs[CPU_NB_REGS];
78 static TCGv cpu_seg_base[6];
79 static TCGv_i64 cpu_bndl[4];
80 static TCGv_i64 cpu_bndu[4];
82 #include "exec/gen-icount.h"
84 typedef struct DisasContext {
85 DisasContextBase base;
87 /* current insn context */
88 int override; /* -1 if no override */
89 int prefix;
90 MemOp aflag;
91 MemOp dflag;
92 target_ulong pc_start;
93 target_ulong pc; /* pc = eip + cs_base */
94 /* current block context */
95 target_ulong cs_base; /* base of CS segment */
96 int pe; /* protected mode */
97 int code32; /* 32 bit code segment */
98 #ifdef TARGET_X86_64
99 int lma; /* long mode active */
100 int code64; /* 64 bit code segment */
101 int rex_x, rex_b;
102 #endif
103 int vex_l; /* vex vector length */
104 int vex_v; /* vex vvvv register, without 1's complement. */
105 int ss32; /* 32 bit stack segment */
106 CCOp cc_op; /* current CC operation */
107 bool cc_op_dirty;
108 #ifdef TARGET_X86_64
109 bool x86_64_hregs;
110 #endif
111 int addseg; /* non zero if either DS/ES/SS have a non zero base */
112 int f_st; /* currently unused */
113 int vm86; /* vm86 mode */
114 int cpl;
115 int iopl;
116 int tf; /* TF cpu flag */
117 int jmp_opt; /* use direct block chaining for direct jumps */
118 int repz_opt; /* optimize jumps within repz instructions */
119 int mem_index; /* select memory access functions */
120 uint64_t flags; /* all execution flags */
121 int popl_esp_hack; /* for correct popl with esp base handling */
122 int rip_offset; /* only used in x86_64, but left for simplicity */
123 int cpuid_features;
124 int cpuid_ext_features;
125 int cpuid_ext2_features;
126 int cpuid_ext3_features;
127 int cpuid_7_0_ebx_features;
128 int cpuid_xsave_features;
130 /* TCG local temps */
131 TCGv cc_srcT;
132 TCGv A0;
133 TCGv T0;
134 TCGv T1;
136 /* TCG local register indexes (only used inside old micro ops) */
137 TCGv tmp0;
138 TCGv tmp4;
139 TCGv_ptr ptr0;
140 TCGv_ptr ptr1;
141 TCGv_i32 tmp2_i32;
142 TCGv_i32 tmp3_i32;
143 TCGv_i64 tmp1_i64;
145 sigjmp_buf jmpbuf;
146 } DisasContext;
148 static void gen_eob(DisasContext *s);
149 static void gen_jr(DisasContext *s, TCGv dest);
150 static void gen_jmp(DisasContext *s, target_ulong eip);
151 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
152 static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
154 /* i386 arith/logic operations */
155 enum {
156 OP_ADDL,
157 OP_ORL,
158 OP_ADCL,
159 OP_SBBL,
160 OP_ANDL,
161 OP_SUBL,
162 OP_XORL,
163 OP_CMPL,
166 /* i386 shift ops */
167 enum {
168 OP_ROL,
169 OP_ROR,
170 OP_RCL,
171 OP_RCR,
172 OP_SHL,
173 OP_SHR,
174 OP_SHL1, /* undocumented */
175 OP_SAR = 7,
178 enum {
179 JCC_O,
180 JCC_B,
181 JCC_Z,
182 JCC_BE,
183 JCC_S,
184 JCC_P,
185 JCC_L,
186 JCC_LE,
189 enum {
190 /* I386 int registers */
191 OR_EAX, /* MUST be even numbered */
192 OR_ECX,
193 OR_EDX,
194 OR_EBX,
195 OR_ESP,
196 OR_EBP,
197 OR_ESI,
198 OR_EDI,
200 OR_TMP0 = 16, /* temporary operand register */
201 OR_TMP1,
202 OR_A0, /* temporary register used when doing address evaluation */
205 enum {
206 USES_CC_DST = 1,
207 USES_CC_SRC = 2,
208 USES_CC_SRC2 = 4,
209 USES_CC_SRCT = 8,
212 /* Bit set if the global variable is live after setting CC_OP to X. */
213 static const uint8_t cc_op_live[CC_OP_NB] = {
214 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
215 [CC_OP_EFLAGS] = USES_CC_SRC,
216 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
217 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
218 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
219 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
220 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
221 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
222 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
223 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
224 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
225 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
226 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
227 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
228 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
229 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
230 [CC_OP_CLR] = 0,
231 [CC_OP_POPCNT] = USES_CC_SRC,
234 static void set_cc_op(DisasContext *s, CCOp op)
236 int dead;
238 if (s->cc_op == op) {
239 return;
242 /* Discard CC computation that will no longer be used. */
243 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
244 if (dead & USES_CC_DST) {
245 tcg_gen_discard_tl(cpu_cc_dst);
247 if (dead & USES_CC_SRC) {
248 tcg_gen_discard_tl(cpu_cc_src);
250 if (dead & USES_CC_SRC2) {
251 tcg_gen_discard_tl(cpu_cc_src2);
253 if (dead & USES_CC_SRCT) {
254 tcg_gen_discard_tl(s->cc_srcT);
257 if (op == CC_OP_DYNAMIC) {
258 /* The DYNAMIC setting is translator only, and should never be
259 stored. Thus we always consider it clean. */
260 s->cc_op_dirty = false;
261 } else {
262 /* Discard any computed CC_OP value (see shifts). */
263 if (s->cc_op == CC_OP_DYNAMIC) {
264 tcg_gen_discard_i32(cpu_cc_op);
266 s->cc_op_dirty = true;
268 s->cc_op = op;
271 static void gen_update_cc_op(DisasContext *s)
273 if (s->cc_op_dirty) {
274 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
275 s->cc_op_dirty = false;
279 #ifdef TARGET_X86_64
281 #define NB_OP_SIZES 4
283 #else /* !TARGET_X86_64 */
285 #define NB_OP_SIZES 3
287 #endif /* !TARGET_X86_64 */
289 #if defined(HOST_WORDS_BIGENDIAN)
290 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
291 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
292 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
293 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
294 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
295 #else
296 #define REG_B_OFFSET 0
297 #define REG_H_OFFSET 1
298 #define REG_W_OFFSET 0
299 #define REG_L_OFFSET 0
300 #define REG_LH_OFFSET 4
301 #endif
303 /* In instruction encodings for byte register accesses the
304 * register number usually indicates "low 8 bits of register N";
305 * however there are some special cases where N 4..7 indicates
306 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
307 * true for this special case, false otherwise.
309 static inline bool byte_reg_is_xH(DisasContext *s, int reg)
311 if (reg < 4) {
312 return false;
314 #ifdef TARGET_X86_64
315 if (reg >= 8 || s->x86_64_hregs) {
316 return false;
318 #endif
319 return true;
322 /* Select the size of a push/pop operation. */
323 static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
325 if (CODE64(s)) {
326 return ot == MO_16 ? MO_16 : MO_64;
327 } else {
328 return ot;
332 /* Select the size of the stack pointer. */
333 static inline MemOp mo_stacksize(DisasContext *s)
335 return CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
338 /* Select only size 64 else 32. Used for SSE operand sizes. */
339 static inline MemOp mo_64_32(MemOp ot)
341 #ifdef TARGET_X86_64
342 return ot == MO_64 ? MO_64 : MO_32;
343 #else
344 return MO_32;
345 #endif
348 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
349 byte vs word opcodes. */
350 static inline MemOp mo_b_d(int b, MemOp ot)
352 return b & 1 ? ot : MO_8;
355 /* Select size 8 if lsb of B is clear, else OT capped at 32.
356 Used for decoding operand size of port opcodes. */
357 static inline MemOp mo_b_d32(int b, MemOp ot)
359 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
362 static void gen_op_mov_reg_v(DisasContext *s, MemOp ot, int reg, TCGv t0)
364 switch(ot) {
365 case MO_8:
366 if (!byte_reg_is_xH(s, reg)) {
367 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
368 } else {
369 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
371 break;
372 case MO_16:
373 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
374 break;
375 case MO_32:
376 /* For x86_64, this sets the higher half of register to zero.
377 For i386, this is equivalent to a mov. */
378 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
379 break;
380 #ifdef TARGET_X86_64
381 case MO_64:
382 tcg_gen_mov_tl(cpu_regs[reg], t0);
383 break;
384 #endif
385 default:
386 tcg_abort();
390 static inline
391 void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg)
393 if (ot == MO_8 && byte_reg_is_xH(s, reg)) {
394 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
395 } else {
396 tcg_gen_mov_tl(t0, cpu_regs[reg]);
400 static void gen_add_A0_im(DisasContext *s, int val)
402 tcg_gen_addi_tl(s->A0, s->A0, val);
403 if (!CODE64(s)) {
404 tcg_gen_ext32u_tl(s->A0, s->A0);
408 static inline void gen_op_jmp_v(TCGv dest)
410 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
413 static inline
414 void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val)
416 tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val);
417 gen_op_mov_reg_v(s, size, reg, s->tmp0);
420 static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg)
422 tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0);
423 gen_op_mov_reg_v(s, size, reg, s->tmp0);
426 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
428 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
431 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
433 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
436 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
438 if (d == OR_TMP0) {
439 gen_op_st_v(s, idx, s->T0, s->A0);
440 } else {
441 gen_op_mov_reg_v(s, idx, d, s->T0);
445 static inline void gen_jmp_im(DisasContext *s, target_ulong pc)
447 tcg_gen_movi_tl(s->tmp0, pc);
448 gen_op_jmp_v(s->tmp0);
451 /* Compute SEG:REG into A0. SEG is selected from the override segment
452 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
453 indicate no override. */
454 static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
455 int def_seg, int ovr_seg)
457 switch (aflag) {
458 #ifdef TARGET_X86_64
459 case MO_64:
460 if (ovr_seg < 0) {
461 tcg_gen_mov_tl(s->A0, a0);
462 return;
464 break;
465 #endif
466 case MO_32:
467 /* 32 bit address */
468 if (ovr_seg < 0 && s->addseg) {
469 ovr_seg = def_seg;
471 if (ovr_seg < 0) {
472 tcg_gen_ext32u_tl(s->A0, a0);
473 return;
475 break;
476 case MO_16:
477 /* 16 bit address */
478 tcg_gen_ext16u_tl(s->A0, a0);
479 a0 = s->A0;
480 if (ovr_seg < 0) {
481 if (s->addseg) {
482 ovr_seg = def_seg;
483 } else {
484 return;
487 break;
488 default:
489 tcg_abort();
492 if (ovr_seg >= 0) {
493 TCGv seg = cpu_seg_base[ovr_seg];
495 if (aflag == MO_64) {
496 tcg_gen_add_tl(s->A0, a0, seg);
497 } else if (CODE64(s)) {
498 tcg_gen_ext32u_tl(s->A0, a0);
499 tcg_gen_add_tl(s->A0, s->A0, seg);
500 } else {
501 tcg_gen_add_tl(s->A0, a0, seg);
502 tcg_gen_ext32u_tl(s->A0, s->A0);
507 static inline void gen_string_movl_A0_ESI(DisasContext *s)
509 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
512 static inline void gen_string_movl_A0_EDI(DisasContext *s)
514 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
517 static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
519 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
520 tcg_gen_shli_tl(s->T0, s->T0, ot);
523 static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
525 switch (size) {
526 case MO_8:
527 if (sign) {
528 tcg_gen_ext8s_tl(dst, src);
529 } else {
530 tcg_gen_ext8u_tl(dst, src);
532 return dst;
533 case MO_16:
534 if (sign) {
535 tcg_gen_ext16s_tl(dst, src);
536 } else {
537 tcg_gen_ext16u_tl(dst, src);
539 return dst;
540 #ifdef TARGET_X86_64
541 case MO_32:
542 if (sign) {
543 tcg_gen_ext32s_tl(dst, src);
544 } else {
545 tcg_gen_ext32u_tl(dst, src);
547 return dst;
548 #endif
549 default:
550 return src;
554 static void gen_extu(MemOp ot, TCGv reg)
556 gen_ext_tl(reg, reg, ot, false);
559 static void gen_exts(MemOp ot, TCGv reg)
561 gen_ext_tl(reg, reg, ot, true);
564 static inline
565 void gen_op_jnz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
567 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
568 gen_extu(size, s->tmp0);
569 tcg_gen_brcondi_tl(TCG_COND_NE, s->tmp0, 0, label1);
572 static inline
573 void gen_op_jz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
575 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
576 gen_extu(size, s->tmp0);
577 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
580 static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
582 switch (ot) {
583 case MO_8:
584 gen_helper_inb(v, cpu_env, n);
585 break;
586 case MO_16:
587 gen_helper_inw(v, cpu_env, n);
588 break;
589 case MO_32:
590 gen_helper_inl(v, cpu_env, n);
591 break;
592 default:
593 tcg_abort();
597 static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
599 switch (ot) {
600 case MO_8:
601 gen_helper_outb(cpu_env, v, n);
602 break;
603 case MO_16:
604 gen_helper_outw(cpu_env, v, n);
605 break;
606 case MO_32:
607 gen_helper_outl(cpu_env, v, n);
608 break;
609 default:
610 tcg_abort();
614 static void gen_check_io(DisasContext *s, MemOp ot, target_ulong cur_eip,
615 uint32_t svm_flags)
617 target_ulong next_eip;
619 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
620 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
621 switch (ot) {
622 case MO_8:
623 gen_helper_check_iob(cpu_env, s->tmp2_i32);
624 break;
625 case MO_16:
626 gen_helper_check_iow(cpu_env, s->tmp2_i32);
627 break;
628 case MO_32:
629 gen_helper_check_iol(cpu_env, s->tmp2_i32);
630 break;
631 default:
632 tcg_abort();
635 if(s->flags & HF_GUEST_MASK) {
636 gen_update_cc_op(s);
637 gen_jmp_im(s, cur_eip);
638 svm_flags |= (1 << (4 + ot));
639 next_eip = s->pc - s->cs_base;
640 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
641 gen_helper_svm_check_io(cpu_env, s->tmp2_i32,
642 tcg_const_i32(svm_flags),
643 tcg_const_i32(next_eip - cur_eip));
647 static inline void gen_movs(DisasContext *s, MemOp ot)
649 gen_string_movl_A0_ESI(s);
650 gen_op_ld_v(s, ot, s->T0, s->A0);
651 gen_string_movl_A0_EDI(s);
652 gen_op_st_v(s, ot, s->T0, s->A0);
653 gen_op_movl_T0_Dshift(s, ot);
654 gen_op_add_reg_T0(s, s->aflag, R_ESI);
655 gen_op_add_reg_T0(s, s->aflag, R_EDI);
658 static void gen_op_update1_cc(DisasContext *s)
660 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
663 static void gen_op_update2_cc(DisasContext *s)
665 tcg_gen_mov_tl(cpu_cc_src, s->T1);
666 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
669 static void gen_op_update3_cc(DisasContext *s, TCGv reg)
671 tcg_gen_mov_tl(cpu_cc_src2, reg);
672 tcg_gen_mov_tl(cpu_cc_src, s->T1);
673 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
676 static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
678 tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1);
681 static void gen_op_update_neg_cc(DisasContext *s)
683 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
684 tcg_gen_neg_tl(cpu_cc_src, s->T0);
685 tcg_gen_movi_tl(s->cc_srcT, 0);
688 /* compute all eflags to cc_src */
689 static void gen_compute_eflags(DisasContext *s)
691 TCGv zero, dst, src1, src2;
692 int live, dead;
694 if (s->cc_op == CC_OP_EFLAGS) {
695 return;
697 if (s->cc_op == CC_OP_CLR) {
698 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
699 set_cc_op(s, CC_OP_EFLAGS);
700 return;
703 zero = NULL;
704 dst = cpu_cc_dst;
705 src1 = cpu_cc_src;
706 src2 = cpu_cc_src2;
708 /* Take care to not read values that are not live. */
709 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
710 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
711 if (dead) {
712 zero = tcg_const_tl(0);
713 if (dead & USES_CC_DST) {
714 dst = zero;
716 if (dead & USES_CC_SRC) {
717 src1 = zero;
719 if (dead & USES_CC_SRC2) {
720 src2 = zero;
724 gen_update_cc_op(s);
725 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
726 set_cc_op(s, CC_OP_EFLAGS);
728 if (dead) {
729 tcg_temp_free(zero);
733 typedef struct CCPrepare {
734 TCGCond cond;
735 TCGv reg;
736 TCGv reg2;
737 target_ulong imm;
738 target_ulong mask;
739 bool use_reg2;
740 bool no_setcond;
741 } CCPrepare;
743 /* compute eflags.C to reg */
744 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
746 TCGv t0, t1;
747 int size, shift;
749 switch (s->cc_op) {
750 case CC_OP_SUBB ... CC_OP_SUBQ:
751 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
752 size = s->cc_op - CC_OP_SUBB;
753 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
754 /* If no temporary was used, be careful not to alias t1 and t0. */
755 t0 = t1 == cpu_cc_src ? s->tmp0 : reg;
756 tcg_gen_mov_tl(t0, s->cc_srcT);
757 gen_extu(size, t0);
758 goto add_sub;
760 case CC_OP_ADDB ... CC_OP_ADDQ:
761 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
762 size = s->cc_op - CC_OP_ADDB;
763 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
764 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
765 add_sub:
766 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
767 .reg2 = t1, .mask = -1, .use_reg2 = true };
769 case CC_OP_LOGICB ... CC_OP_LOGICQ:
770 case CC_OP_CLR:
771 case CC_OP_POPCNT:
772 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
774 case CC_OP_INCB ... CC_OP_INCQ:
775 case CC_OP_DECB ... CC_OP_DECQ:
776 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
777 .mask = -1, .no_setcond = true };
779 case CC_OP_SHLB ... CC_OP_SHLQ:
780 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
781 size = s->cc_op - CC_OP_SHLB;
782 shift = (8 << size) - 1;
783 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
784 .mask = (target_ulong)1 << shift };
786 case CC_OP_MULB ... CC_OP_MULQ:
787 return (CCPrepare) { .cond = TCG_COND_NE,
788 .reg = cpu_cc_src, .mask = -1 };
790 case CC_OP_BMILGB ... CC_OP_BMILGQ:
791 size = s->cc_op - CC_OP_BMILGB;
792 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
793 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
795 case CC_OP_ADCX:
796 case CC_OP_ADCOX:
797 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
798 .mask = -1, .no_setcond = true };
800 case CC_OP_EFLAGS:
801 case CC_OP_SARB ... CC_OP_SARQ:
802 /* CC_SRC & 1 */
803 return (CCPrepare) { .cond = TCG_COND_NE,
804 .reg = cpu_cc_src, .mask = CC_C };
806 default:
807 /* The need to compute only C from CC_OP_DYNAMIC is important
808 in efficiently implementing e.g. INC at the start of a TB. */
809 gen_update_cc_op(s);
810 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
811 cpu_cc_src2, cpu_cc_op);
812 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
813 .mask = -1, .no_setcond = true };
817 /* compute eflags.P to reg */
818 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
820 gen_compute_eflags(s);
821 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
822 .mask = CC_P };
825 /* compute eflags.S to reg */
826 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
828 switch (s->cc_op) {
829 case CC_OP_DYNAMIC:
830 gen_compute_eflags(s);
831 /* FALLTHRU */
832 case CC_OP_EFLAGS:
833 case CC_OP_ADCX:
834 case CC_OP_ADOX:
835 case CC_OP_ADCOX:
836 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
837 .mask = CC_S };
838 case CC_OP_CLR:
839 case CC_OP_POPCNT:
840 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
841 default:
843 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
844 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
845 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
850 /* compute eflags.O to reg */
851 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
853 switch (s->cc_op) {
854 case CC_OP_ADOX:
855 case CC_OP_ADCOX:
856 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
857 .mask = -1, .no_setcond = true };
858 case CC_OP_CLR:
859 case CC_OP_POPCNT:
860 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
861 default:
862 gen_compute_eflags(s);
863 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
864 .mask = CC_O };
868 /* compute eflags.Z to reg */
869 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
871 switch (s->cc_op) {
872 case CC_OP_DYNAMIC:
873 gen_compute_eflags(s);
874 /* FALLTHRU */
875 case CC_OP_EFLAGS:
876 case CC_OP_ADCX:
877 case CC_OP_ADOX:
878 case CC_OP_ADCOX:
879 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
880 .mask = CC_Z };
881 case CC_OP_CLR:
882 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
883 case CC_OP_POPCNT:
884 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
885 .mask = -1 };
886 default:
888 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
889 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
890 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
895 /* perform a conditional store into register 'reg' according to jump opcode
896 value 'b'. In the fast case, T0 is guaranted not to be used. */
897 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
899 int inv, jcc_op, cond;
900 MemOp size;
901 CCPrepare cc;
902 TCGv t0;
904 inv = b & 1;
905 jcc_op = (b >> 1) & 7;
907 switch (s->cc_op) {
908 case CC_OP_SUBB ... CC_OP_SUBQ:
909 /* We optimize relational operators for the cmp/jcc case. */
910 size = s->cc_op - CC_OP_SUBB;
911 switch (jcc_op) {
912 case JCC_BE:
913 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
914 gen_extu(size, s->tmp4);
915 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
916 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4,
917 .reg2 = t0, .mask = -1, .use_reg2 = true };
918 break;
920 case JCC_L:
921 cond = TCG_COND_LT;
922 goto fast_jcc_l;
923 case JCC_LE:
924 cond = TCG_COND_LE;
925 fast_jcc_l:
926 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
927 gen_exts(size, s->tmp4);
928 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true);
929 cc = (CCPrepare) { .cond = cond, .reg = s->tmp4,
930 .reg2 = t0, .mask = -1, .use_reg2 = true };
931 break;
933 default:
934 goto slow_jcc;
936 break;
938 default:
939 slow_jcc:
940 /* This actually generates good code for JC, JZ and JS. */
941 switch (jcc_op) {
942 case JCC_O:
943 cc = gen_prepare_eflags_o(s, reg);
944 break;
945 case JCC_B:
946 cc = gen_prepare_eflags_c(s, reg);
947 break;
948 case JCC_Z:
949 cc = gen_prepare_eflags_z(s, reg);
950 break;
951 case JCC_BE:
952 gen_compute_eflags(s);
953 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
954 .mask = CC_Z | CC_C };
955 break;
956 case JCC_S:
957 cc = gen_prepare_eflags_s(s, reg);
958 break;
959 case JCC_P:
960 cc = gen_prepare_eflags_p(s, reg);
961 break;
962 case JCC_L:
963 gen_compute_eflags(s);
964 if (reg == cpu_cc_src) {
965 reg = s->tmp0;
967 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
968 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
969 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
970 .mask = CC_S };
971 break;
972 default:
973 case JCC_LE:
974 gen_compute_eflags(s);
975 if (reg == cpu_cc_src) {
976 reg = s->tmp0;
978 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
979 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
980 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
981 .mask = CC_S | CC_Z };
982 break;
984 break;
987 if (inv) {
988 cc.cond = tcg_invert_cond(cc.cond);
990 return cc;
993 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
995 CCPrepare cc = gen_prepare_cc(s, b, reg);
997 if (cc.no_setcond) {
998 if (cc.cond == TCG_COND_EQ) {
999 tcg_gen_xori_tl(reg, cc.reg, 1);
1000 } else {
1001 tcg_gen_mov_tl(reg, cc.reg);
1003 return;
1006 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1007 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1008 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1009 tcg_gen_andi_tl(reg, reg, 1);
1010 return;
1012 if (cc.mask != -1) {
1013 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1014 cc.reg = reg;
1016 if (cc.use_reg2) {
1017 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1018 } else {
1019 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1023 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1025 gen_setcc1(s, JCC_B << 1, reg);
1028 /* generate a conditional jump to label 'l1' according to jump opcode
1029 value 'b'. In the fast case, T0 is guaranted not to be used. */
1030 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1032 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1034 if (cc.mask != -1) {
1035 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1036 cc.reg = s->T0;
1038 if (cc.use_reg2) {
1039 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1040 } else {
1041 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1045 /* Generate a conditional jump to label 'l1' according to jump opcode
1046 value 'b'. In the fast case, T0 is guaranted not to be used.
1047 A translation block must end soon. */
1048 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1050 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1052 gen_update_cc_op(s);
1053 if (cc.mask != -1) {
1054 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1055 cc.reg = s->T0;
1057 set_cc_op(s, CC_OP_DYNAMIC);
1058 if (cc.use_reg2) {
1059 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1060 } else {
1061 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1065 /* XXX: does not work with gdbstub "ice" single step - not a
1066 serious problem */
1067 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1069 TCGLabel *l1 = gen_new_label();
1070 TCGLabel *l2 = gen_new_label();
1071 gen_op_jnz_ecx(s, s->aflag, l1);
1072 gen_set_label(l2);
1073 gen_jmp_tb(s, next_eip, 1);
1074 gen_set_label(l1);
1075 return l2;
1078 static inline void gen_stos(DisasContext *s, MemOp ot)
1080 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
1081 gen_string_movl_A0_EDI(s);
1082 gen_op_st_v(s, ot, s->T0, s->A0);
1083 gen_op_movl_T0_Dshift(s, ot);
1084 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1087 static inline void gen_lods(DisasContext *s, MemOp ot)
1089 gen_string_movl_A0_ESI(s);
1090 gen_op_ld_v(s, ot, s->T0, s->A0);
1091 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
1092 gen_op_movl_T0_Dshift(s, ot);
1093 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1096 static inline void gen_scas(DisasContext *s, MemOp ot)
1098 gen_string_movl_A0_EDI(s);
1099 gen_op_ld_v(s, ot, s->T1, s->A0);
1100 gen_op(s, OP_CMPL, ot, R_EAX);
1101 gen_op_movl_T0_Dshift(s, ot);
1102 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1105 static inline void gen_cmps(DisasContext *s, MemOp ot)
1107 gen_string_movl_A0_EDI(s);
1108 gen_op_ld_v(s, ot, s->T1, s->A0);
1109 gen_string_movl_A0_ESI(s);
1110 gen_op(s, OP_CMPL, ot, OR_TMP0);
1111 gen_op_movl_T0_Dshift(s, ot);
1112 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1113 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1116 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1118 if (s->flags & HF_IOBPT_MASK) {
1119 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1120 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1122 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1123 tcg_temp_free_i32(t_size);
1124 tcg_temp_free(t_next);
1129 static inline void gen_ins(DisasContext *s, MemOp ot)
1131 gen_string_movl_A0_EDI(s);
1132 /* Note: we must do this dummy write first to be restartable in
1133 case of page fault. */
1134 tcg_gen_movi_tl(s->T0, 0);
1135 gen_op_st_v(s, ot, s->T0, s->A0);
1136 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1137 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1138 gen_helper_in_func(ot, s->T0, s->tmp2_i32);
1139 gen_op_st_v(s, ot, s->T0, s->A0);
1140 gen_op_movl_T0_Dshift(s, ot);
1141 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1142 gen_bpt_io(s, s->tmp2_i32, ot);
1145 static inline void gen_outs(DisasContext *s, MemOp ot)
1147 gen_string_movl_A0_ESI(s);
1148 gen_op_ld_v(s, ot, s->T0, s->A0);
1150 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1151 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1152 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0);
1153 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
1154 gen_op_movl_T0_Dshift(s, ot);
1155 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1156 gen_bpt_io(s, s->tmp2_i32, ot);
1159 /* same method as Valgrind : we generate jumps to current or next
1160 instruction */
1161 #define GEN_REPZ(op) \
1162 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1163 target_ulong cur_eip, target_ulong next_eip) \
1165 TCGLabel *l2; \
1166 gen_update_cc_op(s); \
1167 l2 = gen_jz_ecx_string(s, next_eip); \
1168 gen_ ## op(s, ot); \
1169 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1170 /* a loop would cause two single step exceptions if ECX = 1 \
1171 before rep string_insn */ \
1172 if (s->repz_opt) \
1173 gen_op_jz_ecx(s, s->aflag, l2); \
1174 gen_jmp(s, cur_eip); \
1177 #define GEN_REPZ2(op) \
1178 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1179 target_ulong cur_eip, \
1180 target_ulong next_eip, \
1181 int nz) \
1183 TCGLabel *l2; \
1184 gen_update_cc_op(s); \
1185 l2 = gen_jz_ecx_string(s, next_eip); \
1186 gen_ ## op(s, ot); \
1187 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1188 gen_update_cc_op(s); \
1189 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1190 if (s->repz_opt) \
1191 gen_op_jz_ecx(s, s->aflag, l2); \
1192 gen_jmp(s, cur_eip); \
1195 GEN_REPZ(movs)
1196 GEN_REPZ(stos)
1197 GEN_REPZ(lods)
1198 GEN_REPZ(ins)
1199 GEN_REPZ(outs)
1200 GEN_REPZ2(scas)
1201 GEN_REPZ2(cmps)
1203 static void gen_helper_fp_arith_ST0_FT0(int op)
1205 switch (op) {
1206 case 0:
1207 gen_helper_fadd_ST0_FT0(cpu_env);
1208 break;
1209 case 1:
1210 gen_helper_fmul_ST0_FT0(cpu_env);
1211 break;
1212 case 2:
1213 gen_helper_fcom_ST0_FT0(cpu_env);
1214 break;
1215 case 3:
1216 gen_helper_fcom_ST0_FT0(cpu_env);
1217 break;
1218 case 4:
1219 gen_helper_fsub_ST0_FT0(cpu_env);
1220 break;
1221 case 5:
1222 gen_helper_fsubr_ST0_FT0(cpu_env);
1223 break;
1224 case 6:
1225 gen_helper_fdiv_ST0_FT0(cpu_env);
1226 break;
1227 case 7:
1228 gen_helper_fdivr_ST0_FT0(cpu_env);
1229 break;
1233 /* NOTE the exception in "r" op ordering */
1234 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1236 TCGv_i32 tmp = tcg_const_i32(opreg);
1237 switch (op) {
1238 case 0:
1239 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1240 break;
1241 case 1:
1242 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1243 break;
1244 case 4:
1245 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1246 break;
1247 case 5:
1248 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1249 break;
1250 case 6:
1251 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1252 break;
1253 case 7:
1254 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1255 break;
1259 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
1261 gen_update_cc_op(s);
1262 gen_jmp_im(s, cur_eip);
1263 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
1264 s->base.is_jmp = DISAS_NORETURN;
1267 /* Generate #UD for the current instruction. The assumption here is that
1268 the instruction is known, but it isn't allowed in the current cpu mode. */
1269 static void gen_illegal_opcode(DisasContext *s)
1271 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
1274 /* if d == OR_TMP0, it means memory operand (address in A0) */
1275 static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
1277 if (d != OR_TMP0) {
1278 if (s1->prefix & PREFIX_LOCK) {
1279 /* Lock prefix when destination is not memory. */
1280 gen_illegal_opcode(s1);
1281 return;
1283 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1284 } else if (!(s1->prefix & PREFIX_LOCK)) {
1285 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1287 switch(op) {
1288 case OP_ADCL:
1289 gen_compute_eflags_c(s1, s1->tmp4);
1290 if (s1->prefix & PREFIX_LOCK) {
1291 tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1);
1292 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1293 s1->mem_index, ot | MO_LE);
1294 } else {
1295 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1296 tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4);
1297 gen_op_st_rm_T0_A0(s1, ot, d);
1299 gen_op_update3_cc(s1, s1->tmp4);
1300 set_cc_op(s1, CC_OP_ADCB + ot);
1301 break;
1302 case OP_SBBL:
1303 gen_compute_eflags_c(s1, s1->tmp4);
1304 if (s1->prefix & PREFIX_LOCK) {
1305 tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4);
1306 tcg_gen_neg_tl(s1->T0, s1->T0);
1307 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1308 s1->mem_index, ot | MO_LE);
1309 } else {
1310 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1311 tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4);
1312 gen_op_st_rm_T0_A0(s1, ot, d);
1314 gen_op_update3_cc(s1, s1->tmp4);
1315 set_cc_op(s1, CC_OP_SBBB + ot);
1316 break;
1317 case OP_ADDL:
1318 if (s1->prefix & PREFIX_LOCK) {
1319 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1,
1320 s1->mem_index, ot | MO_LE);
1321 } else {
1322 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1323 gen_op_st_rm_T0_A0(s1, ot, d);
1325 gen_op_update2_cc(s1);
1326 set_cc_op(s1, CC_OP_ADDB + ot);
1327 break;
1328 case OP_SUBL:
1329 if (s1->prefix & PREFIX_LOCK) {
1330 tcg_gen_neg_tl(s1->T0, s1->T1);
1331 tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
1332 s1->mem_index, ot | MO_LE);
1333 tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
1334 } else {
1335 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1336 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1337 gen_op_st_rm_T0_A0(s1, ot, d);
1339 gen_op_update2_cc(s1);
1340 set_cc_op(s1, CC_OP_SUBB + ot);
1341 break;
1342 default:
1343 case OP_ANDL:
1344 if (s1->prefix & PREFIX_LOCK) {
1345 tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1,
1346 s1->mem_index, ot | MO_LE);
1347 } else {
1348 tcg_gen_and_tl(s1->T0, s1->T0, s1->T1);
1349 gen_op_st_rm_T0_A0(s1, ot, d);
1351 gen_op_update1_cc(s1);
1352 set_cc_op(s1, CC_OP_LOGICB + ot);
1353 break;
1354 case OP_ORL:
1355 if (s1->prefix & PREFIX_LOCK) {
1356 tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1,
1357 s1->mem_index, ot | MO_LE);
1358 } else {
1359 tcg_gen_or_tl(s1->T0, s1->T0, s1->T1);
1360 gen_op_st_rm_T0_A0(s1, ot, d);
1362 gen_op_update1_cc(s1);
1363 set_cc_op(s1, CC_OP_LOGICB + ot);
1364 break;
1365 case OP_XORL:
1366 if (s1->prefix & PREFIX_LOCK) {
1367 tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1,
1368 s1->mem_index, ot | MO_LE);
1369 } else {
1370 tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1);
1371 gen_op_st_rm_T0_A0(s1, ot, d);
1373 gen_op_update1_cc(s1);
1374 set_cc_op(s1, CC_OP_LOGICB + ot);
1375 break;
1376 case OP_CMPL:
1377 tcg_gen_mov_tl(cpu_cc_src, s1->T1);
1378 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1379 tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
1380 set_cc_op(s1, CC_OP_SUBB + ot);
1381 break;
1385 /* if d == OR_TMP0, it means memory operand (address in A0) */
1386 static void gen_inc(DisasContext *s1, MemOp ot, int d, int c)
1388 if (s1->prefix & PREFIX_LOCK) {
1389 if (d != OR_TMP0) {
1390 /* Lock prefix when destination is not memory */
1391 gen_illegal_opcode(s1);
1392 return;
1394 tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
1395 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1396 s1->mem_index, ot | MO_LE);
1397 } else {
1398 if (d != OR_TMP0) {
1399 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1400 } else {
1401 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1403 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
1404 gen_op_st_rm_T0_A0(s1, ot, d);
1407 gen_compute_eflags_c(s1, cpu_cc_src);
1408 tcg_gen_mov_tl(cpu_cc_dst, s1->T0);
1409 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1412 static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
1413 TCGv shm1, TCGv count, bool is_right)
1415 TCGv_i32 z32, s32, oldop;
1416 TCGv z_tl;
1418 /* Store the results into the CC variables. If we know that the
1419 variable must be dead, store unconditionally. Otherwise we'll
1420 need to not disrupt the current contents. */
1421 z_tl = tcg_const_tl(0);
1422 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1423 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1424 result, cpu_cc_dst);
1425 } else {
1426 tcg_gen_mov_tl(cpu_cc_dst, result);
1428 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1429 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1430 shm1, cpu_cc_src);
1431 } else {
1432 tcg_gen_mov_tl(cpu_cc_src, shm1);
1434 tcg_temp_free(z_tl);
1436 /* Get the two potential CC_OP values into temporaries. */
1437 tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1438 if (s->cc_op == CC_OP_DYNAMIC) {
1439 oldop = cpu_cc_op;
1440 } else {
1441 tcg_gen_movi_i32(s->tmp3_i32, s->cc_op);
1442 oldop = s->tmp3_i32;
1445 /* Conditionally store the CC_OP value. */
1446 z32 = tcg_const_i32(0);
1447 s32 = tcg_temp_new_i32();
1448 tcg_gen_trunc_tl_i32(s32, count);
1449 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop);
1450 tcg_temp_free_i32(z32);
1451 tcg_temp_free_i32(s32);
1453 /* The CC_OP value is no longer predictable. */
1454 set_cc_op(s, CC_OP_DYNAMIC);
1457 static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1,
1458 int is_right, int is_arith)
1460 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1462 /* load */
1463 if (op1 == OR_TMP0) {
1464 gen_op_ld_v(s, ot, s->T0, s->A0);
1465 } else {
1466 gen_op_mov_v_reg(s, ot, s->T0, op1);
1469 tcg_gen_andi_tl(s->T1, s->T1, mask);
1470 tcg_gen_subi_tl(s->tmp0, s->T1, 1);
1472 if (is_right) {
1473 if (is_arith) {
1474 gen_exts(ot, s->T0);
1475 tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0);
1476 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
1477 } else {
1478 gen_extu(ot, s->T0);
1479 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1480 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
1482 } else {
1483 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1484 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
1487 /* store */
1488 gen_op_st_rm_T0_A0(s, ot, op1);
1490 gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right);
1493 static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1494 int is_right, int is_arith)
1496 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1498 /* load */
1499 if (op1 == OR_TMP0)
1500 gen_op_ld_v(s, ot, s->T0, s->A0);
1501 else
1502 gen_op_mov_v_reg(s, ot, s->T0, op1);
1504 op2 &= mask;
1505 if (op2 != 0) {
1506 if (is_right) {
1507 if (is_arith) {
1508 gen_exts(ot, s->T0);
1509 tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1);
1510 tcg_gen_sari_tl(s->T0, s->T0, op2);
1511 } else {
1512 gen_extu(ot, s->T0);
1513 tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1);
1514 tcg_gen_shri_tl(s->T0, s->T0, op2);
1516 } else {
1517 tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1);
1518 tcg_gen_shli_tl(s->T0, s->T0, op2);
1522 /* store */
1523 gen_op_st_rm_T0_A0(s, ot, op1);
1525 /* update eflags if non zero shift */
1526 if (op2 != 0) {
1527 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
1528 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
1529 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1533 static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right)
1535 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1536 TCGv_i32 t0, t1;
1538 /* load */
1539 if (op1 == OR_TMP0) {
1540 gen_op_ld_v(s, ot, s->T0, s->A0);
1541 } else {
1542 gen_op_mov_v_reg(s, ot, s->T0, op1);
1545 tcg_gen_andi_tl(s->T1, s->T1, mask);
1547 switch (ot) {
1548 case MO_8:
1549 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1550 tcg_gen_ext8u_tl(s->T0, s->T0);
1551 tcg_gen_muli_tl(s->T0, s->T0, 0x01010101);
1552 goto do_long;
1553 case MO_16:
1554 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1555 tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16);
1556 goto do_long;
1557 do_long:
1558 #ifdef TARGET_X86_64
1559 case MO_32:
1560 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1561 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
1562 if (is_right) {
1563 tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1564 } else {
1565 tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1567 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1568 break;
1569 #endif
1570 default:
1571 if (is_right) {
1572 tcg_gen_rotr_tl(s->T0, s->T0, s->T1);
1573 } else {
1574 tcg_gen_rotl_tl(s->T0, s->T0, s->T1);
1576 break;
1579 /* store */
1580 gen_op_st_rm_T0_A0(s, ot, op1);
1582 /* We'll need the flags computed into CC_SRC. */
1583 gen_compute_eflags(s);
1585 /* The value that was "rotated out" is now present at the other end
1586 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1587 since we've computed the flags into CC_SRC, these variables are
1588 currently dead. */
1589 if (is_right) {
1590 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1591 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1592 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1593 } else {
1594 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1595 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1597 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1598 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1600 /* Now conditionally store the new CC_OP value. If the shift count
1601 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1602 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1603 exactly as we computed above. */
1604 t0 = tcg_const_i32(0);
1605 t1 = tcg_temp_new_i32();
1606 tcg_gen_trunc_tl_i32(t1, s->T1);
1607 tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX);
1608 tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS);
1609 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1610 s->tmp2_i32, s->tmp3_i32);
1611 tcg_temp_free_i32(t0);
1612 tcg_temp_free_i32(t1);
1614 /* The CC_OP value is no longer predictable. */
1615 set_cc_op(s, CC_OP_DYNAMIC);
1618 static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1619 int is_right)
1621 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1622 int shift;
1624 /* load */
1625 if (op1 == OR_TMP0) {
1626 gen_op_ld_v(s, ot, s->T0, s->A0);
1627 } else {
1628 gen_op_mov_v_reg(s, ot, s->T0, op1);
1631 op2 &= mask;
1632 if (op2 != 0) {
1633 switch (ot) {
1634 #ifdef TARGET_X86_64
1635 case MO_32:
1636 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1637 if (is_right) {
1638 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2);
1639 } else {
1640 tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2);
1642 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1643 break;
1644 #endif
1645 default:
1646 if (is_right) {
1647 tcg_gen_rotri_tl(s->T0, s->T0, op2);
1648 } else {
1649 tcg_gen_rotli_tl(s->T0, s->T0, op2);
1651 break;
1652 case MO_8:
1653 mask = 7;
1654 goto do_shifts;
1655 case MO_16:
1656 mask = 15;
1657 do_shifts:
1658 shift = op2 & mask;
1659 if (is_right) {
1660 shift = mask + 1 - shift;
1662 gen_extu(ot, s->T0);
1663 tcg_gen_shli_tl(s->tmp0, s->T0, shift);
1664 tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift);
1665 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
1666 break;
1670 /* store */
1671 gen_op_st_rm_T0_A0(s, ot, op1);
1673 if (op2 != 0) {
1674 /* Compute the flags into CC_SRC. */
1675 gen_compute_eflags(s);
1677 /* The value that was "rotated out" is now present at the other end
1678 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1679 since we've computed the flags into CC_SRC, these variables are
1680 currently dead. */
1681 if (is_right) {
1682 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1683 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1684 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1685 } else {
1686 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1687 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1689 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1690 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1691 set_cc_op(s, CC_OP_ADCOX);
1695 /* XXX: add faster immediate = 1 case */
1696 static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
1697 int is_right)
1699 gen_compute_eflags(s);
1700 assert(s->cc_op == CC_OP_EFLAGS);
1702 /* load */
1703 if (op1 == OR_TMP0)
1704 gen_op_ld_v(s, ot, s->T0, s->A0);
1705 else
1706 gen_op_mov_v_reg(s, ot, s->T0, op1);
1708 if (is_right) {
1709 switch (ot) {
1710 case MO_8:
1711 gen_helper_rcrb(s->T0, cpu_env, s->T0, s->T1);
1712 break;
1713 case MO_16:
1714 gen_helper_rcrw(s->T0, cpu_env, s->T0, s->T1);
1715 break;
1716 case MO_32:
1717 gen_helper_rcrl(s->T0, cpu_env, s->T0, s->T1);
1718 break;
1719 #ifdef TARGET_X86_64
1720 case MO_64:
1721 gen_helper_rcrq(s->T0, cpu_env, s->T0, s->T1);
1722 break;
1723 #endif
1724 default:
1725 tcg_abort();
1727 } else {
1728 switch (ot) {
1729 case MO_8:
1730 gen_helper_rclb(s->T0, cpu_env, s->T0, s->T1);
1731 break;
1732 case MO_16:
1733 gen_helper_rclw(s->T0, cpu_env, s->T0, s->T1);
1734 break;
1735 case MO_32:
1736 gen_helper_rcll(s->T0, cpu_env, s->T0, s->T1);
1737 break;
1738 #ifdef TARGET_X86_64
1739 case MO_64:
1740 gen_helper_rclq(s->T0, cpu_env, s->T0, s->T1);
1741 break;
1742 #endif
1743 default:
1744 tcg_abort();
1747 /* store */
1748 gen_op_st_rm_T0_A0(s, ot, op1);
1751 /* XXX: add faster immediate case */
1752 static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
1753 bool is_right, TCGv count_in)
1755 target_ulong mask = (ot == MO_64 ? 63 : 31);
1756 TCGv count;
1758 /* load */
1759 if (op1 == OR_TMP0) {
1760 gen_op_ld_v(s, ot, s->T0, s->A0);
1761 } else {
1762 gen_op_mov_v_reg(s, ot, s->T0, op1);
1765 count = tcg_temp_new();
1766 tcg_gen_andi_tl(count, count_in, mask);
1768 switch (ot) {
1769 case MO_16:
1770 /* Note: we implement the Intel behaviour for shift count > 16.
1771 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1772 portion by constructing it as a 32-bit value. */
1773 if (is_right) {
1774 tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16);
1775 tcg_gen_mov_tl(s->T1, s->T0);
1776 tcg_gen_mov_tl(s->T0, s->tmp0);
1777 } else {
1778 tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
1780 /* FALLTHRU */
1781 #ifdef TARGET_X86_64
1782 case MO_32:
1783 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1784 tcg_gen_subi_tl(s->tmp0, count, 1);
1785 if (is_right) {
1786 tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1);
1787 tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0);
1788 tcg_gen_shr_i64(s->T0, s->T0, count);
1789 } else {
1790 tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0);
1791 tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0);
1792 tcg_gen_shl_i64(s->T0, s->T0, count);
1793 tcg_gen_shri_i64(s->tmp0, s->tmp0, 32);
1794 tcg_gen_shri_i64(s->T0, s->T0, 32);
1796 break;
1797 #endif
1798 default:
1799 tcg_gen_subi_tl(s->tmp0, count, 1);
1800 if (is_right) {
1801 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1803 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1804 tcg_gen_shr_tl(s->T0, s->T0, count);
1805 tcg_gen_shl_tl(s->T1, s->T1, s->tmp4);
1806 } else {
1807 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1808 if (ot == MO_16) {
1809 /* Only needed if count > 16, for Intel behaviour. */
1810 tcg_gen_subfi_tl(s->tmp4, 33, count);
1811 tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4);
1812 tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4);
1815 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1816 tcg_gen_shl_tl(s->T0, s->T0, count);
1817 tcg_gen_shr_tl(s->T1, s->T1, s->tmp4);
1819 tcg_gen_movi_tl(s->tmp4, 0);
1820 tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4,
1821 s->tmp4, s->T1);
1822 tcg_gen_or_tl(s->T0, s->T0, s->T1);
1823 break;
1826 /* store */
1827 gen_op_st_rm_T0_A0(s, ot, op1);
1829 gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
1830 tcg_temp_free(count);
1833 static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s)
1835 if (s != OR_TMP1)
1836 gen_op_mov_v_reg(s1, ot, s1->T1, s);
1837 switch(op) {
1838 case OP_ROL:
1839 gen_rot_rm_T1(s1, ot, d, 0);
1840 break;
1841 case OP_ROR:
1842 gen_rot_rm_T1(s1, ot, d, 1);
1843 break;
1844 case OP_SHL:
1845 case OP_SHL1:
1846 gen_shift_rm_T1(s1, ot, d, 0, 0);
1847 break;
1848 case OP_SHR:
1849 gen_shift_rm_T1(s1, ot, d, 1, 0);
1850 break;
1851 case OP_SAR:
1852 gen_shift_rm_T1(s1, ot, d, 1, 1);
1853 break;
1854 case OP_RCL:
1855 gen_rotc_rm_T1(s1, ot, d, 0);
1856 break;
1857 case OP_RCR:
1858 gen_rotc_rm_T1(s1, ot, d, 1);
1859 break;
1863 static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c)
1865 switch(op) {
1866 case OP_ROL:
1867 gen_rot_rm_im(s1, ot, d, c, 0);
1868 break;
1869 case OP_ROR:
1870 gen_rot_rm_im(s1, ot, d, c, 1);
1871 break;
1872 case OP_SHL:
1873 case OP_SHL1:
1874 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1875 break;
1876 case OP_SHR:
1877 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1878 break;
1879 case OP_SAR:
1880 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1881 break;
1882 default:
1883 /* currently not optimized */
1884 tcg_gen_movi_tl(s1->T1, c);
1885 gen_shift(s1, op, ot, d, OR_TMP1);
1886 break;
1890 #define X86_MAX_INSN_LENGTH 15
1892 static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
1894 uint64_t pc = s->pc;
1896 s->pc += num_bytes;
1897 if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
1898 /* If the instruction's 16th byte is on a different page than the 1st, a
1899 * page fault on the second page wins over the general protection fault
1900 * caused by the instruction being too long.
1901 * This can happen even if the operand is only one byte long!
1903 if (((s->pc - 1) ^ (pc - 1)) & TARGET_PAGE_MASK) {
1904 volatile uint8_t unused =
1905 cpu_ldub_code(env, (s->pc - 1) & TARGET_PAGE_MASK);
1906 (void) unused;
1908 siglongjmp(s->jmpbuf, 1);
1911 return pc;
1914 static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
1916 return translator_ldub(env, advance_pc(env, s, 1));
1919 static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
1921 return translator_ldsw(env, advance_pc(env, s, 2));
1924 static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
1926 return translator_lduw(env, advance_pc(env, s, 2));
1929 static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
1931 return translator_ldl(env, advance_pc(env, s, 4));
1934 #ifdef TARGET_X86_64
1935 static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
1937 return translator_ldq(env, advance_pc(env, s, 8));
1939 #endif
1941 /* Decompose an address. */
1943 typedef struct AddressParts {
1944 int def_seg;
1945 int base;
1946 int index;
1947 int scale;
1948 target_long disp;
1949 } AddressParts;
1951 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
1952 int modrm)
1954 int def_seg, base, index, scale, mod, rm;
1955 target_long disp;
1956 bool havesib;
1958 def_seg = R_DS;
1959 index = -1;
1960 scale = 0;
1961 disp = 0;
1963 mod = (modrm >> 6) & 3;
1964 rm = modrm & 7;
1965 base = rm | REX_B(s);
1967 if (mod == 3) {
1968 /* Normally filtered out earlier, but including this path
1969 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
1970 goto done;
1973 switch (s->aflag) {
1974 case MO_64:
1975 case MO_32:
1976 havesib = 0;
1977 if (rm == 4) {
1978 int code = x86_ldub_code(env, s);
1979 scale = (code >> 6) & 3;
1980 index = ((code >> 3) & 7) | REX_X(s);
1981 if (index == 4) {
1982 index = -1; /* no index */
1984 base = (code & 7) | REX_B(s);
1985 havesib = 1;
1988 switch (mod) {
1989 case 0:
1990 if ((base & 7) == 5) {
1991 base = -1;
1992 disp = (int32_t)x86_ldl_code(env, s);
1993 if (CODE64(s) && !havesib) {
1994 base = -2;
1995 disp += s->pc + s->rip_offset;
1998 break;
1999 case 1:
2000 disp = (int8_t)x86_ldub_code(env, s);
2001 break;
2002 default:
2003 case 2:
2004 disp = (int32_t)x86_ldl_code(env, s);
2005 break;
2008 /* For correct popl handling with esp. */
2009 if (base == R_ESP && s->popl_esp_hack) {
2010 disp += s->popl_esp_hack;
2012 if (base == R_EBP || base == R_ESP) {
2013 def_seg = R_SS;
2015 break;
2017 case MO_16:
2018 if (mod == 0) {
2019 if (rm == 6) {
2020 base = -1;
2021 disp = x86_lduw_code(env, s);
2022 break;
2024 } else if (mod == 1) {
2025 disp = (int8_t)x86_ldub_code(env, s);
2026 } else {
2027 disp = (int16_t)x86_lduw_code(env, s);
2030 switch (rm) {
2031 case 0:
2032 base = R_EBX;
2033 index = R_ESI;
2034 break;
2035 case 1:
2036 base = R_EBX;
2037 index = R_EDI;
2038 break;
2039 case 2:
2040 base = R_EBP;
2041 index = R_ESI;
2042 def_seg = R_SS;
2043 break;
2044 case 3:
2045 base = R_EBP;
2046 index = R_EDI;
2047 def_seg = R_SS;
2048 break;
2049 case 4:
2050 base = R_ESI;
2051 break;
2052 case 5:
2053 base = R_EDI;
2054 break;
2055 case 6:
2056 base = R_EBP;
2057 def_seg = R_SS;
2058 break;
2059 default:
2060 case 7:
2061 base = R_EBX;
2062 break;
2064 break;
2066 default:
2067 tcg_abort();
2070 done:
2071 return (AddressParts){ def_seg, base, index, scale, disp };
2074 /* Compute the address, with a minimum number of TCG ops. */
2075 static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a)
2077 TCGv ea = NULL;
2079 if (a.index >= 0) {
2080 if (a.scale == 0) {
2081 ea = cpu_regs[a.index];
2082 } else {
2083 tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale);
2084 ea = s->A0;
2086 if (a.base >= 0) {
2087 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2088 ea = s->A0;
2090 } else if (a.base >= 0) {
2091 ea = cpu_regs[a.base];
2093 if (!ea) {
2094 tcg_gen_movi_tl(s->A0, a.disp);
2095 ea = s->A0;
2096 } else if (a.disp != 0) {
2097 tcg_gen_addi_tl(s->A0, ea, a.disp);
2098 ea = s->A0;
2101 return ea;
2104 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2106 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2107 TCGv ea = gen_lea_modrm_1(s, a);
2108 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2111 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2113 (void)gen_lea_modrm_0(env, s, modrm);
2116 /* Used for BNDCL, BNDCU, BNDCN. */
2117 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2118 TCGCond cond, TCGv_i64 bndv)
2120 TCGv ea = gen_lea_modrm_1(s, gen_lea_modrm_0(env, s, modrm));
2122 tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
2123 if (!CODE64(s)) {
2124 tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64);
2126 tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv);
2127 tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64);
2128 gen_helper_bndck(cpu_env, s->tmp2_i32);
2131 /* used for LEA and MOV AX, mem */
2132 static void gen_add_A0_ds_seg(DisasContext *s)
2134 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
2137 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2138 OR_TMP0 */
2139 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2140 MemOp ot, int reg, int is_store)
2142 int mod, rm;
2144 mod = (modrm >> 6) & 3;
2145 rm = (modrm & 7) | REX_B(s);
2146 if (mod == 3) {
2147 if (is_store) {
2148 if (reg != OR_TMP0)
2149 gen_op_mov_v_reg(s, ot, s->T0, reg);
2150 gen_op_mov_reg_v(s, ot, rm, s->T0);
2151 } else {
2152 gen_op_mov_v_reg(s, ot, s->T0, rm);
2153 if (reg != OR_TMP0)
2154 gen_op_mov_reg_v(s, ot, reg, s->T0);
2156 } else {
2157 gen_lea_modrm(env, s, modrm);
2158 if (is_store) {
2159 if (reg != OR_TMP0)
2160 gen_op_mov_v_reg(s, ot, s->T0, reg);
2161 gen_op_st_v(s, ot, s->T0, s->A0);
2162 } else {
2163 gen_op_ld_v(s, ot, s->T0, s->A0);
2164 if (reg != OR_TMP0)
2165 gen_op_mov_reg_v(s, ot, reg, s->T0);
2170 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
2172 uint32_t ret;
2174 switch (ot) {
2175 case MO_8:
2176 ret = x86_ldub_code(env, s);
2177 break;
2178 case MO_16:
2179 ret = x86_lduw_code(env, s);
2180 break;
2181 case MO_32:
2182 #ifdef TARGET_X86_64
2183 case MO_64:
2184 #endif
2185 ret = x86_ldl_code(env, s);
2186 break;
2187 default:
2188 tcg_abort();
2190 return ret;
2193 static inline int insn_const_size(MemOp ot)
2195 if (ot <= MO_32) {
2196 return 1 << ot;
2197 } else {
2198 return 4;
2202 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2204 #ifndef CONFIG_USER_ONLY
2205 return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
2206 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2207 #else
2208 return true;
2209 #endif
2212 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2214 target_ulong pc = s->cs_base + eip;
2216 if (use_goto_tb(s, pc)) {
2217 /* jump to same page: we can use a direct jump */
2218 tcg_gen_goto_tb(tb_num);
2219 gen_jmp_im(s, eip);
2220 tcg_gen_exit_tb(s->base.tb, tb_num);
2221 s->base.is_jmp = DISAS_NORETURN;
2222 } else {
2223 /* jump to another page */
2224 gen_jmp_im(s, eip);
2225 gen_jr(s, s->tmp0);
2229 static inline void gen_jcc(DisasContext *s, int b,
2230 target_ulong val, target_ulong next_eip)
2232 TCGLabel *l1, *l2;
2234 if (s->jmp_opt) {
2235 l1 = gen_new_label();
2236 gen_jcc1(s, b, l1);
2238 gen_goto_tb(s, 0, next_eip);
2240 gen_set_label(l1);
2241 gen_goto_tb(s, 1, val);
2242 } else {
2243 l1 = gen_new_label();
2244 l2 = gen_new_label();
2245 gen_jcc1(s, b, l1);
2247 gen_jmp_im(s, next_eip);
2248 tcg_gen_br(l2);
2250 gen_set_label(l1);
2251 gen_jmp_im(s, val);
2252 gen_set_label(l2);
2253 gen_eob(s);
2257 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
2258 int modrm, int reg)
2260 CCPrepare cc;
2262 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2264 cc = gen_prepare_cc(s, b, s->T1);
2265 if (cc.mask != -1) {
2266 TCGv t0 = tcg_temp_new();
2267 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2268 cc.reg = t0;
2270 if (!cc.use_reg2) {
2271 cc.reg2 = tcg_const_tl(cc.imm);
2274 tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2,
2275 s->T0, cpu_regs[reg]);
2276 gen_op_mov_reg_v(s, ot, reg, s->T0);
2278 if (cc.mask != -1) {
2279 tcg_temp_free(cc.reg);
2281 if (!cc.use_reg2) {
2282 tcg_temp_free(cc.reg2);
2286 static inline void gen_op_movl_T0_seg(DisasContext *s, int seg_reg)
2288 tcg_gen_ld32u_tl(s->T0, cpu_env,
2289 offsetof(CPUX86State,segs[seg_reg].selector));
2292 static inline void gen_op_movl_seg_T0_vm(DisasContext *s, int seg_reg)
2294 tcg_gen_ext16u_tl(s->T0, s->T0);
2295 tcg_gen_st32_tl(s->T0, cpu_env,
2296 offsetof(CPUX86State,segs[seg_reg].selector));
2297 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
2300 /* move T0 to seg_reg and compute if the CPU state may change. Never
2301 call this function with seg_reg == R_CS */
2302 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
2304 if (s->pe && !s->vm86) {
2305 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
2306 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), s->tmp2_i32);
2307 /* abort translation because the addseg value may change or
2308 because ss32 may change. For R_SS, translation must always
2309 stop as a special handling must be done to disable hardware
2310 interrupts for the next instruction */
2311 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) {
2312 s->base.is_jmp = DISAS_TOO_MANY;
2314 } else {
2315 gen_op_movl_seg_T0_vm(s, seg_reg);
2316 if (seg_reg == R_SS) {
2317 s->base.is_jmp = DISAS_TOO_MANY;
2322 static inline int svm_is_rep(int prefixes)
2324 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2327 static inline void
2328 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2329 uint32_t type, uint64_t param)
2331 /* no SVM activated; fast case */
2332 if (likely(!(s->flags & HF_GUEST_MASK)))
2333 return;
2334 gen_update_cc_op(s);
2335 gen_jmp_im(s, pc_start - s->cs_base);
2336 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2337 tcg_const_i64(param));
2340 static inline void
2341 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2343 gen_svm_check_intercept_param(s, pc_start, type, 0);
2346 static inline void gen_stack_update(DisasContext *s, int addend)
2348 gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend);
2351 /* Generate a push. It depends on ss32, addseg and dflag. */
2352 static void gen_push_v(DisasContext *s, TCGv val)
2354 MemOp d_ot = mo_pushpop(s, s->dflag);
2355 MemOp a_ot = mo_stacksize(s);
2356 int size = 1 << d_ot;
2357 TCGv new_esp = s->A0;
2359 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2361 if (!CODE64(s)) {
2362 if (s->addseg) {
2363 new_esp = s->tmp4;
2364 tcg_gen_mov_tl(new_esp, s->A0);
2366 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2369 gen_op_st_v(s, d_ot, val, s->A0);
2370 gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp);
2373 /* two step pop is necessary for precise exceptions */
2374 static MemOp gen_pop_T0(DisasContext *s)
2376 MemOp d_ot = mo_pushpop(s, s->dflag);
2378 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2379 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2381 return d_ot;
2384 static inline void gen_pop_update(DisasContext *s, MemOp ot)
2386 gen_stack_update(s, 1 << ot);
2389 static inline void gen_stack_A0(DisasContext *s)
2391 gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2394 static void gen_pusha(DisasContext *s)
2396 MemOp s_ot = s->ss32 ? MO_32 : MO_16;
2397 MemOp d_ot = s->dflag;
2398 int size = 1 << d_ot;
2399 int i;
2401 for (i = 0; i < 8; i++) {
2402 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size);
2403 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2404 gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0);
2407 gen_stack_update(s, -8 * size);
2410 static void gen_popa(DisasContext *s)
2412 MemOp s_ot = s->ss32 ? MO_32 : MO_16;
2413 MemOp d_ot = s->dflag;
2414 int size = 1 << d_ot;
2415 int i;
2417 for (i = 0; i < 8; i++) {
2418 /* ESP is not reloaded */
2419 if (7 - i == R_ESP) {
2420 continue;
2422 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size);
2423 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2424 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2425 gen_op_mov_reg_v(s, d_ot, 7 - i, s->T0);
2428 gen_stack_update(s, 8 * size);
2431 static void gen_enter(DisasContext *s, int esp_addend, int level)
2433 MemOp d_ot = mo_pushpop(s, s->dflag);
2434 MemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
2435 int size = 1 << d_ot;
2437 /* Push BP; compute FrameTemp into T1. */
2438 tcg_gen_subi_tl(s->T1, cpu_regs[R_ESP], size);
2439 gen_lea_v_seg(s, a_ot, s->T1, R_SS, -1);
2440 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0);
2442 level &= 31;
2443 if (level != 0) {
2444 int i;
2446 /* Copy level-1 pointers from the previous frame. */
2447 for (i = 1; i < level; ++i) {
2448 tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i);
2449 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2450 gen_op_ld_v(s, d_ot, s->tmp0, s->A0);
2452 tcg_gen_subi_tl(s->A0, s->T1, size * i);
2453 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2454 gen_op_st_v(s, d_ot, s->tmp0, s->A0);
2457 /* Push the current FrameTemp as the last level. */
2458 tcg_gen_subi_tl(s->A0, s->T1, size * level);
2459 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2460 gen_op_st_v(s, d_ot, s->T1, s->A0);
2463 /* Copy the FrameTemp value to EBP. */
2464 gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
2466 /* Compute the final value of ESP. */
2467 tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
2468 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2471 static void gen_leave(DisasContext *s)
2473 MemOp d_ot = mo_pushpop(s, s->dflag);
2474 MemOp a_ot = mo_stacksize(s);
2476 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2477 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2479 tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot);
2481 gen_op_mov_reg_v(s, d_ot, R_EBP, s->T0);
2482 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2485 /* Similarly, except that the assumption here is that we don't decode
2486 the instruction at all -- either a missing opcode, an unimplemented
2487 feature, or just a bogus instruction stream. */
2488 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2490 gen_illegal_opcode(s);
2492 if (qemu_loglevel_mask(LOG_UNIMP)) {
2493 FILE *logfile = qemu_log_lock();
2494 target_ulong pc = s->pc_start, end = s->pc;
2496 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2497 for (; pc < end; ++pc) {
2498 qemu_log(" %02x", cpu_ldub_code(env, pc));
2500 qemu_log("\n");
2501 qemu_log_unlock(logfile);
2505 /* an interrupt is different from an exception because of the
2506 privilege checks */
2507 static void gen_interrupt(DisasContext *s, int intno,
2508 target_ulong cur_eip, target_ulong next_eip)
2510 gen_update_cc_op(s);
2511 gen_jmp_im(s, cur_eip);
2512 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2513 tcg_const_i32(next_eip - cur_eip));
2514 s->base.is_jmp = DISAS_NORETURN;
2517 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2519 gen_update_cc_op(s);
2520 gen_jmp_im(s, cur_eip);
2521 gen_helper_debug(cpu_env);
2522 s->base.is_jmp = DISAS_NORETURN;
2525 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2527 if ((s->flags & mask) == 0) {
2528 TCGv_i32 t = tcg_temp_new_i32();
2529 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2530 tcg_gen_ori_i32(t, t, mask);
2531 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2532 tcg_temp_free_i32(t);
2533 s->flags |= mask;
2537 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2539 if (s->flags & mask) {
2540 TCGv_i32 t = tcg_temp_new_i32();
2541 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2542 tcg_gen_andi_i32(t, t, ~mask);
2543 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2544 tcg_temp_free_i32(t);
2545 s->flags &= ~mask;
2549 /* Clear BND registers during legacy branches. */
2550 static void gen_bnd_jmp(DisasContext *s)
2552 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2553 and if the BNDREGs are known to be in use (non-zero) already.
2554 The helper itself will check BNDPRESERVE at runtime. */
2555 if ((s->prefix & PREFIX_REPNZ) == 0
2556 && (s->flags & HF_MPX_EN_MASK) != 0
2557 && (s->flags & HF_MPX_IU_MASK) != 0) {
2558 gen_helper_bnd_jmp(cpu_env);
2562 /* Generate an end of block. Trace exception is also generated if needed.
2563 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.
2564 If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
2565 S->TF. This is used by the syscall/sysret insns. */
2566 static void
2567 do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2569 gen_update_cc_op(s);
2571 /* If several instructions disable interrupts, only the first does it. */
2572 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2573 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2574 } else {
2575 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2578 if (s->base.tb->flags & HF_RF_MASK) {
2579 gen_helper_reset_rf(cpu_env);
2581 if (s->base.singlestep_enabled) {
2582 gen_helper_debug(cpu_env);
2583 } else if (recheck_tf) {
2584 gen_helper_rechecking_single_step(cpu_env);
2585 tcg_gen_exit_tb(NULL, 0);
2586 } else if (s->tf) {
2587 gen_helper_single_step(cpu_env);
2588 } else if (jr) {
2589 tcg_gen_lookup_and_goto_ptr();
2590 } else {
2591 tcg_gen_exit_tb(NULL, 0);
2593 s->base.is_jmp = DISAS_NORETURN;
2596 static inline void
2597 gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2599 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2602 /* End of block.
2603 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2604 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2606 gen_eob_worker(s, inhibit, false);
2609 /* End of block, resetting the inhibit irq flag. */
2610 static void gen_eob(DisasContext *s)
2612 gen_eob_worker(s, false, false);
2615 /* Jump to register */
2616 static void gen_jr(DisasContext *s, TCGv dest)
2618 do_gen_eob_worker(s, false, false, true);
2621 /* generate a jump to eip. No segment change must happen before as a
2622 direct call to the next block may occur */
2623 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2625 gen_update_cc_op(s);
2626 set_cc_op(s, CC_OP_DYNAMIC);
2627 if (s->jmp_opt) {
2628 gen_goto_tb(s, tb_num, eip);
2629 } else {
2630 gen_jmp_im(s, eip);
2631 gen_eob(s);
2635 static void gen_jmp(DisasContext *s, target_ulong eip)
2637 gen_jmp_tb(s, eip, 0);
2640 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2642 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2643 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset);
2646 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2648 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset);
2649 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2652 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2654 int mem_index = s->mem_index;
2655 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2656 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2657 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2658 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2659 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2662 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2664 int mem_index = s->mem_index;
2665 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2666 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2667 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2668 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2669 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2672 static inline void gen_op_movo(DisasContext *s, int d_offset, int s_offset)
2674 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2675 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2676 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2677 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2680 static inline void gen_op_movq(DisasContext *s, int d_offset, int s_offset)
2682 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset);
2683 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2686 static inline void gen_op_movl(DisasContext *s, int d_offset, int s_offset)
2688 tcg_gen_ld_i32(s->tmp2_i32, cpu_env, s_offset);
2689 tcg_gen_st_i32(s->tmp2_i32, cpu_env, d_offset);
2692 static inline void gen_op_movq_env_0(DisasContext *s, int d_offset)
2694 tcg_gen_movi_i64(s->tmp1_i64, 0);
2695 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2698 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2699 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2700 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2701 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2702 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2703 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2704 TCGv_i32 val);
2705 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2706 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2707 TCGv val);
2709 #define SSE_SPECIAL ((void *)1)
2710 #define SSE_DUMMY ((void *)2)
2712 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2713 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2714 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2716 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2717 /* 3DNow! extensions */
2718 [0x0e] = { SSE_DUMMY }, /* femms */
2719 [0x0f] = { SSE_DUMMY }, /* pf... */
2720 /* pure SSE operations */
2721 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2722 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2723 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2724 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2725 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2726 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2727 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2728 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2730 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2731 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2732 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2733 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2734 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2735 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2736 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2737 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2738 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2739 [0x51] = SSE_FOP(sqrt),
2740 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2741 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2742 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2743 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2744 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2745 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2746 [0x58] = SSE_FOP(add),
2747 [0x59] = SSE_FOP(mul),
2748 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2749 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2750 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2751 [0x5c] = SSE_FOP(sub),
2752 [0x5d] = SSE_FOP(min),
2753 [0x5e] = SSE_FOP(div),
2754 [0x5f] = SSE_FOP(max),
2756 [0xc2] = SSE_FOP(cmpeq),
2757 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2758 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2760 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2761 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2762 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2764 /* MMX ops and their SSE extensions */
2765 [0x60] = MMX_OP2(punpcklbw),
2766 [0x61] = MMX_OP2(punpcklwd),
2767 [0x62] = MMX_OP2(punpckldq),
2768 [0x63] = MMX_OP2(packsswb),
2769 [0x64] = MMX_OP2(pcmpgtb),
2770 [0x65] = MMX_OP2(pcmpgtw),
2771 [0x66] = MMX_OP2(pcmpgtl),
2772 [0x67] = MMX_OP2(packuswb),
2773 [0x68] = MMX_OP2(punpckhbw),
2774 [0x69] = MMX_OP2(punpckhwd),
2775 [0x6a] = MMX_OP2(punpckhdq),
2776 [0x6b] = MMX_OP2(packssdw),
2777 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2778 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2779 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2780 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2781 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2782 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2783 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2784 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2785 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2786 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2787 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2788 [0x74] = MMX_OP2(pcmpeqb),
2789 [0x75] = MMX_OP2(pcmpeqw),
2790 [0x76] = MMX_OP2(pcmpeql),
2791 [0x77] = { SSE_DUMMY }, /* emms */
2792 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2793 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2794 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2795 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2796 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2797 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2798 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2799 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2800 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2801 [0xd1] = MMX_OP2(psrlw),
2802 [0xd2] = MMX_OP2(psrld),
2803 [0xd3] = MMX_OP2(psrlq),
2804 [0xd4] = MMX_OP2(paddq),
2805 [0xd5] = MMX_OP2(pmullw),
2806 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2807 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2808 [0xd8] = MMX_OP2(psubusb),
2809 [0xd9] = MMX_OP2(psubusw),
2810 [0xda] = MMX_OP2(pminub),
2811 [0xdb] = MMX_OP2(pand),
2812 [0xdc] = MMX_OP2(paddusb),
2813 [0xdd] = MMX_OP2(paddusw),
2814 [0xde] = MMX_OP2(pmaxub),
2815 [0xdf] = MMX_OP2(pandn),
2816 [0xe0] = MMX_OP2(pavgb),
2817 [0xe1] = MMX_OP2(psraw),
2818 [0xe2] = MMX_OP2(psrad),
2819 [0xe3] = MMX_OP2(pavgw),
2820 [0xe4] = MMX_OP2(pmulhuw),
2821 [0xe5] = MMX_OP2(pmulhw),
2822 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2823 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2824 [0xe8] = MMX_OP2(psubsb),
2825 [0xe9] = MMX_OP2(psubsw),
2826 [0xea] = MMX_OP2(pminsw),
2827 [0xeb] = MMX_OP2(por),
2828 [0xec] = MMX_OP2(paddsb),
2829 [0xed] = MMX_OP2(paddsw),
2830 [0xee] = MMX_OP2(pmaxsw),
2831 [0xef] = MMX_OP2(pxor),
2832 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2833 [0xf1] = MMX_OP2(psllw),
2834 [0xf2] = MMX_OP2(pslld),
2835 [0xf3] = MMX_OP2(psllq),
2836 [0xf4] = MMX_OP2(pmuludq),
2837 [0xf5] = MMX_OP2(pmaddwd),
2838 [0xf6] = MMX_OP2(psadbw),
2839 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2840 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2841 [0xf8] = MMX_OP2(psubb),
2842 [0xf9] = MMX_OP2(psubw),
2843 [0xfa] = MMX_OP2(psubl),
2844 [0xfb] = MMX_OP2(psubq),
2845 [0xfc] = MMX_OP2(paddb),
2846 [0xfd] = MMX_OP2(paddw),
2847 [0xfe] = MMX_OP2(paddl),
2850 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2851 [0 + 2] = MMX_OP2(psrlw),
2852 [0 + 4] = MMX_OP2(psraw),
2853 [0 + 6] = MMX_OP2(psllw),
2854 [8 + 2] = MMX_OP2(psrld),
2855 [8 + 4] = MMX_OP2(psrad),
2856 [8 + 6] = MMX_OP2(pslld),
2857 [16 + 2] = MMX_OP2(psrlq),
2858 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2859 [16 + 6] = MMX_OP2(psllq),
2860 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2863 static const SSEFunc_0_epi sse_op_table3ai[] = {
2864 gen_helper_cvtsi2ss,
2865 gen_helper_cvtsi2sd
2868 #ifdef TARGET_X86_64
2869 static const SSEFunc_0_epl sse_op_table3aq[] = {
2870 gen_helper_cvtsq2ss,
2871 gen_helper_cvtsq2sd
2873 #endif
2875 static const SSEFunc_i_ep sse_op_table3bi[] = {
2876 gen_helper_cvttss2si,
2877 gen_helper_cvtss2si,
2878 gen_helper_cvttsd2si,
2879 gen_helper_cvtsd2si
2882 #ifdef TARGET_X86_64
2883 static const SSEFunc_l_ep sse_op_table3bq[] = {
2884 gen_helper_cvttss2sq,
2885 gen_helper_cvtss2sq,
2886 gen_helper_cvttsd2sq,
2887 gen_helper_cvtsd2sq
2889 #endif
2891 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2892 SSE_FOP(cmpeq),
2893 SSE_FOP(cmplt),
2894 SSE_FOP(cmple),
2895 SSE_FOP(cmpunord),
2896 SSE_FOP(cmpneq),
2897 SSE_FOP(cmpnlt),
2898 SSE_FOP(cmpnle),
2899 SSE_FOP(cmpord),
2902 static const SSEFunc_0_epp sse_op_table5[256] = {
2903 [0x0c] = gen_helper_pi2fw,
2904 [0x0d] = gen_helper_pi2fd,
2905 [0x1c] = gen_helper_pf2iw,
2906 [0x1d] = gen_helper_pf2id,
2907 [0x8a] = gen_helper_pfnacc,
2908 [0x8e] = gen_helper_pfpnacc,
2909 [0x90] = gen_helper_pfcmpge,
2910 [0x94] = gen_helper_pfmin,
2911 [0x96] = gen_helper_pfrcp,
2912 [0x97] = gen_helper_pfrsqrt,
2913 [0x9a] = gen_helper_pfsub,
2914 [0x9e] = gen_helper_pfadd,
2915 [0xa0] = gen_helper_pfcmpgt,
2916 [0xa4] = gen_helper_pfmax,
2917 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2918 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2919 [0xaa] = gen_helper_pfsubr,
2920 [0xae] = gen_helper_pfacc,
2921 [0xb0] = gen_helper_pfcmpeq,
2922 [0xb4] = gen_helper_pfmul,
2923 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2924 [0xb7] = gen_helper_pmulhrw_mmx,
2925 [0xbb] = gen_helper_pswapd,
2926 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
2929 struct SSEOpHelper_epp {
2930 SSEFunc_0_epp op[2];
2931 uint32_t ext_mask;
2934 struct SSEOpHelper_eppi {
2935 SSEFunc_0_eppi op[2];
2936 uint32_t ext_mask;
2939 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2940 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2941 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
2942 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
2943 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2944 CPUID_EXT_PCLMULQDQ }
2945 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
2947 static const struct SSEOpHelper_epp sse_op_table6[256] = {
2948 [0x00] = SSSE3_OP(pshufb),
2949 [0x01] = SSSE3_OP(phaddw),
2950 [0x02] = SSSE3_OP(phaddd),
2951 [0x03] = SSSE3_OP(phaddsw),
2952 [0x04] = SSSE3_OP(pmaddubsw),
2953 [0x05] = SSSE3_OP(phsubw),
2954 [0x06] = SSSE3_OP(phsubd),
2955 [0x07] = SSSE3_OP(phsubsw),
2956 [0x08] = SSSE3_OP(psignb),
2957 [0x09] = SSSE3_OP(psignw),
2958 [0x0a] = SSSE3_OP(psignd),
2959 [0x0b] = SSSE3_OP(pmulhrsw),
2960 [0x10] = SSE41_OP(pblendvb),
2961 [0x14] = SSE41_OP(blendvps),
2962 [0x15] = SSE41_OP(blendvpd),
2963 [0x17] = SSE41_OP(ptest),
2964 [0x1c] = SSSE3_OP(pabsb),
2965 [0x1d] = SSSE3_OP(pabsw),
2966 [0x1e] = SSSE3_OP(pabsd),
2967 [0x20] = SSE41_OP(pmovsxbw),
2968 [0x21] = SSE41_OP(pmovsxbd),
2969 [0x22] = SSE41_OP(pmovsxbq),
2970 [0x23] = SSE41_OP(pmovsxwd),
2971 [0x24] = SSE41_OP(pmovsxwq),
2972 [0x25] = SSE41_OP(pmovsxdq),
2973 [0x28] = SSE41_OP(pmuldq),
2974 [0x29] = SSE41_OP(pcmpeqq),
2975 [0x2a] = SSE41_SPECIAL, /* movntqda */
2976 [0x2b] = SSE41_OP(packusdw),
2977 [0x30] = SSE41_OP(pmovzxbw),
2978 [0x31] = SSE41_OP(pmovzxbd),
2979 [0x32] = SSE41_OP(pmovzxbq),
2980 [0x33] = SSE41_OP(pmovzxwd),
2981 [0x34] = SSE41_OP(pmovzxwq),
2982 [0x35] = SSE41_OP(pmovzxdq),
2983 [0x37] = SSE42_OP(pcmpgtq),
2984 [0x38] = SSE41_OP(pminsb),
2985 [0x39] = SSE41_OP(pminsd),
2986 [0x3a] = SSE41_OP(pminuw),
2987 [0x3b] = SSE41_OP(pminud),
2988 [0x3c] = SSE41_OP(pmaxsb),
2989 [0x3d] = SSE41_OP(pmaxsd),
2990 [0x3e] = SSE41_OP(pmaxuw),
2991 [0x3f] = SSE41_OP(pmaxud),
2992 [0x40] = SSE41_OP(pmulld),
2993 [0x41] = SSE41_OP(phminposuw),
2994 [0xdb] = AESNI_OP(aesimc),
2995 [0xdc] = AESNI_OP(aesenc),
2996 [0xdd] = AESNI_OP(aesenclast),
2997 [0xde] = AESNI_OP(aesdec),
2998 [0xdf] = AESNI_OP(aesdeclast),
3001 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
3002 [0x08] = SSE41_OP(roundps),
3003 [0x09] = SSE41_OP(roundpd),
3004 [0x0a] = SSE41_OP(roundss),
3005 [0x0b] = SSE41_OP(roundsd),
3006 [0x0c] = SSE41_OP(blendps),
3007 [0x0d] = SSE41_OP(blendpd),
3008 [0x0e] = SSE41_OP(pblendw),
3009 [0x0f] = SSSE3_OP(palignr),
3010 [0x14] = SSE41_SPECIAL, /* pextrb */
3011 [0x15] = SSE41_SPECIAL, /* pextrw */
3012 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3013 [0x17] = SSE41_SPECIAL, /* extractps */
3014 [0x20] = SSE41_SPECIAL, /* pinsrb */
3015 [0x21] = SSE41_SPECIAL, /* insertps */
3016 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3017 [0x40] = SSE41_OP(dpps),
3018 [0x41] = SSE41_OP(dppd),
3019 [0x42] = SSE41_OP(mpsadbw),
3020 [0x44] = PCLMULQDQ_OP(pclmulqdq),
3021 [0x60] = SSE42_OP(pcmpestrm),
3022 [0x61] = SSE42_OP(pcmpestri),
3023 [0x62] = SSE42_OP(pcmpistrm),
3024 [0x63] = SSE42_OP(pcmpistri),
3025 [0xdf] = AESNI_OP(aeskeygenassist),
3028 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3029 target_ulong pc_start, int rex_r)
3031 int b1, op1_offset, op2_offset, is_xmm, val;
3032 int modrm, mod, rm, reg;
3033 SSEFunc_0_epp sse_fn_epp;
3034 SSEFunc_0_eppi sse_fn_eppi;
3035 SSEFunc_0_ppi sse_fn_ppi;
3036 SSEFunc_0_eppt sse_fn_eppt;
3037 MemOp ot;
3039 b &= 0xff;
3040 if (s->prefix & PREFIX_DATA)
3041 b1 = 1;
3042 else if (s->prefix & PREFIX_REPZ)
3043 b1 = 2;
3044 else if (s->prefix & PREFIX_REPNZ)
3045 b1 = 3;
3046 else
3047 b1 = 0;
3048 sse_fn_epp = sse_op_table1[b][b1];
3049 if (!sse_fn_epp) {
3050 goto unknown_op;
3052 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3053 is_xmm = 1;
3054 } else {
3055 if (b1 == 0) {
3056 /* MMX case */
3057 is_xmm = 0;
3058 } else {
3059 is_xmm = 1;
3062 /* simple MMX/SSE operation */
3063 if (s->flags & HF_TS_MASK) {
3064 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3065 return;
3067 if (s->flags & HF_EM_MASK) {
3068 illegal_op:
3069 gen_illegal_opcode(s);
3070 return;
3072 if (is_xmm
3073 && !(s->flags & HF_OSFXSR_MASK)
3074 && ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
3075 goto unknown_op;
3077 if (b == 0x0e) {
3078 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3079 /* If we were fully decoding this we might use illegal_op. */
3080 goto unknown_op;
3082 /* femms */
3083 gen_helper_emms(cpu_env);
3084 return;
3086 if (b == 0x77) {
3087 /* emms */
3088 gen_helper_emms(cpu_env);
3089 return;
3091 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3092 the static cpu state) */
3093 if (!is_xmm) {
3094 gen_helper_enter_mmx(cpu_env);
3097 modrm = x86_ldub_code(env, s);
3098 reg = ((modrm >> 3) & 7);
3099 if (is_xmm)
3100 reg |= rex_r;
3101 mod = (modrm >> 6) & 3;
3102 if (sse_fn_epp == SSE_SPECIAL) {
3103 b |= (b1 << 8);
3104 switch(b) {
3105 case 0x0e7: /* movntq */
3106 if (mod == 3) {
3107 goto illegal_op;
3109 gen_lea_modrm(env, s, modrm);
3110 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3111 break;
3112 case 0x1e7: /* movntdq */
3113 case 0x02b: /* movntps */
3114 case 0x12b: /* movntps */
3115 if (mod == 3)
3116 goto illegal_op;
3117 gen_lea_modrm(env, s, modrm);
3118 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3119 break;
3120 case 0x3f0: /* lddqu */
3121 if (mod == 3)
3122 goto illegal_op;
3123 gen_lea_modrm(env, s, modrm);
3124 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3125 break;
3126 case 0x22b: /* movntss */
3127 case 0x32b: /* movntsd */
3128 if (mod == 3)
3129 goto illegal_op;
3130 gen_lea_modrm(env, s, modrm);
3131 if (b1 & 1) {
3132 gen_stq_env_A0(s, offsetof(CPUX86State,
3133 xmm_regs[reg].ZMM_Q(0)));
3134 } else {
3135 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
3136 xmm_regs[reg].ZMM_L(0)));
3137 gen_op_st_v(s, MO_32, s->T0, s->A0);
3139 break;
3140 case 0x6e: /* movd mm, ea */
3141 #ifdef TARGET_X86_64
3142 if (s->dflag == MO_64) {
3143 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3144 tcg_gen_st_tl(s->T0, cpu_env,
3145 offsetof(CPUX86State, fpregs[reg].mmx));
3146 } else
3147 #endif
3149 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3150 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3151 offsetof(CPUX86State,fpregs[reg].mmx));
3152 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3153 gen_helper_movl_mm_T0_mmx(s->ptr0, s->tmp2_i32);
3155 break;
3156 case 0x16e: /* movd xmm, ea */
3157 #ifdef TARGET_X86_64
3158 if (s->dflag == MO_64) {
3159 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3160 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3161 offsetof(CPUX86State,xmm_regs[reg]));
3162 gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0);
3163 } else
3164 #endif
3166 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3167 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3168 offsetof(CPUX86State,xmm_regs[reg]));
3169 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3170 gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32);
3172 break;
3173 case 0x6f: /* movq mm, ea */
3174 if (mod != 3) {
3175 gen_lea_modrm(env, s, modrm);
3176 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3177 } else {
3178 rm = (modrm & 7);
3179 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
3180 offsetof(CPUX86State,fpregs[rm].mmx));
3181 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
3182 offsetof(CPUX86State,fpregs[reg].mmx));
3184 break;
3185 case 0x010: /* movups */
3186 case 0x110: /* movupd */
3187 case 0x028: /* movaps */
3188 case 0x128: /* movapd */
3189 case 0x16f: /* movdqa xmm, ea */
3190 case 0x26f: /* movdqu xmm, ea */
3191 if (mod != 3) {
3192 gen_lea_modrm(env, s, modrm);
3193 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3194 } else {
3195 rm = (modrm & 7) | REX_B(s);
3196 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[reg]),
3197 offsetof(CPUX86State,xmm_regs[rm]));
3199 break;
3200 case 0x210: /* movss xmm, ea */
3201 if (mod != 3) {
3202 gen_lea_modrm(env, s, modrm);
3203 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3204 tcg_gen_st32_tl(s->T0, cpu_env,
3205 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3206 tcg_gen_movi_tl(s->T0, 0);
3207 tcg_gen_st32_tl(s->T0, cpu_env,
3208 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)));
3209 tcg_gen_st32_tl(s->T0, cpu_env,
3210 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3211 tcg_gen_st32_tl(s->T0, cpu_env,
3212 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3213 } else {
3214 rm = (modrm & 7) | REX_B(s);
3215 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3216 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3218 break;
3219 case 0x310: /* movsd xmm, ea */
3220 if (mod != 3) {
3221 gen_lea_modrm(env, s, modrm);
3222 gen_ldq_env_A0(s, offsetof(CPUX86State,
3223 xmm_regs[reg].ZMM_Q(0)));
3224 tcg_gen_movi_tl(s->T0, 0);
3225 tcg_gen_st32_tl(s->T0, cpu_env,
3226 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3227 tcg_gen_st32_tl(s->T0, cpu_env,
3228 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3229 } else {
3230 rm = (modrm & 7) | REX_B(s);
3231 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3232 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3234 break;
3235 case 0x012: /* movlps */
3236 case 0x112: /* movlpd */
3237 if (mod != 3) {
3238 gen_lea_modrm(env, s, modrm);
3239 gen_ldq_env_A0(s, offsetof(CPUX86State,
3240 xmm_regs[reg].ZMM_Q(0)));
3241 } else {
3242 /* movhlps */
3243 rm = (modrm & 7) | REX_B(s);
3244 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3245 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3247 break;
3248 case 0x212: /* movsldup */
3249 if (mod != 3) {
3250 gen_lea_modrm(env, s, modrm);
3251 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3252 } else {
3253 rm = (modrm & 7) | REX_B(s);
3254 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3255 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3256 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3257 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3259 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3260 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3261 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3262 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3263 break;
3264 case 0x312: /* movddup */
3265 if (mod != 3) {
3266 gen_lea_modrm(env, s, modrm);
3267 gen_ldq_env_A0(s, offsetof(CPUX86State,
3268 xmm_regs[reg].ZMM_Q(0)));
3269 } else {
3270 rm = (modrm & 7) | REX_B(s);
3271 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3272 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3274 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3275 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3276 break;
3277 case 0x016: /* movhps */
3278 case 0x116: /* movhpd */
3279 if (mod != 3) {
3280 gen_lea_modrm(env, s, modrm);
3281 gen_ldq_env_A0(s, offsetof(CPUX86State,
3282 xmm_regs[reg].ZMM_Q(1)));
3283 } else {
3284 /* movlhps */
3285 rm = (modrm & 7) | REX_B(s);
3286 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3287 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3289 break;
3290 case 0x216: /* movshdup */
3291 if (mod != 3) {
3292 gen_lea_modrm(env, s, modrm);
3293 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3294 } else {
3295 rm = (modrm & 7) | REX_B(s);
3296 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3297 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3298 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3299 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3301 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3302 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3303 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3304 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3305 break;
3306 case 0x178:
3307 case 0x378:
3309 int bit_index, field_length;
3311 if (b1 == 1 && reg != 0)
3312 goto illegal_op;
3313 field_length = x86_ldub_code(env, s) & 0x3F;
3314 bit_index = x86_ldub_code(env, s) & 0x3F;
3315 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3316 offsetof(CPUX86State,xmm_regs[reg]));
3317 if (b1 == 1)
3318 gen_helper_extrq_i(cpu_env, s->ptr0,
3319 tcg_const_i32(bit_index),
3320 tcg_const_i32(field_length));
3321 else
3322 gen_helper_insertq_i(cpu_env, s->ptr0,
3323 tcg_const_i32(bit_index),
3324 tcg_const_i32(field_length));
3326 break;
3327 case 0x7e: /* movd ea, mm */
3328 #ifdef TARGET_X86_64
3329 if (s->dflag == MO_64) {
3330 tcg_gen_ld_i64(s->T0, cpu_env,
3331 offsetof(CPUX86State,fpregs[reg].mmx));
3332 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3333 } else
3334 #endif
3336 tcg_gen_ld32u_tl(s->T0, cpu_env,
3337 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3338 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3340 break;
3341 case 0x17e: /* movd ea, xmm */
3342 #ifdef TARGET_X86_64
3343 if (s->dflag == MO_64) {
3344 tcg_gen_ld_i64(s->T0, cpu_env,
3345 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3346 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3347 } else
3348 #endif
3350 tcg_gen_ld32u_tl(s->T0, cpu_env,
3351 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3352 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3354 break;
3355 case 0x27e: /* movq xmm, ea */
3356 if (mod != 3) {
3357 gen_lea_modrm(env, s, modrm);
3358 gen_ldq_env_A0(s, offsetof(CPUX86State,
3359 xmm_regs[reg].ZMM_Q(0)));
3360 } else {
3361 rm = (modrm & 7) | REX_B(s);
3362 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3363 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3365 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3366 break;
3367 case 0x7f: /* movq ea, mm */
3368 if (mod != 3) {
3369 gen_lea_modrm(env, s, modrm);
3370 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3371 } else {
3372 rm = (modrm & 7);
3373 gen_op_movq(s, offsetof(CPUX86State, fpregs[rm].mmx),
3374 offsetof(CPUX86State,fpregs[reg].mmx));
3376 break;
3377 case 0x011: /* movups */
3378 case 0x111: /* movupd */
3379 case 0x029: /* movaps */
3380 case 0x129: /* movapd */
3381 case 0x17f: /* movdqa ea, xmm */
3382 case 0x27f: /* movdqu ea, xmm */
3383 if (mod != 3) {
3384 gen_lea_modrm(env, s, modrm);
3385 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3386 } else {
3387 rm = (modrm & 7) | REX_B(s);
3388 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[rm]),
3389 offsetof(CPUX86State,xmm_regs[reg]));
3391 break;
3392 case 0x211: /* movss ea, xmm */
3393 if (mod != 3) {
3394 gen_lea_modrm(env, s, modrm);
3395 tcg_gen_ld32u_tl(s->T0, cpu_env,
3396 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3397 gen_op_st_v(s, MO_32, s->T0, s->A0);
3398 } else {
3399 rm = (modrm & 7) | REX_B(s);
3400 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0)),
3401 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3403 break;
3404 case 0x311: /* movsd ea, xmm */
3405 if (mod != 3) {
3406 gen_lea_modrm(env, s, modrm);
3407 gen_stq_env_A0(s, offsetof(CPUX86State,
3408 xmm_regs[reg].ZMM_Q(0)));
3409 } else {
3410 rm = (modrm & 7) | REX_B(s);
3411 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3412 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3414 break;
3415 case 0x013: /* movlps */
3416 case 0x113: /* movlpd */
3417 if (mod != 3) {
3418 gen_lea_modrm(env, s, modrm);
3419 gen_stq_env_A0(s, offsetof(CPUX86State,
3420 xmm_regs[reg].ZMM_Q(0)));
3421 } else {
3422 goto illegal_op;
3424 break;
3425 case 0x017: /* movhps */
3426 case 0x117: /* movhpd */
3427 if (mod != 3) {
3428 gen_lea_modrm(env, s, modrm);
3429 gen_stq_env_A0(s, offsetof(CPUX86State,
3430 xmm_regs[reg].ZMM_Q(1)));
3431 } else {
3432 goto illegal_op;
3434 break;
3435 case 0x71: /* shift mm, im */
3436 case 0x72:
3437 case 0x73:
3438 case 0x171: /* shift xmm, im */
3439 case 0x172:
3440 case 0x173:
3441 if (b1 >= 2) {
3442 goto unknown_op;
3444 val = x86_ldub_code(env, s);
3445 if (is_xmm) {
3446 tcg_gen_movi_tl(s->T0, val);
3447 tcg_gen_st32_tl(s->T0, cpu_env,
3448 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3449 tcg_gen_movi_tl(s->T0, 0);
3450 tcg_gen_st32_tl(s->T0, cpu_env,
3451 offsetof(CPUX86State, xmm_t0.ZMM_L(1)));
3452 op1_offset = offsetof(CPUX86State,xmm_t0);
3453 } else {
3454 tcg_gen_movi_tl(s->T0, val);
3455 tcg_gen_st32_tl(s->T0, cpu_env,
3456 offsetof(CPUX86State, mmx_t0.MMX_L(0)));
3457 tcg_gen_movi_tl(s->T0, 0);
3458 tcg_gen_st32_tl(s->T0, cpu_env,
3459 offsetof(CPUX86State, mmx_t0.MMX_L(1)));
3460 op1_offset = offsetof(CPUX86State,mmx_t0);
3462 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3463 (((modrm >> 3)) & 7)][b1];
3464 if (!sse_fn_epp) {
3465 goto unknown_op;
3467 if (is_xmm) {
3468 rm = (modrm & 7) | REX_B(s);
3469 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3470 } else {
3471 rm = (modrm & 7);
3472 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3474 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3475 tcg_gen_addi_ptr(s->ptr1, cpu_env, op1_offset);
3476 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3477 break;
3478 case 0x050: /* movmskps */
3479 rm = (modrm & 7) | REX_B(s);
3480 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3481 offsetof(CPUX86State,xmm_regs[rm]));
3482 gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0);
3483 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3484 break;
3485 case 0x150: /* movmskpd */
3486 rm = (modrm & 7) | REX_B(s);
3487 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3488 offsetof(CPUX86State,xmm_regs[rm]));
3489 gen_helper_movmskpd(s->tmp2_i32, cpu_env, s->ptr0);
3490 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3491 break;
3492 case 0x02a: /* cvtpi2ps */
3493 case 0x12a: /* cvtpi2pd */
3494 gen_helper_enter_mmx(cpu_env);
3495 if (mod != 3) {
3496 gen_lea_modrm(env, s, modrm);
3497 op2_offset = offsetof(CPUX86State,mmx_t0);
3498 gen_ldq_env_A0(s, op2_offset);
3499 } else {
3500 rm = (modrm & 7);
3501 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3503 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3504 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3505 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3506 switch(b >> 8) {
3507 case 0x0:
3508 gen_helper_cvtpi2ps(cpu_env, s->ptr0, s->ptr1);
3509 break;
3510 default:
3511 case 0x1:
3512 gen_helper_cvtpi2pd(cpu_env, s->ptr0, s->ptr1);
3513 break;
3515 break;
3516 case 0x22a: /* cvtsi2ss */
3517 case 0x32a: /* cvtsi2sd */
3518 ot = mo_64_32(s->dflag);
3519 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3520 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3521 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3522 if (ot == MO_32) {
3523 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3524 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3525 sse_fn_epi(cpu_env, s->ptr0, s->tmp2_i32);
3526 } else {
3527 #ifdef TARGET_X86_64
3528 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3529 sse_fn_epl(cpu_env, s->ptr0, s->T0);
3530 #else
3531 goto illegal_op;
3532 #endif
3534 break;
3535 case 0x02c: /* cvttps2pi */
3536 case 0x12c: /* cvttpd2pi */
3537 case 0x02d: /* cvtps2pi */
3538 case 0x12d: /* cvtpd2pi */
3539 gen_helper_enter_mmx(cpu_env);
3540 if (mod != 3) {
3541 gen_lea_modrm(env, s, modrm);
3542 op2_offset = offsetof(CPUX86State,xmm_t0);
3543 gen_ldo_env_A0(s, op2_offset);
3544 } else {
3545 rm = (modrm & 7) | REX_B(s);
3546 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3548 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3549 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3550 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3551 switch(b) {
3552 case 0x02c:
3553 gen_helper_cvttps2pi(cpu_env, s->ptr0, s->ptr1);
3554 break;
3555 case 0x12c:
3556 gen_helper_cvttpd2pi(cpu_env, s->ptr0, s->ptr1);
3557 break;
3558 case 0x02d:
3559 gen_helper_cvtps2pi(cpu_env, s->ptr0, s->ptr1);
3560 break;
3561 case 0x12d:
3562 gen_helper_cvtpd2pi(cpu_env, s->ptr0, s->ptr1);
3563 break;
3565 break;
3566 case 0x22c: /* cvttss2si */
3567 case 0x32c: /* cvttsd2si */
3568 case 0x22d: /* cvtss2si */
3569 case 0x32d: /* cvtsd2si */
3570 ot = mo_64_32(s->dflag);
3571 if (mod != 3) {
3572 gen_lea_modrm(env, s, modrm);
3573 if ((b >> 8) & 1) {
3574 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3575 } else {
3576 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3577 tcg_gen_st32_tl(s->T0, cpu_env,
3578 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3580 op2_offset = offsetof(CPUX86State,xmm_t0);
3581 } else {
3582 rm = (modrm & 7) | REX_B(s);
3583 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3585 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3586 if (ot == MO_32) {
3587 SSEFunc_i_ep sse_fn_i_ep =
3588 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3589 sse_fn_i_ep(s->tmp2_i32, cpu_env, s->ptr0);
3590 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
3591 } else {
3592 #ifdef TARGET_X86_64
3593 SSEFunc_l_ep sse_fn_l_ep =
3594 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3595 sse_fn_l_ep(s->T0, cpu_env, s->ptr0);
3596 #else
3597 goto illegal_op;
3598 #endif
3600 gen_op_mov_reg_v(s, ot, reg, s->T0);
3601 break;
3602 case 0xc4: /* pinsrw */
3603 case 0x1c4:
3604 s->rip_offset = 1;
3605 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3606 val = x86_ldub_code(env, s);
3607 if (b1) {
3608 val &= 7;
3609 tcg_gen_st16_tl(s->T0, cpu_env,
3610 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3611 } else {
3612 val &= 3;
3613 tcg_gen_st16_tl(s->T0, cpu_env,
3614 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3616 break;
3617 case 0xc5: /* pextrw */
3618 case 0x1c5:
3619 if (mod != 3)
3620 goto illegal_op;
3621 ot = mo_64_32(s->dflag);
3622 val = x86_ldub_code(env, s);
3623 if (b1) {
3624 val &= 7;
3625 rm = (modrm & 7) | REX_B(s);
3626 tcg_gen_ld16u_tl(s->T0, cpu_env,
3627 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3628 } else {
3629 val &= 3;
3630 rm = (modrm & 7);
3631 tcg_gen_ld16u_tl(s->T0, cpu_env,
3632 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3634 reg = ((modrm >> 3) & 7) | rex_r;
3635 gen_op_mov_reg_v(s, ot, reg, s->T0);
3636 break;
3637 case 0x1d6: /* movq ea, xmm */
3638 if (mod != 3) {
3639 gen_lea_modrm(env, s, modrm);
3640 gen_stq_env_A0(s, offsetof(CPUX86State,
3641 xmm_regs[reg].ZMM_Q(0)));
3642 } else {
3643 rm = (modrm & 7) | REX_B(s);
3644 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3645 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3646 gen_op_movq_env_0(s,
3647 offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(1)));
3649 break;
3650 case 0x2d6: /* movq2dq */
3651 gen_helper_enter_mmx(cpu_env);
3652 rm = (modrm & 7);
3653 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3654 offsetof(CPUX86State,fpregs[rm].mmx));
3655 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3656 break;
3657 case 0x3d6: /* movdq2q */
3658 gen_helper_enter_mmx(cpu_env);
3659 rm = (modrm & 7) | REX_B(s);
3660 gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx),
3661 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3662 break;
3663 case 0xd7: /* pmovmskb */
3664 case 0x1d7:
3665 if (mod != 3)
3666 goto illegal_op;
3667 if (b1) {
3668 rm = (modrm & 7) | REX_B(s);
3669 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3670 offsetof(CPUX86State, xmm_regs[rm]));
3671 gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0);
3672 } else {
3673 rm = (modrm & 7);
3674 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3675 offsetof(CPUX86State, fpregs[rm].mmx));
3676 gen_helper_pmovmskb_mmx(s->tmp2_i32, cpu_env, s->ptr0);
3678 reg = ((modrm >> 3) & 7) | rex_r;
3679 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3680 break;
3682 case 0x138:
3683 case 0x038:
3684 b = modrm;
3685 if ((b & 0xf0) == 0xf0) {
3686 goto do_0f_38_fx;
3688 modrm = x86_ldub_code(env, s);
3689 rm = modrm & 7;
3690 reg = ((modrm >> 3) & 7) | rex_r;
3691 mod = (modrm >> 6) & 3;
3692 if (b1 >= 2) {
3693 goto unknown_op;
3696 sse_fn_epp = sse_op_table6[b].op[b1];
3697 if (!sse_fn_epp) {
3698 goto unknown_op;
3700 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3701 goto illegal_op;
3703 if (b1) {
3704 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3705 if (mod == 3) {
3706 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3707 } else {
3708 op2_offset = offsetof(CPUX86State,xmm_t0);
3709 gen_lea_modrm(env, s, modrm);
3710 switch (b) {
3711 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3712 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3713 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3714 gen_ldq_env_A0(s, op2_offset +
3715 offsetof(ZMMReg, ZMM_Q(0)));
3716 break;
3717 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3718 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3719 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
3720 s->mem_index, MO_LEUL);
3721 tcg_gen_st_i32(s->tmp2_i32, cpu_env, op2_offset +
3722 offsetof(ZMMReg, ZMM_L(0)));
3723 break;
3724 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3725 tcg_gen_qemu_ld_tl(s->tmp0, s->A0,
3726 s->mem_index, MO_LEUW);
3727 tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset +
3728 offsetof(ZMMReg, ZMM_W(0)));
3729 break;
3730 case 0x2a: /* movntqda */
3731 gen_ldo_env_A0(s, op1_offset);
3732 return;
3733 default:
3734 gen_ldo_env_A0(s, op2_offset);
3737 } else {
3738 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3739 if (mod == 3) {
3740 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3741 } else {
3742 op2_offset = offsetof(CPUX86State,mmx_t0);
3743 gen_lea_modrm(env, s, modrm);
3744 gen_ldq_env_A0(s, op2_offset);
3747 if (sse_fn_epp == SSE_SPECIAL) {
3748 goto unknown_op;
3751 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3752 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3753 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3755 if (b == 0x17) {
3756 set_cc_op(s, CC_OP_EFLAGS);
3758 break;
3760 case 0x238:
3761 case 0x338:
3762 do_0f_38_fx:
3763 /* Various integer extensions at 0f 38 f[0-f]. */
3764 b = modrm | (b1 << 8);
3765 modrm = x86_ldub_code(env, s);
3766 reg = ((modrm >> 3) & 7) | rex_r;
3768 switch (b) {
3769 case 0x3f0: /* crc32 Gd,Eb */
3770 case 0x3f1: /* crc32 Gd,Ey */
3771 do_crc32:
3772 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3773 goto illegal_op;
3775 if ((b & 0xff) == 0xf0) {
3776 ot = MO_8;
3777 } else if (s->dflag != MO_64) {
3778 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3779 } else {
3780 ot = MO_64;
3783 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[reg]);
3784 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3785 gen_helper_crc32(s->T0, s->tmp2_i32,
3786 s->T0, tcg_const_i32(8 << ot));
3788 ot = mo_64_32(s->dflag);
3789 gen_op_mov_reg_v(s, ot, reg, s->T0);
3790 break;
3792 case 0x1f0: /* crc32 or movbe */
3793 case 0x1f1:
3794 /* For these insns, the f3 prefix is supposed to have priority
3795 over the 66 prefix, but that's not what we implement above
3796 setting b1. */
3797 if (s->prefix & PREFIX_REPNZ) {
3798 goto do_crc32;
3800 /* FALLTHRU */
3801 case 0x0f0: /* movbe Gy,My */
3802 case 0x0f1: /* movbe My,Gy */
3803 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3804 goto illegal_op;
3806 if (s->dflag != MO_64) {
3807 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3808 } else {
3809 ot = MO_64;
3812 gen_lea_modrm(env, s, modrm);
3813 if ((b & 1) == 0) {
3814 tcg_gen_qemu_ld_tl(s->T0, s->A0,
3815 s->mem_index, ot | MO_BE);
3816 gen_op_mov_reg_v(s, ot, reg, s->T0);
3817 } else {
3818 tcg_gen_qemu_st_tl(cpu_regs[reg], s->A0,
3819 s->mem_index, ot | MO_BE);
3821 break;
3823 case 0x0f2: /* andn Gy, By, Ey */
3824 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3825 || !(s->prefix & PREFIX_VEX)
3826 || s->vex_l != 0) {
3827 goto illegal_op;
3829 ot = mo_64_32(s->dflag);
3830 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3831 tcg_gen_andc_tl(s->T0, s->T0, cpu_regs[s->vex_v]);
3832 gen_op_mov_reg_v(s, ot, reg, s->T0);
3833 gen_op_update1_cc(s);
3834 set_cc_op(s, CC_OP_LOGICB + ot);
3835 break;
3837 case 0x0f7: /* bextr Gy, Ey, By */
3838 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3839 || !(s->prefix & PREFIX_VEX)
3840 || s->vex_l != 0) {
3841 goto illegal_op;
3843 ot = mo_64_32(s->dflag);
3845 TCGv bound, zero;
3847 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3848 /* Extract START, and shift the operand.
3849 Shifts larger than operand size get zeros. */
3850 tcg_gen_ext8u_tl(s->A0, cpu_regs[s->vex_v]);
3851 tcg_gen_shr_tl(s->T0, s->T0, s->A0);
3853 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3854 zero = tcg_const_tl(0);
3855 tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound,
3856 s->T0, zero);
3857 tcg_temp_free(zero);
3859 /* Extract the LEN into a mask. Lengths larger than
3860 operand size get all ones. */
3861 tcg_gen_extract_tl(s->A0, cpu_regs[s->vex_v], 8, 8);
3862 tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound,
3863 s->A0, bound);
3864 tcg_temp_free(bound);
3865 tcg_gen_movi_tl(s->T1, 1);
3866 tcg_gen_shl_tl(s->T1, s->T1, s->A0);
3867 tcg_gen_subi_tl(s->T1, s->T1, 1);
3868 tcg_gen_and_tl(s->T0, s->T0, s->T1);
3870 gen_op_mov_reg_v(s, ot, reg, s->T0);
3871 gen_op_update1_cc(s);
3872 set_cc_op(s, CC_OP_LOGICB + ot);
3874 break;
3876 case 0x0f5: /* bzhi Gy, Ey, By */
3877 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3878 || !(s->prefix & PREFIX_VEX)
3879 || s->vex_l != 0) {
3880 goto illegal_op;
3882 ot = mo_64_32(s->dflag);
3883 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3884 tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]);
3886 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3887 /* Note that since we're using BMILG (in order to get O
3888 cleared) we need to store the inverse into C. */
3889 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3890 s->T1, bound);
3891 tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1,
3892 bound, bound, s->T1);
3893 tcg_temp_free(bound);
3895 tcg_gen_movi_tl(s->A0, -1);
3896 tcg_gen_shl_tl(s->A0, s->A0, s->T1);
3897 tcg_gen_andc_tl(s->T0, s->T0, s->A0);
3898 gen_op_mov_reg_v(s, ot, reg, s->T0);
3899 gen_op_update1_cc(s);
3900 set_cc_op(s, CC_OP_BMILGB + ot);
3901 break;
3903 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3904 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3905 || !(s->prefix & PREFIX_VEX)
3906 || s->vex_l != 0) {
3907 goto illegal_op;
3909 ot = mo_64_32(s->dflag);
3910 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3911 switch (ot) {
3912 default:
3913 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3914 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EDX]);
3915 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
3916 s->tmp2_i32, s->tmp3_i32);
3917 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32);
3918 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp3_i32);
3919 break;
3920 #ifdef TARGET_X86_64
3921 case MO_64:
3922 tcg_gen_mulu2_i64(s->T0, s->T1,
3923 s->T0, cpu_regs[R_EDX]);
3924 tcg_gen_mov_i64(cpu_regs[s->vex_v], s->T0);
3925 tcg_gen_mov_i64(cpu_regs[reg], s->T1);
3926 break;
3927 #endif
3929 break;
3931 case 0x3f5: /* pdep Gy, By, Ey */
3932 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3933 || !(s->prefix & PREFIX_VEX)
3934 || s->vex_l != 0) {
3935 goto illegal_op;
3937 ot = mo_64_32(s->dflag);
3938 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3939 /* Note that by zero-extending the mask operand, we
3940 automatically handle zero-extending the result. */
3941 if (ot == MO_64) {
3942 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
3943 } else {
3944 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
3946 gen_helper_pdep(cpu_regs[reg], s->T0, s->T1);
3947 break;
3949 case 0x2f5: /* pext Gy, By, Ey */
3950 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3951 || !(s->prefix & PREFIX_VEX)
3952 || s->vex_l != 0) {
3953 goto illegal_op;
3955 ot = mo_64_32(s->dflag);
3956 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3957 /* Note that by zero-extending the mask operand, we
3958 automatically handle zero-extending the result. */
3959 if (ot == MO_64) {
3960 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
3961 } else {
3962 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
3964 gen_helper_pext(cpu_regs[reg], s->T0, s->T1);
3965 break;
3967 case 0x1f6: /* adcx Gy, Ey */
3968 case 0x2f6: /* adox Gy, Ey */
3969 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3970 goto illegal_op;
3971 } else {
3972 TCGv carry_in, carry_out, zero;
3973 int end_op;
3975 ot = mo_64_32(s->dflag);
3976 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3978 /* Re-use the carry-out from a previous round. */
3979 carry_in = NULL;
3980 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3981 switch (s->cc_op) {
3982 case CC_OP_ADCX:
3983 if (b == 0x1f6) {
3984 carry_in = cpu_cc_dst;
3985 end_op = CC_OP_ADCX;
3986 } else {
3987 end_op = CC_OP_ADCOX;
3989 break;
3990 case CC_OP_ADOX:
3991 if (b == 0x1f6) {
3992 end_op = CC_OP_ADCOX;
3993 } else {
3994 carry_in = cpu_cc_src2;
3995 end_op = CC_OP_ADOX;
3997 break;
3998 case CC_OP_ADCOX:
3999 end_op = CC_OP_ADCOX;
4000 carry_in = carry_out;
4001 break;
4002 default:
4003 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
4004 break;
4006 /* If we can't reuse carry-out, get it out of EFLAGS. */
4007 if (!carry_in) {
4008 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4009 gen_compute_eflags(s);
4011 carry_in = s->tmp0;
4012 tcg_gen_extract_tl(carry_in, cpu_cc_src,
4013 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
4016 switch (ot) {
4017 #ifdef TARGET_X86_64
4018 case MO_32:
4019 /* If we know TL is 64-bit, and we want a 32-bit
4020 result, just do everything in 64-bit arithmetic. */
4021 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4022 tcg_gen_ext32u_i64(s->T0, s->T0);
4023 tcg_gen_add_i64(s->T0, s->T0, cpu_regs[reg]);
4024 tcg_gen_add_i64(s->T0, s->T0, carry_in);
4025 tcg_gen_ext32u_i64(cpu_regs[reg], s->T0);
4026 tcg_gen_shri_i64(carry_out, s->T0, 32);
4027 break;
4028 #endif
4029 default:
4030 /* Otherwise compute the carry-out in two steps. */
4031 zero = tcg_const_tl(0);
4032 tcg_gen_add2_tl(s->T0, carry_out,
4033 s->T0, zero,
4034 carry_in, zero);
4035 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4036 cpu_regs[reg], carry_out,
4037 s->T0, zero);
4038 tcg_temp_free(zero);
4039 break;
4041 set_cc_op(s, end_op);
4043 break;
4045 case 0x1f7: /* shlx Gy, Ey, By */
4046 case 0x2f7: /* sarx Gy, Ey, By */
4047 case 0x3f7: /* shrx Gy, Ey, By */
4048 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4049 || !(s->prefix & PREFIX_VEX)
4050 || s->vex_l != 0) {
4051 goto illegal_op;
4053 ot = mo_64_32(s->dflag);
4054 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4055 if (ot == MO_64) {
4056 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 63);
4057 } else {
4058 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 31);
4060 if (b == 0x1f7) {
4061 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
4062 } else if (b == 0x2f7) {
4063 if (ot != MO_64) {
4064 tcg_gen_ext32s_tl(s->T0, s->T0);
4066 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
4067 } else {
4068 if (ot != MO_64) {
4069 tcg_gen_ext32u_tl(s->T0, s->T0);
4071 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
4073 gen_op_mov_reg_v(s, ot, reg, s->T0);
4074 break;
4076 case 0x0f3:
4077 case 0x1f3:
4078 case 0x2f3:
4079 case 0x3f3: /* Group 17 */
4080 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4081 || !(s->prefix & PREFIX_VEX)
4082 || s->vex_l != 0) {
4083 goto illegal_op;
4085 ot = mo_64_32(s->dflag);
4086 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4088 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4089 switch (reg & 7) {
4090 case 1: /* blsr By,Ey */
4091 tcg_gen_subi_tl(s->T1, s->T0, 1);
4092 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4093 break;
4094 case 2: /* blsmsk By,Ey */
4095 tcg_gen_subi_tl(s->T1, s->T0, 1);
4096 tcg_gen_xor_tl(s->T0, s->T0, s->T1);
4097 break;
4098 case 3: /* blsi By, Ey */
4099 tcg_gen_neg_tl(s->T1, s->T0);
4100 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4101 break;
4102 default:
4103 goto unknown_op;
4105 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4106 gen_op_mov_reg_v(s, ot, s->vex_v, s->T0);
4107 set_cc_op(s, CC_OP_BMILGB + ot);
4108 break;
4110 default:
4111 goto unknown_op;
4113 break;
4115 case 0x03a:
4116 case 0x13a:
4117 b = modrm;
4118 modrm = x86_ldub_code(env, s);
4119 rm = modrm & 7;
4120 reg = ((modrm >> 3) & 7) | rex_r;
4121 mod = (modrm >> 6) & 3;
4122 if (b1 >= 2) {
4123 goto unknown_op;
4126 sse_fn_eppi = sse_op_table7[b].op[b1];
4127 if (!sse_fn_eppi) {
4128 goto unknown_op;
4130 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4131 goto illegal_op;
4133 s->rip_offset = 1;
4135 if (sse_fn_eppi == SSE_SPECIAL) {
4136 ot = mo_64_32(s->dflag);
4137 rm = (modrm & 7) | REX_B(s);
4138 if (mod != 3)
4139 gen_lea_modrm(env, s, modrm);
4140 reg = ((modrm >> 3) & 7) | rex_r;
4141 val = x86_ldub_code(env, s);
4142 switch (b) {
4143 case 0x14: /* pextrb */
4144 tcg_gen_ld8u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4145 xmm_regs[reg].ZMM_B(val & 15)));
4146 if (mod == 3) {
4147 gen_op_mov_reg_v(s, ot, rm, s->T0);
4148 } else {
4149 tcg_gen_qemu_st_tl(s->T0, s->A0,
4150 s->mem_index, MO_UB);
4152 break;
4153 case 0x15: /* pextrw */
4154 tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4155 xmm_regs[reg].ZMM_W(val & 7)));
4156 if (mod == 3) {
4157 gen_op_mov_reg_v(s, ot, rm, s->T0);
4158 } else {
4159 tcg_gen_qemu_st_tl(s->T0, s->A0,
4160 s->mem_index, MO_LEUW);
4162 break;
4163 case 0x16:
4164 if (ot == MO_32) { /* pextrd */
4165 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4166 offsetof(CPUX86State,
4167 xmm_regs[reg].ZMM_L(val & 3)));
4168 if (mod == 3) {
4169 tcg_gen_extu_i32_tl(cpu_regs[rm], s->tmp2_i32);
4170 } else {
4171 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4172 s->mem_index, MO_LEUL);
4174 } else { /* pextrq */
4175 #ifdef TARGET_X86_64
4176 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
4177 offsetof(CPUX86State,
4178 xmm_regs[reg].ZMM_Q(val & 1)));
4179 if (mod == 3) {
4180 tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64);
4181 } else {
4182 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4183 s->mem_index, MO_LEQ);
4185 #else
4186 goto illegal_op;
4187 #endif
4189 break;
4190 case 0x17: /* extractps */
4191 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4192 xmm_regs[reg].ZMM_L(val & 3)));
4193 if (mod == 3) {
4194 gen_op_mov_reg_v(s, ot, rm, s->T0);
4195 } else {
4196 tcg_gen_qemu_st_tl(s->T0, s->A0,
4197 s->mem_index, MO_LEUL);
4199 break;
4200 case 0x20: /* pinsrb */
4201 if (mod == 3) {
4202 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
4203 } else {
4204 tcg_gen_qemu_ld_tl(s->T0, s->A0,
4205 s->mem_index, MO_UB);
4207 tcg_gen_st8_tl(s->T0, cpu_env, offsetof(CPUX86State,
4208 xmm_regs[reg].ZMM_B(val & 15)));
4209 break;
4210 case 0x21: /* insertps */
4211 if (mod == 3) {
4212 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4213 offsetof(CPUX86State,xmm_regs[rm]
4214 .ZMM_L((val >> 6) & 3)));
4215 } else {
4216 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4217 s->mem_index, MO_LEUL);
4219 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4220 offsetof(CPUX86State,xmm_regs[reg]
4221 .ZMM_L((val >> 4) & 3)));
4222 if ((val >> 0) & 1)
4223 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4224 cpu_env, offsetof(CPUX86State,
4225 xmm_regs[reg].ZMM_L(0)));
4226 if ((val >> 1) & 1)
4227 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4228 cpu_env, offsetof(CPUX86State,
4229 xmm_regs[reg].ZMM_L(1)));
4230 if ((val >> 2) & 1)
4231 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4232 cpu_env, offsetof(CPUX86State,
4233 xmm_regs[reg].ZMM_L(2)));
4234 if ((val >> 3) & 1)
4235 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4236 cpu_env, offsetof(CPUX86State,
4237 xmm_regs[reg].ZMM_L(3)));
4238 break;
4239 case 0x22:
4240 if (ot == MO_32) { /* pinsrd */
4241 if (mod == 3) {
4242 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[rm]);
4243 } else {
4244 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4245 s->mem_index, MO_LEUL);
4247 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4248 offsetof(CPUX86State,
4249 xmm_regs[reg].ZMM_L(val & 3)));
4250 } else { /* pinsrq */
4251 #ifdef TARGET_X86_64
4252 if (mod == 3) {
4253 gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm);
4254 } else {
4255 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4256 s->mem_index, MO_LEQ);
4258 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
4259 offsetof(CPUX86State,
4260 xmm_regs[reg].ZMM_Q(val & 1)));
4261 #else
4262 goto illegal_op;
4263 #endif
4265 break;
4267 return;
4270 if (b1) {
4271 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4272 if (mod == 3) {
4273 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4274 } else {
4275 op2_offset = offsetof(CPUX86State,xmm_t0);
4276 gen_lea_modrm(env, s, modrm);
4277 gen_ldo_env_A0(s, op2_offset);
4279 } else {
4280 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4281 if (mod == 3) {
4282 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4283 } else {
4284 op2_offset = offsetof(CPUX86State,mmx_t0);
4285 gen_lea_modrm(env, s, modrm);
4286 gen_ldq_env_A0(s, op2_offset);
4289 val = x86_ldub_code(env, s);
4291 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4292 set_cc_op(s, CC_OP_EFLAGS);
4294 if (s->dflag == MO_64) {
4295 /* The helper must use entire 64-bit gp registers */
4296 val |= 1 << 8;
4300 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4301 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4302 sse_fn_eppi(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val));
4303 break;
4305 case 0x33a:
4306 /* Various integer extensions at 0f 3a f[0-f]. */
4307 b = modrm | (b1 << 8);
4308 modrm = x86_ldub_code(env, s);
4309 reg = ((modrm >> 3) & 7) | rex_r;
4311 switch (b) {
4312 case 0x3f0: /* rorx Gy,Ey, Ib */
4313 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4314 || !(s->prefix & PREFIX_VEX)
4315 || s->vex_l != 0) {
4316 goto illegal_op;
4318 ot = mo_64_32(s->dflag);
4319 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4320 b = x86_ldub_code(env, s);
4321 if (ot == MO_64) {
4322 tcg_gen_rotri_tl(s->T0, s->T0, b & 63);
4323 } else {
4324 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4325 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b & 31);
4326 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
4328 gen_op_mov_reg_v(s, ot, reg, s->T0);
4329 break;
4331 default:
4332 goto unknown_op;
4334 break;
4336 default:
4337 unknown_op:
4338 gen_unknown_opcode(env, s);
4339 return;
4341 } else {
4342 /* generic MMX or SSE operation */
4343 switch(b) {
4344 case 0x70: /* pshufx insn */
4345 case 0xc6: /* pshufx insn */
4346 case 0xc2: /* compare insns */
4347 s->rip_offset = 1;
4348 break;
4349 default:
4350 break;
4352 if (is_xmm) {
4353 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4354 if (mod != 3) {
4355 int sz = 4;
4357 gen_lea_modrm(env, s, modrm);
4358 op2_offset = offsetof(CPUX86State,xmm_t0);
4360 switch (b) {
4361 case 0x50 ... 0x5a:
4362 case 0x5c ... 0x5f:
4363 case 0xc2:
4364 /* Most sse scalar operations. */
4365 if (b1 == 2) {
4366 sz = 2;
4367 } else if (b1 == 3) {
4368 sz = 3;
4370 break;
4372 case 0x2e: /* ucomis[sd] */
4373 case 0x2f: /* comis[sd] */
4374 if (b1 == 0) {
4375 sz = 2;
4376 } else {
4377 sz = 3;
4379 break;
4382 switch (sz) {
4383 case 2:
4384 /* 32 bit access */
4385 gen_op_ld_v(s, MO_32, s->T0, s->A0);
4386 tcg_gen_st32_tl(s->T0, cpu_env,
4387 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4388 break;
4389 case 3:
4390 /* 64 bit access */
4391 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4392 break;
4393 default:
4394 /* 128 bit access */
4395 gen_ldo_env_A0(s, op2_offset);
4396 break;
4398 } else {
4399 rm = (modrm & 7) | REX_B(s);
4400 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4402 } else {
4403 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4404 if (mod != 3) {
4405 gen_lea_modrm(env, s, modrm);
4406 op2_offset = offsetof(CPUX86State,mmx_t0);
4407 gen_ldq_env_A0(s, op2_offset);
4408 } else {
4409 rm = (modrm & 7);
4410 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4413 switch(b) {
4414 case 0x0f: /* 3DNow! data insns */
4415 val = x86_ldub_code(env, s);
4416 sse_fn_epp = sse_op_table5[val];
4417 if (!sse_fn_epp) {
4418 goto unknown_op;
4420 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4421 goto illegal_op;
4423 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4424 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4425 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4426 break;
4427 case 0x70: /* pshufx insn */
4428 case 0xc6: /* pshufx insn */
4429 val = x86_ldub_code(env, s);
4430 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4431 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4432 /* XXX: introduce a new table? */
4433 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4434 sse_fn_ppi(s->ptr0, s->ptr1, tcg_const_i32(val));
4435 break;
4436 case 0xc2:
4437 /* compare insns */
4438 val = x86_ldub_code(env, s);
4439 if (val >= 8)
4440 goto unknown_op;
4441 sse_fn_epp = sse_op_table4[val][b1];
4443 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4444 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4445 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4446 break;
4447 case 0xf7:
4448 /* maskmov : we must prepare A0 */
4449 if (mod != 3)
4450 goto illegal_op;
4451 tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]);
4452 gen_extu(s->aflag, s->A0);
4453 gen_add_A0_ds_seg(s);
4455 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4456 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4457 /* XXX: introduce a new table? */
4458 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4459 sse_fn_eppt(cpu_env, s->ptr0, s->ptr1, s->A0);
4460 break;
4461 default:
4462 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4463 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4464 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4465 break;
4467 if (b == 0x2e || b == 0x2f) {
4468 set_cc_op(s, CC_OP_EFLAGS);
4473 /* convert one instruction. s->base.is_jmp is set if the translation must
4474 be stopped. Return the next pc value */
4475 static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
4477 CPUX86State *env = cpu->env_ptr;
4478 int b, prefixes;
4479 int shift;
4480 MemOp ot, aflag, dflag;
4481 int modrm, reg, rm, mod, op, opreg, val;
4482 target_ulong next_eip, tval;
4483 int rex_w, rex_r;
4484 target_ulong pc_start = s->base.pc_next;
4486 s->pc_start = s->pc = pc_start;
4487 s->override = -1;
4488 #ifdef TARGET_X86_64
4489 s->rex_x = 0;
4490 s->rex_b = 0;
4491 s->x86_64_hregs = false;
4492 #endif
4493 s->rip_offset = 0; /* for relative ip address */
4494 s->vex_l = 0;
4495 s->vex_v = 0;
4496 if (sigsetjmp(s->jmpbuf, 0) != 0) {
4497 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4498 return s->pc;
4501 prefixes = 0;
4502 rex_w = -1;
4503 rex_r = 0;
4505 next_byte:
4506 b = x86_ldub_code(env, s);
4507 /* Collect prefixes. */
4508 switch (b) {
4509 case 0xf3:
4510 prefixes |= PREFIX_REPZ;
4511 goto next_byte;
4512 case 0xf2:
4513 prefixes |= PREFIX_REPNZ;
4514 goto next_byte;
4515 case 0xf0:
4516 prefixes |= PREFIX_LOCK;
4517 goto next_byte;
4518 case 0x2e:
4519 s->override = R_CS;
4520 goto next_byte;
4521 case 0x36:
4522 s->override = R_SS;
4523 goto next_byte;
4524 case 0x3e:
4525 s->override = R_DS;
4526 goto next_byte;
4527 case 0x26:
4528 s->override = R_ES;
4529 goto next_byte;
4530 case 0x64:
4531 s->override = R_FS;
4532 goto next_byte;
4533 case 0x65:
4534 s->override = R_GS;
4535 goto next_byte;
4536 case 0x66:
4537 prefixes |= PREFIX_DATA;
4538 goto next_byte;
4539 case 0x67:
4540 prefixes |= PREFIX_ADR;
4541 goto next_byte;
4542 #ifdef TARGET_X86_64
4543 case 0x40 ... 0x4f:
4544 if (CODE64(s)) {
4545 /* REX prefix */
4546 rex_w = (b >> 3) & 1;
4547 rex_r = (b & 0x4) << 1;
4548 s->rex_x = (b & 0x2) << 2;
4549 REX_B(s) = (b & 0x1) << 3;
4550 /* select uniform byte register addressing */
4551 s->x86_64_hregs = true;
4552 goto next_byte;
4554 break;
4555 #endif
4556 case 0xc5: /* 2-byte VEX */
4557 case 0xc4: /* 3-byte VEX */
4558 /* VEX prefixes cannot be used except in 32-bit mode.
4559 Otherwise the instruction is LES or LDS. */
4560 if (s->code32 && !s->vm86) {
4561 static const int pp_prefix[4] = {
4562 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4564 int vex3, vex2 = x86_ldub_code(env, s);
4566 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4567 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4568 otherwise the instruction is LES or LDS. */
4569 s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
4570 break;
4573 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4574 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4575 | PREFIX_LOCK | PREFIX_DATA)) {
4576 goto illegal_op;
4578 #ifdef TARGET_X86_64
4579 if (s->x86_64_hregs) {
4580 goto illegal_op;
4582 #endif
4583 rex_r = (~vex2 >> 4) & 8;
4584 if (b == 0xc5) {
4585 /* 2-byte VEX prefix: RVVVVlpp, implied 0f leading opcode byte */
4586 vex3 = vex2;
4587 b = x86_ldub_code(env, s) | 0x100;
4588 } else {
4589 /* 3-byte VEX prefix: RXBmmmmm wVVVVlpp */
4590 #ifdef TARGET_X86_64
4591 s->rex_x = (~vex2 >> 3) & 8;
4592 s->rex_b = (~vex2 >> 2) & 8;
4593 #endif
4594 vex3 = x86_ldub_code(env, s);
4595 rex_w = (vex3 >> 7) & 1;
4596 switch (vex2 & 0x1f) {
4597 case 0x01: /* Implied 0f leading opcode bytes. */
4598 b = x86_ldub_code(env, s) | 0x100;
4599 break;
4600 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4601 b = 0x138;
4602 break;
4603 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4604 b = 0x13a;
4605 break;
4606 default: /* Reserved for future use. */
4607 goto unknown_op;
4610 s->vex_v = (~vex3 >> 3) & 0xf;
4611 s->vex_l = (vex3 >> 2) & 1;
4612 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4614 break;
4617 /* Post-process prefixes. */
4618 if (CODE64(s)) {
4619 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4620 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4621 over 0x66 if both are present. */
4622 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4623 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4624 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4625 } else {
4626 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4627 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4628 dflag = MO_32;
4629 } else {
4630 dflag = MO_16;
4632 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4633 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4634 aflag = MO_32;
4635 } else {
4636 aflag = MO_16;
4640 s->prefix = prefixes;
4641 s->aflag = aflag;
4642 s->dflag = dflag;
4644 /* now check op code */
4645 reswitch:
4646 switch(b) {
4647 case 0x0f:
4648 /**************************/
4649 /* extended op code */
4650 b = x86_ldub_code(env, s) | 0x100;
4651 goto reswitch;
4653 /**************************/
4654 /* arith & logic */
4655 case 0x00 ... 0x05:
4656 case 0x08 ... 0x0d:
4657 case 0x10 ... 0x15:
4658 case 0x18 ... 0x1d:
4659 case 0x20 ... 0x25:
4660 case 0x28 ... 0x2d:
4661 case 0x30 ... 0x35:
4662 case 0x38 ... 0x3d:
4664 int op, f, val;
4665 op = (b >> 3) & 7;
4666 f = (b >> 1) & 3;
4668 ot = mo_b_d(b, dflag);
4670 switch(f) {
4671 case 0: /* OP Ev, Gv */
4672 modrm = x86_ldub_code(env, s);
4673 reg = ((modrm >> 3) & 7) | rex_r;
4674 mod = (modrm >> 6) & 3;
4675 rm = (modrm & 7) | REX_B(s);
4676 if (mod != 3) {
4677 gen_lea_modrm(env, s, modrm);
4678 opreg = OR_TMP0;
4679 } else if (op == OP_XORL && rm == reg) {
4680 xor_zero:
4681 /* xor reg, reg optimisation */
4682 set_cc_op(s, CC_OP_CLR);
4683 tcg_gen_movi_tl(s->T0, 0);
4684 gen_op_mov_reg_v(s, ot, reg, s->T0);
4685 break;
4686 } else {
4687 opreg = rm;
4689 gen_op_mov_v_reg(s, ot, s->T1, reg);
4690 gen_op(s, op, ot, opreg);
4691 break;
4692 case 1: /* OP Gv, Ev */
4693 modrm = x86_ldub_code(env, s);
4694 mod = (modrm >> 6) & 3;
4695 reg = ((modrm >> 3) & 7) | rex_r;
4696 rm = (modrm & 7) | REX_B(s);
4697 if (mod != 3) {
4698 gen_lea_modrm(env, s, modrm);
4699 gen_op_ld_v(s, ot, s->T1, s->A0);
4700 } else if (op == OP_XORL && rm == reg) {
4701 goto xor_zero;
4702 } else {
4703 gen_op_mov_v_reg(s, ot, s->T1, rm);
4705 gen_op(s, op, ot, reg);
4706 break;
4707 case 2: /* OP A, Iv */
4708 val = insn_get(env, s, ot);
4709 tcg_gen_movi_tl(s->T1, val);
4710 gen_op(s, op, ot, OR_EAX);
4711 break;
4714 break;
4716 case 0x82:
4717 if (CODE64(s))
4718 goto illegal_op;
4719 /* fall through */
4720 case 0x80: /* GRP1 */
4721 case 0x81:
4722 case 0x83:
4724 int val;
4726 ot = mo_b_d(b, dflag);
4728 modrm = x86_ldub_code(env, s);
4729 mod = (modrm >> 6) & 3;
4730 rm = (modrm & 7) | REX_B(s);
4731 op = (modrm >> 3) & 7;
4733 if (mod != 3) {
4734 if (b == 0x83)
4735 s->rip_offset = 1;
4736 else
4737 s->rip_offset = insn_const_size(ot);
4738 gen_lea_modrm(env, s, modrm);
4739 opreg = OR_TMP0;
4740 } else {
4741 opreg = rm;
4744 switch(b) {
4745 default:
4746 case 0x80:
4747 case 0x81:
4748 case 0x82:
4749 val = insn_get(env, s, ot);
4750 break;
4751 case 0x83:
4752 val = (int8_t)insn_get(env, s, MO_8);
4753 break;
4755 tcg_gen_movi_tl(s->T1, val);
4756 gen_op(s, op, ot, opreg);
4758 break;
4760 /**************************/
4761 /* inc, dec, and other misc arith */
4762 case 0x40 ... 0x47: /* inc Gv */
4763 ot = dflag;
4764 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4765 break;
4766 case 0x48 ... 0x4f: /* dec Gv */
4767 ot = dflag;
4768 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4769 break;
4770 case 0xf6: /* GRP3 */
4771 case 0xf7:
4772 ot = mo_b_d(b, dflag);
4774 modrm = x86_ldub_code(env, s);
4775 mod = (modrm >> 6) & 3;
4776 rm = (modrm & 7) | REX_B(s);
4777 op = (modrm >> 3) & 7;
4778 if (mod != 3) {
4779 if (op == 0) {
4780 s->rip_offset = insn_const_size(ot);
4782 gen_lea_modrm(env, s, modrm);
4783 /* For those below that handle locked memory, don't load here. */
4784 if (!(s->prefix & PREFIX_LOCK)
4785 || op != 2) {
4786 gen_op_ld_v(s, ot, s->T0, s->A0);
4788 } else {
4789 gen_op_mov_v_reg(s, ot, s->T0, rm);
4792 switch(op) {
4793 case 0: /* test */
4794 val = insn_get(env, s, ot);
4795 tcg_gen_movi_tl(s->T1, val);
4796 gen_op_testl_T0_T1_cc(s);
4797 set_cc_op(s, CC_OP_LOGICB + ot);
4798 break;
4799 case 2: /* not */
4800 if (s->prefix & PREFIX_LOCK) {
4801 if (mod == 3) {
4802 goto illegal_op;
4804 tcg_gen_movi_tl(s->T0, ~0);
4805 tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0,
4806 s->mem_index, ot | MO_LE);
4807 } else {
4808 tcg_gen_not_tl(s->T0, s->T0);
4809 if (mod != 3) {
4810 gen_op_st_v(s, ot, s->T0, s->A0);
4811 } else {
4812 gen_op_mov_reg_v(s, ot, rm, s->T0);
4815 break;
4816 case 3: /* neg */
4817 if (s->prefix & PREFIX_LOCK) {
4818 TCGLabel *label1;
4819 TCGv a0, t0, t1, t2;
4821 if (mod == 3) {
4822 goto illegal_op;
4824 a0 = tcg_temp_local_new();
4825 t0 = tcg_temp_local_new();
4826 label1 = gen_new_label();
4828 tcg_gen_mov_tl(a0, s->A0);
4829 tcg_gen_mov_tl(t0, s->T0);
4831 gen_set_label(label1);
4832 t1 = tcg_temp_new();
4833 t2 = tcg_temp_new();
4834 tcg_gen_mov_tl(t2, t0);
4835 tcg_gen_neg_tl(t1, t0);
4836 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4837 s->mem_index, ot | MO_LE);
4838 tcg_temp_free(t1);
4839 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4841 tcg_temp_free(t2);
4842 tcg_temp_free(a0);
4843 tcg_gen_mov_tl(s->T0, t0);
4844 tcg_temp_free(t0);
4845 } else {
4846 tcg_gen_neg_tl(s->T0, s->T0);
4847 if (mod != 3) {
4848 gen_op_st_v(s, ot, s->T0, s->A0);
4849 } else {
4850 gen_op_mov_reg_v(s, ot, rm, s->T0);
4853 gen_op_update_neg_cc(s);
4854 set_cc_op(s, CC_OP_SUBB + ot);
4855 break;
4856 case 4: /* mul */
4857 switch(ot) {
4858 case MO_8:
4859 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4860 tcg_gen_ext8u_tl(s->T0, s->T0);
4861 tcg_gen_ext8u_tl(s->T1, s->T1);
4862 /* XXX: use 32 bit mul which could be faster */
4863 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4864 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4865 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4866 tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00);
4867 set_cc_op(s, CC_OP_MULB);
4868 break;
4869 case MO_16:
4870 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
4871 tcg_gen_ext16u_tl(s->T0, s->T0);
4872 tcg_gen_ext16u_tl(s->T1, s->T1);
4873 /* XXX: use 32 bit mul which could be faster */
4874 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4875 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4876 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4877 tcg_gen_shri_tl(s->T0, s->T0, 16);
4878 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
4879 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4880 set_cc_op(s, CC_OP_MULW);
4881 break;
4882 default:
4883 case MO_32:
4884 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4885 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
4886 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
4887 s->tmp2_i32, s->tmp3_i32);
4888 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
4889 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
4890 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4891 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4892 set_cc_op(s, CC_OP_MULL);
4893 break;
4894 #ifdef TARGET_X86_64
4895 case MO_64:
4896 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4897 s->T0, cpu_regs[R_EAX]);
4898 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4899 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4900 set_cc_op(s, CC_OP_MULQ);
4901 break;
4902 #endif
4904 break;
4905 case 5: /* imul */
4906 switch(ot) {
4907 case MO_8:
4908 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4909 tcg_gen_ext8s_tl(s->T0, s->T0);
4910 tcg_gen_ext8s_tl(s->T1, s->T1);
4911 /* XXX: use 32 bit mul which could be faster */
4912 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4913 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4914 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4915 tcg_gen_ext8s_tl(s->tmp0, s->T0);
4916 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
4917 set_cc_op(s, CC_OP_MULB);
4918 break;
4919 case MO_16:
4920 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
4921 tcg_gen_ext16s_tl(s->T0, s->T0);
4922 tcg_gen_ext16s_tl(s->T1, s->T1);
4923 /* XXX: use 32 bit mul which could be faster */
4924 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4925 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4926 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4927 tcg_gen_ext16s_tl(s->tmp0, s->T0);
4928 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
4929 tcg_gen_shri_tl(s->T0, s->T0, 16);
4930 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
4931 set_cc_op(s, CC_OP_MULW);
4932 break;
4933 default:
4934 case MO_32:
4935 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4936 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
4937 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
4938 s->tmp2_i32, s->tmp3_i32);
4939 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
4940 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
4941 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
4942 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4943 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
4944 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
4945 set_cc_op(s, CC_OP_MULL);
4946 break;
4947 #ifdef TARGET_X86_64
4948 case MO_64:
4949 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4950 s->T0, cpu_regs[R_EAX]);
4951 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4952 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4953 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4954 set_cc_op(s, CC_OP_MULQ);
4955 break;
4956 #endif
4958 break;
4959 case 6: /* div */
4960 switch(ot) {
4961 case MO_8:
4962 gen_helper_divb_AL(cpu_env, s->T0);
4963 break;
4964 case MO_16:
4965 gen_helper_divw_AX(cpu_env, s->T0);
4966 break;
4967 default:
4968 case MO_32:
4969 gen_helper_divl_EAX(cpu_env, s->T0);
4970 break;
4971 #ifdef TARGET_X86_64
4972 case MO_64:
4973 gen_helper_divq_EAX(cpu_env, s->T0);
4974 break;
4975 #endif
4977 break;
4978 case 7: /* idiv */
4979 switch(ot) {
4980 case MO_8:
4981 gen_helper_idivb_AL(cpu_env, s->T0);
4982 break;
4983 case MO_16:
4984 gen_helper_idivw_AX(cpu_env, s->T0);
4985 break;
4986 default:
4987 case MO_32:
4988 gen_helper_idivl_EAX(cpu_env, s->T0);
4989 break;
4990 #ifdef TARGET_X86_64
4991 case MO_64:
4992 gen_helper_idivq_EAX(cpu_env, s->T0);
4993 break;
4994 #endif
4996 break;
4997 default:
4998 goto unknown_op;
5000 break;
5002 case 0xfe: /* GRP4 */
5003 case 0xff: /* GRP5 */
5004 ot = mo_b_d(b, dflag);
5006 modrm = x86_ldub_code(env, s);
5007 mod = (modrm >> 6) & 3;
5008 rm = (modrm & 7) | REX_B(s);
5009 op = (modrm >> 3) & 7;
5010 if (op >= 2 && b == 0xfe) {
5011 goto unknown_op;
5013 if (CODE64(s)) {
5014 if (op == 2 || op == 4) {
5015 /* operand size for jumps is 64 bit */
5016 ot = MO_64;
5017 } else if (op == 3 || op == 5) {
5018 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
5019 } else if (op == 6) {
5020 /* default push size is 64 bit */
5021 ot = mo_pushpop(s, dflag);
5024 if (mod != 3) {
5025 gen_lea_modrm(env, s, modrm);
5026 if (op >= 2 && op != 3 && op != 5)
5027 gen_op_ld_v(s, ot, s->T0, s->A0);
5028 } else {
5029 gen_op_mov_v_reg(s, ot, s->T0, rm);
5032 switch(op) {
5033 case 0: /* inc Ev */
5034 if (mod != 3)
5035 opreg = OR_TMP0;
5036 else
5037 opreg = rm;
5038 gen_inc(s, ot, opreg, 1);
5039 break;
5040 case 1: /* dec Ev */
5041 if (mod != 3)
5042 opreg = OR_TMP0;
5043 else
5044 opreg = rm;
5045 gen_inc(s, ot, opreg, -1);
5046 break;
5047 case 2: /* call Ev */
5048 /* XXX: optimize if memory (no 'and' is necessary) */
5049 if (dflag == MO_16) {
5050 tcg_gen_ext16u_tl(s->T0, s->T0);
5052 next_eip = s->pc - s->cs_base;
5053 tcg_gen_movi_tl(s->T1, next_eip);
5054 gen_push_v(s, s->T1);
5055 gen_op_jmp_v(s->T0);
5056 gen_bnd_jmp(s);
5057 gen_jr(s, s->T0);
5058 break;
5059 case 3: /* lcall Ev */
5060 gen_op_ld_v(s, ot, s->T1, s->A0);
5061 gen_add_A0_im(s, 1 << ot);
5062 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5063 do_lcall:
5064 if (s->pe && !s->vm86) {
5065 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5066 gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
5067 tcg_const_i32(dflag - 1),
5068 tcg_const_tl(s->pc - s->cs_base));
5069 } else {
5070 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5071 gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1,
5072 tcg_const_i32(dflag - 1),
5073 tcg_const_i32(s->pc - s->cs_base));
5075 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5076 gen_jr(s, s->tmp4);
5077 break;
5078 case 4: /* jmp Ev */
5079 if (dflag == MO_16) {
5080 tcg_gen_ext16u_tl(s->T0, s->T0);
5082 gen_op_jmp_v(s->T0);
5083 gen_bnd_jmp(s);
5084 gen_jr(s, s->T0);
5085 break;
5086 case 5: /* ljmp Ev */
5087 gen_op_ld_v(s, ot, s->T1, s->A0);
5088 gen_add_A0_im(s, 1 << ot);
5089 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5090 do_ljmp:
5091 if (s->pe && !s->vm86) {
5092 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5093 gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1,
5094 tcg_const_tl(s->pc - s->cs_base));
5095 } else {
5096 gen_op_movl_seg_T0_vm(s, R_CS);
5097 gen_op_jmp_v(s->T1);
5099 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5100 gen_jr(s, s->tmp4);
5101 break;
5102 case 6: /* push Ev */
5103 gen_push_v(s, s->T0);
5104 break;
5105 default:
5106 goto unknown_op;
5108 break;
5110 case 0x84: /* test Ev, Gv */
5111 case 0x85:
5112 ot = mo_b_d(b, dflag);
5114 modrm = x86_ldub_code(env, s);
5115 reg = ((modrm >> 3) & 7) | rex_r;
5117 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5118 gen_op_mov_v_reg(s, ot, s->T1, reg);
5119 gen_op_testl_T0_T1_cc(s);
5120 set_cc_op(s, CC_OP_LOGICB + ot);
5121 break;
5123 case 0xa8: /* test eAX, Iv */
5124 case 0xa9:
5125 ot = mo_b_d(b, dflag);
5126 val = insn_get(env, s, ot);
5128 gen_op_mov_v_reg(s, ot, s->T0, OR_EAX);
5129 tcg_gen_movi_tl(s->T1, val);
5130 gen_op_testl_T0_T1_cc(s);
5131 set_cc_op(s, CC_OP_LOGICB + ot);
5132 break;
5134 case 0x98: /* CWDE/CBW */
5135 switch (dflag) {
5136 #ifdef TARGET_X86_64
5137 case MO_64:
5138 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5139 tcg_gen_ext32s_tl(s->T0, s->T0);
5140 gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0);
5141 break;
5142 #endif
5143 case MO_32:
5144 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5145 tcg_gen_ext16s_tl(s->T0, s->T0);
5146 gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0);
5147 break;
5148 case MO_16:
5149 gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX);
5150 tcg_gen_ext8s_tl(s->T0, s->T0);
5151 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5152 break;
5153 default:
5154 tcg_abort();
5156 break;
5157 case 0x99: /* CDQ/CWD */
5158 switch (dflag) {
5159 #ifdef TARGET_X86_64
5160 case MO_64:
5161 gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX);
5162 tcg_gen_sari_tl(s->T0, s->T0, 63);
5163 gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0);
5164 break;
5165 #endif
5166 case MO_32:
5167 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5168 tcg_gen_ext32s_tl(s->T0, s->T0);
5169 tcg_gen_sari_tl(s->T0, s->T0, 31);
5170 gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0);
5171 break;
5172 case MO_16:
5173 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5174 tcg_gen_ext16s_tl(s->T0, s->T0);
5175 tcg_gen_sari_tl(s->T0, s->T0, 15);
5176 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5177 break;
5178 default:
5179 tcg_abort();
5181 break;
5182 case 0x1af: /* imul Gv, Ev */
5183 case 0x69: /* imul Gv, Ev, I */
5184 case 0x6b:
5185 ot = dflag;
5186 modrm = x86_ldub_code(env, s);
5187 reg = ((modrm >> 3) & 7) | rex_r;
5188 if (b == 0x69)
5189 s->rip_offset = insn_const_size(ot);
5190 else if (b == 0x6b)
5191 s->rip_offset = 1;
5192 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5193 if (b == 0x69) {
5194 val = insn_get(env, s, ot);
5195 tcg_gen_movi_tl(s->T1, val);
5196 } else if (b == 0x6b) {
5197 val = (int8_t)insn_get(env, s, MO_8);
5198 tcg_gen_movi_tl(s->T1, val);
5199 } else {
5200 gen_op_mov_v_reg(s, ot, s->T1, reg);
5202 switch (ot) {
5203 #ifdef TARGET_X86_64
5204 case MO_64:
5205 tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1);
5206 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5207 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5208 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1);
5209 break;
5210 #endif
5211 case MO_32:
5212 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5213 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
5214 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5215 s->tmp2_i32, s->tmp3_i32);
5216 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
5217 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5218 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5219 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5220 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5221 break;
5222 default:
5223 tcg_gen_ext16s_tl(s->T0, s->T0);
5224 tcg_gen_ext16s_tl(s->T1, s->T1);
5225 /* XXX: use 32 bit mul which could be faster */
5226 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5227 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5228 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5229 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5230 gen_op_mov_reg_v(s, ot, reg, s->T0);
5231 break;
5233 set_cc_op(s, CC_OP_MULB + ot);
5234 break;
5235 case 0x1c0:
5236 case 0x1c1: /* xadd Ev, Gv */
5237 ot = mo_b_d(b, dflag);
5238 modrm = x86_ldub_code(env, s);
5239 reg = ((modrm >> 3) & 7) | rex_r;
5240 mod = (modrm >> 6) & 3;
5241 gen_op_mov_v_reg(s, ot, s->T0, reg);
5242 if (mod == 3) {
5243 rm = (modrm & 7) | REX_B(s);
5244 gen_op_mov_v_reg(s, ot, s->T1, rm);
5245 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5246 gen_op_mov_reg_v(s, ot, reg, s->T1);
5247 gen_op_mov_reg_v(s, ot, rm, s->T0);
5248 } else {
5249 gen_lea_modrm(env, s, modrm);
5250 if (s->prefix & PREFIX_LOCK) {
5251 tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0,
5252 s->mem_index, ot | MO_LE);
5253 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5254 } else {
5255 gen_op_ld_v(s, ot, s->T1, s->A0);
5256 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5257 gen_op_st_v(s, ot, s->T0, s->A0);
5259 gen_op_mov_reg_v(s, ot, reg, s->T1);
5261 gen_op_update2_cc(s);
5262 set_cc_op(s, CC_OP_ADDB + ot);
5263 break;
5264 case 0x1b0:
5265 case 0x1b1: /* cmpxchg Ev, Gv */
5267 TCGv oldv, newv, cmpv;
5269 ot = mo_b_d(b, dflag);
5270 modrm = x86_ldub_code(env, s);
5271 reg = ((modrm >> 3) & 7) | rex_r;
5272 mod = (modrm >> 6) & 3;
5273 oldv = tcg_temp_new();
5274 newv = tcg_temp_new();
5275 cmpv = tcg_temp_new();
5276 gen_op_mov_v_reg(s, ot, newv, reg);
5277 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5279 if (s->prefix & PREFIX_LOCK) {
5280 if (mod == 3) {
5281 goto illegal_op;
5283 gen_lea_modrm(env, s, modrm);
5284 tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
5285 s->mem_index, ot | MO_LE);
5286 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5287 } else {
5288 if (mod == 3) {
5289 rm = (modrm & 7) | REX_B(s);
5290 gen_op_mov_v_reg(s, ot, oldv, rm);
5291 } else {
5292 gen_lea_modrm(env, s, modrm);
5293 gen_op_ld_v(s, ot, oldv, s->A0);
5294 rm = 0; /* avoid warning */
5296 gen_extu(ot, oldv);
5297 gen_extu(ot, cmpv);
5298 /* store value = (old == cmp ? new : old); */
5299 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5300 if (mod == 3) {
5301 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5302 gen_op_mov_reg_v(s, ot, rm, newv);
5303 } else {
5304 /* Perform an unconditional store cycle like physical cpu;
5305 must be before changing accumulator to ensure
5306 idempotency if the store faults and the instruction
5307 is restarted */
5308 gen_op_st_v(s, ot, newv, s->A0);
5309 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5312 tcg_gen_mov_tl(cpu_cc_src, oldv);
5313 tcg_gen_mov_tl(s->cc_srcT, cmpv);
5314 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5315 set_cc_op(s, CC_OP_SUBB + ot);
5316 tcg_temp_free(oldv);
5317 tcg_temp_free(newv);
5318 tcg_temp_free(cmpv);
5320 break;
5321 case 0x1c7: /* cmpxchg8b */
5322 modrm = x86_ldub_code(env, s);
5323 mod = (modrm >> 6) & 3;
5324 switch ((modrm >> 3) & 7) {
5325 case 1: /* CMPXCHG8, CMPXCHG16 */
5326 if (mod == 3) {
5327 goto illegal_op;
5329 #ifdef TARGET_X86_64
5330 if (dflag == MO_64) {
5331 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) {
5332 goto illegal_op;
5334 gen_lea_modrm(env, s, modrm);
5335 if ((s->prefix & PREFIX_LOCK) &&
5336 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5337 gen_helper_cmpxchg16b(cpu_env, s->A0);
5338 } else {
5339 gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0);
5341 set_cc_op(s, CC_OP_EFLAGS);
5342 break;
5344 #endif
5345 if (!(s->cpuid_features & CPUID_CX8)) {
5346 goto illegal_op;
5348 gen_lea_modrm(env, s, modrm);
5349 if ((s->prefix & PREFIX_LOCK) &&
5350 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5351 gen_helper_cmpxchg8b(cpu_env, s->A0);
5352 } else {
5353 gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0);
5355 set_cc_op(s, CC_OP_EFLAGS);
5356 break;
5358 case 7: /* RDSEED */
5359 case 6: /* RDRAND */
5360 if (mod != 3 ||
5361 (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
5362 !(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
5363 goto illegal_op;
5365 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5366 gen_io_start();
5368 gen_helper_rdrand(s->T0, cpu_env);
5369 rm = (modrm & 7) | REX_B(s);
5370 gen_op_mov_reg_v(s, dflag, rm, s->T0);
5371 set_cc_op(s, CC_OP_EFLAGS);
5372 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5373 gen_jmp(s, s->pc - s->cs_base);
5375 break;
5377 default:
5378 goto illegal_op;
5380 break;
5382 /**************************/
5383 /* push/pop */
5384 case 0x50 ... 0x57: /* push */
5385 gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s));
5386 gen_push_v(s, s->T0);
5387 break;
5388 case 0x58 ... 0x5f: /* pop */
5389 ot = gen_pop_T0(s);
5390 /* NOTE: order is important for pop %sp */
5391 gen_pop_update(s, ot);
5392 gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0);
5393 break;
5394 case 0x60: /* pusha */
5395 if (CODE64(s))
5396 goto illegal_op;
5397 gen_pusha(s);
5398 break;
5399 case 0x61: /* popa */
5400 if (CODE64(s))
5401 goto illegal_op;
5402 gen_popa(s);
5403 break;
5404 case 0x68: /* push Iv */
5405 case 0x6a:
5406 ot = mo_pushpop(s, dflag);
5407 if (b == 0x68)
5408 val = insn_get(env, s, ot);
5409 else
5410 val = (int8_t)insn_get(env, s, MO_8);
5411 tcg_gen_movi_tl(s->T0, val);
5412 gen_push_v(s, s->T0);
5413 break;
5414 case 0x8f: /* pop Ev */
5415 modrm = x86_ldub_code(env, s);
5416 mod = (modrm >> 6) & 3;
5417 ot = gen_pop_T0(s);
5418 if (mod == 3) {
5419 /* NOTE: order is important for pop %sp */
5420 gen_pop_update(s, ot);
5421 rm = (modrm & 7) | REX_B(s);
5422 gen_op_mov_reg_v(s, ot, rm, s->T0);
5423 } else {
5424 /* NOTE: order is important too for MMU exceptions */
5425 s->popl_esp_hack = 1 << ot;
5426 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5427 s->popl_esp_hack = 0;
5428 gen_pop_update(s, ot);
5430 break;
5431 case 0xc8: /* enter */
5433 int level;
5434 val = x86_lduw_code(env, s);
5435 level = x86_ldub_code(env, s);
5436 gen_enter(s, val, level);
5438 break;
5439 case 0xc9: /* leave */
5440 gen_leave(s);
5441 break;
5442 case 0x06: /* push es */
5443 case 0x0e: /* push cs */
5444 case 0x16: /* push ss */
5445 case 0x1e: /* push ds */
5446 if (CODE64(s))
5447 goto illegal_op;
5448 gen_op_movl_T0_seg(s, b >> 3);
5449 gen_push_v(s, s->T0);
5450 break;
5451 case 0x1a0: /* push fs */
5452 case 0x1a8: /* push gs */
5453 gen_op_movl_T0_seg(s, (b >> 3) & 7);
5454 gen_push_v(s, s->T0);
5455 break;
5456 case 0x07: /* pop es */
5457 case 0x17: /* pop ss */
5458 case 0x1f: /* pop ds */
5459 if (CODE64(s))
5460 goto illegal_op;
5461 reg = b >> 3;
5462 ot = gen_pop_T0(s);
5463 gen_movl_seg_T0(s, reg);
5464 gen_pop_update(s, ot);
5465 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5466 if (s->base.is_jmp) {
5467 gen_jmp_im(s, s->pc - s->cs_base);
5468 if (reg == R_SS) {
5469 s->tf = 0;
5470 gen_eob_inhibit_irq(s, true);
5471 } else {
5472 gen_eob(s);
5475 break;
5476 case 0x1a1: /* pop fs */
5477 case 0x1a9: /* pop gs */
5478 ot = gen_pop_T0(s);
5479 gen_movl_seg_T0(s, (b >> 3) & 7);
5480 gen_pop_update(s, ot);
5481 if (s->base.is_jmp) {
5482 gen_jmp_im(s, s->pc - s->cs_base);
5483 gen_eob(s);
5485 break;
5487 /**************************/
5488 /* mov */
5489 case 0x88:
5490 case 0x89: /* mov Gv, Ev */
5491 ot = mo_b_d(b, dflag);
5492 modrm = x86_ldub_code(env, s);
5493 reg = ((modrm >> 3) & 7) | rex_r;
5495 /* generate a generic store */
5496 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5497 break;
5498 case 0xc6:
5499 case 0xc7: /* mov Ev, Iv */
5500 ot = mo_b_d(b, dflag);
5501 modrm = x86_ldub_code(env, s);
5502 mod = (modrm >> 6) & 3;
5503 if (mod != 3) {
5504 s->rip_offset = insn_const_size(ot);
5505 gen_lea_modrm(env, s, modrm);
5507 val = insn_get(env, s, ot);
5508 tcg_gen_movi_tl(s->T0, val);
5509 if (mod != 3) {
5510 gen_op_st_v(s, ot, s->T0, s->A0);
5511 } else {
5512 gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0);
5514 break;
5515 case 0x8a:
5516 case 0x8b: /* mov Ev, Gv */
5517 ot = mo_b_d(b, dflag);
5518 modrm = x86_ldub_code(env, s);
5519 reg = ((modrm >> 3) & 7) | rex_r;
5521 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5522 gen_op_mov_reg_v(s, ot, reg, s->T0);
5523 break;
5524 case 0x8e: /* mov seg, Gv */
5525 modrm = x86_ldub_code(env, s);
5526 reg = (modrm >> 3) & 7;
5527 if (reg >= 6 || reg == R_CS)
5528 goto illegal_op;
5529 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5530 gen_movl_seg_T0(s, reg);
5531 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5532 if (s->base.is_jmp) {
5533 gen_jmp_im(s, s->pc - s->cs_base);
5534 if (reg == R_SS) {
5535 s->tf = 0;
5536 gen_eob_inhibit_irq(s, true);
5537 } else {
5538 gen_eob(s);
5541 break;
5542 case 0x8c: /* mov Gv, seg */
5543 modrm = x86_ldub_code(env, s);
5544 reg = (modrm >> 3) & 7;
5545 mod = (modrm >> 6) & 3;
5546 if (reg >= 6)
5547 goto illegal_op;
5548 gen_op_movl_T0_seg(s, reg);
5549 ot = mod == 3 ? dflag : MO_16;
5550 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5551 break;
5553 case 0x1b6: /* movzbS Gv, Eb */
5554 case 0x1b7: /* movzwS Gv, Eb */
5555 case 0x1be: /* movsbS Gv, Eb */
5556 case 0x1bf: /* movswS Gv, Eb */
5558 MemOp d_ot;
5559 MemOp s_ot;
5561 /* d_ot is the size of destination */
5562 d_ot = dflag;
5563 /* ot is the size of source */
5564 ot = (b & 1) + MO_8;
5565 /* s_ot is the sign+size of source */
5566 s_ot = b & 8 ? MO_SIGN | ot : ot;
5568 modrm = x86_ldub_code(env, s);
5569 reg = ((modrm >> 3) & 7) | rex_r;
5570 mod = (modrm >> 6) & 3;
5571 rm = (modrm & 7) | REX_B(s);
5573 if (mod == 3) {
5574 if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) {
5575 tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8);
5576 } else {
5577 gen_op_mov_v_reg(s, ot, s->T0, rm);
5578 switch (s_ot) {
5579 case MO_UB:
5580 tcg_gen_ext8u_tl(s->T0, s->T0);
5581 break;
5582 case MO_SB:
5583 tcg_gen_ext8s_tl(s->T0, s->T0);
5584 break;
5585 case MO_UW:
5586 tcg_gen_ext16u_tl(s->T0, s->T0);
5587 break;
5588 default:
5589 case MO_SW:
5590 tcg_gen_ext16s_tl(s->T0, s->T0);
5591 break;
5594 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5595 } else {
5596 gen_lea_modrm(env, s, modrm);
5597 gen_op_ld_v(s, s_ot, s->T0, s->A0);
5598 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5601 break;
5603 case 0x8d: /* lea */
5604 modrm = x86_ldub_code(env, s);
5605 mod = (modrm >> 6) & 3;
5606 if (mod == 3)
5607 goto illegal_op;
5608 reg = ((modrm >> 3) & 7) | rex_r;
5610 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5611 TCGv ea = gen_lea_modrm_1(s, a);
5612 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5613 gen_op_mov_reg_v(s, dflag, reg, s->A0);
5615 break;
5617 case 0xa0: /* mov EAX, Ov */
5618 case 0xa1:
5619 case 0xa2: /* mov Ov, EAX */
5620 case 0xa3:
5622 target_ulong offset_addr;
5624 ot = mo_b_d(b, dflag);
5625 switch (s->aflag) {
5626 #ifdef TARGET_X86_64
5627 case MO_64:
5628 offset_addr = x86_ldq_code(env, s);
5629 break;
5630 #endif
5631 default:
5632 offset_addr = insn_get(env, s, s->aflag);
5633 break;
5635 tcg_gen_movi_tl(s->A0, offset_addr);
5636 gen_add_A0_ds_seg(s);
5637 if ((b & 2) == 0) {
5638 gen_op_ld_v(s, ot, s->T0, s->A0);
5639 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
5640 } else {
5641 gen_op_mov_v_reg(s, ot, s->T0, R_EAX);
5642 gen_op_st_v(s, ot, s->T0, s->A0);
5645 break;
5646 case 0xd7: /* xlat */
5647 tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]);
5648 tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]);
5649 tcg_gen_add_tl(s->A0, s->A0, s->T0);
5650 gen_extu(s->aflag, s->A0);
5651 gen_add_A0_ds_seg(s);
5652 gen_op_ld_v(s, MO_8, s->T0, s->A0);
5653 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
5654 break;
5655 case 0xb0 ... 0xb7: /* mov R, Ib */
5656 val = insn_get(env, s, MO_8);
5657 tcg_gen_movi_tl(s->T0, val);
5658 gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0);
5659 break;
5660 case 0xb8 ... 0xbf: /* mov R, Iv */
5661 #ifdef TARGET_X86_64
5662 if (dflag == MO_64) {
5663 uint64_t tmp;
5664 /* 64 bit case */
5665 tmp = x86_ldq_code(env, s);
5666 reg = (b & 7) | REX_B(s);
5667 tcg_gen_movi_tl(s->T0, tmp);
5668 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
5669 } else
5670 #endif
5672 ot = dflag;
5673 val = insn_get(env, s, ot);
5674 reg = (b & 7) | REX_B(s);
5675 tcg_gen_movi_tl(s->T0, val);
5676 gen_op_mov_reg_v(s, ot, reg, s->T0);
5678 break;
5680 case 0x91 ... 0x97: /* xchg R, EAX */
5681 do_xchg_reg_eax:
5682 ot = dflag;
5683 reg = (b & 7) | REX_B(s);
5684 rm = R_EAX;
5685 goto do_xchg_reg;
5686 case 0x86:
5687 case 0x87: /* xchg Ev, Gv */
5688 ot = mo_b_d(b, dflag);
5689 modrm = x86_ldub_code(env, s);
5690 reg = ((modrm >> 3) & 7) | rex_r;
5691 mod = (modrm >> 6) & 3;
5692 if (mod == 3) {
5693 rm = (modrm & 7) | REX_B(s);
5694 do_xchg_reg:
5695 gen_op_mov_v_reg(s, ot, s->T0, reg);
5696 gen_op_mov_v_reg(s, ot, s->T1, rm);
5697 gen_op_mov_reg_v(s, ot, rm, s->T0);
5698 gen_op_mov_reg_v(s, ot, reg, s->T1);
5699 } else {
5700 gen_lea_modrm(env, s, modrm);
5701 gen_op_mov_v_reg(s, ot, s->T0, reg);
5702 /* for xchg, lock is implicit */
5703 tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0,
5704 s->mem_index, ot | MO_LE);
5705 gen_op_mov_reg_v(s, ot, reg, s->T1);
5707 break;
5708 case 0xc4: /* les Gv */
5709 /* In CODE64 this is VEX3; see above. */
5710 op = R_ES;
5711 goto do_lxx;
5712 case 0xc5: /* lds Gv */
5713 /* In CODE64 this is VEX2; see above. */
5714 op = R_DS;
5715 goto do_lxx;
5716 case 0x1b2: /* lss Gv */
5717 op = R_SS;
5718 goto do_lxx;
5719 case 0x1b4: /* lfs Gv */
5720 op = R_FS;
5721 goto do_lxx;
5722 case 0x1b5: /* lgs Gv */
5723 op = R_GS;
5724 do_lxx:
5725 ot = dflag != MO_16 ? MO_32 : MO_16;
5726 modrm = x86_ldub_code(env, s);
5727 reg = ((modrm >> 3) & 7) | rex_r;
5728 mod = (modrm >> 6) & 3;
5729 if (mod == 3)
5730 goto illegal_op;
5731 gen_lea_modrm(env, s, modrm);
5732 gen_op_ld_v(s, ot, s->T1, s->A0);
5733 gen_add_A0_im(s, 1 << ot);
5734 /* load the segment first to handle exceptions properly */
5735 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5736 gen_movl_seg_T0(s, op);
5737 /* then put the data */
5738 gen_op_mov_reg_v(s, ot, reg, s->T1);
5739 if (s->base.is_jmp) {
5740 gen_jmp_im(s, s->pc - s->cs_base);
5741 gen_eob(s);
5743 break;
5745 /************************/
5746 /* shifts */
5747 case 0xc0:
5748 case 0xc1:
5749 /* shift Ev,Ib */
5750 shift = 2;
5751 grp2:
5753 ot = mo_b_d(b, dflag);
5754 modrm = x86_ldub_code(env, s);
5755 mod = (modrm >> 6) & 3;
5756 op = (modrm >> 3) & 7;
5758 if (mod != 3) {
5759 if (shift == 2) {
5760 s->rip_offset = 1;
5762 gen_lea_modrm(env, s, modrm);
5763 opreg = OR_TMP0;
5764 } else {
5765 opreg = (modrm & 7) | REX_B(s);
5768 /* simpler op */
5769 if (shift == 0) {
5770 gen_shift(s, op, ot, opreg, OR_ECX);
5771 } else {
5772 if (shift == 2) {
5773 shift = x86_ldub_code(env, s);
5775 gen_shifti(s, op, ot, opreg, shift);
5778 break;
5779 case 0xd0:
5780 case 0xd1:
5781 /* shift Ev,1 */
5782 shift = 1;
5783 goto grp2;
5784 case 0xd2:
5785 case 0xd3:
5786 /* shift Ev,cl */
5787 shift = 0;
5788 goto grp2;
5790 case 0x1a4: /* shld imm */
5791 op = 0;
5792 shift = 1;
5793 goto do_shiftd;
5794 case 0x1a5: /* shld cl */
5795 op = 0;
5796 shift = 0;
5797 goto do_shiftd;
5798 case 0x1ac: /* shrd imm */
5799 op = 1;
5800 shift = 1;
5801 goto do_shiftd;
5802 case 0x1ad: /* shrd cl */
5803 op = 1;
5804 shift = 0;
5805 do_shiftd:
5806 ot = dflag;
5807 modrm = x86_ldub_code(env, s);
5808 mod = (modrm >> 6) & 3;
5809 rm = (modrm & 7) | REX_B(s);
5810 reg = ((modrm >> 3) & 7) | rex_r;
5811 if (mod != 3) {
5812 gen_lea_modrm(env, s, modrm);
5813 opreg = OR_TMP0;
5814 } else {
5815 opreg = rm;
5817 gen_op_mov_v_reg(s, ot, s->T1, reg);
5819 if (shift) {
5820 TCGv imm = tcg_const_tl(x86_ldub_code(env, s));
5821 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5822 tcg_temp_free(imm);
5823 } else {
5824 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5826 break;
5828 /************************/
5829 /* floats */
5830 case 0xd8 ... 0xdf:
5831 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5832 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5833 /* XXX: what to do if illegal op ? */
5834 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5835 break;
5837 modrm = x86_ldub_code(env, s);
5838 mod = (modrm >> 6) & 3;
5839 rm = modrm & 7;
5840 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5841 if (mod != 3) {
5842 /* memory op */
5843 gen_lea_modrm(env, s, modrm);
5844 switch(op) {
5845 case 0x00 ... 0x07: /* fxxxs */
5846 case 0x10 ... 0x17: /* fixxxl */
5847 case 0x20 ... 0x27: /* fxxxl */
5848 case 0x30 ... 0x37: /* fixxx */
5850 int op1;
5851 op1 = op & 7;
5853 switch(op >> 4) {
5854 case 0:
5855 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5856 s->mem_index, MO_LEUL);
5857 gen_helper_flds_FT0(cpu_env, s->tmp2_i32);
5858 break;
5859 case 1:
5860 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5861 s->mem_index, MO_LEUL);
5862 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5863 break;
5864 case 2:
5865 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5866 s->mem_index, MO_LEQ);
5867 gen_helper_fldl_FT0(cpu_env, s->tmp1_i64);
5868 break;
5869 case 3:
5870 default:
5871 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5872 s->mem_index, MO_LESW);
5873 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5874 break;
5877 gen_helper_fp_arith_ST0_FT0(op1);
5878 if (op1 == 3) {
5879 /* fcomp needs pop */
5880 gen_helper_fpop(cpu_env);
5883 break;
5884 case 0x08: /* flds */
5885 case 0x0a: /* fsts */
5886 case 0x0b: /* fstps */
5887 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5888 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5889 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5890 switch(op & 7) {
5891 case 0:
5892 switch(op >> 4) {
5893 case 0:
5894 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5895 s->mem_index, MO_LEUL);
5896 gen_helper_flds_ST0(cpu_env, s->tmp2_i32);
5897 break;
5898 case 1:
5899 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5900 s->mem_index, MO_LEUL);
5901 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
5902 break;
5903 case 2:
5904 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5905 s->mem_index, MO_LEQ);
5906 gen_helper_fldl_ST0(cpu_env, s->tmp1_i64);
5907 break;
5908 case 3:
5909 default:
5910 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5911 s->mem_index, MO_LESW);
5912 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
5913 break;
5915 break;
5916 case 1:
5917 /* XXX: the corresponding CPUID bit must be tested ! */
5918 switch(op >> 4) {
5919 case 1:
5920 gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env);
5921 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5922 s->mem_index, MO_LEUL);
5923 break;
5924 case 2:
5925 gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env);
5926 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
5927 s->mem_index, MO_LEQ);
5928 break;
5929 case 3:
5930 default:
5931 gen_helper_fistt_ST0(s->tmp2_i32, cpu_env);
5932 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5933 s->mem_index, MO_LEUW);
5934 break;
5936 gen_helper_fpop(cpu_env);
5937 break;
5938 default:
5939 switch(op >> 4) {
5940 case 0:
5941 gen_helper_fsts_ST0(s->tmp2_i32, cpu_env);
5942 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5943 s->mem_index, MO_LEUL);
5944 break;
5945 case 1:
5946 gen_helper_fistl_ST0(s->tmp2_i32, cpu_env);
5947 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5948 s->mem_index, MO_LEUL);
5949 break;
5950 case 2:
5951 gen_helper_fstl_ST0(s->tmp1_i64, cpu_env);
5952 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
5953 s->mem_index, MO_LEQ);
5954 break;
5955 case 3:
5956 default:
5957 gen_helper_fist_ST0(s->tmp2_i32, cpu_env);
5958 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5959 s->mem_index, MO_LEUW);
5960 break;
5962 if ((op & 7) == 3)
5963 gen_helper_fpop(cpu_env);
5964 break;
5966 break;
5967 case 0x0c: /* fldenv mem */
5968 gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
5969 break;
5970 case 0x0d: /* fldcw mem */
5971 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5972 s->mem_index, MO_LEUW);
5973 gen_helper_fldcw(cpu_env, s->tmp2_i32);
5974 break;
5975 case 0x0e: /* fnstenv mem */
5976 gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
5977 break;
5978 case 0x0f: /* fnstcw mem */
5979 gen_helper_fnstcw(s->tmp2_i32, cpu_env);
5980 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5981 s->mem_index, MO_LEUW);
5982 break;
5983 case 0x1d: /* fldt mem */
5984 gen_helper_fldt_ST0(cpu_env, s->A0);
5985 break;
5986 case 0x1f: /* fstpt mem */
5987 gen_helper_fstt_ST0(cpu_env, s->A0);
5988 gen_helper_fpop(cpu_env);
5989 break;
5990 case 0x2c: /* frstor mem */
5991 gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1));
5992 break;
5993 case 0x2e: /* fnsave mem */
5994 gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1));
5995 break;
5996 case 0x2f: /* fnstsw mem */
5997 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
5998 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5999 s->mem_index, MO_LEUW);
6000 break;
6001 case 0x3c: /* fbld */
6002 gen_helper_fbld_ST0(cpu_env, s->A0);
6003 break;
6004 case 0x3e: /* fbstp */
6005 gen_helper_fbst_ST0(cpu_env, s->A0);
6006 gen_helper_fpop(cpu_env);
6007 break;
6008 case 0x3d: /* fildll */
6009 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6010 gen_helper_fildll_ST0(cpu_env, s->tmp1_i64);
6011 break;
6012 case 0x3f: /* fistpll */
6013 gen_helper_fistll_ST0(s->tmp1_i64, cpu_env);
6014 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6015 gen_helper_fpop(cpu_env);
6016 break;
6017 default:
6018 goto unknown_op;
6020 } else {
6021 /* register float ops */
6022 opreg = rm;
6024 switch(op) {
6025 case 0x08: /* fld sti */
6026 gen_helper_fpush(cpu_env);
6027 gen_helper_fmov_ST0_STN(cpu_env,
6028 tcg_const_i32((opreg + 1) & 7));
6029 break;
6030 case 0x09: /* fxchg sti */
6031 case 0x29: /* fxchg4 sti, undocumented op */
6032 case 0x39: /* fxchg7 sti, undocumented op */
6033 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
6034 break;
6035 case 0x0a: /* grp d9/2 */
6036 switch(rm) {
6037 case 0: /* fnop */
6038 /* check exceptions (FreeBSD FPU probe) */
6039 gen_helper_fwait(cpu_env);
6040 break;
6041 default:
6042 goto unknown_op;
6044 break;
6045 case 0x0c: /* grp d9/4 */
6046 switch(rm) {
6047 case 0: /* fchs */
6048 gen_helper_fchs_ST0(cpu_env);
6049 break;
6050 case 1: /* fabs */
6051 gen_helper_fabs_ST0(cpu_env);
6052 break;
6053 case 4: /* ftst */
6054 gen_helper_fldz_FT0(cpu_env);
6055 gen_helper_fcom_ST0_FT0(cpu_env);
6056 break;
6057 case 5: /* fxam */
6058 gen_helper_fxam_ST0(cpu_env);
6059 break;
6060 default:
6061 goto unknown_op;
6063 break;
6064 case 0x0d: /* grp d9/5 */
6066 switch(rm) {
6067 case 0:
6068 gen_helper_fpush(cpu_env);
6069 gen_helper_fld1_ST0(cpu_env);
6070 break;
6071 case 1:
6072 gen_helper_fpush(cpu_env);
6073 gen_helper_fldl2t_ST0(cpu_env);
6074 break;
6075 case 2:
6076 gen_helper_fpush(cpu_env);
6077 gen_helper_fldl2e_ST0(cpu_env);
6078 break;
6079 case 3:
6080 gen_helper_fpush(cpu_env);
6081 gen_helper_fldpi_ST0(cpu_env);
6082 break;
6083 case 4:
6084 gen_helper_fpush(cpu_env);
6085 gen_helper_fldlg2_ST0(cpu_env);
6086 break;
6087 case 5:
6088 gen_helper_fpush(cpu_env);
6089 gen_helper_fldln2_ST0(cpu_env);
6090 break;
6091 case 6:
6092 gen_helper_fpush(cpu_env);
6093 gen_helper_fldz_ST0(cpu_env);
6094 break;
6095 default:
6096 goto unknown_op;
6099 break;
6100 case 0x0e: /* grp d9/6 */
6101 switch(rm) {
6102 case 0: /* f2xm1 */
6103 gen_helper_f2xm1(cpu_env);
6104 break;
6105 case 1: /* fyl2x */
6106 gen_helper_fyl2x(cpu_env);
6107 break;
6108 case 2: /* fptan */
6109 gen_helper_fptan(cpu_env);
6110 break;
6111 case 3: /* fpatan */
6112 gen_helper_fpatan(cpu_env);
6113 break;
6114 case 4: /* fxtract */
6115 gen_helper_fxtract(cpu_env);
6116 break;
6117 case 5: /* fprem1 */
6118 gen_helper_fprem1(cpu_env);
6119 break;
6120 case 6: /* fdecstp */
6121 gen_helper_fdecstp(cpu_env);
6122 break;
6123 default:
6124 case 7: /* fincstp */
6125 gen_helper_fincstp(cpu_env);
6126 break;
6128 break;
6129 case 0x0f: /* grp d9/7 */
6130 switch(rm) {
6131 case 0: /* fprem */
6132 gen_helper_fprem(cpu_env);
6133 break;
6134 case 1: /* fyl2xp1 */
6135 gen_helper_fyl2xp1(cpu_env);
6136 break;
6137 case 2: /* fsqrt */
6138 gen_helper_fsqrt(cpu_env);
6139 break;
6140 case 3: /* fsincos */
6141 gen_helper_fsincos(cpu_env);
6142 break;
6143 case 5: /* fscale */
6144 gen_helper_fscale(cpu_env);
6145 break;
6146 case 4: /* frndint */
6147 gen_helper_frndint(cpu_env);
6148 break;
6149 case 6: /* fsin */
6150 gen_helper_fsin(cpu_env);
6151 break;
6152 default:
6153 case 7: /* fcos */
6154 gen_helper_fcos(cpu_env);
6155 break;
6157 break;
6158 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6159 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6160 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6162 int op1;
6164 op1 = op & 7;
6165 if (op >= 0x20) {
6166 gen_helper_fp_arith_STN_ST0(op1, opreg);
6167 if (op >= 0x30)
6168 gen_helper_fpop(cpu_env);
6169 } else {
6170 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6171 gen_helper_fp_arith_ST0_FT0(op1);
6174 break;
6175 case 0x02: /* fcom */
6176 case 0x22: /* fcom2, undocumented op */
6177 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6178 gen_helper_fcom_ST0_FT0(cpu_env);
6179 break;
6180 case 0x03: /* fcomp */
6181 case 0x23: /* fcomp3, undocumented op */
6182 case 0x32: /* fcomp5, undocumented op */
6183 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6184 gen_helper_fcom_ST0_FT0(cpu_env);
6185 gen_helper_fpop(cpu_env);
6186 break;
6187 case 0x15: /* da/5 */
6188 switch(rm) {
6189 case 1: /* fucompp */
6190 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6191 gen_helper_fucom_ST0_FT0(cpu_env);
6192 gen_helper_fpop(cpu_env);
6193 gen_helper_fpop(cpu_env);
6194 break;
6195 default:
6196 goto unknown_op;
6198 break;
6199 case 0x1c:
6200 switch(rm) {
6201 case 0: /* feni (287 only, just do nop here) */
6202 break;
6203 case 1: /* fdisi (287 only, just do nop here) */
6204 break;
6205 case 2: /* fclex */
6206 gen_helper_fclex(cpu_env);
6207 break;
6208 case 3: /* fninit */
6209 gen_helper_fninit(cpu_env);
6210 break;
6211 case 4: /* fsetpm (287 only, just do nop here) */
6212 break;
6213 default:
6214 goto unknown_op;
6216 break;
6217 case 0x1d: /* fucomi */
6218 if (!(s->cpuid_features & CPUID_CMOV)) {
6219 goto illegal_op;
6221 gen_update_cc_op(s);
6222 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6223 gen_helper_fucomi_ST0_FT0(cpu_env);
6224 set_cc_op(s, CC_OP_EFLAGS);
6225 break;
6226 case 0x1e: /* fcomi */
6227 if (!(s->cpuid_features & CPUID_CMOV)) {
6228 goto illegal_op;
6230 gen_update_cc_op(s);
6231 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6232 gen_helper_fcomi_ST0_FT0(cpu_env);
6233 set_cc_op(s, CC_OP_EFLAGS);
6234 break;
6235 case 0x28: /* ffree sti */
6236 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6237 break;
6238 case 0x2a: /* fst sti */
6239 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6240 break;
6241 case 0x2b: /* fstp sti */
6242 case 0x0b: /* fstp1 sti, undocumented op */
6243 case 0x3a: /* fstp8 sti, undocumented op */
6244 case 0x3b: /* fstp9 sti, undocumented op */
6245 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6246 gen_helper_fpop(cpu_env);
6247 break;
6248 case 0x2c: /* fucom st(i) */
6249 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6250 gen_helper_fucom_ST0_FT0(cpu_env);
6251 break;
6252 case 0x2d: /* fucomp st(i) */
6253 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6254 gen_helper_fucom_ST0_FT0(cpu_env);
6255 gen_helper_fpop(cpu_env);
6256 break;
6257 case 0x33: /* de/3 */
6258 switch(rm) {
6259 case 1: /* fcompp */
6260 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6261 gen_helper_fcom_ST0_FT0(cpu_env);
6262 gen_helper_fpop(cpu_env);
6263 gen_helper_fpop(cpu_env);
6264 break;
6265 default:
6266 goto unknown_op;
6268 break;
6269 case 0x38: /* ffreep sti, undocumented op */
6270 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6271 gen_helper_fpop(cpu_env);
6272 break;
6273 case 0x3c: /* df/4 */
6274 switch(rm) {
6275 case 0:
6276 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6277 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
6278 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
6279 break;
6280 default:
6281 goto unknown_op;
6283 break;
6284 case 0x3d: /* fucomip */
6285 if (!(s->cpuid_features & CPUID_CMOV)) {
6286 goto illegal_op;
6288 gen_update_cc_op(s);
6289 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6290 gen_helper_fucomi_ST0_FT0(cpu_env);
6291 gen_helper_fpop(cpu_env);
6292 set_cc_op(s, CC_OP_EFLAGS);
6293 break;
6294 case 0x3e: /* fcomip */
6295 if (!(s->cpuid_features & CPUID_CMOV)) {
6296 goto illegal_op;
6298 gen_update_cc_op(s);
6299 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6300 gen_helper_fcomi_ST0_FT0(cpu_env);
6301 gen_helper_fpop(cpu_env);
6302 set_cc_op(s, CC_OP_EFLAGS);
6303 break;
6304 case 0x10 ... 0x13: /* fcmovxx */
6305 case 0x18 ... 0x1b:
6307 int op1;
6308 TCGLabel *l1;
6309 static const uint8_t fcmov_cc[8] = {
6310 (JCC_B << 1),
6311 (JCC_Z << 1),
6312 (JCC_BE << 1),
6313 (JCC_P << 1),
6316 if (!(s->cpuid_features & CPUID_CMOV)) {
6317 goto illegal_op;
6319 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6320 l1 = gen_new_label();
6321 gen_jcc1_noeob(s, op1, l1);
6322 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6323 gen_set_label(l1);
6325 break;
6326 default:
6327 goto unknown_op;
6330 break;
6331 /************************/
6332 /* string ops */
6334 case 0xa4: /* movsS */
6335 case 0xa5:
6336 ot = mo_b_d(b, dflag);
6337 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6338 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6339 } else {
6340 gen_movs(s, ot);
6342 break;
6344 case 0xaa: /* stosS */
6345 case 0xab:
6346 ot = mo_b_d(b, dflag);
6347 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6348 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6349 } else {
6350 gen_stos(s, ot);
6352 break;
6353 case 0xac: /* lodsS */
6354 case 0xad:
6355 ot = mo_b_d(b, dflag);
6356 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6357 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6358 } else {
6359 gen_lods(s, ot);
6361 break;
6362 case 0xae: /* scasS */
6363 case 0xaf:
6364 ot = mo_b_d(b, dflag);
6365 if (prefixes & PREFIX_REPNZ) {
6366 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6367 } else if (prefixes & PREFIX_REPZ) {
6368 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6369 } else {
6370 gen_scas(s, ot);
6372 break;
6374 case 0xa6: /* cmpsS */
6375 case 0xa7:
6376 ot = mo_b_d(b, dflag);
6377 if (prefixes & PREFIX_REPNZ) {
6378 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6379 } else if (prefixes & PREFIX_REPZ) {
6380 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6381 } else {
6382 gen_cmps(s, ot);
6384 break;
6385 case 0x6c: /* insS */
6386 case 0x6d:
6387 ot = mo_b_d32(b, dflag);
6388 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6389 gen_check_io(s, ot, pc_start - s->cs_base,
6390 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6391 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6392 gen_io_start();
6394 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6395 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6396 /* jump generated by gen_repz_ins */
6397 } else {
6398 gen_ins(s, ot);
6399 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6400 gen_jmp(s, s->pc - s->cs_base);
6403 break;
6404 case 0x6e: /* outsS */
6405 case 0x6f:
6406 ot = mo_b_d32(b, dflag);
6407 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6408 gen_check_io(s, ot, pc_start - s->cs_base,
6409 svm_is_rep(prefixes) | 4);
6410 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6411 gen_io_start();
6413 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6414 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6415 /* jump generated by gen_repz_outs */
6416 } else {
6417 gen_outs(s, ot);
6418 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6419 gen_jmp(s, s->pc - s->cs_base);
6422 break;
6424 /************************/
6425 /* port I/O */
6427 case 0xe4:
6428 case 0xe5:
6429 ot = mo_b_d32(b, dflag);
6430 val = x86_ldub_code(env, s);
6431 tcg_gen_movi_tl(s->T0, val);
6432 gen_check_io(s, ot, pc_start - s->cs_base,
6433 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6434 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6435 gen_io_start();
6437 tcg_gen_movi_i32(s->tmp2_i32, val);
6438 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6439 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6440 gen_bpt_io(s, s->tmp2_i32, ot);
6441 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6442 gen_jmp(s, s->pc - s->cs_base);
6444 break;
6445 case 0xe6:
6446 case 0xe7:
6447 ot = mo_b_d32(b, dflag);
6448 val = x86_ldub_code(env, s);
6449 tcg_gen_movi_tl(s->T0, val);
6450 gen_check_io(s, ot, pc_start - s->cs_base,
6451 svm_is_rep(prefixes));
6452 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6454 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6455 gen_io_start();
6457 tcg_gen_movi_i32(s->tmp2_i32, val);
6458 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6459 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6460 gen_bpt_io(s, s->tmp2_i32, ot);
6461 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6462 gen_jmp(s, s->pc - s->cs_base);
6464 break;
6465 case 0xec:
6466 case 0xed:
6467 ot = mo_b_d32(b, dflag);
6468 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6469 gen_check_io(s, ot, pc_start - s->cs_base,
6470 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6471 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6472 gen_io_start();
6474 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
6475 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6476 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6477 gen_bpt_io(s, s->tmp2_i32, ot);
6478 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6479 gen_jmp(s, s->pc - s->cs_base);
6481 break;
6482 case 0xee:
6483 case 0xef:
6484 ot = mo_b_d32(b, dflag);
6485 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6486 gen_check_io(s, ot, pc_start - s->cs_base,
6487 svm_is_rep(prefixes));
6488 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6490 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6491 gen_io_start();
6493 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
6494 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6495 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6496 gen_bpt_io(s, s->tmp2_i32, ot);
6497 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6498 gen_jmp(s, s->pc - s->cs_base);
6500 break;
6502 /************************/
6503 /* control */
6504 case 0xc2: /* ret im */
6505 val = x86_ldsw_code(env, s);
6506 ot = gen_pop_T0(s);
6507 gen_stack_update(s, val + (1 << ot));
6508 /* Note that gen_pop_T0 uses a zero-extending load. */
6509 gen_op_jmp_v(s->T0);
6510 gen_bnd_jmp(s);
6511 gen_jr(s, s->T0);
6512 break;
6513 case 0xc3: /* ret */
6514 ot = gen_pop_T0(s);
6515 gen_pop_update(s, ot);
6516 /* Note that gen_pop_T0 uses a zero-extending load. */
6517 gen_op_jmp_v(s->T0);
6518 gen_bnd_jmp(s);
6519 gen_jr(s, s->T0);
6520 break;
6521 case 0xca: /* lret im */
6522 val = x86_ldsw_code(env, s);
6523 do_lret:
6524 if (s->pe && !s->vm86) {
6525 gen_update_cc_op(s);
6526 gen_jmp_im(s, pc_start - s->cs_base);
6527 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6528 tcg_const_i32(val));
6529 } else {
6530 gen_stack_A0(s);
6531 /* pop offset */
6532 gen_op_ld_v(s, dflag, s->T0, s->A0);
6533 /* NOTE: keeping EIP updated is not a problem in case of
6534 exception */
6535 gen_op_jmp_v(s->T0);
6536 /* pop selector */
6537 gen_add_A0_im(s, 1 << dflag);
6538 gen_op_ld_v(s, dflag, s->T0, s->A0);
6539 gen_op_movl_seg_T0_vm(s, R_CS);
6540 /* add stack offset */
6541 gen_stack_update(s, val + (2 << dflag));
6543 gen_eob(s);
6544 break;
6545 case 0xcb: /* lret */
6546 val = 0;
6547 goto do_lret;
6548 case 0xcf: /* iret */
6549 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6550 if (!s->pe) {
6551 /* real mode */
6552 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6553 set_cc_op(s, CC_OP_EFLAGS);
6554 } else if (s->vm86) {
6555 if (s->iopl != 3) {
6556 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6557 } else {
6558 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6559 set_cc_op(s, CC_OP_EFLAGS);
6561 } else {
6562 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6563 tcg_const_i32(s->pc - s->cs_base));
6564 set_cc_op(s, CC_OP_EFLAGS);
6566 gen_eob(s);
6567 break;
6568 case 0xe8: /* call im */
6570 if (dflag != MO_16) {
6571 tval = (int32_t)insn_get(env, s, MO_32);
6572 } else {
6573 tval = (int16_t)insn_get(env, s, MO_16);
6575 next_eip = s->pc - s->cs_base;
6576 tval += next_eip;
6577 if (dflag == MO_16) {
6578 tval &= 0xffff;
6579 } else if (!CODE64(s)) {
6580 tval &= 0xffffffff;
6582 tcg_gen_movi_tl(s->T0, next_eip);
6583 gen_push_v(s, s->T0);
6584 gen_bnd_jmp(s);
6585 gen_jmp(s, tval);
6587 break;
6588 case 0x9a: /* lcall im */
6590 unsigned int selector, offset;
6592 if (CODE64(s))
6593 goto illegal_op;
6594 ot = dflag;
6595 offset = insn_get(env, s, ot);
6596 selector = insn_get(env, s, MO_16);
6598 tcg_gen_movi_tl(s->T0, selector);
6599 tcg_gen_movi_tl(s->T1, offset);
6601 goto do_lcall;
6602 case 0xe9: /* jmp im */
6603 if (dflag != MO_16) {
6604 tval = (int32_t)insn_get(env, s, MO_32);
6605 } else {
6606 tval = (int16_t)insn_get(env, s, MO_16);
6608 tval += s->pc - s->cs_base;
6609 if (dflag == MO_16) {
6610 tval &= 0xffff;
6611 } else if (!CODE64(s)) {
6612 tval &= 0xffffffff;
6614 gen_bnd_jmp(s);
6615 gen_jmp(s, tval);
6616 break;
6617 case 0xea: /* ljmp im */
6619 unsigned int selector, offset;
6621 if (CODE64(s))
6622 goto illegal_op;
6623 ot = dflag;
6624 offset = insn_get(env, s, ot);
6625 selector = insn_get(env, s, MO_16);
6627 tcg_gen_movi_tl(s->T0, selector);
6628 tcg_gen_movi_tl(s->T1, offset);
6630 goto do_ljmp;
6631 case 0xeb: /* jmp Jb */
6632 tval = (int8_t)insn_get(env, s, MO_8);
6633 tval += s->pc - s->cs_base;
6634 if (dflag == MO_16) {
6635 tval &= 0xffff;
6637 gen_jmp(s, tval);
6638 break;
6639 case 0x70 ... 0x7f: /* jcc Jb */
6640 tval = (int8_t)insn_get(env, s, MO_8);
6641 goto do_jcc;
6642 case 0x180 ... 0x18f: /* jcc Jv */
6643 if (dflag != MO_16) {
6644 tval = (int32_t)insn_get(env, s, MO_32);
6645 } else {
6646 tval = (int16_t)insn_get(env, s, MO_16);
6648 do_jcc:
6649 next_eip = s->pc - s->cs_base;
6650 tval += next_eip;
6651 if (dflag == MO_16) {
6652 tval &= 0xffff;
6654 gen_bnd_jmp(s);
6655 gen_jcc(s, b, tval, next_eip);
6656 break;
6658 case 0x190 ... 0x19f: /* setcc Gv */
6659 modrm = x86_ldub_code(env, s);
6660 gen_setcc1(s, b, s->T0);
6661 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6662 break;
6663 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6664 if (!(s->cpuid_features & CPUID_CMOV)) {
6665 goto illegal_op;
6667 ot = dflag;
6668 modrm = x86_ldub_code(env, s);
6669 reg = ((modrm >> 3) & 7) | rex_r;
6670 gen_cmovcc1(env, s, ot, b, modrm, reg);
6671 break;
6673 /************************/
6674 /* flags */
6675 case 0x9c: /* pushf */
6676 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6677 if (s->vm86 && s->iopl != 3) {
6678 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6679 } else {
6680 gen_update_cc_op(s);
6681 gen_helper_read_eflags(s->T0, cpu_env);
6682 gen_push_v(s, s->T0);
6684 break;
6685 case 0x9d: /* popf */
6686 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6687 if (s->vm86 && s->iopl != 3) {
6688 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6689 } else {
6690 ot = gen_pop_T0(s);
6691 if (s->cpl == 0) {
6692 if (dflag != MO_16) {
6693 gen_helper_write_eflags(cpu_env, s->T0,
6694 tcg_const_i32((TF_MASK | AC_MASK |
6695 ID_MASK | NT_MASK |
6696 IF_MASK |
6697 IOPL_MASK)));
6698 } else {
6699 gen_helper_write_eflags(cpu_env, s->T0,
6700 tcg_const_i32((TF_MASK | AC_MASK |
6701 ID_MASK | NT_MASK |
6702 IF_MASK | IOPL_MASK)
6703 & 0xffff));
6705 } else {
6706 if (s->cpl <= s->iopl) {
6707 if (dflag != MO_16) {
6708 gen_helper_write_eflags(cpu_env, s->T0,
6709 tcg_const_i32((TF_MASK |
6710 AC_MASK |
6711 ID_MASK |
6712 NT_MASK |
6713 IF_MASK)));
6714 } else {
6715 gen_helper_write_eflags(cpu_env, s->T0,
6716 tcg_const_i32((TF_MASK |
6717 AC_MASK |
6718 ID_MASK |
6719 NT_MASK |
6720 IF_MASK)
6721 & 0xffff));
6723 } else {
6724 if (dflag != MO_16) {
6725 gen_helper_write_eflags(cpu_env, s->T0,
6726 tcg_const_i32((TF_MASK | AC_MASK |
6727 ID_MASK | NT_MASK)));
6728 } else {
6729 gen_helper_write_eflags(cpu_env, s->T0,
6730 tcg_const_i32((TF_MASK | AC_MASK |
6731 ID_MASK | NT_MASK)
6732 & 0xffff));
6736 gen_pop_update(s, ot);
6737 set_cc_op(s, CC_OP_EFLAGS);
6738 /* abort translation because TF/AC flag may change */
6739 gen_jmp_im(s, s->pc - s->cs_base);
6740 gen_eob(s);
6742 break;
6743 case 0x9e: /* sahf */
6744 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6745 goto illegal_op;
6746 gen_op_mov_v_reg(s, MO_8, s->T0, R_AH);
6747 gen_compute_eflags(s);
6748 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6749 tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6750 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
6751 break;
6752 case 0x9f: /* lahf */
6753 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6754 goto illegal_op;
6755 gen_compute_eflags(s);
6756 /* Note: gen_compute_eflags() only gives the condition codes */
6757 tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02);
6758 gen_op_mov_reg_v(s, MO_8, R_AH, s->T0);
6759 break;
6760 case 0xf5: /* cmc */
6761 gen_compute_eflags(s);
6762 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6763 break;
6764 case 0xf8: /* clc */
6765 gen_compute_eflags(s);
6766 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6767 break;
6768 case 0xf9: /* stc */
6769 gen_compute_eflags(s);
6770 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6771 break;
6772 case 0xfc: /* cld */
6773 tcg_gen_movi_i32(s->tmp2_i32, 1);
6774 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6775 break;
6776 case 0xfd: /* std */
6777 tcg_gen_movi_i32(s->tmp2_i32, -1);
6778 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6779 break;
6781 /************************/
6782 /* bit operations */
6783 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6784 ot = dflag;
6785 modrm = x86_ldub_code(env, s);
6786 op = (modrm >> 3) & 7;
6787 mod = (modrm >> 6) & 3;
6788 rm = (modrm & 7) | REX_B(s);
6789 if (mod != 3) {
6790 s->rip_offset = 1;
6791 gen_lea_modrm(env, s, modrm);
6792 if (!(s->prefix & PREFIX_LOCK)) {
6793 gen_op_ld_v(s, ot, s->T0, s->A0);
6795 } else {
6796 gen_op_mov_v_reg(s, ot, s->T0, rm);
6798 /* load shift */
6799 val = x86_ldub_code(env, s);
6800 tcg_gen_movi_tl(s->T1, val);
6801 if (op < 4)
6802 goto unknown_op;
6803 op -= 4;
6804 goto bt_op;
6805 case 0x1a3: /* bt Gv, Ev */
6806 op = 0;
6807 goto do_btx;
6808 case 0x1ab: /* bts */
6809 op = 1;
6810 goto do_btx;
6811 case 0x1b3: /* btr */
6812 op = 2;
6813 goto do_btx;
6814 case 0x1bb: /* btc */
6815 op = 3;
6816 do_btx:
6817 ot = dflag;
6818 modrm = x86_ldub_code(env, s);
6819 reg = ((modrm >> 3) & 7) | rex_r;
6820 mod = (modrm >> 6) & 3;
6821 rm = (modrm & 7) | REX_B(s);
6822 gen_op_mov_v_reg(s, MO_32, s->T1, reg);
6823 if (mod != 3) {
6824 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6825 /* specific case: we need to add a displacement */
6826 gen_exts(ot, s->T1);
6827 tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
6828 tcg_gen_shli_tl(s->tmp0, s->tmp0, ot);
6829 tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a), s->tmp0);
6830 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
6831 if (!(s->prefix & PREFIX_LOCK)) {
6832 gen_op_ld_v(s, ot, s->T0, s->A0);
6834 } else {
6835 gen_op_mov_v_reg(s, ot, s->T0, rm);
6837 bt_op:
6838 tcg_gen_andi_tl(s->T1, s->T1, (1 << (3 + ot)) - 1);
6839 tcg_gen_movi_tl(s->tmp0, 1);
6840 tcg_gen_shl_tl(s->tmp0, s->tmp0, s->T1);
6841 if (s->prefix & PREFIX_LOCK) {
6842 switch (op) {
6843 case 0: /* bt */
6844 /* Needs no atomic ops; we surpressed the normal
6845 memory load for LOCK above so do it now. */
6846 gen_op_ld_v(s, ot, s->T0, s->A0);
6847 break;
6848 case 1: /* bts */
6849 tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, s->tmp0,
6850 s->mem_index, ot | MO_LE);
6851 break;
6852 case 2: /* btr */
6853 tcg_gen_not_tl(s->tmp0, s->tmp0);
6854 tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, s->tmp0,
6855 s->mem_index, ot | MO_LE);
6856 break;
6857 default:
6858 case 3: /* btc */
6859 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0,
6860 s->mem_index, ot | MO_LE);
6861 break;
6863 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6864 } else {
6865 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6866 switch (op) {
6867 case 0: /* bt */
6868 /* Data already loaded; nothing to do. */
6869 break;
6870 case 1: /* bts */
6871 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
6872 break;
6873 case 2: /* btr */
6874 tcg_gen_andc_tl(s->T0, s->T0, s->tmp0);
6875 break;
6876 default:
6877 case 3: /* btc */
6878 tcg_gen_xor_tl(s->T0, s->T0, s->tmp0);
6879 break;
6881 if (op != 0) {
6882 if (mod != 3) {
6883 gen_op_st_v(s, ot, s->T0, s->A0);
6884 } else {
6885 gen_op_mov_reg_v(s, ot, rm, s->T0);
6890 /* Delay all CC updates until after the store above. Note that
6891 C is the result of the test, Z is unchanged, and the others
6892 are all undefined. */
6893 switch (s->cc_op) {
6894 case CC_OP_MULB ... CC_OP_MULQ:
6895 case CC_OP_ADDB ... CC_OP_ADDQ:
6896 case CC_OP_ADCB ... CC_OP_ADCQ:
6897 case CC_OP_SUBB ... CC_OP_SUBQ:
6898 case CC_OP_SBBB ... CC_OP_SBBQ:
6899 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6900 case CC_OP_INCB ... CC_OP_INCQ:
6901 case CC_OP_DECB ... CC_OP_DECQ:
6902 case CC_OP_SHLB ... CC_OP_SHLQ:
6903 case CC_OP_SARB ... CC_OP_SARQ:
6904 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6905 /* Z was going to be computed from the non-zero status of CC_DST.
6906 We can get that same Z value (and the new C value) by leaving
6907 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6908 same width. */
6909 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
6910 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6911 break;
6912 default:
6913 /* Otherwise, generate EFLAGS and replace the C bit. */
6914 gen_compute_eflags(s);
6915 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, s->tmp4,
6916 ctz32(CC_C), 1);
6917 break;
6919 break;
6920 case 0x1bc: /* bsf / tzcnt */
6921 case 0x1bd: /* bsr / lzcnt */
6922 ot = dflag;
6923 modrm = x86_ldub_code(env, s);
6924 reg = ((modrm >> 3) & 7) | rex_r;
6925 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6926 gen_extu(ot, s->T0);
6928 /* Note that lzcnt and tzcnt are in different extensions. */
6929 if ((prefixes & PREFIX_REPZ)
6930 && (b & 1
6931 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6932 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6933 int size = 8 << ot;
6934 /* For lzcnt/tzcnt, C bit is defined related to the input. */
6935 tcg_gen_mov_tl(cpu_cc_src, s->T0);
6936 if (b & 1) {
6937 /* For lzcnt, reduce the target_ulong result by the
6938 number of zeros that we expect to find at the top. */
6939 tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
6940 tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
6941 } else {
6942 /* For tzcnt, a zero input must return the operand size. */
6943 tcg_gen_ctzi_tl(s->T0, s->T0, size);
6945 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
6946 gen_op_update1_cc(s);
6947 set_cc_op(s, CC_OP_BMILGB + ot);
6948 } else {
6949 /* For bsr/bsf, only the Z bit is defined and it is related
6950 to the input and not the result. */
6951 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
6952 set_cc_op(s, CC_OP_LOGICB + ot);
6954 /* ??? The manual says that the output is undefined when the
6955 input is zero, but real hardware leaves it unchanged, and
6956 real programs appear to depend on that. Accomplish this
6957 by passing the output as the value to return upon zero. */
6958 if (b & 1) {
6959 /* For bsr, return the bit index of the first 1 bit,
6960 not the count of leading zeros. */
6961 tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
6962 tcg_gen_clz_tl(s->T0, s->T0, s->T1);
6963 tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
6964 } else {
6965 tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
6968 gen_op_mov_reg_v(s, ot, reg, s->T0);
6969 break;
6970 /************************/
6971 /* bcd */
6972 case 0x27: /* daa */
6973 if (CODE64(s))
6974 goto illegal_op;
6975 gen_update_cc_op(s);
6976 gen_helper_daa(cpu_env);
6977 set_cc_op(s, CC_OP_EFLAGS);
6978 break;
6979 case 0x2f: /* das */
6980 if (CODE64(s))
6981 goto illegal_op;
6982 gen_update_cc_op(s);
6983 gen_helper_das(cpu_env);
6984 set_cc_op(s, CC_OP_EFLAGS);
6985 break;
6986 case 0x37: /* aaa */
6987 if (CODE64(s))
6988 goto illegal_op;
6989 gen_update_cc_op(s);
6990 gen_helper_aaa(cpu_env);
6991 set_cc_op(s, CC_OP_EFLAGS);
6992 break;
6993 case 0x3f: /* aas */
6994 if (CODE64(s))
6995 goto illegal_op;
6996 gen_update_cc_op(s);
6997 gen_helper_aas(cpu_env);
6998 set_cc_op(s, CC_OP_EFLAGS);
6999 break;
7000 case 0xd4: /* aam */
7001 if (CODE64(s))
7002 goto illegal_op;
7003 val = x86_ldub_code(env, s);
7004 if (val == 0) {
7005 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7006 } else {
7007 gen_helper_aam(cpu_env, tcg_const_i32(val));
7008 set_cc_op(s, CC_OP_LOGICB);
7010 break;
7011 case 0xd5: /* aad */
7012 if (CODE64(s))
7013 goto illegal_op;
7014 val = x86_ldub_code(env, s);
7015 gen_helper_aad(cpu_env, tcg_const_i32(val));
7016 set_cc_op(s, CC_OP_LOGICB);
7017 break;
7018 /************************/
7019 /* misc */
7020 case 0x90: /* nop */
7021 /* XXX: correct lock test for all insn */
7022 if (prefixes & PREFIX_LOCK) {
7023 goto illegal_op;
7025 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
7026 if (REX_B(s)) {
7027 goto do_xchg_reg_eax;
7029 if (prefixes & PREFIX_REPZ) {
7030 gen_update_cc_op(s);
7031 gen_jmp_im(s, pc_start - s->cs_base);
7032 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
7033 s->base.is_jmp = DISAS_NORETURN;
7035 break;
7036 case 0x9b: /* fwait */
7037 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7038 (HF_MP_MASK | HF_TS_MASK)) {
7039 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7040 } else {
7041 gen_helper_fwait(cpu_env);
7043 break;
7044 case 0xcc: /* int3 */
7045 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7046 break;
7047 case 0xcd: /* int N */
7048 val = x86_ldub_code(env, s);
7049 if (s->vm86 && s->iopl != 3) {
7050 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7051 } else {
7052 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7054 break;
7055 case 0xce: /* into */
7056 if (CODE64(s))
7057 goto illegal_op;
7058 gen_update_cc_op(s);
7059 gen_jmp_im(s, pc_start - s->cs_base);
7060 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
7061 break;
7062 #ifdef WANT_ICEBP
7063 case 0xf1: /* icebp (undocumented, exits to external debugger) */
7064 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
7065 gen_debug(s, pc_start - s->cs_base);
7066 break;
7067 #endif
7068 case 0xfa: /* cli */
7069 if (!s->vm86) {
7070 if (s->cpl <= s->iopl) {
7071 gen_helper_cli(cpu_env);
7072 } else {
7073 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7075 } else {
7076 if (s->iopl == 3) {
7077 gen_helper_cli(cpu_env);
7078 } else {
7079 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7082 break;
7083 case 0xfb: /* sti */
7084 if (s->vm86 ? s->iopl == 3 : s->cpl <= s->iopl) {
7085 gen_helper_sti(cpu_env);
7086 /* interruptions are enabled only the first insn after sti */
7087 gen_jmp_im(s, s->pc - s->cs_base);
7088 gen_eob_inhibit_irq(s, true);
7089 } else {
7090 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7092 break;
7093 case 0x62: /* bound */
7094 if (CODE64(s))
7095 goto illegal_op;
7096 ot = dflag;
7097 modrm = x86_ldub_code(env, s);
7098 reg = (modrm >> 3) & 7;
7099 mod = (modrm >> 6) & 3;
7100 if (mod == 3)
7101 goto illegal_op;
7102 gen_op_mov_v_reg(s, ot, s->T0, reg);
7103 gen_lea_modrm(env, s, modrm);
7104 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7105 if (ot == MO_16) {
7106 gen_helper_boundw(cpu_env, s->A0, s->tmp2_i32);
7107 } else {
7108 gen_helper_boundl(cpu_env, s->A0, s->tmp2_i32);
7110 break;
7111 case 0x1c8 ... 0x1cf: /* bswap reg */
7112 reg = (b & 7) | REX_B(s);
7113 #ifdef TARGET_X86_64
7114 if (dflag == MO_64) {
7115 gen_op_mov_v_reg(s, MO_64, s->T0, reg);
7116 tcg_gen_bswap64_i64(s->T0, s->T0);
7117 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
7118 } else
7119 #endif
7121 gen_op_mov_v_reg(s, MO_32, s->T0, reg);
7122 tcg_gen_ext32u_tl(s->T0, s->T0);
7123 tcg_gen_bswap32_tl(s->T0, s->T0);
7124 gen_op_mov_reg_v(s, MO_32, reg, s->T0);
7126 break;
7127 case 0xd6: /* salc */
7128 if (CODE64(s))
7129 goto illegal_op;
7130 gen_compute_eflags_c(s, s->T0);
7131 tcg_gen_neg_tl(s->T0, s->T0);
7132 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
7133 break;
7134 case 0xe0: /* loopnz */
7135 case 0xe1: /* loopz */
7136 case 0xe2: /* loop */
7137 case 0xe3: /* jecxz */
7139 TCGLabel *l1, *l2, *l3;
7141 tval = (int8_t)insn_get(env, s, MO_8);
7142 next_eip = s->pc - s->cs_base;
7143 tval += next_eip;
7144 if (dflag == MO_16) {
7145 tval &= 0xffff;
7148 l1 = gen_new_label();
7149 l2 = gen_new_label();
7150 l3 = gen_new_label();
7151 gen_update_cc_op(s);
7152 b &= 3;
7153 switch(b) {
7154 case 0: /* loopnz */
7155 case 1: /* loopz */
7156 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7157 gen_op_jz_ecx(s, s->aflag, l3);
7158 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7159 break;
7160 case 2: /* loop */
7161 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7162 gen_op_jnz_ecx(s, s->aflag, l1);
7163 break;
7164 default:
7165 case 3: /* jcxz */
7166 gen_op_jz_ecx(s, s->aflag, l1);
7167 break;
7170 gen_set_label(l3);
7171 gen_jmp_im(s, next_eip);
7172 tcg_gen_br(l2);
7174 gen_set_label(l1);
7175 gen_jmp_im(s, tval);
7176 gen_set_label(l2);
7177 gen_eob(s);
7179 break;
7180 case 0x130: /* wrmsr */
7181 case 0x132: /* rdmsr */
7182 if (s->cpl != 0) {
7183 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7184 } else {
7185 gen_update_cc_op(s);
7186 gen_jmp_im(s, pc_start - s->cs_base);
7187 if (b & 2) {
7188 gen_helper_rdmsr(cpu_env);
7189 } else {
7190 gen_helper_wrmsr(cpu_env);
7193 break;
7194 case 0x131: /* rdtsc */
7195 gen_update_cc_op(s);
7196 gen_jmp_im(s, pc_start - s->cs_base);
7197 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7198 gen_io_start();
7200 gen_helper_rdtsc(cpu_env);
7201 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7202 gen_jmp(s, s->pc - s->cs_base);
7204 break;
7205 case 0x133: /* rdpmc */
7206 gen_update_cc_op(s);
7207 gen_jmp_im(s, pc_start - s->cs_base);
7208 gen_helper_rdpmc(cpu_env);
7209 break;
7210 case 0x134: /* sysenter */
7211 /* For Intel SYSENTER is valid on 64-bit */
7212 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7213 goto illegal_op;
7214 if (!s->pe) {
7215 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7216 } else {
7217 gen_helper_sysenter(cpu_env);
7218 gen_eob(s);
7220 break;
7221 case 0x135: /* sysexit */
7222 /* For Intel SYSEXIT is valid on 64-bit */
7223 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7224 goto illegal_op;
7225 if (!s->pe) {
7226 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7227 } else {
7228 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7229 gen_eob(s);
7231 break;
7232 #ifdef TARGET_X86_64
7233 case 0x105: /* syscall */
7234 /* XXX: is it usable in real mode ? */
7235 gen_update_cc_op(s);
7236 gen_jmp_im(s, pc_start - s->cs_base);
7237 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7238 /* TF handling for the syscall insn is different. The TF bit is checked
7239 after the syscall insn completes. This allows #DB to not be
7240 generated after one has entered CPL0 if TF is set in FMASK. */
7241 gen_eob_worker(s, false, true);
7242 break;
7243 case 0x107: /* sysret */
7244 if (!s->pe) {
7245 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7246 } else {
7247 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7248 /* condition codes are modified only in long mode */
7249 if (s->lma) {
7250 set_cc_op(s, CC_OP_EFLAGS);
7252 /* TF handling for the sysret insn is different. The TF bit is
7253 checked after the sysret insn completes. This allows #DB to be
7254 generated "as if" the syscall insn in userspace has just
7255 completed. */
7256 gen_eob_worker(s, false, true);
7258 break;
7259 #endif
7260 case 0x1a2: /* cpuid */
7261 gen_update_cc_op(s);
7262 gen_jmp_im(s, pc_start - s->cs_base);
7263 gen_helper_cpuid(cpu_env);
7264 break;
7265 case 0xf4: /* hlt */
7266 if (s->cpl != 0) {
7267 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7268 } else {
7269 gen_update_cc_op(s);
7270 gen_jmp_im(s, pc_start - s->cs_base);
7271 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7272 s->base.is_jmp = DISAS_NORETURN;
7274 break;
7275 case 0x100:
7276 modrm = x86_ldub_code(env, s);
7277 mod = (modrm >> 6) & 3;
7278 op = (modrm >> 3) & 7;
7279 switch(op) {
7280 case 0: /* sldt */
7281 if (!s->pe || s->vm86)
7282 goto illegal_op;
7283 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7284 tcg_gen_ld32u_tl(s->T0, cpu_env,
7285 offsetof(CPUX86State, ldt.selector));
7286 ot = mod == 3 ? dflag : MO_16;
7287 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7288 break;
7289 case 2: /* lldt */
7290 if (!s->pe || s->vm86)
7291 goto illegal_op;
7292 if (s->cpl != 0) {
7293 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7294 } else {
7295 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7296 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7297 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7298 gen_helper_lldt(cpu_env, s->tmp2_i32);
7300 break;
7301 case 1: /* str */
7302 if (!s->pe || s->vm86)
7303 goto illegal_op;
7304 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7305 tcg_gen_ld32u_tl(s->T0, cpu_env,
7306 offsetof(CPUX86State, tr.selector));
7307 ot = mod == 3 ? dflag : MO_16;
7308 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7309 break;
7310 case 3: /* ltr */
7311 if (!s->pe || s->vm86)
7312 goto illegal_op;
7313 if (s->cpl != 0) {
7314 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7315 } else {
7316 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7317 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7318 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7319 gen_helper_ltr(cpu_env, s->tmp2_i32);
7321 break;
7322 case 4: /* verr */
7323 case 5: /* verw */
7324 if (!s->pe || s->vm86)
7325 goto illegal_op;
7326 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7327 gen_update_cc_op(s);
7328 if (op == 4) {
7329 gen_helper_verr(cpu_env, s->T0);
7330 } else {
7331 gen_helper_verw(cpu_env, s->T0);
7333 set_cc_op(s, CC_OP_EFLAGS);
7334 break;
7335 default:
7336 goto unknown_op;
7338 break;
7340 case 0x101:
7341 modrm = x86_ldub_code(env, s);
7342 switch (modrm) {
7343 CASE_MODRM_MEM_OP(0): /* sgdt */
7344 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7345 gen_lea_modrm(env, s, modrm);
7346 tcg_gen_ld32u_tl(s->T0,
7347 cpu_env, offsetof(CPUX86State, gdt.limit));
7348 gen_op_st_v(s, MO_16, s->T0, s->A0);
7349 gen_add_A0_im(s, 2);
7350 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7351 if (dflag == MO_16) {
7352 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7354 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7355 break;
7357 case 0xc8: /* monitor */
7358 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7359 goto illegal_op;
7361 gen_update_cc_op(s);
7362 gen_jmp_im(s, pc_start - s->cs_base);
7363 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7364 gen_extu(s->aflag, s->A0);
7365 gen_add_A0_ds_seg(s);
7366 gen_helper_monitor(cpu_env, s->A0);
7367 break;
7369 case 0xc9: /* mwait */
7370 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7371 goto illegal_op;
7373 gen_update_cc_op(s);
7374 gen_jmp_im(s, pc_start - s->cs_base);
7375 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7376 gen_eob(s);
7377 break;
7379 case 0xca: /* clac */
7380 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7381 || s->cpl != 0) {
7382 goto illegal_op;
7384 gen_helper_clac(cpu_env);
7385 gen_jmp_im(s, s->pc - s->cs_base);
7386 gen_eob(s);
7387 break;
7389 case 0xcb: /* stac */
7390 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7391 || s->cpl != 0) {
7392 goto illegal_op;
7394 gen_helper_stac(cpu_env);
7395 gen_jmp_im(s, s->pc - s->cs_base);
7396 gen_eob(s);
7397 break;
7399 CASE_MODRM_MEM_OP(1): /* sidt */
7400 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7401 gen_lea_modrm(env, s, modrm);
7402 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit));
7403 gen_op_st_v(s, MO_16, s->T0, s->A0);
7404 gen_add_A0_im(s, 2);
7405 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7406 if (dflag == MO_16) {
7407 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7409 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7410 break;
7412 case 0xd0: /* xgetbv */
7413 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7414 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7415 | PREFIX_REPZ | PREFIX_REPNZ))) {
7416 goto illegal_op;
7418 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7419 gen_helper_xgetbv(s->tmp1_i64, cpu_env, s->tmp2_i32);
7420 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7421 break;
7423 case 0xd1: /* xsetbv */
7424 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7425 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7426 | PREFIX_REPZ | PREFIX_REPNZ))) {
7427 goto illegal_op;
7429 if (s->cpl != 0) {
7430 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7431 break;
7433 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7434 cpu_regs[R_EDX]);
7435 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7436 gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
7437 /* End TB because translation flags may change. */
7438 gen_jmp_im(s, s->pc - s->cs_base);
7439 gen_eob(s);
7440 break;
7442 case 0xd8: /* VMRUN */
7443 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7444 goto illegal_op;
7446 if (s->cpl != 0) {
7447 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7448 break;
7450 gen_update_cc_op(s);
7451 gen_jmp_im(s, pc_start - s->cs_base);
7452 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7453 tcg_const_i32(s->pc - pc_start));
7454 tcg_gen_exit_tb(NULL, 0);
7455 s->base.is_jmp = DISAS_NORETURN;
7456 break;
7458 case 0xd9: /* VMMCALL */
7459 if (!(s->flags & HF_SVME_MASK)) {
7460 goto illegal_op;
7462 gen_update_cc_op(s);
7463 gen_jmp_im(s, pc_start - s->cs_base);
7464 gen_helper_vmmcall(cpu_env);
7465 break;
7467 case 0xda: /* VMLOAD */
7468 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7469 goto illegal_op;
7471 if (s->cpl != 0) {
7472 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7473 break;
7475 gen_update_cc_op(s);
7476 gen_jmp_im(s, pc_start - s->cs_base);
7477 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7478 break;
7480 case 0xdb: /* VMSAVE */
7481 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7482 goto illegal_op;
7484 if (s->cpl != 0) {
7485 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7486 break;
7488 gen_update_cc_op(s);
7489 gen_jmp_im(s, pc_start - s->cs_base);
7490 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7491 break;
7493 case 0xdc: /* STGI */
7494 if ((!(s->flags & HF_SVME_MASK)
7495 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7496 || !s->pe) {
7497 goto illegal_op;
7499 if (s->cpl != 0) {
7500 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7501 break;
7503 gen_update_cc_op(s);
7504 gen_helper_stgi(cpu_env);
7505 gen_jmp_im(s, s->pc - s->cs_base);
7506 gen_eob(s);
7507 break;
7509 case 0xdd: /* CLGI */
7510 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7511 goto illegal_op;
7513 if (s->cpl != 0) {
7514 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7515 break;
7517 gen_update_cc_op(s);
7518 gen_jmp_im(s, pc_start - s->cs_base);
7519 gen_helper_clgi(cpu_env);
7520 break;
7522 case 0xde: /* SKINIT */
7523 if ((!(s->flags & HF_SVME_MASK)
7524 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7525 || !s->pe) {
7526 goto illegal_op;
7528 gen_update_cc_op(s);
7529 gen_jmp_im(s, pc_start - s->cs_base);
7530 gen_helper_skinit(cpu_env);
7531 break;
7533 case 0xdf: /* INVLPGA */
7534 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7535 goto illegal_op;
7537 if (s->cpl != 0) {
7538 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7539 break;
7541 gen_update_cc_op(s);
7542 gen_jmp_im(s, pc_start - s->cs_base);
7543 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7544 break;
7546 CASE_MODRM_MEM_OP(2): /* lgdt */
7547 if (s->cpl != 0) {
7548 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7549 break;
7551 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE);
7552 gen_lea_modrm(env, s, modrm);
7553 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7554 gen_add_A0_im(s, 2);
7555 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7556 if (dflag == MO_16) {
7557 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7559 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7560 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7561 break;
7563 CASE_MODRM_MEM_OP(3): /* lidt */
7564 if (s->cpl != 0) {
7565 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7566 break;
7568 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7569 gen_lea_modrm(env, s, modrm);
7570 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7571 gen_add_A0_im(s, 2);
7572 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7573 if (dflag == MO_16) {
7574 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7576 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7577 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, idt.limit));
7578 break;
7580 CASE_MODRM_OP(4): /* smsw */
7581 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7582 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
7584 * In 32-bit mode, the higher 16 bits of the destination
7585 * register are undefined. In practice CR0[31:0] is stored
7586 * just like in 64-bit mode.
7588 mod = (modrm >> 6) & 3;
7589 ot = (mod != 3 ? MO_16 : s->dflag);
7590 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7591 break;
7592 case 0xee: /* rdpkru */
7593 if (prefixes & PREFIX_LOCK) {
7594 goto illegal_op;
7596 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7597 gen_helper_rdpkru(s->tmp1_i64, cpu_env, s->tmp2_i32);
7598 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7599 break;
7600 case 0xef: /* wrpkru */
7601 if (prefixes & PREFIX_LOCK) {
7602 goto illegal_op;
7604 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7605 cpu_regs[R_EDX]);
7606 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7607 gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64);
7608 break;
7609 CASE_MODRM_OP(6): /* lmsw */
7610 if (s->cpl != 0) {
7611 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7612 break;
7614 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7615 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7616 gen_helper_lmsw(cpu_env, s->T0);
7617 gen_jmp_im(s, s->pc - s->cs_base);
7618 gen_eob(s);
7619 break;
7621 CASE_MODRM_MEM_OP(7): /* invlpg */
7622 if (s->cpl != 0) {
7623 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7624 break;
7626 gen_update_cc_op(s);
7627 gen_jmp_im(s, pc_start - s->cs_base);
7628 gen_lea_modrm(env, s, modrm);
7629 gen_helper_invlpg(cpu_env, s->A0);
7630 gen_jmp_im(s, s->pc - s->cs_base);
7631 gen_eob(s);
7632 break;
7634 case 0xf8: /* swapgs */
7635 #ifdef TARGET_X86_64
7636 if (CODE64(s)) {
7637 if (s->cpl != 0) {
7638 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7639 } else {
7640 tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]);
7641 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7642 offsetof(CPUX86State, kernelgsbase));
7643 tcg_gen_st_tl(s->T0, cpu_env,
7644 offsetof(CPUX86State, kernelgsbase));
7646 break;
7648 #endif
7649 goto illegal_op;
7651 case 0xf9: /* rdtscp */
7652 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7653 goto illegal_op;
7655 gen_update_cc_op(s);
7656 gen_jmp_im(s, pc_start - s->cs_base);
7657 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7658 gen_io_start();
7660 gen_helper_rdtscp(cpu_env);
7661 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7662 gen_jmp(s, s->pc - s->cs_base);
7664 break;
7666 default:
7667 goto unknown_op;
7669 break;
7671 case 0x108: /* invd */
7672 case 0x109: /* wbinvd */
7673 if (s->cpl != 0) {
7674 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7675 } else {
7676 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7677 /* nothing to do */
7679 break;
7680 case 0x63: /* arpl or movslS (x86_64) */
7681 #ifdef TARGET_X86_64
7682 if (CODE64(s)) {
7683 int d_ot;
7684 /* d_ot is the size of destination */
7685 d_ot = dflag;
7687 modrm = x86_ldub_code(env, s);
7688 reg = ((modrm >> 3) & 7) | rex_r;
7689 mod = (modrm >> 6) & 3;
7690 rm = (modrm & 7) | REX_B(s);
7692 if (mod == 3) {
7693 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
7694 /* sign extend */
7695 if (d_ot == MO_64) {
7696 tcg_gen_ext32s_tl(s->T0, s->T0);
7698 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7699 } else {
7700 gen_lea_modrm(env, s, modrm);
7701 gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0);
7702 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7704 } else
7705 #endif
7707 TCGLabel *label1;
7708 TCGv t0, t1, t2, a0;
7710 if (!s->pe || s->vm86)
7711 goto illegal_op;
7712 t0 = tcg_temp_local_new();
7713 t1 = tcg_temp_local_new();
7714 t2 = tcg_temp_local_new();
7715 ot = MO_16;
7716 modrm = x86_ldub_code(env, s);
7717 reg = (modrm >> 3) & 7;
7718 mod = (modrm >> 6) & 3;
7719 rm = modrm & 7;
7720 if (mod != 3) {
7721 gen_lea_modrm(env, s, modrm);
7722 gen_op_ld_v(s, ot, t0, s->A0);
7723 a0 = tcg_temp_local_new();
7724 tcg_gen_mov_tl(a0, s->A0);
7725 } else {
7726 gen_op_mov_v_reg(s, ot, t0, rm);
7727 a0 = NULL;
7729 gen_op_mov_v_reg(s, ot, t1, reg);
7730 tcg_gen_andi_tl(s->tmp0, t0, 3);
7731 tcg_gen_andi_tl(t1, t1, 3);
7732 tcg_gen_movi_tl(t2, 0);
7733 label1 = gen_new_label();
7734 tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1);
7735 tcg_gen_andi_tl(t0, t0, ~3);
7736 tcg_gen_or_tl(t0, t0, t1);
7737 tcg_gen_movi_tl(t2, CC_Z);
7738 gen_set_label(label1);
7739 if (mod != 3) {
7740 gen_op_st_v(s, ot, t0, a0);
7741 tcg_temp_free(a0);
7742 } else {
7743 gen_op_mov_reg_v(s, ot, rm, t0);
7745 gen_compute_eflags(s);
7746 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7747 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7748 tcg_temp_free(t0);
7749 tcg_temp_free(t1);
7750 tcg_temp_free(t2);
7752 break;
7753 case 0x102: /* lar */
7754 case 0x103: /* lsl */
7756 TCGLabel *label1;
7757 TCGv t0;
7758 if (!s->pe || s->vm86)
7759 goto illegal_op;
7760 ot = dflag != MO_16 ? MO_32 : MO_16;
7761 modrm = x86_ldub_code(env, s);
7762 reg = ((modrm >> 3) & 7) | rex_r;
7763 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7764 t0 = tcg_temp_local_new();
7765 gen_update_cc_op(s);
7766 if (b == 0x102) {
7767 gen_helper_lar(t0, cpu_env, s->T0);
7768 } else {
7769 gen_helper_lsl(t0, cpu_env, s->T0);
7771 tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z);
7772 label1 = gen_new_label();
7773 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
7774 gen_op_mov_reg_v(s, ot, reg, t0);
7775 gen_set_label(label1);
7776 set_cc_op(s, CC_OP_EFLAGS);
7777 tcg_temp_free(t0);
7779 break;
7780 case 0x118:
7781 modrm = x86_ldub_code(env, s);
7782 mod = (modrm >> 6) & 3;
7783 op = (modrm >> 3) & 7;
7784 switch(op) {
7785 case 0: /* prefetchnta */
7786 case 1: /* prefetchnt0 */
7787 case 2: /* prefetchnt0 */
7788 case 3: /* prefetchnt0 */
7789 if (mod == 3)
7790 goto illegal_op;
7791 gen_nop_modrm(env, s, modrm);
7792 /* nothing more to do */
7793 break;
7794 default: /* nop (multi byte) */
7795 gen_nop_modrm(env, s, modrm);
7796 break;
7798 break;
7799 case 0x11a:
7800 modrm = x86_ldub_code(env, s);
7801 if (s->flags & HF_MPX_EN_MASK) {
7802 mod = (modrm >> 6) & 3;
7803 reg = ((modrm >> 3) & 7) | rex_r;
7804 if (prefixes & PREFIX_REPZ) {
7805 /* bndcl */
7806 if (reg >= 4
7807 || (prefixes & PREFIX_LOCK)
7808 || s->aflag == MO_16) {
7809 goto illegal_op;
7811 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7812 } else if (prefixes & PREFIX_REPNZ) {
7813 /* bndcu */
7814 if (reg >= 4
7815 || (prefixes & PREFIX_LOCK)
7816 || s->aflag == MO_16) {
7817 goto illegal_op;
7819 TCGv_i64 notu = tcg_temp_new_i64();
7820 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7821 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7822 tcg_temp_free_i64(notu);
7823 } else if (prefixes & PREFIX_DATA) {
7824 /* bndmov -- from reg/mem */
7825 if (reg >= 4 || s->aflag == MO_16) {
7826 goto illegal_op;
7828 if (mod == 3) {
7829 int reg2 = (modrm & 7) | REX_B(s);
7830 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7831 goto illegal_op;
7833 if (s->flags & HF_MPX_IU_MASK) {
7834 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7835 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7837 } else {
7838 gen_lea_modrm(env, s, modrm);
7839 if (CODE64(s)) {
7840 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7841 s->mem_index, MO_LEQ);
7842 tcg_gen_addi_tl(s->A0, s->A0, 8);
7843 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7844 s->mem_index, MO_LEQ);
7845 } else {
7846 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7847 s->mem_index, MO_LEUL);
7848 tcg_gen_addi_tl(s->A0, s->A0, 4);
7849 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7850 s->mem_index, MO_LEUL);
7852 /* bnd registers are now in-use */
7853 gen_set_hflag(s, HF_MPX_IU_MASK);
7855 } else if (mod != 3) {
7856 /* bndldx */
7857 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7858 if (reg >= 4
7859 || (prefixes & PREFIX_LOCK)
7860 || s->aflag == MO_16
7861 || a.base < -1) {
7862 goto illegal_op;
7864 if (a.base >= 0) {
7865 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
7866 } else {
7867 tcg_gen_movi_tl(s->A0, 0);
7869 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
7870 if (a.index >= 0) {
7871 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
7872 } else {
7873 tcg_gen_movi_tl(s->T0, 0);
7875 if (CODE64(s)) {
7876 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0);
7877 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7878 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7879 } else {
7880 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0);
7881 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7882 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7884 gen_set_hflag(s, HF_MPX_IU_MASK);
7887 gen_nop_modrm(env, s, modrm);
7888 break;
7889 case 0x11b:
7890 modrm = x86_ldub_code(env, s);
7891 if (s->flags & HF_MPX_EN_MASK) {
7892 mod = (modrm >> 6) & 3;
7893 reg = ((modrm >> 3) & 7) | rex_r;
7894 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7895 /* bndmk */
7896 if (reg >= 4
7897 || (prefixes & PREFIX_LOCK)
7898 || s->aflag == MO_16) {
7899 goto illegal_op;
7901 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7902 if (a.base >= 0) {
7903 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7904 if (!CODE64(s)) {
7905 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7907 } else if (a.base == -1) {
7908 /* no base register has lower bound of 0 */
7909 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7910 } else {
7911 /* rip-relative generates #ud */
7912 goto illegal_op;
7914 tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a));
7915 if (!CODE64(s)) {
7916 tcg_gen_ext32u_tl(s->A0, s->A0);
7918 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
7919 /* bnd registers are now in-use */
7920 gen_set_hflag(s, HF_MPX_IU_MASK);
7921 break;
7922 } else if (prefixes & PREFIX_REPNZ) {
7923 /* bndcn */
7924 if (reg >= 4
7925 || (prefixes & PREFIX_LOCK)
7926 || s->aflag == MO_16) {
7927 goto illegal_op;
7929 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
7930 } else if (prefixes & PREFIX_DATA) {
7931 /* bndmov -- to reg/mem */
7932 if (reg >= 4 || s->aflag == MO_16) {
7933 goto illegal_op;
7935 if (mod == 3) {
7936 int reg2 = (modrm & 7) | REX_B(s);
7937 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7938 goto illegal_op;
7940 if (s->flags & HF_MPX_IU_MASK) {
7941 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7942 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7944 } else {
7945 gen_lea_modrm(env, s, modrm);
7946 if (CODE64(s)) {
7947 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
7948 s->mem_index, MO_LEQ);
7949 tcg_gen_addi_tl(s->A0, s->A0, 8);
7950 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
7951 s->mem_index, MO_LEQ);
7952 } else {
7953 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
7954 s->mem_index, MO_LEUL);
7955 tcg_gen_addi_tl(s->A0, s->A0, 4);
7956 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
7957 s->mem_index, MO_LEUL);
7960 } else if (mod != 3) {
7961 /* bndstx */
7962 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7963 if (reg >= 4
7964 || (prefixes & PREFIX_LOCK)
7965 || s->aflag == MO_16
7966 || a.base < -1) {
7967 goto illegal_op;
7969 if (a.base >= 0) {
7970 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
7971 } else {
7972 tcg_gen_movi_tl(s->A0, 0);
7974 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
7975 if (a.index >= 0) {
7976 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
7977 } else {
7978 tcg_gen_movi_tl(s->T0, 0);
7980 if (CODE64(s)) {
7981 gen_helper_bndstx64(cpu_env, s->A0, s->T0,
7982 cpu_bndl[reg], cpu_bndu[reg]);
7983 } else {
7984 gen_helper_bndstx32(cpu_env, s->A0, s->T0,
7985 cpu_bndl[reg], cpu_bndu[reg]);
7989 gen_nop_modrm(env, s, modrm);
7990 break;
7991 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
7992 modrm = x86_ldub_code(env, s);
7993 gen_nop_modrm(env, s, modrm);
7994 break;
7995 case 0x120: /* mov reg, crN */
7996 case 0x122: /* mov crN, reg */
7997 if (s->cpl != 0) {
7998 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7999 } else {
8000 modrm = x86_ldub_code(env, s);
8001 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8002 * AMD documentation (24594.pdf) and testing of
8003 * intel 386 and 486 processors all show that the mod bits
8004 * are assumed to be 1's, regardless of actual values.
8006 rm = (modrm & 7) | REX_B(s);
8007 reg = ((modrm >> 3) & 7) | rex_r;
8008 if (CODE64(s))
8009 ot = MO_64;
8010 else
8011 ot = MO_32;
8012 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
8013 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
8014 reg = 8;
8016 switch(reg) {
8017 case 0:
8018 case 2:
8019 case 3:
8020 case 4:
8021 case 8:
8022 gen_update_cc_op(s);
8023 gen_jmp_im(s, pc_start - s->cs_base);
8024 if (b & 2) {
8025 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8026 gen_io_start();
8028 gen_op_mov_v_reg(s, ot, s->T0, rm);
8029 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
8030 s->T0);
8031 gen_jmp_im(s, s->pc - s->cs_base);
8032 gen_eob(s);
8033 } else {
8034 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8035 gen_io_start();
8037 gen_helper_read_crN(s->T0, cpu_env, tcg_const_i32(reg));
8038 gen_op_mov_reg_v(s, ot, rm, s->T0);
8039 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8040 gen_jmp(s, s->pc - s->cs_base);
8043 break;
8044 default:
8045 goto unknown_op;
8048 break;
8049 case 0x121: /* mov reg, drN */
8050 case 0x123: /* mov drN, reg */
8051 if (s->cpl != 0) {
8052 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8053 } else {
8054 modrm = x86_ldub_code(env, s);
8055 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8056 * AMD documentation (24594.pdf) and testing of
8057 * intel 386 and 486 processors all show that the mod bits
8058 * are assumed to be 1's, regardless of actual values.
8060 rm = (modrm & 7) | REX_B(s);
8061 reg = ((modrm >> 3) & 7) | rex_r;
8062 if (CODE64(s))
8063 ot = MO_64;
8064 else
8065 ot = MO_32;
8066 if (reg >= 8) {
8067 goto illegal_op;
8069 if (b & 2) {
8070 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
8071 gen_op_mov_v_reg(s, ot, s->T0, rm);
8072 tcg_gen_movi_i32(s->tmp2_i32, reg);
8073 gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
8074 gen_jmp_im(s, s->pc - s->cs_base);
8075 gen_eob(s);
8076 } else {
8077 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
8078 tcg_gen_movi_i32(s->tmp2_i32, reg);
8079 gen_helper_get_dr(s->T0, cpu_env, s->tmp2_i32);
8080 gen_op_mov_reg_v(s, ot, rm, s->T0);
8083 break;
8084 case 0x106: /* clts */
8085 if (s->cpl != 0) {
8086 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8087 } else {
8088 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
8089 gen_helper_clts(cpu_env);
8090 /* abort block because static cpu state changed */
8091 gen_jmp_im(s, s->pc - s->cs_base);
8092 gen_eob(s);
8094 break;
8095 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
8096 case 0x1c3: /* MOVNTI reg, mem */
8097 if (!(s->cpuid_features & CPUID_SSE2))
8098 goto illegal_op;
8099 ot = mo_64_32(dflag);
8100 modrm = x86_ldub_code(env, s);
8101 mod = (modrm >> 6) & 3;
8102 if (mod == 3)
8103 goto illegal_op;
8104 reg = ((modrm >> 3) & 7) | rex_r;
8105 /* generate a generic store */
8106 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8107 break;
8108 case 0x1ae:
8109 modrm = x86_ldub_code(env, s);
8110 switch (modrm) {
8111 CASE_MODRM_MEM_OP(0): /* fxsave */
8112 if (!(s->cpuid_features & CPUID_FXSR)
8113 || (prefixes & PREFIX_LOCK)) {
8114 goto illegal_op;
8116 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8117 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8118 break;
8120 gen_lea_modrm(env, s, modrm);
8121 gen_helper_fxsave(cpu_env, s->A0);
8122 break;
8124 CASE_MODRM_MEM_OP(1): /* fxrstor */
8125 if (!(s->cpuid_features & CPUID_FXSR)
8126 || (prefixes & PREFIX_LOCK)) {
8127 goto illegal_op;
8129 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8130 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8131 break;
8133 gen_lea_modrm(env, s, modrm);
8134 gen_helper_fxrstor(cpu_env, s->A0);
8135 break;
8137 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
8138 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8139 goto illegal_op;
8141 if (s->flags & HF_TS_MASK) {
8142 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8143 break;
8145 gen_lea_modrm(env, s, modrm);
8146 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
8147 gen_helper_ldmxcsr(cpu_env, s->tmp2_i32);
8148 break;
8150 CASE_MODRM_MEM_OP(3): /* stmxcsr */
8151 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8152 goto illegal_op;
8154 if (s->flags & HF_TS_MASK) {
8155 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8156 break;
8158 gen_helper_update_mxcsr(cpu_env);
8159 gen_lea_modrm(env, s, modrm);
8160 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr));
8161 gen_op_st_v(s, MO_32, s->T0, s->A0);
8162 break;
8164 CASE_MODRM_MEM_OP(4): /* xsave */
8165 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8166 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8167 | PREFIX_REPZ | PREFIX_REPNZ))) {
8168 goto illegal_op;
8170 gen_lea_modrm(env, s, modrm);
8171 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8172 cpu_regs[R_EDX]);
8173 gen_helper_xsave(cpu_env, s->A0, s->tmp1_i64);
8174 break;
8176 CASE_MODRM_MEM_OP(5): /* xrstor */
8177 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8178 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8179 | PREFIX_REPZ | PREFIX_REPNZ))) {
8180 goto illegal_op;
8182 gen_lea_modrm(env, s, modrm);
8183 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8184 cpu_regs[R_EDX]);
8185 gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64);
8186 /* XRSTOR is how MPX is enabled, which changes how
8187 we translate. Thus we need to end the TB. */
8188 gen_update_cc_op(s);
8189 gen_jmp_im(s, s->pc - s->cs_base);
8190 gen_eob(s);
8191 break;
8193 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
8194 if (prefixes & PREFIX_LOCK) {
8195 goto illegal_op;
8197 if (prefixes & PREFIX_DATA) {
8198 /* clwb */
8199 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8200 goto illegal_op;
8202 gen_nop_modrm(env, s, modrm);
8203 } else {
8204 /* xsaveopt */
8205 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8206 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8207 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8208 goto illegal_op;
8210 gen_lea_modrm(env, s, modrm);
8211 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8212 cpu_regs[R_EDX]);
8213 gen_helper_xsaveopt(cpu_env, s->A0, s->tmp1_i64);
8215 break;
8217 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
8218 if (prefixes & PREFIX_LOCK) {
8219 goto illegal_op;
8221 if (prefixes & PREFIX_DATA) {
8222 /* clflushopt */
8223 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8224 goto illegal_op;
8226 } else {
8227 /* clflush */
8228 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8229 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8230 goto illegal_op;
8233 gen_nop_modrm(env, s, modrm);
8234 break;
8236 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
8237 case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
8238 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
8239 case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
8240 if (CODE64(s)
8241 && (prefixes & PREFIX_REPZ)
8242 && !(prefixes & PREFIX_LOCK)
8243 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8244 TCGv base, treg, src, dst;
8246 /* Preserve hflags bits by testing CR4 at runtime. */
8247 tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
8248 gen_helper_cr4_testbit(cpu_env, s->tmp2_i32);
8250 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8251 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8253 if (modrm & 0x10) {
8254 /* wr*base */
8255 dst = base, src = treg;
8256 } else {
8257 /* rd*base */
8258 dst = treg, src = base;
8261 if (s->dflag == MO_32) {
8262 tcg_gen_ext32u_tl(dst, src);
8263 } else {
8264 tcg_gen_mov_tl(dst, src);
8266 break;
8268 goto unknown_op;
8270 case 0xf8: /* sfence / pcommit */
8271 if (prefixes & PREFIX_DATA) {
8272 /* pcommit */
8273 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8274 || (prefixes & PREFIX_LOCK)) {
8275 goto illegal_op;
8277 break;
8279 /* fallthru */
8280 case 0xf9 ... 0xff: /* sfence */
8281 if (!(s->cpuid_features & CPUID_SSE)
8282 || (prefixes & PREFIX_LOCK)) {
8283 goto illegal_op;
8285 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8286 break;
8287 case 0xe8 ... 0xef: /* lfence */
8288 if (!(s->cpuid_features & CPUID_SSE)
8289 || (prefixes & PREFIX_LOCK)) {
8290 goto illegal_op;
8292 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8293 break;
8294 case 0xf0 ... 0xf7: /* mfence */
8295 if (!(s->cpuid_features & CPUID_SSE2)
8296 || (prefixes & PREFIX_LOCK)) {
8297 goto illegal_op;
8299 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8300 break;
8302 default:
8303 goto unknown_op;
8305 break;
8307 case 0x10d: /* 3DNow! prefetch(w) */
8308 modrm = x86_ldub_code(env, s);
8309 mod = (modrm >> 6) & 3;
8310 if (mod == 3)
8311 goto illegal_op;
8312 gen_nop_modrm(env, s, modrm);
8313 break;
8314 case 0x1aa: /* rsm */
8315 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8316 if (!(s->flags & HF_SMM_MASK))
8317 goto illegal_op;
8318 gen_update_cc_op(s);
8319 gen_jmp_im(s, s->pc - s->cs_base);
8320 gen_helper_rsm(cpu_env);
8321 gen_eob(s);
8322 break;
8323 case 0x1b8: /* SSE4.2 popcnt */
8324 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8325 PREFIX_REPZ)
8326 goto illegal_op;
8327 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8328 goto illegal_op;
8330 modrm = x86_ldub_code(env, s);
8331 reg = ((modrm >> 3) & 7) | rex_r;
8333 if (s->prefix & PREFIX_DATA) {
8334 ot = MO_16;
8335 } else {
8336 ot = mo_64_32(dflag);
8339 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8340 gen_extu(ot, s->T0);
8341 tcg_gen_mov_tl(cpu_cc_src, s->T0);
8342 tcg_gen_ctpop_tl(s->T0, s->T0);
8343 gen_op_mov_reg_v(s, ot, reg, s->T0);
8345 set_cc_op(s, CC_OP_POPCNT);
8346 break;
8347 case 0x10e ... 0x10f:
8348 /* 3DNow! instructions, ignore prefixes */
8349 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8350 /* fall through */
8351 case 0x110 ... 0x117:
8352 case 0x128 ... 0x12f:
8353 case 0x138 ... 0x13a:
8354 case 0x150 ... 0x179:
8355 case 0x17c ... 0x17f:
8356 case 0x1c2:
8357 case 0x1c4 ... 0x1c6:
8358 case 0x1d0 ... 0x1fe:
8359 gen_sse(env, s, b, pc_start, rex_r);
8360 break;
8361 default:
8362 goto unknown_op;
8364 return s->pc;
8365 illegal_op:
8366 gen_illegal_opcode(s);
8367 return s->pc;
8368 unknown_op:
8369 gen_unknown_opcode(env, s);
8370 return s->pc;
8373 void tcg_x86_init(void)
8375 static const char reg_names[CPU_NB_REGS][4] = {
8376 #ifdef TARGET_X86_64
8377 [R_EAX] = "rax",
8378 [R_EBX] = "rbx",
8379 [R_ECX] = "rcx",
8380 [R_EDX] = "rdx",
8381 [R_ESI] = "rsi",
8382 [R_EDI] = "rdi",
8383 [R_EBP] = "rbp",
8384 [R_ESP] = "rsp",
8385 [8] = "r8",
8386 [9] = "r9",
8387 [10] = "r10",
8388 [11] = "r11",
8389 [12] = "r12",
8390 [13] = "r13",
8391 [14] = "r14",
8392 [15] = "r15",
8393 #else
8394 [R_EAX] = "eax",
8395 [R_EBX] = "ebx",
8396 [R_ECX] = "ecx",
8397 [R_EDX] = "edx",
8398 [R_ESI] = "esi",
8399 [R_EDI] = "edi",
8400 [R_EBP] = "ebp",
8401 [R_ESP] = "esp",
8402 #endif
8404 static const char seg_base_names[6][8] = {
8405 [R_CS] = "cs_base",
8406 [R_DS] = "ds_base",
8407 [R_ES] = "es_base",
8408 [R_FS] = "fs_base",
8409 [R_GS] = "gs_base",
8410 [R_SS] = "ss_base",
8412 static const char bnd_regl_names[4][8] = {
8413 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8415 static const char bnd_regu_names[4][8] = {
8416 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8418 int i;
8420 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8421 offsetof(CPUX86State, cc_op), "cc_op");
8422 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8423 "cc_dst");
8424 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8425 "cc_src");
8426 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8427 "cc_src2");
8429 for (i = 0; i < CPU_NB_REGS; ++i) {
8430 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8431 offsetof(CPUX86State, regs[i]),
8432 reg_names[i]);
8435 for (i = 0; i < 6; ++i) {
8436 cpu_seg_base[i]
8437 = tcg_global_mem_new(cpu_env,
8438 offsetof(CPUX86State, segs[i].base),
8439 seg_base_names[i]);
8442 for (i = 0; i < 4; ++i) {
8443 cpu_bndl[i]
8444 = tcg_global_mem_new_i64(cpu_env,
8445 offsetof(CPUX86State, bnd_regs[i].lb),
8446 bnd_regl_names[i]);
8447 cpu_bndu[i]
8448 = tcg_global_mem_new_i64(cpu_env,
8449 offsetof(CPUX86State, bnd_regs[i].ub),
8450 bnd_regu_names[i]);
8454 static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
8456 DisasContext *dc = container_of(dcbase, DisasContext, base);
8457 CPUX86State *env = cpu->env_ptr;
8458 uint32_t flags = dc->base.tb->flags;
8459 target_ulong cs_base = dc->base.tb->cs_base;
8461 dc->pe = (flags >> HF_PE_SHIFT) & 1;
8462 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8463 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8464 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8465 dc->f_st = 0;
8466 dc->vm86 = (flags >> VM_SHIFT) & 1;
8467 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8468 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8469 dc->tf = (flags >> TF_SHIFT) & 1;
8470 dc->cc_op = CC_OP_DYNAMIC;
8471 dc->cc_op_dirty = false;
8472 dc->cs_base = cs_base;
8473 dc->popl_esp_hack = 0;
8474 /* select memory access functions */
8475 dc->mem_index = 0;
8476 #ifdef CONFIG_SOFTMMU
8477 dc->mem_index = cpu_mmu_index(env, false);
8478 #endif
8479 dc->cpuid_features = env->features[FEAT_1_EDX];
8480 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8481 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8482 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8483 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8484 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8485 #ifdef TARGET_X86_64
8486 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8487 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8488 #endif
8489 dc->flags = flags;
8490 dc->jmp_opt = !(dc->tf || dc->base.singlestep_enabled ||
8491 (flags & HF_INHIBIT_IRQ_MASK));
8492 /* Do not optimize repz jumps at all in icount mode, because
8493 rep movsS instructions are execured with different paths
8494 in !repz_opt and repz_opt modes. The first one was used
8495 always except single step mode. And this setting
8496 disables jumps optimization and control paths become
8497 equivalent in run and single step modes.
8498 Now there will be no jump optimization for repz in
8499 record/replay modes and there will always be an
8500 additional step for ecx=0 when icount is enabled.
8502 dc->repz_opt = !dc->jmp_opt && !(tb_cflags(dc->base.tb) & CF_USE_ICOUNT);
8503 #if 0
8504 /* check addseg logic */
8505 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8506 printf("ERROR addseg\n");
8507 #endif
8509 dc->T0 = tcg_temp_new();
8510 dc->T1 = tcg_temp_new();
8511 dc->A0 = tcg_temp_new();
8513 dc->tmp0 = tcg_temp_new();
8514 dc->tmp1_i64 = tcg_temp_new_i64();
8515 dc->tmp2_i32 = tcg_temp_new_i32();
8516 dc->tmp3_i32 = tcg_temp_new_i32();
8517 dc->tmp4 = tcg_temp_new();
8518 dc->ptr0 = tcg_temp_new_ptr();
8519 dc->ptr1 = tcg_temp_new_ptr();
8520 dc->cc_srcT = tcg_temp_local_new();
8523 static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
8527 static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8529 DisasContext *dc = container_of(dcbase, DisasContext, base);
8531 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
8534 static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8535 const CPUBreakpoint *bp)
8537 DisasContext *dc = container_of(dcbase, DisasContext, base);
8538 /* If RF is set, suppress an internally generated breakpoint. */
8539 int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
8540 if (bp->flags & flags) {
8541 gen_debug(dc, dc->base.pc_next - dc->cs_base);
8542 dc->base.is_jmp = DISAS_NORETURN;
8543 /* The address covered by the breakpoint must be included in
8544 [tb->pc, tb->pc + tb->size) in order to for it to be
8545 properly cleared -- thus we increment the PC here so that
8546 the generic logic setting tb->size later does the right thing. */
8547 dc->base.pc_next += 1;
8548 return true;
8549 } else {
8550 return false;
8554 static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8556 DisasContext *dc = container_of(dcbase, DisasContext, base);
8557 target_ulong pc_next;
8559 #ifdef TARGET_VSYSCALL_PAGE
8561 * Detect entry into the vsyscall page and invoke the syscall.
8563 if ((dc->base.pc_next & TARGET_PAGE_MASK) == TARGET_VSYSCALL_PAGE) {
8564 gen_exception(dc, EXCP_VSYSCALL, dc->base.pc_next);
8565 return;
8567 #endif
8569 pc_next = disas_insn(dc, cpu);
8571 if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
8572 /* if single step mode, we generate only one instruction and
8573 generate an exception */
8574 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8575 the flag and abort the translation to give the irqs a
8576 chance to happen */
8577 dc->base.is_jmp = DISAS_TOO_MANY;
8578 } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
8579 && ((pc_next & TARGET_PAGE_MASK)
8580 != ((pc_next + TARGET_MAX_INSN_SIZE - 1)
8581 & TARGET_PAGE_MASK)
8582 || (pc_next & ~TARGET_PAGE_MASK) == 0)) {
8583 /* Do not cross the boundary of the pages in icount mode,
8584 it can cause an exception. Do it only when boundary is
8585 crossed by the first instruction in the block.
8586 If current instruction already crossed the bound - it's ok,
8587 because an exception hasn't stopped this code.
8589 dc->base.is_jmp = DISAS_TOO_MANY;
8590 } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
8591 dc->base.is_jmp = DISAS_TOO_MANY;
8594 dc->base.pc_next = pc_next;
8597 static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8599 DisasContext *dc = container_of(dcbase, DisasContext, base);
8601 if (dc->base.is_jmp == DISAS_TOO_MANY) {
8602 gen_jmp_im(dc, dc->base.pc_next - dc->cs_base);
8603 gen_eob(dc);
8607 static void i386_tr_disas_log(const DisasContextBase *dcbase,
8608 CPUState *cpu)
8610 DisasContext *dc = container_of(dcbase, DisasContext, base);
8612 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
8613 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
8616 static const TranslatorOps i386_tr_ops = {
8617 .init_disas_context = i386_tr_init_disas_context,
8618 .tb_start = i386_tr_tb_start,
8619 .insn_start = i386_tr_insn_start,
8620 .breakpoint_check = i386_tr_breakpoint_check,
8621 .translate_insn = i386_tr_translate_insn,
8622 .tb_stop = i386_tr_tb_stop,
8623 .disas_log = i386_tr_disas_log,
8626 /* generate intermediate code for basic block 'tb'. */
8627 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
8629 DisasContext dc;
8631 translator_loop(&i386_tr_ops, &dc.base, cpu, tb, max_insns);
8634 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8635 target_ulong *data)
8637 int cc_op = data[1];
8638 env->eip = data[0] - tb->cs_base;
8639 if (cc_op != CC_OP_DYNAMIC) {
8640 env->cc_op = cc_op;