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