virtio: move ioeventfd_started flag to VirtioBusState
[qemu/ar7.git] / target-i386 / translate.c
blob927b3665341f9b6f43ec4752596715512e393ff8
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("ILLOPC: " TARGET_FMT_lx ":", pc);
2436 for (; pc < end; ++pc) {
2437 qemu_log(" %02x", cpu_ldub_code(env, pc));
2439 qemu_log("\n");
2443 /* an interrupt is different from an exception because of the
2444 privilege checks */
2445 static void gen_interrupt(DisasContext *s, int intno,
2446 target_ulong cur_eip, target_ulong next_eip)
2448 gen_update_cc_op(s);
2449 gen_jmp_im(cur_eip);
2450 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2451 tcg_const_i32(next_eip - cur_eip));
2452 s->is_jmp = DISAS_TB_JUMP;
2455 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2457 gen_update_cc_op(s);
2458 gen_jmp_im(cur_eip);
2459 gen_helper_debug(cpu_env);
2460 s->is_jmp = DISAS_TB_JUMP;
2463 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2465 if ((s->flags & mask) == 0) {
2466 TCGv_i32 t = tcg_temp_new_i32();
2467 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2468 tcg_gen_ori_i32(t, t, mask);
2469 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2470 tcg_temp_free_i32(t);
2471 s->flags |= mask;
2475 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2477 if (s->flags & mask) {
2478 TCGv_i32 t = tcg_temp_new_i32();
2479 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2480 tcg_gen_andi_i32(t, t, ~mask);
2481 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2482 tcg_temp_free_i32(t);
2483 s->flags &= ~mask;
2487 /* Clear BND registers during legacy branches. */
2488 static void gen_bnd_jmp(DisasContext *s)
2490 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2491 and if the BNDREGs are known to be in use (non-zero) already.
2492 The helper itself will check BNDPRESERVE at runtime. */
2493 if ((s->prefix & PREFIX_REPNZ) == 0
2494 && (s->flags & HF_MPX_EN_MASK) != 0
2495 && (s->flags & HF_MPX_IU_MASK) != 0) {
2496 gen_helper_bnd_jmp(cpu_env);
2500 /* Generate an end of block. Trace exception is also generated if needed.
2501 If IIM, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2502 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2504 gen_update_cc_op(s);
2506 /* If several instructions disable interrupts, only the first does it. */
2507 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2508 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2509 } else {
2510 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2513 if (s->tb->flags & HF_RF_MASK) {
2514 gen_helper_reset_rf(cpu_env);
2516 if (s->singlestep_enabled) {
2517 gen_helper_debug(cpu_env);
2518 } else if (s->tf) {
2519 gen_helper_single_step(cpu_env);
2520 } else {
2521 tcg_gen_exit_tb(0);
2523 s->is_jmp = DISAS_TB_JUMP;
2526 /* End of block, resetting the inhibit irq flag. */
2527 static void gen_eob(DisasContext *s)
2529 gen_eob_inhibit_irq(s, false);
2532 /* generate a jump to eip. No segment change must happen before as a
2533 direct call to the next block may occur */
2534 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2536 gen_update_cc_op(s);
2537 set_cc_op(s, CC_OP_DYNAMIC);
2538 if (s->jmp_opt) {
2539 gen_goto_tb(s, tb_num, eip);
2540 s->is_jmp = DISAS_TB_JUMP;
2541 } else {
2542 gen_jmp_im(eip);
2543 gen_eob(s);
2547 static void gen_jmp(DisasContext *s, target_ulong eip)
2549 gen_jmp_tb(s, eip, 0);
2552 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2554 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2555 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2558 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2560 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2561 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2564 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2566 int mem_index = s->mem_index;
2567 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2568 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2569 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2570 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2571 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2574 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2576 int mem_index = s->mem_index;
2577 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2578 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2579 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2580 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2581 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2584 static inline void gen_op_movo(int d_offset, int s_offset)
2586 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2587 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2588 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2589 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2592 static inline void gen_op_movq(int d_offset, int s_offset)
2594 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2595 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2598 static inline void gen_op_movl(int d_offset, int s_offset)
2600 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2601 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2604 static inline void gen_op_movq_env_0(int d_offset)
2606 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2607 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2610 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2611 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2612 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2613 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2614 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2615 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2616 TCGv_i32 val);
2617 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2618 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2619 TCGv val);
2621 #define SSE_SPECIAL ((void *)1)
2622 #define SSE_DUMMY ((void *)2)
2624 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2625 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2626 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2628 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2629 /* 3DNow! extensions */
2630 [0x0e] = { SSE_DUMMY }, /* femms */
2631 [0x0f] = { SSE_DUMMY }, /* pf... */
2632 /* pure SSE operations */
2633 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2634 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2635 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2636 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2637 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2638 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2639 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2640 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2642 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2643 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2644 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2645 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2646 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2647 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2648 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2649 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2650 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2651 [0x51] = SSE_FOP(sqrt),
2652 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2653 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2654 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2655 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2656 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2657 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2658 [0x58] = SSE_FOP(add),
2659 [0x59] = SSE_FOP(mul),
2660 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2661 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2662 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2663 [0x5c] = SSE_FOP(sub),
2664 [0x5d] = SSE_FOP(min),
2665 [0x5e] = SSE_FOP(div),
2666 [0x5f] = SSE_FOP(max),
2668 [0xc2] = SSE_FOP(cmpeq),
2669 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2670 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2672 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2673 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2674 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2676 /* MMX ops and their SSE extensions */
2677 [0x60] = MMX_OP2(punpcklbw),
2678 [0x61] = MMX_OP2(punpcklwd),
2679 [0x62] = MMX_OP2(punpckldq),
2680 [0x63] = MMX_OP2(packsswb),
2681 [0x64] = MMX_OP2(pcmpgtb),
2682 [0x65] = MMX_OP2(pcmpgtw),
2683 [0x66] = MMX_OP2(pcmpgtl),
2684 [0x67] = MMX_OP2(packuswb),
2685 [0x68] = MMX_OP2(punpckhbw),
2686 [0x69] = MMX_OP2(punpckhwd),
2687 [0x6a] = MMX_OP2(punpckhdq),
2688 [0x6b] = MMX_OP2(packssdw),
2689 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2690 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2691 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2692 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2693 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2694 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2695 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2696 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2697 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2698 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2699 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2700 [0x74] = MMX_OP2(pcmpeqb),
2701 [0x75] = MMX_OP2(pcmpeqw),
2702 [0x76] = MMX_OP2(pcmpeql),
2703 [0x77] = { SSE_DUMMY }, /* emms */
2704 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2705 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2706 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2707 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2708 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2709 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2710 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2711 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2712 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2713 [0xd1] = MMX_OP2(psrlw),
2714 [0xd2] = MMX_OP2(psrld),
2715 [0xd3] = MMX_OP2(psrlq),
2716 [0xd4] = MMX_OP2(paddq),
2717 [0xd5] = MMX_OP2(pmullw),
2718 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2719 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2720 [0xd8] = MMX_OP2(psubusb),
2721 [0xd9] = MMX_OP2(psubusw),
2722 [0xda] = MMX_OP2(pminub),
2723 [0xdb] = MMX_OP2(pand),
2724 [0xdc] = MMX_OP2(paddusb),
2725 [0xdd] = MMX_OP2(paddusw),
2726 [0xde] = MMX_OP2(pmaxub),
2727 [0xdf] = MMX_OP2(pandn),
2728 [0xe0] = MMX_OP2(pavgb),
2729 [0xe1] = MMX_OP2(psraw),
2730 [0xe2] = MMX_OP2(psrad),
2731 [0xe3] = MMX_OP2(pavgw),
2732 [0xe4] = MMX_OP2(pmulhuw),
2733 [0xe5] = MMX_OP2(pmulhw),
2734 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2735 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2736 [0xe8] = MMX_OP2(psubsb),
2737 [0xe9] = MMX_OP2(psubsw),
2738 [0xea] = MMX_OP2(pminsw),
2739 [0xeb] = MMX_OP2(por),
2740 [0xec] = MMX_OP2(paddsb),
2741 [0xed] = MMX_OP2(paddsw),
2742 [0xee] = MMX_OP2(pmaxsw),
2743 [0xef] = MMX_OP2(pxor),
2744 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2745 [0xf1] = MMX_OP2(psllw),
2746 [0xf2] = MMX_OP2(pslld),
2747 [0xf3] = MMX_OP2(psllq),
2748 [0xf4] = MMX_OP2(pmuludq),
2749 [0xf5] = MMX_OP2(pmaddwd),
2750 [0xf6] = MMX_OP2(psadbw),
2751 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2752 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2753 [0xf8] = MMX_OP2(psubb),
2754 [0xf9] = MMX_OP2(psubw),
2755 [0xfa] = MMX_OP2(psubl),
2756 [0xfb] = MMX_OP2(psubq),
2757 [0xfc] = MMX_OP2(paddb),
2758 [0xfd] = MMX_OP2(paddw),
2759 [0xfe] = MMX_OP2(paddl),
2762 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2763 [0 + 2] = MMX_OP2(psrlw),
2764 [0 + 4] = MMX_OP2(psraw),
2765 [0 + 6] = MMX_OP2(psllw),
2766 [8 + 2] = MMX_OP2(psrld),
2767 [8 + 4] = MMX_OP2(psrad),
2768 [8 + 6] = MMX_OP2(pslld),
2769 [16 + 2] = MMX_OP2(psrlq),
2770 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2771 [16 + 6] = MMX_OP2(psllq),
2772 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2775 static const SSEFunc_0_epi sse_op_table3ai[] = {
2776 gen_helper_cvtsi2ss,
2777 gen_helper_cvtsi2sd
2780 #ifdef TARGET_X86_64
2781 static const SSEFunc_0_epl sse_op_table3aq[] = {
2782 gen_helper_cvtsq2ss,
2783 gen_helper_cvtsq2sd
2785 #endif
2787 static const SSEFunc_i_ep sse_op_table3bi[] = {
2788 gen_helper_cvttss2si,
2789 gen_helper_cvtss2si,
2790 gen_helper_cvttsd2si,
2791 gen_helper_cvtsd2si
2794 #ifdef TARGET_X86_64
2795 static const SSEFunc_l_ep sse_op_table3bq[] = {
2796 gen_helper_cvttss2sq,
2797 gen_helper_cvtss2sq,
2798 gen_helper_cvttsd2sq,
2799 gen_helper_cvtsd2sq
2801 #endif
2803 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2804 SSE_FOP(cmpeq),
2805 SSE_FOP(cmplt),
2806 SSE_FOP(cmple),
2807 SSE_FOP(cmpunord),
2808 SSE_FOP(cmpneq),
2809 SSE_FOP(cmpnlt),
2810 SSE_FOP(cmpnle),
2811 SSE_FOP(cmpord),
2814 static const SSEFunc_0_epp sse_op_table5[256] = {
2815 [0x0c] = gen_helper_pi2fw,
2816 [0x0d] = gen_helper_pi2fd,
2817 [0x1c] = gen_helper_pf2iw,
2818 [0x1d] = gen_helper_pf2id,
2819 [0x8a] = gen_helper_pfnacc,
2820 [0x8e] = gen_helper_pfpnacc,
2821 [0x90] = gen_helper_pfcmpge,
2822 [0x94] = gen_helper_pfmin,
2823 [0x96] = gen_helper_pfrcp,
2824 [0x97] = gen_helper_pfrsqrt,
2825 [0x9a] = gen_helper_pfsub,
2826 [0x9e] = gen_helper_pfadd,
2827 [0xa0] = gen_helper_pfcmpgt,
2828 [0xa4] = gen_helper_pfmax,
2829 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2830 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2831 [0xaa] = gen_helper_pfsubr,
2832 [0xae] = gen_helper_pfacc,
2833 [0xb0] = gen_helper_pfcmpeq,
2834 [0xb4] = gen_helper_pfmul,
2835 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2836 [0xb7] = gen_helper_pmulhrw_mmx,
2837 [0xbb] = gen_helper_pswapd,
2838 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
2841 struct SSEOpHelper_epp {
2842 SSEFunc_0_epp op[2];
2843 uint32_t ext_mask;
2846 struct SSEOpHelper_eppi {
2847 SSEFunc_0_eppi op[2];
2848 uint32_t ext_mask;
2851 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2852 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2853 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
2854 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
2855 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2856 CPUID_EXT_PCLMULQDQ }
2857 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
2859 static const struct SSEOpHelper_epp sse_op_table6[256] = {
2860 [0x00] = SSSE3_OP(pshufb),
2861 [0x01] = SSSE3_OP(phaddw),
2862 [0x02] = SSSE3_OP(phaddd),
2863 [0x03] = SSSE3_OP(phaddsw),
2864 [0x04] = SSSE3_OP(pmaddubsw),
2865 [0x05] = SSSE3_OP(phsubw),
2866 [0x06] = SSSE3_OP(phsubd),
2867 [0x07] = SSSE3_OP(phsubsw),
2868 [0x08] = SSSE3_OP(psignb),
2869 [0x09] = SSSE3_OP(psignw),
2870 [0x0a] = SSSE3_OP(psignd),
2871 [0x0b] = SSSE3_OP(pmulhrsw),
2872 [0x10] = SSE41_OP(pblendvb),
2873 [0x14] = SSE41_OP(blendvps),
2874 [0x15] = SSE41_OP(blendvpd),
2875 [0x17] = SSE41_OP(ptest),
2876 [0x1c] = SSSE3_OP(pabsb),
2877 [0x1d] = SSSE3_OP(pabsw),
2878 [0x1e] = SSSE3_OP(pabsd),
2879 [0x20] = SSE41_OP(pmovsxbw),
2880 [0x21] = SSE41_OP(pmovsxbd),
2881 [0x22] = SSE41_OP(pmovsxbq),
2882 [0x23] = SSE41_OP(pmovsxwd),
2883 [0x24] = SSE41_OP(pmovsxwq),
2884 [0x25] = SSE41_OP(pmovsxdq),
2885 [0x28] = SSE41_OP(pmuldq),
2886 [0x29] = SSE41_OP(pcmpeqq),
2887 [0x2a] = SSE41_SPECIAL, /* movntqda */
2888 [0x2b] = SSE41_OP(packusdw),
2889 [0x30] = SSE41_OP(pmovzxbw),
2890 [0x31] = SSE41_OP(pmovzxbd),
2891 [0x32] = SSE41_OP(pmovzxbq),
2892 [0x33] = SSE41_OP(pmovzxwd),
2893 [0x34] = SSE41_OP(pmovzxwq),
2894 [0x35] = SSE41_OP(pmovzxdq),
2895 [0x37] = SSE42_OP(pcmpgtq),
2896 [0x38] = SSE41_OP(pminsb),
2897 [0x39] = SSE41_OP(pminsd),
2898 [0x3a] = SSE41_OP(pminuw),
2899 [0x3b] = SSE41_OP(pminud),
2900 [0x3c] = SSE41_OP(pmaxsb),
2901 [0x3d] = SSE41_OP(pmaxsd),
2902 [0x3e] = SSE41_OP(pmaxuw),
2903 [0x3f] = SSE41_OP(pmaxud),
2904 [0x40] = SSE41_OP(pmulld),
2905 [0x41] = SSE41_OP(phminposuw),
2906 [0xdb] = AESNI_OP(aesimc),
2907 [0xdc] = AESNI_OP(aesenc),
2908 [0xdd] = AESNI_OP(aesenclast),
2909 [0xde] = AESNI_OP(aesdec),
2910 [0xdf] = AESNI_OP(aesdeclast),
2913 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
2914 [0x08] = SSE41_OP(roundps),
2915 [0x09] = SSE41_OP(roundpd),
2916 [0x0a] = SSE41_OP(roundss),
2917 [0x0b] = SSE41_OP(roundsd),
2918 [0x0c] = SSE41_OP(blendps),
2919 [0x0d] = SSE41_OP(blendpd),
2920 [0x0e] = SSE41_OP(pblendw),
2921 [0x0f] = SSSE3_OP(palignr),
2922 [0x14] = SSE41_SPECIAL, /* pextrb */
2923 [0x15] = SSE41_SPECIAL, /* pextrw */
2924 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
2925 [0x17] = SSE41_SPECIAL, /* extractps */
2926 [0x20] = SSE41_SPECIAL, /* pinsrb */
2927 [0x21] = SSE41_SPECIAL, /* insertps */
2928 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
2929 [0x40] = SSE41_OP(dpps),
2930 [0x41] = SSE41_OP(dppd),
2931 [0x42] = SSE41_OP(mpsadbw),
2932 [0x44] = PCLMULQDQ_OP(pclmulqdq),
2933 [0x60] = SSE42_OP(pcmpestrm),
2934 [0x61] = SSE42_OP(pcmpestri),
2935 [0x62] = SSE42_OP(pcmpistrm),
2936 [0x63] = SSE42_OP(pcmpistri),
2937 [0xdf] = AESNI_OP(aeskeygenassist),
2940 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
2941 target_ulong pc_start, int rex_r)
2943 int b1, op1_offset, op2_offset, is_xmm, val;
2944 int modrm, mod, rm, reg;
2945 SSEFunc_0_epp sse_fn_epp;
2946 SSEFunc_0_eppi sse_fn_eppi;
2947 SSEFunc_0_ppi sse_fn_ppi;
2948 SSEFunc_0_eppt sse_fn_eppt;
2949 TCGMemOp ot;
2951 b &= 0xff;
2952 if (s->prefix & PREFIX_DATA)
2953 b1 = 1;
2954 else if (s->prefix & PREFIX_REPZ)
2955 b1 = 2;
2956 else if (s->prefix & PREFIX_REPNZ)
2957 b1 = 3;
2958 else
2959 b1 = 0;
2960 sse_fn_epp = sse_op_table1[b][b1];
2961 if (!sse_fn_epp) {
2962 goto unknown_op;
2964 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
2965 is_xmm = 1;
2966 } else {
2967 if (b1 == 0) {
2968 /* MMX case */
2969 is_xmm = 0;
2970 } else {
2971 is_xmm = 1;
2974 /* simple MMX/SSE operation */
2975 if (s->flags & HF_TS_MASK) {
2976 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2977 return;
2979 if (s->flags & HF_EM_MASK) {
2980 illegal_op:
2981 gen_illegal_opcode(s);
2982 return;
2984 if (is_xmm
2985 && !(s->flags & HF_OSFXSR_MASK)
2986 && ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
2987 goto unknown_op;
2989 if (b == 0x0e) {
2990 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
2991 /* If we were fully decoding this we might use illegal_op. */
2992 goto unknown_op;
2994 /* femms */
2995 gen_helper_emms(cpu_env);
2996 return;
2998 if (b == 0x77) {
2999 /* emms */
3000 gen_helper_emms(cpu_env);
3001 return;
3003 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3004 the static cpu state) */
3005 if (!is_xmm) {
3006 gen_helper_enter_mmx(cpu_env);
3009 modrm = cpu_ldub_code(env, s->pc++);
3010 reg = ((modrm >> 3) & 7);
3011 if (is_xmm)
3012 reg |= rex_r;
3013 mod = (modrm >> 6) & 3;
3014 if (sse_fn_epp == SSE_SPECIAL) {
3015 b |= (b1 << 8);
3016 switch(b) {
3017 case 0x0e7: /* movntq */
3018 if (mod == 3) {
3019 goto illegal_op;
3021 gen_lea_modrm(env, s, modrm);
3022 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3023 break;
3024 case 0x1e7: /* movntdq */
3025 case 0x02b: /* movntps */
3026 case 0x12b: /* movntps */
3027 if (mod == 3)
3028 goto illegal_op;
3029 gen_lea_modrm(env, s, modrm);
3030 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3031 break;
3032 case 0x3f0: /* lddqu */
3033 if (mod == 3)
3034 goto illegal_op;
3035 gen_lea_modrm(env, s, modrm);
3036 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3037 break;
3038 case 0x22b: /* movntss */
3039 case 0x32b: /* movntsd */
3040 if (mod == 3)
3041 goto illegal_op;
3042 gen_lea_modrm(env, s, modrm);
3043 if (b1 & 1) {
3044 gen_stq_env_A0(s, offsetof(CPUX86State,
3045 xmm_regs[reg].ZMM_Q(0)));
3046 } else {
3047 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
3048 xmm_regs[reg].ZMM_L(0)));
3049 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3051 break;
3052 case 0x6e: /* movd mm, ea */
3053 #ifdef TARGET_X86_64
3054 if (s->dflag == MO_64) {
3055 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3056 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3057 } else
3058 #endif
3060 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3061 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3062 offsetof(CPUX86State,fpregs[reg].mmx));
3063 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3064 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
3066 break;
3067 case 0x16e: /* movd xmm, ea */
3068 #ifdef TARGET_X86_64
3069 if (s->dflag == MO_64) {
3070 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3071 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3072 offsetof(CPUX86State,xmm_regs[reg]));
3073 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T0);
3074 } else
3075 #endif
3077 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3078 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3079 offsetof(CPUX86State,xmm_regs[reg]));
3080 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3081 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
3083 break;
3084 case 0x6f: /* movq mm, ea */
3085 if (mod != 3) {
3086 gen_lea_modrm(env, s, modrm);
3087 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3088 } else {
3089 rm = (modrm & 7);
3090 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3091 offsetof(CPUX86State,fpregs[rm].mmx));
3092 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3093 offsetof(CPUX86State,fpregs[reg].mmx));
3095 break;
3096 case 0x010: /* movups */
3097 case 0x110: /* movupd */
3098 case 0x028: /* movaps */
3099 case 0x128: /* movapd */
3100 case 0x16f: /* movdqa xmm, ea */
3101 case 0x26f: /* movdqu xmm, ea */
3102 if (mod != 3) {
3103 gen_lea_modrm(env, s, modrm);
3104 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3105 } else {
3106 rm = (modrm & 7) | REX_B(s);
3107 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3108 offsetof(CPUX86State,xmm_regs[rm]));
3110 break;
3111 case 0x210: /* movss xmm, ea */
3112 if (mod != 3) {
3113 gen_lea_modrm(env, s, modrm);
3114 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3115 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3116 tcg_gen_movi_tl(cpu_T0, 0);
3117 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3118 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3119 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3120 } else {
3121 rm = (modrm & 7) | REX_B(s);
3122 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3123 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3125 break;
3126 case 0x310: /* movsd xmm, ea */
3127 if (mod != 3) {
3128 gen_lea_modrm(env, s, modrm);
3129 gen_ldq_env_A0(s, offsetof(CPUX86State,
3130 xmm_regs[reg].ZMM_Q(0)));
3131 tcg_gen_movi_tl(cpu_T0, 0);
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_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3137 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3139 break;
3140 case 0x012: /* movlps */
3141 case 0x112: /* movlpd */
3142 if (mod != 3) {
3143 gen_lea_modrm(env, s, modrm);
3144 gen_ldq_env_A0(s, offsetof(CPUX86State,
3145 xmm_regs[reg].ZMM_Q(0)));
3146 } else {
3147 /* movhlps */
3148 rm = (modrm & 7) | REX_B(s);
3149 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3150 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3152 break;
3153 case 0x212: /* movsldup */
3154 if (mod != 3) {
3155 gen_lea_modrm(env, s, modrm);
3156 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3157 } else {
3158 rm = (modrm & 7) | REX_B(s);
3159 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3160 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3161 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3162 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3164 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3165 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3166 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3167 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3168 break;
3169 case 0x312: /* movddup */
3170 if (mod != 3) {
3171 gen_lea_modrm(env, s, modrm);
3172 gen_ldq_env_A0(s, offsetof(CPUX86State,
3173 xmm_regs[reg].ZMM_Q(0)));
3174 } else {
3175 rm = (modrm & 7) | REX_B(s);
3176 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3177 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3179 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3180 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3181 break;
3182 case 0x016: /* movhps */
3183 case 0x116: /* movhpd */
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(1)));
3188 } else {
3189 /* movlhps */
3190 rm = (modrm & 7) | REX_B(s);
3191 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3192 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3194 break;
3195 case 0x216: /* movshdup */
3196 if (mod != 3) {
3197 gen_lea_modrm(env, s, modrm);
3198 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3199 } else {
3200 rm = (modrm & 7) | REX_B(s);
3201 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3202 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3203 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3204 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3206 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3207 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3208 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3209 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3210 break;
3211 case 0x178:
3212 case 0x378:
3214 int bit_index, field_length;
3216 if (b1 == 1 && reg != 0)
3217 goto illegal_op;
3218 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3219 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3220 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3221 offsetof(CPUX86State,xmm_regs[reg]));
3222 if (b1 == 1)
3223 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3224 tcg_const_i32(bit_index),
3225 tcg_const_i32(field_length));
3226 else
3227 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3228 tcg_const_i32(bit_index),
3229 tcg_const_i32(field_length));
3231 break;
3232 case 0x7e: /* movd ea, mm */
3233 #ifdef TARGET_X86_64
3234 if (s->dflag == MO_64) {
3235 tcg_gen_ld_i64(cpu_T0, cpu_env,
3236 offsetof(CPUX86State,fpregs[reg].mmx));
3237 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3238 } else
3239 #endif
3241 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3242 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3243 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3245 break;
3246 case 0x17e: /* movd ea, xmm */
3247 #ifdef TARGET_X86_64
3248 if (s->dflag == MO_64) {
3249 tcg_gen_ld_i64(cpu_T0, cpu_env,
3250 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
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,xmm_regs[reg].ZMM_L(0)));
3257 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3259 break;
3260 case 0x27e: /* movq xmm, ea */
3261 if (mod != 3) {
3262 gen_lea_modrm(env, s, modrm);
3263 gen_ldq_env_A0(s, offsetof(CPUX86State,
3264 xmm_regs[reg].ZMM_Q(0)));
3265 } else {
3266 rm = (modrm & 7) | REX_B(s);
3267 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3268 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3270 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3271 break;
3272 case 0x7f: /* movq ea, mm */
3273 if (mod != 3) {
3274 gen_lea_modrm(env, s, modrm);
3275 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3276 } else {
3277 rm = (modrm & 7);
3278 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3279 offsetof(CPUX86State,fpregs[reg].mmx));
3281 break;
3282 case 0x011: /* movups */
3283 case 0x111: /* movupd */
3284 case 0x029: /* movaps */
3285 case 0x129: /* movapd */
3286 case 0x17f: /* movdqa ea, xmm */
3287 case 0x27f: /* movdqu ea, xmm */
3288 if (mod != 3) {
3289 gen_lea_modrm(env, s, modrm);
3290 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3291 } else {
3292 rm = (modrm & 7) | REX_B(s);
3293 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3294 offsetof(CPUX86State,xmm_regs[reg]));
3296 break;
3297 case 0x211: /* movss ea, xmm */
3298 if (mod != 3) {
3299 gen_lea_modrm(env, s, modrm);
3300 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3301 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3302 } else {
3303 rm = (modrm & 7) | REX_B(s);
3304 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)),
3305 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3307 break;
3308 case 0x311: /* movsd ea, xmm */
3309 if (mod != 3) {
3310 gen_lea_modrm(env, s, modrm);
3311 gen_stq_env_A0(s, offsetof(CPUX86State,
3312 xmm_regs[reg].ZMM_Q(0)));
3313 } else {
3314 rm = (modrm & 7) | REX_B(s);
3315 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3316 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3318 break;
3319 case 0x013: /* movlps */
3320 case 0x113: /* movlpd */
3321 if (mod != 3) {
3322 gen_lea_modrm(env, s, modrm);
3323 gen_stq_env_A0(s, offsetof(CPUX86State,
3324 xmm_regs[reg].ZMM_Q(0)));
3325 } else {
3326 goto illegal_op;
3328 break;
3329 case 0x017: /* movhps */
3330 case 0x117: /* movhpd */
3331 if (mod != 3) {
3332 gen_lea_modrm(env, s, modrm);
3333 gen_stq_env_A0(s, offsetof(CPUX86State,
3334 xmm_regs[reg].ZMM_Q(1)));
3335 } else {
3336 goto illegal_op;
3338 break;
3339 case 0x71: /* shift mm, im */
3340 case 0x72:
3341 case 0x73:
3342 case 0x171: /* shift xmm, im */
3343 case 0x172:
3344 case 0x173:
3345 if (b1 >= 2) {
3346 goto unknown_op;
3348 val = cpu_ldub_code(env, s->pc++);
3349 if (is_xmm) {
3350 tcg_gen_movi_tl(cpu_T0, val);
3351 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3352 tcg_gen_movi_tl(cpu_T0, 0);
3353 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(1)));
3354 op1_offset = offsetof(CPUX86State,xmm_t0);
3355 } else {
3356 tcg_gen_movi_tl(cpu_T0, val);
3357 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3358 tcg_gen_movi_tl(cpu_T0, 0);
3359 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3360 op1_offset = offsetof(CPUX86State,mmx_t0);
3362 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3363 (((modrm >> 3)) & 7)][b1];
3364 if (!sse_fn_epp) {
3365 goto unknown_op;
3367 if (is_xmm) {
3368 rm = (modrm & 7) | REX_B(s);
3369 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3370 } else {
3371 rm = (modrm & 7);
3372 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3374 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3375 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3376 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3377 break;
3378 case 0x050: /* movmskps */
3379 rm = (modrm & 7) | REX_B(s);
3380 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3381 offsetof(CPUX86State,xmm_regs[rm]));
3382 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3383 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3384 break;
3385 case 0x150: /* movmskpd */
3386 rm = (modrm & 7) | REX_B(s);
3387 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3388 offsetof(CPUX86State,xmm_regs[rm]));
3389 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3390 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3391 break;
3392 case 0x02a: /* cvtpi2ps */
3393 case 0x12a: /* cvtpi2pd */
3394 gen_helper_enter_mmx(cpu_env);
3395 if (mod != 3) {
3396 gen_lea_modrm(env, s, modrm);
3397 op2_offset = offsetof(CPUX86State,mmx_t0);
3398 gen_ldq_env_A0(s, op2_offset);
3399 } else {
3400 rm = (modrm & 7);
3401 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3403 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3404 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3405 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3406 switch(b >> 8) {
3407 case 0x0:
3408 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3409 break;
3410 default:
3411 case 0x1:
3412 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3413 break;
3415 break;
3416 case 0x22a: /* cvtsi2ss */
3417 case 0x32a: /* cvtsi2sd */
3418 ot = mo_64_32(s->dflag);
3419 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3420 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3421 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3422 if (ot == MO_32) {
3423 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3424 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3425 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3426 } else {
3427 #ifdef TARGET_X86_64
3428 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3429 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T0);
3430 #else
3431 goto illegal_op;
3432 #endif
3434 break;
3435 case 0x02c: /* cvttps2pi */
3436 case 0x12c: /* cvttpd2pi */
3437 case 0x02d: /* cvtps2pi */
3438 case 0x12d: /* cvtpd2pi */
3439 gen_helper_enter_mmx(cpu_env);
3440 if (mod != 3) {
3441 gen_lea_modrm(env, s, modrm);
3442 op2_offset = offsetof(CPUX86State,xmm_t0);
3443 gen_ldo_env_A0(s, op2_offset);
3444 } else {
3445 rm = (modrm & 7) | REX_B(s);
3446 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3448 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3449 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3450 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3451 switch(b) {
3452 case 0x02c:
3453 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3454 break;
3455 case 0x12c:
3456 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3457 break;
3458 case 0x02d:
3459 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3460 break;
3461 case 0x12d:
3462 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3463 break;
3465 break;
3466 case 0x22c: /* cvttss2si */
3467 case 0x32c: /* cvttsd2si */
3468 case 0x22d: /* cvtss2si */
3469 case 0x32d: /* cvtsd2si */
3470 ot = mo_64_32(s->dflag);
3471 if (mod != 3) {
3472 gen_lea_modrm(env, s, modrm);
3473 if ((b >> 8) & 1) {
3474 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3475 } else {
3476 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3477 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3479 op2_offset = offsetof(CPUX86State,xmm_t0);
3480 } else {
3481 rm = (modrm & 7) | REX_B(s);
3482 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3484 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3485 if (ot == MO_32) {
3486 SSEFunc_i_ep sse_fn_i_ep =
3487 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3488 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3489 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
3490 } else {
3491 #ifdef TARGET_X86_64
3492 SSEFunc_l_ep sse_fn_l_ep =
3493 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3494 sse_fn_l_ep(cpu_T0, cpu_env, cpu_ptr0);
3495 #else
3496 goto illegal_op;
3497 #endif
3499 gen_op_mov_reg_v(ot, reg, cpu_T0);
3500 break;
3501 case 0xc4: /* pinsrw */
3502 case 0x1c4:
3503 s->rip_offset = 1;
3504 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3505 val = cpu_ldub_code(env, s->pc++);
3506 if (b1) {
3507 val &= 7;
3508 tcg_gen_st16_tl(cpu_T0, cpu_env,
3509 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3510 } else {
3511 val &= 3;
3512 tcg_gen_st16_tl(cpu_T0, cpu_env,
3513 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3515 break;
3516 case 0xc5: /* pextrw */
3517 case 0x1c5:
3518 if (mod != 3)
3519 goto illegal_op;
3520 ot = mo_64_32(s->dflag);
3521 val = cpu_ldub_code(env, s->pc++);
3522 if (b1) {
3523 val &= 7;
3524 rm = (modrm & 7) | REX_B(s);
3525 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3526 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3527 } else {
3528 val &= 3;
3529 rm = (modrm & 7);
3530 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3531 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3533 reg = ((modrm >> 3) & 7) | rex_r;
3534 gen_op_mov_reg_v(ot, reg, cpu_T0);
3535 break;
3536 case 0x1d6: /* movq ea, xmm */
3537 if (mod != 3) {
3538 gen_lea_modrm(env, s, modrm);
3539 gen_stq_env_A0(s, offsetof(CPUX86State,
3540 xmm_regs[reg].ZMM_Q(0)));
3541 } else {
3542 rm = (modrm & 7) | REX_B(s);
3543 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3544 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3545 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3547 break;
3548 case 0x2d6: /* movq2dq */
3549 gen_helper_enter_mmx(cpu_env);
3550 rm = (modrm & 7);
3551 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3552 offsetof(CPUX86State,fpregs[rm].mmx));
3553 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3554 break;
3555 case 0x3d6: /* movdq2q */
3556 gen_helper_enter_mmx(cpu_env);
3557 rm = (modrm & 7) | REX_B(s);
3558 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3559 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3560 break;
3561 case 0xd7: /* pmovmskb */
3562 case 0x1d7:
3563 if (mod != 3)
3564 goto illegal_op;
3565 if (b1) {
3566 rm = (modrm & 7) | REX_B(s);
3567 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3568 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3569 } else {
3570 rm = (modrm & 7);
3571 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3572 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3574 reg = ((modrm >> 3) & 7) | rex_r;
3575 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3576 break;
3578 case 0x138:
3579 case 0x038:
3580 b = modrm;
3581 if ((b & 0xf0) == 0xf0) {
3582 goto do_0f_38_fx;
3584 modrm = cpu_ldub_code(env, s->pc++);
3585 rm = modrm & 7;
3586 reg = ((modrm >> 3) & 7) | rex_r;
3587 mod = (modrm >> 6) & 3;
3588 if (b1 >= 2) {
3589 goto unknown_op;
3592 sse_fn_epp = sse_op_table6[b].op[b1];
3593 if (!sse_fn_epp) {
3594 goto unknown_op;
3596 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3597 goto illegal_op;
3599 if (b1) {
3600 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3601 if (mod == 3) {
3602 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3603 } else {
3604 op2_offset = offsetof(CPUX86State,xmm_t0);
3605 gen_lea_modrm(env, s, modrm);
3606 switch (b) {
3607 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3608 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3609 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3610 gen_ldq_env_A0(s, op2_offset +
3611 offsetof(ZMMReg, ZMM_Q(0)));
3612 break;
3613 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3614 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3615 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3616 s->mem_index, MO_LEUL);
3617 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3618 offsetof(ZMMReg, ZMM_L(0)));
3619 break;
3620 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3621 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3622 s->mem_index, MO_LEUW);
3623 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3624 offsetof(ZMMReg, ZMM_W(0)));
3625 break;
3626 case 0x2a: /* movntqda */
3627 gen_ldo_env_A0(s, op1_offset);
3628 return;
3629 default:
3630 gen_ldo_env_A0(s, op2_offset);
3633 } else {
3634 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3635 if (mod == 3) {
3636 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3637 } else {
3638 op2_offset = offsetof(CPUX86State,mmx_t0);
3639 gen_lea_modrm(env, s, modrm);
3640 gen_ldq_env_A0(s, op2_offset);
3643 if (sse_fn_epp == SSE_SPECIAL) {
3644 goto unknown_op;
3647 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3648 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3649 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3651 if (b == 0x17) {
3652 set_cc_op(s, CC_OP_EFLAGS);
3654 break;
3656 case 0x238:
3657 case 0x338:
3658 do_0f_38_fx:
3659 /* Various integer extensions at 0f 38 f[0-f]. */
3660 b = modrm | (b1 << 8);
3661 modrm = cpu_ldub_code(env, s->pc++);
3662 reg = ((modrm >> 3) & 7) | rex_r;
3664 switch (b) {
3665 case 0x3f0: /* crc32 Gd,Eb */
3666 case 0x3f1: /* crc32 Gd,Ey */
3667 do_crc32:
3668 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3669 goto illegal_op;
3671 if ((b & 0xff) == 0xf0) {
3672 ot = MO_8;
3673 } else if (s->dflag != MO_64) {
3674 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3675 } else {
3676 ot = MO_64;
3679 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
3680 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3681 gen_helper_crc32(cpu_T0, cpu_tmp2_i32,
3682 cpu_T0, tcg_const_i32(8 << ot));
3684 ot = mo_64_32(s->dflag);
3685 gen_op_mov_reg_v(ot, reg, cpu_T0);
3686 break;
3688 case 0x1f0: /* crc32 or movbe */
3689 case 0x1f1:
3690 /* For these insns, the f3 prefix is supposed to have priority
3691 over the 66 prefix, but that's not what we implement above
3692 setting b1. */
3693 if (s->prefix & PREFIX_REPNZ) {
3694 goto do_crc32;
3696 /* FALLTHRU */
3697 case 0x0f0: /* movbe Gy,My */
3698 case 0x0f1: /* movbe My,Gy */
3699 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3700 goto illegal_op;
3702 if (s->dflag != MO_64) {
3703 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3704 } else {
3705 ot = MO_64;
3708 gen_lea_modrm(env, s, modrm);
3709 if ((b & 1) == 0) {
3710 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
3711 s->mem_index, ot | MO_BE);
3712 gen_op_mov_reg_v(ot, reg, cpu_T0);
3713 } else {
3714 tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
3715 s->mem_index, ot | MO_BE);
3717 break;
3719 case 0x0f2: /* andn Gy, By, Ey */
3720 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3721 || !(s->prefix & PREFIX_VEX)
3722 || s->vex_l != 0) {
3723 goto illegal_op;
3725 ot = mo_64_32(s->dflag);
3726 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3727 tcg_gen_andc_tl(cpu_T0, cpu_regs[s->vex_v], cpu_T0);
3728 gen_op_mov_reg_v(ot, reg, cpu_T0);
3729 gen_op_update1_cc();
3730 set_cc_op(s, CC_OP_LOGICB + ot);
3731 break;
3733 case 0x0f7: /* bextr Gy, Ey, By */
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);
3741 TCGv bound, zero;
3743 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3744 /* Extract START, and shift the operand.
3745 Shifts larger than operand size get zeros. */
3746 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
3747 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_A0);
3749 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3750 zero = tcg_const_tl(0);
3751 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T0, cpu_A0, bound,
3752 cpu_T0, zero);
3753 tcg_temp_free(zero);
3755 /* Extract the LEN into a mask. Lengths larger than
3756 operand size get all ones. */
3757 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
3758 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
3759 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
3760 cpu_A0, bound);
3761 tcg_temp_free(bound);
3762 tcg_gen_movi_tl(cpu_T1, 1);
3763 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_A0);
3764 tcg_gen_subi_tl(cpu_T1, cpu_T1, 1);
3765 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
3767 gen_op_mov_reg_v(ot, reg, cpu_T0);
3768 gen_op_update1_cc();
3769 set_cc_op(s, CC_OP_LOGICB + ot);
3771 break;
3773 case 0x0f5: /* bzhi Gy, Ey, By */
3774 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3775 || !(s->prefix & PREFIX_VEX)
3776 || s->vex_l != 0) {
3777 goto illegal_op;
3779 ot = mo_64_32(s->dflag);
3780 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3781 tcg_gen_ext8u_tl(cpu_T1, cpu_regs[s->vex_v]);
3783 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3784 /* Note that since we're using BMILG (in order to get O
3785 cleared) we need to store the inverse into C. */
3786 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3787 cpu_T1, bound);
3788 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T1, cpu_T1,
3789 bound, bound, cpu_T1);
3790 tcg_temp_free(bound);
3792 tcg_gen_movi_tl(cpu_A0, -1);
3793 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T1);
3794 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_A0);
3795 gen_op_mov_reg_v(ot, reg, cpu_T0);
3796 gen_op_update1_cc();
3797 set_cc_op(s, CC_OP_BMILGB + ot);
3798 break;
3800 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3801 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3802 || !(s->prefix & PREFIX_VEX)
3803 || s->vex_l != 0) {
3804 goto illegal_op;
3806 ot = mo_64_32(s->dflag);
3807 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3808 switch (ot) {
3809 default:
3810 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3811 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3812 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3813 cpu_tmp2_i32, cpu_tmp3_i32);
3814 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3815 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
3816 break;
3817 #ifdef TARGET_X86_64
3818 case MO_64:
3819 tcg_gen_mulu2_i64(cpu_T0, cpu_T1,
3820 cpu_T0, cpu_regs[R_EDX]);
3821 tcg_gen_mov_i64(cpu_regs[s->vex_v], cpu_T0);
3822 tcg_gen_mov_i64(cpu_regs[reg], cpu_T1);
3823 break;
3824 #endif
3826 break;
3828 case 0x3f5: /* pdep Gy, By, Ey */
3829 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3830 || !(s->prefix & PREFIX_VEX)
3831 || s->vex_l != 0) {
3832 goto illegal_op;
3834 ot = mo_64_32(s->dflag);
3835 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3836 /* Note that by zero-extending the mask operand, we
3837 automatically handle zero-extending the result. */
3838 if (ot == MO_64) {
3839 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3840 } else {
3841 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3843 gen_helper_pdep(cpu_regs[reg], cpu_T0, cpu_T1);
3844 break;
3846 case 0x2f5: /* pext Gy, By, Ey */
3847 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3848 || !(s->prefix & PREFIX_VEX)
3849 || s->vex_l != 0) {
3850 goto illegal_op;
3852 ot = mo_64_32(s->dflag);
3853 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3854 /* Note that by zero-extending the mask operand, we
3855 automatically handle zero-extending the result. */
3856 if (ot == MO_64) {
3857 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3858 } else {
3859 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3861 gen_helper_pext(cpu_regs[reg], cpu_T0, cpu_T1);
3862 break;
3864 case 0x1f6: /* adcx Gy, Ey */
3865 case 0x2f6: /* adox Gy, Ey */
3866 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3867 goto illegal_op;
3868 } else {
3869 TCGv carry_in, carry_out, zero;
3870 int end_op;
3872 ot = mo_64_32(s->dflag);
3873 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3875 /* Re-use the carry-out from a previous round. */
3876 TCGV_UNUSED(carry_in);
3877 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3878 switch (s->cc_op) {
3879 case CC_OP_ADCX:
3880 if (b == 0x1f6) {
3881 carry_in = cpu_cc_dst;
3882 end_op = CC_OP_ADCX;
3883 } else {
3884 end_op = CC_OP_ADCOX;
3886 break;
3887 case CC_OP_ADOX:
3888 if (b == 0x1f6) {
3889 end_op = CC_OP_ADCOX;
3890 } else {
3891 carry_in = cpu_cc_src2;
3892 end_op = CC_OP_ADOX;
3894 break;
3895 case CC_OP_ADCOX:
3896 end_op = CC_OP_ADCOX;
3897 carry_in = carry_out;
3898 break;
3899 default:
3900 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
3901 break;
3903 /* If we can't reuse carry-out, get it out of EFLAGS. */
3904 if (TCGV_IS_UNUSED(carry_in)) {
3905 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3906 gen_compute_eflags(s);
3908 carry_in = cpu_tmp0;
3909 tcg_gen_shri_tl(carry_in, cpu_cc_src,
3910 ctz32(b == 0x1f6 ? CC_C : CC_O));
3911 tcg_gen_andi_tl(carry_in, carry_in, 1);
3914 switch (ot) {
3915 #ifdef TARGET_X86_64
3916 case MO_32:
3917 /* If we know TL is 64-bit, and we want a 32-bit
3918 result, just do everything in 64-bit arithmetic. */
3919 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3920 tcg_gen_ext32u_i64(cpu_T0, cpu_T0);
3921 tcg_gen_add_i64(cpu_T0, cpu_T0, cpu_regs[reg]);
3922 tcg_gen_add_i64(cpu_T0, cpu_T0, carry_in);
3923 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T0);
3924 tcg_gen_shri_i64(carry_out, cpu_T0, 32);
3925 break;
3926 #endif
3927 default:
3928 /* Otherwise compute the carry-out in two steps. */
3929 zero = tcg_const_tl(0);
3930 tcg_gen_add2_tl(cpu_T0, carry_out,
3931 cpu_T0, zero,
3932 carry_in, zero);
3933 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3934 cpu_regs[reg], carry_out,
3935 cpu_T0, zero);
3936 tcg_temp_free(zero);
3937 break;
3939 set_cc_op(s, end_op);
3941 break;
3943 case 0x1f7: /* shlx Gy, Ey, By */
3944 case 0x2f7: /* sarx Gy, Ey, By */
3945 case 0x3f7: /* shrx Gy, Ey, By */
3946 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3947 || !(s->prefix & PREFIX_VEX)
3948 || s->vex_l != 0) {
3949 goto illegal_op;
3951 ot = mo_64_32(s->dflag);
3952 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3953 if (ot == MO_64) {
3954 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 63);
3955 } else {
3956 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 31);
3958 if (b == 0x1f7) {
3959 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
3960 } else if (b == 0x2f7) {
3961 if (ot != MO_64) {
3962 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
3964 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
3965 } else {
3966 if (ot != MO_64) {
3967 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
3969 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
3971 gen_op_mov_reg_v(ot, reg, cpu_T0);
3972 break;
3974 case 0x0f3:
3975 case 0x1f3:
3976 case 0x2f3:
3977 case 0x3f3: /* Group 17 */
3978 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3979 || !(s->prefix & PREFIX_VEX)
3980 || s->vex_l != 0) {
3981 goto illegal_op;
3983 ot = mo_64_32(s->dflag);
3984 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3986 switch (reg & 7) {
3987 case 1: /* blsr By,Ey */
3988 tcg_gen_neg_tl(cpu_T1, cpu_T0);
3989 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
3990 gen_op_mov_reg_v(ot, s->vex_v, cpu_T0);
3991 gen_op_update2_cc();
3992 set_cc_op(s, CC_OP_BMILGB + ot);
3993 break;
3995 case 2: /* blsmsk By,Ey */
3996 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
3997 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
3998 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_cc_src);
3999 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4000 set_cc_op(s, CC_OP_BMILGB + ot);
4001 break;
4003 case 3: /* blsi By, Ey */
4004 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4005 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
4006 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_cc_src);
4007 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4008 set_cc_op(s, CC_OP_BMILGB + ot);
4009 break;
4011 default:
4012 goto unknown_op;
4014 break;
4016 default:
4017 goto unknown_op;
4019 break;
4021 case 0x03a:
4022 case 0x13a:
4023 b = modrm;
4024 modrm = cpu_ldub_code(env, s->pc++);
4025 rm = modrm & 7;
4026 reg = ((modrm >> 3) & 7) | rex_r;
4027 mod = (modrm >> 6) & 3;
4028 if (b1 >= 2) {
4029 goto unknown_op;
4032 sse_fn_eppi = sse_op_table7[b].op[b1];
4033 if (!sse_fn_eppi) {
4034 goto unknown_op;
4036 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4037 goto illegal_op;
4039 if (sse_fn_eppi == SSE_SPECIAL) {
4040 ot = mo_64_32(s->dflag);
4041 rm = (modrm & 7) | REX_B(s);
4042 if (mod != 3)
4043 gen_lea_modrm(env, s, modrm);
4044 reg = ((modrm >> 3) & 7) | rex_r;
4045 val = cpu_ldub_code(env, s->pc++);
4046 switch (b) {
4047 case 0x14: /* pextrb */
4048 tcg_gen_ld8u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4049 xmm_regs[reg].ZMM_B(val & 15)));
4050 if (mod == 3) {
4051 gen_op_mov_reg_v(ot, rm, cpu_T0);
4052 } else {
4053 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4054 s->mem_index, MO_UB);
4056 break;
4057 case 0x15: /* pextrw */
4058 tcg_gen_ld16u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4059 xmm_regs[reg].ZMM_W(val & 7)));
4060 if (mod == 3) {
4061 gen_op_mov_reg_v(ot, rm, cpu_T0);
4062 } else {
4063 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4064 s->mem_index, MO_LEUW);
4066 break;
4067 case 0x16:
4068 if (ot == MO_32) { /* pextrd */
4069 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4070 offsetof(CPUX86State,
4071 xmm_regs[reg].ZMM_L(val & 3)));
4072 if (mod == 3) {
4073 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
4074 } else {
4075 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4076 s->mem_index, MO_LEUL);
4078 } else { /* pextrq */
4079 #ifdef TARGET_X86_64
4080 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4081 offsetof(CPUX86State,
4082 xmm_regs[reg].ZMM_Q(val & 1)));
4083 if (mod == 3) {
4084 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
4085 } else {
4086 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4087 s->mem_index, MO_LEQ);
4089 #else
4090 goto illegal_op;
4091 #endif
4093 break;
4094 case 0x17: /* extractps */
4095 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4096 xmm_regs[reg].ZMM_L(val & 3)));
4097 if (mod == 3) {
4098 gen_op_mov_reg_v(ot, rm, cpu_T0);
4099 } else {
4100 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4101 s->mem_index, MO_LEUL);
4103 break;
4104 case 0x20: /* pinsrb */
4105 if (mod == 3) {
4106 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
4107 } else {
4108 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
4109 s->mem_index, MO_UB);
4111 tcg_gen_st8_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4112 xmm_regs[reg].ZMM_B(val & 15)));
4113 break;
4114 case 0x21: /* insertps */
4115 if (mod == 3) {
4116 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4117 offsetof(CPUX86State,xmm_regs[rm]
4118 .ZMM_L((val >> 6) & 3)));
4119 } else {
4120 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4121 s->mem_index, MO_LEUL);
4123 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4124 offsetof(CPUX86State,xmm_regs[reg]
4125 .ZMM_L((val >> 4) & 3)));
4126 if ((val >> 0) & 1)
4127 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4128 cpu_env, offsetof(CPUX86State,
4129 xmm_regs[reg].ZMM_L(0)));
4130 if ((val >> 1) & 1)
4131 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4132 cpu_env, offsetof(CPUX86State,
4133 xmm_regs[reg].ZMM_L(1)));
4134 if ((val >> 2) & 1)
4135 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4136 cpu_env, offsetof(CPUX86State,
4137 xmm_regs[reg].ZMM_L(2)));
4138 if ((val >> 3) & 1)
4139 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4140 cpu_env, offsetof(CPUX86State,
4141 xmm_regs[reg].ZMM_L(3)));
4142 break;
4143 case 0x22:
4144 if (ot == MO_32) { /* pinsrd */
4145 if (mod == 3) {
4146 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
4147 } else {
4148 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4149 s->mem_index, MO_LEUL);
4151 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4152 offsetof(CPUX86State,
4153 xmm_regs[reg].ZMM_L(val & 3)));
4154 } else { /* pinsrq */
4155 #ifdef TARGET_X86_64
4156 if (mod == 3) {
4157 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4158 } else {
4159 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4160 s->mem_index, MO_LEQ);
4162 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4163 offsetof(CPUX86State,
4164 xmm_regs[reg].ZMM_Q(val & 1)));
4165 #else
4166 goto illegal_op;
4167 #endif
4169 break;
4171 return;
4174 if (b1) {
4175 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4176 if (mod == 3) {
4177 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4178 } else {
4179 op2_offset = offsetof(CPUX86State,xmm_t0);
4180 gen_lea_modrm(env, s, modrm);
4181 gen_ldo_env_A0(s, op2_offset);
4183 } else {
4184 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4185 if (mod == 3) {
4186 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4187 } else {
4188 op2_offset = offsetof(CPUX86State,mmx_t0);
4189 gen_lea_modrm(env, s, modrm);
4190 gen_ldq_env_A0(s, op2_offset);
4193 val = cpu_ldub_code(env, s->pc++);
4195 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4196 set_cc_op(s, CC_OP_EFLAGS);
4198 if (s->dflag == MO_64) {
4199 /* The helper must use entire 64-bit gp registers */
4200 val |= 1 << 8;
4204 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4205 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4206 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4207 break;
4209 case 0x33a:
4210 /* Various integer extensions at 0f 3a f[0-f]. */
4211 b = modrm | (b1 << 8);
4212 modrm = cpu_ldub_code(env, s->pc++);
4213 reg = ((modrm >> 3) & 7) | rex_r;
4215 switch (b) {
4216 case 0x3f0: /* rorx Gy,Ey, Ib */
4217 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4218 || !(s->prefix & PREFIX_VEX)
4219 || s->vex_l != 0) {
4220 goto illegal_op;
4222 ot = mo_64_32(s->dflag);
4223 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4224 b = cpu_ldub_code(env, s->pc++);
4225 if (ot == MO_64) {
4226 tcg_gen_rotri_tl(cpu_T0, cpu_T0, b & 63);
4227 } else {
4228 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4229 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4230 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
4232 gen_op_mov_reg_v(ot, reg, cpu_T0);
4233 break;
4235 default:
4236 goto unknown_op;
4238 break;
4240 default:
4241 unknown_op:
4242 gen_unknown_opcode(env, s);
4243 return;
4245 } else {
4246 /* generic MMX or SSE operation */
4247 switch(b) {
4248 case 0x70: /* pshufx insn */
4249 case 0xc6: /* pshufx insn */
4250 case 0xc2: /* compare insns */
4251 s->rip_offset = 1;
4252 break;
4253 default:
4254 break;
4256 if (is_xmm) {
4257 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4258 if (mod != 3) {
4259 int sz = 4;
4261 gen_lea_modrm(env, s, modrm);
4262 op2_offset = offsetof(CPUX86State,xmm_t0);
4264 switch (b) {
4265 case 0x50 ... 0x5a:
4266 case 0x5c ... 0x5f:
4267 case 0xc2:
4268 /* Most sse scalar operations. */
4269 if (b1 == 2) {
4270 sz = 2;
4271 } else if (b1 == 3) {
4272 sz = 3;
4274 break;
4276 case 0x2e: /* ucomis[sd] */
4277 case 0x2f: /* comis[sd] */
4278 if (b1 == 0) {
4279 sz = 2;
4280 } else {
4281 sz = 3;
4283 break;
4286 switch (sz) {
4287 case 2:
4288 /* 32 bit access */
4289 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
4290 tcg_gen_st32_tl(cpu_T0, cpu_env,
4291 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4292 break;
4293 case 3:
4294 /* 64 bit access */
4295 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4296 break;
4297 default:
4298 /* 128 bit access */
4299 gen_ldo_env_A0(s, op2_offset);
4300 break;
4302 } else {
4303 rm = (modrm & 7) | REX_B(s);
4304 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4306 } else {
4307 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4308 if (mod != 3) {
4309 gen_lea_modrm(env, s, modrm);
4310 op2_offset = offsetof(CPUX86State,mmx_t0);
4311 gen_ldq_env_A0(s, op2_offset);
4312 } else {
4313 rm = (modrm & 7);
4314 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4317 switch(b) {
4318 case 0x0f: /* 3DNow! data insns */
4319 val = cpu_ldub_code(env, s->pc++);
4320 sse_fn_epp = sse_op_table5[val];
4321 if (!sse_fn_epp) {
4322 goto unknown_op;
4324 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4325 goto illegal_op;
4327 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4328 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4329 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4330 break;
4331 case 0x70: /* pshufx insn */
4332 case 0xc6: /* pshufx insn */
4333 val = cpu_ldub_code(env, s->pc++);
4334 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4335 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4336 /* XXX: introduce a new table? */
4337 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4338 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4339 break;
4340 case 0xc2:
4341 /* compare insns */
4342 val = cpu_ldub_code(env, s->pc++);
4343 if (val >= 8)
4344 goto unknown_op;
4345 sse_fn_epp = sse_op_table4[val][b1];
4347 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4348 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4349 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4350 break;
4351 case 0xf7:
4352 /* maskmov : we must prepare A0 */
4353 if (mod != 3)
4354 goto illegal_op;
4355 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4356 gen_extu(s->aflag, cpu_A0);
4357 gen_add_A0_ds_seg(s);
4359 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4360 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4361 /* XXX: introduce a new table? */
4362 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4363 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4364 break;
4365 default:
4366 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4367 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4368 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4369 break;
4371 if (b == 0x2e || b == 0x2f) {
4372 set_cc_op(s, CC_OP_EFLAGS);
4377 /* convert one instruction. s->is_jmp is set if the translation must
4378 be stopped. Return the next pc value */
4379 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4380 target_ulong pc_start)
4382 int b, prefixes;
4383 int shift;
4384 TCGMemOp ot, aflag, dflag;
4385 int modrm, reg, rm, mod, op, opreg, val;
4386 target_ulong next_eip, tval;
4387 int rex_w, rex_r;
4389 s->pc_start = s->pc = pc_start;
4390 prefixes = 0;
4391 s->override = -1;
4392 rex_w = -1;
4393 rex_r = 0;
4394 #ifdef TARGET_X86_64
4395 s->rex_x = 0;
4396 s->rex_b = 0;
4397 x86_64_hregs = 0;
4398 #endif
4399 s->rip_offset = 0; /* for relative ip address */
4400 s->vex_l = 0;
4401 s->vex_v = 0;
4402 next_byte:
4403 b = cpu_ldub_code(env, s->pc);
4404 s->pc++;
4405 /* Collect prefixes. */
4406 switch (b) {
4407 case 0xf3:
4408 prefixes |= PREFIX_REPZ;
4409 goto next_byte;
4410 case 0xf2:
4411 prefixes |= PREFIX_REPNZ;
4412 goto next_byte;
4413 case 0xf0:
4414 prefixes |= PREFIX_LOCK;
4415 goto next_byte;
4416 case 0x2e:
4417 s->override = R_CS;
4418 goto next_byte;
4419 case 0x36:
4420 s->override = R_SS;
4421 goto next_byte;
4422 case 0x3e:
4423 s->override = R_DS;
4424 goto next_byte;
4425 case 0x26:
4426 s->override = R_ES;
4427 goto next_byte;
4428 case 0x64:
4429 s->override = R_FS;
4430 goto next_byte;
4431 case 0x65:
4432 s->override = R_GS;
4433 goto next_byte;
4434 case 0x66:
4435 prefixes |= PREFIX_DATA;
4436 goto next_byte;
4437 case 0x67:
4438 prefixes |= PREFIX_ADR;
4439 goto next_byte;
4440 #ifdef TARGET_X86_64
4441 case 0x40 ... 0x4f:
4442 if (CODE64(s)) {
4443 /* REX prefix */
4444 rex_w = (b >> 3) & 1;
4445 rex_r = (b & 0x4) << 1;
4446 s->rex_x = (b & 0x2) << 2;
4447 REX_B(s) = (b & 0x1) << 3;
4448 x86_64_hregs = 1; /* select uniform byte register addressing */
4449 goto next_byte;
4451 break;
4452 #endif
4453 case 0xc5: /* 2-byte VEX */
4454 case 0xc4: /* 3-byte VEX */
4455 /* VEX prefixes cannot be used except in 32-bit mode.
4456 Otherwise the instruction is LES or LDS. */
4457 if (s->code32 && !s->vm86) {
4458 static const int pp_prefix[4] = {
4459 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4461 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4463 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4464 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4465 otherwise the instruction is LES or LDS. */
4466 break;
4468 s->pc++;
4470 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4471 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4472 | PREFIX_LOCK | PREFIX_DATA)) {
4473 goto illegal_op;
4475 #ifdef TARGET_X86_64
4476 if (x86_64_hregs) {
4477 goto illegal_op;
4479 #endif
4480 rex_r = (~vex2 >> 4) & 8;
4481 if (b == 0xc5) {
4482 vex3 = vex2;
4483 b = cpu_ldub_code(env, s->pc++);
4484 } else {
4485 #ifdef TARGET_X86_64
4486 s->rex_x = (~vex2 >> 3) & 8;
4487 s->rex_b = (~vex2 >> 2) & 8;
4488 #endif
4489 vex3 = cpu_ldub_code(env, s->pc++);
4490 rex_w = (vex3 >> 7) & 1;
4491 switch (vex2 & 0x1f) {
4492 case 0x01: /* Implied 0f leading opcode bytes. */
4493 b = cpu_ldub_code(env, s->pc++) | 0x100;
4494 break;
4495 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4496 b = 0x138;
4497 break;
4498 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4499 b = 0x13a;
4500 break;
4501 default: /* Reserved for future use. */
4502 goto unknown_op;
4505 s->vex_v = (~vex3 >> 3) & 0xf;
4506 s->vex_l = (vex3 >> 2) & 1;
4507 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4509 break;
4512 /* Post-process prefixes. */
4513 if (CODE64(s)) {
4514 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4515 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4516 over 0x66 if both are present. */
4517 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4518 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4519 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4520 } else {
4521 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4522 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4523 dflag = MO_32;
4524 } else {
4525 dflag = MO_16;
4527 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4528 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4529 aflag = MO_32;
4530 } else {
4531 aflag = MO_16;
4535 s->prefix = prefixes;
4536 s->aflag = aflag;
4537 s->dflag = dflag;
4539 /* now check op code */
4540 reswitch:
4541 switch(b) {
4542 case 0x0f:
4543 /**************************/
4544 /* extended op code */
4545 b = cpu_ldub_code(env, s->pc++) | 0x100;
4546 goto reswitch;
4548 /**************************/
4549 /* arith & logic */
4550 case 0x00 ... 0x05:
4551 case 0x08 ... 0x0d:
4552 case 0x10 ... 0x15:
4553 case 0x18 ... 0x1d:
4554 case 0x20 ... 0x25:
4555 case 0x28 ... 0x2d:
4556 case 0x30 ... 0x35:
4557 case 0x38 ... 0x3d:
4559 int op, f, val;
4560 op = (b >> 3) & 7;
4561 f = (b >> 1) & 3;
4563 ot = mo_b_d(b, dflag);
4565 switch(f) {
4566 case 0: /* OP Ev, Gv */
4567 modrm = cpu_ldub_code(env, s->pc++);
4568 reg = ((modrm >> 3) & 7) | rex_r;
4569 mod = (modrm >> 6) & 3;
4570 rm = (modrm & 7) | REX_B(s);
4571 if (mod != 3) {
4572 gen_lea_modrm(env, s, modrm);
4573 opreg = OR_TMP0;
4574 } else if (op == OP_XORL && rm == reg) {
4575 xor_zero:
4576 /* xor reg, reg optimisation */
4577 set_cc_op(s, CC_OP_CLR);
4578 tcg_gen_movi_tl(cpu_T0, 0);
4579 gen_op_mov_reg_v(ot, reg, cpu_T0);
4580 break;
4581 } else {
4582 opreg = rm;
4584 gen_op_mov_v_reg(ot, cpu_T1, reg);
4585 gen_op(s, op, ot, opreg);
4586 break;
4587 case 1: /* OP Gv, Ev */
4588 modrm = cpu_ldub_code(env, s->pc++);
4589 mod = (modrm >> 6) & 3;
4590 reg = ((modrm >> 3) & 7) | rex_r;
4591 rm = (modrm & 7) | REX_B(s);
4592 if (mod != 3) {
4593 gen_lea_modrm(env, s, modrm);
4594 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4595 } else if (op == OP_XORL && rm == reg) {
4596 goto xor_zero;
4597 } else {
4598 gen_op_mov_v_reg(ot, cpu_T1, rm);
4600 gen_op(s, op, ot, reg);
4601 break;
4602 case 2: /* OP A, Iv */
4603 val = insn_get(env, s, ot);
4604 tcg_gen_movi_tl(cpu_T1, val);
4605 gen_op(s, op, ot, OR_EAX);
4606 break;
4609 break;
4611 case 0x82:
4612 if (CODE64(s))
4613 goto illegal_op;
4614 case 0x80: /* GRP1 */
4615 case 0x81:
4616 case 0x83:
4618 int val;
4620 ot = mo_b_d(b, dflag);
4622 modrm = cpu_ldub_code(env, s->pc++);
4623 mod = (modrm >> 6) & 3;
4624 rm = (modrm & 7) | REX_B(s);
4625 op = (modrm >> 3) & 7;
4627 if (mod != 3) {
4628 if (b == 0x83)
4629 s->rip_offset = 1;
4630 else
4631 s->rip_offset = insn_const_size(ot);
4632 gen_lea_modrm(env, s, modrm);
4633 opreg = OR_TMP0;
4634 } else {
4635 opreg = rm;
4638 switch(b) {
4639 default:
4640 case 0x80:
4641 case 0x81:
4642 case 0x82:
4643 val = insn_get(env, s, ot);
4644 break;
4645 case 0x83:
4646 val = (int8_t)insn_get(env, s, MO_8);
4647 break;
4649 tcg_gen_movi_tl(cpu_T1, val);
4650 gen_op(s, op, ot, opreg);
4652 break;
4654 /**************************/
4655 /* inc, dec, and other misc arith */
4656 case 0x40 ... 0x47: /* inc Gv */
4657 ot = dflag;
4658 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4659 break;
4660 case 0x48 ... 0x4f: /* dec Gv */
4661 ot = dflag;
4662 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4663 break;
4664 case 0xf6: /* GRP3 */
4665 case 0xf7:
4666 ot = mo_b_d(b, dflag);
4668 modrm = cpu_ldub_code(env, s->pc++);
4669 mod = (modrm >> 6) & 3;
4670 rm = (modrm & 7) | REX_B(s);
4671 op = (modrm >> 3) & 7;
4672 if (mod != 3) {
4673 if (op == 0) {
4674 s->rip_offset = insn_const_size(ot);
4676 gen_lea_modrm(env, s, modrm);
4677 /* For those below that handle locked memory, don't load here. */
4678 if (!(s->prefix & PREFIX_LOCK)
4679 || op != 2) {
4680 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4682 } else {
4683 gen_op_mov_v_reg(ot, cpu_T0, rm);
4686 switch(op) {
4687 case 0: /* test */
4688 val = insn_get(env, s, ot);
4689 tcg_gen_movi_tl(cpu_T1, val);
4690 gen_op_testl_T0_T1_cc();
4691 set_cc_op(s, CC_OP_LOGICB + ot);
4692 break;
4693 case 2: /* not */
4694 if (s->prefix & PREFIX_LOCK) {
4695 if (mod == 3) {
4696 goto illegal_op;
4698 tcg_gen_movi_tl(cpu_T0, ~0);
4699 tcg_gen_atomic_xor_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
4700 s->mem_index, ot | MO_LE);
4701 } else {
4702 tcg_gen_not_tl(cpu_T0, cpu_T0);
4703 if (mod != 3) {
4704 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4705 } else {
4706 gen_op_mov_reg_v(ot, rm, cpu_T0);
4709 break;
4710 case 3: /* neg */
4711 if (s->prefix & PREFIX_LOCK) {
4712 TCGLabel *label1;
4713 TCGv a0, t0, t1, t2;
4715 if (mod == 3) {
4716 goto illegal_op;
4718 a0 = tcg_temp_local_new();
4719 t0 = tcg_temp_local_new();
4720 label1 = gen_new_label();
4722 tcg_gen_mov_tl(a0, cpu_A0);
4723 tcg_gen_mov_tl(t0, cpu_T0);
4725 gen_set_label(label1);
4726 t1 = tcg_temp_new();
4727 t2 = tcg_temp_new();
4728 tcg_gen_mov_tl(t2, t0);
4729 tcg_gen_neg_tl(t1, t0);
4730 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4731 s->mem_index, ot | MO_LE);
4732 tcg_temp_free(t1);
4733 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4735 tcg_temp_free(t2);
4736 tcg_temp_free(a0);
4737 tcg_gen_mov_tl(cpu_T0, t0);
4738 tcg_temp_free(t0);
4739 } else {
4740 tcg_gen_neg_tl(cpu_T0, cpu_T0);
4741 if (mod != 3) {
4742 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4743 } else {
4744 gen_op_mov_reg_v(ot, rm, cpu_T0);
4747 gen_op_update_neg_cc();
4748 set_cc_op(s, CC_OP_SUBB + ot);
4749 break;
4750 case 4: /* mul */
4751 switch(ot) {
4752 case MO_8:
4753 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4754 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
4755 tcg_gen_ext8u_tl(cpu_T1, cpu_T1);
4756 /* XXX: use 32 bit mul which could be faster */
4757 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4758 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4759 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4760 tcg_gen_andi_tl(cpu_cc_src, cpu_T0, 0xff00);
4761 set_cc_op(s, CC_OP_MULB);
4762 break;
4763 case MO_16:
4764 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4765 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4766 tcg_gen_ext16u_tl(cpu_T1, cpu_T1);
4767 /* XXX: use 32 bit mul which could be faster */
4768 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4769 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4770 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4771 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4772 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4773 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4774 set_cc_op(s, CC_OP_MULW);
4775 break;
4776 default:
4777 case MO_32:
4778 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4779 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4780 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4781 cpu_tmp2_i32, cpu_tmp3_i32);
4782 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4783 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4784 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4785 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4786 set_cc_op(s, CC_OP_MULL);
4787 break;
4788 #ifdef TARGET_X86_64
4789 case MO_64:
4790 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4791 cpu_T0, cpu_regs[R_EAX]);
4792 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4793 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4794 set_cc_op(s, CC_OP_MULQ);
4795 break;
4796 #endif
4798 break;
4799 case 5: /* imul */
4800 switch(ot) {
4801 case MO_8:
4802 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4803 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
4804 tcg_gen_ext8s_tl(cpu_T1, cpu_T1);
4805 /* XXX: use 32 bit mul which could be faster */
4806 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4807 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4808 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4809 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T0);
4810 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4811 set_cc_op(s, CC_OP_MULB);
4812 break;
4813 case MO_16:
4814 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4815 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4816 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
4817 /* XXX: use 32 bit mul which could be faster */
4818 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4819 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4820 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4821 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
4822 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4823 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4824 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4825 set_cc_op(s, CC_OP_MULW);
4826 break;
4827 default:
4828 case MO_32:
4829 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4830 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4831 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4832 cpu_tmp2_i32, cpu_tmp3_i32);
4833 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4834 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4835 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4836 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4837 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4838 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4839 set_cc_op(s, CC_OP_MULL);
4840 break;
4841 #ifdef TARGET_X86_64
4842 case MO_64:
4843 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4844 cpu_T0, cpu_regs[R_EAX]);
4845 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4846 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4847 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4848 set_cc_op(s, CC_OP_MULQ);
4849 break;
4850 #endif
4852 break;
4853 case 6: /* div */
4854 switch(ot) {
4855 case MO_8:
4856 gen_helper_divb_AL(cpu_env, cpu_T0);
4857 break;
4858 case MO_16:
4859 gen_helper_divw_AX(cpu_env, cpu_T0);
4860 break;
4861 default:
4862 case MO_32:
4863 gen_helper_divl_EAX(cpu_env, cpu_T0);
4864 break;
4865 #ifdef TARGET_X86_64
4866 case MO_64:
4867 gen_helper_divq_EAX(cpu_env, cpu_T0);
4868 break;
4869 #endif
4871 break;
4872 case 7: /* idiv */
4873 switch(ot) {
4874 case MO_8:
4875 gen_helper_idivb_AL(cpu_env, cpu_T0);
4876 break;
4877 case MO_16:
4878 gen_helper_idivw_AX(cpu_env, cpu_T0);
4879 break;
4880 default:
4881 case MO_32:
4882 gen_helper_idivl_EAX(cpu_env, cpu_T0);
4883 break;
4884 #ifdef TARGET_X86_64
4885 case MO_64:
4886 gen_helper_idivq_EAX(cpu_env, cpu_T0);
4887 break;
4888 #endif
4890 break;
4891 default:
4892 goto unknown_op;
4894 break;
4896 case 0xfe: /* GRP4 */
4897 case 0xff: /* GRP5 */
4898 ot = mo_b_d(b, dflag);
4900 modrm = cpu_ldub_code(env, s->pc++);
4901 mod = (modrm >> 6) & 3;
4902 rm = (modrm & 7) | REX_B(s);
4903 op = (modrm >> 3) & 7;
4904 if (op >= 2 && b == 0xfe) {
4905 goto unknown_op;
4907 if (CODE64(s)) {
4908 if (op == 2 || op == 4) {
4909 /* operand size for jumps is 64 bit */
4910 ot = MO_64;
4911 } else if (op == 3 || op == 5) {
4912 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
4913 } else if (op == 6) {
4914 /* default push size is 64 bit */
4915 ot = mo_pushpop(s, dflag);
4918 if (mod != 3) {
4919 gen_lea_modrm(env, s, modrm);
4920 if (op >= 2 && op != 3 && op != 5)
4921 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4922 } else {
4923 gen_op_mov_v_reg(ot, cpu_T0, rm);
4926 switch(op) {
4927 case 0: /* inc Ev */
4928 if (mod != 3)
4929 opreg = OR_TMP0;
4930 else
4931 opreg = rm;
4932 gen_inc(s, ot, opreg, 1);
4933 break;
4934 case 1: /* dec Ev */
4935 if (mod != 3)
4936 opreg = OR_TMP0;
4937 else
4938 opreg = rm;
4939 gen_inc(s, ot, opreg, -1);
4940 break;
4941 case 2: /* call Ev */
4942 /* XXX: optimize if memory (no 'and' is necessary) */
4943 if (dflag == MO_16) {
4944 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4946 next_eip = s->pc - s->cs_base;
4947 tcg_gen_movi_tl(cpu_T1, next_eip);
4948 gen_push_v(s, cpu_T1);
4949 gen_op_jmp_v(cpu_T0);
4950 gen_bnd_jmp(s);
4951 gen_eob(s);
4952 break;
4953 case 3: /* lcall Ev */
4954 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4955 gen_add_A0_im(s, 1 << ot);
4956 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
4957 do_lcall:
4958 if (s->pe && !s->vm86) {
4959 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4960 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
4961 tcg_const_i32(dflag - 1),
4962 tcg_const_tl(s->pc - s->cs_base));
4963 } else {
4964 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4965 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T1,
4966 tcg_const_i32(dflag - 1),
4967 tcg_const_i32(s->pc - s->cs_base));
4969 gen_eob(s);
4970 break;
4971 case 4: /* jmp Ev */
4972 if (dflag == MO_16) {
4973 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4975 gen_op_jmp_v(cpu_T0);
4976 gen_bnd_jmp(s);
4977 gen_eob(s);
4978 break;
4979 case 5: /* ljmp Ev */
4980 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4981 gen_add_A0_im(s, 1 << ot);
4982 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
4983 do_ljmp:
4984 if (s->pe && !s->vm86) {
4985 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4986 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
4987 tcg_const_tl(s->pc - s->cs_base));
4988 } else {
4989 gen_op_movl_seg_T0_vm(R_CS);
4990 gen_op_jmp_v(cpu_T1);
4992 gen_eob(s);
4993 break;
4994 case 6: /* push Ev */
4995 gen_push_v(s, cpu_T0);
4996 break;
4997 default:
4998 goto unknown_op;
5000 break;
5002 case 0x84: /* test Ev, Gv */
5003 case 0x85:
5004 ot = mo_b_d(b, dflag);
5006 modrm = cpu_ldub_code(env, s->pc++);
5007 reg = ((modrm >> 3) & 7) | rex_r;
5009 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5010 gen_op_mov_v_reg(ot, cpu_T1, reg);
5011 gen_op_testl_T0_T1_cc();
5012 set_cc_op(s, CC_OP_LOGICB + ot);
5013 break;
5015 case 0xa8: /* test eAX, Iv */
5016 case 0xa9:
5017 ot = mo_b_d(b, dflag);
5018 val = insn_get(env, s, ot);
5020 gen_op_mov_v_reg(ot, cpu_T0, OR_EAX);
5021 tcg_gen_movi_tl(cpu_T1, val);
5022 gen_op_testl_T0_T1_cc();
5023 set_cc_op(s, CC_OP_LOGICB + ot);
5024 break;
5026 case 0x98: /* CWDE/CBW */
5027 switch (dflag) {
5028 #ifdef TARGET_X86_64
5029 case MO_64:
5030 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
5031 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
5032 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T0);
5033 break;
5034 #endif
5035 case MO_32:
5036 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
5037 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5038 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T0);
5039 break;
5040 case MO_16:
5041 gen_op_mov_v_reg(MO_8, cpu_T0, R_EAX);
5042 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
5043 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
5044 break;
5045 default:
5046 tcg_abort();
5048 break;
5049 case 0x99: /* CDQ/CWD */
5050 switch (dflag) {
5051 #ifdef TARGET_X86_64
5052 case MO_64:
5053 gen_op_mov_v_reg(MO_64, cpu_T0, R_EAX);
5054 tcg_gen_sari_tl(cpu_T0, cpu_T0, 63);
5055 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T0);
5056 break;
5057 #endif
5058 case MO_32:
5059 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
5060 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
5061 tcg_gen_sari_tl(cpu_T0, cpu_T0, 31);
5062 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T0);
5063 break;
5064 case MO_16:
5065 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
5066 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5067 tcg_gen_sari_tl(cpu_T0, cpu_T0, 15);
5068 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
5069 break;
5070 default:
5071 tcg_abort();
5073 break;
5074 case 0x1af: /* imul Gv, Ev */
5075 case 0x69: /* imul Gv, Ev, I */
5076 case 0x6b:
5077 ot = dflag;
5078 modrm = cpu_ldub_code(env, s->pc++);
5079 reg = ((modrm >> 3) & 7) | rex_r;
5080 if (b == 0x69)
5081 s->rip_offset = insn_const_size(ot);
5082 else if (b == 0x6b)
5083 s->rip_offset = 1;
5084 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5085 if (b == 0x69) {
5086 val = insn_get(env, s, ot);
5087 tcg_gen_movi_tl(cpu_T1, val);
5088 } else if (b == 0x6b) {
5089 val = (int8_t)insn_get(env, s, MO_8);
5090 tcg_gen_movi_tl(cpu_T1, val);
5091 } else {
5092 gen_op_mov_v_reg(ot, cpu_T1, reg);
5094 switch (ot) {
5095 #ifdef TARGET_X86_64
5096 case MO_64:
5097 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T1, cpu_T0, cpu_T1);
5098 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5099 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5100 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T1);
5101 break;
5102 #endif
5103 case MO_32:
5104 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
5105 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
5106 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5107 cpu_tmp2_i32, cpu_tmp3_i32);
5108 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5109 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5110 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5111 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5112 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5113 break;
5114 default:
5115 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5116 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
5117 /* XXX: use 32 bit mul which could be faster */
5118 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
5119 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
5120 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
5121 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
5122 gen_op_mov_reg_v(ot, reg, cpu_T0);
5123 break;
5125 set_cc_op(s, CC_OP_MULB + ot);
5126 break;
5127 case 0x1c0:
5128 case 0x1c1: /* xadd Ev, Gv */
5129 ot = mo_b_d(b, dflag);
5130 modrm = cpu_ldub_code(env, s->pc++);
5131 reg = ((modrm >> 3) & 7) | rex_r;
5132 mod = (modrm >> 6) & 3;
5133 gen_op_mov_v_reg(ot, cpu_T0, reg);
5134 if (mod == 3) {
5135 rm = (modrm & 7) | REX_B(s);
5136 gen_op_mov_v_reg(ot, cpu_T1, rm);
5137 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5138 gen_op_mov_reg_v(ot, reg, cpu_T1);
5139 gen_op_mov_reg_v(ot, rm, cpu_T0);
5140 } else {
5141 gen_lea_modrm(env, s, modrm);
5142 if (s->prefix & PREFIX_LOCK) {
5143 tcg_gen_atomic_fetch_add_tl(cpu_T1, cpu_A0, cpu_T0,
5144 s->mem_index, ot | MO_LE);
5145 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5146 } else {
5147 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5148 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5149 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5151 gen_op_mov_reg_v(ot, reg, cpu_T1);
5153 gen_op_update2_cc();
5154 set_cc_op(s, CC_OP_ADDB + ot);
5155 break;
5156 case 0x1b0:
5157 case 0x1b1: /* cmpxchg Ev, Gv */
5159 TCGv oldv, newv, cmpv;
5161 ot = mo_b_d(b, dflag);
5162 modrm = cpu_ldub_code(env, s->pc++);
5163 reg = ((modrm >> 3) & 7) | rex_r;
5164 mod = (modrm >> 6) & 3;
5165 oldv = tcg_temp_new();
5166 newv = tcg_temp_new();
5167 cmpv = tcg_temp_new();
5168 gen_op_mov_v_reg(ot, newv, reg);
5169 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5171 if (s->prefix & PREFIX_LOCK) {
5172 if (mod == 3) {
5173 goto illegal_op;
5175 gen_lea_modrm(env, s, modrm);
5176 tcg_gen_atomic_cmpxchg_tl(oldv, cpu_A0, cmpv, newv,
5177 s->mem_index, ot | MO_LE);
5178 gen_op_mov_reg_v(ot, R_EAX, oldv);
5179 } else {
5180 if (mod == 3) {
5181 rm = (modrm & 7) | REX_B(s);
5182 gen_op_mov_v_reg(ot, oldv, rm);
5183 } else {
5184 gen_lea_modrm(env, s, modrm);
5185 gen_op_ld_v(s, ot, oldv, cpu_A0);
5186 rm = 0; /* avoid warning */
5188 gen_extu(ot, oldv);
5189 gen_extu(ot, cmpv);
5190 /* store value = (old == cmp ? new : old); */
5191 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5192 if (mod == 3) {
5193 gen_op_mov_reg_v(ot, R_EAX, oldv);
5194 gen_op_mov_reg_v(ot, rm, newv);
5195 } else {
5196 /* Perform an unconditional store cycle like physical cpu;
5197 must be before changing accumulator to ensure
5198 idempotency if the store faults and the instruction
5199 is restarted */
5200 gen_op_st_v(s, ot, newv, cpu_A0);
5201 gen_op_mov_reg_v(ot, R_EAX, oldv);
5204 tcg_gen_mov_tl(cpu_cc_src, oldv);
5205 tcg_gen_mov_tl(cpu_cc_srcT, cmpv);
5206 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5207 set_cc_op(s, CC_OP_SUBB + ot);
5208 tcg_temp_free(oldv);
5209 tcg_temp_free(newv);
5210 tcg_temp_free(cmpv);
5212 break;
5213 case 0x1c7: /* cmpxchg8b */
5214 modrm = cpu_ldub_code(env, s->pc++);
5215 mod = (modrm >> 6) & 3;
5216 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5217 goto illegal_op;
5218 #ifdef TARGET_X86_64
5219 if (dflag == MO_64) {
5220 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5221 goto illegal_op;
5222 gen_lea_modrm(env, s, modrm);
5223 if ((s->prefix & PREFIX_LOCK) && parallel_cpus) {
5224 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5225 } else {
5226 gen_helper_cmpxchg16b_unlocked(cpu_env, cpu_A0);
5228 } else
5229 #endif
5231 if (!(s->cpuid_features & CPUID_CX8))
5232 goto illegal_op;
5233 gen_lea_modrm(env, s, modrm);
5234 if ((s->prefix & PREFIX_LOCK) && parallel_cpus) {
5235 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5236 } else {
5237 gen_helper_cmpxchg8b_unlocked(cpu_env, cpu_A0);
5240 set_cc_op(s, CC_OP_EFLAGS);
5241 break;
5243 /**************************/
5244 /* push/pop */
5245 case 0x50 ... 0x57: /* push */
5246 gen_op_mov_v_reg(MO_32, cpu_T0, (b & 7) | REX_B(s));
5247 gen_push_v(s, cpu_T0);
5248 break;
5249 case 0x58 ... 0x5f: /* pop */
5250 ot = gen_pop_T0(s);
5251 /* NOTE: order is important for pop %sp */
5252 gen_pop_update(s, ot);
5253 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T0);
5254 break;
5255 case 0x60: /* pusha */
5256 if (CODE64(s))
5257 goto illegal_op;
5258 gen_pusha(s);
5259 break;
5260 case 0x61: /* popa */
5261 if (CODE64(s))
5262 goto illegal_op;
5263 gen_popa(s);
5264 break;
5265 case 0x68: /* push Iv */
5266 case 0x6a:
5267 ot = mo_pushpop(s, dflag);
5268 if (b == 0x68)
5269 val = insn_get(env, s, ot);
5270 else
5271 val = (int8_t)insn_get(env, s, MO_8);
5272 tcg_gen_movi_tl(cpu_T0, val);
5273 gen_push_v(s, cpu_T0);
5274 break;
5275 case 0x8f: /* pop Ev */
5276 modrm = cpu_ldub_code(env, s->pc++);
5277 mod = (modrm >> 6) & 3;
5278 ot = gen_pop_T0(s);
5279 if (mod == 3) {
5280 /* NOTE: order is important for pop %sp */
5281 gen_pop_update(s, ot);
5282 rm = (modrm & 7) | REX_B(s);
5283 gen_op_mov_reg_v(ot, rm, cpu_T0);
5284 } else {
5285 /* NOTE: order is important too for MMU exceptions */
5286 s->popl_esp_hack = 1 << ot;
5287 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5288 s->popl_esp_hack = 0;
5289 gen_pop_update(s, ot);
5291 break;
5292 case 0xc8: /* enter */
5294 int level;
5295 val = cpu_lduw_code(env, s->pc);
5296 s->pc += 2;
5297 level = cpu_ldub_code(env, s->pc++);
5298 gen_enter(s, val, level);
5300 break;
5301 case 0xc9: /* leave */
5302 gen_leave(s);
5303 break;
5304 case 0x06: /* push es */
5305 case 0x0e: /* push cs */
5306 case 0x16: /* push ss */
5307 case 0x1e: /* push ds */
5308 if (CODE64(s))
5309 goto illegal_op;
5310 gen_op_movl_T0_seg(b >> 3);
5311 gen_push_v(s, cpu_T0);
5312 break;
5313 case 0x1a0: /* push fs */
5314 case 0x1a8: /* push gs */
5315 gen_op_movl_T0_seg((b >> 3) & 7);
5316 gen_push_v(s, cpu_T0);
5317 break;
5318 case 0x07: /* pop es */
5319 case 0x17: /* pop ss */
5320 case 0x1f: /* pop ds */
5321 if (CODE64(s))
5322 goto illegal_op;
5323 reg = b >> 3;
5324 ot = gen_pop_T0(s);
5325 gen_movl_seg_T0(s, reg);
5326 gen_pop_update(s, ot);
5327 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5328 if (s->is_jmp) {
5329 gen_jmp_im(s->pc - s->cs_base);
5330 if (reg == R_SS) {
5331 s->tf = 0;
5332 gen_eob_inhibit_irq(s, true);
5333 } else {
5334 gen_eob(s);
5337 break;
5338 case 0x1a1: /* pop fs */
5339 case 0x1a9: /* pop gs */
5340 ot = gen_pop_T0(s);
5341 gen_movl_seg_T0(s, (b >> 3) & 7);
5342 gen_pop_update(s, ot);
5343 if (s->is_jmp) {
5344 gen_jmp_im(s->pc - s->cs_base);
5345 gen_eob(s);
5347 break;
5349 /**************************/
5350 /* mov */
5351 case 0x88:
5352 case 0x89: /* mov Gv, Ev */
5353 ot = mo_b_d(b, dflag);
5354 modrm = cpu_ldub_code(env, s->pc++);
5355 reg = ((modrm >> 3) & 7) | rex_r;
5357 /* generate a generic store */
5358 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5359 break;
5360 case 0xc6:
5361 case 0xc7: /* mov Ev, Iv */
5362 ot = mo_b_d(b, dflag);
5363 modrm = cpu_ldub_code(env, s->pc++);
5364 mod = (modrm >> 6) & 3;
5365 if (mod != 3) {
5366 s->rip_offset = insn_const_size(ot);
5367 gen_lea_modrm(env, s, modrm);
5369 val = insn_get(env, s, ot);
5370 tcg_gen_movi_tl(cpu_T0, val);
5371 if (mod != 3) {
5372 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5373 } else {
5374 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T0);
5376 break;
5377 case 0x8a:
5378 case 0x8b: /* mov Ev, Gv */
5379 ot = mo_b_d(b, dflag);
5380 modrm = cpu_ldub_code(env, s->pc++);
5381 reg = ((modrm >> 3) & 7) | rex_r;
5383 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5384 gen_op_mov_reg_v(ot, reg, cpu_T0);
5385 break;
5386 case 0x8e: /* mov seg, Gv */
5387 modrm = cpu_ldub_code(env, s->pc++);
5388 reg = (modrm >> 3) & 7;
5389 if (reg >= 6 || reg == R_CS)
5390 goto illegal_op;
5391 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5392 gen_movl_seg_T0(s, reg);
5393 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5394 if (s->is_jmp) {
5395 gen_jmp_im(s->pc - s->cs_base);
5396 if (reg == R_SS) {
5397 s->tf = 0;
5398 gen_eob_inhibit_irq(s, true);
5399 } else {
5400 gen_eob(s);
5403 break;
5404 case 0x8c: /* mov Gv, seg */
5405 modrm = cpu_ldub_code(env, s->pc++);
5406 reg = (modrm >> 3) & 7;
5407 mod = (modrm >> 6) & 3;
5408 if (reg >= 6)
5409 goto illegal_op;
5410 gen_op_movl_T0_seg(reg);
5411 ot = mod == 3 ? dflag : MO_16;
5412 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5413 break;
5415 case 0x1b6: /* movzbS Gv, Eb */
5416 case 0x1b7: /* movzwS Gv, Eb */
5417 case 0x1be: /* movsbS Gv, Eb */
5418 case 0x1bf: /* movswS Gv, Eb */
5420 TCGMemOp d_ot;
5421 TCGMemOp s_ot;
5423 /* d_ot is the size of destination */
5424 d_ot = dflag;
5425 /* ot is the size of source */
5426 ot = (b & 1) + MO_8;
5427 /* s_ot is the sign+size of source */
5428 s_ot = b & 8 ? MO_SIGN | ot : ot;
5430 modrm = cpu_ldub_code(env, s->pc++);
5431 reg = ((modrm >> 3) & 7) | rex_r;
5432 mod = (modrm >> 6) & 3;
5433 rm = (modrm & 7) | REX_B(s);
5435 if (mod == 3) {
5436 gen_op_mov_v_reg(ot, cpu_T0, rm);
5437 switch (s_ot) {
5438 case MO_UB:
5439 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
5440 break;
5441 case MO_SB:
5442 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
5443 break;
5444 case MO_UW:
5445 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
5446 break;
5447 default:
5448 case MO_SW:
5449 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5450 break;
5452 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5453 } else {
5454 gen_lea_modrm(env, s, modrm);
5455 gen_op_ld_v(s, s_ot, cpu_T0, cpu_A0);
5456 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5459 break;
5461 case 0x8d: /* lea */
5462 modrm = cpu_ldub_code(env, s->pc++);
5463 mod = (modrm >> 6) & 3;
5464 if (mod == 3)
5465 goto illegal_op;
5466 reg = ((modrm >> 3) & 7) | rex_r;
5468 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5469 TCGv ea = gen_lea_modrm_1(a);
5470 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5471 gen_op_mov_reg_v(dflag, reg, cpu_A0);
5473 break;
5475 case 0xa0: /* mov EAX, Ov */
5476 case 0xa1:
5477 case 0xa2: /* mov Ov, EAX */
5478 case 0xa3:
5480 target_ulong offset_addr;
5482 ot = mo_b_d(b, dflag);
5483 switch (s->aflag) {
5484 #ifdef TARGET_X86_64
5485 case MO_64:
5486 offset_addr = cpu_ldq_code(env, s->pc);
5487 s->pc += 8;
5488 break;
5489 #endif
5490 default:
5491 offset_addr = insn_get(env, s, s->aflag);
5492 break;
5494 tcg_gen_movi_tl(cpu_A0, offset_addr);
5495 gen_add_A0_ds_seg(s);
5496 if ((b & 2) == 0) {
5497 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
5498 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
5499 } else {
5500 gen_op_mov_v_reg(ot, cpu_T0, R_EAX);
5501 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5504 break;
5505 case 0xd7: /* xlat */
5506 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5507 tcg_gen_ext8u_tl(cpu_T0, cpu_regs[R_EAX]);
5508 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T0);
5509 gen_extu(s->aflag, cpu_A0);
5510 gen_add_A0_ds_seg(s);
5511 gen_op_ld_v(s, MO_8, cpu_T0, cpu_A0);
5512 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
5513 break;
5514 case 0xb0 ... 0xb7: /* mov R, Ib */
5515 val = insn_get(env, s, MO_8);
5516 tcg_gen_movi_tl(cpu_T0, val);
5517 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T0);
5518 break;
5519 case 0xb8 ... 0xbf: /* mov R, Iv */
5520 #ifdef TARGET_X86_64
5521 if (dflag == MO_64) {
5522 uint64_t tmp;
5523 /* 64 bit case */
5524 tmp = cpu_ldq_code(env, s->pc);
5525 s->pc += 8;
5526 reg = (b & 7) | REX_B(s);
5527 tcg_gen_movi_tl(cpu_T0, tmp);
5528 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
5529 } else
5530 #endif
5532 ot = dflag;
5533 val = insn_get(env, s, ot);
5534 reg = (b & 7) | REX_B(s);
5535 tcg_gen_movi_tl(cpu_T0, val);
5536 gen_op_mov_reg_v(ot, reg, cpu_T0);
5538 break;
5540 case 0x91 ... 0x97: /* xchg R, EAX */
5541 do_xchg_reg_eax:
5542 ot = dflag;
5543 reg = (b & 7) | REX_B(s);
5544 rm = R_EAX;
5545 goto do_xchg_reg;
5546 case 0x86:
5547 case 0x87: /* xchg Ev, Gv */
5548 ot = mo_b_d(b, dflag);
5549 modrm = cpu_ldub_code(env, s->pc++);
5550 reg = ((modrm >> 3) & 7) | rex_r;
5551 mod = (modrm >> 6) & 3;
5552 if (mod == 3) {
5553 rm = (modrm & 7) | REX_B(s);
5554 do_xchg_reg:
5555 gen_op_mov_v_reg(ot, cpu_T0, reg);
5556 gen_op_mov_v_reg(ot, cpu_T1, rm);
5557 gen_op_mov_reg_v(ot, rm, cpu_T0);
5558 gen_op_mov_reg_v(ot, reg, cpu_T1);
5559 } else {
5560 gen_lea_modrm(env, s, modrm);
5561 gen_op_mov_v_reg(ot, cpu_T0, reg);
5562 /* for xchg, lock is implicit */
5563 tcg_gen_atomic_xchg_tl(cpu_T1, cpu_A0, cpu_T0,
5564 s->mem_index, ot | MO_LE);
5565 gen_op_mov_reg_v(ot, reg, cpu_T1);
5567 break;
5568 case 0xc4: /* les Gv */
5569 /* In CODE64 this is VEX3; see above. */
5570 op = R_ES;
5571 goto do_lxx;
5572 case 0xc5: /* lds Gv */
5573 /* In CODE64 this is VEX2; see above. */
5574 op = R_DS;
5575 goto do_lxx;
5576 case 0x1b2: /* lss Gv */
5577 op = R_SS;
5578 goto do_lxx;
5579 case 0x1b4: /* lfs Gv */
5580 op = R_FS;
5581 goto do_lxx;
5582 case 0x1b5: /* lgs Gv */
5583 op = R_GS;
5584 do_lxx:
5585 ot = dflag != MO_16 ? MO_32 : MO_16;
5586 modrm = cpu_ldub_code(env, s->pc++);
5587 reg = ((modrm >> 3) & 7) | rex_r;
5588 mod = (modrm >> 6) & 3;
5589 if (mod == 3)
5590 goto illegal_op;
5591 gen_lea_modrm(env, s, modrm);
5592 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5593 gen_add_A0_im(s, 1 << ot);
5594 /* load the segment first to handle exceptions properly */
5595 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
5596 gen_movl_seg_T0(s, op);
5597 /* then put the data */
5598 gen_op_mov_reg_v(ot, reg, cpu_T1);
5599 if (s->is_jmp) {
5600 gen_jmp_im(s->pc - s->cs_base);
5601 gen_eob(s);
5603 break;
5605 /************************/
5606 /* shifts */
5607 case 0xc0:
5608 case 0xc1:
5609 /* shift Ev,Ib */
5610 shift = 2;
5611 grp2:
5613 ot = mo_b_d(b, dflag);
5614 modrm = cpu_ldub_code(env, s->pc++);
5615 mod = (modrm >> 6) & 3;
5616 op = (modrm >> 3) & 7;
5618 if (mod != 3) {
5619 if (shift == 2) {
5620 s->rip_offset = 1;
5622 gen_lea_modrm(env, s, modrm);
5623 opreg = OR_TMP0;
5624 } else {
5625 opreg = (modrm & 7) | REX_B(s);
5628 /* simpler op */
5629 if (shift == 0) {
5630 gen_shift(s, op, ot, opreg, OR_ECX);
5631 } else {
5632 if (shift == 2) {
5633 shift = cpu_ldub_code(env, s->pc++);
5635 gen_shifti(s, op, ot, opreg, shift);
5638 break;
5639 case 0xd0:
5640 case 0xd1:
5641 /* shift Ev,1 */
5642 shift = 1;
5643 goto grp2;
5644 case 0xd2:
5645 case 0xd3:
5646 /* shift Ev,cl */
5647 shift = 0;
5648 goto grp2;
5650 case 0x1a4: /* shld imm */
5651 op = 0;
5652 shift = 1;
5653 goto do_shiftd;
5654 case 0x1a5: /* shld cl */
5655 op = 0;
5656 shift = 0;
5657 goto do_shiftd;
5658 case 0x1ac: /* shrd imm */
5659 op = 1;
5660 shift = 1;
5661 goto do_shiftd;
5662 case 0x1ad: /* shrd cl */
5663 op = 1;
5664 shift = 0;
5665 do_shiftd:
5666 ot = dflag;
5667 modrm = cpu_ldub_code(env, s->pc++);
5668 mod = (modrm >> 6) & 3;
5669 rm = (modrm & 7) | REX_B(s);
5670 reg = ((modrm >> 3) & 7) | rex_r;
5671 if (mod != 3) {
5672 gen_lea_modrm(env, s, modrm);
5673 opreg = OR_TMP0;
5674 } else {
5675 opreg = rm;
5677 gen_op_mov_v_reg(ot, cpu_T1, reg);
5679 if (shift) {
5680 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5681 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5682 tcg_temp_free(imm);
5683 } else {
5684 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5686 break;
5688 /************************/
5689 /* floats */
5690 case 0xd8 ... 0xdf:
5691 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5692 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5693 /* XXX: what to do if illegal op ? */
5694 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5695 break;
5697 modrm = cpu_ldub_code(env, s->pc++);
5698 mod = (modrm >> 6) & 3;
5699 rm = modrm & 7;
5700 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5701 if (mod != 3) {
5702 /* memory op */
5703 gen_lea_modrm(env, s, modrm);
5704 switch(op) {
5705 case 0x00 ... 0x07: /* fxxxs */
5706 case 0x10 ... 0x17: /* fixxxl */
5707 case 0x20 ... 0x27: /* fxxxl */
5708 case 0x30 ... 0x37: /* fixxx */
5710 int op1;
5711 op1 = op & 7;
5713 switch(op >> 4) {
5714 case 0:
5715 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5716 s->mem_index, MO_LEUL);
5717 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5718 break;
5719 case 1:
5720 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5721 s->mem_index, MO_LEUL);
5722 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5723 break;
5724 case 2:
5725 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5726 s->mem_index, MO_LEQ);
5727 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5728 break;
5729 case 3:
5730 default:
5731 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5732 s->mem_index, MO_LESW);
5733 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5734 break;
5737 gen_helper_fp_arith_ST0_FT0(op1);
5738 if (op1 == 3) {
5739 /* fcomp needs pop */
5740 gen_helper_fpop(cpu_env);
5743 break;
5744 case 0x08: /* flds */
5745 case 0x0a: /* fsts */
5746 case 0x0b: /* fstps */
5747 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5748 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5749 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5750 switch(op & 7) {
5751 case 0:
5752 switch(op >> 4) {
5753 case 0:
5754 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5755 s->mem_index, MO_LEUL);
5756 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5757 break;
5758 case 1:
5759 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5760 s->mem_index, MO_LEUL);
5761 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5762 break;
5763 case 2:
5764 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5765 s->mem_index, MO_LEQ);
5766 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5767 break;
5768 case 3:
5769 default:
5770 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5771 s->mem_index, MO_LESW);
5772 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5773 break;
5775 break;
5776 case 1:
5777 /* XXX: the corresponding CPUID bit must be tested ! */
5778 switch(op >> 4) {
5779 case 1:
5780 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5781 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5782 s->mem_index, MO_LEUL);
5783 break;
5784 case 2:
5785 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5786 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5787 s->mem_index, MO_LEQ);
5788 break;
5789 case 3:
5790 default:
5791 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5792 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5793 s->mem_index, MO_LEUW);
5794 break;
5796 gen_helper_fpop(cpu_env);
5797 break;
5798 default:
5799 switch(op >> 4) {
5800 case 0:
5801 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5802 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5803 s->mem_index, MO_LEUL);
5804 break;
5805 case 1:
5806 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5807 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5808 s->mem_index, MO_LEUL);
5809 break;
5810 case 2:
5811 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5812 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5813 s->mem_index, MO_LEQ);
5814 break;
5815 case 3:
5816 default:
5817 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5818 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5819 s->mem_index, MO_LEUW);
5820 break;
5822 if ((op & 7) == 3)
5823 gen_helper_fpop(cpu_env);
5824 break;
5826 break;
5827 case 0x0c: /* fldenv mem */
5828 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5829 break;
5830 case 0x0d: /* fldcw mem */
5831 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5832 s->mem_index, MO_LEUW);
5833 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5834 break;
5835 case 0x0e: /* fnstenv mem */
5836 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5837 break;
5838 case 0x0f: /* fnstcw mem */
5839 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5840 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5841 s->mem_index, MO_LEUW);
5842 break;
5843 case 0x1d: /* fldt mem */
5844 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5845 break;
5846 case 0x1f: /* fstpt mem */
5847 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5848 gen_helper_fpop(cpu_env);
5849 break;
5850 case 0x2c: /* frstor mem */
5851 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5852 break;
5853 case 0x2e: /* fnsave mem */
5854 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5855 break;
5856 case 0x2f: /* fnstsw mem */
5857 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5858 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5859 s->mem_index, MO_LEUW);
5860 break;
5861 case 0x3c: /* fbld */
5862 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5863 break;
5864 case 0x3e: /* fbstp */
5865 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5866 gen_helper_fpop(cpu_env);
5867 break;
5868 case 0x3d: /* fildll */
5869 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5870 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5871 break;
5872 case 0x3f: /* fistpll */
5873 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5874 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5875 gen_helper_fpop(cpu_env);
5876 break;
5877 default:
5878 goto unknown_op;
5880 } else {
5881 /* register float ops */
5882 opreg = rm;
5884 switch(op) {
5885 case 0x08: /* fld sti */
5886 gen_helper_fpush(cpu_env);
5887 gen_helper_fmov_ST0_STN(cpu_env,
5888 tcg_const_i32((opreg + 1) & 7));
5889 break;
5890 case 0x09: /* fxchg sti */
5891 case 0x29: /* fxchg4 sti, undocumented op */
5892 case 0x39: /* fxchg7 sti, undocumented op */
5893 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5894 break;
5895 case 0x0a: /* grp d9/2 */
5896 switch(rm) {
5897 case 0: /* fnop */
5898 /* check exceptions (FreeBSD FPU probe) */
5899 gen_helper_fwait(cpu_env);
5900 break;
5901 default:
5902 goto unknown_op;
5904 break;
5905 case 0x0c: /* grp d9/4 */
5906 switch(rm) {
5907 case 0: /* fchs */
5908 gen_helper_fchs_ST0(cpu_env);
5909 break;
5910 case 1: /* fabs */
5911 gen_helper_fabs_ST0(cpu_env);
5912 break;
5913 case 4: /* ftst */
5914 gen_helper_fldz_FT0(cpu_env);
5915 gen_helper_fcom_ST0_FT0(cpu_env);
5916 break;
5917 case 5: /* fxam */
5918 gen_helper_fxam_ST0(cpu_env);
5919 break;
5920 default:
5921 goto unknown_op;
5923 break;
5924 case 0x0d: /* grp d9/5 */
5926 switch(rm) {
5927 case 0:
5928 gen_helper_fpush(cpu_env);
5929 gen_helper_fld1_ST0(cpu_env);
5930 break;
5931 case 1:
5932 gen_helper_fpush(cpu_env);
5933 gen_helper_fldl2t_ST0(cpu_env);
5934 break;
5935 case 2:
5936 gen_helper_fpush(cpu_env);
5937 gen_helper_fldl2e_ST0(cpu_env);
5938 break;
5939 case 3:
5940 gen_helper_fpush(cpu_env);
5941 gen_helper_fldpi_ST0(cpu_env);
5942 break;
5943 case 4:
5944 gen_helper_fpush(cpu_env);
5945 gen_helper_fldlg2_ST0(cpu_env);
5946 break;
5947 case 5:
5948 gen_helper_fpush(cpu_env);
5949 gen_helper_fldln2_ST0(cpu_env);
5950 break;
5951 case 6:
5952 gen_helper_fpush(cpu_env);
5953 gen_helper_fldz_ST0(cpu_env);
5954 break;
5955 default:
5956 goto unknown_op;
5959 break;
5960 case 0x0e: /* grp d9/6 */
5961 switch(rm) {
5962 case 0: /* f2xm1 */
5963 gen_helper_f2xm1(cpu_env);
5964 break;
5965 case 1: /* fyl2x */
5966 gen_helper_fyl2x(cpu_env);
5967 break;
5968 case 2: /* fptan */
5969 gen_helper_fptan(cpu_env);
5970 break;
5971 case 3: /* fpatan */
5972 gen_helper_fpatan(cpu_env);
5973 break;
5974 case 4: /* fxtract */
5975 gen_helper_fxtract(cpu_env);
5976 break;
5977 case 5: /* fprem1 */
5978 gen_helper_fprem1(cpu_env);
5979 break;
5980 case 6: /* fdecstp */
5981 gen_helper_fdecstp(cpu_env);
5982 break;
5983 default:
5984 case 7: /* fincstp */
5985 gen_helper_fincstp(cpu_env);
5986 break;
5988 break;
5989 case 0x0f: /* grp d9/7 */
5990 switch(rm) {
5991 case 0: /* fprem */
5992 gen_helper_fprem(cpu_env);
5993 break;
5994 case 1: /* fyl2xp1 */
5995 gen_helper_fyl2xp1(cpu_env);
5996 break;
5997 case 2: /* fsqrt */
5998 gen_helper_fsqrt(cpu_env);
5999 break;
6000 case 3: /* fsincos */
6001 gen_helper_fsincos(cpu_env);
6002 break;
6003 case 5: /* fscale */
6004 gen_helper_fscale(cpu_env);
6005 break;
6006 case 4: /* frndint */
6007 gen_helper_frndint(cpu_env);
6008 break;
6009 case 6: /* fsin */
6010 gen_helper_fsin(cpu_env);
6011 break;
6012 default:
6013 case 7: /* fcos */
6014 gen_helper_fcos(cpu_env);
6015 break;
6017 break;
6018 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6019 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6020 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6022 int op1;
6024 op1 = op & 7;
6025 if (op >= 0x20) {
6026 gen_helper_fp_arith_STN_ST0(op1, opreg);
6027 if (op >= 0x30)
6028 gen_helper_fpop(cpu_env);
6029 } else {
6030 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6031 gen_helper_fp_arith_ST0_FT0(op1);
6034 break;
6035 case 0x02: /* fcom */
6036 case 0x22: /* fcom2, undocumented op */
6037 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6038 gen_helper_fcom_ST0_FT0(cpu_env);
6039 break;
6040 case 0x03: /* fcomp */
6041 case 0x23: /* fcomp3, undocumented op */
6042 case 0x32: /* fcomp5, undocumented op */
6043 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6044 gen_helper_fcom_ST0_FT0(cpu_env);
6045 gen_helper_fpop(cpu_env);
6046 break;
6047 case 0x15: /* da/5 */
6048 switch(rm) {
6049 case 1: /* fucompp */
6050 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6051 gen_helper_fucom_ST0_FT0(cpu_env);
6052 gen_helper_fpop(cpu_env);
6053 gen_helper_fpop(cpu_env);
6054 break;
6055 default:
6056 goto unknown_op;
6058 break;
6059 case 0x1c:
6060 switch(rm) {
6061 case 0: /* feni (287 only, just do nop here) */
6062 break;
6063 case 1: /* fdisi (287 only, just do nop here) */
6064 break;
6065 case 2: /* fclex */
6066 gen_helper_fclex(cpu_env);
6067 break;
6068 case 3: /* fninit */
6069 gen_helper_fninit(cpu_env);
6070 break;
6071 case 4: /* fsetpm (287 only, just do nop here) */
6072 break;
6073 default:
6074 goto unknown_op;
6076 break;
6077 case 0x1d: /* fucomi */
6078 if (!(s->cpuid_features & CPUID_CMOV)) {
6079 goto illegal_op;
6081 gen_update_cc_op(s);
6082 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6083 gen_helper_fucomi_ST0_FT0(cpu_env);
6084 set_cc_op(s, CC_OP_EFLAGS);
6085 break;
6086 case 0x1e: /* fcomi */
6087 if (!(s->cpuid_features & CPUID_CMOV)) {
6088 goto illegal_op;
6090 gen_update_cc_op(s);
6091 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6092 gen_helper_fcomi_ST0_FT0(cpu_env);
6093 set_cc_op(s, CC_OP_EFLAGS);
6094 break;
6095 case 0x28: /* ffree sti */
6096 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6097 break;
6098 case 0x2a: /* fst sti */
6099 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6100 break;
6101 case 0x2b: /* fstp sti */
6102 case 0x0b: /* fstp1 sti, undocumented op */
6103 case 0x3a: /* fstp8 sti, undocumented op */
6104 case 0x3b: /* fstp9 sti, undocumented op */
6105 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6106 gen_helper_fpop(cpu_env);
6107 break;
6108 case 0x2c: /* fucom st(i) */
6109 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6110 gen_helper_fucom_ST0_FT0(cpu_env);
6111 break;
6112 case 0x2d: /* fucomp st(i) */
6113 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6114 gen_helper_fucom_ST0_FT0(cpu_env);
6115 gen_helper_fpop(cpu_env);
6116 break;
6117 case 0x33: /* de/3 */
6118 switch(rm) {
6119 case 1: /* fcompp */
6120 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6121 gen_helper_fcom_ST0_FT0(cpu_env);
6122 gen_helper_fpop(cpu_env);
6123 gen_helper_fpop(cpu_env);
6124 break;
6125 default:
6126 goto unknown_op;
6128 break;
6129 case 0x38: /* ffreep sti, undocumented op */
6130 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6131 gen_helper_fpop(cpu_env);
6132 break;
6133 case 0x3c: /* df/4 */
6134 switch(rm) {
6135 case 0:
6136 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6137 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
6138 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
6139 break;
6140 default:
6141 goto unknown_op;
6143 break;
6144 case 0x3d: /* fucomip */
6145 if (!(s->cpuid_features & CPUID_CMOV)) {
6146 goto illegal_op;
6148 gen_update_cc_op(s);
6149 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6150 gen_helper_fucomi_ST0_FT0(cpu_env);
6151 gen_helper_fpop(cpu_env);
6152 set_cc_op(s, CC_OP_EFLAGS);
6153 break;
6154 case 0x3e: /* fcomip */
6155 if (!(s->cpuid_features & CPUID_CMOV)) {
6156 goto illegal_op;
6158 gen_update_cc_op(s);
6159 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6160 gen_helper_fcomi_ST0_FT0(cpu_env);
6161 gen_helper_fpop(cpu_env);
6162 set_cc_op(s, CC_OP_EFLAGS);
6163 break;
6164 case 0x10 ... 0x13: /* fcmovxx */
6165 case 0x18 ... 0x1b:
6167 int op1;
6168 TCGLabel *l1;
6169 static const uint8_t fcmov_cc[8] = {
6170 (JCC_B << 1),
6171 (JCC_Z << 1),
6172 (JCC_BE << 1),
6173 (JCC_P << 1),
6176 if (!(s->cpuid_features & CPUID_CMOV)) {
6177 goto illegal_op;
6179 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6180 l1 = gen_new_label();
6181 gen_jcc1_noeob(s, op1, l1);
6182 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6183 gen_set_label(l1);
6185 break;
6186 default:
6187 goto unknown_op;
6190 break;
6191 /************************/
6192 /* string ops */
6194 case 0xa4: /* movsS */
6195 case 0xa5:
6196 ot = mo_b_d(b, dflag);
6197 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6198 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6199 } else {
6200 gen_movs(s, ot);
6202 break;
6204 case 0xaa: /* stosS */
6205 case 0xab:
6206 ot = mo_b_d(b, dflag);
6207 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6208 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6209 } else {
6210 gen_stos(s, ot);
6212 break;
6213 case 0xac: /* lodsS */
6214 case 0xad:
6215 ot = mo_b_d(b, dflag);
6216 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6217 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6218 } else {
6219 gen_lods(s, ot);
6221 break;
6222 case 0xae: /* scasS */
6223 case 0xaf:
6224 ot = mo_b_d(b, dflag);
6225 if (prefixes & PREFIX_REPNZ) {
6226 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6227 } else if (prefixes & PREFIX_REPZ) {
6228 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6229 } else {
6230 gen_scas(s, ot);
6232 break;
6234 case 0xa6: /* cmpsS */
6235 case 0xa7:
6236 ot = mo_b_d(b, dflag);
6237 if (prefixes & PREFIX_REPNZ) {
6238 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6239 } else if (prefixes & PREFIX_REPZ) {
6240 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6241 } else {
6242 gen_cmps(s, ot);
6244 break;
6245 case 0x6c: /* insS */
6246 case 0x6d:
6247 ot = mo_b_d32(b, dflag);
6248 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6249 gen_check_io(s, ot, pc_start - s->cs_base,
6250 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6251 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6252 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6253 } else {
6254 gen_ins(s, ot);
6255 if (s->tb->cflags & CF_USE_ICOUNT) {
6256 gen_jmp(s, s->pc - s->cs_base);
6259 break;
6260 case 0x6e: /* outsS */
6261 case 0x6f:
6262 ot = mo_b_d32(b, dflag);
6263 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6264 gen_check_io(s, ot, pc_start - s->cs_base,
6265 svm_is_rep(prefixes) | 4);
6266 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6267 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6268 } else {
6269 gen_outs(s, ot);
6270 if (s->tb->cflags & CF_USE_ICOUNT) {
6271 gen_jmp(s, s->pc - s->cs_base);
6274 break;
6276 /************************/
6277 /* port I/O */
6279 case 0xe4:
6280 case 0xe5:
6281 ot = mo_b_d32(b, dflag);
6282 val = cpu_ldub_code(env, s->pc++);
6283 tcg_gen_movi_tl(cpu_T0, val);
6284 gen_check_io(s, ot, pc_start - s->cs_base,
6285 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6286 if (s->tb->cflags & CF_USE_ICOUNT) {
6287 gen_io_start();
6289 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6290 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6291 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6292 gen_bpt_io(s, cpu_tmp2_i32, ot);
6293 if (s->tb->cflags & CF_USE_ICOUNT) {
6294 gen_io_end();
6295 gen_jmp(s, s->pc - s->cs_base);
6297 break;
6298 case 0xe6:
6299 case 0xe7:
6300 ot = mo_b_d32(b, dflag);
6301 val = cpu_ldub_code(env, s->pc++);
6302 tcg_gen_movi_tl(cpu_T0, val);
6303 gen_check_io(s, ot, pc_start - s->cs_base,
6304 svm_is_rep(prefixes));
6305 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6307 if (s->tb->cflags & CF_USE_ICOUNT) {
6308 gen_io_start();
6310 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6311 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6312 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6313 gen_bpt_io(s, cpu_tmp2_i32, ot);
6314 if (s->tb->cflags & CF_USE_ICOUNT) {
6315 gen_io_end();
6316 gen_jmp(s, s->pc - s->cs_base);
6318 break;
6319 case 0xec:
6320 case 0xed:
6321 ot = mo_b_d32(b, dflag);
6322 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6323 gen_check_io(s, ot, pc_start - s->cs_base,
6324 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6325 if (s->tb->cflags & CF_USE_ICOUNT) {
6326 gen_io_start();
6328 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6329 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6330 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6331 gen_bpt_io(s, cpu_tmp2_i32, ot);
6332 if (s->tb->cflags & CF_USE_ICOUNT) {
6333 gen_io_end();
6334 gen_jmp(s, s->pc - s->cs_base);
6336 break;
6337 case 0xee:
6338 case 0xef:
6339 ot = mo_b_d32(b, dflag);
6340 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6341 gen_check_io(s, ot, pc_start - s->cs_base,
6342 svm_is_rep(prefixes));
6343 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6345 if (s->tb->cflags & CF_USE_ICOUNT) {
6346 gen_io_start();
6348 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6349 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6350 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6351 gen_bpt_io(s, cpu_tmp2_i32, ot);
6352 if (s->tb->cflags & CF_USE_ICOUNT) {
6353 gen_io_end();
6354 gen_jmp(s, s->pc - s->cs_base);
6356 break;
6358 /************************/
6359 /* control */
6360 case 0xc2: /* ret im */
6361 val = cpu_ldsw_code(env, s->pc);
6362 s->pc += 2;
6363 ot = gen_pop_T0(s);
6364 gen_stack_update(s, val + (1 << ot));
6365 /* Note that gen_pop_T0 uses a zero-extending load. */
6366 gen_op_jmp_v(cpu_T0);
6367 gen_bnd_jmp(s);
6368 gen_eob(s);
6369 break;
6370 case 0xc3: /* ret */
6371 ot = gen_pop_T0(s);
6372 gen_pop_update(s, ot);
6373 /* Note that gen_pop_T0 uses a zero-extending load. */
6374 gen_op_jmp_v(cpu_T0);
6375 gen_bnd_jmp(s);
6376 gen_eob(s);
6377 break;
6378 case 0xca: /* lret im */
6379 val = cpu_ldsw_code(env, s->pc);
6380 s->pc += 2;
6381 do_lret:
6382 if (s->pe && !s->vm86) {
6383 gen_update_cc_op(s);
6384 gen_jmp_im(pc_start - s->cs_base);
6385 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6386 tcg_const_i32(val));
6387 } else {
6388 gen_stack_A0(s);
6389 /* pop offset */
6390 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6391 /* NOTE: keeping EIP updated is not a problem in case of
6392 exception */
6393 gen_op_jmp_v(cpu_T0);
6394 /* pop selector */
6395 gen_add_A0_im(s, 1 << dflag);
6396 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6397 gen_op_movl_seg_T0_vm(R_CS);
6398 /* add stack offset */
6399 gen_stack_update(s, val + (2 << dflag));
6401 gen_eob(s);
6402 break;
6403 case 0xcb: /* lret */
6404 val = 0;
6405 goto do_lret;
6406 case 0xcf: /* iret */
6407 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6408 if (!s->pe) {
6409 /* real mode */
6410 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6411 set_cc_op(s, CC_OP_EFLAGS);
6412 } else if (s->vm86) {
6413 if (s->iopl != 3) {
6414 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6415 } else {
6416 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6417 set_cc_op(s, CC_OP_EFLAGS);
6419 } else {
6420 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6421 tcg_const_i32(s->pc - s->cs_base));
6422 set_cc_op(s, CC_OP_EFLAGS);
6424 gen_eob(s);
6425 break;
6426 case 0xe8: /* call im */
6428 if (dflag != MO_16) {
6429 tval = (int32_t)insn_get(env, s, MO_32);
6430 } else {
6431 tval = (int16_t)insn_get(env, s, MO_16);
6433 next_eip = s->pc - s->cs_base;
6434 tval += next_eip;
6435 if (dflag == MO_16) {
6436 tval &= 0xffff;
6437 } else if (!CODE64(s)) {
6438 tval &= 0xffffffff;
6440 tcg_gen_movi_tl(cpu_T0, next_eip);
6441 gen_push_v(s, cpu_T0);
6442 gen_bnd_jmp(s);
6443 gen_jmp(s, tval);
6445 break;
6446 case 0x9a: /* lcall im */
6448 unsigned int selector, offset;
6450 if (CODE64(s))
6451 goto illegal_op;
6452 ot = dflag;
6453 offset = insn_get(env, s, ot);
6454 selector = insn_get(env, s, MO_16);
6456 tcg_gen_movi_tl(cpu_T0, selector);
6457 tcg_gen_movi_tl(cpu_T1, offset);
6459 goto do_lcall;
6460 case 0xe9: /* jmp im */
6461 if (dflag != MO_16) {
6462 tval = (int32_t)insn_get(env, s, MO_32);
6463 } else {
6464 tval = (int16_t)insn_get(env, s, MO_16);
6466 tval += s->pc - s->cs_base;
6467 if (dflag == MO_16) {
6468 tval &= 0xffff;
6469 } else if (!CODE64(s)) {
6470 tval &= 0xffffffff;
6472 gen_bnd_jmp(s);
6473 gen_jmp(s, tval);
6474 break;
6475 case 0xea: /* ljmp im */
6477 unsigned int selector, offset;
6479 if (CODE64(s))
6480 goto illegal_op;
6481 ot = dflag;
6482 offset = insn_get(env, s, ot);
6483 selector = insn_get(env, s, MO_16);
6485 tcg_gen_movi_tl(cpu_T0, selector);
6486 tcg_gen_movi_tl(cpu_T1, offset);
6488 goto do_ljmp;
6489 case 0xeb: /* jmp Jb */
6490 tval = (int8_t)insn_get(env, s, MO_8);
6491 tval += s->pc - s->cs_base;
6492 if (dflag == MO_16) {
6493 tval &= 0xffff;
6495 gen_jmp(s, tval);
6496 break;
6497 case 0x70 ... 0x7f: /* jcc Jb */
6498 tval = (int8_t)insn_get(env, s, MO_8);
6499 goto do_jcc;
6500 case 0x180 ... 0x18f: /* jcc Jv */
6501 if (dflag != MO_16) {
6502 tval = (int32_t)insn_get(env, s, MO_32);
6503 } else {
6504 tval = (int16_t)insn_get(env, s, MO_16);
6506 do_jcc:
6507 next_eip = s->pc - s->cs_base;
6508 tval += next_eip;
6509 if (dflag == MO_16) {
6510 tval &= 0xffff;
6512 gen_bnd_jmp(s);
6513 gen_jcc(s, b, tval, next_eip);
6514 break;
6516 case 0x190 ... 0x19f: /* setcc Gv */
6517 modrm = cpu_ldub_code(env, s->pc++);
6518 gen_setcc1(s, b, cpu_T0);
6519 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6520 break;
6521 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6522 if (!(s->cpuid_features & CPUID_CMOV)) {
6523 goto illegal_op;
6525 ot = dflag;
6526 modrm = cpu_ldub_code(env, s->pc++);
6527 reg = ((modrm >> 3) & 7) | rex_r;
6528 gen_cmovcc1(env, s, ot, b, modrm, reg);
6529 break;
6531 /************************/
6532 /* flags */
6533 case 0x9c: /* pushf */
6534 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6535 if (s->vm86 && s->iopl != 3) {
6536 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6537 } else {
6538 gen_update_cc_op(s);
6539 gen_helper_read_eflags(cpu_T0, cpu_env);
6540 gen_push_v(s, cpu_T0);
6542 break;
6543 case 0x9d: /* popf */
6544 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6545 if (s->vm86 && s->iopl != 3) {
6546 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6547 } else {
6548 ot = gen_pop_T0(s);
6549 if (s->cpl == 0) {
6550 if (dflag != MO_16) {
6551 gen_helper_write_eflags(cpu_env, cpu_T0,
6552 tcg_const_i32((TF_MASK | AC_MASK |
6553 ID_MASK | NT_MASK |
6554 IF_MASK |
6555 IOPL_MASK)));
6556 } else {
6557 gen_helper_write_eflags(cpu_env, cpu_T0,
6558 tcg_const_i32((TF_MASK | AC_MASK |
6559 ID_MASK | NT_MASK |
6560 IF_MASK | IOPL_MASK)
6561 & 0xffff));
6563 } else {
6564 if (s->cpl <= s->iopl) {
6565 if (dflag != MO_16) {
6566 gen_helper_write_eflags(cpu_env, cpu_T0,
6567 tcg_const_i32((TF_MASK |
6568 AC_MASK |
6569 ID_MASK |
6570 NT_MASK |
6571 IF_MASK)));
6572 } else {
6573 gen_helper_write_eflags(cpu_env, cpu_T0,
6574 tcg_const_i32((TF_MASK |
6575 AC_MASK |
6576 ID_MASK |
6577 NT_MASK |
6578 IF_MASK)
6579 & 0xffff));
6581 } else {
6582 if (dflag != MO_16) {
6583 gen_helper_write_eflags(cpu_env, cpu_T0,
6584 tcg_const_i32((TF_MASK | AC_MASK |
6585 ID_MASK | NT_MASK)));
6586 } else {
6587 gen_helper_write_eflags(cpu_env, cpu_T0,
6588 tcg_const_i32((TF_MASK | AC_MASK |
6589 ID_MASK | NT_MASK)
6590 & 0xffff));
6594 gen_pop_update(s, ot);
6595 set_cc_op(s, CC_OP_EFLAGS);
6596 /* abort translation because TF/AC flag may change */
6597 gen_jmp_im(s->pc - s->cs_base);
6598 gen_eob(s);
6600 break;
6601 case 0x9e: /* sahf */
6602 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6603 goto illegal_op;
6604 gen_op_mov_v_reg(MO_8, cpu_T0, R_AH);
6605 gen_compute_eflags(s);
6606 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6607 tcg_gen_andi_tl(cpu_T0, cpu_T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6608 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T0);
6609 break;
6610 case 0x9f: /* lahf */
6611 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6612 goto illegal_op;
6613 gen_compute_eflags(s);
6614 /* Note: gen_compute_eflags() only gives the condition codes */
6615 tcg_gen_ori_tl(cpu_T0, cpu_cc_src, 0x02);
6616 gen_op_mov_reg_v(MO_8, R_AH, cpu_T0);
6617 break;
6618 case 0xf5: /* cmc */
6619 gen_compute_eflags(s);
6620 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6621 break;
6622 case 0xf8: /* clc */
6623 gen_compute_eflags(s);
6624 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6625 break;
6626 case 0xf9: /* stc */
6627 gen_compute_eflags(s);
6628 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6629 break;
6630 case 0xfc: /* cld */
6631 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6632 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6633 break;
6634 case 0xfd: /* std */
6635 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6636 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6637 break;
6639 /************************/
6640 /* bit operations */
6641 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6642 ot = dflag;
6643 modrm = cpu_ldub_code(env, s->pc++);
6644 op = (modrm >> 3) & 7;
6645 mod = (modrm >> 6) & 3;
6646 rm = (modrm & 7) | REX_B(s);
6647 if (mod != 3) {
6648 s->rip_offset = 1;
6649 gen_lea_modrm(env, s, modrm);
6650 if (!(s->prefix & PREFIX_LOCK)) {
6651 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6653 } else {
6654 gen_op_mov_v_reg(ot, cpu_T0, rm);
6656 /* load shift */
6657 val = cpu_ldub_code(env, s->pc++);
6658 tcg_gen_movi_tl(cpu_T1, val);
6659 if (op < 4)
6660 goto unknown_op;
6661 op -= 4;
6662 goto bt_op;
6663 case 0x1a3: /* bt Gv, Ev */
6664 op = 0;
6665 goto do_btx;
6666 case 0x1ab: /* bts */
6667 op = 1;
6668 goto do_btx;
6669 case 0x1b3: /* btr */
6670 op = 2;
6671 goto do_btx;
6672 case 0x1bb: /* btc */
6673 op = 3;
6674 do_btx:
6675 ot = dflag;
6676 modrm = cpu_ldub_code(env, s->pc++);
6677 reg = ((modrm >> 3) & 7) | rex_r;
6678 mod = (modrm >> 6) & 3;
6679 rm = (modrm & 7) | REX_B(s);
6680 gen_op_mov_v_reg(MO_32, cpu_T1, reg);
6681 if (mod != 3) {
6682 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6683 /* specific case: we need to add a displacement */
6684 gen_exts(ot, cpu_T1);
6685 tcg_gen_sari_tl(cpu_tmp0, cpu_T1, 3 + ot);
6686 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6687 tcg_gen_add_tl(cpu_A0, gen_lea_modrm_1(a), cpu_tmp0);
6688 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
6689 if (!(s->prefix & PREFIX_LOCK)) {
6690 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6692 } else {
6693 gen_op_mov_v_reg(ot, cpu_T0, rm);
6695 bt_op:
6696 tcg_gen_andi_tl(cpu_T1, cpu_T1, (1 << (3 + ot)) - 1);
6697 tcg_gen_movi_tl(cpu_tmp0, 1);
6698 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6699 if (s->prefix & PREFIX_LOCK) {
6700 switch (op) {
6701 case 0: /* bt */
6702 /* Needs no atomic ops; we surpressed the normal
6703 memory load for LOCK above so do it now. */
6704 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6705 break;
6706 case 1: /* bts */
6707 tcg_gen_atomic_fetch_or_tl(cpu_T0, cpu_A0, cpu_tmp0,
6708 s->mem_index, ot | MO_LE);
6709 break;
6710 case 2: /* btr */
6711 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
6712 tcg_gen_atomic_fetch_and_tl(cpu_T0, cpu_A0, cpu_tmp0,
6713 s->mem_index, ot | MO_LE);
6714 break;
6715 default:
6716 case 3: /* btc */
6717 tcg_gen_atomic_fetch_xor_tl(cpu_T0, cpu_A0, cpu_tmp0,
6718 s->mem_index, ot | MO_LE);
6719 break;
6721 tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1);
6722 } else {
6723 tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1);
6724 switch (op) {
6725 case 0: /* bt */
6726 /* Data already loaded; nothing to do. */
6727 break;
6728 case 1: /* bts */
6729 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
6730 break;
6731 case 2: /* btr */
6732 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_tmp0);
6733 break;
6734 default:
6735 case 3: /* btc */
6736 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_tmp0);
6737 break;
6739 if (op != 0) {
6740 if (mod != 3) {
6741 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
6742 } else {
6743 gen_op_mov_reg_v(ot, rm, cpu_T0);
6748 /* Delay all CC updates until after the store above. Note that
6749 C is the result of the test, Z is unchanged, and the others
6750 are all undefined. */
6751 switch (s->cc_op) {
6752 case CC_OP_MULB ... CC_OP_MULQ:
6753 case CC_OP_ADDB ... CC_OP_ADDQ:
6754 case CC_OP_ADCB ... CC_OP_ADCQ:
6755 case CC_OP_SUBB ... CC_OP_SUBQ:
6756 case CC_OP_SBBB ... CC_OP_SBBQ:
6757 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6758 case CC_OP_INCB ... CC_OP_INCQ:
6759 case CC_OP_DECB ... CC_OP_DECQ:
6760 case CC_OP_SHLB ... CC_OP_SHLQ:
6761 case CC_OP_SARB ... CC_OP_SARQ:
6762 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6763 /* Z was going to be computed from the non-zero status of CC_DST.
6764 We can get that same Z value (and the new C value) by leaving
6765 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6766 same width. */
6767 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6768 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6769 break;
6770 default:
6771 /* Otherwise, generate EFLAGS and replace the C bit. */
6772 gen_compute_eflags(s);
6773 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6774 ctz32(CC_C), 1);
6775 break;
6777 break;
6778 case 0x1bc: /* bsf / tzcnt */
6779 case 0x1bd: /* bsr / lzcnt */
6780 ot = dflag;
6781 modrm = cpu_ldub_code(env, s->pc++);
6782 reg = ((modrm >> 3) & 7) | rex_r;
6783 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6784 gen_extu(ot, cpu_T0);
6786 /* Note that lzcnt and tzcnt are in different extensions. */
6787 if ((prefixes & PREFIX_REPZ)
6788 && (b & 1
6789 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6790 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6791 int size = 8 << ot;
6792 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
6793 if (b & 1) {
6794 /* For lzcnt, reduce the target_ulong result by the
6795 number of zeros that we expect to find at the top. */
6796 gen_helper_clz(cpu_T0, cpu_T0);
6797 tcg_gen_subi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - size);
6798 } else {
6799 /* For tzcnt, a zero input must return the operand size:
6800 force all bits outside the operand size to 1. */
6801 target_ulong mask = (target_ulong)-2 << (size - 1);
6802 tcg_gen_ori_tl(cpu_T0, cpu_T0, mask);
6803 gen_helper_ctz(cpu_T0, cpu_T0);
6805 /* For lzcnt/tzcnt, C and Z bits are defined and are
6806 related to the result. */
6807 gen_op_update1_cc();
6808 set_cc_op(s, CC_OP_BMILGB + ot);
6809 } else {
6810 /* For bsr/bsf, only the Z bit is defined and it is related
6811 to the input and not the result. */
6812 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
6813 set_cc_op(s, CC_OP_LOGICB + ot);
6814 if (b & 1) {
6815 /* For bsr, return the bit index of the first 1 bit,
6816 not the count of leading zeros. */
6817 gen_helper_clz(cpu_T0, cpu_T0);
6818 tcg_gen_xori_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - 1);
6819 } else {
6820 gen_helper_ctz(cpu_T0, cpu_T0);
6822 /* ??? The manual says that the output is undefined when the
6823 input is zero, but real hardware leaves it unchanged, and
6824 real programs appear to depend on that. */
6825 tcg_gen_movi_tl(cpu_tmp0, 0);
6826 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T0, cpu_cc_dst, cpu_tmp0,
6827 cpu_regs[reg], cpu_T0);
6829 gen_op_mov_reg_v(ot, reg, cpu_T0);
6830 break;
6831 /************************/
6832 /* bcd */
6833 case 0x27: /* daa */
6834 if (CODE64(s))
6835 goto illegal_op;
6836 gen_update_cc_op(s);
6837 gen_helper_daa(cpu_env);
6838 set_cc_op(s, CC_OP_EFLAGS);
6839 break;
6840 case 0x2f: /* das */
6841 if (CODE64(s))
6842 goto illegal_op;
6843 gen_update_cc_op(s);
6844 gen_helper_das(cpu_env);
6845 set_cc_op(s, CC_OP_EFLAGS);
6846 break;
6847 case 0x37: /* aaa */
6848 if (CODE64(s))
6849 goto illegal_op;
6850 gen_update_cc_op(s);
6851 gen_helper_aaa(cpu_env);
6852 set_cc_op(s, CC_OP_EFLAGS);
6853 break;
6854 case 0x3f: /* aas */
6855 if (CODE64(s))
6856 goto illegal_op;
6857 gen_update_cc_op(s);
6858 gen_helper_aas(cpu_env);
6859 set_cc_op(s, CC_OP_EFLAGS);
6860 break;
6861 case 0xd4: /* aam */
6862 if (CODE64(s))
6863 goto illegal_op;
6864 val = cpu_ldub_code(env, s->pc++);
6865 if (val == 0) {
6866 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6867 } else {
6868 gen_helper_aam(cpu_env, tcg_const_i32(val));
6869 set_cc_op(s, CC_OP_LOGICB);
6871 break;
6872 case 0xd5: /* aad */
6873 if (CODE64(s))
6874 goto illegal_op;
6875 val = cpu_ldub_code(env, s->pc++);
6876 gen_helper_aad(cpu_env, tcg_const_i32(val));
6877 set_cc_op(s, CC_OP_LOGICB);
6878 break;
6879 /************************/
6880 /* misc */
6881 case 0x90: /* nop */
6882 /* XXX: correct lock test for all insn */
6883 if (prefixes & PREFIX_LOCK) {
6884 goto illegal_op;
6886 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6887 if (REX_B(s)) {
6888 goto do_xchg_reg_eax;
6890 if (prefixes & PREFIX_REPZ) {
6891 gen_update_cc_op(s);
6892 gen_jmp_im(pc_start - s->cs_base);
6893 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6894 s->is_jmp = DISAS_TB_JUMP;
6896 break;
6897 case 0x9b: /* fwait */
6898 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6899 (HF_MP_MASK | HF_TS_MASK)) {
6900 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6901 } else {
6902 gen_helper_fwait(cpu_env);
6904 break;
6905 case 0xcc: /* int3 */
6906 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6907 break;
6908 case 0xcd: /* int N */
6909 val = cpu_ldub_code(env, s->pc++);
6910 if (s->vm86 && s->iopl != 3) {
6911 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6912 } else {
6913 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6915 break;
6916 case 0xce: /* into */
6917 if (CODE64(s))
6918 goto illegal_op;
6919 gen_update_cc_op(s);
6920 gen_jmp_im(pc_start - s->cs_base);
6921 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6922 break;
6923 #ifdef WANT_ICEBP
6924 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6925 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6926 #if 1
6927 gen_debug(s, pc_start - s->cs_base);
6928 #else
6929 /* start debug */
6930 tb_flush(CPU(x86_env_get_cpu(env)));
6931 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6932 #endif
6933 break;
6934 #endif
6935 case 0xfa: /* cli */
6936 if (!s->vm86) {
6937 if (s->cpl <= s->iopl) {
6938 gen_helper_cli(cpu_env);
6939 } else {
6940 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6942 } else {
6943 if (s->iopl == 3) {
6944 gen_helper_cli(cpu_env);
6945 } else {
6946 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6949 break;
6950 case 0xfb: /* sti */
6951 if (s->vm86 ? s->iopl == 3 : s->cpl <= s->iopl) {
6952 gen_helper_sti(cpu_env);
6953 /* interruptions are enabled only the first insn after sti */
6954 gen_jmp_im(s->pc - s->cs_base);
6955 gen_eob_inhibit_irq(s, true);
6956 } else {
6957 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6959 break;
6960 case 0x62: /* bound */
6961 if (CODE64(s))
6962 goto illegal_op;
6963 ot = dflag;
6964 modrm = cpu_ldub_code(env, s->pc++);
6965 reg = (modrm >> 3) & 7;
6966 mod = (modrm >> 6) & 3;
6967 if (mod == 3)
6968 goto illegal_op;
6969 gen_op_mov_v_reg(ot, cpu_T0, reg);
6970 gen_lea_modrm(env, s, modrm);
6971 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6972 if (ot == MO_16) {
6973 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
6974 } else {
6975 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
6977 break;
6978 case 0x1c8 ... 0x1cf: /* bswap reg */
6979 reg = (b & 7) | REX_B(s);
6980 #ifdef TARGET_X86_64
6981 if (dflag == MO_64) {
6982 gen_op_mov_v_reg(MO_64, cpu_T0, reg);
6983 tcg_gen_bswap64_i64(cpu_T0, cpu_T0);
6984 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
6985 } else
6986 #endif
6988 gen_op_mov_v_reg(MO_32, cpu_T0, reg);
6989 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
6990 tcg_gen_bswap32_tl(cpu_T0, cpu_T0);
6991 gen_op_mov_reg_v(MO_32, reg, cpu_T0);
6993 break;
6994 case 0xd6: /* salc */
6995 if (CODE64(s))
6996 goto illegal_op;
6997 gen_compute_eflags_c(s, cpu_T0);
6998 tcg_gen_neg_tl(cpu_T0, cpu_T0);
6999 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
7000 break;
7001 case 0xe0: /* loopnz */
7002 case 0xe1: /* loopz */
7003 case 0xe2: /* loop */
7004 case 0xe3: /* jecxz */
7006 TCGLabel *l1, *l2, *l3;
7008 tval = (int8_t)insn_get(env, s, MO_8);
7009 next_eip = s->pc - s->cs_base;
7010 tval += next_eip;
7011 if (dflag == MO_16) {
7012 tval &= 0xffff;
7015 l1 = gen_new_label();
7016 l2 = gen_new_label();
7017 l3 = gen_new_label();
7018 b &= 3;
7019 switch(b) {
7020 case 0: /* loopnz */
7021 case 1: /* loopz */
7022 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7023 gen_op_jz_ecx(s->aflag, l3);
7024 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7025 break;
7026 case 2: /* loop */
7027 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7028 gen_op_jnz_ecx(s->aflag, l1);
7029 break;
7030 default:
7031 case 3: /* jcxz */
7032 gen_op_jz_ecx(s->aflag, l1);
7033 break;
7036 gen_set_label(l3);
7037 gen_jmp_im(next_eip);
7038 tcg_gen_br(l2);
7040 gen_set_label(l1);
7041 gen_jmp_im(tval);
7042 gen_set_label(l2);
7043 gen_eob(s);
7045 break;
7046 case 0x130: /* wrmsr */
7047 case 0x132: /* rdmsr */
7048 if (s->cpl != 0) {
7049 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7050 } else {
7051 gen_update_cc_op(s);
7052 gen_jmp_im(pc_start - s->cs_base);
7053 if (b & 2) {
7054 gen_helper_rdmsr(cpu_env);
7055 } else {
7056 gen_helper_wrmsr(cpu_env);
7059 break;
7060 case 0x131: /* rdtsc */
7061 gen_update_cc_op(s);
7062 gen_jmp_im(pc_start - s->cs_base);
7063 if (s->tb->cflags & CF_USE_ICOUNT) {
7064 gen_io_start();
7066 gen_helper_rdtsc(cpu_env);
7067 if (s->tb->cflags & CF_USE_ICOUNT) {
7068 gen_io_end();
7069 gen_jmp(s, s->pc - s->cs_base);
7071 break;
7072 case 0x133: /* rdpmc */
7073 gen_update_cc_op(s);
7074 gen_jmp_im(pc_start - s->cs_base);
7075 gen_helper_rdpmc(cpu_env);
7076 break;
7077 case 0x134: /* sysenter */
7078 /* For Intel SYSENTER is valid on 64-bit */
7079 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7080 goto illegal_op;
7081 if (!s->pe) {
7082 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7083 } else {
7084 gen_helper_sysenter(cpu_env);
7085 gen_eob(s);
7087 break;
7088 case 0x135: /* sysexit */
7089 /* For Intel SYSEXIT is valid on 64-bit */
7090 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7091 goto illegal_op;
7092 if (!s->pe) {
7093 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7094 } else {
7095 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7096 gen_eob(s);
7098 break;
7099 #ifdef TARGET_X86_64
7100 case 0x105: /* syscall */
7101 /* XXX: is it usable in real mode ? */
7102 gen_update_cc_op(s);
7103 gen_jmp_im(pc_start - s->cs_base);
7104 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7105 gen_eob(s);
7106 break;
7107 case 0x107: /* sysret */
7108 if (!s->pe) {
7109 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7110 } else {
7111 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7112 /* condition codes are modified only in long mode */
7113 if (s->lma) {
7114 set_cc_op(s, CC_OP_EFLAGS);
7116 gen_eob(s);
7118 break;
7119 #endif
7120 case 0x1a2: /* cpuid */
7121 gen_update_cc_op(s);
7122 gen_jmp_im(pc_start - s->cs_base);
7123 gen_helper_cpuid(cpu_env);
7124 break;
7125 case 0xf4: /* hlt */
7126 if (s->cpl != 0) {
7127 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7128 } else {
7129 gen_update_cc_op(s);
7130 gen_jmp_im(pc_start - s->cs_base);
7131 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7132 s->is_jmp = DISAS_TB_JUMP;
7134 break;
7135 case 0x100:
7136 modrm = cpu_ldub_code(env, s->pc++);
7137 mod = (modrm >> 6) & 3;
7138 op = (modrm >> 3) & 7;
7139 switch(op) {
7140 case 0: /* sldt */
7141 if (!s->pe || s->vm86)
7142 goto illegal_op;
7143 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7144 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
7145 offsetof(CPUX86State, ldt.selector));
7146 ot = mod == 3 ? dflag : MO_16;
7147 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7148 break;
7149 case 2: /* lldt */
7150 if (!s->pe || s->vm86)
7151 goto illegal_op;
7152 if (s->cpl != 0) {
7153 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7154 } else {
7155 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7156 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7157 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
7158 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7160 break;
7161 case 1: /* str */
7162 if (!s->pe || s->vm86)
7163 goto illegal_op;
7164 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7165 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
7166 offsetof(CPUX86State, tr.selector));
7167 ot = mod == 3 ? dflag : MO_16;
7168 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7169 break;
7170 case 3: /* ltr */
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_TR_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_ltr(cpu_env, cpu_tmp2_i32);
7181 break;
7182 case 4: /* verr */
7183 case 5: /* verw */
7184 if (!s->pe || s->vm86)
7185 goto illegal_op;
7186 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7187 gen_update_cc_op(s);
7188 if (op == 4) {
7189 gen_helper_verr(cpu_env, cpu_T0);
7190 } else {
7191 gen_helper_verw(cpu_env, cpu_T0);
7193 set_cc_op(s, CC_OP_EFLAGS);
7194 break;
7195 default:
7196 goto unknown_op;
7198 break;
7200 case 0x101:
7201 modrm = cpu_ldub_code(env, s->pc++);
7202 switch (modrm) {
7203 CASE_MODRM_MEM_OP(0): /* sgdt */
7204 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7205 gen_lea_modrm(env, s, modrm);
7206 tcg_gen_ld32u_tl(cpu_T0,
7207 cpu_env, offsetof(CPUX86State, gdt.limit));
7208 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7209 gen_add_A0_im(s, 2);
7210 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7211 if (dflag == MO_16) {
7212 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7214 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7215 break;
7217 case 0xc8: /* monitor */
7218 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7219 goto illegal_op;
7221 gen_update_cc_op(s);
7222 gen_jmp_im(pc_start - s->cs_base);
7223 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7224 gen_extu(s->aflag, cpu_A0);
7225 gen_add_A0_ds_seg(s);
7226 gen_helper_monitor(cpu_env, cpu_A0);
7227 break;
7229 case 0xc9: /* mwait */
7230 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7231 goto illegal_op;
7233 gen_update_cc_op(s);
7234 gen_jmp_im(pc_start - s->cs_base);
7235 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7236 gen_eob(s);
7237 break;
7239 case 0xca: /* clac */
7240 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7241 || s->cpl != 0) {
7242 goto illegal_op;
7244 gen_helper_clac(cpu_env);
7245 gen_jmp_im(s->pc - s->cs_base);
7246 gen_eob(s);
7247 break;
7249 case 0xcb: /* stac */
7250 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7251 || s->cpl != 0) {
7252 goto illegal_op;
7254 gen_helper_stac(cpu_env);
7255 gen_jmp_im(s->pc - s->cs_base);
7256 gen_eob(s);
7257 break;
7259 CASE_MODRM_MEM_OP(1): /* sidt */
7260 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7261 gen_lea_modrm(env, s, modrm);
7262 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.limit));
7263 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7264 gen_add_A0_im(s, 2);
7265 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base));
7266 if (dflag == MO_16) {
7267 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7269 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7270 break;
7272 case 0xd0: /* xgetbv */
7273 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7274 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7275 | PREFIX_REPZ | PREFIX_REPNZ))) {
7276 goto illegal_op;
7278 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7279 gen_helper_xgetbv(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7280 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7281 break;
7283 case 0xd1: /* xsetbv */
7284 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7285 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7286 | PREFIX_REPZ | PREFIX_REPNZ))) {
7287 goto illegal_op;
7289 if (s->cpl != 0) {
7290 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7291 break;
7293 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7294 cpu_regs[R_EDX]);
7295 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7296 gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7297 /* End TB because translation flags may change. */
7298 gen_jmp_im(s->pc - s->cs_base);
7299 gen_eob(s);
7300 break;
7302 case 0xd8: /* VMRUN */
7303 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7304 goto illegal_op;
7306 if (s->cpl != 0) {
7307 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7308 break;
7310 gen_update_cc_op(s);
7311 gen_jmp_im(pc_start - s->cs_base);
7312 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7313 tcg_const_i32(s->pc - pc_start));
7314 tcg_gen_exit_tb(0);
7315 s->is_jmp = DISAS_TB_JUMP;
7316 break;
7318 case 0xd9: /* VMMCALL */
7319 if (!(s->flags & HF_SVME_MASK)) {
7320 goto illegal_op;
7322 gen_update_cc_op(s);
7323 gen_jmp_im(pc_start - s->cs_base);
7324 gen_helper_vmmcall(cpu_env);
7325 break;
7327 case 0xda: /* VMLOAD */
7328 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7329 goto illegal_op;
7331 if (s->cpl != 0) {
7332 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7333 break;
7335 gen_update_cc_op(s);
7336 gen_jmp_im(pc_start - s->cs_base);
7337 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7338 break;
7340 case 0xdb: /* VMSAVE */
7341 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7342 goto illegal_op;
7344 if (s->cpl != 0) {
7345 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7346 break;
7348 gen_update_cc_op(s);
7349 gen_jmp_im(pc_start - s->cs_base);
7350 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7351 break;
7353 case 0xdc: /* STGI */
7354 if ((!(s->flags & HF_SVME_MASK)
7355 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7356 || !s->pe) {
7357 goto illegal_op;
7359 if (s->cpl != 0) {
7360 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7361 break;
7363 gen_update_cc_op(s);
7364 gen_jmp_im(pc_start - s->cs_base);
7365 gen_helper_stgi(cpu_env);
7366 break;
7368 case 0xdd: /* CLGI */
7369 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7370 goto illegal_op;
7372 if (s->cpl != 0) {
7373 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7374 break;
7376 gen_update_cc_op(s);
7377 gen_jmp_im(pc_start - s->cs_base);
7378 gen_helper_clgi(cpu_env);
7379 break;
7381 case 0xde: /* SKINIT */
7382 if ((!(s->flags & HF_SVME_MASK)
7383 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7384 || !s->pe) {
7385 goto illegal_op;
7387 gen_update_cc_op(s);
7388 gen_jmp_im(pc_start - s->cs_base);
7389 gen_helper_skinit(cpu_env);
7390 break;
7392 case 0xdf: /* INVLPGA */
7393 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7394 goto illegal_op;
7396 if (s->cpl != 0) {
7397 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7398 break;
7400 gen_update_cc_op(s);
7401 gen_jmp_im(pc_start - s->cs_base);
7402 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7403 break;
7405 CASE_MODRM_MEM_OP(2): /* lgdt */
7406 if (s->cpl != 0) {
7407 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7408 break;
7410 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE);
7411 gen_lea_modrm(env, s, modrm);
7412 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7413 gen_add_A0_im(s, 2);
7414 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7415 if (dflag == MO_16) {
7416 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7418 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7419 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7420 break;
7422 CASE_MODRM_MEM_OP(3): /* lidt */
7423 if (s->cpl != 0) {
7424 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7425 break;
7427 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7428 gen_lea_modrm(env, s, modrm);
7429 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7430 gen_add_A0_im(s, 2);
7431 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7432 if (dflag == MO_16) {
7433 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7435 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base));
7436 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, idt.limit));
7437 break;
7439 CASE_MODRM_OP(4): /* smsw */
7440 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7441 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, cr[0]));
7442 if (CODE64(s)) {
7443 mod = (modrm >> 6) & 3;
7444 ot = (mod != 3 ? MO_16 : s->dflag);
7445 } else {
7446 ot = MO_16;
7448 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7449 break;
7450 case 0xee: /* rdpkru */
7451 if (prefixes & PREFIX_LOCK) {
7452 goto illegal_op;
7454 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7455 gen_helper_rdpkru(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7456 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7457 break;
7458 case 0xef: /* wrpkru */
7459 if (prefixes & PREFIX_LOCK) {
7460 goto illegal_op;
7462 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7463 cpu_regs[R_EDX]);
7464 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7465 gen_helper_wrpkru(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7466 break;
7467 CASE_MODRM_OP(6): /* lmsw */
7468 if (s->cpl != 0) {
7469 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7470 break;
7472 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7473 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7474 gen_helper_lmsw(cpu_env, cpu_T0);
7475 gen_jmp_im(s->pc - s->cs_base);
7476 gen_eob(s);
7477 break;
7479 CASE_MODRM_MEM_OP(7): /* invlpg */
7480 if (s->cpl != 0) {
7481 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7482 break;
7484 gen_update_cc_op(s);
7485 gen_jmp_im(pc_start - s->cs_base);
7486 gen_lea_modrm(env, s, modrm);
7487 gen_helper_invlpg(cpu_env, cpu_A0);
7488 gen_jmp_im(s->pc - s->cs_base);
7489 gen_eob(s);
7490 break;
7492 case 0xf8: /* swapgs */
7493 #ifdef TARGET_X86_64
7494 if (CODE64(s)) {
7495 if (s->cpl != 0) {
7496 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7497 } else {
7498 tcg_gen_mov_tl(cpu_T0, cpu_seg_base[R_GS]);
7499 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7500 offsetof(CPUX86State, kernelgsbase));
7501 tcg_gen_st_tl(cpu_T0, cpu_env,
7502 offsetof(CPUX86State, kernelgsbase));
7504 break;
7506 #endif
7507 goto illegal_op;
7509 case 0xf9: /* rdtscp */
7510 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7511 goto illegal_op;
7513 gen_update_cc_op(s);
7514 gen_jmp_im(pc_start - s->cs_base);
7515 if (s->tb->cflags & CF_USE_ICOUNT) {
7516 gen_io_start();
7518 gen_helper_rdtscp(cpu_env);
7519 if (s->tb->cflags & CF_USE_ICOUNT) {
7520 gen_io_end();
7521 gen_jmp(s, s->pc - s->cs_base);
7523 break;
7525 default:
7526 goto unknown_op;
7528 break;
7530 case 0x108: /* invd */
7531 case 0x109: /* wbinvd */
7532 if (s->cpl != 0) {
7533 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7534 } else {
7535 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7536 /* nothing to do */
7538 break;
7539 case 0x63: /* arpl or movslS (x86_64) */
7540 #ifdef TARGET_X86_64
7541 if (CODE64(s)) {
7542 int d_ot;
7543 /* d_ot is the size of destination */
7544 d_ot = dflag;
7546 modrm = cpu_ldub_code(env, s->pc++);
7547 reg = ((modrm >> 3) & 7) | rex_r;
7548 mod = (modrm >> 6) & 3;
7549 rm = (modrm & 7) | REX_B(s);
7551 if (mod == 3) {
7552 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
7553 /* sign extend */
7554 if (d_ot == MO_64) {
7555 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
7557 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7558 } else {
7559 gen_lea_modrm(env, s, modrm);
7560 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T0, cpu_A0);
7561 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7563 } else
7564 #endif
7566 TCGLabel *label1;
7567 TCGv t0, t1, t2, a0;
7569 if (!s->pe || s->vm86)
7570 goto illegal_op;
7571 t0 = tcg_temp_local_new();
7572 t1 = tcg_temp_local_new();
7573 t2 = tcg_temp_local_new();
7574 ot = MO_16;
7575 modrm = cpu_ldub_code(env, s->pc++);
7576 reg = (modrm >> 3) & 7;
7577 mod = (modrm >> 6) & 3;
7578 rm = modrm & 7;
7579 if (mod != 3) {
7580 gen_lea_modrm(env, s, modrm);
7581 gen_op_ld_v(s, ot, t0, cpu_A0);
7582 a0 = tcg_temp_local_new();
7583 tcg_gen_mov_tl(a0, cpu_A0);
7584 } else {
7585 gen_op_mov_v_reg(ot, t0, rm);
7586 TCGV_UNUSED(a0);
7588 gen_op_mov_v_reg(ot, t1, reg);
7589 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7590 tcg_gen_andi_tl(t1, t1, 3);
7591 tcg_gen_movi_tl(t2, 0);
7592 label1 = gen_new_label();
7593 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7594 tcg_gen_andi_tl(t0, t0, ~3);
7595 tcg_gen_or_tl(t0, t0, t1);
7596 tcg_gen_movi_tl(t2, CC_Z);
7597 gen_set_label(label1);
7598 if (mod != 3) {
7599 gen_op_st_v(s, ot, t0, a0);
7600 tcg_temp_free(a0);
7601 } else {
7602 gen_op_mov_reg_v(ot, rm, t0);
7604 gen_compute_eflags(s);
7605 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7606 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7607 tcg_temp_free(t0);
7608 tcg_temp_free(t1);
7609 tcg_temp_free(t2);
7611 break;
7612 case 0x102: /* lar */
7613 case 0x103: /* lsl */
7615 TCGLabel *label1;
7616 TCGv t0;
7617 if (!s->pe || s->vm86)
7618 goto illegal_op;
7619 ot = dflag != MO_16 ? MO_32 : MO_16;
7620 modrm = cpu_ldub_code(env, s->pc++);
7621 reg = ((modrm >> 3) & 7) | rex_r;
7622 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7623 t0 = tcg_temp_local_new();
7624 gen_update_cc_op(s);
7625 if (b == 0x102) {
7626 gen_helper_lar(t0, cpu_env, cpu_T0);
7627 } else {
7628 gen_helper_lsl(t0, cpu_env, cpu_T0);
7630 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7631 label1 = gen_new_label();
7632 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7633 gen_op_mov_reg_v(ot, reg, t0);
7634 gen_set_label(label1);
7635 set_cc_op(s, CC_OP_EFLAGS);
7636 tcg_temp_free(t0);
7638 break;
7639 case 0x118:
7640 modrm = cpu_ldub_code(env, s->pc++);
7641 mod = (modrm >> 6) & 3;
7642 op = (modrm >> 3) & 7;
7643 switch(op) {
7644 case 0: /* prefetchnta */
7645 case 1: /* prefetchnt0 */
7646 case 2: /* prefetchnt0 */
7647 case 3: /* prefetchnt0 */
7648 if (mod == 3)
7649 goto illegal_op;
7650 gen_nop_modrm(env, s, modrm);
7651 /* nothing more to do */
7652 break;
7653 default: /* nop (multi byte) */
7654 gen_nop_modrm(env, s, modrm);
7655 break;
7657 break;
7658 case 0x11a:
7659 modrm = cpu_ldub_code(env, s->pc++);
7660 if (s->flags & HF_MPX_EN_MASK) {
7661 mod = (modrm >> 6) & 3;
7662 reg = ((modrm >> 3) & 7) | rex_r;
7663 if (prefixes & PREFIX_REPZ) {
7664 /* bndcl */
7665 if (reg >= 4
7666 || (prefixes & PREFIX_LOCK)
7667 || s->aflag == MO_16) {
7668 goto illegal_op;
7670 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7671 } else if (prefixes & PREFIX_REPNZ) {
7672 /* bndcu */
7673 if (reg >= 4
7674 || (prefixes & PREFIX_LOCK)
7675 || s->aflag == MO_16) {
7676 goto illegal_op;
7678 TCGv_i64 notu = tcg_temp_new_i64();
7679 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7680 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7681 tcg_temp_free_i64(notu);
7682 } else if (prefixes & PREFIX_DATA) {
7683 /* bndmov -- from reg/mem */
7684 if (reg >= 4 || s->aflag == MO_16) {
7685 goto illegal_op;
7687 if (mod == 3) {
7688 int reg2 = (modrm & 7) | REX_B(s);
7689 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7690 goto illegal_op;
7692 if (s->flags & HF_MPX_IU_MASK) {
7693 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7694 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7696 } else {
7697 gen_lea_modrm(env, s, modrm);
7698 if (CODE64(s)) {
7699 tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0,
7700 s->mem_index, MO_LEQ);
7701 tcg_gen_addi_tl(cpu_A0, cpu_A0, 8);
7702 tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0,
7703 s->mem_index, MO_LEQ);
7704 } else {
7705 tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0,
7706 s->mem_index, MO_LEUL);
7707 tcg_gen_addi_tl(cpu_A0, cpu_A0, 4);
7708 tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0,
7709 s->mem_index, MO_LEUL);
7711 /* bnd registers are now in-use */
7712 gen_set_hflag(s, HF_MPX_IU_MASK);
7714 } else if (mod != 3) {
7715 /* bndldx */
7716 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7717 if (reg >= 4
7718 || (prefixes & PREFIX_LOCK)
7719 || s->aflag == MO_16
7720 || a.base < -1) {
7721 goto illegal_op;
7723 if (a.base >= 0) {
7724 tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp);
7725 } else {
7726 tcg_gen_movi_tl(cpu_A0, 0);
7728 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
7729 if (a.index >= 0) {
7730 tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]);
7731 } else {
7732 tcg_gen_movi_tl(cpu_T0, 0);
7734 if (CODE64(s)) {
7735 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, cpu_A0, cpu_T0);
7736 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7737 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7738 } else {
7739 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, cpu_A0, cpu_T0);
7740 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7741 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7743 gen_set_hflag(s, HF_MPX_IU_MASK);
7746 gen_nop_modrm(env, s, modrm);
7747 break;
7748 case 0x11b:
7749 modrm = cpu_ldub_code(env, s->pc++);
7750 if (s->flags & HF_MPX_EN_MASK) {
7751 mod = (modrm >> 6) & 3;
7752 reg = ((modrm >> 3) & 7) | rex_r;
7753 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7754 /* bndmk */
7755 if (reg >= 4
7756 || (prefixes & PREFIX_LOCK)
7757 || s->aflag == MO_16) {
7758 goto illegal_op;
7760 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7761 if (a.base >= 0) {
7762 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7763 if (!CODE64(s)) {
7764 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7766 } else if (a.base == -1) {
7767 /* no base register has lower bound of 0 */
7768 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7769 } else {
7770 /* rip-relative generates #ud */
7771 goto illegal_op;
7773 tcg_gen_not_tl(cpu_A0, gen_lea_modrm_1(a));
7774 if (!CODE64(s)) {
7775 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
7777 tcg_gen_extu_tl_i64(cpu_bndu[reg], cpu_A0);
7778 /* bnd registers are now in-use */
7779 gen_set_hflag(s, HF_MPX_IU_MASK);
7780 break;
7781 } else if (prefixes & PREFIX_REPNZ) {
7782 /* bndcn */
7783 if (reg >= 4
7784 || (prefixes & PREFIX_LOCK)
7785 || s->aflag == MO_16) {
7786 goto illegal_op;
7788 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
7789 } else if (prefixes & PREFIX_DATA) {
7790 /* bndmov -- to reg/mem */
7791 if (reg >= 4 || s->aflag == MO_16) {
7792 goto illegal_op;
7794 if (mod == 3) {
7795 int reg2 = (modrm & 7) | REX_B(s);
7796 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7797 goto illegal_op;
7799 if (s->flags & HF_MPX_IU_MASK) {
7800 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7801 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7803 } else {
7804 gen_lea_modrm(env, s, modrm);
7805 if (CODE64(s)) {
7806 tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0,
7807 s->mem_index, MO_LEQ);
7808 tcg_gen_addi_tl(cpu_A0, cpu_A0, 8);
7809 tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0,
7810 s->mem_index, MO_LEQ);
7811 } else {
7812 tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0,
7813 s->mem_index, MO_LEUL);
7814 tcg_gen_addi_tl(cpu_A0, cpu_A0, 4);
7815 tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0,
7816 s->mem_index, MO_LEUL);
7819 } else if (mod != 3) {
7820 /* bndstx */
7821 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7822 if (reg >= 4
7823 || (prefixes & PREFIX_LOCK)
7824 || s->aflag == MO_16
7825 || a.base < -1) {
7826 goto illegal_op;
7828 if (a.base >= 0) {
7829 tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp);
7830 } else {
7831 tcg_gen_movi_tl(cpu_A0, 0);
7833 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
7834 if (a.index >= 0) {
7835 tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]);
7836 } else {
7837 tcg_gen_movi_tl(cpu_T0, 0);
7839 if (CODE64(s)) {
7840 gen_helper_bndstx64(cpu_env, cpu_A0, cpu_T0,
7841 cpu_bndl[reg], cpu_bndu[reg]);
7842 } else {
7843 gen_helper_bndstx32(cpu_env, cpu_A0, cpu_T0,
7844 cpu_bndl[reg], cpu_bndu[reg]);
7848 gen_nop_modrm(env, s, modrm);
7849 break;
7850 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
7851 modrm = cpu_ldub_code(env, s->pc++);
7852 gen_nop_modrm(env, s, modrm);
7853 break;
7854 case 0x120: /* mov reg, crN */
7855 case 0x122: /* mov crN, reg */
7856 if (s->cpl != 0) {
7857 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7858 } else {
7859 modrm = cpu_ldub_code(env, s->pc++);
7860 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7861 * AMD documentation (24594.pdf) and testing of
7862 * intel 386 and 486 processors all show that the mod bits
7863 * are assumed to be 1's, regardless of actual values.
7865 rm = (modrm & 7) | REX_B(s);
7866 reg = ((modrm >> 3) & 7) | rex_r;
7867 if (CODE64(s))
7868 ot = MO_64;
7869 else
7870 ot = MO_32;
7871 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7872 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7873 reg = 8;
7875 switch(reg) {
7876 case 0:
7877 case 2:
7878 case 3:
7879 case 4:
7880 case 8:
7881 gen_update_cc_op(s);
7882 gen_jmp_im(pc_start - s->cs_base);
7883 if (b & 2) {
7884 gen_op_mov_v_reg(ot, cpu_T0, rm);
7885 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7886 cpu_T0);
7887 gen_jmp_im(s->pc - s->cs_base);
7888 gen_eob(s);
7889 } else {
7890 gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg));
7891 gen_op_mov_reg_v(ot, rm, cpu_T0);
7893 break;
7894 default:
7895 goto unknown_op;
7898 break;
7899 case 0x121: /* mov reg, drN */
7900 case 0x123: /* mov drN, reg */
7901 if (s->cpl != 0) {
7902 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7903 } else {
7904 modrm = cpu_ldub_code(env, s->pc++);
7905 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7906 * AMD documentation (24594.pdf) and testing of
7907 * intel 386 and 486 processors all show that the mod bits
7908 * are assumed to be 1's, regardless of actual values.
7910 rm = (modrm & 7) | REX_B(s);
7911 reg = ((modrm >> 3) & 7) | rex_r;
7912 if (CODE64(s))
7913 ot = MO_64;
7914 else
7915 ot = MO_32;
7916 if (reg >= 8) {
7917 goto illegal_op;
7919 if (b & 2) {
7920 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7921 gen_op_mov_v_reg(ot, cpu_T0, rm);
7922 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7923 gen_helper_set_dr(cpu_env, cpu_tmp2_i32, cpu_T0);
7924 gen_jmp_im(s->pc - s->cs_base);
7925 gen_eob(s);
7926 } else {
7927 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7928 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7929 gen_helper_get_dr(cpu_T0, cpu_env, cpu_tmp2_i32);
7930 gen_op_mov_reg_v(ot, rm, cpu_T0);
7933 break;
7934 case 0x106: /* clts */
7935 if (s->cpl != 0) {
7936 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7937 } else {
7938 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7939 gen_helper_clts(cpu_env);
7940 /* abort block because static cpu state changed */
7941 gen_jmp_im(s->pc - s->cs_base);
7942 gen_eob(s);
7944 break;
7945 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
7946 case 0x1c3: /* MOVNTI reg, mem */
7947 if (!(s->cpuid_features & CPUID_SSE2))
7948 goto illegal_op;
7949 ot = mo_64_32(dflag);
7950 modrm = cpu_ldub_code(env, s->pc++);
7951 mod = (modrm >> 6) & 3;
7952 if (mod == 3)
7953 goto illegal_op;
7954 reg = ((modrm >> 3) & 7) | rex_r;
7955 /* generate a generic store */
7956 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
7957 break;
7958 case 0x1ae:
7959 modrm = cpu_ldub_code(env, s->pc++);
7960 switch (modrm) {
7961 CASE_MODRM_MEM_OP(0): /* fxsave */
7962 if (!(s->cpuid_features & CPUID_FXSR)
7963 || (prefixes & PREFIX_LOCK)) {
7964 goto illegal_op;
7966 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7967 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7968 break;
7970 gen_lea_modrm(env, s, modrm);
7971 gen_helper_fxsave(cpu_env, cpu_A0);
7972 break;
7974 CASE_MODRM_MEM_OP(1): /* fxrstor */
7975 if (!(s->cpuid_features & CPUID_FXSR)
7976 || (prefixes & PREFIX_LOCK)) {
7977 goto illegal_op;
7979 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7980 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7981 break;
7983 gen_lea_modrm(env, s, modrm);
7984 gen_helper_fxrstor(cpu_env, cpu_A0);
7985 break;
7987 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
7988 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
7989 goto illegal_op;
7991 if (s->flags & HF_TS_MASK) {
7992 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7993 break;
7995 gen_lea_modrm(env, s, modrm);
7996 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, s->mem_index, MO_LEUL);
7997 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
7998 break;
8000 CASE_MODRM_MEM_OP(3): /* stmxcsr */
8001 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8002 goto illegal_op;
8004 if (s->flags & HF_TS_MASK) {
8005 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8006 break;
8008 gen_lea_modrm(env, s, modrm);
8009 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, mxcsr));
8010 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
8011 break;
8013 CASE_MODRM_MEM_OP(4): /* xsave */
8014 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8015 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8016 | PREFIX_REPZ | PREFIX_REPNZ))) {
8017 goto illegal_op;
8019 gen_lea_modrm(env, s, modrm);
8020 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8021 cpu_regs[R_EDX]);
8022 gen_helper_xsave(cpu_env, cpu_A0, cpu_tmp1_i64);
8023 break;
8025 CASE_MODRM_MEM_OP(5): /* xrstor */
8026 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8027 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8028 | PREFIX_REPZ | PREFIX_REPNZ))) {
8029 goto illegal_op;
8031 gen_lea_modrm(env, s, modrm);
8032 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8033 cpu_regs[R_EDX]);
8034 gen_helper_xrstor(cpu_env, cpu_A0, cpu_tmp1_i64);
8035 /* XRSTOR is how MPX is enabled, which changes how
8036 we translate. Thus we need to end the TB. */
8037 gen_update_cc_op(s);
8038 gen_jmp_im(s->pc - s->cs_base);
8039 gen_eob(s);
8040 break;
8042 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
8043 if (prefixes & PREFIX_LOCK) {
8044 goto illegal_op;
8046 if (prefixes & PREFIX_DATA) {
8047 /* clwb */
8048 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8049 goto illegal_op;
8051 gen_nop_modrm(env, s, modrm);
8052 } else {
8053 /* xsaveopt */
8054 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8055 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8056 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8057 goto illegal_op;
8059 gen_lea_modrm(env, s, modrm);
8060 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8061 cpu_regs[R_EDX]);
8062 gen_helper_xsaveopt(cpu_env, cpu_A0, cpu_tmp1_i64);
8064 break;
8066 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
8067 if (prefixes & PREFIX_LOCK) {
8068 goto illegal_op;
8070 if (prefixes & PREFIX_DATA) {
8071 /* clflushopt */
8072 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8073 goto illegal_op;
8075 } else {
8076 /* clflush */
8077 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8078 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8079 goto illegal_op;
8082 gen_nop_modrm(env, s, modrm);
8083 break;
8085 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
8086 case 0xc8 ... 0xc8: /* rdgsbase (f3 0f ae /1) */
8087 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
8088 case 0xd8 ... 0xd8: /* wrgsbase (f3 0f ae /3) */
8089 if (CODE64(s)
8090 && (prefixes & PREFIX_REPZ)
8091 && !(prefixes & PREFIX_LOCK)
8092 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8093 TCGv base, treg, src, dst;
8095 /* Preserve hflags bits by testing CR4 at runtime. */
8096 tcg_gen_movi_i32(cpu_tmp2_i32, CR4_FSGSBASE_MASK);
8097 gen_helper_cr4_testbit(cpu_env, cpu_tmp2_i32);
8099 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8100 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8102 if (modrm & 0x10) {
8103 /* wr*base */
8104 dst = base, src = treg;
8105 } else {
8106 /* rd*base */
8107 dst = treg, src = base;
8110 if (s->dflag == MO_32) {
8111 tcg_gen_ext32u_tl(dst, src);
8112 } else {
8113 tcg_gen_mov_tl(dst, src);
8115 break;
8117 goto unknown_op;
8119 case 0xf8: /* sfence / pcommit */
8120 if (prefixes & PREFIX_DATA) {
8121 /* pcommit */
8122 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8123 || (prefixes & PREFIX_LOCK)) {
8124 goto illegal_op;
8126 break;
8128 /* fallthru */
8129 case 0xf9 ... 0xff: /* sfence */
8130 if (!(s->cpuid_features & CPUID_SSE)
8131 || (prefixes & PREFIX_LOCK)) {
8132 goto illegal_op;
8134 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8135 break;
8136 case 0xe8 ... 0xef: /* lfence */
8137 if (!(s->cpuid_features & CPUID_SSE)
8138 || (prefixes & PREFIX_LOCK)) {
8139 goto illegal_op;
8141 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8142 break;
8143 case 0xf0 ... 0xf7: /* mfence */
8144 if (!(s->cpuid_features & CPUID_SSE2)
8145 || (prefixes & PREFIX_LOCK)) {
8146 goto illegal_op;
8148 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8149 break;
8151 default:
8152 goto unknown_op;
8154 break;
8156 case 0x10d: /* 3DNow! prefetch(w) */
8157 modrm = cpu_ldub_code(env, s->pc++);
8158 mod = (modrm >> 6) & 3;
8159 if (mod == 3)
8160 goto illegal_op;
8161 gen_nop_modrm(env, s, modrm);
8162 break;
8163 case 0x1aa: /* rsm */
8164 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8165 if (!(s->flags & HF_SMM_MASK))
8166 goto illegal_op;
8167 gen_update_cc_op(s);
8168 gen_jmp_im(s->pc - s->cs_base);
8169 gen_helper_rsm(cpu_env);
8170 gen_eob(s);
8171 break;
8172 case 0x1b8: /* SSE4.2 popcnt */
8173 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8174 PREFIX_REPZ)
8175 goto illegal_op;
8176 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8177 goto illegal_op;
8179 modrm = cpu_ldub_code(env, s->pc++);
8180 reg = ((modrm >> 3) & 7) | rex_r;
8182 if (s->prefix & PREFIX_DATA) {
8183 ot = MO_16;
8184 } else {
8185 ot = mo_64_32(dflag);
8188 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8189 gen_helper_popcnt(cpu_T0, cpu_env, cpu_T0, tcg_const_i32(ot));
8190 gen_op_mov_reg_v(ot, reg, cpu_T0);
8192 set_cc_op(s, CC_OP_EFLAGS);
8193 break;
8194 case 0x10e ... 0x10f:
8195 /* 3DNow! instructions, ignore prefixes */
8196 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8197 case 0x110 ... 0x117:
8198 case 0x128 ... 0x12f:
8199 case 0x138 ... 0x13a:
8200 case 0x150 ... 0x179:
8201 case 0x17c ... 0x17f:
8202 case 0x1c2:
8203 case 0x1c4 ... 0x1c6:
8204 case 0x1d0 ... 0x1fe:
8205 gen_sse(env, s, b, pc_start, rex_r);
8206 break;
8207 default:
8208 goto unknown_op;
8210 return s->pc;
8211 illegal_op:
8212 gen_illegal_opcode(s);
8213 return s->pc;
8214 unknown_op:
8215 gen_unknown_opcode(env, s);
8216 return s->pc;
8219 void tcg_x86_init(void)
8221 static const char reg_names[CPU_NB_REGS][4] = {
8222 #ifdef TARGET_X86_64
8223 [R_EAX] = "rax",
8224 [R_EBX] = "rbx",
8225 [R_ECX] = "rcx",
8226 [R_EDX] = "rdx",
8227 [R_ESI] = "rsi",
8228 [R_EDI] = "rdi",
8229 [R_EBP] = "rbp",
8230 [R_ESP] = "rsp",
8231 [8] = "r8",
8232 [9] = "r9",
8233 [10] = "r10",
8234 [11] = "r11",
8235 [12] = "r12",
8236 [13] = "r13",
8237 [14] = "r14",
8238 [15] = "r15",
8239 #else
8240 [R_EAX] = "eax",
8241 [R_EBX] = "ebx",
8242 [R_ECX] = "ecx",
8243 [R_EDX] = "edx",
8244 [R_ESI] = "esi",
8245 [R_EDI] = "edi",
8246 [R_EBP] = "ebp",
8247 [R_ESP] = "esp",
8248 #endif
8250 static const char seg_base_names[6][8] = {
8251 [R_CS] = "cs_base",
8252 [R_DS] = "ds_base",
8253 [R_ES] = "es_base",
8254 [R_FS] = "fs_base",
8255 [R_GS] = "gs_base",
8256 [R_SS] = "ss_base",
8258 static const char bnd_regl_names[4][8] = {
8259 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8261 static const char bnd_regu_names[4][8] = {
8262 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8264 int i;
8265 static bool initialized;
8267 if (initialized) {
8268 return;
8270 initialized = true;
8272 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8273 tcg_ctx.tcg_env = cpu_env;
8274 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8275 offsetof(CPUX86State, cc_op), "cc_op");
8276 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8277 "cc_dst");
8278 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8279 "cc_src");
8280 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8281 "cc_src2");
8283 for (i = 0; i < CPU_NB_REGS; ++i) {
8284 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8285 offsetof(CPUX86State, regs[i]),
8286 reg_names[i]);
8289 for (i = 0; i < 6; ++i) {
8290 cpu_seg_base[i]
8291 = tcg_global_mem_new(cpu_env,
8292 offsetof(CPUX86State, segs[i].base),
8293 seg_base_names[i]);
8296 for (i = 0; i < 4; ++i) {
8297 cpu_bndl[i]
8298 = tcg_global_mem_new_i64(cpu_env,
8299 offsetof(CPUX86State, bnd_regs[i].lb),
8300 bnd_regl_names[i]);
8301 cpu_bndu[i]
8302 = tcg_global_mem_new_i64(cpu_env,
8303 offsetof(CPUX86State, bnd_regs[i].ub),
8304 bnd_regu_names[i]);
8308 /* generate intermediate code for basic block 'tb'. */
8309 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
8311 X86CPU *cpu = x86_env_get_cpu(env);
8312 CPUState *cs = CPU(cpu);
8313 DisasContext dc1, *dc = &dc1;
8314 target_ulong pc_ptr;
8315 uint32_t flags;
8316 target_ulong pc_start;
8317 target_ulong cs_base;
8318 int num_insns;
8319 int max_insns;
8321 /* generate intermediate code */
8322 pc_start = tb->pc;
8323 cs_base = tb->cs_base;
8324 flags = tb->flags;
8326 dc->pe = (flags >> HF_PE_SHIFT) & 1;
8327 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8328 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8329 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8330 dc->f_st = 0;
8331 dc->vm86 = (flags >> VM_SHIFT) & 1;
8332 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8333 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8334 dc->tf = (flags >> TF_SHIFT) & 1;
8335 dc->singlestep_enabled = cs->singlestep_enabled;
8336 dc->cc_op = CC_OP_DYNAMIC;
8337 dc->cc_op_dirty = false;
8338 dc->cs_base = cs_base;
8339 dc->tb = tb;
8340 dc->popl_esp_hack = 0;
8341 /* select memory access functions */
8342 dc->mem_index = 0;
8343 #ifdef CONFIG_SOFTMMU
8344 dc->mem_index = cpu_mmu_index(env, false);
8345 #endif
8346 dc->cpuid_features = env->features[FEAT_1_EDX];
8347 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8348 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8349 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8350 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8351 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8352 #ifdef TARGET_X86_64
8353 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8354 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8355 #endif
8356 dc->flags = flags;
8357 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
8358 (flags & HF_INHIBIT_IRQ_MASK));
8359 /* Do not optimize repz jumps at all in icount mode, because
8360 rep movsS instructions are execured with different paths
8361 in !repz_opt and repz_opt modes. The first one was used
8362 always except single step mode. And this setting
8363 disables jumps optimization and control paths become
8364 equivalent in run and single step modes.
8365 Now there will be no jump optimization for repz in
8366 record/replay modes and there will always be an
8367 additional step for ecx=0 when icount is enabled.
8369 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
8370 #if 0
8371 /* check addseg logic */
8372 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8373 printf("ERROR addseg\n");
8374 #endif
8376 cpu_T0 = tcg_temp_new();
8377 cpu_T1 = tcg_temp_new();
8378 cpu_A0 = tcg_temp_new();
8380 cpu_tmp0 = tcg_temp_new();
8381 cpu_tmp1_i64 = tcg_temp_new_i64();
8382 cpu_tmp2_i32 = tcg_temp_new_i32();
8383 cpu_tmp3_i32 = tcg_temp_new_i32();
8384 cpu_tmp4 = tcg_temp_new();
8385 cpu_ptr0 = tcg_temp_new_ptr();
8386 cpu_ptr1 = tcg_temp_new_ptr();
8387 cpu_cc_srcT = tcg_temp_local_new();
8389 dc->is_jmp = DISAS_NEXT;
8390 pc_ptr = pc_start;
8391 num_insns = 0;
8392 max_insns = tb->cflags & CF_COUNT_MASK;
8393 if (max_insns == 0) {
8394 max_insns = CF_COUNT_MASK;
8396 if (max_insns > TCG_MAX_INSNS) {
8397 max_insns = TCG_MAX_INSNS;
8400 gen_tb_start(tb);
8401 for(;;) {
8402 tcg_gen_insn_start(pc_ptr, dc->cc_op);
8403 num_insns++;
8405 /* If RF is set, suppress an internally generated breakpoint. */
8406 if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
8407 tb->flags & HF_RF_MASK
8408 ? BP_GDB : BP_ANY))) {
8409 gen_debug(dc, pc_ptr - dc->cs_base);
8410 /* The address covered by the breakpoint must be included in
8411 [tb->pc, tb->pc + tb->size) in order to for it to be
8412 properly cleared -- thus we increment the PC here so that
8413 the logic setting tb->size below does the right thing. */
8414 pc_ptr += 1;
8415 goto done_generating;
8417 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
8418 gen_io_start();
8421 pc_ptr = disas_insn(env, dc, pc_ptr);
8422 /* stop translation if indicated */
8423 if (dc->is_jmp)
8424 break;
8425 /* if single step mode, we generate only one instruction and
8426 generate an exception */
8427 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8428 the flag and abort the translation to give the irqs a
8429 change to be happen */
8430 if (dc->tf || dc->singlestep_enabled ||
8431 (flags & HF_INHIBIT_IRQ_MASK)) {
8432 gen_jmp_im(pc_ptr - dc->cs_base);
8433 gen_eob(dc);
8434 break;
8436 /* Do not cross the boundary of the pages in icount mode,
8437 it can cause an exception. Do it only when boundary is
8438 crossed by the first instruction in the block.
8439 If current instruction already crossed the bound - it's ok,
8440 because an exception hasn't stopped this code.
8442 if ((tb->cflags & CF_USE_ICOUNT)
8443 && ((pc_ptr & TARGET_PAGE_MASK)
8444 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
8445 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
8446 gen_jmp_im(pc_ptr - dc->cs_base);
8447 gen_eob(dc);
8448 break;
8450 /* if too long translation, stop generation too */
8451 if (tcg_op_buf_full() ||
8452 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8453 num_insns >= max_insns) {
8454 gen_jmp_im(pc_ptr - dc->cs_base);
8455 gen_eob(dc);
8456 break;
8458 if (singlestep) {
8459 gen_jmp_im(pc_ptr - dc->cs_base);
8460 gen_eob(dc);
8461 break;
8464 if (tb->cflags & CF_LAST_IO)
8465 gen_io_end();
8466 done_generating:
8467 gen_tb_end(tb, num_insns);
8469 #ifdef DEBUG_DISAS
8470 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
8471 && qemu_log_in_addr_range(pc_start)) {
8472 int disas_flags;
8473 qemu_log("----------------\n");
8474 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8475 #ifdef TARGET_X86_64
8476 if (dc->code64)
8477 disas_flags = 2;
8478 else
8479 #endif
8480 disas_flags = !dc->code32;
8481 log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
8482 qemu_log("\n");
8484 #endif
8486 tb->size = pc_ptr - pc_start;
8487 tb->icount = num_insns;
8490 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8491 target_ulong *data)
8493 int cc_op = data[1];
8494 env->eip = data[0] - tb->cs_base;
8495 if (cc_op != CC_OP_DYNAMIC) {
8496 env->cc_op = cc_op;