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