target-i386: Deconstruct the cpu_T array
[qemu/ar7.git] / target-i386 / translate.c
blobc8e2799269f8937600d85049fd770ded5483d81d
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 "tcg-op.h"
25 #include "exec/cpu_ldst.h"
27 #include "exec/helper-proto.h"
28 #include "exec/helper-gen.h"
30 #include "trace-tcg.h"
31 #include "exec/log.h"
34 #define PREFIX_REPZ 0x01
35 #define PREFIX_REPNZ 0x02
36 #define PREFIX_LOCK 0x04
37 #define PREFIX_DATA 0x08
38 #define PREFIX_ADR 0x10
39 #define PREFIX_VEX 0x20
41 #ifdef TARGET_X86_64
42 #define CODE64(s) ((s)->code64)
43 #define REX_X(s) ((s)->rex_x)
44 #define REX_B(s) ((s)->rex_b)
45 #else
46 #define CODE64(s) 0
47 #define REX_X(s) 0
48 #define REX_B(s) 0
49 #endif
51 #ifdef TARGET_X86_64
52 # define ctztl ctz64
53 # define clztl clz64
54 #else
55 # define ctztl ctz32
56 # define clztl clz32
57 #endif
59 //#define MACRO_TEST 1
61 /* global register indexes */
62 static TCGv_ptr cpu_env;
63 static TCGv cpu_A0;
64 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
65 static TCGv_i32 cpu_cc_op;
66 static TCGv cpu_regs[CPU_NB_REGS];
67 static TCGv cpu_seg_base[6];
68 /* local temps */
69 static TCGv cpu_T0, cpu_T1;
70 /* local register indexes (only used inside old micro ops) */
71 static TCGv cpu_tmp0, cpu_tmp4;
72 static TCGv_ptr cpu_ptr0, cpu_ptr1;
73 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
74 static TCGv_i64 cpu_tmp1_i64;
76 #include "exec/gen-icount.h"
78 #ifdef TARGET_X86_64
79 static int x86_64_hregs;
80 #endif
82 typedef struct DisasContext {
83 /* current insn context */
84 int override; /* -1 if no override */
85 int prefix;
86 TCGMemOp aflag;
87 TCGMemOp dflag;
88 target_ulong pc; /* pc = eip + cs_base */
89 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
90 static state change (stop translation) */
91 /* current block context */
92 target_ulong cs_base; /* base of CS segment */
93 int pe; /* protected mode */
94 int code32; /* 32 bit code segment */
95 #ifdef TARGET_X86_64
96 int lma; /* long mode active */
97 int code64; /* 64 bit code segment */
98 int rex_x, rex_b;
99 #endif
100 int vex_l; /* vex vector length */
101 int vex_v; /* vex vvvv register, without 1's compliment. */
102 int ss32; /* 32 bit stack segment */
103 CCOp cc_op; /* current CC operation */
104 bool cc_op_dirty;
105 int addseg; /* non zero if either DS/ES/SS have a non zero base */
106 int f_st; /* currently unused */
107 int vm86; /* vm86 mode */
108 int cpl;
109 int iopl;
110 int tf; /* TF cpu flag */
111 int singlestep_enabled; /* "hardware" single step enabled */
112 int jmp_opt; /* use direct block chaining for direct jumps */
113 int repz_opt; /* optimize jumps within repz instructions */
114 int mem_index; /* select memory access functions */
115 uint64_t flags; /* all execution flags */
116 struct TranslationBlock *tb;
117 int popl_esp_hack; /* for correct popl with esp base handling */
118 int rip_offset; /* only used in x86_64, but left for simplicity */
119 int cpuid_features;
120 int cpuid_ext_features;
121 int cpuid_ext2_features;
122 int cpuid_ext3_features;
123 int cpuid_7_0_ebx_features;
124 } DisasContext;
126 static void gen_eob(DisasContext *s);
127 static void gen_jmp(DisasContext *s, target_ulong eip);
128 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
129 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d);
131 /* i386 arith/logic operations */
132 enum {
133 OP_ADDL,
134 OP_ORL,
135 OP_ADCL,
136 OP_SBBL,
137 OP_ANDL,
138 OP_SUBL,
139 OP_XORL,
140 OP_CMPL,
143 /* i386 shift ops */
144 enum {
145 OP_ROL,
146 OP_ROR,
147 OP_RCL,
148 OP_RCR,
149 OP_SHL,
150 OP_SHR,
151 OP_SHL1, /* undocumented */
152 OP_SAR = 7,
155 enum {
156 JCC_O,
157 JCC_B,
158 JCC_Z,
159 JCC_BE,
160 JCC_S,
161 JCC_P,
162 JCC_L,
163 JCC_LE,
166 enum {
167 /* I386 int registers */
168 OR_EAX, /* MUST be even numbered */
169 OR_ECX,
170 OR_EDX,
171 OR_EBX,
172 OR_ESP,
173 OR_EBP,
174 OR_ESI,
175 OR_EDI,
177 OR_TMP0 = 16, /* temporary operand register */
178 OR_TMP1,
179 OR_A0, /* temporary register used when doing address evaluation */
182 enum {
183 USES_CC_DST = 1,
184 USES_CC_SRC = 2,
185 USES_CC_SRC2 = 4,
186 USES_CC_SRCT = 8,
189 /* Bit set if the global variable is live after setting CC_OP to X. */
190 static const uint8_t cc_op_live[CC_OP_NB] = {
191 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
192 [CC_OP_EFLAGS] = USES_CC_SRC,
193 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
194 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
195 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
196 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
197 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
198 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
199 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
200 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
201 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
202 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
203 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
204 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
205 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
206 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
207 [CC_OP_CLR] = 0,
210 static void set_cc_op(DisasContext *s, CCOp op)
212 int dead;
214 if (s->cc_op == op) {
215 return;
218 /* Discard CC computation that will no longer be used. */
219 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
220 if (dead & USES_CC_DST) {
221 tcg_gen_discard_tl(cpu_cc_dst);
223 if (dead & USES_CC_SRC) {
224 tcg_gen_discard_tl(cpu_cc_src);
226 if (dead & USES_CC_SRC2) {
227 tcg_gen_discard_tl(cpu_cc_src2);
229 if (dead & USES_CC_SRCT) {
230 tcg_gen_discard_tl(cpu_cc_srcT);
233 if (op == CC_OP_DYNAMIC) {
234 /* The DYNAMIC setting is translator only, and should never be
235 stored. Thus we always consider it clean. */
236 s->cc_op_dirty = false;
237 } else {
238 /* Discard any computed CC_OP value (see shifts). */
239 if (s->cc_op == CC_OP_DYNAMIC) {
240 tcg_gen_discard_i32(cpu_cc_op);
242 s->cc_op_dirty = true;
244 s->cc_op = op;
247 static void gen_update_cc_op(DisasContext *s)
249 if (s->cc_op_dirty) {
250 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
251 s->cc_op_dirty = false;
255 #ifdef TARGET_X86_64
257 #define NB_OP_SIZES 4
259 #else /* !TARGET_X86_64 */
261 #define NB_OP_SIZES 3
263 #endif /* !TARGET_X86_64 */
265 #if defined(HOST_WORDS_BIGENDIAN)
266 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
267 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
268 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
269 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
270 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
271 #else
272 #define REG_B_OFFSET 0
273 #define REG_H_OFFSET 1
274 #define REG_W_OFFSET 0
275 #define REG_L_OFFSET 0
276 #define REG_LH_OFFSET 4
277 #endif
279 /* In instruction encodings for byte register accesses the
280 * register number usually indicates "low 8 bits of register N";
281 * however there are some special cases where N 4..7 indicates
282 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
283 * true for this special case, false otherwise.
285 static inline bool byte_reg_is_xH(int reg)
287 if (reg < 4) {
288 return false;
290 #ifdef TARGET_X86_64
291 if (reg >= 8 || x86_64_hregs) {
292 return false;
294 #endif
295 return true;
298 /* Select the size of a push/pop operation. */
299 static inline TCGMemOp mo_pushpop(DisasContext *s, TCGMemOp ot)
301 if (CODE64(s)) {
302 return ot == MO_16 ? MO_16 : MO_64;
303 } else {
304 return ot;
308 /* Select the size of the stack pointer. */
309 static inline TCGMemOp mo_stacksize(DisasContext *s)
311 return CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
314 /* Select only size 64 else 32. Used for SSE operand sizes. */
315 static inline TCGMemOp mo_64_32(TCGMemOp ot)
317 #ifdef TARGET_X86_64
318 return ot == MO_64 ? MO_64 : MO_32;
319 #else
320 return MO_32;
321 #endif
324 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
325 byte vs word opcodes. */
326 static inline TCGMemOp mo_b_d(int b, TCGMemOp ot)
328 return b & 1 ? ot : MO_8;
331 /* Select size 8 if lsb of B is clear, else OT capped at 32.
332 Used for decoding operand size of port opcodes. */
333 static inline TCGMemOp mo_b_d32(int b, TCGMemOp ot)
335 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
338 static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
340 switch(ot) {
341 case MO_8:
342 if (!byte_reg_is_xH(reg)) {
343 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
344 } else {
345 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
347 break;
348 case MO_16:
349 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
350 break;
351 case MO_32:
352 /* For x86_64, this sets the higher half of register to zero.
353 For i386, this is equivalent to a mov. */
354 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
355 break;
356 #ifdef TARGET_X86_64
357 case MO_64:
358 tcg_gen_mov_tl(cpu_regs[reg], t0);
359 break;
360 #endif
361 default:
362 tcg_abort();
366 static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
368 if (ot == MO_8 && byte_reg_is_xH(reg)) {
369 tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
370 tcg_gen_ext8u_tl(t0, t0);
371 } else {
372 tcg_gen_mov_tl(t0, cpu_regs[reg]);
376 static void gen_add_A0_im(DisasContext *s, int val)
378 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
379 if (!CODE64(s)) {
380 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
384 static inline void gen_op_jmp_v(TCGv dest)
386 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
389 static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
391 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
392 gen_op_mov_reg_v(size, reg, cpu_tmp0);
395 static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
397 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T0);
398 gen_op_mov_reg_v(size, reg, cpu_tmp0);
401 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
403 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
406 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
408 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
411 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
413 if (d == OR_TMP0) {
414 gen_op_st_v(s, idx, cpu_T0, cpu_A0);
415 } else {
416 gen_op_mov_reg_v(idx, d, cpu_T0);
420 static inline void gen_jmp_im(target_ulong pc)
422 tcg_gen_movi_tl(cpu_tmp0, pc);
423 gen_op_jmp_v(cpu_tmp0);
426 /* Compute SEG:REG into A0. SEG is selected from the override segment
427 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
428 indicate no override. */
429 static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
430 int def_seg, int ovr_seg)
432 switch (aflag) {
433 #ifdef TARGET_X86_64
434 case MO_64:
435 if (ovr_seg < 0) {
436 tcg_gen_mov_tl(cpu_A0, a0);
437 return;
439 break;
440 #endif
441 case MO_32:
442 /* 32 bit address */
443 if (ovr_seg < 0) {
444 if (s->addseg) {
445 ovr_seg = def_seg;
446 } else {
447 tcg_gen_ext32u_tl(cpu_A0, a0);
448 return;
451 break;
452 case MO_16:
453 /* 16 bit address */
454 if (ovr_seg < 0) {
455 ovr_seg = def_seg;
457 tcg_gen_ext16u_tl(cpu_A0, a0);
458 /* ADDSEG will only be false in 16-bit mode for LEA. */
459 if (!s->addseg) {
460 return;
462 a0 = cpu_A0;
463 break;
464 default:
465 tcg_abort();
468 if (ovr_seg >= 0) {
469 TCGv seg = cpu_seg_base[ovr_seg];
471 if (aflag == MO_64) {
472 tcg_gen_add_tl(cpu_A0, a0, seg);
473 } else if (CODE64(s)) {
474 tcg_gen_ext32u_tl(cpu_A0, a0);
475 tcg_gen_add_tl(cpu_A0, cpu_A0, seg);
476 } else {
477 tcg_gen_add_tl(cpu_A0, a0, seg);
478 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
483 static inline void gen_string_movl_A0_ESI(DisasContext *s)
485 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
488 static inline void gen_string_movl_A0_EDI(DisasContext *s)
490 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
493 static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
495 tcg_gen_ld32s_tl(cpu_T0, cpu_env, offsetof(CPUX86State, df));
496 tcg_gen_shli_tl(cpu_T0, cpu_T0, ot);
499 static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign)
501 switch (size) {
502 case MO_8:
503 if (sign) {
504 tcg_gen_ext8s_tl(dst, src);
505 } else {
506 tcg_gen_ext8u_tl(dst, src);
508 return dst;
509 case MO_16:
510 if (sign) {
511 tcg_gen_ext16s_tl(dst, src);
512 } else {
513 tcg_gen_ext16u_tl(dst, src);
515 return dst;
516 #ifdef TARGET_X86_64
517 case MO_32:
518 if (sign) {
519 tcg_gen_ext32s_tl(dst, src);
520 } else {
521 tcg_gen_ext32u_tl(dst, src);
523 return dst;
524 #endif
525 default:
526 return src;
530 static void gen_extu(TCGMemOp ot, TCGv reg)
532 gen_ext_tl(reg, reg, ot, false);
535 static void gen_exts(TCGMemOp ot, TCGv reg)
537 gen_ext_tl(reg, reg, ot, true);
540 static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1)
542 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
543 gen_extu(size, cpu_tmp0);
544 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
547 static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1)
549 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
550 gen_extu(size, cpu_tmp0);
551 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
554 static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n)
556 switch (ot) {
557 case MO_8:
558 gen_helper_inb(v, cpu_env, n);
559 break;
560 case MO_16:
561 gen_helper_inw(v, cpu_env, n);
562 break;
563 case MO_32:
564 gen_helper_inl(v, cpu_env, n);
565 break;
566 default:
567 tcg_abort();
571 static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n)
573 switch (ot) {
574 case MO_8:
575 gen_helper_outb(cpu_env, v, n);
576 break;
577 case MO_16:
578 gen_helper_outw(cpu_env, v, n);
579 break;
580 case MO_32:
581 gen_helper_outl(cpu_env, v, n);
582 break;
583 default:
584 tcg_abort();
588 static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
589 uint32_t svm_flags)
591 target_ulong next_eip;
593 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
594 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
595 switch (ot) {
596 case MO_8:
597 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
598 break;
599 case MO_16:
600 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
601 break;
602 case MO_32:
603 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
604 break;
605 default:
606 tcg_abort();
609 if(s->flags & HF_SVMI_MASK) {
610 gen_update_cc_op(s);
611 gen_jmp_im(cur_eip);
612 svm_flags |= (1 << (4 + ot));
613 next_eip = s->pc - s->cs_base;
614 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
615 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
616 tcg_const_i32(svm_flags),
617 tcg_const_i32(next_eip - cur_eip));
621 static inline void gen_movs(DisasContext *s, TCGMemOp ot)
623 gen_string_movl_A0_ESI(s);
624 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
625 gen_string_movl_A0_EDI(s);
626 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
627 gen_op_movl_T0_Dshift(ot);
628 gen_op_add_reg_T0(s->aflag, R_ESI);
629 gen_op_add_reg_T0(s->aflag, R_EDI);
632 static void gen_op_update1_cc(void)
634 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
637 static void gen_op_update2_cc(void)
639 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
640 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
643 static void gen_op_update3_cc(TCGv reg)
645 tcg_gen_mov_tl(cpu_cc_src2, reg);
646 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
647 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
650 static inline void gen_op_testl_T0_T1_cc(void)
652 tcg_gen_and_tl(cpu_cc_dst, cpu_T0, cpu_T1);
655 static void gen_op_update_neg_cc(void)
657 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
658 tcg_gen_neg_tl(cpu_cc_src, cpu_T0);
659 tcg_gen_movi_tl(cpu_cc_srcT, 0);
662 /* compute all eflags to cc_src */
663 static void gen_compute_eflags(DisasContext *s)
665 TCGv zero, dst, src1, src2;
666 int live, dead;
668 if (s->cc_op == CC_OP_EFLAGS) {
669 return;
671 if (s->cc_op == CC_OP_CLR) {
672 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
673 set_cc_op(s, CC_OP_EFLAGS);
674 return;
677 TCGV_UNUSED(zero);
678 dst = cpu_cc_dst;
679 src1 = cpu_cc_src;
680 src2 = cpu_cc_src2;
682 /* Take care to not read values that are not live. */
683 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
684 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
685 if (dead) {
686 zero = tcg_const_tl(0);
687 if (dead & USES_CC_DST) {
688 dst = zero;
690 if (dead & USES_CC_SRC) {
691 src1 = zero;
693 if (dead & USES_CC_SRC2) {
694 src2 = zero;
698 gen_update_cc_op(s);
699 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
700 set_cc_op(s, CC_OP_EFLAGS);
702 if (dead) {
703 tcg_temp_free(zero);
707 typedef struct CCPrepare {
708 TCGCond cond;
709 TCGv reg;
710 TCGv reg2;
711 target_ulong imm;
712 target_ulong mask;
713 bool use_reg2;
714 bool no_setcond;
715 } CCPrepare;
717 /* compute eflags.C to reg */
718 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
720 TCGv t0, t1;
721 int size, shift;
723 switch (s->cc_op) {
724 case CC_OP_SUBB ... CC_OP_SUBQ:
725 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
726 size = s->cc_op - CC_OP_SUBB;
727 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
728 /* If no temporary was used, be careful not to alias t1 and t0. */
729 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
730 tcg_gen_mov_tl(t0, cpu_cc_srcT);
731 gen_extu(size, t0);
732 goto add_sub;
734 case CC_OP_ADDB ... CC_OP_ADDQ:
735 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
736 size = s->cc_op - CC_OP_ADDB;
737 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
738 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
739 add_sub:
740 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
741 .reg2 = t1, .mask = -1, .use_reg2 = true };
743 case CC_OP_LOGICB ... CC_OP_LOGICQ:
744 case CC_OP_CLR:
745 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
747 case CC_OP_INCB ... CC_OP_INCQ:
748 case CC_OP_DECB ... CC_OP_DECQ:
749 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
750 .mask = -1, .no_setcond = true };
752 case CC_OP_SHLB ... CC_OP_SHLQ:
753 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
754 size = s->cc_op - CC_OP_SHLB;
755 shift = (8 << size) - 1;
756 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
757 .mask = (target_ulong)1 << shift };
759 case CC_OP_MULB ... CC_OP_MULQ:
760 return (CCPrepare) { .cond = TCG_COND_NE,
761 .reg = cpu_cc_src, .mask = -1 };
763 case CC_OP_BMILGB ... CC_OP_BMILGQ:
764 size = s->cc_op - CC_OP_BMILGB;
765 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
766 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
768 case CC_OP_ADCX:
769 case CC_OP_ADCOX:
770 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
771 .mask = -1, .no_setcond = true };
773 case CC_OP_EFLAGS:
774 case CC_OP_SARB ... CC_OP_SARQ:
775 /* CC_SRC & 1 */
776 return (CCPrepare) { .cond = TCG_COND_NE,
777 .reg = cpu_cc_src, .mask = CC_C };
779 default:
780 /* The need to compute only C from CC_OP_DYNAMIC is important
781 in efficiently implementing e.g. INC at the start of a TB. */
782 gen_update_cc_op(s);
783 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
784 cpu_cc_src2, cpu_cc_op);
785 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
786 .mask = -1, .no_setcond = true };
790 /* compute eflags.P to reg */
791 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
793 gen_compute_eflags(s);
794 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
795 .mask = CC_P };
798 /* compute eflags.S to reg */
799 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
801 switch (s->cc_op) {
802 case CC_OP_DYNAMIC:
803 gen_compute_eflags(s);
804 /* FALLTHRU */
805 case CC_OP_EFLAGS:
806 case CC_OP_ADCX:
807 case CC_OP_ADOX:
808 case CC_OP_ADCOX:
809 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
810 .mask = CC_S };
811 case CC_OP_CLR:
812 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
813 default:
815 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
816 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
817 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
822 /* compute eflags.O to reg */
823 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
825 switch (s->cc_op) {
826 case CC_OP_ADOX:
827 case CC_OP_ADCOX:
828 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
829 .mask = -1, .no_setcond = true };
830 case CC_OP_CLR:
831 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
832 default:
833 gen_compute_eflags(s);
834 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
835 .mask = CC_O };
839 /* compute eflags.Z to reg */
840 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
842 switch (s->cc_op) {
843 case CC_OP_DYNAMIC:
844 gen_compute_eflags(s);
845 /* FALLTHRU */
846 case CC_OP_EFLAGS:
847 case CC_OP_ADCX:
848 case CC_OP_ADOX:
849 case CC_OP_ADCOX:
850 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
851 .mask = CC_Z };
852 case CC_OP_CLR:
853 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
854 default:
856 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
857 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
858 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
863 /* perform a conditional store into register 'reg' according to jump opcode
864 value 'b'. In the fast case, T0 is guaranted not to be used. */
865 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
867 int inv, jcc_op, cond;
868 TCGMemOp size;
869 CCPrepare cc;
870 TCGv t0;
872 inv = b & 1;
873 jcc_op = (b >> 1) & 7;
875 switch (s->cc_op) {
876 case CC_OP_SUBB ... CC_OP_SUBQ:
877 /* We optimize relational operators for the cmp/jcc case. */
878 size = s->cc_op - CC_OP_SUBB;
879 switch (jcc_op) {
880 case JCC_BE:
881 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
882 gen_extu(size, cpu_tmp4);
883 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
884 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
885 .reg2 = t0, .mask = -1, .use_reg2 = true };
886 break;
888 case JCC_L:
889 cond = TCG_COND_LT;
890 goto fast_jcc_l;
891 case JCC_LE:
892 cond = TCG_COND_LE;
893 fast_jcc_l:
894 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
895 gen_exts(size, cpu_tmp4);
896 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
897 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
898 .reg2 = t0, .mask = -1, .use_reg2 = true };
899 break;
901 default:
902 goto slow_jcc;
904 break;
906 default:
907 slow_jcc:
908 /* This actually generates good code for JC, JZ and JS. */
909 switch (jcc_op) {
910 case JCC_O:
911 cc = gen_prepare_eflags_o(s, reg);
912 break;
913 case JCC_B:
914 cc = gen_prepare_eflags_c(s, reg);
915 break;
916 case JCC_Z:
917 cc = gen_prepare_eflags_z(s, reg);
918 break;
919 case JCC_BE:
920 gen_compute_eflags(s);
921 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
922 .mask = CC_Z | CC_C };
923 break;
924 case JCC_S:
925 cc = gen_prepare_eflags_s(s, reg);
926 break;
927 case JCC_P:
928 cc = gen_prepare_eflags_p(s, reg);
929 break;
930 case JCC_L:
931 gen_compute_eflags(s);
932 if (TCGV_EQUAL(reg, cpu_cc_src)) {
933 reg = cpu_tmp0;
935 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
936 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
937 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
938 .mask = CC_S };
939 break;
940 default:
941 case JCC_LE:
942 gen_compute_eflags(s);
943 if (TCGV_EQUAL(reg, cpu_cc_src)) {
944 reg = cpu_tmp0;
946 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
947 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
948 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
949 .mask = CC_S | CC_Z };
950 break;
952 break;
955 if (inv) {
956 cc.cond = tcg_invert_cond(cc.cond);
958 return cc;
961 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
963 CCPrepare cc = gen_prepare_cc(s, b, reg);
965 if (cc.no_setcond) {
966 if (cc.cond == TCG_COND_EQ) {
967 tcg_gen_xori_tl(reg, cc.reg, 1);
968 } else {
969 tcg_gen_mov_tl(reg, cc.reg);
971 return;
974 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
975 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
976 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
977 tcg_gen_andi_tl(reg, reg, 1);
978 return;
980 if (cc.mask != -1) {
981 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
982 cc.reg = reg;
984 if (cc.use_reg2) {
985 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
986 } else {
987 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
991 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
993 gen_setcc1(s, JCC_B << 1, reg);
996 /* generate a conditional jump to label 'l1' according to jump opcode
997 value 'b'. In the fast case, T0 is guaranted not to be used. */
998 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1000 CCPrepare cc = gen_prepare_cc(s, b, cpu_T0);
1002 if (cc.mask != -1) {
1003 tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask);
1004 cc.reg = cpu_T0;
1006 if (cc.use_reg2) {
1007 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1008 } else {
1009 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1013 /* Generate a conditional jump to label 'l1' according to jump opcode
1014 value 'b'. In the fast case, T0 is guaranted not to be used.
1015 A translation block must end soon. */
1016 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1018 CCPrepare cc = gen_prepare_cc(s, b, cpu_T0);
1020 gen_update_cc_op(s);
1021 if (cc.mask != -1) {
1022 tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask);
1023 cc.reg = cpu_T0;
1025 set_cc_op(s, CC_OP_DYNAMIC);
1026 if (cc.use_reg2) {
1027 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1028 } else {
1029 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1033 /* XXX: does not work with gdbstub "ice" single step - not a
1034 serious problem */
1035 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1037 TCGLabel *l1 = gen_new_label();
1038 TCGLabel *l2 = gen_new_label();
1039 gen_op_jnz_ecx(s->aflag, l1);
1040 gen_set_label(l2);
1041 gen_jmp_tb(s, next_eip, 1);
1042 gen_set_label(l1);
1043 return l2;
1046 static inline void gen_stos(DisasContext *s, TCGMemOp ot)
1048 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
1049 gen_string_movl_A0_EDI(s);
1050 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1051 gen_op_movl_T0_Dshift(ot);
1052 gen_op_add_reg_T0(s->aflag, R_EDI);
1055 static inline void gen_lods(DisasContext *s, TCGMemOp ot)
1057 gen_string_movl_A0_ESI(s);
1058 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1059 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
1060 gen_op_movl_T0_Dshift(ot);
1061 gen_op_add_reg_T0(s->aflag, R_ESI);
1064 static inline void gen_scas(DisasContext *s, TCGMemOp ot)
1066 gen_string_movl_A0_EDI(s);
1067 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
1068 gen_op(s, OP_CMPL, ot, R_EAX);
1069 gen_op_movl_T0_Dshift(ot);
1070 gen_op_add_reg_T0(s->aflag, R_EDI);
1073 static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
1075 gen_string_movl_A0_EDI(s);
1076 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
1077 gen_string_movl_A0_ESI(s);
1078 gen_op(s, OP_CMPL, ot, OR_TMP0);
1079 gen_op_movl_T0_Dshift(ot);
1080 gen_op_add_reg_T0(s->aflag, R_ESI);
1081 gen_op_add_reg_T0(s->aflag, R_EDI);
1084 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1086 if (s->flags & HF_IOBPT_MASK) {
1087 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1088 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1090 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1091 tcg_temp_free_i32(t_size);
1092 tcg_temp_free(t_next);
1097 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
1099 if (s->tb->cflags & CF_USE_ICOUNT) {
1100 gen_io_start();
1102 gen_string_movl_A0_EDI(s);
1103 /* Note: we must do this dummy write first to be restartable in
1104 case of page fault. */
1105 tcg_gen_movi_tl(cpu_T0, 0);
1106 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1107 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1108 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1109 gen_helper_in_func(ot, cpu_T0, cpu_tmp2_i32);
1110 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1111 gen_op_movl_T0_Dshift(ot);
1112 gen_op_add_reg_T0(s->aflag, R_EDI);
1113 gen_bpt_io(s, cpu_tmp2_i32, ot);
1114 if (s->tb->cflags & CF_USE_ICOUNT) {
1115 gen_io_end();
1119 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
1121 if (s->tb->cflags & CF_USE_ICOUNT) {
1122 gen_io_start();
1124 gen_string_movl_A0_ESI(s);
1125 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1127 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1128 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1129 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T0);
1130 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1131 gen_op_movl_T0_Dshift(ot);
1132 gen_op_add_reg_T0(s->aflag, R_ESI);
1133 gen_bpt_io(s, cpu_tmp2_i32, ot);
1134 if (s->tb->cflags & CF_USE_ICOUNT) {
1135 gen_io_end();
1139 /* same method as Valgrind : we generate jumps to current or next
1140 instruction */
1141 #define GEN_REPZ(op) \
1142 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1143 target_ulong cur_eip, target_ulong next_eip) \
1145 TCGLabel *l2; \
1146 gen_update_cc_op(s); \
1147 l2 = gen_jz_ecx_string(s, next_eip); \
1148 gen_ ## op(s, ot); \
1149 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1150 /* a loop would cause two single step exceptions if ECX = 1 \
1151 before rep string_insn */ \
1152 if (s->repz_opt) \
1153 gen_op_jz_ecx(s->aflag, l2); \
1154 gen_jmp(s, cur_eip); \
1157 #define GEN_REPZ2(op) \
1158 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1159 target_ulong cur_eip, \
1160 target_ulong next_eip, \
1161 int nz) \
1163 TCGLabel *l2; \
1164 gen_update_cc_op(s); \
1165 l2 = gen_jz_ecx_string(s, next_eip); \
1166 gen_ ## op(s, ot); \
1167 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1168 gen_update_cc_op(s); \
1169 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1170 if (s->repz_opt) \
1171 gen_op_jz_ecx(s->aflag, l2); \
1172 gen_jmp(s, cur_eip); \
1175 GEN_REPZ(movs)
1176 GEN_REPZ(stos)
1177 GEN_REPZ(lods)
1178 GEN_REPZ(ins)
1179 GEN_REPZ(outs)
1180 GEN_REPZ2(scas)
1181 GEN_REPZ2(cmps)
1183 static void gen_helper_fp_arith_ST0_FT0(int op)
1185 switch (op) {
1186 case 0:
1187 gen_helper_fadd_ST0_FT0(cpu_env);
1188 break;
1189 case 1:
1190 gen_helper_fmul_ST0_FT0(cpu_env);
1191 break;
1192 case 2:
1193 gen_helper_fcom_ST0_FT0(cpu_env);
1194 break;
1195 case 3:
1196 gen_helper_fcom_ST0_FT0(cpu_env);
1197 break;
1198 case 4:
1199 gen_helper_fsub_ST0_FT0(cpu_env);
1200 break;
1201 case 5:
1202 gen_helper_fsubr_ST0_FT0(cpu_env);
1203 break;
1204 case 6:
1205 gen_helper_fdiv_ST0_FT0(cpu_env);
1206 break;
1207 case 7:
1208 gen_helper_fdivr_ST0_FT0(cpu_env);
1209 break;
1213 /* NOTE the exception in "r" op ordering */
1214 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1216 TCGv_i32 tmp = tcg_const_i32(opreg);
1217 switch (op) {
1218 case 0:
1219 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1220 break;
1221 case 1:
1222 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1223 break;
1224 case 4:
1225 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1226 break;
1227 case 5:
1228 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1229 break;
1230 case 6:
1231 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1232 break;
1233 case 7:
1234 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1235 break;
1239 /* if d == OR_TMP0, it means memory operand (address in A0) */
1240 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
1242 if (d != OR_TMP0) {
1243 gen_op_mov_v_reg(ot, cpu_T0, d);
1244 } else {
1245 gen_op_ld_v(s1, ot, cpu_T0, cpu_A0);
1247 switch(op) {
1248 case OP_ADCL:
1249 gen_compute_eflags_c(s1, cpu_tmp4);
1250 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
1251 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_tmp4);
1252 gen_op_st_rm_T0_A0(s1, ot, d);
1253 gen_op_update3_cc(cpu_tmp4);
1254 set_cc_op(s1, CC_OP_ADCB + ot);
1255 break;
1256 case OP_SBBL:
1257 gen_compute_eflags_c(s1, cpu_tmp4);
1258 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1);
1259 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_tmp4);
1260 gen_op_st_rm_T0_A0(s1, ot, d);
1261 gen_op_update3_cc(cpu_tmp4);
1262 set_cc_op(s1, CC_OP_SBBB + ot);
1263 break;
1264 case OP_ADDL:
1265 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
1266 gen_op_st_rm_T0_A0(s1, ot, d);
1267 gen_op_update2_cc();
1268 set_cc_op(s1, CC_OP_ADDB + ot);
1269 break;
1270 case OP_SUBL:
1271 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0);
1272 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1);
1273 gen_op_st_rm_T0_A0(s1, ot, d);
1274 gen_op_update2_cc();
1275 set_cc_op(s1, CC_OP_SUBB + ot);
1276 break;
1277 default:
1278 case OP_ANDL:
1279 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
1280 gen_op_st_rm_T0_A0(s1, ot, d);
1281 gen_op_update1_cc();
1282 set_cc_op(s1, CC_OP_LOGICB + ot);
1283 break;
1284 case OP_ORL:
1285 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1);
1286 gen_op_st_rm_T0_A0(s1, ot, d);
1287 gen_op_update1_cc();
1288 set_cc_op(s1, CC_OP_LOGICB + ot);
1289 break;
1290 case OP_XORL:
1291 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_T1);
1292 gen_op_st_rm_T0_A0(s1, ot, d);
1293 gen_op_update1_cc();
1294 set_cc_op(s1, CC_OP_LOGICB + ot);
1295 break;
1296 case OP_CMPL:
1297 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
1298 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0);
1299 tcg_gen_sub_tl(cpu_cc_dst, cpu_T0, cpu_T1);
1300 set_cc_op(s1, CC_OP_SUBB + ot);
1301 break;
1305 /* if d == OR_TMP0, it means memory operand (address in A0) */
1306 static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
1308 if (d != OR_TMP0) {
1309 gen_op_mov_v_reg(ot, cpu_T0, d);
1310 } else {
1311 gen_op_ld_v(s1, ot, cpu_T0, cpu_A0);
1313 gen_compute_eflags_c(s1, cpu_cc_src);
1314 if (c > 0) {
1315 tcg_gen_addi_tl(cpu_T0, cpu_T0, 1);
1316 set_cc_op(s1, CC_OP_INCB + ot);
1317 } else {
1318 tcg_gen_addi_tl(cpu_T0, cpu_T0, -1);
1319 set_cc_op(s1, CC_OP_DECB + ot);
1321 gen_op_st_rm_T0_A0(s1, ot, d);
1322 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
1325 static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
1326 TCGv shm1, TCGv count, bool is_right)
1328 TCGv_i32 z32, s32, oldop;
1329 TCGv z_tl;
1331 /* Store the results into the CC variables. If we know that the
1332 variable must be dead, store unconditionally. Otherwise we'll
1333 need to not disrupt the current contents. */
1334 z_tl = tcg_const_tl(0);
1335 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1336 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1337 result, cpu_cc_dst);
1338 } else {
1339 tcg_gen_mov_tl(cpu_cc_dst, result);
1341 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1342 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1343 shm1, cpu_cc_src);
1344 } else {
1345 tcg_gen_mov_tl(cpu_cc_src, shm1);
1347 tcg_temp_free(z_tl);
1349 /* Get the two potential CC_OP values into temporaries. */
1350 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1351 if (s->cc_op == CC_OP_DYNAMIC) {
1352 oldop = cpu_cc_op;
1353 } else {
1354 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1355 oldop = cpu_tmp3_i32;
1358 /* Conditionally store the CC_OP value. */
1359 z32 = tcg_const_i32(0);
1360 s32 = tcg_temp_new_i32();
1361 tcg_gen_trunc_tl_i32(s32, count);
1362 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1363 tcg_temp_free_i32(z32);
1364 tcg_temp_free_i32(s32);
1366 /* The CC_OP value is no longer predictable. */
1367 set_cc_op(s, CC_OP_DYNAMIC);
1370 static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1371 int is_right, int is_arith)
1373 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1375 /* load */
1376 if (op1 == OR_TMP0) {
1377 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1378 } else {
1379 gen_op_mov_v_reg(ot, cpu_T0, op1);
1382 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1383 tcg_gen_subi_tl(cpu_tmp0, cpu_T1, 1);
1385 if (is_right) {
1386 if (is_arith) {
1387 gen_exts(ot, cpu_T0);
1388 tcg_gen_sar_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1389 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
1390 } else {
1391 gen_extu(ot, cpu_T0);
1392 tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1393 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
1395 } else {
1396 tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1397 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
1400 /* store */
1401 gen_op_st_rm_T0_A0(s, ot, op1);
1403 gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, cpu_T1, is_right);
1406 static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1407 int is_right, int is_arith)
1409 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1411 /* load */
1412 if (op1 == OR_TMP0)
1413 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1414 else
1415 gen_op_mov_v_reg(ot, cpu_T0, op1);
1417 op2 &= mask;
1418 if (op2 != 0) {
1419 if (is_right) {
1420 if (is_arith) {
1421 gen_exts(ot, cpu_T0);
1422 tcg_gen_sari_tl(cpu_tmp4, cpu_T0, op2 - 1);
1423 tcg_gen_sari_tl(cpu_T0, cpu_T0, op2);
1424 } else {
1425 gen_extu(ot, cpu_T0);
1426 tcg_gen_shri_tl(cpu_tmp4, cpu_T0, op2 - 1);
1427 tcg_gen_shri_tl(cpu_T0, cpu_T0, op2);
1429 } else {
1430 tcg_gen_shli_tl(cpu_tmp4, cpu_T0, op2 - 1);
1431 tcg_gen_shli_tl(cpu_T0, cpu_T0, op2);
1435 /* store */
1436 gen_op_st_rm_T0_A0(s, ot, op1);
1438 /* update eflags if non zero shift */
1439 if (op2 != 0) {
1440 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1441 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
1442 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1446 static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
1448 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1449 TCGv_i32 t0, t1;
1451 /* load */
1452 if (op1 == OR_TMP0) {
1453 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1454 } else {
1455 gen_op_mov_v_reg(ot, cpu_T0, op1);
1458 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1460 switch (ot) {
1461 case MO_8:
1462 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1463 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
1464 tcg_gen_muli_tl(cpu_T0, cpu_T0, 0x01010101);
1465 goto do_long;
1466 case MO_16:
1467 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1468 tcg_gen_deposit_tl(cpu_T0, cpu_T0, cpu_T0, 16, 16);
1469 goto do_long;
1470 do_long:
1471 #ifdef TARGET_X86_64
1472 case MO_32:
1473 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
1474 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
1475 if (is_right) {
1476 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1477 } else {
1478 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1480 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
1481 break;
1482 #endif
1483 default:
1484 if (is_right) {
1485 tcg_gen_rotr_tl(cpu_T0, cpu_T0, cpu_T1);
1486 } else {
1487 tcg_gen_rotl_tl(cpu_T0, cpu_T0, cpu_T1);
1489 break;
1492 /* store */
1493 gen_op_st_rm_T0_A0(s, ot, op1);
1495 /* We'll need the flags computed into CC_SRC. */
1496 gen_compute_eflags(s);
1498 /* The value that was "rotated out" is now present at the other end
1499 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1500 since we've computed the flags into CC_SRC, these variables are
1501 currently dead. */
1502 if (is_right) {
1503 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1);
1504 tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask);
1505 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1506 } else {
1507 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask);
1508 tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1);
1510 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1511 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1513 /* Now conditionally store the new CC_OP value. If the shift count
1514 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1515 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1516 exactly as we computed above. */
1517 t0 = tcg_const_i32(0);
1518 t1 = tcg_temp_new_i32();
1519 tcg_gen_trunc_tl_i32(t1, cpu_T1);
1520 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1521 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1522 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1523 cpu_tmp2_i32, cpu_tmp3_i32);
1524 tcg_temp_free_i32(t0);
1525 tcg_temp_free_i32(t1);
1527 /* The CC_OP value is no longer predictable. */
1528 set_cc_op(s, CC_OP_DYNAMIC);
1531 static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1532 int is_right)
1534 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1535 int shift;
1537 /* load */
1538 if (op1 == OR_TMP0) {
1539 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1540 } else {
1541 gen_op_mov_v_reg(ot, cpu_T0, op1);
1544 op2 &= mask;
1545 if (op2 != 0) {
1546 switch (ot) {
1547 #ifdef TARGET_X86_64
1548 case MO_32:
1549 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
1550 if (is_right) {
1551 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1552 } else {
1553 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1555 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
1556 break;
1557 #endif
1558 default:
1559 if (is_right) {
1560 tcg_gen_rotri_tl(cpu_T0, cpu_T0, op2);
1561 } else {
1562 tcg_gen_rotli_tl(cpu_T0, cpu_T0, op2);
1564 break;
1565 case MO_8:
1566 mask = 7;
1567 goto do_shifts;
1568 case MO_16:
1569 mask = 15;
1570 do_shifts:
1571 shift = op2 & mask;
1572 if (is_right) {
1573 shift = mask + 1 - shift;
1575 gen_extu(ot, cpu_T0);
1576 tcg_gen_shli_tl(cpu_tmp0, cpu_T0, shift);
1577 tcg_gen_shri_tl(cpu_T0, cpu_T0, mask + 1 - shift);
1578 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
1579 break;
1583 /* store */
1584 gen_op_st_rm_T0_A0(s, ot, op1);
1586 if (op2 != 0) {
1587 /* Compute the flags into CC_SRC. */
1588 gen_compute_eflags(s);
1590 /* The value that was "rotated out" is now present at the other end
1591 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1592 since we've computed the flags into CC_SRC, these variables are
1593 currently dead. */
1594 if (is_right) {
1595 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1);
1596 tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask);
1597 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1598 } else {
1599 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask);
1600 tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1);
1602 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1603 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1604 set_cc_op(s, CC_OP_ADCOX);
1608 /* XXX: add faster immediate = 1 case */
1609 static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1610 int is_right)
1612 gen_compute_eflags(s);
1613 assert(s->cc_op == CC_OP_EFLAGS);
1615 /* load */
1616 if (op1 == OR_TMP0)
1617 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1618 else
1619 gen_op_mov_v_reg(ot, cpu_T0, op1);
1621 if (is_right) {
1622 switch (ot) {
1623 case MO_8:
1624 gen_helper_rcrb(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1625 break;
1626 case MO_16:
1627 gen_helper_rcrw(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1628 break;
1629 case MO_32:
1630 gen_helper_rcrl(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1631 break;
1632 #ifdef TARGET_X86_64
1633 case MO_64:
1634 gen_helper_rcrq(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1635 break;
1636 #endif
1637 default:
1638 tcg_abort();
1640 } else {
1641 switch (ot) {
1642 case MO_8:
1643 gen_helper_rclb(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1644 break;
1645 case MO_16:
1646 gen_helper_rclw(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1647 break;
1648 case MO_32:
1649 gen_helper_rcll(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1650 break;
1651 #ifdef TARGET_X86_64
1652 case MO_64:
1653 gen_helper_rclq(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1654 break;
1655 #endif
1656 default:
1657 tcg_abort();
1660 /* store */
1661 gen_op_st_rm_T0_A0(s, ot, op1);
1664 /* XXX: add faster immediate case */
1665 static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1666 bool is_right, TCGv count_in)
1668 target_ulong mask = (ot == MO_64 ? 63 : 31);
1669 TCGv count;
1671 /* load */
1672 if (op1 == OR_TMP0) {
1673 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1674 } else {
1675 gen_op_mov_v_reg(ot, cpu_T0, op1);
1678 count = tcg_temp_new();
1679 tcg_gen_andi_tl(count, count_in, mask);
1681 switch (ot) {
1682 case MO_16:
1683 /* Note: we implement the Intel behaviour for shift count > 16.
1684 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1685 portion by constructing it as a 32-bit value. */
1686 if (is_right) {
1687 tcg_gen_deposit_tl(cpu_tmp0, cpu_T0, cpu_T1, 16, 16);
1688 tcg_gen_mov_tl(cpu_T1, cpu_T0);
1689 tcg_gen_mov_tl(cpu_T0, cpu_tmp0);
1690 } else {
1691 tcg_gen_deposit_tl(cpu_T1, cpu_T0, cpu_T1, 16, 16);
1693 /* FALLTHRU */
1694 #ifdef TARGET_X86_64
1695 case MO_32:
1696 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1697 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1698 if (is_right) {
1699 tcg_gen_concat_tl_i64(cpu_T0, cpu_T0, cpu_T1);
1700 tcg_gen_shr_i64(cpu_tmp0, cpu_T0, cpu_tmp0);
1701 tcg_gen_shr_i64(cpu_T0, cpu_T0, count);
1702 } else {
1703 tcg_gen_concat_tl_i64(cpu_T0, cpu_T1, cpu_T0);
1704 tcg_gen_shl_i64(cpu_tmp0, cpu_T0, cpu_tmp0);
1705 tcg_gen_shl_i64(cpu_T0, cpu_T0, count);
1706 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1707 tcg_gen_shri_i64(cpu_T0, cpu_T0, 32);
1709 break;
1710 #endif
1711 default:
1712 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1713 if (is_right) {
1714 tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1716 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1717 tcg_gen_shr_tl(cpu_T0, cpu_T0, count);
1718 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_tmp4);
1719 } else {
1720 tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1721 if (ot == MO_16) {
1722 /* Only needed if count > 16, for Intel behaviour. */
1723 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1724 tcg_gen_shr_tl(cpu_tmp4, cpu_T1, cpu_tmp4);
1725 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1728 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1729 tcg_gen_shl_tl(cpu_T0, cpu_T0, count);
1730 tcg_gen_shr_tl(cpu_T1, cpu_T1, cpu_tmp4);
1732 tcg_gen_movi_tl(cpu_tmp4, 0);
1733 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T1, count, cpu_tmp4,
1734 cpu_tmp4, cpu_T1);
1735 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1);
1736 break;
1739 /* store */
1740 gen_op_st_rm_T0_A0(s, ot, op1);
1742 gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, count, is_right);
1743 tcg_temp_free(count);
1746 static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
1748 if (s != OR_TMP1)
1749 gen_op_mov_v_reg(ot, cpu_T1, s);
1750 switch(op) {
1751 case OP_ROL:
1752 gen_rot_rm_T1(s1, ot, d, 0);
1753 break;
1754 case OP_ROR:
1755 gen_rot_rm_T1(s1, ot, d, 1);
1756 break;
1757 case OP_SHL:
1758 case OP_SHL1:
1759 gen_shift_rm_T1(s1, ot, d, 0, 0);
1760 break;
1761 case OP_SHR:
1762 gen_shift_rm_T1(s1, ot, d, 1, 0);
1763 break;
1764 case OP_SAR:
1765 gen_shift_rm_T1(s1, ot, d, 1, 1);
1766 break;
1767 case OP_RCL:
1768 gen_rotc_rm_T1(s1, ot, d, 0);
1769 break;
1770 case OP_RCR:
1771 gen_rotc_rm_T1(s1, ot, d, 1);
1772 break;
1776 static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
1778 switch(op) {
1779 case OP_ROL:
1780 gen_rot_rm_im(s1, ot, d, c, 0);
1781 break;
1782 case OP_ROR:
1783 gen_rot_rm_im(s1, ot, d, c, 1);
1784 break;
1785 case OP_SHL:
1786 case OP_SHL1:
1787 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1788 break;
1789 case OP_SHR:
1790 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1791 break;
1792 case OP_SAR:
1793 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1794 break;
1795 default:
1796 /* currently not optimized */
1797 tcg_gen_movi_tl(cpu_T1, c);
1798 gen_shift(s1, op, ot, d, OR_TMP1);
1799 break;
1803 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
1805 target_long disp;
1806 int havesib, base, index, scale;
1807 int mod, rm, code, def_seg, ovr_seg;
1808 TCGv sum;
1810 def_seg = R_DS;
1811 ovr_seg = s->override;
1812 mod = (modrm >> 6) & 3;
1813 rm = modrm & 7;
1815 switch (s->aflag) {
1816 case MO_64:
1817 case MO_32:
1818 havesib = 0;
1819 base = rm;
1820 index = -1;
1821 scale = 0;
1823 if (base == 4) {
1824 havesib = 1;
1825 code = cpu_ldub_code(env, s->pc++);
1826 scale = (code >> 6) & 3;
1827 index = ((code >> 3) & 7) | REX_X(s);
1828 if (index == 4) {
1829 index = -1; /* no index */
1831 base = (code & 7);
1833 base |= REX_B(s);
1835 switch (mod) {
1836 case 0:
1837 if ((base & 7) == 5) {
1838 base = -1;
1839 disp = (int32_t)cpu_ldl_code(env, s->pc);
1840 s->pc += 4;
1841 if (CODE64(s) && !havesib) {
1842 disp += s->pc + s->rip_offset;
1844 } else {
1845 disp = 0;
1847 break;
1848 case 1:
1849 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1850 break;
1851 default:
1852 case 2:
1853 disp = (int32_t)cpu_ldl_code(env, s->pc);
1854 s->pc += 4;
1855 break;
1858 /* For correct popl handling with esp. */
1859 if (base == R_ESP && s->popl_esp_hack) {
1860 disp += s->popl_esp_hack;
1863 /* Compute the address, with a minimum number of TCG ops. */
1864 TCGV_UNUSED(sum);
1865 if (index >= 0) {
1866 if (scale == 0) {
1867 sum = cpu_regs[index];
1868 } else {
1869 tcg_gen_shli_tl(cpu_A0, cpu_regs[index], scale);
1870 sum = cpu_A0;
1872 if (base >= 0) {
1873 tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]);
1874 sum = cpu_A0;
1876 } else if (base >= 0) {
1877 sum = cpu_regs[base];
1879 if (TCGV_IS_UNUSED(sum)) {
1880 tcg_gen_movi_tl(cpu_A0, disp);
1881 sum = cpu_A0;
1882 } else if (disp != 0) {
1883 tcg_gen_addi_tl(cpu_A0, sum, disp);
1884 sum = cpu_A0;
1887 if (base == R_EBP || base == R_ESP) {
1888 def_seg = R_SS;
1890 break;
1892 case MO_16:
1893 sum = cpu_A0;
1894 if (mod == 0) {
1895 if (rm == 6) {
1896 disp = cpu_lduw_code(env, s->pc);
1897 s->pc += 2;
1898 tcg_gen_movi_tl(cpu_A0, disp);
1899 break;
1901 disp = 0;
1902 } else if (mod == 1) {
1903 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1904 } else {
1905 disp = (int16_t)cpu_lduw_code(env, s->pc);
1906 s->pc += 2;
1909 switch (rm) {
1910 case 0:
1911 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_ESI]);
1912 break;
1913 case 1:
1914 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_EDI]);
1915 break;
1916 case 2:
1917 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_ESI]);
1918 def_seg = R_SS;
1919 break;
1920 case 3:
1921 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_EDI]);
1922 def_seg = R_SS;
1923 break;
1924 case 4:
1925 sum = cpu_regs[R_ESI];
1926 break;
1927 case 5:
1928 sum = cpu_regs[R_EDI];
1929 break;
1930 case 6:
1931 sum = cpu_regs[R_EBP];
1932 def_seg = R_SS;
1933 break;
1934 default:
1935 case 7:
1936 sum = cpu_regs[R_EBX];
1937 break;
1939 if (disp != 0) {
1940 tcg_gen_addi_tl(cpu_A0, sum, disp);
1941 sum = cpu_A0;
1943 break;
1945 default:
1946 tcg_abort();
1949 gen_lea_v_seg(s, s->aflag, sum, def_seg, ovr_seg);
1952 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
1954 int mod, rm, base, code;
1956 mod = (modrm >> 6) & 3;
1957 if (mod == 3)
1958 return;
1959 rm = modrm & 7;
1961 switch (s->aflag) {
1962 case MO_64:
1963 case MO_32:
1964 base = rm;
1966 if (base == 4) {
1967 code = cpu_ldub_code(env, s->pc++);
1968 base = (code & 7);
1971 switch (mod) {
1972 case 0:
1973 if (base == 5) {
1974 s->pc += 4;
1976 break;
1977 case 1:
1978 s->pc++;
1979 break;
1980 default:
1981 case 2:
1982 s->pc += 4;
1983 break;
1985 break;
1987 case MO_16:
1988 switch (mod) {
1989 case 0:
1990 if (rm == 6) {
1991 s->pc += 2;
1993 break;
1994 case 1:
1995 s->pc++;
1996 break;
1997 default:
1998 case 2:
1999 s->pc += 2;
2000 break;
2002 break;
2004 default:
2005 tcg_abort();
2009 /* used for LEA and MOV AX, mem */
2010 static void gen_add_A0_ds_seg(DisasContext *s)
2012 gen_lea_v_seg(s, s->aflag, cpu_A0, R_DS, s->override);
2015 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2016 OR_TMP0 */
2017 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2018 TCGMemOp ot, int reg, int is_store)
2020 int mod, rm;
2022 mod = (modrm >> 6) & 3;
2023 rm = (modrm & 7) | REX_B(s);
2024 if (mod == 3) {
2025 if (is_store) {
2026 if (reg != OR_TMP0)
2027 gen_op_mov_v_reg(ot, cpu_T0, reg);
2028 gen_op_mov_reg_v(ot, rm, cpu_T0);
2029 } else {
2030 gen_op_mov_v_reg(ot, cpu_T0, rm);
2031 if (reg != OR_TMP0)
2032 gen_op_mov_reg_v(ot, reg, cpu_T0);
2034 } else {
2035 gen_lea_modrm(env, s, modrm);
2036 if (is_store) {
2037 if (reg != OR_TMP0)
2038 gen_op_mov_v_reg(ot, cpu_T0, reg);
2039 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
2040 } else {
2041 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
2042 if (reg != OR_TMP0)
2043 gen_op_mov_reg_v(ot, reg, cpu_T0);
2048 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
2050 uint32_t ret;
2052 switch (ot) {
2053 case MO_8:
2054 ret = cpu_ldub_code(env, s->pc);
2055 s->pc++;
2056 break;
2057 case MO_16:
2058 ret = cpu_lduw_code(env, s->pc);
2059 s->pc += 2;
2060 break;
2061 case MO_32:
2062 #ifdef TARGET_X86_64
2063 case MO_64:
2064 #endif
2065 ret = cpu_ldl_code(env, s->pc);
2066 s->pc += 4;
2067 break;
2068 default:
2069 tcg_abort();
2071 return ret;
2074 static inline int insn_const_size(TCGMemOp ot)
2076 if (ot <= MO_32) {
2077 return 1 << ot;
2078 } else {
2079 return 4;
2083 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2085 TranslationBlock *tb;
2086 target_ulong pc;
2088 pc = s->cs_base + eip;
2089 tb = s->tb;
2090 /* NOTE: we handle the case where the TB spans two pages here */
2091 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2092 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2093 /* jump to same page: we can use a direct jump */
2094 tcg_gen_goto_tb(tb_num);
2095 gen_jmp_im(eip);
2096 tcg_gen_exit_tb((uintptr_t)tb + tb_num);
2097 } else {
2098 /* jump to another page: currently not optimized */
2099 gen_jmp_im(eip);
2100 gen_eob(s);
2104 static inline void gen_jcc(DisasContext *s, int b,
2105 target_ulong val, target_ulong next_eip)
2107 TCGLabel *l1, *l2;
2109 if (s->jmp_opt) {
2110 l1 = gen_new_label();
2111 gen_jcc1(s, b, l1);
2113 gen_goto_tb(s, 0, next_eip);
2115 gen_set_label(l1);
2116 gen_goto_tb(s, 1, val);
2117 s->is_jmp = DISAS_TB_JUMP;
2118 } else {
2119 l1 = gen_new_label();
2120 l2 = gen_new_label();
2121 gen_jcc1(s, b, l1);
2123 gen_jmp_im(next_eip);
2124 tcg_gen_br(l2);
2126 gen_set_label(l1);
2127 gen_jmp_im(val);
2128 gen_set_label(l2);
2129 gen_eob(s);
2133 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
2134 int modrm, int reg)
2136 CCPrepare cc;
2138 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2140 cc = gen_prepare_cc(s, b, cpu_T1);
2141 if (cc.mask != -1) {
2142 TCGv t0 = tcg_temp_new();
2143 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2144 cc.reg = t0;
2146 if (!cc.use_reg2) {
2147 cc.reg2 = tcg_const_tl(cc.imm);
2150 tcg_gen_movcond_tl(cc.cond, cpu_T0, cc.reg, cc.reg2,
2151 cpu_T0, cpu_regs[reg]);
2152 gen_op_mov_reg_v(ot, reg, cpu_T0);
2154 if (cc.mask != -1) {
2155 tcg_temp_free(cc.reg);
2157 if (!cc.use_reg2) {
2158 tcg_temp_free(cc.reg2);
2162 static inline void gen_op_movl_T0_seg(int seg_reg)
2164 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
2165 offsetof(CPUX86State,segs[seg_reg].selector));
2168 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2170 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
2171 tcg_gen_st32_tl(cpu_T0, cpu_env,
2172 offsetof(CPUX86State,segs[seg_reg].selector));
2173 tcg_gen_shli_tl(cpu_seg_base[seg_reg], cpu_T0, 4);
2176 /* move T0 to seg_reg and compute if the CPU state may change. Never
2177 call this function with seg_reg == R_CS */
2178 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
2180 if (s->pe && !s->vm86) {
2181 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
2182 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
2183 /* abort translation because the addseg value may change or
2184 because ss32 may change. For R_SS, translation must always
2185 stop as a special handling must be done to disable hardware
2186 interrupts for the next instruction */
2187 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
2188 s->is_jmp = DISAS_TB_JUMP;
2189 } else {
2190 gen_op_movl_seg_T0_vm(seg_reg);
2191 if (seg_reg == R_SS)
2192 s->is_jmp = DISAS_TB_JUMP;
2196 static inline int svm_is_rep(int prefixes)
2198 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2201 static inline void
2202 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2203 uint32_t type, uint64_t param)
2205 /* no SVM activated; fast case */
2206 if (likely(!(s->flags & HF_SVMI_MASK)))
2207 return;
2208 gen_update_cc_op(s);
2209 gen_jmp_im(pc_start - s->cs_base);
2210 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2211 tcg_const_i64(param));
2214 static inline void
2215 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2217 gen_svm_check_intercept_param(s, pc_start, type, 0);
2220 static inline void gen_stack_update(DisasContext *s, int addend)
2222 gen_op_add_reg_im(mo_stacksize(s), R_ESP, addend);
2225 /* Generate a push. It depends on ss32, addseg and dflag. */
2226 static void gen_push_v(DisasContext *s, TCGv val)
2228 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2229 TCGMemOp a_ot = mo_stacksize(s);
2230 int size = 1 << d_ot;
2231 TCGv new_esp = cpu_A0;
2233 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
2235 if (!CODE64(s)) {
2236 if (s->addseg) {
2237 new_esp = cpu_tmp4;
2238 tcg_gen_mov_tl(new_esp, cpu_A0);
2240 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2243 gen_op_st_v(s, d_ot, val, cpu_A0);
2244 gen_op_mov_reg_v(a_ot, R_ESP, new_esp);
2247 /* two step pop is necessary for precise exceptions */
2248 static TCGMemOp gen_pop_T0(DisasContext *s)
2250 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2252 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2253 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2255 return d_ot;
2258 static inline void gen_pop_update(DisasContext *s, TCGMemOp ot)
2260 gen_stack_update(s, 1 << ot);
2263 static inline void gen_stack_A0(DisasContext *s)
2265 gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2268 static void gen_pusha(DisasContext *s)
2270 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2271 TCGMemOp d_ot = s->dflag;
2272 int size = 1 << d_ot;
2273 int i;
2275 for (i = 0; i < 8; i++) {
2276 tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], (i - 8) * size);
2277 gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
2278 gen_op_st_v(s, d_ot, cpu_regs[7 - i], cpu_A0);
2281 gen_stack_update(s, -8 * size);
2284 static void gen_popa(DisasContext *s)
2286 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2287 TCGMemOp d_ot = s->dflag;
2288 int size = 1 << d_ot;
2289 int i;
2291 for (i = 0; i < 8; i++) {
2292 /* ESP is not reloaded */
2293 if (7 - i == R_ESP) {
2294 continue;
2296 tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], i * size);
2297 gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
2298 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2299 gen_op_mov_reg_v(d_ot, 7 - i, cpu_T0);
2302 gen_stack_update(s, 8 * size);
2305 static void gen_enter(DisasContext *s, int esp_addend, int level)
2307 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2308 TCGMemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
2309 int size = 1 << d_ot;
2311 /* Push BP; compute FrameTemp into T1. */
2312 tcg_gen_subi_tl(cpu_T1, cpu_regs[R_ESP], size);
2313 gen_lea_v_seg(s, a_ot, cpu_T1, R_SS, -1);
2314 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], cpu_A0);
2316 level &= 31;
2317 if (level != 0) {
2318 int i;
2320 /* Copy level-1 pointers from the previous frame. */
2321 for (i = 1; i < level; ++i) {
2322 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_EBP], size * i);
2323 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2324 gen_op_ld_v(s, d_ot, cpu_tmp0, cpu_A0);
2326 tcg_gen_subi_tl(cpu_A0, cpu_T1, size * i);
2327 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2328 gen_op_st_v(s, d_ot, cpu_tmp0, cpu_A0);
2331 /* Push the current FrameTemp as the last level. */
2332 tcg_gen_subi_tl(cpu_A0, cpu_T1, size * level);
2333 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2334 gen_op_st_v(s, d_ot, cpu_T1, cpu_A0);
2337 /* Copy the FrameTemp value to EBP. */
2338 gen_op_mov_reg_v(a_ot, R_EBP, cpu_T1);
2340 /* Compute the final value of ESP. */
2341 tcg_gen_subi_tl(cpu_T1, cpu_T1, esp_addend + size * level);
2342 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2345 static void gen_leave(DisasContext *s)
2347 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2348 TCGMemOp a_ot = mo_stacksize(s);
2350 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2351 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2353 tcg_gen_addi_tl(cpu_T1, cpu_regs[R_EBP], 1 << d_ot);
2355 gen_op_mov_reg_v(d_ot, R_EBP, cpu_T0);
2356 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2359 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2361 gen_update_cc_op(s);
2362 gen_jmp_im(cur_eip);
2363 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
2364 s->is_jmp = DISAS_TB_JUMP;
2367 /* an interrupt is different from an exception because of the
2368 privilege checks */
2369 static void gen_interrupt(DisasContext *s, int intno,
2370 target_ulong cur_eip, target_ulong next_eip)
2372 gen_update_cc_op(s);
2373 gen_jmp_im(cur_eip);
2374 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2375 tcg_const_i32(next_eip - cur_eip));
2376 s->is_jmp = DISAS_TB_JUMP;
2379 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2381 gen_update_cc_op(s);
2382 gen_jmp_im(cur_eip);
2383 gen_helper_debug(cpu_env);
2384 s->is_jmp = DISAS_TB_JUMP;
2387 /* generate a generic end of block. Trace exception is also generated
2388 if needed */
2389 static void gen_eob(DisasContext *s)
2391 gen_update_cc_op(s);
2392 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2393 gen_helper_reset_inhibit_irq(cpu_env);
2395 if (s->tb->flags & HF_RF_MASK) {
2396 gen_helper_reset_rf(cpu_env);
2398 if (s->singlestep_enabled) {
2399 gen_helper_debug(cpu_env);
2400 } else if (s->tf) {
2401 gen_helper_single_step(cpu_env);
2402 } else {
2403 tcg_gen_exit_tb(0);
2405 s->is_jmp = DISAS_TB_JUMP;
2408 /* generate a jump to eip. No segment change must happen before as a
2409 direct call to the next block may occur */
2410 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2412 gen_update_cc_op(s);
2413 set_cc_op(s, CC_OP_DYNAMIC);
2414 if (s->jmp_opt) {
2415 gen_goto_tb(s, tb_num, eip);
2416 s->is_jmp = DISAS_TB_JUMP;
2417 } else {
2418 gen_jmp_im(eip);
2419 gen_eob(s);
2423 static void gen_jmp(DisasContext *s, target_ulong eip)
2425 gen_jmp_tb(s, eip, 0);
2428 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2430 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2431 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2434 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2436 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2437 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2440 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2442 int mem_index = s->mem_index;
2443 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2444 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2445 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2446 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2447 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2450 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2452 int mem_index = s->mem_index;
2453 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2454 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2455 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2456 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2457 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2460 static inline void gen_op_movo(int d_offset, int s_offset)
2462 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2463 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2464 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2465 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2468 static inline void gen_op_movq(int d_offset, int s_offset)
2470 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2471 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2474 static inline void gen_op_movl(int d_offset, int s_offset)
2476 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2477 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2480 static inline void gen_op_movq_env_0(int d_offset)
2482 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2483 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2486 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2487 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2488 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2489 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2490 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2491 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2492 TCGv_i32 val);
2493 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2494 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2495 TCGv val);
2497 #define SSE_SPECIAL ((void *)1)
2498 #define SSE_DUMMY ((void *)2)
2500 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2501 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2502 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2504 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2505 /* 3DNow! extensions */
2506 [0x0e] = { SSE_DUMMY }, /* femms */
2507 [0x0f] = { SSE_DUMMY }, /* pf... */
2508 /* pure SSE operations */
2509 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2510 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2511 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2512 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2513 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2514 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2515 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2516 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2518 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2519 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2520 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2521 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2522 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2523 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2524 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2525 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2526 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2527 [0x51] = SSE_FOP(sqrt),
2528 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2529 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2530 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2531 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2532 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2533 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2534 [0x58] = SSE_FOP(add),
2535 [0x59] = SSE_FOP(mul),
2536 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2537 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2538 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2539 [0x5c] = SSE_FOP(sub),
2540 [0x5d] = SSE_FOP(min),
2541 [0x5e] = SSE_FOP(div),
2542 [0x5f] = SSE_FOP(max),
2544 [0xc2] = SSE_FOP(cmpeq),
2545 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2546 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2548 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2549 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2550 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2552 /* MMX ops and their SSE extensions */
2553 [0x60] = MMX_OP2(punpcklbw),
2554 [0x61] = MMX_OP2(punpcklwd),
2555 [0x62] = MMX_OP2(punpckldq),
2556 [0x63] = MMX_OP2(packsswb),
2557 [0x64] = MMX_OP2(pcmpgtb),
2558 [0x65] = MMX_OP2(pcmpgtw),
2559 [0x66] = MMX_OP2(pcmpgtl),
2560 [0x67] = MMX_OP2(packuswb),
2561 [0x68] = MMX_OP2(punpckhbw),
2562 [0x69] = MMX_OP2(punpckhwd),
2563 [0x6a] = MMX_OP2(punpckhdq),
2564 [0x6b] = MMX_OP2(packssdw),
2565 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2566 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2567 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2568 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2569 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2570 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2571 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2572 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2573 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2574 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2575 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2576 [0x74] = MMX_OP2(pcmpeqb),
2577 [0x75] = MMX_OP2(pcmpeqw),
2578 [0x76] = MMX_OP2(pcmpeql),
2579 [0x77] = { SSE_DUMMY }, /* emms */
2580 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2581 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2582 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2583 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2584 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2585 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2586 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2587 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2588 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2589 [0xd1] = MMX_OP2(psrlw),
2590 [0xd2] = MMX_OP2(psrld),
2591 [0xd3] = MMX_OP2(psrlq),
2592 [0xd4] = MMX_OP2(paddq),
2593 [0xd5] = MMX_OP2(pmullw),
2594 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2595 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2596 [0xd8] = MMX_OP2(psubusb),
2597 [0xd9] = MMX_OP2(psubusw),
2598 [0xda] = MMX_OP2(pminub),
2599 [0xdb] = MMX_OP2(pand),
2600 [0xdc] = MMX_OP2(paddusb),
2601 [0xdd] = MMX_OP2(paddusw),
2602 [0xde] = MMX_OP2(pmaxub),
2603 [0xdf] = MMX_OP2(pandn),
2604 [0xe0] = MMX_OP2(pavgb),
2605 [0xe1] = MMX_OP2(psraw),
2606 [0xe2] = MMX_OP2(psrad),
2607 [0xe3] = MMX_OP2(pavgw),
2608 [0xe4] = MMX_OP2(pmulhuw),
2609 [0xe5] = MMX_OP2(pmulhw),
2610 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2611 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2612 [0xe8] = MMX_OP2(psubsb),
2613 [0xe9] = MMX_OP2(psubsw),
2614 [0xea] = MMX_OP2(pminsw),
2615 [0xeb] = MMX_OP2(por),
2616 [0xec] = MMX_OP2(paddsb),
2617 [0xed] = MMX_OP2(paddsw),
2618 [0xee] = MMX_OP2(pmaxsw),
2619 [0xef] = MMX_OP2(pxor),
2620 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2621 [0xf1] = MMX_OP2(psllw),
2622 [0xf2] = MMX_OP2(pslld),
2623 [0xf3] = MMX_OP2(psllq),
2624 [0xf4] = MMX_OP2(pmuludq),
2625 [0xf5] = MMX_OP2(pmaddwd),
2626 [0xf6] = MMX_OP2(psadbw),
2627 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2628 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2629 [0xf8] = MMX_OP2(psubb),
2630 [0xf9] = MMX_OP2(psubw),
2631 [0xfa] = MMX_OP2(psubl),
2632 [0xfb] = MMX_OP2(psubq),
2633 [0xfc] = MMX_OP2(paddb),
2634 [0xfd] = MMX_OP2(paddw),
2635 [0xfe] = MMX_OP2(paddl),
2638 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2639 [0 + 2] = MMX_OP2(psrlw),
2640 [0 + 4] = MMX_OP2(psraw),
2641 [0 + 6] = MMX_OP2(psllw),
2642 [8 + 2] = MMX_OP2(psrld),
2643 [8 + 4] = MMX_OP2(psrad),
2644 [8 + 6] = MMX_OP2(pslld),
2645 [16 + 2] = MMX_OP2(psrlq),
2646 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2647 [16 + 6] = MMX_OP2(psllq),
2648 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2651 static const SSEFunc_0_epi sse_op_table3ai[] = {
2652 gen_helper_cvtsi2ss,
2653 gen_helper_cvtsi2sd
2656 #ifdef TARGET_X86_64
2657 static const SSEFunc_0_epl sse_op_table3aq[] = {
2658 gen_helper_cvtsq2ss,
2659 gen_helper_cvtsq2sd
2661 #endif
2663 static const SSEFunc_i_ep sse_op_table3bi[] = {
2664 gen_helper_cvttss2si,
2665 gen_helper_cvtss2si,
2666 gen_helper_cvttsd2si,
2667 gen_helper_cvtsd2si
2670 #ifdef TARGET_X86_64
2671 static const SSEFunc_l_ep sse_op_table3bq[] = {
2672 gen_helper_cvttss2sq,
2673 gen_helper_cvtss2sq,
2674 gen_helper_cvttsd2sq,
2675 gen_helper_cvtsd2sq
2677 #endif
2679 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2680 SSE_FOP(cmpeq),
2681 SSE_FOP(cmplt),
2682 SSE_FOP(cmple),
2683 SSE_FOP(cmpunord),
2684 SSE_FOP(cmpneq),
2685 SSE_FOP(cmpnlt),
2686 SSE_FOP(cmpnle),
2687 SSE_FOP(cmpord),
2690 static const SSEFunc_0_epp sse_op_table5[256] = {
2691 [0x0c] = gen_helper_pi2fw,
2692 [0x0d] = gen_helper_pi2fd,
2693 [0x1c] = gen_helper_pf2iw,
2694 [0x1d] = gen_helper_pf2id,
2695 [0x8a] = gen_helper_pfnacc,
2696 [0x8e] = gen_helper_pfpnacc,
2697 [0x90] = gen_helper_pfcmpge,
2698 [0x94] = gen_helper_pfmin,
2699 [0x96] = gen_helper_pfrcp,
2700 [0x97] = gen_helper_pfrsqrt,
2701 [0x9a] = gen_helper_pfsub,
2702 [0x9e] = gen_helper_pfadd,
2703 [0xa0] = gen_helper_pfcmpgt,
2704 [0xa4] = gen_helper_pfmax,
2705 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2706 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2707 [0xaa] = gen_helper_pfsubr,
2708 [0xae] = gen_helper_pfacc,
2709 [0xb0] = gen_helper_pfcmpeq,
2710 [0xb4] = gen_helper_pfmul,
2711 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2712 [0xb7] = gen_helper_pmulhrw_mmx,
2713 [0xbb] = gen_helper_pswapd,
2714 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
2717 struct SSEOpHelper_epp {
2718 SSEFunc_0_epp op[2];
2719 uint32_t ext_mask;
2722 struct SSEOpHelper_eppi {
2723 SSEFunc_0_eppi op[2];
2724 uint32_t ext_mask;
2727 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2728 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2729 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
2730 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
2731 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2732 CPUID_EXT_PCLMULQDQ }
2733 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
2735 static const struct SSEOpHelper_epp sse_op_table6[256] = {
2736 [0x00] = SSSE3_OP(pshufb),
2737 [0x01] = SSSE3_OP(phaddw),
2738 [0x02] = SSSE3_OP(phaddd),
2739 [0x03] = SSSE3_OP(phaddsw),
2740 [0x04] = SSSE3_OP(pmaddubsw),
2741 [0x05] = SSSE3_OP(phsubw),
2742 [0x06] = SSSE3_OP(phsubd),
2743 [0x07] = SSSE3_OP(phsubsw),
2744 [0x08] = SSSE3_OP(psignb),
2745 [0x09] = SSSE3_OP(psignw),
2746 [0x0a] = SSSE3_OP(psignd),
2747 [0x0b] = SSSE3_OP(pmulhrsw),
2748 [0x10] = SSE41_OP(pblendvb),
2749 [0x14] = SSE41_OP(blendvps),
2750 [0x15] = SSE41_OP(blendvpd),
2751 [0x17] = SSE41_OP(ptest),
2752 [0x1c] = SSSE3_OP(pabsb),
2753 [0x1d] = SSSE3_OP(pabsw),
2754 [0x1e] = SSSE3_OP(pabsd),
2755 [0x20] = SSE41_OP(pmovsxbw),
2756 [0x21] = SSE41_OP(pmovsxbd),
2757 [0x22] = SSE41_OP(pmovsxbq),
2758 [0x23] = SSE41_OP(pmovsxwd),
2759 [0x24] = SSE41_OP(pmovsxwq),
2760 [0x25] = SSE41_OP(pmovsxdq),
2761 [0x28] = SSE41_OP(pmuldq),
2762 [0x29] = SSE41_OP(pcmpeqq),
2763 [0x2a] = SSE41_SPECIAL, /* movntqda */
2764 [0x2b] = SSE41_OP(packusdw),
2765 [0x30] = SSE41_OP(pmovzxbw),
2766 [0x31] = SSE41_OP(pmovzxbd),
2767 [0x32] = SSE41_OP(pmovzxbq),
2768 [0x33] = SSE41_OP(pmovzxwd),
2769 [0x34] = SSE41_OP(pmovzxwq),
2770 [0x35] = SSE41_OP(pmovzxdq),
2771 [0x37] = SSE42_OP(pcmpgtq),
2772 [0x38] = SSE41_OP(pminsb),
2773 [0x39] = SSE41_OP(pminsd),
2774 [0x3a] = SSE41_OP(pminuw),
2775 [0x3b] = SSE41_OP(pminud),
2776 [0x3c] = SSE41_OP(pmaxsb),
2777 [0x3d] = SSE41_OP(pmaxsd),
2778 [0x3e] = SSE41_OP(pmaxuw),
2779 [0x3f] = SSE41_OP(pmaxud),
2780 [0x40] = SSE41_OP(pmulld),
2781 [0x41] = SSE41_OP(phminposuw),
2782 [0xdb] = AESNI_OP(aesimc),
2783 [0xdc] = AESNI_OP(aesenc),
2784 [0xdd] = AESNI_OP(aesenclast),
2785 [0xde] = AESNI_OP(aesdec),
2786 [0xdf] = AESNI_OP(aesdeclast),
2789 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
2790 [0x08] = SSE41_OP(roundps),
2791 [0x09] = SSE41_OP(roundpd),
2792 [0x0a] = SSE41_OP(roundss),
2793 [0x0b] = SSE41_OP(roundsd),
2794 [0x0c] = SSE41_OP(blendps),
2795 [0x0d] = SSE41_OP(blendpd),
2796 [0x0e] = SSE41_OP(pblendw),
2797 [0x0f] = SSSE3_OP(palignr),
2798 [0x14] = SSE41_SPECIAL, /* pextrb */
2799 [0x15] = SSE41_SPECIAL, /* pextrw */
2800 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
2801 [0x17] = SSE41_SPECIAL, /* extractps */
2802 [0x20] = SSE41_SPECIAL, /* pinsrb */
2803 [0x21] = SSE41_SPECIAL, /* insertps */
2804 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
2805 [0x40] = SSE41_OP(dpps),
2806 [0x41] = SSE41_OP(dppd),
2807 [0x42] = SSE41_OP(mpsadbw),
2808 [0x44] = PCLMULQDQ_OP(pclmulqdq),
2809 [0x60] = SSE42_OP(pcmpestrm),
2810 [0x61] = SSE42_OP(pcmpestri),
2811 [0x62] = SSE42_OP(pcmpistrm),
2812 [0x63] = SSE42_OP(pcmpistri),
2813 [0xdf] = AESNI_OP(aeskeygenassist),
2816 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
2817 target_ulong pc_start, int rex_r)
2819 int b1, op1_offset, op2_offset, is_xmm, val;
2820 int modrm, mod, rm, reg;
2821 SSEFunc_0_epp sse_fn_epp;
2822 SSEFunc_0_eppi sse_fn_eppi;
2823 SSEFunc_0_ppi sse_fn_ppi;
2824 SSEFunc_0_eppt sse_fn_eppt;
2825 TCGMemOp ot;
2827 b &= 0xff;
2828 if (s->prefix & PREFIX_DATA)
2829 b1 = 1;
2830 else if (s->prefix & PREFIX_REPZ)
2831 b1 = 2;
2832 else if (s->prefix & PREFIX_REPNZ)
2833 b1 = 3;
2834 else
2835 b1 = 0;
2836 sse_fn_epp = sse_op_table1[b][b1];
2837 if (!sse_fn_epp) {
2838 goto illegal_op;
2840 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
2841 is_xmm = 1;
2842 } else {
2843 if (b1 == 0) {
2844 /* MMX case */
2845 is_xmm = 0;
2846 } else {
2847 is_xmm = 1;
2850 /* simple MMX/SSE operation */
2851 if (s->flags & HF_TS_MASK) {
2852 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2853 return;
2855 if (s->flags & HF_EM_MASK) {
2856 illegal_op:
2857 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2858 return;
2860 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2861 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
2862 goto illegal_op;
2863 if (b == 0x0e) {
2864 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
2865 goto illegal_op;
2866 /* femms */
2867 gen_helper_emms(cpu_env);
2868 return;
2870 if (b == 0x77) {
2871 /* emms */
2872 gen_helper_emms(cpu_env);
2873 return;
2875 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2876 the static cpu state) */
2877 if (!is_xmm) {
2878 gen_helper_enter_mmx(cpu_env);
2881 modrm = cpu_ldub_code(env, s->pc++);
2882 reg = ((modrm >> 3) & 7);
2883 if (is_xmm)
2884 reg |= rex_r;
2885 mod = (modrm >> 6) & 3;
2886 if (sse_fn_epp == SSE_SPECIAL) {
2887 b |= (b1 << 8);
2888 switch(b) {
2889 case 0x0e7: /* movntq */
2890 if (mod == 3)
2891 goto illegal_op;
2892 gen_lea_modrm(env, s, modrm);
2893 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
2894 break;
2895 case 0x1e7: /* movntdq */
2896 case 0x02b: /* movntps */
2897 case 0x12b: /* movntps */
2898 if (mod == 3)
2899 goto illegal_op;
2900 gen_lea_modrm(env, s, modrm);
2901 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
2902 break;
2903 case 0x3f0: /* lddqu */
2904 if (mod == 3)
2905 goto illegal_op;
2906 gen_lea_modrm(env, s, modrm);
2907 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
2908 break;
2909 case 0x22b: /* movntss */
2910 case 0x32b: /* movntsd */
2911 if (mod == 3)
2912 goto illegal_op;
2913 gen_lea_modrm(env, s, modrm);
2914 if (b1 & 1) {
2915 gen_stq_env_A0(s, offsetof(CPUX86State,
2916 xmm_regs[reg].ZMM_Q(0)));
2917 } else {
2918 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
2919 xmm_regs[reg].ZMM_L(0)));
2920 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
2922 break;
2923 case 0x6e: /* movd mm, ea */
2924 #ifdef TARGET_X86_64
2925 if (s->dflag == MO_64) {
2926 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
2927 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
2928 } else
2929 #endif
2931 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
2932 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
2933 offsetof(CPUX86State,fpregs[reg].mmx));
2934 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
2935 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
2937 break;
2938 case 0x16e: /* movd xmm, ea */
2939 #ifdef TARGET_X86_64
2940 if (s->dflag == MO_64) {
2941 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
2942 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
2943 offsetof(CPUX86State,xmm_regs[reg]));
2944 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T0);
2945 } else
2946 #endif
2948 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
2949 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
2950 offsetof(CPUX86State,xmm_regs[reg]));
2951 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
2952 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
2954 break;
2955 case 0x6f: /* movq mm, ea */
2956 if (mod != 3) {
2957 gen_lea_modrm(env, s, modrm);
2958 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
2959 } else {
2960 rm = (modrm & 7);
2961 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
2962 offsetof(CPUX86State,fpregs[rm].mmx));
2963 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
2964 offsetof(CPUX86State,fpregs[reg].mmx));
2966 break;
2967 case 0x010: /* movups */
2968 case 0x110: /* movupd */
2969 case 0x028: /* movaps */
2970 case 0x128: /* movapd */
2971 case 0x16f: /* movdqa xmm, ea */
2972 case 0x26f: /* movdqu xmm, ea */
2973 if (mod != 3) {
2974 gen_lea_modrm(env, s, modrm);
2975 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
2976 } else {
2977 rm = (modrm & 7) | REX_B(s);
2978 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2979 offsetof(CPUX86State,xmm_regs[rm]));
2981 break;
2982 case 0x210: /* movss xmm, ea */
2983 if (mod != 3) {
2984 gen_lea_modrm(env, s, modrm);
2985 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
2986 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
2987 tcg_gen_movi_tl(cpu_T0, 0);
2988 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
2989 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
2990 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
2991 } else {
2992 rm = (modrm & 7) | REX_B(s);
2993 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
2994 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
2996 break;
2997 case 0x310: /* movsd xmm, ea */
2998 if (mod != 3) {
2999 gen_lea_modrm(env, s, modrm);
3000 gen_ldq_env_A0(s, offsetof(CPUX86State,
3001 xmm_regs[reg].ZMM_Q(0)));
3002 tcg_gen_movi_tl(cpu_T0, 0);
3003 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3004 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3005 } else {
3006 rm = (modrm & 7) | REX_B(s);
3007 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3008 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3010 break;
3011 case 0x012: /* movlps */
3012 case 0x112: /* movlpd */
3013 if (mod != 3) {
3014 gen_lea_modrm(env, s, modrm);
3015 gen_ldq_env_A0(s, offsetof(CPUX86State,
3016 xmm_regs[reg].ZMM_Q(0)));
3017 } else {
3018 /* movhlps */
3019 rm = (modrm & 7) | REX_B(s);
3020 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3021 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3023 break;
3024 case 0x212: /* movsldup */
3025 if (mod != 3) {
3026 gen_lea_modrm(env, s, modrm);
3027 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3028 } else {
3029 rm = (modrm & 7) | REX_B(s);
3030 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3031 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3032 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3033 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3035 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3036 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3037 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3038 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3039 break;
3040 case 0x312: /* movddup */
3041 if (mod != 3) {
3042 gen_lea_modrm(env, s, modrm);
3043 gen_ldq_env_A0(s, offsetof(CPUX86State,
3044 xmm_regs[reg].ZMM_Q(0)));
3045 } else {
3046 rm = (modrm & 7) | REX_B(s);
3047 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3048 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3050 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3051 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3052 break;
3053 case 0x016: /* movhps */
3054 case 0x116: /* movhpd */
3055 if (mod != 3) {
3056 gen_lea_modrm(env, s, modrm);
3057 gen_ldq_env_A0(s, offsetof(CPUX86State,
3058 xmm_regs[reg].ZMM_Q(1)));
3059 } else {
3060 /* movlhps */
3061 rm = (modrm & 7) | REX_B(s);
3062 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3063 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3065 break;
3066 case 0x216: /* movshdup */
3067 if (mod != 3) {
3068 gen_lea_modrm(env, s, modrm);
3069 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3070 } else {
3071 rm = (modrm & 7) | REX_B(s);
3072 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3073 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3074 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3075 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3077 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3078 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3079 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3080 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3081 break;
3082 case 0x178:
3083 case 0x378:
3085 int bit_index, field_length;
3087 if (b1 == 1 && reg != 0)
3088 goto illegal_op;
3089 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3090 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3091 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3092 offsetof(CPUX86State,xmm_regs[reg]));
3093 if (b1 == 1)
3094 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3095 tcg_const_i32(bit_index),
3096 tcg_const_i32(field_length));
3097 else
3098 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3099 tcg_const_i32(bit_index),
3100 tcg_const_i32(field_length));
3102 break;
3103 case 0x7e: /* movd ea, mm */
3104 #ifdef TARGET_X86_64
3105 if (s->dflag == MO_64) {
3106 tcg_gen_ld_i64(cpu_T0, cpu_env,
3107 offsetof(CPUX86State,fpregs[reg].mmx));
3108 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3109 } else
3110 #endif
3112 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3113 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3114 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3116 break;
3117 case 0x17e: /* movd ea, xmm */
3118 #ifdef TARGET_X86_64
3119 if (s->dflag == MO_64) {
3120 tcg_gen_ld_i64(cpu_T0, cpu_env,
3121 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3122 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3123 } else
3124 #endif
3126 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3127 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3128 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3130 break;
3131 case 0x27e: /* movq xmm, ea */
3132 if (mod != 3) {
3133 gen_lea_modrm(env, s, modrm);
3134 gen_ldq_env_A0(s, offsetof(CPUX86State,
3135 xmm_regs[reg].ZMM_Q(0)));
3136 } else {
3137 rm = (modrm & 7) | REX_B(s);
3138 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3139 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3141 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3142 break;
3143 case 0x7f: /* movq ea, mm */
3144 if (mod != 3) {
3145 gen_lea_modrm(env, s, modrm);
3146 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3147 } else {
3148 rm = (modrm & 7);
3149 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3150 offsetof(CPUX86State,fpregs[reg].mmx));
3152 break;
3153 case 0x011: /* movups */
3154 case 0x111: /* movupd */
3155 case 0x029: /* movaps */
3156 case 0x129: /* movapd */
3157 case 0x17f: /* movdqa ea, xmm */
3158 case 0x27f: /* movdqu ea, xmm */
3159 if (mod != 3) {
3160 gen_lea_modrm(env, s, modrm);
3161 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3162 } else {
3163 rm = (modrm & 7) | REX_B(s);
3164 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3165 offsetof(CPUX86State,xmm_regs[reg]));
3167 break;
3168 case 0x211: /* movss ea, xmm */
3169 if (mod != 3) {
3170 gen_lea_modrm(env, s, modrm);
3171 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3172 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3173 } else {
3174 rm = (modrm & 7) | REX_B(s);
3175 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)),
3176 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3178 break;
3179 case 0x311: /* movsd ea, xmm */
3180 if (mod != 3) {
3181 gen_lea_modrm(env, s, modrm);
3182 gen_stq_env_A0(s, offsetof(CPUX86State,
3183 xmm_regs[reg].ZMM_Q(0)));
3184 } else {
3185 rm = (modrm & 7) | REX_B(s);
3186 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3187 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3189 break;
3190 case 0x013: /* movlps */
3191 case 0x113: /* movlpd */
3192 if (mod != 3) {
3193 gen_lea_modrm(env, s, modrm);
3194 gen_stq_env_A0(s, offsetof(CPUX86State,
3195 xmm_regs[reg].ZMM_Q(0)));
3196 } else {
3197 goto illegal_op;
3199 break;
3200 case 0x017: /* movhps */
3201 case 0x117: /* movhpd */
3202 if (mod != 3) {
3203 gen_lea_modrm(env, s, modrm);
3204 gen_stq_env_A0(s, offsetof(CPUX86State,
3205 xmm_regs[reg].ZMM_Q(1)));
3206 } else {
3207 goto illegal_op;
3209 break;
3210 case 0x71: /* shift mm, im */
3211 case 0x72:
3212 case 0x73:
3213 case 0x171: /* shift xmm, im */
3214 case 0x172:
3215 case 0x173:
3216 if (b1 >= 2) {
3217 goto illegal_op;
3219 val = cpu_ldub_code(env, s->pc++);
3220 if (is_xmm) {
3221 tcg_gen_movi_tl(cpu_T0, val);
3222 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3223 tcg_gen_movi_tl(cpu_T0, 0);
3224 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(1)));
3225 op1_offset = offsetof(CPUX86State,xmm_t0);
3226 } else {
3227 tcg_gen_movi_tl(cpu_T0, val);
3228 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3229 tcg_gen_movi_tl(cpu_T0, 0);
3230 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3231 op1_offset = offsetof(CPUX86State,mmx_t0);
3233 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3234 (((modrm >> 3)) & 7)][b1];
3235 if (!sse_fn_epp) {
3236 goto illegal_op;
3238 if (is_xmm) {
3239 rm = (modrm & 7) | REX_B(s);
3240 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3241 } else {
3242 rm = (modrm & 7);
3243 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3245 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3246 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3247 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3248 break;
3249 case 0x050: /* movmskps */
3250 rm = (modrm & 7) | REX_B(s);
3251 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3252 offsetof(CPUX86State,xmm_regs[rm]));
3253 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3254 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3255 break;
3256 case 0x150: /* movmskpd */
3257 rm = (modrm & 7) | REX_B(s);
3258 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3259 offsetof(CPUX86State,xmm_regs[rm]));
3260 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3261 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3262 break;
3263 case 0x02a: /* cvtpi2ps */
3264 case 0x12a: /* cvtpi2pd */
3265 gen_helper_enter_mmx(cpu_env);
3266 if (mod != 3) {
3267 gen_lea_modrm(env, s, modrm);
3268 op2_offset = offsetof(CPUX86State,mmx_t0);
3269 gen_ldq_env_A0(s, op2_offset);
3270 } else {
3271 rm = (modrm & 7);
3272 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3274 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3275 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3276 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3277 switch(b >> 8) {
3278 case 0x0:
3279 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3280 break;
3281 default:
3282 case 0x1:
3283 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3284 break;
3286 break;
3287 case 0x22a: /* cvtsi2ss */
3288 case 0x32a: /* cvtsi2sd */
3289 ot = mo_64_32(s->dflag);
3290 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3291 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3292 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3293 if (ot == MO_32) {
3294 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3295 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3296 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3297 } else {
3298 #ifdef TARGET_X86_64
3299 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3300 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T0);
3301 #else
3302 goto illegal_op;
3303 #endif
3305 break;
3306 case 0x02c: /* cvttps2pi */
3307 case 0x12c: /* cvttpd2pi */
3308 case 0x02d: /* cvtps2pi */
3309 case 0x12d: /* cvtpd2pi */
3310 gen_helper_enter_mmx(cpu_env);
3311 if (mod != 3) {
3312 gen_lea_modrm(env, s, modrm);
3313 op2_offset = offsetof(CPUX86State,xmm_t0);
3314 gen_ldo_env_A0(s, op2_offset);
3315 } else {
3316 rm = (modrm & 7) | REX_B(s);
3317 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3319 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3320 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3321 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3322 switch(b) {
3323 case 0x02c:
3324 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3325 break;
3326 case 0x12c:
3327 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3328 break;
3329 case 0x02d:
3330 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3331 break;
3332 case 0x12d:
3333 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3334 break;
3336 break;
3337 case 0x22c: /* cvttss2si */
3338 case 0x32c: /* cvttsd2si */
3339 case 0x22d: /* cvtss2si */
3340 case 0x32d: /* cvtsd2si */
3341 ot = mo_64_32(s->dflag);
3342 if (mod != 3) {
3343 gen_lea_modrm(env, s, modrm);
3344 if ((b >> 8) & 1) {
3345 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3346 } else {
3347 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3348 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3350 op2_offset = offsetof(CPUX86State,xmm_t0);
3351 } else {
3352 rm = (modrm & 7) | REX_B(s);
3353 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3355 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3356 if (ot == MO_32) {
3357 SSEFunc_i_ep sse_fn_i_ep =
3358 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3359 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3360 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
3361 } else {
3362 #ifdef TARGET_X86_64
3363 SSEFunc_l_ep sse_fn_l_ep =
3364 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3365 sse_fn_l_ep(cpu_T0, cpu_env, cpu_ptr0);
3366 #else
3367 goto illegal_op;
3368 #endif
3370 gen_op_mov_reg_v(ot, reg, cpu_T0);
3371 break;
3372 case 0xc4: /* pinsrw */
3373 case 0x1c4:
3374 s->rip_offset = 1;
3375 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3376 val = cpu_ldub_code(env, s->pc++);
3377 if (b1) {
3378 val &= 7;
3379 tcg_gen_st16_tl(cpu_T0, cpu_env,
3380 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3381 } else {
3382 val &= 3;
3383 tcg_gen_st16_tl(cpu_T0, cpu_env,
3384 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3386 break;
3387 case 0xc5: /* pextrw */
3388 case 0x1c5:
3389 if (mod != 3)
3390 goto illegal_op;
3391 ot = mo_64_32(s->dflag);
3392 val = cpu_ldub_code(env, s->pc++);
3393 if (b1) {
3394 val &= 7;
3395 rm = (modrm & 7) | REX_B(s);
3396 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3397 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3398 } else {
3399 val &= 3;
3400 rm = (modrm & 7);
3401 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3402 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3404 reg = ((modrm >> 3) & 7) | rex_r;
3405 gen_op_mov_reg_v(ot, reg, cpu_T0);
3406 break;
3407 case 0x1d6: /* movq ea, xmm */
3408 if (mod != 3) {
3409 gen_lea_modrm(env, s, modrm);
3410 gen_stq_env_A0(s, offsetof(CPUX86State,
3411 xmm_regs[reg].ZMM_Q(0)));
3412 } else {
3413 rm = (modrm & 7) | REX_B(s);
3414 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3415 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3416 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3418 break;
3419 case 0x2d6: /* movq2dq */
3420 gen_helper_enter_mmx(cpu_env);
3421 rm = (modrm & 7);
3422 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3423 offsetof(CPUX86State,fpregs[rm].mmx));
3424 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3425 break;
3426 case 0x3d6: /* movdq2q */
3427 gen_helper_enter_mmx(cpu_env);
3428 rm = (modrm & 7) | REX_B(s);
3429 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3430 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3431 break;
3432 case 0xd7: /* pmovmskb */
3433 case 0x1d7:
3434 if (mod != 3)
3435 goto illegal_op;
3436 if (b1) {
3437 rm = (modrm & 7) | REX_B(s);
3438 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3439 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3440 } else {
3441 rm = (modrm & 7);
3442 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3443 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3445 reg = ((modrm >> 3) & 7) | rex_r;
3446 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3447 break;
3449 case 0x138:
3450 case 0x038:
3451 b = modrm;
3452 if ((b & 0xf0) == 0xf0) {
3453 goto do_0f_38_fx;
3455 modrm = cpu_ldub_code(env, s->pc++);
3456 rm = modrm & 7;
3457 reg = ((modrm >> 3) & 7) | rex_r;
3458 mod = (modrm >> 6) & 3;
3459 if (b1 >= 2) {
3460 goto illegal_op;
3463 sse_fn_epp = sse_op_table6[b].op[b1];
3464 if (!sse_fn_epp) {
3465 goto illegal_op;
3467 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3468 goto illegal_op;
3470 if (b1) {
3471 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3472 if (mod == 3) {
3473 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3474 } else {
3475 op2_offset = offsetof(CPUX86State,xmm_t0);
3476 gen_lea_modrm(env, s, modrm);
3477 switch (b) {
3478 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3479 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3480 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3481 gen_ldq_env_A0(s, op2_offset +
3482 offsetof(ZMMReg, ZMM_Q(0)));
3483 break;
3484 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3485 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3486 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3487 s->mem_index, MO_LEUL);
3488 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3489 offsetof(ZMMReg, ZMM_L(0)));
3490 break;
3491 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3492 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3493 s->mem_index, MO_LEUW);
3494 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3495 offsetof(ZMMReg, ZMM_W(0)));
3496 break;
3497 case 0x2a: /* movntqda */
3498 gen_ldo_env_A0(s, op1_offset);
3499 return;
3500 default:
3501 gen_ldo_env_A0(s, op2_offset);
3504 } else {
3505 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3506 if (mod == 3) {
3507 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3508 } else {
3509 op2_offset = offsetof(CPUX86State,mmx_t0);
3510 gen_lea_modrm(env, s, modrm);
3511 gen_ldq_env_A0(s, op2_offset);
3514 if (sse_fn_epp == SSE_SPECIAL) {
3515 goto illegal_op;
3518 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3519 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3520 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3522 if (b == 0x17) {
3523 set_cc_op(s, CC_OP_EFLAGS);
3525 break;
3527 case 0x238:
3528 case 0x338:
3529 do_0f_38_fx:
3530 /* Various integer extensions at 0f 38 f[0-f]. */
3531 b = modrm | (b1 << 8);
3532 modrm = cpu_ldub_code(env, s->pc++);
3533 reg = ((modrm >> 3) & 7) | rex_r;
3535 switch (b) {
3536 case 0x3f0: /* crc32 Gd,Eb */
3537 case 0x3f1: /* crc32 Gd,Ey */
3538 do_crc32:
3539 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3540 goto illegal_op;
3542 if ((b & 0xff) == 0xf0) {
3543 ot = MO_8;
3544 } else if (s->dflag != MO_64) {
3545 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3546 } else {
3547 ot = MO_64;
3550 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
3551 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3552 gen_helper_crc32(cpu_T0, cpu_tmp2_i32,
3553 cpu_T0, tcg_const_i32(8 << ot));
3555 ot = mo_64_32(s->dflag);
3556 gen_op_mov_reg_v(ot, reg, cpu_T0);
3557 break;
3559 case 0x1f0: /* crc32 or movbe */
3560 case 0x1f1:
3561 /* For these insns, the f3 prefix is supposed to have priority
3562 over the 66 prefix, but that's not what we implement above
3563 setting b1. */
3564 if (s->prefix & PREFIX_REPNZ) {
3565 goto do_crc32;
3567 /* FALLTHRU */
3568 case 0x0f0: /* movbe Gy,My */
3569 case 0x0f1: /* movbe My,Gy */
3570 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3571 goto illegal_op;
3573 if (s->dflag != MO_64) {
3574 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3575 } else {
3576 ot = MO_64;
3579 gen_lea_modrm(env, s, modrm);
3580 if ((b & 1) == 0) {
3581 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
3582 s->mem_index, ot | MO_BE);
3583 gen_op_mov_reg_v(ot, reg, cpu_T0);
3584 } else {
3585 tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
3586 s->mem_index, ot | MO_BE);
3588 break;
3590 case 0x0f2: /* andn Gy, By, Ey */
3591 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3592 || !(s->prefix & PREFIX_VEX)
3593 || s->vex_l != 0) {
3594 goto illegal_op;
3596 ot = mo_64_32(s->dflag);
3597 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3598 tcg_gen_andc_tl(cpu_T0, cpu_regs[s->vex_v], cpu_T0);
3599 gen_op_mov_reg_v(ot, reg, cpu_T0);
3600 gen_op_update1_cc();
3601 set_cc_op(s, CC_OP_LOGICB + ot);
3602 break;
3604 case 0x0f7: /* bextr Gy, Ey, By */
3605 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3606 || !(s->prefix & PREFIX_VEX)
3607 || s->vex_l != 0) {
3608 goto illegal_op;
3610 ot = mo_64_32(s->dflag);
3612 TCGv bound, zero;
3614 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3615 /* Extract START, and shift the operand.
3616 Shifts larger than operand size get zeros. */
3617 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
3618 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_A0);
3620 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3621 zero = tcg_const_tl(0);
3622 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T0, cpu_A0, bound,
3623 cpu_T0, zero);
3624 tcg_temp_free(zero);
3626 /* Extract the LEN into a mask. Lengths larger than
3627 operand size get all ones. */
3628 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
3629 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
3630 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
3631 cpu_A0, bound);
3632 tcg_temp_free(bound);
3633 tcg_gen_movi_tl(cpu_T1, 1);
3634 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_A0);
3635 tcg_gen_subi_tl(cpu_T1, cpu_T1, 1);
3636 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
3638 gen_op_mov_reg_v(ot, reg, cpu_T0);
3639 gen_op_update1_cc();
3640 set_cc_op(s, CC_OP_LOGICB + ot);
3642 break;
3644 case 0x0f5: /* bzhi Gy, Ey, By */
3645 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3646 || !(s->prefix & PREFIX_VEX)
3647 || s->vex_l != 0) {
3648 goto illegal_op;
3650 ot = mo_64_32(s->dflag);
3651 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3652 tcg_gen_ext8u_tl(cpu_T1, cpu_regs[s->vex_v]);
3654 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3655 /* Note that since we're using BMILG (in order to get O
3656 cleared) we need to store the inverse into C. */
3657 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3658 cpu_T1, bound);
3659 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T1, cpu_T1,
3660 bound, bound, cpu_T1);
3661 tcg_temp_free(bound);
3663 tcg_gen_movi_tl(cpu_A0, -1);
3664 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T1);
3665 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_A0);
3666 gen_op_mov_reg_v(ot, reg, cpu_T0);
3667 gen_op_update1_cc();
3668 set_cc_op(s, CC_OP_BMILGB + ot);
3669 break;
3671 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3672 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3673 || !(s->prefix & PREFIX_VEX)
3674 || s->vex_l != 0) {
3675 goto illegal_op;
3677 ot = mo_64_32(s->dflag);
3678 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3679 switch (ot) {
3680 default:
3681 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3682 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3683 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3684 cpu_tmp2_i32, cpu_tmp3_i32);
3685 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3686 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
3687 break;
3688 #ifdef TARGET_X86_64
3689 case MO_64:
3690 tcg_gen_mulu2_i64(cpu_T0, cpu_T1,
3691 cpu_T0, cpu_regs[R_EDX]);
3692 tcg_gen_mov_i64(cpu_regs[s->vex_v], cpu_T0);
3693 tcg_gen_mov_i64(cpu_regs[reg], cpu_T1);
3694 break;
3695 #endif
3697 break;
3699 case 0x3f5: /* pdep Gy, By, Ey */
3700 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3701 || !(s->prefix & PREFIX_VEX)
3702 || s->vex_l != 0) {
3703 goto illegal_op;
3705 ot = mo_64_32(s->dflag);
3706 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3707 /* Note that by zero-extending the mask operand, we
3708 automatically handle zero-extending the result. */
3709 if (ot == MO_64) {
3710 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3711 } else {
3712 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3714 gen_helper_pdep(cpu_regs[reg], cpu_T0, cpu_T1);
3715 break;
3717 case 0x2f5: /* pext Gy, By, Ey */
3718 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3719 || !(s->prefix & PREFIX_VEX)
3720 || s->vex_l != 0) {
3721 goto illegal_op;
3723 ot = mo_64_32(s->dflag);
3724 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3725 /* Note that by zero-extending the mask operand, we
3726 automatically handle zero-extending the result. */
3727 if (ot == MO_64) {
3728 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3729 } else {
3730 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3732 gen_helper_pext(cpu_regs[reg], cpu_T0, cpu_T1);
3733 break;
3735 case 0x1f6: /* adcx Gy, Ey */
3736 case 0x2f6: /* adox Gy, Ey */
3737 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3738 goto illegal_op;
3739 } else {
3740 TCGv carry_in, carry_out, zero;
3741 int end_op;
3743 ot = mo_64_32(s->dflag);
3744 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3746 /* Re-use the carry-out from a previous round. */
3747 TCGV_UNUSED(carry_in);
3748 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3749 switch (s->cc_op) {
3750 case CC_OP_ADCX:
3751 if (b == 0x1f6) {
3752 carry_in = cpu_cc_dst;
3753 end_op = CC_OP_ADCX;
3754 } else {
3755 end_op = CC_OP_ADCOX;
3757 break;
3758 case CC_OP_ADOX:
3759 if (b == 0x1f6) {
3760 end_op = CC_OP_ADCOX;
3761 } else {
3762 carry_in = cpu_cc_src2;
3763 end_op = CC_OP_ADOX;
3765 break;
3766 case CC_OP_ADCOX:
3767 end_op = CC_OP_ADCOX;
3768 carry_in = carry_out;
3769 break;
3770 default:
3771 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
3772 break;
3774 /* If we can't reuse carry-out, get it out of EFLAGS. */
3775 if (TCGV_IS_UNUSED(carry_in)) {
3776 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3777 gen_compute_eflags(s);
3779 carry_in = cpu_tmp0;
3780 tcg_gen_shri_tl(carry_in, cpu_cc_src,
3781 ctz32(b == 0x1f6 ? CC_C : CC_O));
3782 tcg_gen_andi_tl(carry_in, carry_in, 1);
3785 switch (ot) {
3786 #ifdef TARGET_X86_64
3787 case MO_32:
3788 /* If we know TL is 64-bit, and we want a 32-bit
3789 result, just do everything in 64-bit arithmetic. */
3790 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3791 tcg_gen_ext32u_i64(cpu_T0, cpu_T0);
3792 tcg_gen_add_i64(cpu_T0, cpu_T0, cpu_regs[reg]);
3793 tcg_gen_add_i64(cpu_T0, cpu_T0, carry_in);
3794 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T0);
3795 tcg_gen_shri_i64(carry_out, cpu_T0, 32);
3796 break;
3797 #endif
3798 default:
3799 /* Otherwise compute the carry-out in two steps. */
3800 zero = tcg_const_tl(0);
3801 tcg_gen_add2_tl(cpu_T0, carry_out,
3802 cpu_T0, zero,
3803 carry_in, zero);
3804 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3805 cpu_regs[reg], carry_out,
3806 cpu_T0, zero);
3807 tcg_temp_free(zero);
3808 break;
3810 set_cc_op(s, end_op);
3812 break;
3814 case 0x1f7: /* shlx Gy, Ey, By */
3815 case 0x2f7: /* sarx Gy, Ey, By */
3816 case 0x3f7: /* shrx Gy, Ey, By */
3817 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3818 || !(s->prefix & PREFIX_VEX)
3819 || s->vex_l != 0) {
3820 goto illegal_op;
3822 ot = mo_64_32(s->dflag);
3823 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3824 if (ot == MO_64) {
3825 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 63);
3826 } else {
3827 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 31);
3829 if (b == 0x1f7) {
3830 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
3831 } else if (b == 0x2f7) {
3832 if (ot != MO_64) {
3833 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
3835 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
3836 } else {
3837 if (ot != MO_64) {
3838 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
3840 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
3842 gen_op_mov_reg_v(ot, reg, cpu_T0);
3843 break;
3845 case 0x0f3:
3846 case 0x1f3:
3847 case 0x2f3:
3848 case 0x3f3: /* Group 17 */
3849 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3850 || !(s->prefix & PREFIX_VEX)
3851 || s->vex_l != 0) {
3852 goto illegal_op;
3854 ot = mo_64_32(s->dflag);
3855 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3857 switch (reg & 7) {
3858 case 1: /* blsr By,Ey */
3859 tcg_gen_neg_tl(cpu_T1, cpu_T0);
3860 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
3861 gen_op_mov_reg_v(ot, s->vex_v, cpu_T0);
3862 gen_op_update2_cc();
3863 set_cc_op(s, CC_OP_BMILGB + ot);
3864 break;
3866 case 2: /* blsmsk By,Ey */
3867 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
3868 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
3869 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_cc_src);
3870 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
3871 set_cc_op(s, CC_OP_BMILGB + ot);
3872 break;
3874 case 3: /* blsi By, Ey */
3875 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
3876 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
3877 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_cc_src);
3878 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
3879 set_cc_op(s, CC_OP_BMILGB + ot);
3880 break;
3882 default:
3883 goto illegal_op;
3885 break;
3887 default:
3888 goto illegal_op;
3890 break;
3892 case 0x03a:
3893 case 0x13a:
3894 b = modrm;
3895 modrm = cpu_ldub_code(env, s->pc++);
3896 rm = modrm & 7;
3897 reg = ((modrm >> 3) & 7) | rex_r;
3898 mod = (modrm >> 6) & 3;
3899 if (b1 >= 2) {
3900 goto illegal_op;
3903 sse_fn_eppi = sse_op_table7[b].op[b1];
3904 if (!sse_fn_eppi) {
3905 goto illegal_op;
3907 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
3908 goto illegal_op;
3910 if (sse_fn_eppi == SSE_SPECIAL) {
3911 ot = mo_64_32(s->dflag);
3912 rm = (modrm & 7) | REX_B(s);
3913 if (mod != 3)
3914 gen_lea_modrm(env, s, modrm);
3915 reg = ((modrm >> 3) & 7) | rex_r;
3916 val = cpu_ldub_code(env, s->pc++);
3917 switch (b) {
3918 case 0x14: /* pextrb */
3919 tcg_gen_ld8u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
3920 xmm_regs[reg].ZMM_B(val & 15)));
3921 if (mod == 3) {
3922 gen_op_mov_reg_v(ot, rm, cpu_T0);
3923 } else {
3924 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
3925 s->mem_index, MO_UB);
3927 break;
3928 case 0x15: /* pextrw */
3929 tcg_gen_ld16u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
3930 xmm_regs[reg].ZMM_W(val & 7)));
3931 if (mod == 3) {
3932 gen_op_mov_reg_v(ot, rm, cpu_T0);
3933 } else {
3934 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
3935 s->mem_index, MO_LEUW);
3937 break;
3938 case 0x16:
3939 if (ot == MO_32) { /* pextrd */
3940 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
3941 offsetof(CPUX86State,
3942 xmm_regs[reg].ZMM_L(val & 3)));
3943 if (mod == 3) {
3944 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
3945 } else {
3946 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
3947 s->mem_index, MO_LEUL);
3949 } else { /* pextrq */
3950 #ifdef TARGET_X86_64
3951 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3952 offsetof(CPUX86State,
3953 xmm_regs[reg].ZMM_Q(val & 1)));
3954 if (mod == 3) {
3955 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
3956 } else {
3957 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
3958 s->mem_index, MO_LEQ);
3960 #else
3961 goto illegal_op;
3962 #endif
3964 break;
3965 case 0x17: /* extractps */
3966 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
3967 xmm_regs[reg].ZMM_L(val & 3)));
3968 if (mod == 3) {
3969 gen_op_mov_reg_v(ot, rm, cpu_T0);
3970 } else {
3971 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
3972 s->mem_index, MO_LEUL);
3974 break;
3975 case 0x20: /* pinsrb */
3976 if (mod == 3) {
3977 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
3978 } else {
3979 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
3980 s->mem_index, MO_UB);
3982 tcg_gen_st8_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
3983 xmm_regs[reg].ZMM_B(val & 15)));
3984 break;
3985 case 0x21: /* insertps */
3986 if (mod == 3) {
3987 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
3988 offsetof(CPUX86State,xmm_regs[rm]
3989 .ZMM_L((val >> 6) & 3)));
3990 } else {
3991 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3992 s->mem_index, MO_LEUL);
3994 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
3995 offsetof(CPUX86State,xmm_regs[reg]
3996 .ZMM_L((val >> 4) & 3)));
3997 if ((val >> 0) & 1)
3998 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
3999 cpu_env, offsetof(CPUX86State,
4000 xmm_regs[reg].ZMM_L(0)));
4001 if ((val >> 1) & 1)
4002 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4003 cpu_env, offsetof(CPUX86State,
4004 xmm_regs[reg].ZMM_L(1)));
4005 if ((val >> 2) & 1)
4006 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4007 cpu_env, offsetof(CPUX86State,
4008 xmm_regs[reg].ZMM_L(2)));
4009 if ((val >> 3) & 1)
4010 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4011 cpu_env, offsetof(CPUX86State,
4012 xmm_regs[reg].ZMM_L(3)));
4013 break;
4014 case 0x22:
4015 if (ot == MO_32) { /* pinsrd */
4016 if (mod == 3) {
4017 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
4018 } else {
4019 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4020 s->mem_index, MO_LEUL);
4022 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4023 offsetof(CPUX86State,
4024 xmm_regs[reg].ZMM_L(val & 3)));
4025 } else { /* pinsrq */
4026 #ifdef TARGET_X86_64
4027 if (mod == 3) {
4028 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4029 } else {
4030 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4031 s->mem_index, MO_LEQ);
4033 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4034 offsetof(CPUX86State,
4035 xmm_regs[reg].ZMM_Q(val & 1)));
4036 #else
4037 goto illegal_op;
4038 #endif
4040 break;
4042 return;
4045 if (b1) {
4046 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4047 if (mod == 3) {
4048 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4049 } else {
4050 op2_offset = offsetof(CPUX86State,xmm_t0);
4051 gen_lea_modrm(env, s, modrm);
4052 gen_ldo_env_A0(s, op2_offset);
4054 } else {
4055 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4056 if (mod == 3) {
4057 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4058 } else {
4059 op2_offset = offsetof(CPUX86State,mmx_t0);
4060 gen_lea_modrm(env, s, modrm);
4061 gen_ldq_env_A0(s, op2_offset);
4064 val = cpu_ldub_code(env, s->pc++);
4066 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4067 set_cc_op(s, CC_OP_EFLAGS);
4069 if (s->dflag == MO_64) {
4070 /* The helper must use entire 64-bit gp registers */
4071 val |= 1 << 8;
4075 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4076 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4077 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4078 break;
4080 case 0x33a:
4081 /* Various integer extensions at 0f 3a f[0-f]. */
4082 b = modrm | (b1 << 8);
4083 modrm = cpu_ldub_code(env, s->pc++);
4084 reg = ((modrm >> 3) & 7) | rex_r;
4086 switch (b) {
4087 case 0x3f0: /* rorx Gy,Ey, Ib */
4088 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4089 || !(s->prefix & PREFIX_VEX)
4090 || s->vex_l != 0) {
4091 goto illegal_op;
4093 ot = mo_64_32(s->dflag);
4094 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4095 b = cpu_ldub_code(env, s->pc++);
4096 if (ot == MO_64) {
4097 tcg_gen_rotri_tl(cpu_T0, cpu_T0, b & 63);
4098 } else {
4099 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4100 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4101 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
4103 gen_op_mov_reg_v(ot, reg, cpu_T0);
4104 break;
4106 default:
4107 goto illegal_op;
4109 break;
4111 default:
4112 goto illegal_op;
4114 } else {
4115 /* generic MMX or SSE operation */
4116 switch(b) {
4117 case 0x70: /* pshufx insn */
4118 case 0xc6: /* pshufx insn */
4119 case 0xc2: /* compare insns */
4120 s->rip_offset = 1;
4121 break;
4122 default:
4123 break;
4125 if (is_xmm) {
4126 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4127 if (mod != 3) {
4128 int sz = 4;
4130 gen_lea_modrm(env, s, modrm);
4131 op2_offset = offsetof(CPUX86State,xmm_t0);
4133 switch (b) {
4134 case 0x50 ... 0x5a:
4135 case 0x5c ... 0x5f:
4136 case 0xc2:
4137 /* Most sse scalar operations. */
4138 if (b1 == 2) {
4139 sz = 2;
4140 } else if (b1 == 3) {
4141 sz = 3;
4143 break;
4145 case 0x2e: /* ucomis[sd] */
4146 case 0x2f: /* comis[sd] */
4147 if (b1 == 0) {
4148 sz = 2;
4149 } else {
4150 sz = 3;
4152 break;
4155 switch (sz) {
4156 case 2:
4157 /* 32 bit access */
4158 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
4159 tcg_gen_st32_tl(cpu_T0, cpu_env,
4160 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4161 break;
4162 case 3:
4163 /* 64 bit access */
4164 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4165 break;
4166 default:
4167 /* 128 bit access */
4168 gen_ldo_env_A0(s, op2_offset);
4169 break;
4171 } else {
4172 rm = (modrm & 7) | REX_B(s);
4173 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4175 } else {
4176 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4177 if (mod != 3) {
4178 gen_lea_modrm(env, s, modrm);
4179 op2_offset = offsetof(CPUX86State,mmx_t0);
4180 gen_ldq_env_A0(s, op2_offset);
4181 } else {
4182 rm = (modrm & 7);
4183 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4186 switch(b) {
4187 case 0x0f: /* 3DNow! data insns */
4188 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4189 goto illegal_op;
4190 val = cpu_ldub_code(env, s->pc++);
4191 sse_fn_epp = sse_op_table5[val];
4192 if (!sse_fn_epp) {
4193 goto illegal_op;
4195 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4196 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4197 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4198 break;
4199 case 0x70: /* pshufx insn */
4200 case 0xc6: /* pshufx insn */
4201 val = cpu_ldub_code(env, s->pc++);
4202 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4203 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4204 /* XXX: introduce a new table? */
4205 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4206 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4207 break;
4208 case 0xc2:
4209 /* compare insns */
4210 val = cpu_ldub_code(env, s->pc++);
4211 if (val >= 8)
4212 goto illegal_op;
4213 sse_fn_epp = sse_op_table4[val][b1];
4215 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4216 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4217 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4218 break;
4219 case 0xf7:
4220 /* maskmov : we must prepare A0 */
4221 if (mod != 3)
4222 goto illegal_op;
4223 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4224 gen_extu(s->aflag, cpu_A0);
4225 gen_add_A0_ds_seg(s);
4227 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4228 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4229 /* XXX: introduce a new table? */
4230 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4231 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4232 break;
4233 default:
4234 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4235 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4236 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4237 break;
4239 if (b == 0x2e || b == 0x2f) {
4240 set_cc_op(s, CC_OP_EFLAGS);
4245 /* convert one instruction. s->is_jmp is set if the translation must
4246 be stopped. Return the next pc value */
4247 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4248 target_ulong pc_start)
4250 int b, prefixes;
4251 int shift;
4252 TCGMemOp ot, aflag, dflag;
4253 int modrm, reg, rm, mod, op, opreg, val;
4254 target_ulong next_eip, tval;
4255 int rex_w, rex_r;
4257 s->pc = pc_start;
4258 prefixes = 0;
4259 s->override = -1;
4260 rex_w = -1;
4261 rex_r = 0;
4262 #ifdef TARGET_X86_64
4263 s->rex_x = 0;
4264 s->rex_b = 0;
4265 x86_64_hregs = 0;
4266 #endif
4267 s->rip_offset = 0; /* for relative ip address */
4268 s->vex_l = 0;
4269 s->vex_v = 0;
4270 next_byte:
4271 b = cpu_ldub_code(env, s->pc);
4272 s->pc++;
4273 /* Collect prefixes. */
4274 switch (b) {
4275 case 0xf3:
4276 prefixes |= PREFIX_REPZ;
4277 goto next_byte;
4278 case 0xf2:
4279 prefixes |= PREFIX_REPNZ;
4280 goto next_byte;
4281 case 0xf0:
4282 prefixes |= PREFIX_LOCK;
4283 goto next_byte;
4284 case 0x2e:
4285 s->override = R_CS;
4286 goto next_byte;
4287 case 0x36:
4288 s->override = R_SS;
4289 goto next_byte;
4290 case 0x3e:
4291 s->override = R_DS;
4292 goto next_byte;
4293 case 0x26:
4294 s->override = R_ES;
4295 goto next_byte;
4296 case 0x64:
4297 s->override = R_FS;
4298 goto next_byte;
4299 case 0x65:
4300 s->override = R_GS;
4301 goto next_byte;
4302 case 0x66:
4303 prefixes |= PREFIX_DATA;
4304 goto next_byte;
4305 case 0x67:
4306 prefixes |= PREFIX_ADR;
4307 goto next_byte;
4308 #ifdef TARGET_X86_64
4309 case 0x40 ... 0x4f:
4310 if (CODE64(s)) {
4311 /* REX prefix */
4312 rex_w = (b >> 3) & 1;
4313 rex_r = (b & 0x4) << 1;
4314 s->rex_x = (b & 0x2) << 2;
4315 REX_B(s) = (b & 0x1) << 3;
4316 x86_64_hregs = 1; /* select uniform byte register addressing */
4317 goto next_byte;
4319 break;
4320 #endif
4321 case 0xc5: /* 2-byte VEX */
4322 case 0xc4: /* 3-byte VEX */
4323 /* VEX prefixes cannot be used except in 32-bit mode.
4324 Otherwise the instruction is LES or LDS. */
4325 if (s->code32 && !s->vm86) {
4326 static const int pp_prefix[4] = {
4327 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4329 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4331 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4332 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4333 otherwise the instruction is LES or LDS. */
4334 break;
4336 s->pc++;
4338 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4339 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4340 | PREFIX_LOCK | PREFIX_DATA)) {
4341 goto illegal_op;
4343 #ifdef TARGET_X86_64
4344 if (x86_64_hregs) {
4345 goto illegal_op;
4347 #endif
4348 rex_r = (~vex2 >> 4) & 8;
4349 if (b == 0xc5) {
4350 vex3 = vex2;
4351 b = cpu_ldub_code(env, s->pc++);
4352 } else {
4353 #ifdef TARGET_X86_64
4354 s->rex_x = (~vex2 >> 3) & 8;
4355 s->rex_b = (~vex2 >> 2) & 8;
4356 #endif
4357 vex3 = cpu_ldub_code(env, s->pc++);
4358 rex_w = (vex3 >> 7) & 1;
4359 switch (vex2 & 0x1f) {
4360 case 0x01: /* Implied 0f leading opcode bytes. */
4361 b = cpu_ldub_code(env, s->pc++) | 0x100;
4362 break;
4363 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4364 b = 0x138;
4365 break;
4366 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4367 b = 0x13a;
4368 break;
4369 default: /* Reserved for future use. */
4370 goto illegal_op;
4373 s->vex_v = (~vex3 >> 3) & 0xf;
4374 s->vex_l = (vex3 >> 2) & 1;
4375 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4377 break;
4380 /* Post-process prefixes. */
4381 if (CODE64(s)) {
4382 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4383 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4384 over 0x66 if both are present. */
4385 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4386 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4387 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4388 } else {
4389 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4390 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4391 dflag = MO_32;
4392 } else {
4393 dflag = MO_16;
4395 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4396 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4397 aflag = MO_32;
4398 } else {
4399 aflag = MO_16;
4403 s->prefix = prefixes;
4404 s->aflag = aflag;
4405 s->dflag = dflag;
4407 /* lock generation */
4408 if (prefixes & PREFIX_LOCK)
4409 gen_helper_lock();
4411 /* now check op code */
4412 reswitch:
4413 switch(b) {
4414 case 0x0f:
4415 /**************************/
4416 /* extended op code */
4417 b = cpu_ldub_code(env, s->pc++) | 0x100;
4418 goto reswitch;
4420 /**************************/
4421 /* arith & logic */
4422 case 0x00 ... 0x05:
4423 case 0x08 ... 0x0d:
4424 case 0x10 ... 0x15:
4425 case 0x18 ... 0x1d:
4426 case 0x20 ... 0x25:
4427 case 0x28 ... 0x2d:
4428 case 0x30 ... 0x35:
4429 case 0x38 ... 0x3d:
4431 int op, f, val;
4432 op = (b >> 3) & 7;
4433 f = (b >> 1) & 3;
4435 ot = mo_b_d(b, dflag);
4437 switch(f) {
4438 case 0: /* OP Ev, Gv */
4439 modrm = cpu_ldub_code(env, s->pc++);
4440 reg = ((modrm >> 3) & 7) | rex_r;
4441 mod = (modrm >> 6) & 3;
4442 rm = (modrm & 7) | REX_B(s);
4443 if (mod != 3) {
4444 gen_lea_modrm(env, s, modrm);
4445 opreg = OR_TMP0;
4446 } else if (op == OP_XORL && rm == reg) {
4447 xor_zero:
4448 /* xor reg, reg optimisation */
4449 set_cc_op(s, CC_OP_CLR);
4450 tcg_gen_movi_tl(cpu_T0, 0);
4451 gen_op_mov_reg_v(ot, reg, cpu_T0);
4452 break;
4453 } else {
4454 opreg = rm;
4456 gen_op_mov_v_reg(ot, cpu_T1, reg);
4457 gen_op(s, op, ot, opreg);
4458 break;
4459 case 1: /* OP Gv, Ev */
4460 modrm = cpu_ldub_code(env, s->pc++);
4461 mod = (modrm >> 6) & 3;
4462 reg = ((modrm >> 3) & 7) | rex_r;
4463 rm = (modrm & 7) | REX_B(s);
4464 if (mod != 3) {
4465 gen_lea_modrm(env, s, modrm);
4466 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4467 } else if (op == OP_XORL && rm == reg) {
4468 goto xor_zero;
4469 } else {
4470 gen_op_mov_v_reg(ot, cpu_T1, rm);
4472 gen_op(s, op, ot, reg);
4473 break;
4474 case 2: /* OP A, Iv */
4475 val = insn_get(env, s, ot);
4476 tcg_gen_movi_tl(cpu_T1, val);
4477 gen_op(s, op, ot, OR_EAX);
4478 break;
4481 break;
4483 case 0x82:
4484 if (CODE64(s))
4485 goto illegal_op;
4486 case 0x80: /* GRP1 */
4487 case 0x81:
4488 case 0x83:
4490 int val;
4492 ot = mo_b_d(b, dflag);
4494 modrm = cpu_ldub_code(env, s->pc++);
4495 mod = (modrm >> 6) & 3;
4496 rm = (modrm & 7) | REX_B(s);
4497 op = (modrm >> 3) & 7;
4499 if (mod != 3) {
4500 if (b == 0x83)
4501 s->rip_offset = 1;
4502 else
4503 s->rip_offset = insn_const_size(ot);
4504 gen_lea_modrm(env, s, modrm);
4505 opreg = OR_TMP0;
4506 } else {
4507 opreg = rm;
4510 switch(b) {
4511 default:
4512 case 0x80:
4513 case 0x81:
4514 case 0x82:
4515 val = insn_get(env, s, ot);
4516 break;
4517 case 0x83:
4518 val = (int8_t)insn_get(env, s, MO_8);
4519 break;
4521 tcg_gen_movi_tl(cpu_T1, val);
4522 gen_op(s, op, ot, opreg);
4524 break;
4526 /**************************/
4527 /* inc, dec, and other misc arith */
4528 case 0x40 ... 0x47: /* inc Gv */
4529 ot = dflag;
4530 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4531 break;
4532 case 0x48 ... 0x4f: /* dec Gv */
4533 ot = dflag;
4534 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4535 break;
4536 case 0xf6: /* GRP3 */
4537 case 0xf7:
4538 ot = mo_b_d(b, dflag);
4540 modrm = cpu_ldub_code(env, s->pc++);
4541 mod = (modrm >> 6) & 3;
4542 rm = (modrm & 7) | REX_B(s);
4543 op = (modrm >> 3) & 7;
4544 if (mod != 3) {
4545 if (op == 0)
4546 s->rip_offset = insn_const_size(ot);
4547 gen_lea_modrm(env, s, modrm);
4548 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4549 } else {
4550 gen_op_mov_v_reg(ot, cpu_T0, rm);
4553 switch(op) {
4554 case 0: /* test */
4555 val = insn_get(env, s, ot);
4556 tcg_gen_movi_tl(cpu_T1, val);
4557 gen_op_testl_T0_T1_cc();
4558 set_cc_op(s, CC_OP_LOGICB + ot);
4559 break;
4560 case 2: /* not */
4561 tcg_gen_not_tl(cpu_T0, cpu_T0);
4562 if (mod != 3) {
4563 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4564 } else {
4565 gen_op_mov_reg_v(ot, rm, cpu_T0);
4567 break;
4568 case 3: /* neg */
4569 tcg_gen_neg_tl(cpu_T0, cpu_T0);
4570 if (mod != 3) {
4571 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4572 } else {
4573 gen_op_mov_reg_v(ot, rm, cpu_T0);
4575 gen_op_update_neg_cc();
4576 set_cc_op(s, CC_OP_SUBB + ot);
4577 break;
4578 case 4: /* mul */
4579 switch(ot) {
4580 case MO_8:
4581 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4582 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
4583 tcg_gen_ext8u_tl(cpu_T1, cpu_T1);
4584 /* XXX: use 32 bit mul which could be faster */
4585 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4586 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4587 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4588 tcg_gen_andi_tl(cpu_cc_src, cpu_T0, 0xff00);
4589 set_cc_op(s, CC_OP_MULB);
4590 break;
4591 case MO_16:
4592 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4593 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4594 tcg_gen_ext16u_tl(cpu_T1, cpu_T1);
4595 /* XXX: use 32 bit mul which could be faster */
4596 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4597 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4598 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4599 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4600 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4601 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4602 set_cc_op(s, CC_OP_MULW);
4603 break;
4604 default:
4605 case MO_32:
4606 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4607 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4608 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4609 cpu_tmp2_i32, cpu_tmp3_i32);
4610 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4611 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4612 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4613 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4614 set_cc_op(s, CC_OP_MULL);
4615 break;
4616 #ifdef TARGET_X86_64
4617 case MO_64:
4618 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4619 cpu_T0, cpu_regs[R_EAX]);
4620 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4621 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4622 set_cc_op(s, CC_OP_MULQ);
4623 break;
4624 #endif
4626 break;
4627 case 5: /* imul */
4628 switch(ot) {
4629 case MO_8:
4630 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4631 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
4632 tcg_gen_ext8s_tl(cpu_T1, cpu_T1);
4633 /* XXX: use 32 bit mul which could be faster */
4634 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4635 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4636 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4637 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T0);
4638 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4639 set_cc_op(s, CC_OP_MULB);
4640 break;
4641 case MO_16:
4642 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4643 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4644 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
4645 /* XXX: use 32 bit mul which could be faster */
4646 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4647 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4648 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4649 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
4650 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4651 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4652 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4653 set_cc_op(s, CC_OP_MULW);
4654 break;
4655 default:
4656 case MO_32:
4657 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4658 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4659 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4660 cpu_tmp2_i32, cpu_tmp3_i32);
4661 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4662 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4663 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4664 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4665 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4666 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4667 set_cc_op(s, CC_OP_MULL);
4668 break;
4669 #ifdef TARGET_X86_64
4670 case MO_64:
4671 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4672 cpu_T0, cpu_regs[R_EAX]);
4673 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4674 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4675 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4676 set_cc_op(s, CC_OP_MULQ);
4677 break;
4678 #endif
4680 break;
4681 case 6: /* div */
4682 switch(ot) {
4683 case MO_8:
4684 gen_helper_divb_AL(cpu_env, cpu_T0);
4685 break;
4686 case MO_16:
4687 gen_helper_divw_AX(cpu_env, cpu_T0);
4688 break;
4689 default:
4690 case MO_32:
4691 gen_helper_divl_EAX(cpu_env, cpu_T0);
4692 break;
4693 #ifdef TARGET_X86_64
4694 case MO_64:
4695 gen_helper_divq_EAX(cpu_env, cpu_T0);
4696 break;
4697 #endif
4699 break;
4700 case 7: /* idiv */
4701 switch(ot) {
4702 case MO_8:
4703 gen_helper_idivb_AL(cpu_env, cpu_T0);
4704 break;
4705 case MO_16:
4706 gen_helper_idivw_AX(cpu_env, cpu_T0);
4707 break;
4708 default:
4709 case MO_32:
4710 gen_helper_idivl_EAX(cpu_env, cpu_T0);
4711 break;
4712 #ifdef TARGET_X86_64
4713 case MO_64:
4714 gen_helper_idivq_EAX(cpu_env, cpu_T0);
4715 break;
4716 #endif
4718 break;
4719 default:
4720 goto illegal_op;
4722 break;
4724 case 0xfe: /* GRP4 */
4725 case 0xff: /* GRP5 */
4726 ot = mo_b_d(b, dflag);
4728 modrm = cpu_ldub_code(env, s->pc++);
4729 mod = (modrm >> 6) & 3;
4730 rm = (modrm & 7) | REX_B(s);
4731 op = (modrm >> 3) & 7;
4732 if (op >= 2 && b == 0xfe) {
4733 goto illegal_op;
4735 if (CODE64(s)) {
4736 if (op == 2 || op == 4) {
4737 /* operand size for jumps is 64 bit */
4738 ot = MO_64;
4739 } else if (op == 3 || op == 5) {
4740 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
4741 } else if (op == 6) {
4742 /* default push size is 64 bit */
4743 ot = mo_pushpop(s, dflag);
4746 if (mod != 3) {
4747 gen_lea_modrm(env, s, modrm);
4748 if (op >= 2 && op != 3 && op != 5)
4749 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4750 } else {
4751 gen_op_mov_v_reg(ot, cpu_T0, rm);
4754 switch(op) {
4755 case 0: /* inc Ev */
4756 if (mod != 3)
4757 opreg = OR_TMP0;
4758 else
4759 opreg = rm;
4760 gen_inc(s, ot, opreg, 1);
4761 break;
4762 case 1: /* dec Ev */
4763 if (mod != 3)
4764 opreg = OR_TMP0;
4765 else
4766 opreg = rm;
4767 gen_inc(s, ot, opreg, -1);
4768 break;
4769 case 2: /* call Ev */
4770 /* XXX: optimize if memory (no 'and' is necessary) */
4771 if (dflag == MO_16) {
4772 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4774 next_eip = s->pc - s->cs_base;
4775 tcg_gen_movi_tl(cpu_T1, next_eip);
4776 gen_push_v(s, cpu_T1);
4777 gen_op_jmp_v(cpu_T0);
4778 gen_eob(s);
4779 break;
4780 case 3: /* lcall Ev */
4781 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4782 gen_add_A0_im(s, 1 << ot);
4783 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
4784 do_lcall:
4785 if (s->pe && !s->vm86) {
4786 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4787 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
4788 tcg_const_i32(dflag - 1),
4789 tcg_const_tl(s->pc - s->cs_base));
4790 } else {
4791 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4792 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T1,
4793 tcg_const_i32(dflag - 1),
4794 tcg_const_i32(s->pc - s->cs_base));
4796 gen_eob(s);
4797 break;
4798 case 4: /* jmp Ev */
4799 if (dflag == MO_16) {
4800 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4802 gen_op_jmp_v(cpu_T0);
4803 gen_eob(s);
4804 break;
4805 case 5: /* ljmp Ev */
4806 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4807 gen_add_A0_im(s, 1 << ot);
4808 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
4809 do_ljmp:
4810 if (s->pe && !s->vm86) {
4811 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4812 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
4813 tcg_const_tl(s->pc - s->cs_base));
4814 } else {
4815 gen_op_movl_seg_T0_vm(R_CS);
4816 gen_op_jmp_v(cpu_T1);
4818 gen_eob(s);
4819 break;
4820 case 6: /* push Ev */
4821 gen_push_v(s, cpu_T0);
4822 break;
4823 default:
4824 goto illegal_op;
4826 break;
4828 case 0x84: /* test Ev, Gv */
4829 case 0x85:
4830 ot = mo_b_d(b, dflag);
4832 modrm = cpu_ldub_code(env, s->pc++);
4833 reg = ((modrm >> 3) & 7) | rex_r;
4835 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4836 gen_op_mov_v_reg(ot, cpu_T1, reg);
4837 gen_op_testl_T0_T1_cc();
4838 set_cc_op(s, CC_OP_LOGICB + ot);
4839 break;
4841 case 0xa8: /* test eAX, Iv */
4842 case 0xa9:
4843 ot = mo_b_d(b, dflag);
4844 val = insn_get(env, s, ot);
4846 gen_op_mov_v_reg(ot, cpu_T0, OR_EAX);
4847 tcg_gen_movi_tl(cpu_T1, val);
4848 gen_op_testl_T0_T1_cc();
4849 set_cc_op(s, CC_OP_LOGICB + ot);
4850 break;
4852 case 0x98: /* CWDE/CBW */
4853 switch (dflag) {
4854 #ifdef TARGET_X86_64
4855 case MO_64:
4856 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
4857 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
4858 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T0);
4859 break;
4860 #endif
4861 case MO_32:
4862 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
4863 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4864 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T0);
4865 break;
4866 case MO_16:
4867 gen_op_mov_v_reg(MO_8, cpu_T0, R_EAX);
4868 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
4869 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4870 break;
4871 default:
4872 tcg_abort();
4874 break;
4875 case 0x99: /* CDQ/CWD */
4876 switch (dflag) {
4877 #ifdef TARGET_X86_64
4878 case MO_64:
4879 gen_op_mov_v_reg(MO_64, cpu_T0, R_EAX);
4880 tcg_gen_sari_tl(cpu_T0, cpu_T0, 63);
4881 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T0);
4882 break;
4883 #endif
4884 case MO_32:
4885 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
4886 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
4887 tcg_gen_sari_tl(cpu_T0, cpu_T0, 31);
4888 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T0);
4889 break;
4890 case MO_16:
4891 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
4892 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4893 tcg_gen_sari_tl(cpu_T0, cpu_T0, 15);
4894 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4895 break;
4896 default:
4897 tcg_abort();
4899 break;
4900 case 0x1af: /* imul Gv, Ev */
4901 case 0x69: /* imul Gv, Ev, I */
4902 case 0x6b:
4903 ot = dflag;
4904 modrm = cpu_ldub_code(env, s->pc++);
4905 reg = ((modrm >> 3) & 7) | rex_r;
4906 if (b == 0x69)
4907 s->rip_offset = insn_const_size(ot);
4908 else if (b == 0x6b)
4909 s->rip_offset = 1;
4910 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4911 if (b == 0x69) {
4912 val = insn_get(env, s, ot);
4913 tcg_gen_movi_tl(cpu_T1, val);
4914 } else if (b == 0x6b) {
4915 val = (int8_t)insn_get(env, s, MO_8);
4916 tcg_gen_movi_tl(cpu_T1, val);
4917 } else {
4918 gen_op_mov_v_reg(ot, cpu_T1, reg);
4920 switch (ot) {
4921 #ifdef TARGET_X86_64
4922 case MO_64:
4923 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T1, cpu_T0, cpu_T1);
4924 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
4925 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
4926 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T1);
4927 break;
4928 #endif
4929 case MO_32:
4930 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4931 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
4932 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4933 cpu_tmp2_i32, cpu_tmp3_i32);
4934 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
4935 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4936 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
4937 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4938 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4939 break;
4940 default:
4941 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4942 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
4943 /* XXX: use 32 bit mul which could be faster */
4944 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4945 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4946 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
4947 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4948 gen_op_mov_reg_v(ot, reg, cpu_T0);
4949 break;
4951 set_cc_op(s, CC_OP_MULB + ot);
4952 break;
4953 case 0x1c0:
4954 case 0x1c1: /* xadd Ev, Gv */
4955 ot = mo_b_d(b, dflag);
4956 modrm = cpu_ldub_code(env, s->pc++);
4957 reg = ((modrm >> 3) & 7) | rex_r;
4958 mod = (modrm >> 6) & 3;
4959 if (mod == 3) {
4960 rm = (modrm & 7) | REX_B(s);
4961 gen_op_mov_v_reg(ot, cpu_T0, reg);
4962 gen_op_mov_v_reg(ot, cpu_T1, rm);
4963 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
4964 gen_op_mov_reg_v(ot, reg, cpu_T1);
4965 gen_op_mov_reg_v(ot, rm, cpu_T0);
4966 } else {
4967 gen_lea_modrm(env, s, modrm);
4968 gen_op_mov_v_reg(ot, cpu_T0, reg);
4969 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4970 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
4971 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4972 gen_op_mov_reg_v(ot, reg, cpu_T1);
4974 gen_op_update2_cc();
4975 set_cc_op(s, CC_OP_ADDB + ot);
4976 break;
4977 case 0x1b0:
4978 case 0x1b1: /* cmpxchg Ev, Gv */
4980 TCGLabel *label1, *label2;
4981 TCGv t0, t1, t2, a0;
4983 ot = mo_b_d(b, dflag);
4984 modrm = cpu_ldub_code(env, s->pc++);
4985 reg = ((modrm >> 3) & 7) | rex_r;
4986 mod = (modrm >> 6) & 3;
4987 t0 = tcg_temp_local_new();
4988 t1 = tcg_temp_local_new();
4989 t2 = tcg_temp_local_new();
4990 a0 = tcg_temp_local_new();
4991 gen_op_mov_v_reg(ot, t1, reg);
4992 if (mod == 3) {
4993 rm = (modrm & 7) | REX_B(s);
4994 gen_op_mov_v_reg(ot, t0, rm);
4995 } else {
4996 gen_lea_modrm(env, s, modrm);
4997 tcg_gen_mov_tl(a0, cpu_A0);
4998 gen_op_ld_v(s, ot, t0, a0);
4999 rm = 0; /* avoid warning */
5001 label1 = gen_new_label();
5002 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5003 gen_extu(ot, t0);
5004 gen_extu(ot, t2);
5005 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
5006 label2 = gen_new_label();
5007 if (mod == 3) {
5008 gen_op_mov_reg_v(ot, R_EAX, t0);
5009 tcg_gen_br(label2);
5010 gen_set_label(label1);
5011 gen_op_mov_reg_v(ot, rm, t1);
5012 } else {
5013 /* perform no-op store cycle like physical cpu; must be
5014 before changing accumulator to ensure idempotency if
5015 the store faults and the instruction is restarted */
5016 gen_op_st_v(s, ot, t0, a0);
5017 gen_op_mov_reg_v(ot, R_EAX, t0);
5018 tcg_gen_br(label2);
5019 gen_set_label(label1);
5020 gen_op_st_v(s, ot, t1, a0);
5022 gen_set_label(label2);
5023 tcg_gen_mov_tl(cpu_cc_src, t0);
5024 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5025 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
5026 set_cc_op(s, CC_OP_SUBB + ot);
5027 tcg_temp_free(t0);
5028 tcg_temp_free(t1);
5029 tcg_temp_free(t2);
5030 tcg_temp_free(a0);
5032 break;
5033 case 0x1c7: /* cmpxchg8b */
5034 modrm = cpu_ldub_code(env, s->pc++);
5035 mod = (modrm >> 6) & 3;
5036 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5037 goto illegal_op;
5038 #ifdef TARGET_X86_64
5039 if (dflag == MO_64) {
5040 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5041 goto illegal_op;
5042 gen_lea_modrm(env, s, modrm);
5043 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5044 } else
5045 #endif
5047 if (!(s->cpuid_features & CPUID_CX8))
5048 goto illegal_op;
5049 gen_lea_modrm(env, s, modrm);
5050 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5052 set_cc_op(s, CC_OP_EFLAGS);
5053 break;
5055 /**************************/
5056 /* push/pop */
5057 case 0x50 ... 0x57: /* push */
5058 gen_op_mov_v_reg(MO_32, cpu_T0, (b & 7) | REX_B(s));
5059 gen_push_v(s, cpu_T0);
5060 break;
5061 case 0x58 ... 0x5f: /* pop */
5062 ot = gen_pop_T0(s);
5063 /* NOTE: order is important for pop %sp */
5064 gen_pop_update(s, ot);
5065 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T0);
5066 break;
5067 case 0x60: /* pusha */
5068 if (CODE64(s))
5069 goto illegal_op;
5070 gen_pusha(s);
5071 break;
5072 case 0x61: /* popa */
5073 if (CODE64(s))
5074 goto illegal_op;
5075 gen_popa(s);
5076 break;
5077 case 0x68: /* push Iv */
5078 case 0x6a:
5079 ot = mo_pushpop(s, dflag);
5080 if (b == 0x68)
5081 val = insn_get(env, s, ot);
5082 else
5083 val = (int8_t)insn_get(env, s, MO_8);
5084 tcg_gen_movi_tl(cpu_T0, val);
5085 gen_push_v(s, cpu_T0);
5086 break;
5087 case 0x8f: /* pop Ev */
5088 modrm = cpu_ldub_code(env, s->pc++);
5089 mod = (modrm >> 6) & 3;
5090 ot = gen_pop_T0(s);
5091 if (mod == 3) {
5092 /* NOTE: order is important for pop %sp */
5093 gen_pop_update(s, ot);
5094 rm = (modrm & 7) | REX_B(s);
5095 gen_op_mov_reg_v(ot, rm, cpu_T0);
5096 } else {
5097 /* NOTE: order is important too for MMU exceptions */
5098 s->popl_esp_hack = 1 << ot;
5099 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5100 s->popl_esp_hack = 0;
5101 gen_pop_update(s, ot);
5103 break;
5104 case 0xc8: /* enter */
5106 int level;
5107 val = cpu_lduw_code(env, s->pc);
5108 s->pc += 2;
5109 level = cpu_ldub_code(env, s->pc++);
5110 gen_enter(s, val, level);
5112 break;
5113 case 0xc9: /* leave */
5114 gen_leave(s);
5115 break;
5116 case 0x06: /* push es */
5117 case 0x0e: /* push cs */
5118 case 0x16: /* push ss */
5119 case 0x1e: /* push ds */
5120 if (CODE64(s))
5121 goto illegal_op;
5122 gen_op_movl_T0_seg(b >> 3);
5123 gen_push_v(s, cpu_T0);
5124 break;
5125 case 0x1a0: /* push fs */
5126 case 0x1a8: /* push gs */
5127 gen_op_movl_T0_seg((b >> 3) & 7);
5128 gen_push_v(s, cpu_T0);
5129 break;
5130 case 0x07: /* pop es */
5131 case 0x17: /* pop ss */
5132 case 0x1f: /* pop ds */
5133 if (CODE64(s))
5134 goto illegal_op;
5135 reg = b >> 3;
5136 ot = gen_pop_T0(s);
5137 gen_movl_seg_T0(s, reg);
5138 gen_pop_update(s, ot);
5139 if (reg == R_SS) {
5140 /* if reg == SS, inhibit interrupts/trace. */
5141 /* If several instructions disable interrupts, only the
5142 _first_ does it */
5143 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5144 gen_helper_set_inhibit_irq(cpu_env);
5145 s->tf = 0;
5147 if (s->is_jmp) {
5148 gen_jmp_im(s->pc - s->cs_base);
5149 gen_eob(s);
5151 break;
5152 case 0x1a1: /* pop fs */
5153 case 0x1a9: /* pop gs */
5154 ot = gen_pop_T0(s);
5155 gen_movl_seg_T0(s, (b >> 3) & 7);
5156 gen_pop_update(s, ot);
5157 if (s->is_jmp) {
5158 gen_jmp_im(s->pc - s->cs_base);
5159 gen_eob(s);
5161 break;
5163 /**************************/
5164 /* mov */
5165 case 0x88:
5166 case 0x89: /* mov Gv, Ev */
5167 ot = mo_b_d(b, dflag);
5168 modrm = cpu_ldub_code(env, s->pc++);
5169 reg = ((modrm >> 3) & 7) | rex_r;
5171 /* generate a generic store */
5172 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5173 break;
5174 case 0xc6:
5175 case 0xc7: /* mov Ev, Iv */
5176 ot = mo_b_d(b, dflag);
5177 modrm = cpu_ldub_code(env, s->pc++);
5178 mod = (modrm >> 6) & 3;
5179 if (mod != 3) {
5180 s->rip_offset = insn_const_size(ot);
5181 gen_lea_modrm(env, s, modrm);
5183 val = insn_get(env, s, ot);
5184 tcg_gen_movi_tl(cpu_T0, val);
5185 if (mod != 3) {
5186 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5187 } else {
5188 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T0);
5190 break;
5191 case 0x8a:
5192 case 0x8b: /* mov Ev, Gv */
5193 ot = mo_b_d(b, dflag);
5194 modrm = cpu_ldub_code(env, s->pc++);
5195 reg = ((modrm >> 3) & 7) | rex_r;
5197 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5198 gen_op_mov_reg_v(ot, reg, cpu_T0);
5199 break;
5200 case 0x8e: /* mov seg, Gv */
5201 modrm = cpu_ldub_code(env, s->pc++);
5202 reg = (modrm >> 3) & 7;
5203 if (reg >= 6 || reg == R_CS)
5204 goto illegal_op;
5205 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5206 gen_movl_seg_T0(s, reg);
5207 if (reg == R_SS) {
5208 /* if reg == SS, inhibit interrupts/trace */
5209 /* If several instructions disable interrupts, only the
5210 _first_ does it */
5211 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5212 gen_helper_set_inhibit_irq(cpu_env);
5213 s->tf = 0;
5215 if (s->is_jmp) {
5216 gen_jmp_im(s->pc - s->cs_base);
5217 gen_eob(s);
5219 break;
5220 case 0x8c: /* mov Gv, seg */
5221 modrm = cpu_ldub_code(env, s->pc++);
5222 reg = (modrm >> 3) & 7;
5223 mod = (modrm >> 6) & 3;
5224 if (reg >= 6)
5225 goto illegal_op;
5226 gen_op_movl_T0_seg(reg);
5227 ot = mod == 3 ? dflag : MO_16;
5228 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5229 break;
5231 case 0x1b6: /* movzbS Gv, Eb */
5232 case 0x1b7: /* movzwS Gv, Eb */
5233 case 0x1be: /* movsbS Gv, Eb */
5234 case 0x1bf: /* movswS Gv, Eb */
5236 TCGMemOp d_ot;
5237 TCGMemOp s_ot;
5239 /* d_ot is the size of destination */
5240 d_ot = dflag;
5241 /* ot is the size of source */
5242 ot = (b & 1) + MO_8;
5243 /* s_ot is the sign+size of source */
5244 s_ot = b & 8 ? MO_SIGN | ot : ot;
5246 modrm = cpu_ldub_code(env, s->pc++);
5247 reg = ((modrm >> 3) & 7) | rex_r;
5248 mod = (modrm >> 6) & 3;
5249 rm = (modrm & 7) | REX_B(s);
5251 if (mod == 3) {
5252 gen_op_mov_v_reg(ot, cpu_T0, rm);
5253 switch (s_ot) {
5254 case MO_UB:
5255 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
5256 break;
5257 case MO_SB:
5258 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
5259 break;
5260 case MO_UW:
5261 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
5262 break;
5263 default:
5264 case MO_SW:
5265 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5266 break;
5268 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5269 } else {
5270 gen_lea_modrm(env, s, modrm);
5271 gen_op_ld_v(s, s_ot, cpu_T0, cpu_A0);
5272 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5275 break;
5277 case 0x8d: /* lea */
5278 ot = dflag;
5279 modrm = cpu_ldub_code(env, s->pc++);
5280 mod = (modrm >> 6) & 3;
5281 if (mod == 3)
5282 goto illegal_op;
5283 reg = ((modrm >> 3) & 7) | rex_r;
5284 /* we must ensure that no segment is added */
5285 s->override = -1;
5286 val = s->addseg;
5287 s->addseg = 0;
5288 gen_lea_modrm(env, s, modrm);
5289 s->addseg = val;
5290 gen_op_mov_reg_v(ot, reg, cpu_A0);
5291 break;
5293 case 0xa0: /* mov EAX, Ov */
5294 case 0xa1:
5295 case 0xa2: /* mov Ov, EAX */
5296 case 0xa3:
5298 target_ulong offset_addr;
5300 ot = mo_b_d(b, dflag);
5301 switch (s->aflag) {
5302 #ifdef TARGET_X86_64
5303 case MO_64:
5304 offset_addr = cpu_ldq_code(env, s->pc);
5305 s->pc += 8;
5306 break;
5307 #endif
5308 default:
5309 offset_addr = insn_get(env, s, s->aflag);
5310 break;
5312 tcg_gen_movi_tl(cpu_A0, offset_addr);
5313 gen_add_A0_ds_seg(s);
5314 if ((b & 2) == 0) {
5315 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
5316 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
5317 } else {
5318 gen_op_mov_v_reg(ot, cpu_T0, R_EAX);
5319 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5322 break;
5323 case 0xd7: /* xlat */
5324 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5325 tcg_gen_ext8u_tl(cpu_T0, cpu_regs[R_EAX]);
5326 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T0);
5327 gen_extu(s->aflag, cpu_A0);
5328 gen_add_A0_ds_seg(s);
5329 gen_op_ld_v(s, MO_8, cpu_T0, cpu_A0);
5330 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
5331 break;
5332 case 0xb0 ... 0xb7: /* mov R, Ib */
5333 val = insn_get(env, s, MO_8);
5334 tcg_gen_movi_tl(cpu_T0, val);
5335 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T0);
5336 break;
5337 case 0xb8 ... 0xbf: /* mov R, Iv */
5338 #ifdef TARGET_X86_64
5339 if (dflag == MO_64) {
5340 uint64_t tmp;
5341 /* 64 bit case */
5342 tmp = cpu_ldq_code(env, s->pc);
5343 s->pc += 8;
5344 reg = (b & 7) | REX_B(s);
5345 tcg_gen_movi_tl(cpu_T0, tmp);
5346 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
5347 } else
5348 #endif
5350 ot = dflag;
5351 val = insn_get(env, s, ot);
5352 reg = (b & 7) | REX_B(s);
5353 tcg_gen_movi_tl(cpu_T0, val);
5354 gen_op_mov_reg_v(ot, reg, cpu_T0);
5356 break;
5358 case 0x91 ... 0x97: /* xchg R, EAX */
5359 do_xchg_reg_eax:
5360 ot = dflag;
5361 reg = (b & 7) | REX_B(s);
5362 rm = R_EAX;
5363 goto do_xchg_reg;
5364 case 0x86:
5365 case 0x87: /* xchg Ev, Gv */
5366 ot = mo_b_d(b, dflag);
5367 modrm = cpu_ldub_code(env, s->pc++);
5368 reg = ((modrm >> 3) & 7) | rex_r;
5369 mod = (modrm >> 6) & 3;
5370 if (mod == 3) {
5371 rm = (modrm & 7) | REX_B(s);
5372 do_xchg_reg:
5373 gen_op_mov_v_reg(ot, cpu_T0, reg);
5374 gen_op_mov_v_reg(ot, cpu_T1, rm);
5375 gen_op_mov_reg_v(ot, rm, cpu_T0);
5376 gen_op_mov_reg_v(ot, reg, cpu_T1);
5377 } else {
5378 gen_lea_modrm(env, s, modrm);
5379 gen_op_mov_v_reg(ot, cpu_T0, reg);
5380 /* for xchg, lock is implicit */
5381 if (!(prefixes & PREFIX_LOCK))
5382 gen_helper_lock();
5383 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5384 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5385 if (!(prefixes & PREFIX_LOCK))
5386 gen_helper_unlock();
5387 gen_op_mov_reg_v(ot, reg, cpu_T1);
5389 break;
5390 case 0xc4: /* les Gv */
5391 /* In CODE64 this is VEX3; see above. */
5392 op = R_ES;
5393 goto do_lxx;
5394 case 0xc5: /* lds Gv */
5395 /* In CODE64 this is VEX2; see above. */
5396 op = R_DS;
5397 goto do_lxx;
5398 case 0x1b2: /* lss Gv */
5399 op = R_SS;
5400 goto do_lxx;
5401 case 0x1b4: /* lfs Gv */
5402 op = R_FS;
5403 goto do_lxx;
5404 case 0x1b5: /* lgs Gv */
5405 op = R_GS;
5406 do_lxx:
5407 ot = dflag != MO_16 ? MO_32 : MO_16;
5408 modrm = cpu_ldub_code(env, s->pc++);
5409 reg = ((modrm >> 3) & 7) | rex_r;
5410 mod = (modrm >> 6) & 3;
5411 if (mod == 3)
5412 goto illegal_op;
5413 gen_lea_modrm(env, s, modrm);
5414 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5415 gen_add_A0_im(s, 1 << ot);
5416 /* load the segment first to handle exceptions properly */
5417 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
5418 gen_movl_seg_T0(s, op);
5419 /* then put the data */
5420 gen_op_mov_reg_v(ot, reg, cpu_T1);
5421 if (s->is_jmp) {
5422 gen_jmp_im(s->pc - s->cs_base);
5423 gen_eob(s);
5425 break;
5427 /************************/
5428 /* shifts */
5429 case 0xc0:
5430 case 0xc1:
5431 /* shift Ev,Ib */
5432 shift = 2;
5433 grp2:
5435 ot = mo_b_d(b, dflag);
5436 modrm = cpu_ldub_code(env, s->pc++);
5437 mod = (modrm >> 6) & 3;
5438 op = (modrm >> 3) & 7;
5440 if (mod != 3) {
5441 if (shift == 2) {
5442 s->rip_offset = 1;
5444 gen_lea_modrm(env, s, modrm);
5445 opreg = OR_TMP0;
5446 } else {
5447 opreg = (modrm & 7) | REX_B(s);
5450 /* simpler op */
5451 if (shift == 0) {
5452 gen_shift(s, op, ot, opreg, OR_ECX);
5453 } else {
5454 if (shift == 2) {
5455 shift = cpu_ldub_code(env, s->pc++);
5457 gen_shifti(s, op, ot, opreg, shift);
5460 break;
5461 case 0xd0:
5462 case 0xd1:
5463 /* shift Ev,1 */
5464 shift = 1;
5465 goto grp2;
5466 case 0xd2:
5467 case 0xd3:
5468 /* shift Ev,cl */
5469 shift = 0;
5470 goto grp2;
5472 case 0x1a4: /* shld imm */
5473 op = 0;
5474 shift = 1;
5475 goto do_shiftd;
5476 case 0x1a5: /* shld cl */
5477 op = 0;
5478 shift = 0;
5479 goto do_shiftd;
5480 case 0x1ac: /* shrd imm */
5481 op = 1;
5482 shift = 1;
5483 goto do_shiftd;
5484 case 0x1ad: /* shrd cl */
5485 op = 1;
5486 shift = 0;
5487 do_shiftd:
5488 ot = dflag;
5489 modrm = cpu_ldub_code(env, s->pc++);
5490 mod = (modrm >> 6) & 3;
5491 rm = (modrm & 7) | REX_B(s);
5492 reg = ((modrm >> 3) & 7) | rex_r;
5493 if (mod != 3) {
5494 gen_lea_modrm(env, s, modrm);
5495 opreg = OR_TMP0;
5496 } else {
5497 opreg = rm;
5499 gen_op_mov_v_reg(ot, cpu_T1, reg);
5501 if (shift) {
5502 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5503 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5504 tcg_temp_free(imm);
5505 } else {
5506 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5508 break;
5510 /************************/
5511 /* floats */
5512 case 0xd8 ... 0xdf:
5513 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5514 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5515 /* XXX: what to do if illegal op ? */
5516 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5517 break;
5519 modrm = cpu_ldub_code(env, s->pc++);
5520 mod = (modrm >> 6) & 3;
5521 rm = modrm & 7;
5522 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5523 if (mod != 3) {
5524 /* memory op */
5525 gen_lea_modrm(env, s, modrm);
5526 switch(op) {
5527 case 0x00 ... 0x07: /* fxxxs */
5528 case 0x10 ... 0x17: /* fixxxl */
5529 case 0x20 ... 0x27: /* fxxxl */
5530 case 0x30 ... 0x37: /* fixxx */
5532 int op1;
5533 op1 = op & 7;
5535 switch(op >> 4) {
5536 case 0:
5537 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5538 s->mem_index, MO_LEUL);
5539 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5540 break;
5541 case 1:
5542 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5543 s->mem_index, MO_LEUL);
5544 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5545 break;
5546 case 2:
5547 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5548 s->mem_index, MO_LEQ);
5549 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5550 break;
5551 case 3:
5552 default:
5553 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5554 s->mem_index, MO_LESW);
5555 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5556 break;
5559 gen_helper_fp_arith_ST0_FT0(op1);
5560 if (op1 == 3) {
5561 /* fcomp needs pop */
5562 gen_helper_fpop(cpu_env);
5565 break;
5566 case 0x08: /* flds */
5567 case 0x0a: /* fsts */
5568 case 0x0b: /* fstps */
5569 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5570 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5571 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5572 switch(op & 7) {
5573 case 0:
5574 switch(op >> 4) {
5575 case 0:
5576 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5577 s->mem_index, MO_LEUL);
5578 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5579 break;
5580 case 1:
5581 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5582 s->mem_index, MO_LEUL);
5583 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5584 break;
5585 case 2:
5586 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5587 s->mem_index, MO_LEQ);
5588 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5589 break;
5590 case 3:
5591 default:
5592 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5593 s->mem_index, MO_LESW);
5594 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5595 break;
5597 break;
5598 case 1:
5599 /* XXX: the corresponding CPUID bit must be tested ! */
5600 switch(op >> 4) {
5601 case 1:
5602 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5603 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5604 s->mem_index, MO_LEUL);
5605 break;
5606 case 2:
5607 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5608 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5609 s->mem_index, MO_LEQ);
5610 break;
5611 case 3:
5612 default:
5613 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5614 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5615 s->mem_index, MO_LEUW);
5616 break;
5618 gen_helper_fpop(cpu_env);
5619 break;
5620 default:
5621 switch(op >> 4) {
5622 case 0:
5623 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5624 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5625 s->mem_index, MO_LEUL);
5626 break;
5627 case 1:
5628 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5629 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5630 s->mem_index, MO_LEUL);
5631 break;
5632 case 2:
5633 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5634 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5635 s->mem_index, MO_LEQ);
5636 break;
5637 case 3:
5638 default:
5639 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5640 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5641 s->mem_index, MO_LEUW);
5642 break;
5644 if ((op & 7) == 3)
5645 gen_helper_fpop(cpu_env);
5646 break;
5648 break;
5649 case 0x0c: /* fldenv mem */
5650 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5651 break;
5652 case 0x0d: /* fldcw mem */
5653 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5654 s->mem_index, MO_LEUW);
5655 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5656 break;
5657 case 0x0e: /* fnstenv mem */
5658 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5659 break;
5660 case 0x0f: /* fnstcw mem */
5661 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5662 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5663 s->mem_index, MO_LEUW);
5664 break;
5665 case 0x1d: /* fldt mem */
5666 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5667 break;
5668 case 0x1f: /* fstpt mem */
5669 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5670 gen_helper_fpop(cpu_env);
5671 break;
5672 case 0x2c: /* frstor mem */
5673 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5674 break;
5675 case 0x2e: /* fnsave mem */
5676 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5677 break;
5678 case 0x2f: /* fnstsw mem */
5679 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5680 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5681 s->mem_index, MO_LEUW);
5682 break;
5683 case 0x3c: /* fbld */
5684 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5685 break;
5686 case 0x3e: /* fbstp */
5687 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5688 gen_helper_fpop(cpu_env);
5689 break;
5690 case 0x3d: /* fildll */
5691 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5692 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5693 break;
5694 case 0x3f: /* fistpll */
5695 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5696 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5697 gen_helper_fpop(cpu_env);
5698 break;
5699 default:
5700 goto illegal_op;
5702 } else {
5703 /* register float ops */
5704 opreg = rm;
5706 switch(op) {
5707 case 0x08: /* fld sti */
5708 gen_helper_fpush(cpu_env);
5709 gen_helper_fmov_ST0_STN(cpu_env,
5710 tcg_const_i32((opreg + 1) & 7));
5711 break;
5712 case 0x09: /* fxchg sti */
5713 case 0x29: /* fxchg4 sti, undocumented op */
5714 case 0x39: /* fxchg7 sti, undocumented op */
5715 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5716 break;
5717 case 0x0a: /* grp d9/2 */
5718 switch(rm) {
5719 case 0: /* fnop */
5720 /* check exceptions (FreeBSD FPU probe) */
5721 gen_helper_fwait(cpu_env);
5722 break;
5723 default:
5724 goto illegal_op;
5726 break;
5727 case 0x0c: /* grp d9/4 */
5728 switch(rm) {
5729 case 0: /* fchs */
5730 gen_helper_fchs_ST0(cpu_env);
5731 break;
5732 case 1: /* fabs */
5733 gen_helper_fabs_ST0(cpu_env);
5734 break;
5735 case 4: /* ftst */
5736 gen_helper_fldz_FT0(cpu_env);
5737 gen_helper_fcom_ST0_FT0(cpu_env);
5738 break;
5739 case 5: /* fxam */
5740 gen_helper_fxam_ST0(cpu_env);
5741 break;
5742 default:
5743 goto illegal_op;
5745 break;
5746 case 0x0d: /* grp d9/5 */
5748 switch(rm) {
5749 case 0:
5750 gen_helper_fpush(cpu_env);
5751 gen_helper_fld1_ST0(cpu_env);
5752 break;
5753 case 1:
5754 gen_helper_fpush(cpu_env);
5755 gen_helper_fldl2t_ST0(cpu_env);
5756 break;
5757 case 2:
5758 gen_helper_fpush(cpu_env);
5759 gen_helper_fldl2e_ST0(cpu_env);
5760 break;
5761 case 3:
5762 gen_helper_fpush(cpu_env);
5763 gen_helper_fldpi_ST0(cpu_env);
5764 break;
5765 case 4:
5766 gen_helper_fpush(cpu_env);
5767 gen_helper_fldlg2_ST0(cpu_env);
5768 break;
5769 case 5:
5770 gen_helper_fpush(cpu_env);
5771 gen_helper_fldln2_ST0(cpu_env);
5772 break;
5773 case 6:
5774 gen_helper_fpush(cpu_env);
5775 gen_helper_fldz_ST0(cpu_env);
5776 break;
5777 default:
5778 goto illegal_op;
5781 break;
5782 case 0x0e: /* grp d9/6 */
5783 switch(rm) {
5784 case 0: /* f2xm1 */
5785 gen_helper_f2xm1(cpu_env);
5786 break;
5787 case 1: /* fyl2x */
5788 gen_helper_fyl2x(cpu_env);
5789 break;
5790 case 2: /* fptan */
5791 gen_helper_fptan(cpu_env);
5792 break;
5793 case 3: /* fpatan */
5794 gen_helper_fpatan(cpu_env);
5795 break;
5796 case 4: /* fxtract */
5797 gen_helper_fxtract(cpu_env);
5798 break;
5799 case 5: /* fprem1 */
5800 gen_helper_fprem1(cpu_env);
5801 break;
5802 case 6: /* fdecstp */
5803 gen_helper_fdecstp(cpu_env);
5804 break;
5805 default:
5806 case 7: /* fincstp */
5807 gen_helper_fincstp(cpu_env);
5808 break;
5810 break;
5811 case 0x0f: /* grp d9/7 */
5812 switch(rm) {
5813 case 0: /* fprem */
5814 gen_helper_fprem(cpu_env);
5815 break;
5816 case 1: /* fyl2xp1 */
5817 gen_helper_fyl2xp1(cpu_env);
5818 break;
5819 case 2: /* fsqrt */
5820 gen_helper_fsqrt(cpu_env);
5821 break;
5822 case 3: /* fsincos */
5823 gen_helper_fsincos(cpu_env);
5824 break;
5825 case 5: /* fscale */
5826 gen_helper_fscale(cpu_env);
5827 break;
5828 case 4: /* frndint */
5829 gen_helper_frndint(cpu_env);
5830 break;
5831 case 6: /* fsin */
5832 gen_helper_fsin(cpu_env);
5833 break;
5834 default:
5835 case 7: /* fcos */
5836 gen_helper_fcos(cpu_env);
5837 break;
5839 break;
5840 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
5841 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
5842 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
5844 int op1;
5846 op1 = op & 7;
5847 if (op >= 0x20) {
5848 gen_helper_fp_arith_STN_ST0(op1, opreg);
5849 if (op >= 0x30)
5850 gen_helper_fpop(cpu_env);
5851 } else {
5852 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5853 gen_helper_fp_arith_ST0_FT0(op1);
5856 break;
5857 case 0x02: /* fcom */
5858 case 0x22: /* fcom2, undocumented op */
5859 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5860 gen_helper_fcom_ST0_FT0(cpu_env);
5861 break;
5862 case 0x03: /* fcomp */
5863 case 0x23: /* fcomp3, undocumented op */
5864 case 0x32: /* fcomp5, undocumented op */
5865 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5866 gen_helper_fcom_ST0_FT0(cpu_env);
5867 gen_helper_fpop(cpu_env);
5868 break;
5869 case 0x15: /* da/5 */
5870 switch(rm) {
5871 case 1: /* fucompp */
5872 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
5873 gen_helper_fucom_ST0_FT0(cpu_env);
5874 gen_helper_fpop(cpu_env);
5875 gen_helper_fpop(cpu_env);
5876 break;
5877 default:
5878 goto illegal_op;
5880 break;
5881 case 0x1c:
5882 switch(rm) {
5883 case 0: /* feni (287 only, just do nop here) */
5884 break;
5885 case 1: /* fdisi (287 only, just do nop here) */
5886 break;
5887 case 2: /* fclex */
5888 gen_helper_fclex(cpu_env);
5889 break;
5890 case 3: /* fninit */
5891 gen_helper_fninit(cpu_env);
5892 break;
5893 case 4: /* fsetpm (287 only, just do nop here) */
5894 break;
5895 default:
5896 goto illegal_op;
5898 break;
5899 case 0x1d: /* fucomi */
5900 if (!(s->cpuid_features & CPUID_CMOV)) {
5901 goto illegal_op;
5903 gen_update_cc_op(s);
5904 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5905 gen_helper_fucomi_ST0_FT0(cpu_env);
5906 set_cc_op(s, CC_OP_EFLAGS);
5907 break;
5908 case 0x1e: /* fcomi */
5909 if (!(s->cpuid_features & CPUID_CMOV)) {
5910 goto illegal_op;
5912 gen_update_cc_op(s);
5913 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5914 gen_helper_fcomi_ST0_FT0(cpu_env);
5915 set_cc_op(s, CC_OP_EFLAGS);
5916 break;
5917 case 0x28: /* ffree sti */
5918 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
5919 break;
5920 case 0x2a: /* fst sti */
5921 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
5922 break;
5923 case 0x2b: /* fstp sti */
5924 case 0x0b: /* fstp1 sti, undocumented op */
5925 case 0x3a: /* fstp8 sti, undocumented op */
5926 case 0x3b: /* fstp9 sti, undocumented op */
5927 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
5928 gen_helper_fpop(cpu_env);
5929 break;
5930 case 0x2c: /* fucom st(i) */
5931 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5932 gen_helper_fucom_ST0_FT0(cpu_env);
5933 break;
5934 case 0x2d: /* fucomp st(i) */
5935 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5936 gen_helper_fucom_ST0_FT0(cpu_env);
5937 gen_helper_fpop(cpu_env);
5938 break;
5939 case 0x33: /* de/3 */
5940 switch(rm) {
5941 case 1: /* fcompp */
5942 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
5943 gen_helper_fcom_ST0_FT0(cpu_env);
5944 gen_helper_fpop(cpu_env);
5945 gen_helper_fpop(cpu_env);
5946 break;
5947 default:
5948 goto illegal_op;
5950 break;
5951 case 0x38: /* ffreep sti, undocumented op */
5952 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
5953 gen_helper_fpop(cpu_env);
5954 break;
5955 case 0x3c: /* df/4 */
5956 switch(rm) {
5957 case 0:
5958 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5959 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
5960 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
5961 break;
5962 default:
5963 goto illegal_op;
5965 break;
5966 case 0x3d: /* fucomip */
5967 if (!(s->cpuid_features & CPUID_CMOV)) {
5968 goto illegal_op;
5970 gen_update_cc_op(s);
5971 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5972 gen_helper_fucomi_ST0_FT0(cpu_env);
5973 gen_helper_fpop(cpu_env);
5974 set_cc_op(s, CC_OP_EFLAGS);
5975 break;
5976 case 0x3e: /* fcomip */
5977 if (!(s->cpuid_features & CPUID_CMOV)) {
5978 goto illegal_op;
5980 gen_update_cc_op(s);
5981 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5982 gen_helper_fcomi_ST0_FT0(cpu_env);
5983 gen_helper_fpop(cpu_env);
5984 set_cc_op(s, CC_OP_EFLAGS);
5985 break;
5986 case 0x10 ... 0x13: /* fcmovxx */
5987 case 0x18 ... 0x1b:
5989 int op1;
5990 TCGLabel *l1;
5991 static const uint8_t fcmov_cc[8] = {
5992 (JCC_B << 1),
5993 (JCC_Z << 1),
5994 (JCC_BE << 1),
5995 (JCC_P << 1),
5998 if (!(s->cpuid_features & CPUID_CMOV)) {
5999 goto illegal_op;
6001 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6002 l1 = gen_new_label();
6003 gen_jcc1_noeob(s, op1, l1);
6004 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6005 gen_set_label(l1);
6007 break;
6008 default:
6009 goto illegal_op;
6012 break;
6013 /************************/
6014 /* string ops */
6016 case 0xa4: /* movsS */
6017 case 0xa5:
6018 ot = mo_b_d(b, dflag);
6019 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6020 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6021 } else {
6022 gen_movs(s, ot);
6024 break;
6026 case 0xaa: /* stosS */
6027 case 0xab:
6028 ot = mo_b_d(b, dflag);
6029 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6030 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6031 } else {
6032 gen_stos(s, ot);
6034 break;
6035 case 0xac: /* lodsS */
6036 case 0xad:
6037 ot = mo_b_d(b, dflag);
6038 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6039 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6040 } else {
6041 gen_lods(s, ot);
6043 break;
6044 case 0xae: /* scasS */
6045 case 0xaf:
6046 ot = mo_b_d(b, dflag);
6047 if (prefixes & PREFIX_REPNZ) {
6048 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6049 } else if (prefixes & PREFIX_REPZ) {
6050 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6051 } else {
6052 gen_scas(s, ot);
6054 break;
6056 case 0xa6: /* cmpsS */
6057 case 0xa7:
6058 ot = mo_b_d(b, dflag);
6059 if (prefixes & PREFIX_REPNZ) {
6060 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6061 } else if (prefixes & PREFIX_REPZ) {
6062 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6063 } else {
6064 gen_cmps(s, ot);
6066 break;
6067 case 0x6c: /* insS */
6068 case 0x6d:
6069 ot = mo_b_d32(b, dflag);
6070 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6071 gen_check_io(s, ot, pc_start - s->cs_base,
6072 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6073 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6074 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6075 } else {
6076 gen_ins(s, ot);
6077 if (s->tb->cflags & CF_USE_ICOUNT) {
6078 gen_jmp(s, s->pc - s->cs_base);
6081 break;
6082 case 0x6e: /* outsS */
6083 case 0x6f:
6084 ot = mo_b_d32(b, dflag);
6085 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6086 gen_check_io(s, ot, pc_start - s->cs_base,
6087 svm_is_rep(prefixes) | 4);
6088 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6089 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6090 } else {
6091 gen_outs(s, ot);
6092 if (s->tb->cflags & CF_USE_ICOUNT) {
6093 gen_jmp(s, s->pc - s->cs_base);
6096 break;
6098 /************************/
6099 /* port I/O */
6101 case 0xe4:
6102 case 0xe5:
6103 ot = mo_b_d32(b, dflag);
6104 val = cpu_ldub_code(env, s->pc++);
6105 tcg_gen_movi_tl(cpu_T0, val);
6106 gen_check_io(s, ot, pc_start - s->cs_base,
6107 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6108 if (s->tb->cflags & CF_USE_ICOUNT) {
6109 gen_io_start();
6111 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6112 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6113 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6114 gen_bpt_io(s, cpu_tmp2_i32, ot);
6115 if (s->tb->cflags & CF_USE_ICOUNT) {
6116 gen_io_end();
6117 gen_jmp(s, s->pc - s->cs_base);
6119 break;
6120 case 0xe6:
6121 case 0xe7:
6122 ot = mo_b_d32(b, dflag);
6123 val = cpu_ldub_code(env, s->pc++);
6124 tcg_gen_movi_tl(cpu_T0, val);
6125 gen_check_io(s, ot, pc_start - s->cs_base,
6126 svm_is_rep(prefixes));
6127 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6129 if (s->tb->cflags & CF_USE_ICOUNT) {
6130 gen_io_start();
6132 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6133 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6134 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6135 gen_bpt_io(s, cpu_tmp2_i32, ot);
6136 if (s->tb->cflags & CF_USE_ICOUNT) {
6137 gen_io_end();
6138 gen_jmp(s, s->pc - s->cs_base);
6140 break;
6141 case 0xec:
6142 case 0xed:
6143 ot = mo_b_d32(b, dflag);
6144 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6145 gen_check_io(s, ot, pc_start - s->cs_base,
6146 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6147 if (s->tb->cflags & CF_USE_ICOUNT) {
6148 gen_io_start();
6150 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6151 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6152 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6153 gen_bpt_io(s, cpu_tmp2_i32, ot);
6154 if (s->tb->cflags & CF_USE_ICOUNT) {
6155 gen_io_end();
6156 gen_jmp(s, s->pc - s->cs_base);
6158 break;
6159 case 0xee:
6160 case 0xef:
6161 ot = mo_b_d32(b, dflag);
6162 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6163 gen_check_io(s, ot, pc_start - s->cs_base,
6164 svm_is_rep(prefixes));
6165 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6167 if (s->tb->cflags & CF_USE_ICOUNT) {
6168 gen_io_start();
6170 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6171 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6172 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6173 gen_bpt_io(s, cpu_tmp2_i32, ot);
6174 if (s->tb->cflags & CF_USE_ICOUNT) {
6175 gen_io_end();
6176 gen_jmp(s, s->pc - s->cs_base);
6178 break;
6180 /************************/
6181 /* control */
6182 case 0xc2: /* ret im */
6183 val = cpu_ldsw_code(env, s->pc);
6184 s->pc += 2;
6185 ot = gen_pop_T0(s);
6186 gen_stack_update(s, val + (1 << ot));
6187 /* Note that gen_pop_T0 uses a zero-extending load. */
6188 gen_op_jmp_v(cpu_T0);
6189 gen_eob(s);
6190 break;
6191 case 0xc3: /* ret */
6192 ot = gen_pop_T0(s);
6193 gen_pop_update(s, ot);
6194 /* Note that gen_pop_T0 uses a zero-extending load. */
6195 gen_op_jmp_v(cpu_T0);
6196 gen_eob(s);
6197 break;
6198 case 0xca: /* lret im */
6199 val = cpu_ldsw_code(env, s->pc);
6200 s->pc += 2;
6201 do_lret:
6202 if (s->pe && !s->vm86) {
6203 gen_update_cc_op(s);
6204 gen_jmp_im(pc_start - s->cs_base);
6205 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6206 tcg_const_i32(val));
6207 } else {
6208 gen_stack_A0(s);
6209 /* pop offset */
6210 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6211 /* NOTE: keeping EIP updated is not a problem in case of
6212 exception */
6213 gen_op_jmp_v(cpu_T0);
6214 /* pop selector */
6215 gen_add_A0_im(s, 1 << dflag);
6216 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6217 gen_op_movl_seg_T0_vm(R_CS);
6218 /* add stack offset */
6219 gen_stack_update(s, val + (2 << dflag));
6221 gen_eob(s);
6222 break;
6223 case 0xcb: /* lret */
6224 val = 0;
6225 goto do_lret;
6226 case 0xcf: /* iret */
6227 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6228 if (!s->pe) {
6229 /* real mode */
6230 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6231 set_cc_op(s, CC_OP_EFLAGS);
6232 } else if (s->vm86) {
6233 if (s->iopl != 3) {
6234 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6235 } else {
6236 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6237 set_cc_op(s, CC_OP_EFLAGS);
6239 } else {
6240 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6241 tcg_const_i32(s->pc - s->cs_base));
6242 set_cc_op(s, CC_OP_EFLAGS);
6244 gen_eob(s);
6245 break;
6246 case 0xe8: /* call im */
6248 if (dflag != MO_16) {
6249 tval = (int32_t)insn_get(env, s, MO_32);
6250 } else {
6251 tval = (int16_t)insn_get(env, s, MO_16);
6253 next_eip = s->pc - s->cs_base;
6254 tval += next_eip;
6255 if (dflag == MO_16) {
6256 tval &= 0xffff;
6257 } else if (!CODE64(s)) {
6258 tval &= 0xffffffff;
6260 tcg_gen_movi_tl(cpu_T0, next_eip);
6261 gen_push_v(s, cpu_T0);
6262 gen_jmp(s, tval);
6264 break;
6265 case 0x9a: /* lcall im */
6267 unsigned int selector, offset;
6269 if (CODE64(s))
6270 goto illegal_op;
6271 ot = dflag;
6272 offset = insn_get(env, s, ot);
6273 selector = insn_get(env, s, MO_16);
6275 tcg_gen_movi_tl(cpu_T0, selector);
6276 tcg_gen_movi_tl(cpu_T1, offset);
6278 goto do_lcall;
6279 case 0xe9: /* jmp im */
6280 if (dflag != MO_16) {
6281 tval = (int32_t)insn_get(env, s, MO_32);
6282 } else {
6283 tval = (int16_t)insn_get(env, s, MO_16);
6285 tval += s->pc - s->cs_base;
6286 if (dflag == MO_16) {
6287 tval &= 0xffff;
6288 } else if (!CODE64(s)) {
6289 tval &= 0xffffffff;
6291 gen_jmp(s, tval);
6292 break;
6293 case 0xea: /* ljmp im */
6295 unsigned int selector, offset;
6297 if (CODE64(s))
6298 goto illegal_op;
6299 ot = dflag;
6300 offset = insn_get(env, s, ot);
6301 selector = insn_get(env, s, MO_16);
6303 tcg_gen_movi_tl(cpu_T0, selector);
6304 tcg_gen_movi_tl(cpu_T1, offset);
6306 goto do_ljmp;
6307 case 0xeb: /* jmp Jb */
6308 tval = (int8_t)insn_get(env, s, MO_8);
6309 tval += s->pc - s->cs_base;
6310 if (dflag == MO_16) {
6311 tval &= 0xffff;
6313 gen_jmp(s, tval);
6314 break;
6315 case 0x70 ... 0x7f: /* jcc Jb */
6316 tval = (int8_t)insn_get(env, s, MO_8);
6317 goto do_jcc;
6318 case 0x180 ... 0x18f: /* jcc Jv */
6319 if (dflag != MO_16) {
6320 tval = (int32_t)insn_get(env, s, MO_32);
6321 } else {
6322 tval = (int16_t)insn_get(env, s, MO_16);
6324 do_jcc:
6325 next_eip = s->pc - s->cs_base;
6326 tval += next_eip;
6327 if (dflag == MO_16) {
6328 tval &= 0xffff;
6330 gen_jcc(s, b, tval, next_eip);
6331 break;
6333 case 0x190 ... 0x19f: /* setcc Gv */
6334 modrm = cpu_ldub_code(env, s->pc++);
6335 gen_setcc1(s, b, cpu_T0);
6336 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6337 break;
6338 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6339 if (!(s->cpuid_features & CPUID_CMOV)) {
6340 goto illegal_op;
6342 ot = dflag;
6343 modrm = cpu_ldub_code(env, s->pc++);
6344 reg = ((modrm >> 3) & 7) | rex_r;
6345 gen_cmovcc1(env, s, ot, b, modrm, reg);
6346 break;
6348 /************************/
6349 /* flags */
6350 case 0x9c: /* pushf */
6351 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6352 if (s->vm86 && s->iopl != 3) {
6353 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6354 } else {
6355 gen_update_cc_op(s);
6356 gen_helper_read_eflags(cpu_T0, cpu_env);
6357 gen_push_v(s, cpu_T0);
6359 break;
6360 case 0x9d: /* popf */
6361 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6362 if (s->vm86 && s->iopl != 3) {
6363 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6364 } else {
6365 ot = gen_pop_T0(s);
6366 if (s->cpl == 0) {
6367 if (dflag != MO_16) {
6368 gen_helper_write_eflags(cpu_env, cpu_T0,
6369 tcg_const_i32((TF_MASK | AC_MASK |
6370 ID_MASK | NT_MASK |
6371 IF_MASK |
6372 IOPL_MASK)));
6373 } else {
6374 gen_helper_write_eflags(cpu_env, cpu_T0,
6375 tcg_const_i32((TF_MASK | AC_MASK |
6376 ID_MASK | NT_MASK |
6377 IF_MASK | IOPL_MASK)
6378 & 0xffff));
6380 } else {
6381 if (s->cpl <= s->iopl) {
6382 if (dflag != MO_16) {
6383 gen_helper_write_eflags(cpu_env, cpu_T0,
6384 tcg_const_i32((TF_MASK |
6385 AC_MASK |
6386 ID_MASK |
6387 NT_MASK |
6388 IF_MASK)));
6389 } else {
6390 gen_helper_write_eflags(cpu_env, cpu_T0,
6391 tcg_const_i32((TF_MASK |
6392 AC_MASK |
6393 ID_MASK |
6394 NT_MASK |
6395 IF_MASK)
6396 & 0xffff));
6398 } else {
6399 if (dflag != MO_16) {
6400 gen_helper_write_eflags(cpu_env, cpu_T0,
6401 tcg_const_i32((TF_MASK | AC_MASK |
6402 ID_MASK | NT_MASK)));
6403 } else {
6404 gen_helper_write_eflags(cpu_env, cpu_T0,
6405 tcg_const_i32((TF_MASK | AC_MASK |
6406 ID_MASK | NT_MASK)
6407 & 0xffff));
6411 gen_pop_update(s, ot);
6412 set_cc_op(s, CC_OP_EFLAGS);
6413 /* abort translation because TF/AC flag may change */
6414 gen_jmp_im(s->pc - s->cs_base);
6415 gen_eob(s);
6417 break;
6418 case 0x9e: /* sahf */
6419 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6420 goto illegal_op;
6421 gen_op_mov_v_reg(MO_8, cpu_T0, R_AH);
6422 gen_compute_eflags(s);
6423 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6424 tcg_gen_andi_tl(cpu_T0, cpu_T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6425 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T0);
6426 break;
6427 case 0x9f: /* lahf */
6428 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6429 goto illegal_op;
6430 gen_compute_eflags(s);
6431 /* Note: gen_compute_eflags() only gives the condition codes */
6432 tcg_gen_ori_tl(cpu_T0, cpu_cc_src, 0x02);
6433 gen_op_mov_reg_v(MO_8, R_AH, cpu_T0);
6434 break;
6435 case 0xf5: /* cmc */
6436 gen_compute_eflags(s);
6437 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6438 break;
6439 case 0xf8: /* clc */
6440 gen_compute_eflags(s);
6441 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6442 break;
6443 case 0xf9: /* stc */
6444 gen_compute_eflags(s);
6445 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6446 break;
6447 case 0xfc: /* cld */
6448 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6449 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6450 break;
6451 case 0xfd: /* std */
6452 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6453 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6454 break;
6456 /************************/
6457 /* bit operations */
6458 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6459 ot = dflag;
6460 modrm = cpu_ldub_code(env, s->pc++);
6461 op = (modrm >> 3) & 7;
6462 mod = (modrm >> 6) & 3;
6463 rm = (modrm & 7) | REX_B(s);
6464 if (mod != 3) {
6465 s->rip_offset = 1;
6466 gen_lea_modrm(env, s, modrm);
6467 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6468 } else {
6469 gen_op_mov_v_reg(ot, cpu_T0, rm);
6471 /* load shift */
6472 val = cpu_ldub_code(env, s->pc++);
6473 tcg_gen_movi_tl(cpu_T1, val);
6474 if (op < 4)
6475 goto illegal_op;
6476 op -= 4;
6477 goto bt_op;
6478 case 0x1a3: /* bt Gv, Ev */
6479 op = 0;
6480 goto do_btx;
6481 case 0x1ab: /* bts */
6482 op = 1;
6483 goto do_btx;
6484 case 0x1b3: /* btr */
6485 op = 2;
6486 goto do_btx;
6487 case 0x1bb: /* btc */
6488 op = 3;
6489 do_btx:
6490 ot = dflag;
6491 modrm = cpu_ldub_code(env, s->pc++);
6492 reg = ((modrm >> 3) & 7) | rex_r;
6493 mod = (modrm >> 6) & 3;
6494 rm = (modrm & 7) | REX_B(s);
6495 gen_op_mov_v_reg(MO_32, cpu_T1, reg);
6496 if (mod != 3) {
6497 gen_lea_modrm(env, s, modrm);
6498 /* specific case: we need to add a displacement */
6499 gen_exts(ot, cpu_T1);
6500 tcg_gen_sari_tl(cpu_tmp0, cpu_T1, 3 + ot);
6501 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6502 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
6503 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6504 } else {
6505 gen_op_mov_v_reg(ot, cpu_T0, rm);
6507 bt_op:
6508 tcg_gen_andi_tl(cpu_T1, cpu_T1, (1 << (3 + ot)) - 1);
6509 tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1);
6510 switch(op) {
6511 case 0:
6512 break;
6513 case 1:
6514 tcg_gen_movi_tl(cpu_tmp0, 1);
6515 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6516 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
6517 break;
6518 case 2:
6519 tcg_gen_movi_tl(cpu_tmp0, 1);
6520 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6521 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_tmp0);
6522 break;
6523 default:
6524 case 3:
6525 tcg_gen_movi_tl(cpu_tmp0, 1);
6526 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6527 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_tmp0);
6528 break;
6530 if (op != 0) {
6531 if (mod != 3) {
6532 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
6533 } else {
6534 gen_op_mov_reg_v(ot, rm, cpu_T0);
6538 /* Delay all CC updates until after the store above. Note that
6539 C is the result of the test, Z is unchanged, and the others
6540 are all undefined. */
6541 switch (s->cc_op) {
6542 case CC_OP_MULB ... CC_OP_MULQ:
6543 case CC_OP_ADDB ... CC_OP_ADDQ:
6544 case CC_OP_ADCB ... CC_OP_ADCQ:
6545 case CC_OP_SUBB ... CC_OP_SUBQ:
6546 case CC_OP_SBBB ... CC_OP_SBBQ:
6547 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6548 case CC_OP_INCB ... CC_OP_INCQ:
6549 case CC_OP_DECB ... CC_OP_DECQ:
6550 case CC_OP_SHLB ... CC_OP_SHLQ:
6551 case CC_OP_SARB ... CC_OP_SARQ:
6552 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6553 /* Z was going to be computed from the non-zero status of CC_DST.
6554 We can get that same Z value (and the new C value) by leaving
6555 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6556 same width. */
6557 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6558 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6559 break;
6560 default:
6561 /* Otherwise, generate EFLAGS and replace the C bit. */
6562 gen_compute_eflags(s);
6563 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6564 ctz32(CC_C), 1);
6565 break;
6567 break;
6568 case 0x1bc: /* bsf / tzcnt */
6569 case 0x1bd: /* bsr / lzcnt */
6570 ot = dflag;
6571 modrm = cpu_ldub_code(env, s->pc++);
6572 reg = ((modrm >> 3) & 7) | rex_r;
6573 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6574 gen_extu(ot, cpu_T0);
6576 /* Note that lzcnt and tzcnt are in different extensions. */
6577 if ((prefixes & PREFIX_REPZ)
6578 && (b & 1
6579 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6580 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6581 int size = 8 << ot;
6582 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
6583 if (b & 1) {
6584 /* For lzcnt, reduce the target_ulong result by the
6585 number of zeros that we expect to find at the top. */
6586 gen_helper_clz(cpu_T0, cpu_T0);
6587 tcg_gen_subi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - size);
6588 } else {
6589 /* For tzcnt, a zero input must return the operand size:
6590 force all bits outside the operand size to 1. */
6591 target_ulong mask = (target_ulong)-2 << (size - 1);
6592 tcg_gen_ori_tl(cpu_T0, cpu_T0, mask);
6593 gen_helper_ctz(cpu_T0, cpu_T0);
6595 /* For lzcnt/tzcnt, C and Z bits are defined and are
6596 related to the result. */
6597 gen_op_update1_cc();
6598 set_cc_op(s, CC_OP_BMILGB + ot);
6599 } else {
6600 /* For bsr/bsf, only the Z bit is defined and it is related
6601 to the input and not the result. */
6602 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
6603 set_cc_op(s, CC_OP_LOGICB + ot);
6604 if (b & 1) {
6605 /* For bsr, return the bit index of the first 1 bit,
6606 not the count of leading zeros. */
6607 gen_helper_clz(cpu_T0, cpu_T0);
6608 tcg_gen_xori_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - 1);
6609 } else {
6610 gen_helper_ctz(cpu_T0, cpu_T0);
6612 /* ??? The manual says that the output is undefined when the
6613 input is zero, but real hardware leaves it unchanged, and
6614 real programs appear to depend on that. */
6615 tcg_gen_movi_tl(cpu_tmp0, 0);
6616 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T0, cpu_cc_dst, cpu_tmp0,
6617 cpu_regs[reg], cpu_T0);
6619 gen_op_mov_reg_v(ot, reg, cpu_T0);
6620 break;
6621 /************************/
6622 /* bcd */
6623 case 0x27: /* daa */
6624 if (CODE64(s))
6625 goto illegal_op;
6626 gen_update_cc_op(s);
6627 gen_helper_daa(cpu_env);
6628 set_cc_op(s, CC_OP_EFLAGS);
6629 break;
6630 case 0x2f: /* das */
6631 if (CODE64(s))
6632 goto illegal_op;
6633 gen_update_cc_op(s);
6634 gen_helper_das(cpu_env);
6635 set_cc_op(s, CC_OP_EFLAGS);
6636 break;
6637 case 0x37: /* aaa */
6638 if (CODE64(s))
6639 goto illegal_op;
6640 gen_update_cc_op(s);
6641 gen_helper_aaa(cpu_env);
6642 set_cc_op(s, CC_OP_EFLAGS);
6643 break;
6644 case 0x3f: /* aas */
6645 if (CODE64(s))
6646 goto illegal_op;
6647 gen_update_cc_op(s);
6648 gen_helper_aas(cpu_env);
6649 set_cc_op(s, CC_OP_EFLAGS);
6650 break;
6651 case 0xd4: /* aam */
6652 if (CODE64(s))
6653 goto illegal_op;
6654 val = cpu_ldub_code(env, s->pc++);
6655 if (val == 0) {
6656 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6657 } else {
6658 gen_helper_aam(cpu_env, tcg_const_i32(val));
6659 set_cc_op(s, CC_OP_LOGICB);
6661 break;
6662 case 0xd5: /* aad */
6663 if (CODE64(s))
6664 goto illegal_op;
6665 val = cpu_ldub_code(env, s->pc++);
6666 gen_helper_aad(cpu_env, tcg_const_i32(val));
6667 set_cc_op(s, CC_OP_LOGICB);
6668 break;
6669 /************************/
6670 /* misc */
6671 case 0x90: /* nop */
6672 /* XXX: correct lock test for all insn */
6673 if (prefixes & PREFIX_LOCK) {
6674 goto illegal_op;
6676 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6677 if (REX_B(s)) {
6678 goto do_xchg_reg_eax;
6680 if (prefixes & PREFIX_REPZ) {
6681 gen_update_cc_op(s);
6682 gen_jmp_im(pc_start - s->cs_base);
6683 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6684 s->is_jmp = DISAS_TB_JUMP;
6686 break;
6687 case 0x9b: /* fwait */
6688 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6689 (HF_MP_MASK | HF_TS_MASK)) {
6690 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6691 } else {
6692 gen_helper_fwait(cpu_env);
6694 break;
6695 case 0xcc: /* int3 */
6696 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6697 break;
6698 case 0xcd: /* int N */
6699 val = cpu_ldub_code(env, s->pc++);
6700 if (s->vm86 && s->iopl != 3) {
6701 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6702 } else {
6703 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6705 break;
6706 case 0xce: /* into */
6707 if (CODE64(s))
6708 goto illegal_op;
6709 gen_update_cc_op(s);
6710 gen_jmp_im(pc_start - s->cs_base);
6711 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6712 break;
6713 #ifdef WANT_ICEBP
6714 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6715 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6716 #if 1
6717 gen_debug(s, pc_start - s->cs_base);
6718 #else
6719 /* start debug */
6720 tb_flush(CPU(x86_env_get_cpu(env)));
6721 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6722 #endif
6723 break;
6724 #endif
6725 case 0xfa: /* cli */
6726 if (!s->vm86) {
6727 if (s->cpl <= s->iopl) {
6728 gen_helper_cli(cpu_env);
6729 } else {
6730 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6732 } else {
6733 if (s->iopl == 3) {
6734 gen_helper_cli(cpu_env);
6735 } else {
6736 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6739 break;
6740 case 0xfb: /* sti */
6741 if (!s->vm86) {
6742 if (s->cpl <= s->iopl) {
6743 gen_sti:
6744 gen_helper_sti(cpu_env);
6745 /* interruptions are enabled only the first insn after sti */
6746 /* If several instructions disable interrupts, only the
6747 _first_ does it */
6748 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
6749 gen_helper_set_inhibit_irq(cpu_env);
6750 /* give a chance to handle pending irqs */
6751 gen_jmp_im(s->pc - s->cs_base);
6752 gen_eob(s);
6753 } else {
6754 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6756 } else {
6757 if (s->iopl == 3) {
6758 goto gen_sti;
6759 } else {
6760 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6763 break;
6764 case 0x62: /* bound */
6765 if (CODE64(s))
6766 goto illegal_op;
6767 ot = dflag;
6768 modrm = cpu_ldub_code(env, s->pc++);
6769 reg = (modrm >> 3) & 7;
6770 mod = (modrm >> 6) & 3;
6771 if (mod == 3)
6772 goto illegal_op;
6773 gen_op_mov_v_reg(ot, cpu_T0, reg);
6774 gen_lea_modrm(env, s, modrm);
6775 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6776 if (ot == MO_16) {
6777 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
6778 } else {
6779 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
6781 break;
6782 case 0x1c8 ... 0x1cf: /* bswap reg */
6783 reg = (b & 7) | REX_B(s);
6784 #ifdef TARGET_X86_64
6785 if (dflag == MO_64) {
6786 gen_op_mov_v_reg(MO_64, cpu_T0, reg);
6787 tcg_gen_bswap64_i64(cpu_T0, cpu_T0);
6788 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
6789 } else
6790 #endif
6792 gen_op_mov_v_reg(MO_32, cpu_T0, reg);
6793 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
6794 tcg_gen_bswap32_tl(cpu_T0, cpu_T0);
6795 gen_op_mov_reg_v(MO_32, reg, cpu_T0);
6797 break;
6798 case 0xd6: /* salc */
6799 if (CODE64(s))
6800 goto illegal_op;
6801 gen_compute_eflags_c(s, cpu_T0);
6802 tcg_gen_neg_tl(cpu_T0, cpu_T0);
6803 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
6804 break;
6805 case 0xe0: /* loopnz */
6806 case 0xe1: /* loopz */
6807 case 0xe2: /* loop */
6808 case 0xe3: /* jecxz */
6810 TCGLabel *l1, *l2, *l3;
6812 tval = (int8_t)insn_get(env, s, MO_8);
6813 next_eip = s->pc - s->cs_base;
6814 tval += next_eip;
6815 if (dflag == MO_16) {
6816 tval &= 0xffff;
6819 l1 = gen_new_label();
6820 l2 = gen_new_label();
6821 l3 = gen_new_label();
6822 b &= 3;
6823 switch(b) {
6824 case 0: /* loopnz */
6825 case 1: /* loopz */
6826 gen_op_add_reg_im(s->aflag, R_ECX, -1);
6827 gen_op_jz_ecx(s->aflag, l3);
6828 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
6829 break;
6830 case 2: /* loop */
6831 gen_op_add_reg_im(s->aflag, R_ECX, -1);
6832 gen_op_jnz_ecx(s->aflag, l1);
6833 break;
6834 default:
6835 case 3: /* jcxz */
6836 gen_op_jz_ecx(s->aflag, l1);
6837 break;
6840 gen_set_label(l3);
6841 gen_jmp_im(next_eip);
6842 tcg_gen_br(l2);
6844 gen_set_label(l1);
6845 gen_jmp_im(tval);
6846 gen_set_label(l2);
6847 gen_eob(s);
6849 break;
6850 case 0x130: /* wrmsr */
6851 case 0x132: /* rdmsr */
6852 if (s->cpl != 0) {
6853 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6854 } else {
6855 gen_update_cc_op(s);
6856 gen_jmp_im(pc_start - s->cs_base);
6857 if (b & 2) {
6858 gen_helper_rdmsr(cpu_env);
6859 } else {
6860 gen_helper_wrmsr(cpu_env);
6863 break;
6864 case 0x131: /* rdtsc */
6865 gen_update_cc_op(s);
6866 gen_jmp_im(pc_start - s->cs_base);
6867 if (s->tb->cflags & CF_USE_ICOUNT) {
6868 gen_io_start();
6870 gen_helper_rdtsc(cpu_env);
6871 if (s->tb->cflags & CF_USE_ICOUNT) {
6872 gen_io_end();
6873 gen_jmp(s, s->pc - s->cs_base);
6875 break;
6876 case 0x133: /* rdpmc */
6877 gen_update_cc_op(s);
6878 gen_jmp_im(pc_start - s->cs_base);
6879 gen_helper_rdpmc(cpu_env);
6880 break;
6881 case 0x134: /* sysenter */
6882 /* For Intel SYSENTER is valid on 64-bit */
6883 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
6884 goto illegal_op;
6885 if (!s->pe) {
6886 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6887 } else {
6888 gen_helper_sysenter(cpu_env);
6889 gen_eob(s);
6891 break;
6892 case 0x135: /* sysexit */
6893 /* For Intel SYSEXIT is valid on 64-bit */
6894 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
6895 goto illegal_op;
6896 if (!s->pe) {
6897 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6898 } else {
6899 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
6900 gen_eob(s);
6902 break;
6903 #ifdef TARGET_X86_64
6904 case 0x105: /* syscall */
6905 /* XXX: is it usable in real mode ? */
6906 gen_update_cc_op(s);
6907 gen_jmp_im(pc_start - s->cs_base);
6908 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
6909 gen_eob(s);
6910 break;
6911 case 0x107: /* sysret */
6912 if (!s->pe) {
6913 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6914 } else {
6915 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
6916 /* condition codes are modified only in long mode */
6917 if (s->lma) {
6918 set_cc_op(s, CC_OP_EFLAGS);
6920 gen_eob(s);
6922 break;
6923 #endif
6924 case 0x1a2: /* cpuid */
6925 gen_update_cc_op(s);
6926 gen_jmp_im(pc_start - s->cs_base);
6927 gen_helper_cpuid(cpu_env);
6928 break;
6929 case 0xf4: /* hlt */
6930 if (s->cpl != 0) {
6931 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6932 } else {
6933 gen_update_cc_op(s);
6934 gen_jmp_im(pc_start - s->cs_base);
6935 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
6936 s->is_jmp = DISAS_TB_JUMP;
6938 break;
6939 case 0x100:
6940 modrm = cpu_ldub_code(env, s->pc++);
6941 mod = (modrm >> 6) & 3;
6942 op = (modrm >> 3) & 7;
6943 switch(op) {
6944 case 0: /* sldt */
6945 if (!s->pe || s->vm86)
6946 goto illegal_op;
6947 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
6948 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
6949 offsetof(CPUX86State, ldt.selector));
6950 ot = mod == 3 ? dflag : MO_16;
6951 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
6952 break;
6953 case 2: /* lldt */
6954 if (!s->pe || s->vm86)
6955 goto illegal_op;
6956 if (s->cpl != 0) {
6957 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6958 } else {
6959 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
6960 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
6961 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6962 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
6964 break;
6965 case 1: /* str */
6966 if (!s->pe || s->vm86)
6967 goto illegal_op;
6968 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
6969 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
6970 offsetof(CPUX86State, tr.selector));
6971 ot = mod == 3 ? dflag : MO_16;
6972 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
6973 break;
6974 case 3: /* ltr */
6975 if (!s->pe || s->vm86)
6976 goto illegal_op;
6977 if (s->cpl != 0) {
6978 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6979 } else {
6980 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
6981 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
6982 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6983 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
6985 break;
6986 case 4: /* verr */
6987 case 5: /* verw */
6988 if (!s->pe || s->vm86)
6989 goto illegal_op;
6990 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
6991 gen_update_cc_op(s);
6992 if (op == 4) {
6993 gen_helper_verr(cpu_env, cpu_T0);
6994 } else {
6995 gen_helper_verw(cpu_env, cpu_T0);
6997 set_cc_op(s, CC_OP_EFLAGS);
6998 break;
6999 default:
7000 goto illegal_op;
7002 break;
7003 case 0x101:
7004 modrm = cpu_ldub_code(env, s->pc++);
7005 mod = (modrm >> 6) & 3;
7006 op = (modrm >> 3) & 7;
7007 rm = modrm & 7;
7008 switch(op) {
7009 case 0: /* sgdt */
7010 if (mod == 3)
7011 goto illegal_op;
7012 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7013 gen_lea_modrm(env, s, modrm);
7014 tcg_gen_ld32u_tl(cpu_T0,
7015 cpu_env, offsetof(CPUX86State, gdt.limit));
7016 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7017 gen_add_A0_im(s, 2);
7018 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7019 if (dflag == MO_16) {
7020 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7022 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7023 break;
7024 case 1:
7025 if (mod == 3) {
7026 switch (rm) {
7027 case 0: /* monitor */
7028 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7029 s->cpl != 0)
7030 goto illegal_op;
7031 gen_update_cc_op(s);
7032 gen_jmp_im(pc_start - s->cs_base);
7033 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7034 gen_extu(s->aflag, cpu_A0);
7035 gen_add_A0_ds_seg(s);
7036 gen_helper_monitor(cpu_env, cpu_A0);
7037 break;
7038 case 1: /* mwait */
7039 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7040 s->cpl != 0)
7041 goto illegal_op;
7042 gen_update_cc_op(s);
7043 gen_jmp_im(pc_start - s->cs_base);
7044 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7045 gen_eob(s);
7046 break;
7047 case 2: /* clac */
7048 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7049 s->cpl != 0) {
7050 goto illegal_op;
7052 gen_helper_clac(cpu_env);
7053 gen_jmp_im(s->pc - s->cs_base);
7054 gen_eob(s);
7055 break;
7056 case 3: /* stac */
7057 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7058 s->cpl != 0) {
7059 goto illegal_op;
7061 gen_helper_stac(cpu_env);
7062 gen_jmp_im(s->pc - s->cs_base);
7063 gen_eob(s);
7064 break;
7065 default:
7066 goto illegal_op;
7068 } else { /* sidt */
7069 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7070 gen_lea_modrm(env, s, modrm);
7071 tcg_gen_ld32u_tl(cpu_T0,
7072 cpu_env, offsetof(CPUX86State, idt.limit));
7073 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7074 gen_add_A0_im(s, 2);
7075 tcg_gen_ld_tl(cpu_T0,
7076 cpu_env, offsetof(CPUX86State, idt.base));
7077 if (dflag == MO_16) {
7078 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7080 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7082 break;
7083 case 2: /* lgdt */
7084 case 3: /* lidt */
7085 if (mod == 3) {
7086 gen_update_cc_op(s);
7087 gen_jmp_im(pc_start - s->cs_base);
7088 switch(rm) {
7089 case 0: /* VMRUN */
7090 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7091 goto illegal_op;
7092 if (s->cpl != 0) {
7093 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7094 break;
7095 } else {
7096 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7097 tcg_const_i32(s->pc - pc_start));
7098 tcg_gen_exit_tb(0);
7099 s->is_jmp = DISAS_TB_JUMP;
7101 break;
7102 case 1: /* VMMCALL */
7103 if (!(s->flags & HF_SVME_MASK))
7104 goto illegal_op;
7105 gen_helper_vmmcall(cpu_env);
7106 break;
7107 case 2: /* VMLOAD */
7108 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7109 goto illegal_op;
7110 if (s->cpl != 0) {
7111 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7112 break;
7113 } else {
7114 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7116 break;
7117 case 3: /* VMSAVE */
7118 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7119 goto illegal_op;
7120 if (s->cpl != 0) {
7121 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7122 break;
7123 } else {
7124 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7126 break;
7127 case 4: /* STGI */
7128 if ((!(s->flags & HF_SVME_MASK) &&
7129 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7130 !s->pe)
7131 goto illegal_op;
7132 if (s->cpl != 0) {
7133 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7134 break;
7135 } else {
7136 gen_helper_stgi(cpu_env);
7138 break;
7139 case 5: /* CLGI */
7140 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7141 goto illegal_op;
7142 if (s->cpl != 0) {
7143 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7144 break;
7145 } else {
7146 gen_helper_clgi(cpu_env);
7148 break;
7149 case 6: /* SKINIT */
7150 if ((!(s->flags & HF_SVME_MASK) &&
7151 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7152 !s->pe)
7153 goto illegal_op;
7154 gen_helper_skinit(cpu_env);
7155 break;
7156 case 7: /* INVLPGA */
7157 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7158 goto illegal_op;
7159 if (s->cpl != 0) {
7160 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7161 break;
7162 } else {
7163 gen_helper_invlpga(cpu_env,
7164 tcg_const_i32(s->aflag - 1));
7166 break;
7167 default:
7168 goto illegal_op;
7170 } else if (s->cpl != 0) {
7171 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7172 } else {
7173 gen_svm_check_intercept(s, pc_start,
7174 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
7175 gen_lea_modrm(env, s, modrm);
7176 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7177 gen_add_A0_im(s, 2);
7178 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7179 if (dflag == MO_16) {
7180 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7182 if (op == 2) {
7183 tcg_gen_st_tl(cpu_T0, cpu_env,
7184 offsetof(CPUX86State, gdt.base));
7185 tcg_gen_st32_tl(cpu_T1, cpu_env,
7186 offsetof(CPUX86State, gdt.limit));
7187 } else {
7188 tcg_gen_st_tl(cpu_T0, cpu_env,
7189 offsetof(CPUX86State, idt.base));
7190 tcg_gen_st32_tl(cpu_T1, cpu_env,
7191 offsetof(CPUX86State, idt.limit));
7194 break;
7195 case 4: /* smsw */
7196 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7197 #if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
7198 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, cr[0]) + 4);
7199 #else
7200 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, cr[0]));
7201 #endif
7202 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 1);
7203 break;
7204 case 6: /* lmsw */
7205 if (s->cpl != 0) {
7206 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7207 } else {
7208 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7209 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7210 gen_helper_lmsw(cpu_env, cpu_T0);
7211 gen_jmp_im(s->pc - s->cs_base);
7212 gen_eob(s);
7214 break;
7215 case 7:
7216 if (mod != 3) { /* invlpg */
7217 if (s->cpl != 0) {
7218 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7219 } else {
7220 gen_update_cc_op(s);
7221 gen_jmp_im(pc_start - s->cs_base);
7222 gen_lea_modrm(env, s, modrm);
7223 gen_helper_invlpg(cpu_env, cpu_A0);
7224 gen_jmp_im(s->pc - s->cs_base);
7225 gen_eob(s);
7227 } else {
7228 switch (rm) {
7229 case 0: /* swapgs */
7230 #ifdef TARGET_X86_64
7231 if (CODE64(s)) {
7232 if (s->cpl != 0) {
7233 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7234 } else {
7235 tcg_gen_mov_tl(cpu_T0, cpu_seg_base[R_GS]);
7236 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7237 offsetof(CPUX86State, kernelgsbase));
7238 tcg_gen_st_tl(cpu_T0, cpu_env,
7239 offsetof(CPUX86State, kernelgsbase));
7241 break;
7243 #endif
7244 goto illegal_op;
7245 case 1: /* rdtscp */
7246 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7247 goto illegal_op;
7248 gen_update_cc_op(s);
7249 gen_jmp_im(pc_start - s->cs_base);
7250 if (s->tb->cflags & CF_USE_ICOUNT) {
7251 gen_io_start();
7253 gen_helper_rdtscp(cpu_env);
7254 if (s->tb->cflags & CF_USE_ICOUNT) {
7255 gen_io_end();
7256 gen_jmp(s, s->pc - s->cs_base);
7258 break;
7259 default:
7260 goto illegal_op;
7263 break;
7264 default:
7265 goto illegal_op;
7267 break;
7268 case 0x108: /* invd */
7269 case 0x109: /* wbinvd */
7270 if (s->cpl != 0) {
7271 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7272 } else {
7273 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7274 /* nothing to do */
7276 break;
7277 case 0x63: /* arpl or movslS (x86_64) */
7278 #ifdef TARGET_X86_64
7279 if (CODE64(s)) {
7280 int d_ot;
7281 /* d_ot is the size of destination */
7282 d_ot = dflag;
7284 modrm = cpu_ldub_code(env, s->pc++);
7285 reg = ((modrm >> 3) & 7) | rex_r;
7286 mod = (modrm >> 6) & 3;
7287 rm = (modrm & 7) | REX_B(s);
7289 if (mod == 3) {
7290 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
7291 /* sign extend */
7292 if (d_ot == MO_64) {
7293 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
7295 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7296 } else {
7297 gen_lea_modrm(env, s, modrm);
7298 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T0, cpu_A0);
7299 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7301 } else
7302 #endif
7304 TCGLabel *label1;
7305 TCGv t0, t1, t2, a0;
7307 if (!s->pe || s->vm86)
7308 goto illegal_op;
7309 t0 = tcg_temp_local_new();
7310 t1 = tcg_temp_local_new();
7311 t2 = tcg_temp_local_new();
7312 ot = MO_16;
7313 modrm = cpu_ldub_code(env, s->pc++);
7314 reg = (modrm >> 3) & 7;
7315 mod = (modrm >> 6) & 3;
7316 rm = modrm & 7;
7317 if (mod != 3) {
7318 gen_lea_modrm(env, s, modrm);
7319 gen_op_ld_v(s, ot, t0, cpu_A0);
7320 a0 = tcg_temp_local_new();
7321 tcg_gen_mov_tl(a0, cpu_A0);
7322 } else {
7323 gen_op_mov_v_reg(ot, t0, rm);
7324 TCGV_UNUSED(a0);
7326 gen_op_mov_v_reg(ot, t1, reg);
7327 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7328 tcg_gen_andi_tl(t1, t1, 3);
7329 tcg_gen_movi_tl(t2, 0);
7330 label1 = gen_new_label();
7331 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7332 tcg_gen_andi_tl(t0, t0, ~3);
7333 tcg_gen_or_tl(t0, t0, t1);
7334 tcg_gen_movi_tl(t2, CC_Z);
7335 gen_set_label(label1);
7336 if (mod != 3) {
7337 gen_op_st_v(s, ot, t0, a0);
7338 tcg_temp_free(a0);
7339 } else {
7340 gen_op_mov_reg_v(ot, rm, t0);
7342 gen_compute_eflags(s);
7343 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7344 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7345 tcg_temp_free(t0);
7346 tcg_temp_free(t1);
7347 tcg_temp_free(t2);
7349 break;
7350 case 0x102: /* lar */
7351 case 0x103: /* lsl */
7353 TCGLabel *label1;
7354 TCGv t0;
7355 if (!s->pe || s->vm86)
7356 goto illegal_op;
7357 ot = dflag != MO_16 ? MO_32 : MO_16;
7358 modrm = cpu_ldub_code(env, s->pc++);
7359 reg = ((modrm >> 3) & 7) | rex_r;
7360 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7361 t0 = tcg_temp_local_new();
7362 gen_update_cc_op(s);
7363 if (b == 0x102) {
7364 gen_helper_lar(t0, cpu_env, cpu_T0);
7365 } else {
7366 gen_helper_lsl(t0, cpu_env, cpu_T0);
7368 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7369 label1 = gen_new_label();
7370 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7371 gen_op_mov_reg_v(ot, reg, t0);
7372 gen_set_label(label1);
7373 set_cc_op(s, CC_OP_EFLAGS);
7374 tcg_temp_free(t0);
7376 break;
7377 case 0x118:
7378 modrm = cpu_ldub_code(env, s->pc++);
7379 mod = (modrm >> 6) & 3;
7380 op = (modrm >> 3) & 7;
7381 switch(op) {
7382 case 0: /* prefetchnta */
7383 case 1: /* prefetchnt0 */
7384 case 2: /* prefetchnt0 */
7385 case 3: /* prefetchnt0 */
7386 if (mod == 3)
7387 goto illegal_op;
7388 gen_lea_modrm(env, s, modrm);
7389 /* nothing more to do */
7390 break;
7391 default: /* nop (multi byte) */
7392 gen_nop_modrm(env, s, modrm);
7393 break;
7395 break;
7396 case 0x119 ... 0x11f: /* nop (multi byte) */
7397 modrm = cpu_ldub_code(env, s->pc++);
7398 gen_nop_modrm(env, s, modrm);
7399 break;
7400 case 0x120: /* mov reg, crN */
7401 case 0x122: /* mov crN, reg */
7402 if (s->cpl != 0) {
7403 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7404 } else {
7405 modrm = cpu_ldub_code(env, s->pc++);
7406 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7407 * AMD documentation (24594.pdf) and testing of
7408 * intel 386 and 486 processors all show that the mod bits
7409 * are assumed to be 1's, regardless of actual values.
7411 rm = (modrm & 7) | REX_B(s);
7412 reg = ((modrm >> 3) & 7) | rex_r;
7413 if (CODE64(s))
7414 ot = MO_64;
7415 else
7416 ot = MO_32;
7417 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7418 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7419 reg = 8;
7421 switch(reg) {
7422 case 0:
7423 case 2:
7424 case 3:
7425 case 4:
7426 case 8:
7427 gen_update_cc_op(s);
7428 gen_jmp_im(pc_start - s->cs_base);
7429 if (b & 2) {
7430 gen_op_mov_v_reg(ot, cpu_T0, rm);
7431 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7432 cpu_T0);
7433 gen_jmp_im(s->pc - s->cs_base);
7434 gen_eob(s);
7435 } else {
7436 gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg));
7437 gen_op_mov_reg_v(ot, rm, cpu_T0);
7439 break;
7440 default:
7441 goto illegal_op;
7444 break;
7445 case 0x121: /* mov reg, drN */
7446 case 0x123: /* mov drN, reg */
7447 if (s->cpl != 0) {
7448 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7449 } else {
7450 modrm = cpu_ldub_code(env, s->pc++);
7451 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7452 * AMD documentation (24594.pdf) and testing of
7453 * intel 386 and 486 processors all show that the mod bits
7454 * are assumed to be 1's, regardless of actual values.
7456 rm = (modrm & 7) | REX_B(s);
7457 reg = ((modrm >> 3) & 7) | rex_r;
7458 if (CODE64(s))
7459 ot = MO_64;
7460 else
7461 ot = MO_32;
7462 if (reg >= 8) {
7463 goto illegal_op;
7465 if (b & 2) {
7466 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7467 gen_op_mov_v_reg(ot, cpu_T0, rm);
7468 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7469 gen_helper_set_dr(cpu_env, cpu_tmp2_i32, cpu_T0);
7470 gen_jmp_im(s->pc - s->cs_base);
7471 gen_eob(s);
7472 } else {
7473 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7474 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7475 gen_helper_get_dr(cpu_T0, cpu_env, cpu_tmp2_i32);
7476 gen_op_mov_reg_v(ot, rm, cpu_T0);
7479 break;
7480 case 0x106: /* clts */
7481 if (s->cpl != 0) {
7482 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7483 } else {
7484 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7485 gen_helper_clts(cpu_env);
7486 /* abort block because static cpu state changed */
7487 gen_jmp_im(s->pc - s->cs_base);
7488 gen_eob(s);
7490 break;
7491 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
7492 case 0x1c3: /* MOVNTI reg, mem */
7493 if (!(s->cpuid_features & CPUID_SSE2))
7494 goto illegal_op;
7495 ot = mo_64_32(dflag);
7496 modrm = cpu_ldub_code(env, s->pc++);
7497 mod = (modrm >> 6) & 3;
7498 if (mod == 3)
7499 goto illegal_op;
7500 reg = ((modrm >> 3) & 7) | rex_r;
7501 /* generate a generic store */
7502 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
7503 break;
7504 case 0x1ae:
7505 modrm = cpu_ldub_code(env, s->pc++);
7506 mod = (modrm >> 6) & 3;
7507 op = (modrm >> 3) & 7;
7508 switch(op) {
7509 case 0: /* fxsave */
7510 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7511 (s->prefix & PREFIX_LOCK))
7512 goto illegal_op;
7513 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7514 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7515 break;
7517 gen_lea_modrm(env, s, modrm);
7518 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
7519 break;
7520 case 1: /* fxrstor */
7521 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7522 (s->prefix & PREFIX_LOCK))
7523 goto illegal_op;
7524 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7525 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7526 break;
7528 gen_lea_modrm(env, s, modrm);
7529 gen_helper_fxrstor(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
7530 break;
7531 case 2: /* ldmxcsr */
7532 case 3: /* stmxcsr */
7533 if (s->flags & HF_TS_MASK) {
7534 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7535 break;
7537 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7538 mod == 3)
7539 goto illegal_op;
7540 gen_lea_modrm(env, s, modrm);
7541 if (op == 2) {
7542 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
7543 s->mem_index, MO_LEUL);
7544 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
7545 } else {
7546 tcg_gen_ld32u_tl(cpu_T0,
7547 cpu_env, offsetof(CPUX86State, mxcsr));
7548 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
7550 break;
7551 case 5: /* lfence */
7552 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
7553 goto illegal_op;
7554 break;
7555 case 6: /* mfence/clwb */
7556 if (s->prefix & PREFIX_DATA) {
7557 /* clwb */
7558 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB))
7559 goto illegal_op;
7560 gen_nop_modrm(env, s, modrm);
7561 } else {
7562 /* mfence */
7563 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
7564 goto illegal_op;
7566 break;
7567 case 7: /* sfence / clflush / clflushopt / pcommit */
7568 if ((modrm & 0xc7) == 0xc0) {
7569 if (s->prefix & PREFIX_DATA) {
7570 /* pcommit */
7571 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT))
7572 goto illegal_op;
7573 } else {
7574 /* sfence */
7575 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
7576 if (!(s->cpuid_features & CPUID_SSE))
7577 goto illegal_op;
7579 } else {
7580 if (s->prefix & PREFIX_DATA) {
7581 /* clflushopt */
7582 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT))
7583 goto illegal_op;
7584 } else {
7585 /* clflush */
7586 if (!(s->cpuid_features & CPUID_CLFLUSH))
7587 goto illegal_op;
7589 gen_lea_modrm(env, s, modrm);
7591 break;
7592 default:
7593 goto illegal_op;
7595 break;
7596 case 0x10d: /* 3DNow! prefetch(w) */
7597 modrm = cpu_ldub_code(env, s->pc++);
7598 mod = (modrm >> 6) & 3;
7599 if (mod == 3)
7600 goto illegal_op;
7601 gen_lea_modrm(env, s, modrm);
7602 /* ignore for now */
7603 break;
7604 case 0x1aa: /* rsm */
7605 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
7606 if (!(s->flags & HF_SMM_MASK))
7607 goto illegal_op;
7608 gen_update_cc_op(s);
7609 gen_jmp_im(s->pc - s->cs_base);
7610 gen_helper_rsm(cpu_env);
7611 gen_eob(s);
7612 break;
7613 case 0x1b8: /* SSE4.2 popcnt */
7614 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
7615 PREFIX_REPZ)
7616 goto illegal_op;
7617 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
7618 goto illegal_op;
7620 modrm = cpu_ldub_code(env, s->pc++);
7621 reg = ((modrm >> 3) & 7) | rex_r;
7623 if (s->prefix & PREFIX_DATA) {
7624 ot = MO_16;
7625 } else {
7626 ot = mo_64_32(dflag);
7629 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7630 gen_helper_popcnt(cpu_T0, cpu_env, cpu_T0, tcg_const_i32(ot));
7631 gen_op_mov_reg_v(ot, reg, cpu_T0);
7633 set_cc_op(s, CC_OP_EFLAGS);
7634 break;
7635 case 0x10e ... 0x10f:
7636 /* 3DNow! instructions, ignore prefixes */
7637 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
7638 case 0x110 ... 0x117:
7639 case 0x128 ... 0x12f:
7640 case 0x138 ... 0x13a:
7641 case 0x150 ... 0x179:
7642 case 0x17c ... 0x17f:
7643 case 0x1c2:
7644 case 0x1c4 ... 0x1c6:
7645 case 0x1d0 ... 0x1fe:
7646 gen_sse(env, s, b, pc_start, rex_r);
7647 break;
7648 default:
7649 goto illegal_op;
7651 /* lock generation */
7652 if (s->prefix & PREFIX_LOCK)
7653 gen_helper_unlock();
7654 return s->pc;
7655 illegal_op:
7656 if (s->prefix & PREFIX_LOCK)
7657 gen_helper_unlock();
7658 /* XXX: ensure that no lock was generated */
7659 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7660 return s->pc;
7663 void tcg_x86_init(void)
7665 static const char reg_names[CPU_NB_REGS][4] = {
7666 #ifdef TARGET_X86_64
7667 [R_EAX] = "rax",
7668 [R_EBX] = "rbx",
7669 [R_ECX] = "rcx",
7670 [R_EDX] = "rdx",
7671 [R_ESI] = "rsi",
7672 [R_EDI] = "rdi",
7673 [R_EBP] = "rbp",
7674 [R_ESP] = "rsp",
7675 [8] = "r8",
7676 [9] = "r9",
7677 [10] = "r10",
7678 [11] = "r11",
7679 [12] = "r12",
7680 [13] = "r13",
7681 [14] = "r14",
7682 [15] = "r15",
7683 #else
7684 [R_EAX] = "eax",
7685 [R_EBX] = "ebx",
7686 [R_ECX] = "ecx",
7687 [R_EDX] = "edx",
7688 [R_ESI] = "esi",
7689 [R_EDI] = "edi",
7690 [R_EBP] = "ebp",
7691 [R_ESP] = "esp",
7692 #endif
7694 static const char seg_base_names[6][8] = {
7695 [R_CS] = "cs_base",
7696 [R_DS] = "ds_base",
7697 [R_ES] = "es_base",
7698 [R_FS] = "fs_base",
7699 [R_GS] = "gs_base",
7700 [R_SS] = "ss_base",
7702 int i;
7704 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7705 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
7706 offsetof(CPUX86State, cc_op), "cc_op");
7707 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
7708 "cc_dst");
7709 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
7710 "cc_src");
7711 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
7712 "cc_src2");
7714 for (i = 0; i < CPU_NB_REGS; ++i) {
7715 cpu_regs[i] = tcg_global_mem_new(cpu_env,
7716 offsetof(CPUX86State, regs[i]),
7717 reg_names[i]);
7720 for (i = 0; i < 6; ++i) {
7721 cpu_seg_base[i]
7722 = tcg_global_mem_new(cpu_env,
7723 offsetof(CPUX86State, segs[i].base),
7724 seg_base_names[i]);
7727 helper_lock_init();
7730 /* generate intermediate code for basic block 'tb'. */
7731 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
7733 X86CPU *cpu = x86_env_get_cpu(env);
7734 CPUState *cs = CPU(cpu);
7735 DisasContext dc1, *dc = &dc1;
7736 target_ulong pc_ptr;
7737 uint64_t flags;
7738 target_ulong pc_start;
7739 target_ulong cs_base;
7740 int num_insns;
7741 int max_insns;
7743 /* generate intermediate code */
7744 pc_start = tb->pc;
7745 cs_base = tb->cs_base;
7746 flags = tb->flags;
7748 dc->pe = (flags >> HF_PE_SHIFT) & 1;
7749 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7750 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7751 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7752 dc->f_st = 0;
7753 dc->vm86 = (flags >> VM_SHIFT) & 1;
7754 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7755 dc->iopl = (flags >> IOPL_SHIFT) & 3;
7756 dc->tf = (flags >> TF_SHIFT) & 1;
7757 dc->singlestep_enabled = cs->singlestep_enabled;
7758 dc->cc_op = CC_OP_DYNAMIC;
7759 dc->cc_op_dirty = false;
7760 dc->cs_base = cs_base;
7761 dc->tb = tb;
7762 dc->popl_esp_hack = 0;
7763 /* select memory access functions */
7764 dc->mem_index = 0;
7765 if (flags & HF_SOFTMMU_MASK) {
7766 dc->mem_index = cpu_mmu_index(env, false);
7768 dc->cpuid_features = env->features[FEAT_1_EDX];
7769 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
7770 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
7771 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
7772 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
7773 #ifdef TARGET_X86_64
7774 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7775 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7776 #endif
7777 dc->flags = flags;
7778 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
7779 (flags & HF_INHIBIT_IRQ_MASK)
7780 #ifndef CONFIG_SOFTMMU
7781 || (flags & HF_SOFTMMU_MASK)
7782 #endif
7784 /* Do not optimize repz jumps at all in icount mode, because
7785 rep movsS instructions are execured with different paths
7786 in !repz_opt and repz_opt modes. The first one was used
7787 always except single step mode. And this setting
7788 disables jumps optimization and control paths become
7789 equivalent in run and single step modes.
7790 Now there will be no jump optimization for repz in
7791 record/replay modes and there will always be an
7792 additional step for ecx=0 when icount is enabled.
7794 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
7795 #if 0
7796 /* check addseg logic */
7797 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
7798 printf("ERROR addseg\n");
7799 #endif
7801 cpu_T0 = tcg_temp_new();
7802 cpu_T1 = tcg_temp_new();
7803 cpu_A0 = tcg_temp_new();
7805 cpu_tmp0 = tcg_temp_new();
7806 cpu_tmp1_i64 = tcg_temp_new_i64();
7807 cpu_tmp2_i32 = tcg_temp_new_i32();
7808 cpu_tmp3_i32 = tcg_temp_new_i32();
7809 cpu_tmp4 = tcg_temp_new();
7810 cpu_ptr0 = tcg_temp_new_ptr();
7811 cpu_ptr1 = tcg_temp_new_ptr();
7812 cpu_cc_srcT = tcg_temp_local_new();
7814 dc->is_jmp = DISAS_NEXT;
7815 pc_ptr = pc_start;
7816 num_insns = 0;
7817 max_insns = tb->cflags & CF_COUNT_MASK;
7818 if (max_insns == 0) {
7819 max_insns = CF_COUNT_MASK;
7821 if (max_insns > TCG_MAX_INSNS) {
7822 max_insns = TCG_MAX_INSNS;
7825 gen_tb_start(tb);
7826 for(;;) {
7827 tcg_gen_insn_start(pc_ptr, dc->cc_op);
7828 num_insns++;
7830 /* If RF is set, suppress an internally generated breakpoint. */
7831 if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
7832 tb->flags & HF_RF_MASK
7833 ? BP_GDB : BP_ANY))) {
7834 gen_debug(dc, pc_ptr - dc->cs_base);
7835 /* The address covered by the breakpoint must be included in
7836 [tb->pc, tb->pc + tb->size) in order to for it to be
7837 properly cleared -- thus we increment the PC here so that
7838 the logic setting tb->size below does the right thing. */
7839 pc_ptr += 1;
7840 goto done_generating;
7842 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
7843 gen_io_start();
7846 pc_ptr = disas_insn(env, dc, pc_ptr);
7847 /* stop translation if indicated */
7848 if (dc->is_jmp)
7849 break;
7850 /* if single step mode, we generate only one instruction and
7851 generate an exception */
7852 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
7853 the flag and abort the translation to give the irqs a
7854 change to be happen */
7855 if (dc->tf || dc->singlestep_enabled ||
7856 (flags & HF_INHIBIT_IRQ_MASK)) {
7857 gen_jmp_im(pc_ptr - dc->cs_base);
7858 gen_eob(dc);
7859 break;
7861 /* Do not cross the boundary of the pages in icount mode,
7862 it can cause an exception. Do it only when boundary is
7863 crossed by the first instruction in the block.
7864 If current instruction already crossed the bound - it's ok,
7865 because an exception hasn't stopped this code.
7867 if ((tb->cflags & CF_USE_ICOUNT)
7868 && ((pc_ptr & TARGET_PAGE_MASK)
7869 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
7870 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
7871 gen_jmp_im(pc_ptr - dc->cs_base);
7872 gen_eob(dc);
7873 break;
7875 /* if too long translation, stop generation too */
7876 if (tcg_op_buf_full() ||
7877 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
7878 num_insns >= max_insns) {
7879 gen_jmp_im(pc_ptr - dc->cs_base);
7880 gen_eob(dc);
7881 break;
7883 if (singlestep) {
7884 gen_jmp_im(pc_ptr - dc->cs_base);
7885 gen_eob(dc);
7886 break;
7889 if (tb->cflags & CF_LAST_IO)
7890 gen_io_end();
7891 done_generating:
7892 gen_tb_end(tb, num_insns);
7894 #ifdef DEBUG_DISAS
7895 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
7896 int disas_flags;
7897 qemu_log("----------------\n");
7898 qemu_log("IN: %s\n", lookup_symbol(pc_start));
7899 #ifdef TARGET_X86_64
7900 if (dc->code64)
7901 disas_flags = 2;
7902 else
7903 #endif
7904 disas_flags = !dc->code32;
7905 log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
7906 qemu_log("\n");
7908 #endif
7910 tb->size = pc_ptr - pc_start;
7911 tb->icount = num_insns;
7914 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
7915 target_ulong *data)
7917 int cc_op = data[1];
7918 env->eip = data[0] - tb->cs_base;
7919 if (cc_op != CC_OP_DYNAMIC) {
7920 env->cc_op = cc_op;