target/i386: Reduce DisasContext.flags to uint32_t
[qemu/ar7.git] / target / i386 / tcg / translate.c
blobca7f0a8cf4636bc72815d4ba888643a5cce5106e
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.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include "qemu/host-utils.h"
22 #include "cpu.h"
23 #include "disas/disas.h"
24 #include "exec/exec-all.h"
25 #include "tcg/tcg-op.h"
26 #include "exec/cpu_ldst.h"
27 #include "exec/translator.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "helper-tcg.h"
33 #include "trace-tcg.h"
34 #include "exec/log.h"
36 #define PREFIX_REPZ 0x01
37 #define PREFIX_REPNZ 0x02
38 #define PREFIX_LOCK 0x04
39 #define PREFIX_DATA 0x08
40 #define PREFIX_ADR 0x10
41 #define PREFIX_VEX 0x20
42 #define PREFIX_REX 0x40
44 #ifdef TARGET_X86_64
45 # define ctztl ctz64
46 # define clztl clz64
47 #else
48 # define ctztl ctz32
49 # define clztl clz32
50 #endif
52 /* For a switch indexed by MODRM, match all memory operands for a given OP. */
53 #define CASE_MODRM_MEM_OP(OP) \
54 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
55 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
56 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
58 #define CASE_MODRM_OP(OP) \
59 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
60 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
61 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
62 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
64 //#define MACRO_TEST 1
66 /* global register indexes */
67 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
68 static TCGv_i32 cpu_cc_op;
69 static TCGv cpu_regs[CPU_NB_REGS];
70 static TCGv cpu_seg_base[6];
71 static TCGv_i64 cpu_bndl[4];
72 static TCGv_i64 cpu_bndu[4];
74 #include "exec/gen-icount.h"
76 typedef struct DisasContext {
77 DisasContextBase base;
79 /* current insn context */
80 int override; /* -1 if no override */
81 int prefix;
82 MemOp aflag;
83 MemOp dflag;
84 target_ulong pc_start;
85 target_ulong pc; /* pc = eip + cs_base */
86 /* current block context */
87 target_ulong cs_base; /* base of CS segment */
89 #ifndef CONFIG_USER_ONLY
90 uint8_t cpl; /* code priv level */
91 uint8_t iopl; /* i/o priv level */
92 #endif
94 #ifdef TARGET_X86_64
95 uint8_t rex_r;
96 uint8_t rex_x;
97 uint8_t rex_b;
98 bool rex_w;
99 #endif
100 int vex_l; /* vex vector length */
101 int vex_v; /* vex vvvv register, without 1's complement. */
102 CCOp cc_op; /* current CC operation */
103 bool cc_op_dirty;
104 int tf; /* TF cpu flag */
105 int jmp_opt; /* use direct block chaining for direct jumps */
106 int repz_opt; /* optimize jumps within repz instructions */
107 int mem_index; /* select memory access functions */
108 uint32_t flags; /* all execution flags */
109 int popl_esp_hack; /* for correct popl with esp base handling */
110 int rip_offset; /* only used in x86_64, but left for simplicity */
111 int cpuid_features;
112 int cpuid_ext_features;
113 int cpuid_ext2_features;
114 int cpuid_ext3_features;
115 int cpuid_7_0_ebx_features;
116 int cpuid_xsave_features;
118 /* TCG local temps */
119 TCGv cc_srcT;
120 TCGv A0;
121 TCGv T0;
122 TCGv T1;
124 /* TCG local register indexes (only used inside old micro ops) */
125 TCGv tmp0;
126 TCGv tmp4;
127 TCGv_ptr ptr0;
128 TCGv_ptr ptr1;
129 TCGv_i32 tmp2_i32;
130 TCGv_i32 tmp3_i32;
131 TCGv_i64 tmp1_i64;
133 sigjmp_buf jmpbuf;
134 } DisasContext;
136 /* The environment in which user-only runs is constrained. */
137 #ifdef CONFIG_USER_ONLY
138 #define PE(S) true
139 #define CPL(S) 3
140 #define IOPL(S) 0
141 #else
142 #define PE(S) (((S)->flags & HF_PE_MASK) != 0)
143 #define CPL(S) ((S)->cpl)
144 #define IOPL(S) ((S)->iopl)
145 #endif
146 #if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
147 #define VM86(S) false
148 #define CODE32(S) true
149 #define SS32(S) true
150 #define ADDSEG(S) false
151 #else
152 #define VM86(S) (((S)->flags & HF_VM_MASK) != 0)
153 #define CODE32(S) (((S)->flags & HF_CS32_MASK) != 0)
154 #define SS32(S) (((S)->flags & HF_SS32_MASK) != 0)
155 #define ADDSEG(S) (((S)->flags & HF_ADDSEG_MASK) != 0)
156 #endif
157 #if !defined(TARGET_X86_64)
158 #define CODE64(S) false
159 #define LMA(S) false
160 #elif defined(CONFIG_USER_ONLY)
161 #define CODE64(S) true
162 #define LMA(S) true
163 #else
164 #define CODE64(S) (((S)->flags & HF_CS64_MASK) != 0)
165 #define LMA(S) (((S)->flags & HF_LMA_MASK) != 0)
166 #endif
168 #ifdef TARGET_X86_64
169 #define REX_PREFIX(S) (((S)->prefix & PREFIX_REX) != 0)
170 #define REX_W(S) ((S)->rex_w)
171 #define REX_R(S) ((S)->rex_r + 0)
172 #define REX_X(S) ((S)->rex_x + 0)
173 #define REX_B(S) ((S)->rex_b + 0)
174 #else
175 #define REX_PREFIX(S) false
176 #define REX_W(S) false
177 #define REX_R(S) 0
178 #define REX_X(S) 0
179 #define REX_B(S) 0
180 #endif
182 static void gen_eob(DisasContext *s);
183 static void gen_jr(DisasContext *s, TCGv dest);
184 static void gen_jmp(DisasContext *s, target_ulong eip);
185 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
186 static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
188 /* i386 arith/logic operations */
189 enum {
190 OP_ADDL,
191 OP_ORL,
192 OP_ADCL,
193 OP_SBBL,
194 OP_ANDL,
195 OP_SUBL,
196 OP_XORL,
197 OP_CMPL,
200 /* i386 shift ops */
201 enum {
202 OP_ROL,
203 OP_ROR,
204 OP_RCL,
205 OP_RCR,
206 OP_SHL,
207 OP_SHR,
208 OP_SHL1, /* undocumented */
209 OP_SAR = 7,
212 enum {
213 JCC_O,
214 JCC_B,
215 JCC_Z,
216 JCC_BE,
217 JCC_S,
218 JCC_P,
219 JCC_L,
220 JCC_LE,
223 enum {
224 /* I386 int registers */
225 OR_EAX, /* MUST be even numbered */
226 OR_ECX,
227 OR_EDX,
228 OR_EBX,
229 OR_ESP,
230 OR_EBP,
231 OR_ESI,
232 OR_EDI,
234 OR_TMP0 = 16, /* temporary operand register */
235 OR_TMP1,
236 OR_A0, /* temporary register used when doing address evaluation */
239 enum {
240 USES_CC_DST = 1,
241 USES_CC_SRC = 2,
242 USES_CC_SRC2 = 4,
243 USES_CC_SRCT = 8,
246 /* Bit set if the global variable is live after setting CC_OP to X. */
247 static const uint8_t cc_op_live[CC_OP_NB] = {
248 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
249 [CC_OP_EFLAGS] = USES_CC_SRC,
250 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
251 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
252 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
253 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
254 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
255 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
256 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
257 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
258 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
259 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
260 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
261 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
262 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
263 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
264 [CC_OP_CLR] = 0,
265 [CC_OP_POPCNT] = USES_CC_SRC,
268 static void set_cc_op(DisasContext *s, CCOp op)
270 int dead;
272 if (s->cc_op == op) {
273 return;
276 /* Discard CC computation that will no longer be used. */
277 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
278 if (dead & USES_CC_DST) {
279 tcg_gen_discard_tl(cpu_cc_dst);
281 if (dead & USES_CC_SRC) {
282 tcg_gen_discard_tl(cpu_cc_src);
284 if (dead & USES_CC_SRC2) {
285 tcg_gen_discard_tl(cpu_cc_src2);
287 if (dead & USES_CC_SRCT) {
288 tcg_gen_discard_tl(s->cc_srcT);
291 if (op == CC_OP_DYNAMIC) {
292 /* The DYNAMIC setting is translator only, and should never be
293 stored. Thus we always consider it clean. */
294 s->cc_op_dirty = false;
295 } else {
296 /* Discard any computed CC_OP value (see shifts). */
297 if (s->cc_op == CC_OP_DYNAMIC) {
298 tcg_gen_discard_i32(cpu_cc_op);
300 s->cc_op_dirty = true;
302 s->cc_op = op;
305 static void gen_update_cc_op(DisasContext *s)
307 if (s->cc_op_dirty) {
308 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
309 s->cc_op_dirty = false;
313 #ifdef TARGET_X86_64
315 #define NB_OP_SIZES 4
317 #else /* !TARGET_X86_64 */
319 #define NB_OP_SIZES 3
321 #endif /* !TARGET_X86_64 */
323 #if defined(HOST_WORDS_BIGENDIAN)
324 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
325 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
326 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
327 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
328 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
329 #else
330 #define REG_B_OFFSET 0
331 #define REG_H_OFFSET 1
332 #define REG_W_OFFSET 0
333 #define REG_L_OFFSET 0
334 #define REG_LH_OFFSET 4
335 #endif
337 /* In instruction encodings for byte register accesses the
338 * register number usually indicates "low 8 bits of register N";
339 * however there are some special cases where N 4..7 indicates
340 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
341 * true for this special case, false otherwise.
343 static inline bool byte_reg_is_xH(DisasContext *s, int reg)
345 /* Any time the REX prefix is present, byte registers are uniform */
346 if (reg < 4 || REX_PREFIX(s)) {
347 return false;
349 return true;
352 /* Select the size of a push/pop operation. */
353 static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
355 if (CODE64(s)) {
356 return ot == MO_16 ? MO_16 : MO_64;
357 } else {
358 return ot;
362 /* Select the size of the stack pointer. */
363 static inline MemOp mo_stacksize(DisasContext *s)
365 return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
368 /* Select only size 64 else 32. Used for SSE operand sizes. */
369 static inline MemOp mo_64_32(MemOp ot)
371 #ifdef TARGET_X86_64
372 return ot == MO_64 ? MO_64 : MO_32;
373 #else
374 return MO_32;
375 #endif
378 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
379 byte vs word opcodes. */
380 static inline MemOp mo_b_d(int b, MemOp ot)
382 return b & 1 ? ot : MO_8;
385 /* Select size 8 if lsb of B is clear, else OT capped at 32.
386 Used for decoding operand size of port opcodes. */
387 static inline MemOp mo_b_d32(int b, MemOp ot)
389 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
392 static void gen_op_mov_reg_v(DisasContext *s, MemOp ot, int reg, TCGv t0)
394 switch(ot) {
395 case MO_8:
396 if (!byte_reg_is_xH(s, reg)) {
397 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
398 } else {
399 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
401 break;
402 case MO_16:
403 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
404 break;
405 case MO_32:
406 /* For x86_64, this sets the higher half of register to zero.
407 For i386, this is equivalent to a mov. */
408 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
409 break;
410 #ifdef TARGET_X86_64
411 case MO_64:
412 tcg_gen_mov_tl(cpu_regs[reg], t0);
413 break;
414 #endif
415 default:
416 tcg_abort();
420 static inline
421 void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg)
423 if (ot == MO_8 && byte_reg_is_xH(s, reg)) {
424 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
425 } else {
426 tcg_gen_mov_tl(t0, cpu_regs[reg]);
430 static void gen_add_A0_im(DisasContext *s, int val)
432 tcg_gen_addi_tl(s->A0, s->A0, val);
433 if (!CODE64(s)) {
434 tcg_gen_ext32u_tl(s->A0, s->A0);
438 static inline void gen_op_jmp_v(TCGv dest)
440 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
443 static inline
444 void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val)
446 tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val);
447 gen_op_mov_reg_v(s, size, reg, s->tmp0);
450 static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg)
452 tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0);
453 gen_op_mov_reg_v(s, size, reg, s->tmp0);
456 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
458 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
461 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
463 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
466 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
468 if (d == OR_TMP0) {
469 gen_op_st_v(s, idx, s->T0, s->A0);
470 } else {
471 gen_op_mov_reg_v(s, idx, d, s->T0);
475 static inline void gen_jmp_im(DisasContext *s, target_ulong pc)
477 tcg_gen_movi_tl(s->tmp0, pc);
478 gen_op_jmp_v(s->tmp0);
481 /* Compute SEG:REG into A0. SEG is selected from the override segment
482 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
483 indicate no override. */
484 static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
485 int def_seg, int ovr_seg)
487 switch (aflag) {
488 #ifdef TARGET_X86_64
489 case MO_64:
490 if (ovr_seg < 0) {
491 tcg_gen_mov_tl(s->A0, a0);
492 return;
494 break;
495 #endif
496 case MO_32:
497 /* 32 bit address */
498 if (ovr_seg < 0 && ADDSEG(s)) {
499 ovr_seg = def_seg;
501 if (ovr_seg < 0) {
502 tcg_gen_ext32u_tl(s->A0, a0);
503 return;
505 break;
506 case MO_16:
507 /* 16 bit address */
508 tcg_gen_ext16u_tl(s->A0, a0);
509 a0 = s->A0;
510 if (ovr_seg < 0) {
511 if (ADDSEG(s)) {
512 ovr_seg = def_seg;
513 } else {
514 return;
517 break;
518 default:
519 tcg_abort();
522 if (ovr_seg >= 0) {
523 TCGv seg = cpu_seg_base[ovr_seg];
525 if (aflag == MO_64) {
526 tcg_gen_add_tl(s->A0, a0, seg);
527 } else if (CODE64(s)) {
528 tcg_gen_ext32u_tl(s->A0, a0);
529 tcg_gen_add_tl(s->A0, s->A0, seg);
530 } else {
531 tcg_gen_add_tl(s->A0, a0, seg);
532 tcg_gen_ext32u_tl(s->A0, s->A0);
537 static inline void gen_string_movl_A0_ESI(DisasContext *s)
539 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
542 static inline void gen_string_movl_A0_EDI(DisasContext *s)
544 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
547 static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
549 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
550 tcg_gen_shli_tl(s->T0, s->T0, ot);
553 static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
555 switch (size) {
556 case MO_8:
557 if (sign) {
558 tcg_gen_ext8s_tl(dst, src);
559 } else {
560 tcg_gen_ext8u_tl(dst, src);
562 return dst;
563 case MO_16:
564 if (sign) {
565 tcg_gen_ext16s_tl(dst, src);
566 } else {
567 tcg_gen_ext16u_tl(dst, src);
569 return dst;
570 #ifdef TARGET_X86_64
571 case MO_32:
572 if (sign) {
573 tcg_gen_ext32s_tl(dst, src);
574 } else {
575 tcg_gen_ext32u_tl(dst, src);
577 return dst;
578 #endif
579 default:
580 return src;
584 static void gen_extu(MemOp ot, TCGv reg)
586 gen_ext_tl(reg, reg, ot, false);
589 static void gen_exts(MemOp ot, TCGv reg)
591 gen_ext_tl(reg, reg, ot, true);
594 static inline
595 void gen_op_jnz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
597 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
598 gen_extu(size, s->tmp0);
599 tcg_gen_brcondi_tl(TCG_COND_NE, s->tmp0, 0, label1);
602 static inline
603 void gen_op_jz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
605 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
606 gen_extu(size, s->tmp0);
607 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
610 static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
612 switch (ot) {
613 case MO_8:
614 gen_helper_inb(v, cpu_env, n);
615 break;
616 case MO_16:
617 gen_helper_inw(v, cpu_env, n);
618 break;
619 case MO_32:
620 gen_helper_inl(v, cpu_env, n);
621 break;
622 default:
623 tcg_abort();
627 static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
629 switch (ot) {
630 case MO_8:
631 gen_helper_outb(cpu_env, v, n);
632 break;
633 case MO_16:
634 gen_helper_outw(cpu_env, v, n);
635 break;
636 case MO_32:
637 gen_helper_outl(cpu_env, v, n);
638 break;
639 default:
640 tcg_abort();
644 static void gen_check_io(DisasContext *s, MemOp ot, target_ulong cur_eip,
645 uint32_t svm_flags)
647 target_ulong next_eip;
649 if (PE(s) && (CPL(s) > IOPL(s) || VM86(s))) {
650 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
651 switch (ot) {
652 case MO_8:
653 gen_helper_check_iob(cpu_env, s->tmp2_i32);
654 break;
655 case MO_16:
656 gen_helper_check_iow(cpu_env, s->tmp2_i32);
657 break;
658 case MO_32:
659 gen_helper_check_iol(cpu_env, s->tmp2_i32);
660 break;
661 default:
662 tcg_abort();
665 if(s->flags & HF_GUEST_MASK) {
666 gen_update_cc_op(s);
667 gen_jmp_im(s, cur_eip);
668 svm_flags |= (1 << (4 + ot));
669 next_eip = s->pc - s->cs_base;
670 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
671 gen_helper_svm_check_io(cpu_env, s->tmp2_i32,
672 tcg_const_i32(svm_flags),
673 tcg_const_i32(next_eip - cur_eip));
677 static inline void gen_movs(DisasContext *s, MemOp ot)
679 gen_string_movl_A0_ESI(s);
680 gen_op_ld_v(s, ot, s->T0, s->A0);
681 gen_string_movl_A0_EDI(s);
682 gen_op_st_v(s, ot, s->T0, s->A0);
683 gen_op_movl_T0_Dshift(s, ot);
684 gen_op_add_reg_T0(s, s->aflag, R_ESI);
685 gen_op_add_reg_T0(s, s->aflag, R_EDI);
688 static void gen_op_update1_cc(DisasContext *s)
690 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
693 static void gen_op_update2_cc(DisasContext *s)
695 tcg_gen_mov_tl(cpu_cc_src, s->T1);
696 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
699 static void gen_op_update3_cc(DisasContext *s, TCGv reg)
701 tcg_gen_mov_tl(cpu_cc_src2, reg);
702 tcg_gen_mov_tl(cpu_cc_src, s->T1);
703 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
706 static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
708 tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1);
711 static void gen_op_update_neg_cc(DisasContext *s)
713 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
714 tcg_gen_neg_tl(cpu_cc_src, s->T0);
715 tcg_gen_movi_tl(s->cc_srcT, 0);
718 /* compute all eflags to cc_src */
719 static void gen_compute_eflags(DisasContext *s)
721 TCGv zero, dst, src1, src2;
722 int live, dead;
724 if (s->cc_op == CC_OP_EFLAGS) {
725 return;
727 if (s->cc_op == CC_OP_CLR) {
728 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
729 set_cc_op(s, CC_OP_EFLAGS);
730 return;
733 zero = NULL;
734 dst = cpu_cc_dst;
735 src1 = cpu_cc_src;
736 src2 = cpu_cc_src2;
738 /* Take care to not read values that are not live. */
739 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
740 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
741 if (dead) {
742 zero = tcg_const_tl(0);
743 if (dead & USES_CC_DST) {
744 dst = zero;
746 if (dead & USES_CC_SRC) {
747 src1 = zero;
749 if (dead & USES_CC_SRC2) {
750 src2 = zero;
754 gen_update_cc_op(s);
755 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
756 set_cc_op(s, CC_OP_EFLAGS);
758 if (dead) {
759 tcg_temp_free(zero);
763 typedef struct CCPrepare {
764 TCGCond cond;
765 TCGv reg;
766 TCGv reg2;
767 target_ulong imm;
768 target_ulong mask;
769 bool use_reg2;
770 bool no_setcond;
771 } CCPrepare;
773 /* compute eflags.C to reg */
774 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
776 TCGv t0, t1;
777 int size, shift;
779 switch (s->cc_op) {
780 case CC_OP_SUBB ... CC_OP_SUBQ:
781 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
782 size = s->cc_op - CC_OP_SUBB;
783 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
784 /* If no temporary was used, be careful not to alias t1 and t0. */
785 t0 = t1 == cpu_cc_src ? s->tmp0 : reg;
786 tcg_gen_mov_tl(t0, s->cc_srcT);
787 gen_extu(size, t0);
788 goto add_sub;
790 case CC_OP_ADDB ... CC_OP_ADDQ:
791 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
792 size = s->cc_op - CC_OP_ADDB;
793 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
794 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
795 add_sub:
796 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
797 .reg2 = t1, .mask = -1, .use_reg2 = true };
799 case CC_OP_LOGICB ... CC_OP_LOGICQ:
800 case CC_OP_CLR:
801 case CC_OP_POPCNT:
802 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
804 case CC_OP_INCB ... CC_OP_INCQ:
805 case CC_OP_DECB ... CC_OP_DECQ:
806 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
807 .mask = -1, .no_setcond = true };
809 case CC_OP_SHLB ... CC_OP_SHLQ:
810 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
811 size = s->cc_op - CC_OP_SHLB;
812 shift = (8 << size) - 1;
813 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
814 .mask = (target_ulong)1 << shift };
816 case CC_OP_MULB ... CC_OP_MULQ:
817 return (CCPrepare) { .cond = TCG_COND_NE,
818 .reg = cpu_cc_src, .mask = -1 };
820 case CC_OP_BMILGB ... CC_OP_BMILGQ:
821 size = s->cc_op - CC_OP_BMILGB;
822 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
823 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
825 case CC_OP_ADCX:
826 case CC_OP_ADCOX:
827 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
828 .mask = -1, .no_setcond = true };
830 case CC_OP_EFLAGS:
831 case CC_OP_SARB ... CC_OP_SARQ:
832 /* CC_SRC & 1 */
833 return (CCPrepare) { .cond = TCG_COND_NE,
834 .reg = cpu_cc_src, .mask = CC_C };
836 default:
837 /* The need to compute only C from CC_OP_DYNAMIC is important
838 in efficiently implementing e.g. INC at the start of a TB. */
839 gen_update_cc_op(s);
840 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
841 cpu_cc_src2, cpu_cc_op);
842 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
843 .mask = -1, .no_setcond = true };
847 /* compute eflags.P to reg */
848 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
850 gen_compute_eflags(s);
851 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
852 .mask = CC_P };
855 /* compute eflags.S to reg */
856 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
858 switch (s->cc_op) {
859 case CC_OP_DYNAMIC:
860 gen_compute_eflags(s);
861 /* FALLTHRU */
862 case CC_OP_EFLAGS:
863 case CC_OP_ADCX:
864 case CC_OP_ADOX:
865 case CC_OP_ADCOX:
866 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
867 .mask = CC_S };
868 case CC_OP_CLR:
869 case CC_OP_POPCNT:
870 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
871 default:
873 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
874 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
875 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
880 /* compute eflags.O to reg */
881 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
883 switch (s->cc_op) {
884 case CC_OP_ADOX:
885 case CC_OP_ADCOX:
886 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
887 .mask = -1, .no_setcond = true };
888 case CC_OP_CLR:
889 case CC_OP_POPCNT:
890 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
891 default:
892 gen_compute_eflags(s);
893 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
894 .mask = CC_O };
898 /* compute eflags.Z to reg */
899 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
901 switch (s->cc_op) {
902 case CC_OP_DYNAMIC:
903 gen_compute_eflags(s);
904 /* FALLTHRU */
905 case CC_OP_EFLAGS:
906 case CC_OP_ADCX:
907 case CC_OP_ADOX:
908 case CC_OP_ADCOX:
909 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
910 .mask = CC_Z };
911 case CC_OP_CLR:
912 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
913 case CC_OP_POPCNT:
914 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
915 .mask = -1 };
916 default:
918 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
919 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
920 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
925 /* perform a conditional store into register 'reg' according to jump opcode
926 value 'b'. In the fast case, T0 is guaranted not to be used. */
927 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
929 int inv, jcc_op, cond;
930 MemOp size;
931 CCPrepare cc;
932 TCGv t0;
934 inv = b & 1;
935 jcc_op = (b >> 1) & 7;
937 switch (s->cc_op) {
938 case CC_OP_SUBB ... CC_OP_SUBQ:
939 /* We optimize relational operators for the cmp/jcc case. */
940 size = s->cc_op - CC_OP_SUBB;
941 switch (jcc_op) {
942 case JCC_BE:
943 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
944 gen_extu(size, s->tmp4);
945 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
946 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4,
947 .reg2 = t0, .mask = -1, .use_reg2 = true };
948 break;
950 case JCC_L:
951 cond = TCG_COND_LT;
952 goto fast_jcc_l;
953 case JCC_LE:
954 cond = TCG_COND_LE;
955 fast_jcc_l:
956 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
957 gen_exts(size, s->tmp4);
958 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true);
959 cc = (CCPrepare) { .cond = cond, .reg = s->tmp4,
960 .reg2 = t0, .mask = -1, .use_reg2 = true };
961 break;
963 default:
964 goto slow_jcc;
966 break;
968 default:
969 slow_jcc:
970 /* This actually generates good code for JC, JZ and JS. */
971 switch (jcc_op) {
972 case JCC_O:
973 cc = gen_prepare_eflags_o(s, reg);
974 break;
975 case JCC_B:
976 cc = gen_prepare_eflags_c(s, reg);
977 break;
978 case JCC_Z:
979 cc = gen_prepare_eflags_z(s, reg);
980 break;
981 case JCC_BE:
982 gen_compute_eflags(s);
983 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
984 .mask = CC_Z | CC_C };
985 break;
986 case JCC_S:
987 cc = gen_prepare_eflags_s(s, reg);
988 break;
989 case JCC_P:
990 cc = gen_prepare_eflags_p(s, reg);
991 break;
992 case JCC_L:
993 gen_compute_eflags(s);
994 if (reg == cpu_cc_src) {
995 reg = s->tmp0;
997 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
998 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
999 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1000 .mask = CC_S };
1001 break;
1002 default:
1003 case JCC_LE:
1004 gen_compute_eflags(s);
1005 if (reg == cpu_cc_src) {
1006 reg = s->tmp0;
1008 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1009 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1010 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1011 .mask = CC_S | CC_Z };
1012 break;
1014 break;
1017 if (inv) {
1018 cc.cond = tcg_invert_cond(cc.cond);
1020 return cc;
1023 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1025 CCPrepare cc = gen_prepare_cc(s, b, reg);
1027 if (cc.no_setcond) {
1028 if (cc.cond == TCG_COND_EQ) {
1029 tcg_gen_xori_tl(reg, cc.reg, 1);
1030 } else {
1031 tcg_gen_mov_tl(reg, cc.reg);
1033 return;
1036 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1037 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1038 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1039 tcg_gen_andi_tl(reg, reg, 1);
1040 return;
1042 if (cc.mask != -1) {
1043 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1044 cc.reg = reg;
1046 if (cc.use_reg2) {
1047 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1048 } else {
1049 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1053 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1055 gen_setcc1(s, JCC_B << 1, reg);
1058 /* generate a conditional jump to label 'l1' according to jump opcode
1059 value 'b'. In the fast case, T0 is guaranted not to be used. */
1060 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1062 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1064 if (cc.mask != -1) {
1065 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1066 cc.reg = s->T0;
1068 if (cc.use_reg2) {
1069 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1070 } else {
1071 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1075 /* Generate a conditional jump to label 'l1' according to jump opcode
1076 value 'b'. In the fast case, T0 is guaranted not to be used.
1077 A translation block must end soon. */
1078 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1080 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1082 gen_update_cc_op(s);
1083 if (cc.mask != -1) {
1084 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1085 cc.reg = s->T0;
1087 set_cc_op(s, CC_OP_DYNAMIC);
1088 if (cc.use_reg2) {
1089 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1090 } else {
1091 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1095 /* XXX: does not work with gdbstub "ice" single step - not a
1096 serious problem */
1097 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1099 TCGLabel *l1 = gen_new_label();
1100 TCGLabel *l2 = gen_new_label();
1101 gen_op_jnz_ecx(s, s->aflag, l1);
1102 gen_set_label(l2);
1103 gen_jmp_tb(s, next_eip, 1);
1104 gen_set_label(l1);
1105 return l2;
1108 static inline void gen_stos(DisasContext *s, MemOp ot)
1110 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
1111 gen_string_movl_A0_EDI(s);
1112 gen_op_st_v(s, ot, s->T0, s->A0);
1113 gen_op_movl_T0_Dshift(s, ot);
1114 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1117 static inline void gen_lods(DisasContext *s, MemOp ot)
1119 gen_string_movl_A0_ESI(s);
1120 gen_op_ld_v(s, ot, s->T0, s->A0);
1121 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
1122 gen_op_movl_T0_Dshift(s, ot);
1123 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1126 static inline void gen_scas(DisasContext *s, MemOp ot)
1128 gen_string_movl_A0_EDI(s);
1129 gen_op_ld_v(s, ot, s->T1, s->A0);
1130 gen_op(s, OP_CMPL, ot, R_EAX);
1131 gen_op_movl_T0_Dshift(s, ot);
1132 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1135 static inline void gen_cmps(DisasContext *s, MemOp ot)
1137 gen_string_movl_A0_EDI(s);
1138 gen_op_ld_v(s, ot, s->T1, s->A0);
1139 gen_string_movl_A0_ESI(s);
1140 gen_op(s, OP_CMPL, ot, OR_TMP0);
1141 gen_op_movl_T0_Dshift(s, ot);
1142 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1143 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1146 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1148 if (s->flags & HF_IOBPT_MASK) {
1149 #ifdef CONFIG_USER_ONLY
1150 /* user-mode cpu should not be in IOBPT mode */
1151 g_assert_not_reached();
1152 #else
1153 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1154 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1156 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1157 tcg_temp_free_i32(t_size);
1158 tcg_temp_free(t_next);
1159 #endif /* CONFIG_USER_ONLY */
1163 static inline void gen_ins(DisasContext *s, MemOp ot)
1165 gen_string_movl_A0_EDI(s);
1166 /* Note: we must do this dummy write first to be restartable in
1167 case of page fault. */
1168 tcg_gen_movi_tl(s->T0, 0);
1169 gen_op_st_v(s, ot, s->T0, s->A0);
1170 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1171 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1172 gen_helper_in_func(ot, s->T0, s->tmp2_i32);
1173 gen_op_st_v(s, ot, s->T0, s->A0);
1174 gen_op_movl_T0_Dshift(s, ot);
1175 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1176 gen_bpt_io(s, s->tmp2_i32, ot);
1179 static inline void gen_outs(DisasContext *s, MemOp ot)
1181 gen_string_movl_A0_ESI(s);
1182 gen_op_ld_v(s, ot, s->T0, s->A0);
1184 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1185 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1186 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0);
1187 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
1188 gen_op_movl_T0_Dshift(s, ot);
1189 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1190 gen_bpt_io(s, s->tmp2_i32, ot);
1193 /* same method as Valgrind : we generate jumps to current or next
1194 instruction */
1195 #define GEN_REPZ(op) \
1196 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1197 target_ulong cur_eip, target_ulong next_eip) \
1199 TCGLabel *l2; \
1200 gen_update_cc_op(s); \
1201 l2 = gen_jz_ecx_string(s, next_eip); \
1202 gen_ ## op(s, ot); \
1203 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1204 /* a loop would cause two single step exceptions if ECX = 1 \
1205 before rep string_insn */ \
1206 if (s->repz_opt) \
1207 gen_op_jz_ecx(s, s->aflag, l2); \
1208 gen_jmp(s, cur_eip); \
1211 #define GEN_REPZ2(op) \
1212 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1213 target_ulong cur_eip, \
1214 target_ulong next_eip, \
1215 int nz) \
1217 TCGLabel *l2; \
1218 gen_update_cc_op(s); \
1219 l2 = gen_jz_ecx_string(s, next_eip); \
1220 gen_ ## op(s, ot); \
1221 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1222 gen_update_cc_op(s); \
1223 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1224 if (s->repz_opt) \
1225 gen_op_jz_ecx(s, s->aflag, l2); \
1226 gen_jmp(s, cur_eip); \
1229 GEN_REPZ(movs)
1230 GEN_REPZ(stos)
1231 GEN_REPZ(lods)
1232 GEN_REPZ(ins)
1233 GEN_REPZ(outs)
1234 GEN_REPZ2(scas)
1235 GEN_REPZ2(cmps)
1237 static void gen_helper_fp_arith_ST0_FT0(int op)
1239 switch (op) {
1240 case 0:
1241 gen_helper_fadd_ST0_FT0(cpu_env);
1242 break;
1243 case 1:
1244 gen_helper_fmul_ST0_FT0(cpu_env);
1245 break;
1246 case 2:
1247 gen_helper_fcom_ST0_FT0(cpu_env);
1248 break;
1249 case 3:
1250 gen_helper_fcom_ST0_FT0(cpu_env);
1251 break;
1252 case 4:
1253 gen_helper_fsub_ST0_FT0(cpu_env);
1254 break;
1255 case 5:
1256 gen_helper_fsubr_ST0_FT0(cpu_env);
1257 break;
1258 case 6:
1259 gen_helper_fdiv_ST0_FT0(cpu_env);
1260 break;
1261 case 7:
1262 gen_helper_fdivr_ST0_FT0(cpu_env);
1263 break;
1267 /* NOTE the exception in "r" op ordering */
1268 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1270 TCGv_i32 tmp = tcg_const_i32(opreg);
1271 switch (op) {
1272 case 0:
1273 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1274 break;
1275 case 1:
1276 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1277 break;
1278 case 4:
1279 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1280 break;
1281 case 5:
1282 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1283 break;
1284 case 6:
1285 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1286 break;
1287 case 7:
1288 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1289 break;
1293 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
1295 gen_update_cc_op(s);
1296 gen_jmp_im(s, cur_eip);
1297 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
1298 s->base.is_jmp = DISAS_NORETURN;
1301 /* Generate #UD for the current instruction. The assumption here is that
1302 the instruction is known, but it isn't allowed in the current cpu mode. */
1303 static void gen_illegal_opcode(DisasContext *s)
1305 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
1308 /* Generate #GP for the current instruction. */
1309 static void gen_exception_gpf(DisasContext *s)
1311 gen_exception(s, EXCP0D_GPF, s->pc_start - s->cs_base);
1314 /* Check for cpl == 0; if not, raise #GP and return false. */
1315 static bool check_cpl0(DisasContext *s)
1317 if (CPL(s) == 0) {
1318 return true;
1320 gen_exception_gpf(s);
1321 return false;
1324 /* If vm86, check for iopl == 3; if not, raise #GP and return false. */
1325 static bool check_vm86_iopl(DisasContext *s)
1327 if (!VM86(s) || IOPL(s) == 3) {
1328 return true;
1330 gen_exception_gpf(s);
1331 return false;
1334 /* Check for iopl allowing access; if not, raise #GP and return false. */
1335 static bool check_iopl(DisasContext *s)
1337 if (VM86(s) ? IOPL(s) == 3 : CPL(s) <= IOPL(s)) {
1338 return true;
1340 gen_exception_gpf(s);
1341 return false;
1344 /* if d == OR_TMP0, it means memory operand (address in A0) */
1345 static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
1347 if (d != OR_TMP0) {
1348 if (s1->prefix & PREFIX_LOCK) {
1349 /* Lock prefix when destination is not memory. */
1350 gen_illegal_opcode(s1);
1351 return;
1353 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1354 } else if (!(s1->prefix & PREFIX_LOCK)) {
1355 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1357 switch(op) {
1358 case OP_ADCL:
1359 gen_compute_eflags_c(s1, s1->tmp4);
1360 if (s1->prefix & PREFIX_LOCK) {
1361 tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1);
1362 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1363 s1->mem_index, ot | MO_LE);
1364 } else {
1365 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1366 tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4);
1367 gen_op_st_rm_T0_A0(s1, ot, d);
1369 gen_op_update3_cc(s1, s1->tmp4);
1370 set_cc_op(s1, CC_OP_ADCB + ot);
1371 break;
1372 case OP_SBBL:
1373 gen_compute_eflags_c(s1, s1->tmp4);
1374 if (s1->prefix & PREFIX_LOCK) {
1375 tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4);
1376 tcg_gen_neg_tl(s1->T0, s1->T0);
1377 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1378 s1->mem_index, ot | MO_LE);
1379 } else {
1380 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1381 tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4);
1382 gen_op_st_rm_T0_A0(s1, ot, d);
1384 gen_op_update3_cc(s1, s1->tmp4);
1385 set_cc_op(s1, CC_OP_SBBB + ot);
1386 break;
1387 case OP_ADDL:
1388 if (s1->prefix & PREFIX_LOCK) {
1389 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1,
1390 s1->mem_index, ot | MO_LE);
1391 } else {
1392 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1393 gen_op_st_rm_T0_A0(s1, ot, d);
1395 gen_op_update2_cc(s1);
1396 set_cc_op(s1, CC_OP_ADDB + ot);
1397 break;
1398 case OP_SUBL:
1399 if (s1->prefix & PREFIX_LOCK) {
1400 tcg_gen_neg_tl(s1->T0, s1->T1);
1401 tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
1402 s1->mem_index, ot | MO_LE);
1403 tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
1404 } else {
1405 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1406 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1407 gen_op_st_rm_T0_A0(s1, ot, d);
1409 gen_op_update2_cc(s1);
1410 set_cc_op(s1, CC_OP_SUBB + ot);
1411 break;
1412 default:
1413 case OP_ANDL:
1414 if (s1->prefix & PREFIX_LOCK) {
1415 tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1,
1416 s1->mem_index, ot | MO_LE);
1417 } else {
1418 tcg_gen_and_tl(s1->T0, s1->T0, s1->T1);
1419 gen_op_st_rm_T0_A0(s1, ot, d);
1421 gen_op_update1_cc(s1);
1422 set_cc_op(s1, CC_OP_LOGICB + ot);
1423 break;
1424 case OP_ORL:
1425 if (s1->prefix & PREFIX_LOCK) {
1426 tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1,
1427 s1->mem_index, ot | MO_LE);
1428 } else {
1429 tcg_gen_or_tl(s1->T0, s1->T0, s1->T1);
1430 gen_op_st_rm_T0_A0(s1, ot, d);
1432 gen_op_update1_cc(s1);
1433 set_cc_op(s1, CC_OP_LOGICB + ot);
1434 break;
1435 case OP_XORL:
1436 if (s1->prefix & PREFIX_LOCK) {
1437 tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1,
1438 s1->mem_index, ot | MO_LE);
1439 } else {
1440 tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1);
1441 gen_op_st_rm_T0_A0(s1, ot, d);
1443 gen_op_update1_cc(s1);
1444 set_cc_op(s1, CC_OP_LOGICB + ot);
1445 break;
1446 case OP_CMPL:
1447 tcg_gen_mov_tl(cpu_cc_src, s1->T1);
1448 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1449 tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
1450 set_cc_op(s1, CC_OP_SUBB + ot);
1451 break;
1455 /* if d == OR_TMP0, it means memory operand (address in A0) */
1456 static void gen_inc(DisasContext *s1, MemOp ot, int d, int c)
1458 if (s1->prefix & PREFIX_LOCK) {
1459 if (d != OR_TMP0) {
1460 /* Lock prefix when destination is not memory */
1461 gen_illegal_opcode(s1);
1462 return;
1464 tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
1465 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1466 s1->mem_index, ot | MO_LE);
1467 } else {
1468 if (d != OR_TMP0) {
1469 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1470 } else {
1471 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1473 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
1474 gen_op_st_rm_T0_A0(s1, ot, d);
1477 gen_compute_eflags_c(s1, cpu_cc_src);
1478 tcg_gen_mov_tl(cpu_cc_dst, s1->T0);
1479 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1482 static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
1483 TCGv shm1, TCGv count, bool is_right)
1485 TCGv_i32 z32, s32, oldop;
1486 TCGv z_tl;
1488 /* Store the results into the CC variables. If we know that the
1489 variable must be dead, store unconditionally. Otherwise we'll
1490 need to not disrupt the current contents. */
1491 z_tl = tcg_const_tl(0);
1492 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1493 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1494 result, cpu_cc_dst);
1495 } else {
1496 tcg_gen_mov_tl(cpu_cc_dst, result);
1498 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1499 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1500 shm1, cpu_cc_src);
1501 } else {
1502 tcg_gen_mov_tl(cpu_cc_src, shm1);
1504 tcg_temp_free(z_tl);
1506 /* Get the two potential CC_OP values into temporaries. */
1507 tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1508 if (s->cc_op == CC_OP_DYNAMIC) {
1509 oldop = cpu_cc_op;
1510 } else {
1511 tcg_gen_movi_i32(s->tmp3_i32, s->cc_op);
1512 oldop = s->tmp3_i32;
1515 /* Conditionally store the CC_OP value. */
1516 z32 = tcg_const_i32(0);
1517 s32 = tcg_temp_new_i32();
1518 tcg_gen_trunc_tl_i32(s32, count);
1519 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop);
1520 tcg_temp_free_i32(z32);
1521 tcg_temp_free_i32(s32);
1523 /* The CC_OP value is no longer predictable. */
1524 set_cc_op(s, CC_OP_DYNAMIC);
1527 static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1,
1528 int is_right, int is_arith)
1530 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1532 /* load */
1533 if (op1 == OR_TMP0) {
1534 gen_op_ld_v(s, ot, s->T0, s->A0);
1535 } else {
1536 gen_op_mov_v_reg(s, ot, s->T0, op1);
1539 tcg_gen_andi_tl(s->T1, s->T1, mask);
1540 tcg_gen_subi_tl(s->tmp0, s->T1, 1);
1542 if (is_right) {
1543 if (is_arith) {
1544 gen_exts(ot, s->T0);
1545 tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0);
1546 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
1547 } else {
1548 gen_extu(ot, s->T0);
1549 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1550 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
1552 } else {
1553 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1554 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
1557 /* store */
1558 gen_op_st_rm_T0_A0(s, ot, op1);
1560 gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right);
1563 static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1564 int is_right, int is_arith)
1566 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1568 /* load */
1569 if (op1 == OR_TMP0)
1570 gen_op_ld_v(s, ot, s->T0, s->A0);
1571 else
1572 gen_op_mov_v_reg(s, ot, s->T0, op1);
1574 op2 &= mask;
1575 if (op2 != 0) {
1576 if (is_right) {
1577 if (is_arith) {
1578 gen_exts(ot, s->T0);
1579 tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1);
1580 tcg_gen_sari_tl(s->T0, s->T0, op2);
1581 } else {
1582 gen_extu(ot, s->T0);
1583 tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1);
1584 tcg_gen_shri_tl(s->T0, s->T0, op2);
1586 } else {
1587 tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1);
1588 tcg_gen_shli_tl(s->T0, s->T0, op2);
1592 /* store */
1593 gen_op_st_rm_T0_A0(s, ot, op1);
1595 /* update eflags if non zero shift */
1596 if (op2 != 0) {
1597 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
1598 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
1599 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1603 static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right)
1605 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1606 TCGv_i32 t0, t1;
1608 /* load */
1609 if (op1 == OR_TMP0) {
1610 gen_op_ld_v(s, ot, s->T0, s->A0);
1611 } else {
1612 gen_op_mov_v_reg(s, ot, s->T0, op1);
1615 tcg_gen_andi_tl(s->T1, s->T1, mask);
1617 switch (ot) {
1618 case MO_8:
1619 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1620 tcg_gen_ext8u_tl(s->T0, s->T0);
1621 tcg_gen_muli_tl(s->T0, s->T0, 0x01010101);
1622 goto do_long;
1623 case MO_16:
1624 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1625 tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16);
1626 goto do_long;
1627 do_long:
1628 #ifdef TARGET_X86_64
1629 case MO_32:
1630 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1631 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
1632 if (is_right) {
1633 tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1634 } else {
1635 tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1637 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1638 break;
1639 #endif
1640 default:
1641 if (is_right) {
1642 tcg_gen_rotr_tl(s->T0, s->T0, s->T1);
1643 } else {
1644 tcg_gen_rotl_tl(s->T0, s->T0, s->T1);
1646 break;
1649 /* store */
1650 gen_op_st_rm_T0_A0(s, ot, op1);
1652 /* We'll need the flags computed into CC_SRC. */
1653 gen_compute_eflags(s);
1655 /* The value that was "rotated out" is now present at the other end
1656 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1657 since we've computed the flags into CC_SRC, these variables are
1658 currently dead. */
1659 if (is_right) {
1660 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1661 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1662 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1663 } else {
1664 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1665 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1667 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1668 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1670 /* Now conditionally store the new CC_OP value. If the shift count
1671 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1672 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1673 exactly as we computed above. */
1674 t0 = tcg_const_i32(0);
1675 t1 = tcg_temp_new_i32();
1676 tcg_gen_trunc_tl_i32(t1, s->T1);
1677 tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX);
1678 tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS);
1679 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1680 s->tmp2_i32, s->tmp3_i32);
1681 tcg_temp_free_i32(t0);
1682 tcg_temp_free_i32(t1);
1684 /* The CC_OP value is no longer predictable. */
1685 set_cc_op(s, CC_OP_DYNAMIC);
1688 static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1689 int is_right)
1691 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1692 int shift;
1694 /* load */
1695 if (op1 == OR_TMP0) {
1696 gen_op_ld_v(s, ot, s->T0, s->A0);
1697 } else {
1698 gen_op_mov_v_reg(s, ot, s->T0, op1);
1701 op2 &= mask;
1702 if (op2 != 0) {
1703 switch (ot) {
1704 #ifdef TARGET_X86_64
1705 case MO_32:
1706 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1707 if (is_right) {
1708 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2);
1709 } else {
1710 tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2);
1712 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1713 break;
1714 #endif
1715 default:
1716 if (is_right) {
1717 tcg_gen_rotri_tl(s->T0, s->T0, op2);
1718 } else {
1719 tcg_gen_rotli_tl(s->T0, s->T0, op2);
1721 break;
1722 case MO_8:
1723 mask = 7;
1724 goto do_shifts;
1725 case MO_16:
1726 mask = 15;
1727 do_shifts:
1728 shift = op2 & mask;
1729 if (is_right) {
1730 shift = mask + 1 - shift;
1732 gen_extu(ot, s->T0);
1733 tcg_gen_shli_tl(s->tmp0, s->T0, shift);
1734 tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift);
1735 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
1736 break;
1740 /* store */
1741 gen_op_st_rm_T0_A0(s, ot, op1);
1743 if (op2 != 0) {
1744 /* Compute the flags into CC_SRC. */
1745 gen_compute_eflags(s);
1747 /* The value that was "rotated out" is now present at the other end
1748 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1749 since we've computed the flags into CC_SRC, these variables are
1750 currently dead. */
1751 if (is_right) {
1752 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1753 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1754 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1755 } else {
1756 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1757 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1759 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1760 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1761 set_cc_op(s, CC_OP_ADCOX);
1765 /* XXX: add faster immediate = 1 case */
1766 static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
1767 int is_right)
1769 gen_compute_eflags(s);
1770 assert(s->cc_op == CC_OP_EFLAGS);
1772 /* load */
1773 if (op1 == OR_TMP0)
1774 gen_op_ld_v(s, ot, s->T0, s->A0);
1775 else
1776 gen_op_mov_v_reg(s, ot, s->T0, op1);
1778 if (is_right) {
1779 switch (ot) {
1780 case MO_8:
1781 gen_helper_rcrb(s->T0, cpu_env, s->T0, s->T1);
1782 break;
1783 case MO_16:
1784 gen_helper_rcrw(s->T0, cpu_env, s->T0, s->T1);
1785 break;
1786 case MO_32:
1787 gen_helper_rcrl(s->T0, cpu_env, s->T0, s->T1);
1788 break;
1789 #ifdef TARGET_X86_64
1790 case MO_64:
1791 gen_helper_rcrq(s->T0, cpu_env, s->T0, s->T1);
1792 break;
1793 #endif
1794 default:
1795 tcg_abort();
1797 } else {
1798 switch (ot) {
1799 case MO_8:
1800 gen_helper_rclb(s->T0, cpu_env, s->T0, s->T1);
1801 break;
1802 case MO_16:
1803 gen_helper_rclw(s->T0, cpu_env, s->T0, s->T1);
1804 break;
1805 case MO_32:
1806 gen_helper_rcll(s->T0, cpu_env, s->T0, s->T1);
1807 break;
1808 #ifdef TARGET_X86_64
1809 case MO_64:
1810 gen_helper_rclq(s->T0, cpu_env, s->T0, s->T1);
1811 break;
1812 #endif
1813 default:
1814 tcg_abort();
1817 /* store */
1818 gen_op_st_rm_T0_A0(s, ot, op1);
1821 /* XXX: add faster immediate case */
1822 static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
1823 bool is_right, TCGv count_in)
1825 target_ulong mask = (ot == MO_64 ? 63 : 31);
1826 TCGv count;
1828 /* load */
1829 if (op1 == OR_TMP0) {
1830 gen_op_ld_v(s, ot, s->T0, s->A0);
1831 } else {
1832 gen_op_mov_v_reg(s, ot, s->T0, op1);
1835 count = tcg_temp_new();
1836 tcg_gen_andi_tl(count, count_in, mask);
1838 switch (ot) {
1839 case MO_16:
1840 /* Note: we implement the Intel behaviour for shift count > 16.
1841 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1842 portion by constructing it as a 32-bit value. */
1843 if (is_right) {
1844 tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16);
1845 tcg_gen_mov_tl(s->T1, s->T0);
1846 tcg_gen_mov_tl(s->T0, s->tmp0);
1847 } else {
1848 tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
1851 * If TARGET_X86_64 defined then fall through into MO_32 case,
1852 * otherwise fall through default case.
1854 case MO_32:
1855 #ifdef TARGET_X86_64
1856 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1857 tcg_gen_subi_tl(s->tmp0, count, 1);
1858 if (is_right) {
1859 tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1);
1860 tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0);
1861 tcg_gen_shr_i64(s->T0, s->T0, count);
1862 } else {
1863 tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0);
1864 tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0);
1865 tcg_gen_shl_i64(s->T0, s->T0, count);
1866 tcg_gen_shri_i64(s->tmp0, s->tmp0, 32);
1867 tcg_gen_shri_i64(s->T0, s->T0, 32);
1869 break;
1870 #endif
1871 default:
1872 tcg_gen_subi_tl(s->tmp0, count, 1);
1873 if (is_right) {
1874 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1876 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1877 tcg_gen_shr_tl(s->T0, s->T0, count);
1878 tcg_gen_shl_tl(s->T1, s->T1, s->tmp4);
1879 } else {
1880 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1881 if (ot == MO_16) {
1882 /* Only needed if count > 16, for Intel behaviour. */
1883 tcg_gen_subfi_tl(s->tmp4, 33, count);
1884 tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4);
1885 tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4);
1888 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1889 tcg_gen_shl_tl(s->T0, s->T0, count);
1890 tcg_gen_shr_tl(s->T1, s->T1, s->tmp4);
1892 tcg_gen_movi_tl(s->tmp4, 0);
1893 tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4,
1894 s->tmp4, s->T1);
1895 tcg_gen_or_tl(s->T0, s->T0, s->T1);
1896 break;
1899 /* store */
1900 gen_op_st_rm_T0_A0(s, ot, op1);
1902 gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
1903 tcg_temp_free(count);
1906 static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s)
1908 if (s != OR_TMP1)
1909 gen_op_mov_v_reg(s1, ot, s1->T1, s);
1910 switch(op) {
1911 case OP_ROL:
1912 gen_rot_rm_T1(s1, ot, d, 0);
1913 break;
1914 case OP_ROR:
1915 gen_rot_rm_T1(s1, ot, d, 1);
1916 break;
1917 case OP_SHL:
1918 case OP_SHL1:
1919 gen_shift_rm_T1(s1, ot, d, 0, 0);
1920 break;
1921 case OP_SHR:
1922 gen_shift_rm_T1(s1, ot, d, 1, 0);
1923 break;
1924 case OP_SAR:
1925 gen_shift_rm_T1(s1, ot, d, 1, 1);
1926 break;
1927 case OP_RCL:
1928 gen_rotc_rm_T1(s1, ot, d, 0);
1929 break;
1930 case OP_RCR:
1931 gen_rotc_rm_T1(s1, ot, d, 1);
1932 break;
1936 static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c)
1938 switch(op) {
1939 case OP_ROL:
1940 gen_rot_rm_im(s1, ot, d, c, 0);
1941 break;
1942 case OP_ROR:
1943 gen_rot_rm_im(s1, ot, d, c, 1);
1944 break;
1945 case OP_SHL:
1946 case OP_SHL1:
1947 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1948 break;
1949 case OP_SHR:
1950 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1951 break;
1952 case OP_SAR:
1953 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1954 break;
1955 default:
1956 /* currently not optimized */
1957 tcg_gen_movi_tl(s1->T1, c);
1958 gen_shift(s1, op, ot, d, OR_TMP1);
1959 break;
1963 #define X86_MAX_INSN_LENGTH 15
1965 static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
1967 uint64_t pc = s->pc;
1969 s->pc += num_bytes;
1970 if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
1971 /* If the instruction's 16th byte is on a different page than the 1st, a
1972 * page fault on the second page wins over the general protection fault
1973 * caused by the instruction being too long.
1974 * This can happen even if the operand is only one byte long!
1976 if (((s->pc - 1) ^ (pc - 1)) & TARGET_PAGE_MASK) {
1977 volatile uint8_t unused =
1978 cpu_ldub_code(env, (s->pc - 1) & TARGET_PAGE_MASK);
1979 (void) unused;
1981 siglongjmp(s->jmpbuf, 1);
1984 return pc;
1987 static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
1989 return translator_ldub(env, advance_pc(env, s, 1));
1992 static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
1994 return translator_ldsw(env, advance_pc(env, s, 2));
1997 static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
1999 return translator_lduw(env, advance_pc(env, s, 2));
2002 static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
2004 return translator_ldl(env, advance_pc(env, s, 4));
2007 #ifdef TARGET_X86_64
2008 static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
2010 return translator_ldq(env, advance_pc(env, s, 8));
2012 #endif
2014 /* Decompose an address. */
2016 typedef struct AddressParts {
2017 int def_seg;
2018 int base;
2019 int index;
2020 int scale;
2021 target_long disp;
2022 } AddressParts;
2024 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
2025 int modrm)
2027 int def_seg, base, index, scale, mod, rm;
2028 target_long disp;
2029 bool havesib;
2031 def_seg = R_DS;
2032 index = -1;
2033 scale = 0;
2034 disp = 0;
2036 mod = (modrm >> 6) & 3;
2037 rm = modrm & 7;
2038 base = rm | REX_B(s);
2040 if (mod == 3) {
2041 /* Normally filtered out earlier, but including this path
2042 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
2043 goto done;
2046 switch (s->aflag) {
2047 case MO_64:
2048 case MO_32:
2049 havesib = 0;
2050 if (rm == 4) {
2051 int code = x86_ldub_code(env, s);
2052 scale = (code >> 6) & 3;
2053 index = ((code >> 3) & 7) | REX_X(s);
2054 if (index == 4) {
2055 index = -1; /* no index */
2057 base = (code & 7) | REX_B(s);
2058 havesib = 1;
2061 switch (mod) {
2062 case 0:
2063 if ((base & 7) == 5) {
2064 base = -1;
2065 disp = (int32_t)x86_ldl_code(env, s);
2066 if (CODE64(s) && !havesib) {
2067 base = -2;
2068 disp += s->pc + s->rip_offset;
2071 break;
2072 case 1:
2073 disp = (int8_t)x86_ldub_code(env, s);
2074 break;
2075 default:
2076 case 2:
2077 disp = (int32_t)x86_ldl_code(env, s);
2078 break;
2081 /* For correct popl handling with esp. */
2082 if (base == R_ESP && s->popl_esp_hack) {
2083 disp += s->popl_esp_hack;
2085 if (base == R_EBP || base == R_ESP) {
2086 def_seg = R_SS;
2088 break;
2090 case MO_16:
2091 if (mod == 0) {
2092 if (rm == 6) {
2093 base = -1;
2094 disp = x86_lduw_code(env, s);
2095 break;
2097 } else if (mod == 1) {
2098 disp = (int8_t)x86_ldub_code(env, s);
2099 } else {
2100 disp = (int16_t)x86_lduw_code(env, s);
2103 switch (rm) {
2104 case 0:
2105 base = R_EBX;
2106 index = R_ESI;
2107 break;
2108 case 1:
2109 base = R_EBX;
2110 index = R_EDI;
2111 break;
2112 case 2:
2113 base = R_EBP;
2114 index = R_ESI;
2115 def_seg = R_SS;
2116 break;
2117 case 3:
2118 base = R_EBP;
2119 index = R_EDI;
2120 def_seg = R_SS;
2121 break;
2122 case 4:
2123 base = R_ESI;
2124 break;
2125 case 5:
2126 base = R_EDI;
2127 break;
2128 case 6:
2129 base = R_EBP;
2130 def_seg = R_SS;
2131 break;
2132 default:
2133 case 7:
2134 base = R_EBX;
2135 break;
2137 break;
2139 default:
2140 tcg_abort();
2143 done:
2144 return (AddressParts){ def_seg, base, index, scale, disp };
2147 /* Compute the address, with a minimum number of TCG ops. */
2148 static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a)
2150 TCGv ea = NULL;
2152 if (a.index >= 0) {
2153 if (a.scale == 0) {
2154 ea = cpu_regs[a.index];
2155 } else {
2156 tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale);
2157 ea = s->A0;
2159 if (a.base >= 0) {
2160 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2161 ea = s->A0;
2163 } else if (a.base >= 0) {
2164 ea = cpu_regs[a.base];
2166 if (!ea) {
2167 tcg_gen_movi_tl(s->A0, a.disp);
2168 ea = s->A0;
2169 } else if (a.disp != 0) {
2170 tcg_gen_addi_tl(s->A0, ea, a.disp);
2171 ea = s->A0;
2174 return ea;
2177 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2179 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2180 TCGv ea = gen_lea_modrm_1(s, a);
2181 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2184 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2186 (void)gen_lea_modrm_0(env, s, modrm);
2189 /* Used for BNDCL, BNDCU, BNDCN. */
2190 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2191 TCGCond cond, TCGv_i64 bndv)
2193 TCGv ea = gen_lea_modrm_1(s, gen_lea_modrm_0(env, s, modrm));
2195 tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
2196 if (!CODE64(s)) {
2197 tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64);
2199 tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv);
2200 tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64);
2201 gen_helper_bndck(cpu_env, s->tmp2_i32);
2204 /* used for LEA and MOV AX, mem */
2205 static void gen_add_A0_ds_seg(DisasContext *s)
2207 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
2210 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2211 OR_TMP0 */
2212 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2213 MemOp ot, int reg, int is_store)
2215 int mod, rm;
2217 mod = (modrm >> 6) & 3;
2218 rm = (modrm & 7) | REX_B(s);
2219 if (mod == 3) {
2220 if (is_store) {
2221 if (reg != OR_TMP0)
2222 gen_op_mov_v_reg(s, ot, s->T0, reg);
2223 gen_op_mov_reg_v(s, ot, rm, s->T0);
2224 } else {
2225 gen_op_mov_v_reg(s, ot, s->T0, rm);
2226 if (reg != OR_TMP0)
2227 gen_op_mov_reg_v(s, ot, reg, s->T0);
2229 } else {
2230 gen_lea_modrm(env, s, modrm);
2231 if (is_store) {
2232 if (reg != OR_TMP0)
2233 gen_op_mov_v_reg(s, ot, s->T0, reg);
2234 gen_op_st_v(s, ot, s->T0, s->A0);
2235 } else {
2236 gen_op_ld_v(s, ot, s->T0, s->A0);
2237 if (reg != OR_TMP0)
2238 gen_op_mov_reg_v(s, ot, reg, s->T0);
2243 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
2245 uint32_t ret;
2247 switch (ot) {
2248 case MO_8:
2249 ret = x86_ldub_code(env, s);
2250 break;
2251 case MO_16:
2252 ret = x86_lduw_code(env, s);
2253 break;
2254 case MO_32:
2255 #ifdef TARGET_X86_64
2256 case MO_64:
2257 #endif
2258 ret = x86_ldl_code(env, s);
2259 break;
2260 default:
2261 tcg_abort();
2263 return ret;
2266 static inline int insn_const_size(MemOp ot)
2268 if (ot <= MO_32) {
2269 return 1 << ot;
2270 } else {
2271 return 4;
2275 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2277 #ifndef CONFIG_USER_ONLY
2278 return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
2279 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2280 #else
2281 return true;
2282 #endif
2285 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2287 target_ulong pc = s->cs_base + eip;
2289 if (use_goto_tb(s, pc)) {
2290 /* jump to same page: we can use a direct jump */
2291 tcg_gen_goto_tb(tb_num);
2292 gen_jmp_im(s, eip);
2293 tcg_gen_exit_tb(s->base.tb, tb_num);
2294 s->base.is_jmp = DISAS_NORETURN;
2295 } else {
2296 /* jump to another page */
2297 gen_jmp_im(s, eip);
2298 gen_jr(s, s->tmp0);
2302 static inline void gen_jcc(DisasContext *s, int b,
2303 target_ulong val, target_ulong next_eip)
2305 TCGLabel *l1, *l2;
2307 if (s->jmp_opt) {
2308 l1 = gen_new_label();
2309 gen_jcc1(s, b, l1);
2311 gen_goto_tb(s, 0, next_eip);
2313 gen_set_label(l1);
2314 gen_goto_tb(s, 1, val);
2315 } else {
2316 l1 = gen_new_label();
2317 l2 = gen_new_label();
2318 gen_jcc1(s, b, l1);
2320 gen_jmp_im(s, next_eip);
2321 tcg_gen_br(l2);
2323 gen_set_label(l1);
2324 gen_jmp_im(s, val);
2325 gen_set_label(l2);
2326 gen_eob(s);
2330 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
2331 int modrm, int reg)
2333 CCPrepare cc;
2335 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2337 cc = gen_prepare_cc(s, b, s->T1);
2338 if (cc.mask != -1) {
2339 TCGv t0 = tcg_temp_new();
2340 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2341 cc.reg = t0;
2343 if (!cc.use_reg2) {
2344 cc.reg2 = tcg_const_tl(cc.imm);
2347 tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2,
2348 s->T0, cpu_regs[reg]);
2349 gen_op_mov_reg_v(s, ot, reg, s->T0);
2351 if (cc.mask != -1) {
2352 tcg_temp_free(cc.reg);
2354 if (!cc.use_reg2) {
2355 tcg_temp_free(cc.reg2);
2359 static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg)
2361 tcg_gen_ld32u_tl(s->T0, cpu_env,
2362 offsetof(CPUX86State,segs[seg_reg].selector));
2365 static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg)
2367 tcg_gen_ext16u_tl(s->T0, s->T0);
2368 tcg_gen_st32_tl(s->T0, cpu_env,
2369 offsetof(CPUX86State,segs[seg_reg].selector));
2370 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
2373 /* move T0 to seg_reg and compute if the CPU state may change. Never
2374 call this function with seg_reg == R_CS */
2375 static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg)
2377 if (PE(s) && !VM86(s)) {
2378 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
2379 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), s->tmp2_i32);
2380 /* abort translation because the addseg value may change or
2381 because ss32 may change. For R_SS, translation must always
2382 stop as a special handling must be done to disable hardware
2383 interrupts for the next instruction */
2384 if (seg_reg == R_SS || (CODE32(s) && seg_reg < R_FS)) {
2385 s->base.is_jmp = DISAS_TOO_MANY;
2387 } else {
2388 gen_op_movl_seg_T0_vm(s, seg_reg);
2389 if (seg_reg == R_SS) {
2390 s->base.is_jmp = DISAS_TOO_MANY;
2395 static inline int svm_is_rep(int prefixes)
2397 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2400 static inline void
2401 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2402 uint32_t type, uint64_t param)
2404 /* no SVM activated; fast case */
2405 if (likely(!(s->flags & HF_GUEST_MASK)))
2406 return;
2407 gen_update_cc_op(s);
2408 gen_jmp_im(s, pc_start - s->cs_base);
2409 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2410 tcg_const_i64(param));
2413 static inline void
2414 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2416 gen_svm_check_intercept_param(s, pc_start, type, 0);
2419 static inline void gen_stack_update(DisasContext *s, int addend)
2421 gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend);
2424 /* Generate a push. It depends on ss32, addseg and dflag. */
2425 static void gen_push_v(DisasContext *s, TCGv val)
2427 MemOp d_ot = mo_pushpop(s, s->dflag);
2428 MemOp a_ot = mo_stacksize(s);
2429 int size = 1 << d_ot;
2430 TCGv new_esp = s->A0;
2432 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2434 if (!CODE64(s)) {
2435 if (ADDSEG(s)) {
2436 new_esp = s->tmp4;
2437 tcg_gen_mov_tl(new_esp, s->A0);
2439 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2442 gen_op_st_v(s, d_ot, val, s->A0);
2443 gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp);
2446 /* two step pop is necessary for precise exceptions */
2447 static MemOp gen_pop_T0(DisasContext *s)
2449 MemOp d_ot = mo_pushpop(s, s->dflag);
2451 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2452 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2454 return d_ot;
2457 static inline void gen_pop_update(DisasContext *s, MemOp ot)
2459 gen_stack_update(s, 1 << ot);
2462 static inline void gen_stack_A0(DisasContext *s)
2464 gen_lea_v_seg(s, SS32(s) ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2467 static void gen_pusha(DisasContext *s)
2469 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2470 MemOp d_ot = s->dflag;
2471 int size = 1 << d_ot;
2472 int i;
2474 for (i = 0; i < 8; i++) {
2475 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size);
2476 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2477 gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0);
2480 gen_stack_update(s, -8 * size);
2483 static void gen_popa(DisasContext *s)
2485 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2486 MemOp d_ot = s->dflag;
2487 int size = 1 << d_ot;
2488 int i;
2490 for (i = 0; i < 8; i++) {
2491 /* ESP is not reloaded */
2492 if (7 - i == R_ESP) {
2493 continue;
2495 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size);
2496 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2497 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2498 gen_op_mov_reg_v(s, d_ot, 7 - i, s->T0);
2501 gen_stack_update(s, 8 * size);
2504 static void gen_enter(DisasContext *s, int esp_addend, int level)
2506 MemOp d_ot = mo_pushpop(s, s->dflag);
2507 MemOp a_ot = CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
2508 int size = 1 << d_ot;
2510 /* Push BP; compute FrameTemp into T1. */
2511 tcg_gen_subi_tl(s->T1, cpu_regs[R_ESP], size);
2512 gen_lea_v_seg(s, a_ot, s->T1, R_SS, -1);
2513 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0);
2515 level &= 31;
2516 if (level != 0) {
2517 int i;
2519 /* Copy level-1 pointers from the previous frame. */
2520 for (i = 1; i < level; ++i) {
2521 tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i);
2522 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2523 gen_op_ld_v(s, d_ot, s->tmp0, s->A0);
2525 tcg_gen_subi_tl(s->A0, s->T1, size * i);
2526 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2527 gen_op_st_v(s, d_ot, s->tmp0, s->A0);
2530 /* Push the current FrameTemp as the last level. */
2531 tcg_gen_subi_tl(s->A0, s->T1, size * level);
2532 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2533 gen_op_st_v(s, d_ot, s->T1, s->A0);
2536 /* Copy the FrameTemp value to EBP. */
2537 gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
2539 /* Compute the final value of ESP. */
2540 tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
2541 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2544 static void gen_leave(DisasContext *s)
2546 MemOp d_ot = mo_pushpop(s, s->dflag);
2547 MemOp a_ot = mo_stacksize(s);
2549 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2550 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2552 tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot);
2554 gen_op_mov_reg_v(s, d_ot, R_EBP, s->T0);
2555 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2558 /* Similarly, except that the assumption here is that we don't decode
2559 the instruction at all -- either a missing opcode, an unimplemented
2560 feature, or just a bogus instruction stream. */
2561 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2563 gen_illegal_opcode(s);
2565 if (qemu_loglevel_mask(LOG_UNIMP)) {
2566 FILE *logfile = qemu_log_lock();
2567 target_ulong pc = s->pc_start, end = s->pc;
2569 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2570 for (; pc < end; ++pc) {
2571 qemu_log(" %02x", cpu_ldub_code(env, pc));
2573 qemu_log("\n");
2574 qemu_log_unlock(logfile);
2578 /* an interrupt is different from an exception because of the
2579 privilege checks */
2580 static void gen_interrupt(DisasContext *s, int intno,
2581 target_ulong cur_eip, target_ulong next_eip)
2583 gen_update_cc_op(s);
2584 gen_jmp_im(s, cur_eip);
2585 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2586 tcg_const_i32(next_eip - cur_eip));
2587 s->base.is_jmp = DISAS_NORETURN;
2590 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2592 gen_update_cc_op(s);
2593 gen_jmp_im(s, cur_eip);
2594 gen_helper_debug(cpu_env);
2595 s->base.is_jmp = DISAS_NORETURN;
2598 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2600 if ((s->flags & mask) == 0) {
2601 TCGv_i32 t = tcg_temp_new_i32();
2602 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2603 tcg_gen_ori_i32(t, t, mask);
2604 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2605 tcg_temp_free_i32(t);
2606 s->flags |= mask;
2610 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2612 if (s->flags & mask) {
2613 TCGv_i32 t = tcg_temp_new_i32();
2614 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2615 tcg_gen_andi_i32(t, t, ~mask);
2616 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2617 tcg_temp_free_i32(t);
2618 s->flags &= ~mask;
2622 /* Clear BND registers during legacy branches. */
2623 static void gen_bnd_jmp(DisasContext *s)
2625 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2626 and if the BNDREGs are known to be in use (non-zero) already.
2627 The helper itself will check BNDPRESERVE at runtime. */
2628 if ((s->prefix & PREFIX_REPNZ) == 0
2629 && (s->flags & HF_MPX_EN_MASK) != 0
2630 && (s->flags & HF_MPX_IU_MASK) != 0) {
2631 gen_helper_bnd_jmp(cpu_env);
2635 /* Generate an end of block. Trace exception is also generated if needed.
2636 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.
2637 If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
2638 S->TF. This is used by the syscall/sysret insns. */
2639 static void
2640 do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2642 gen_update_cc_op(s);
2644 /* If several instructions disable interrupts, only the first does it. */
2645 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2646 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2647 } else {
2648 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2651 if (s->base.tb->flags & HF_RF_MASK) {
2652 gen_helper_reset_rf(cpu_env);
2654 if (s->base.singlestep_enabled) {
2655 gen_helper_debug(cpu_env);
2656 } else if (recheck_tf) {
2657 gen_helper_rechecking_single_step(cpu_env);
2658 tcg_gen_exit_tb(NULL, 0);
2659 } else if (s->tf) {
2660 gen_helper_single_step(cpu_env);
2661 } else if (jr) {
2662 tcg_gen_lookup_and_goto_ptr();
2663 } else {
2664 tcg_gen_exit_tb(NULL, 0);
2666 s->base.is_jmp = DISAS_NORETURN;
2669 static inline void
2670 gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2672 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2675 /* End of block.
2676 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2677 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2679 gen_eob_worker(s, inhibit, false);
2682 /* End of block, resetting the inhibit irq flag. */
2683 static void gen_eob(DisasContext *s)
2685 gen_eob_worker(s, false, false);
2688 /* Jump to register */
2689 static void gen_jr(DisasContext *s, TCGv dest)
2691 do_gen_eob_worker(s, false, false, true);
2694 /* generate a jump to eip. No segment change must happen before as a
2695 direct call to the next block may occur */
2696 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2698 gen_update_cc_op(s);
2699 set_cc_op(s, CC_OP_DYNAMIC);
2700 if (s->jmp_opt) {
2701 gen_goto_tb(s, tb_num, eip);
2702 } else {
2703 gen_jmp_im(s, eip);
2704 gen_eob(s);
2708 static void gen_jmp(DisasContext *s, target_ulong eip)
2710 gen_jmp_tb(s, eip, 0);
2713 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2715 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2716 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset);
2719 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2721 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset);
2722 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2725 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2727 int mem_index = s->mem_index;
2728 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2729 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2730 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2731 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2732 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2735 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2737 int mem_index = s->mem_index;
2738 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2739 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2740 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2741 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2742 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2745 static inline void gen_op_movo(DisasContext *s, int d_offset, int s_offset)
2747 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2748 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2749 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2750 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2753 static inline void gen_op_movq(DisasContext *s, int d_offset, int s_offset)
2755 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset);
2756 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2759 static inline void gen_op_movl(DisasContext *s, int d_offset, int s_offset)
2761 tcg_gen_ld_i32(s->tmp2_i32, cpu_env, s_offset);
2762 tcg_gen_st_i32(s->tmp2_i32, cpu_env, d_offset);
2765 static inline void gen_op_movq_env_0(DisasContext *s, int d_offset)
2767 tcg_gen_movi_i64(s->tmp1_i64, 0);
2768 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2771 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2772 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2773 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2774 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2775 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2776 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2777 TCGv_i32 val);
2778 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2779 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2780 TCGv val);
2782 #define SSE_SPECIAL ((void *)1)
2783 #define SSE_DUMMY ((void *)2)
2785 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2786 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2787 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2789 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2790 /* 3DNow! extensions */
2791 [0x0e] = { SSE_DUMMY }, /* femms */
2792 [0x0f] = { SSE_DUMMY }, /* pf... */
2793 /* pure SSE operations */
2794 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2795 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2796 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2797 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2798 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2799 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2800 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2801 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2803 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2804 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2805 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2806 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2807 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2808 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2809 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2810 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2811 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2812 [0x51] = SSE_FOP(sqrt),
2813 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2814 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2815 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2816 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2817 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2818 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2819 [0x58] = SSE_FOP(add),
2820 [0x59] = SSE_FOP(mul),
2821 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2822 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2823 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2824 [0x5c] = SSE_FOP(sub),
2825 [0x5d] = SSE_FOP(min),
2826 [0x5e] = SSE_FOP(div),
2827 [0x5f] = SSE_FOP(max),
2829 [0xc2] = SSE_FOP(cmpeq),
2830 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2831 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2833 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2834 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2835 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2837 /* MMX ops and their SSE extensions */
2838 [0x60] = MMX_OP2(punpcklbw),
2839 [0x61] = MMX_OP2(punpcklwd),
2840 [0x62] = MMX_OP2(punpckldq),
2841 [0x63] = MMX_OP2(packsswb),
2842 [0x64] = MMX_OP2(pcmpgtb),
2843 [0x65] = MMX_OP2(pcmpgtw),
2844 [0x66] = MMX_OP2(pcmpgtl),
2845 [0x67] = MMX_OP2(packuswb),
2846 [0x68] = MMX_OP2(punpckhbw),
2847 [0x69] = MMX_OP2(punpckhwd),
2848 [0x6a] = MMX_OP2(punpckhdq),
2849 [0x6b] = MMX_OP2(packssdw),
2850 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2851 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2852 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2853 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2854 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2855 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2856 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2857 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2858 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2859 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2860 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2861 [0x74] = MMX_OP2(pcmpeqb),
2862 [0x75] = MMX_OP2(pcmpeqw),
2863 [0x76] = MMX_OP2(pcmpeql),
2864 [0x77] = { SSE_DUMMY }, /* emms */
2865 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2866 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2867 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2868 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2869 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2870 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2871 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2872 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2873 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2874 [0xd1] = MMX_OP2(psrlw),
2875 [0xd2] = MMX_OP2(psrld),
2876 [0xd3] = MMX_OP2(psrlq),
2877 [0xd4] = MMX_OP2(paddq),
2878 [0xd5] = MMX_OP2(pmullw),
2879 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2880 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2881 [0xd8] = MMX_OP2(psubusb),
2882 [0xd9] = MMX_OP2(psubusw),
2883 [0xda] = MMX_OP2(pminub),
2884 [0xdb] = MMX_OP2(pand),
2885 [0xdc] = MMX_OP2(paddusb),
2886 [0xdd] = MMX_OP2(paddusw),
2887 [0xde] = MMX_OP2(pmaxub),
2888 [0xdf] = MMX_OP2(pandn),
2889 [0xe0] = MMX_OP2(pavgb),
2890 [0xe1] = MMX_OP2(psraw),
2891 [0xe2] = MMX_OP2(psrad),
2892 [0xe3] = MMX_OP2(pavgw),
2893 [0xe4] = MMX_OP2(pmulhuw),
2894 [0xe5] = MMX_OP2(pmulhw),
2895 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2896 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2897 [0xe8] = MMX_OP2(psubsb),
2898 [0xe9] = MMX_OP2(psubsw),
2899 [0xea] = MMX_OP2(pminsw),
2900 [0xeb] = MMX_OP2(por),
2901 [0xec] = MMX_OP2(paddsb),
2902 [0xed] = MMX_OP2(paddsw),
2903 [0xee] = MMX_OP2(pmaxsw),
2904 [0xef] = MMX_OP2(pxor),
2905 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2906 [0xf1] = MMX_OP2(psllw),
2907 [0xf2] = MMX_OP2(pslld),
2908 [0xf3] = MMX_OP2(psllq),
2909 [0xf4] = MMX_OP2(pmuludq),
2910 [0xf5] = MMX_OP2(pmaddwd),
2911 [0xf6] = MMX_OP2(psadbw),
2912 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2913 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2914 [0xf8] = MMX_OP2(psubb),
2915 [0xf9] = MMX_OP2(psubw),
2916 [0xfa] = MMX_OP2(psubl),
2917 [0xfb] = MMX_OP2(psubq),
2918 [0xfc] = MMX_OP2(paddb),
2919 [0xfd] = MMX_OP2(paddw),
2920 [0xfe] = MMX_OP2(paddl),
2923 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2924 [0 + 2] = MMX_OP2(psrlw),
2925 [0 + 4] = MMX_OP2(psraw),
2926 [0 + 6] = MMX_OP2(psllw),
2927 [8 + 2] = MMX_OP2(psrld),
2928 [8 + 4] = MMX_OP2(psrad),
2929 [8 + 6] = MMX_OP2(pslld),
2930 [16 + 2] = MMX_OP2(psrlq),
2931 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2932 [16 + 6] = MMX_OP2(psllq),
2933 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2936 static const SSEFunc_0_epi sse_op_table3ai[] = {
2937 gen_helper_cvtsi2ss,
2938 gen_helper_cvtsi2sd
2941 #ifdef TARGET_X86_64
2942 static const SSEFunc_0_epl sse_op_table3aq[] = {
2943 gen_helper_cvtsq2ss,
2944 gen_helper_cvtsq2sd
2946 #endif
2948 static const SSEFunc_i_ep sse_op_table3bi[] = {
2949 gen_helper_cvttss2si,
2950 gen_helper_cvtss2si,
2951 gen_helper_cvttsd2si,
2952 gen_helper_cvtsd2si
2955 #ifdef TARGET_X86_64
2956 static const SSEFunc_l_ep sse_op_table3bq[] = {
2957 gen_helper_cvttss2sq,
2958 gen_helper_cvtss2sq,
2959 gen_helper_cvttsd2sq,
2960 gen_helper_cvtsd2sq
2962 #endif
2964 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2965 SSE_FOP(cmpeq),
2966 SSE_FOP(cmplt),
2967 SSE_FOP(cmple),
2968 SSE_FOP(cmpunord),
2969 SSE_FOP(cmpneq),
2970 SSE_FOP(cmpnlt),
2971 SSE_FOP(cmpnle),
2972 SSE_FOP(cmpord),
2975 static const SSEFunc_0_epp sse_op_table5[256] = {
2976 [0x0c] = gen_helper_pi2fw,
2977 [0x0d] = gen_helper_pi2fd,
2978 [0x1c] = gen_helper_pf2iw,
2979 [0x1d] = gen_helper_pf2id,
2980 [0x8a] = gen_helper_pfnacc,
2981 [0x8e] = gen_helper_pfpnacc,
2982 [0x90] = gen_helper_pfcmpge,
2983 [0x94] = gen_helper_pfmin,
2984 [0x96] = gen_helper_pfrcp,
2985 [0x97] = gen_helper_pfrsqrt,
2986 [0x9a] = gen_helper_pfsub,
2987 [0x9e] = gen_helper_pfadd,
2988 [0xa0] = gen_helper_pfcmpgt,
2989 [0xa4] = gen_helper_pfmax,
2990 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2991 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2992 [0xaa] = gen_helper_pfsubr,
2993 [0xae] = gen_helper_pfacc,
2994 [0xb0] = gen_helper_pfcmpeq,
2995 [0xb4] = gen_helper_pfmul,
2996 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2997 [0xb7] = gen_helper_pmulhrw_mmx,
2998 [0xbb] = gen_helper_pswapd,
2999 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
3002 struct SSEOpHelper_epp {
3003 SSEFunc_0_epp op[2];
3004 uint32_t ext_mask;
3007 struct SSEOpHelper_eppi {
3008 SSEFunc_0_eppi op[2];
3009 uint32_t ext_mask;
3012 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
3013 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
3014 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
3015 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
3016 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
3017 CPUID_EXT_PCLMULQDQ }
3018 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
3020 static const struct SSEOpHelper_epp sse_op_table6[256] = {
3021 [0x00] = SSSE3_OP(pshufb),
3022 [0x01] = SSSE3_OP(phaddw),
3023 [0x02] = SSSE3_OP(phaddd),
3024 [0x03] = SSSE3_OP(phaddsw),
3025 [0x04] = SSSE3_OP(pmaddubsw),
3026 [0x05] = SSSE3_OP(phsubw),
3027 [0x06] = SSSE3_OP(phsubd),
3028 [0x07] = SSSE3_OP(phsubsw),
3029 [0x08] = SSSE3_OP(psignb),
3030 [0x09] = SSSE3_OP(psignw),
3031 [0x0a] = SSSE3_OP(psignd),
3032 [0x0b] = SSSE3_OP(pmulhrsw),
3033 [0x10] = SSE41_OP(pblendvb),
3034 [0x14] = SSE41_OP(blendvps),
3035 [0x15] = SSE41_OP(blendvpd),
3036 [0x17] = SSE41_OP(ptest),
3037 [0x1c] = SSSE3_OP(pabsb),
3038 [0x1d] = SSSE3_OP(pabsw),
3039 [0x1e] = SSSE3_OP(pabsd),
3040 [0x20] = SSE41_OP(pmovsxbw),
3041 [0x21] = SSE41_OP(pmovsxbd),
3042 [0x22] = SSE41_OP(pmovsxbq),
3043 [0x23] = SSE41_OP(pmovsxwd),
3044 [0x24] = SSE41_OP(pmovsxwq),
3045 [0x25] = SSE41_OP(pmovsxdq),
3046 [0x28] = SSE41_OP(pmuldq),
3047 [0x29] = SSE41_OP(pcmpeqq),
3048 [0x2a] = SSE41_SPECIAL, /* movntqda */
3049 [0x2b] = SSE41_OP(packusdw),
3050 [0x30] = SSE41_OP(pmovzxbw),
3051 [0x31] = SSE41_OP(pmovzxbd),
3052 [0x32] = SSE41_OP(pmovzxbq),
3053 [0x33] = SSE41_OP(pmovzxwd),
3054 [0x34] = SSE41_OP(pmovzxwq),
3055 [0x35] = SSE41_OP(pmovzxdq),
3056 [0x37] = SSE42_OP(pcmpgtq),
3057 [0x38] = SSE41_OP(pminsb),
3058 [0x39] = SSE41_OP(pminsd),
3059 [0x3a] = SSE41_OP(pminuw),
3060 [0x3b] = SSE41_OP(pminud),
3061 [0x3c] = SSE41_OP(pmaxsb),
3062 [0x3d] = SSE41_OP(pmaxsd),
3063 [0x3e] = SSE41_OP(pmaxuw),
3064 [0x3f] = SSE41_OP(pmaxud),
3065 [0x40] = SSE41_OP(pmulld),
3066 [0x41] = SSE41_OP(phminposuw),
3067 [0xdb] = AESNI_OP(aesimc),
3068 [0xdc] = AESNI_OP(aesenc),
3069 [0xdd] = AESNI_OP(aesenclast),
3070 [0xde] = AESNI_OP(aesdec),
3071 [0xdf] = AESNI_OP(aesdeclast),
3074 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
3075 [0x08] = SSE41_OP(roundps),
3076 [0x09] = SSE41_OP(roundpd),
3077 [0x0a] = SSE41_OP(roundss),
3078 [0x0b] = SSE41_OP(roundsd),
3079 [0x0c] = SSE41_OP(blendps),
3080 [0x0d] = SSE41_OP(blendpd),
3081 [0x0e] = SSE41_OP(pblendw),
3082 [0x0f] = SSSE3_OP(palignr),
3083 [0x14] = SSE41_SPECIAL, /* pextrb */
3084 [0x15] = SSE41_SPECIAL, /* pextrw */
3085 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3086 [0x17] = SSE41_SPECIAL, /* extractps */
3087 [0x20] = SSE41_SPECIAL, /* pinsrb */
3088 [0x21] = SSE41_SPECIAL, /* insertps */
3089 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3090 [0x40] = SSE41_OP(dpps),
3091 [0x41] = SSE41_OP(dppd),
3092 [0x42] = SSE41_OP(mpsadbw),
3093 [0x44] = PCLMULQDQ_OP(pclmulqdq),
3094 [0x60] = SSE42_OP(pcmpestrm),
3095 [0x61] = SSE42_OP(pcmpestri),
3096 [0x62] = SSE42_OP(pcmpistrm),
3097 [0x63] = SSE42_OP(pcmpistri),
3098 [0xdf] = AESNI_OP(aeskeygenassist),
3101 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3102 target_ulong pc_start)
3104 int b1, op1_offset, op2_offset, is_xmm, val;
3105 int modrm, mod, rm, reg;
3106 SSEFunc_0_epp sse_fn_epp;
3107 SSEFunc_0_eppi sse_fn_eppi;
3108 SSEFunc_0_ppi sse_fn_ppi;
3109 SSEFunc_0_eppt sse_fn_eppt;
3110 MemOp ot;
3112 b &= 0xff;
3113 if (s->prefix & PREFIX_DATA)
3114 b1 = 1;
3115 else if (s->prefix & PREFIX_REPZ)
3116 b1 = 2;
3117 else if (s->prefix & PREFIX_REPNZ)
3118 b1 = 3;
3119 else
3120 b1 = 0;
3121 sse_fn_epp = sse_op_table1[b][b1];
3122 if (!sse_fn_epp) {
3123 goto unknown_op;
3125 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3126 is_xmm = 1;
3127 } else {
3128 if (b1 == 0) {
3129 /* MMX case */
3130 is_xmm = 0;
3131 } else {
3132 is_xmm = 1;
3135 /* simple MMX/SSE operation */
3136 if (s->flags & HF_TS_MASK) {
3137 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3138 return;
3140 if (s->flags & HF_EM_MASK) {
3141 illegal_op:
3142 gen_illegal_opcode(s);
3143 return;
3145 if (is_xmm
3146 && !(s->flags & HF_OSFXSR_MASK)
3147 && (b != 0x38 && b != 0x3a)) {
3148 goto unknown_op;
3150 if (b == 0x0e) {
3151 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3152 /* If we were fully decoding this we might use illegal_op. */
3153 goto unknown_op;
3155 /* femms */
3156 gen_helper_emms(cpu_env);
3157 return;
3159 if (b == 0x77) {
3160 /* emms */
3161 gen_helper_emms(cpu_env);
3162 return;
3164 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3165 the static cpu state) */
3166 if (!is_xmm) {
3167 gen_helper_enter_mmx(cpu_env);
3170 modrm = x86_ldub_code(env, s);
3171 reg = ((modrm >> 3) & 7);
3172 if (is_xmm) {
3173 reg |= REX_R(s);
3175 mod = (modrm >> 6) & 3;
3176 if (sse_fn_epp == SSE_SPECIAL) {
3177 b |= (b1 << 8);
3178 switch(b) {
3179 case 0x0e7: /* movntq */
3180 if (mod == 3) {
3181 goto illegal_op;
3183 gen_lea_modrm(env, s, modrm);
3184 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3185 break;
3186 case 0x1e7: /* movntdq */
3187 case 0x02b: /* movntps */
3188 case 0x12b: /* movntps */
3189 if (mod == 3)
3190 goto illegal_op;
3191 gen_lea_modrm(env, s, modrm);
3192 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3193 break;
3194 case 0x3f0: /* lddqu */
3195 if (mod == 3)
3196 goto illegal_op;
3197 gen_lea_modrm(env, s, modrm);
3198 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3199 break;
3200 case 0x22b: /* movntss */
3201 case 0x32b: /* movntsd */
3202 if (mod == 3)
3203 goto illegal_op;
3204 gen_lea_modrm(env, s, modrm);
3205 if (b1 & 1) {
3206 gen_stq_env_A0(s, offsetof(CPUX86State,
3207 xmm_regs[reg].ZMM_Q(0)));
3208 } else {
3209 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
3210 xmm_regs[reg].ZMM_L(0)));
3211 gen_op_st_v(s, MO_32, s->T0, s->A0);
3213 break;
3214 case 0x6e: /* movd mm, ea */
3215 #ifdef TARGET_X86_64
3216 if (s->dflag == MO_64) {
3217 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3218 tcg_gen_st_tl(s->T0, cpu_env,
3219 offsetof(CPUX86State, fpregs[reg].mmx));
3220 } else
3221 #endif
3223 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3224 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3225 offsetof(CPUX86State,fpregs[reg].mmx));
3226 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3227 gen_helper_movl_mm_T0_mmx(s->ptr0, s->tmp2_i32);
3229 break;
3230 case 0x16e: /* movd xmm, ea */
3231 #ifdef TARGET_X86_64
3232 if (s->dflag == MO_64) {
3233 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3234 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3235 offsetof(CPUX86State,xmm_regs[reg]));
3236 gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0);
3237 } else
3238 #endif
3240 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3241 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3242 offsetof(CPUX86State,xmm_regs[reg]));
3243 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3244 gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32);
3246 break;
3247 case 0x6f: /* movq mm, ea */
3248 if (mod != 3) {
3249 gen_lea_modrm(env, s, modrm);
3250 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3251 } else {
3252 rm = (modrm & 7);
3253 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
3254 offsetof(CPUX86State,fpregs[rm].mmx));
3255 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
3256 offsetof(CPUX86State,fpregs[reg].mmx));
3258 break;
3259 case 0x010: /* movups */
3260 case 0x110: /* movupd */
3261 case 0x028: /* movaps */
3262 case 0x128: /* movapd */
3263 case 0x16f: /* movdqa xmm, ea */
3264 case 0x26f: /* movdqu xmm, ea */
3265 if (mod != 3) {
3266 gen_lea_modrm(env, s, modrm);
3267 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3268 } else {
3269 rm = (modrm & 7) | REX_B(s);
3270 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[reg]),
3271 offsetof(CPUX86State,xmm_regs[rm]));
3273 break;
3274 case 0x210: /* movss xmm, ea */
3275 if (mod != 3) {
3276 gen_lea_modrm(env, s, modrm);
3277 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3278 tcg_gen_st32_tl(s->T0, cpu_env,
3279 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3280 tcg_gen_movi_tl(s->T0, 0);
3281 tcg_gen_st32_tl(s->T0, cpu_env,
3282 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)));
3283 tcg_gen_st32_tl(s->T0, cpu_env,
3284 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3285 tcg_gen_st32_tl(s->T0, cpu_env,
3286 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3287 } else {
3288 rm = (modrm & 7) | REX_B(s);
3289 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3290 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3292 break;
3293 case 0x310: /* movsd xmm, ea */
3294 if (mod != 3) {
3295 gen_lea_modrm(env, s, modrm);
3296 gen_ldq_env_A0(s, offsetof(CPUX86State,
3297 xmm_regs[reg].ZMM_Q(0)));
3298 tcg_gen_movi_tl(s->T0, 0);
3299 tcg_gen_st32_tl(s->T0, cpu_env,
3300 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3301 tcg_gen_st32_tl(s->T0, cpu_env,
3302 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3303 } else {
3304 rm = (modrm & 7) | REX_B(s);
3305 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3306 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3308 break;
3309 case 0x012: /* movlps */
3310 case 0x112: /* movlpd */
3311 if (mod != 3) {
3312 gen_lea_modrm(env, s, modrm);
3313 gen_ldq_env_A0(s, offsetof(CPUX86State,
3314 xmm_regs[reg].ZMM_Q(0)));
3315 } else {
3316 /* movhlps */
3317 rm = (modrm & 7) | REX_B(s);
3318 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3319 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3321 break;
3322 case 0x212: /* movsldup */
3323 if (mod != 3) {
3324 gen_lea_modrm(env, s, modrm);
3325 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3326 } else {
3327 rm = (modrm & 7) | REX_B(s);
3328 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3329 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3330 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3331 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3333 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3334 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3335 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3336 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3337 break;
3338 case 0x312: /* movddup */
3339 if (mod != 3) {
3340 gen_lea_modrm(env, s, modrm);
3341 gen_ldq_env_A0(s, offsetof(CPUX86State,
3342 xmm_regs[reg].ZMM_Q(0)));
3343 } else {
3344 rm = (modrm & 7) | REX_B(s);
3345 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3346 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3348 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3349 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3350 break;
3351 case 0x016: /* movhps */
3352 case 0x116: /* movhpd */
3353 if (mod != 3) {
3354 gen_lea_modrm(env, s, modrm);
3355 gen_ldq_env_A0(s, offsetof(CPUX86State,
3356 xmm_regs[reg].ZMM_Q(1)));
3357 } else {
3358 /* movlhps */
3359 rm = (modrm & 7) | REX_B(s);
3360 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3361 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3363 break;
3364 case 0x216: /* movshdup */
3365 if (mod != 3) {
3366 gen_lea_modrm(env, s, modrm);
3367 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3368 } else {
3369 rm = (modrm & 7) | REX_B(s);
3370 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3371 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3372 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3373 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3375 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3376 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3377 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3378 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3379 break;
3380 case 0x178:
3381 case 0x378:
3383 int bit_index, field_length;
3385 if (b1 == 1 && reg != 0)
3386 goto illegal_op;
3387 field_length = x86_ldub_code(env, s) & 0x3F;
3388 bit_index = x86_ldub_code(env, s) & 0x3F;
3389 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3390 offsetof(CPUX86State,xmm_regs[reg]));
3391 if (b1 == 1)
3392 gen_helper_extrq_i(cpu_env, s->ptr0,
3393 tcg_const_i32(bit_index),
3394 tcg_const_i32(field_length));
3395 else
3396 gen_helper_insertq_i(cpu_env, s->ptr0,
3397 tcg_const_i32(bit_index),
3398 tcg_const_i32(field_length));
3400 break;
3401 case 0x7e: /* movd ea, mm */
3402 #ifdef TARGET_X86_64
3403 if (s->dflag == MO_64) {
3404 tcg_gen_ld_i64(s->T0, cpu_env,
3405 offsetof(CPUX86State,fpregs[reg].mmx));
3406 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3407 } else
3408 #endif
3410 tcg_gen_ld32u_tl(s->T0, cpu_env,
3411 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3412 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3414 break;
3415 case 0x17e: /* movd ea, xmm */
3416 #ifdef TARGET_X86_64
3417 if (s->dflag == MO_64) {
3418 tcg_gen_ld_i64(s->T0, cpu_env,
3419 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3420 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3421 } else
3422 #endif
3424 tcg_gen_ld32u_tl(s->T0, cpu_env,
3425 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3426 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3428 break;
3429 case 0x27e: /* movq xmm, ea */
3430 if (mod != 3) {
3431 gen_lea_modrm(env, s, modrm);
3432 gen_ldq_env_A0(s, offsetof(CPUX86State,
3433 xmm_regs[reg].ZMM_Q(0)));
3434 } else {
3435 rm = (modrm & 7) | REX_B(s);
3436 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3437 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3439 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3440 break;
3441 case 0x7f: /* movq ea, mm */
3442 if (mod != 3) {
3443 gen_lea_modrm(env, s, modrm);
3444 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3445 } else {
3446 rm = (modrm & 7);
3447 gen_op_movq(s, offsetof(CPUX86State, fpregs[rm].mmx),
3448 offsetof(CPUX86State,fpregs[reg].mmx));
3450 break;
3451 case 0x011: /* movups */
3452 case 0x111: /* movupd */
3453 case 0x029: /* movaps */
3454 case 0x129: /* movapd */
3455 case 0x17f: /* movdqa ea, xmm */
3456 case 0x27f: /* movdqu ea, xmm */
3457 if (mod != 3) {
3458 gen_lea_modrm(env, s, modrm);
3459 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3460 } else {
3461 rm = (modrm & 7) | REX_B(s);
3462 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[rm]),
3463 offsetof(CPUX86State,xmm_regs[reg]));
3465 break;
3466 case 0x211: /* movss ea, xmm */
3467 if (mod != 3) {
3468 gen_lea_modrm(env, s, modrm);
3469 tcg_gen_ld32u_tl(s->T0, cpu_env,
3470 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3471 gen_op_st_v(s, MO_32, s->T0, s->A0);
3472 } else {
3473 rm = (modrm & 7) | REX_B(s);
3474 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0)),
3475 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3477 break;
3478 case 0x311: /* movsd ea, xmm */
3479 if (mod != 3) {
3480 gen_lea_modrm(env, s, modrm);
3481 gen_stq_env_A0(s, offsetof(CPUX86State,
3482 xmm_regs[reg].ZMM_Q(0)));
3483 } else {
3484 rm = (modrm & 7) | REX_B(s);
3485 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3486 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3488 break;
3489 case 0x013: /* movlps */
3490 case 0x113: /* movlpd */
3491 if (mod != 3) {
3492 gen_lea_modrm(env, s, modrm);
3493 gen_stq_env_A0(s, offsetof(CPUX86State,
3494 xmm_regs[reg].ZMM_Q(0)));
3495 } else {
3496 goto illegal_op;
3498 break;
3499 case 0x017: /* movhps */
3500 case 0x117: /* movhpd */
3501 if (mod != 3) {
3502 gen_lea_modrm(env, s, modrm);
3503 gen_stq_env_A0(s, offsetof(CPUX86State,
3504 xmm_regs[reg].ZMM_Q(1)));
3505 } else {
3506 goto illegal_op;
3508 break;
3509 case 0x71: /* shift mm, im */
3510 case 0x72:
3511 case 0x73:
3512 case 0x171: /* shift xmm, im */
3513 case 0x172:
3514 case 0x173:
3515 if (b1 >= 2) {
3516 goto unknown_op;
3518 val = x86_ldub_code(env, s);
3519 if (is_xmm) {
3520 tcg_gen_movi_tl(s->T0, val);
3521 tcg_gen_st32_tl(s->T0, cpu_env,
3522 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3523 tcg_gen_movi_tl(s->T0, 0);
3524 tcg_gen_st32_tl(s->T0, cpu_env,
3525 offsetof(CPUX86State, xmm_t0.ZMM_L(1)));
3526 op1_offset = offsetof(CPUX86State,xmm_t0);
3527 } else {
3528 tcg_gen_movi_tl(s->T0, val);
3529 tcg_gen_st32_tl(s->T0, cpu_env,
3530 offsetof(CPUX86State, mmx_t0.MMX_L(0)));
3531 tcg_gen_movi_tl(s->T0, 0);
3532 tcg_gen_st32_tl(s->T0, cpu_env,
3533 offsetof(CPUX86State, mmx_t0.MMX_L(1)));
3534 op1_offset = offsetof(CPUX86State,mmx_t0);
3536 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3537 (((modrm >> 3)) & 7)][b1];
3538 if (!sse_fn_epp) {
3539 goto unknown_op;
3541 if (is_xmm) {
3542 rm = (modrm & 7) | REX_B(s);
3543 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3544 } else {
3545 rm = (modrm & 7);
3546 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3548 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3549 tcg_gen_addi_ptr(s->ptr1, cpu_env, op1_offset);
3550 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3551 break;
3552 case 0x050: /* movmskps */
3553 rm = (modrm & 7) | REX_B(s);
3554 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3555 offsetof(CPUX86State,xmm_regs[rm]));
3556 gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0);
3557 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3558 break;
3559 case 0x150: /* movmskpd */
3560 rm = (modrm & 7) | REX_B(s);
3561 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3562 offsetof(CPUX86State,xmm_regs[rm]));
3563 gen_helper_movmskpd(s->tmp2_i32, cpu_env, s->ptr0);
3564 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3565 break;
3566 case 0x02a: /* cvtpi2ps */
3567 case 0x12a: /* cvtpi2pd */
3568 gen_helper_enter_mmx(cpu_env);
3569 if (mod != 3) {
3570 gen_lea_modrm(env, s, modrm);
3571 op2_offset = offsetof(CPUX86State,mmx_t0);
3572 gen_ldq_env_A0(s, op2_offset);
3573 } else {
3574 rm = (modrm & 7);
3575 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3577 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3578 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3579 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3580 switch(b >> 8) {
3581 case 0x0:
3582 gen_helper_cvtpi2ps(cpu_env, s->ptr0, s->ptr1);
3583 break;
3584 default:
3585 case 0x1:
3586 gen_helper_cvtpi2pd(cpu_env, s->ptr0, s->ptr1);
3587 break;
3589 break;
3590 case 0x22a: /* cvtsi2ss */
3591 case 0x32a: /* cvtsi2sd */
3592 ot = mo_64_32(s->dflag);
3593 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3594 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3595 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3596 if (ot == MO_32) {
3597 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3598 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3599 sse_fn_epi(cpu_env, s->ptr0, s->tmp2_i32);
3600 } else {
3601 #ifdef TARGET_X86_64
3602 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3603 sse_fn_epl(cpu_env, s->ptr0, s->T0);
3604 #else
3605 goto illegal_op;
3606 #endif
3608 break;
3609 case 0x02c: /* cvttps2pi */
3610 case 0x12c: /* cvttpd2pi */
3611 case 0x02d: /* cvtps2pi */
3612 case 0x12d: /* cvtpd2pi */
3613 gen_helper_enter_mmx(cpu_env);
3614 if (mod != 3) {
3615 gen_lea_modrm(env, s, modrm);
3616 op2_offset = offsetof(CPUX86State,xmm_t0);
3617 gen_ldo_env_A0(s, op2_offset);
3618 } else {
3619 rm = (modrm & 7) | REX_B(s);
3620 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3622 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3623 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3624 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3625 switch(b) {
3626 case 0x02c:
3627 gen_helper_cvttps2pi(cpu_env, s->ptr0, s->ptr1);
3628 break;
3629 case 0x12c:
3630 gen_helper_cvttpd2pi(cpu_env, s->ptr0, s->ptr1);
3631 break;
3632 case 0x02d:
3633 gen_helper_cvtps2pi(cpu_env, s->ptr0, s->ptr1);
3634 break;
3635 case 0x12d:
3636 gen_helper_cvtpd2pi(cpu_env, s->ptr0, s->ptr1);
3637 break;
3639 break;
3640 case 0x22c: /* cvttss2si */
3641 case 0x32c: /* cvttsd2si */
3642 case 0x22d: /* cvtss2si */
3643 case 0x32d: /* cvtsd2si */
3644 ot = mo_64_32(s->dflag);
3645 if (mod != 3) {
3646 gen_lea_modrm(env, s, modrm);
3647 if ((b >> 8) & 1) {
3648 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3649 } else {
3650 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3651 tcg_gen_st32_tl(s->T0, cpu_env,
3652 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3654 op2_offset = offsetof(CPUX86State,xmm_t0);
3655 } else {
3656 rm = (modrm & 7) | REX_B(s);
3657 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3659 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3660 if (ot == MO_32) {
3661 SSEFunc_i_ep sse_fn_i_ep =
3662 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3663 sse_fn_i_ep(s->tmp2_i32, cpu_env, s->ptr0);
3664 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
3665 } else {
3666 #ifdef TARGET_X86_64
3667 SSEFunc_l_ep sse_fn_l_ep =
3668 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3669 sse_fn_l_ep(s->T0, cpu_env, s->ptr0);
3670 #else
3671 goto illegal_op;
3672 #endif
3674 gen_op_mov_reg_v(s, ot, reg, s->T0);
3675 break;
3676 case 0xc4: /* pinsrw */
3677 case 0x1c4:
3678 s->rip_offset = 1;
3679 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3680 val = x86_ldub_code(env, s);
3681 if (b1) {
3682 val &= 7;
3683 tcg_gen_st16_tl(s->T0, cpu_env,
3684 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3685 } else {
3686 val &= 3;
3687 tcg_gen_st16_tl(s->T0, cpu_env,
3688 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3690 break;
3691 case 0xc5: /* pextrw */
3692 case 0x1c5:
3693 if (mod != 3)
3694 goto illegal_op;
3695 ot = mo_64_32(s->dflag);
3696 val = x86_ldub_code(env, s);
3697 if (b1) {
3698 val &= 7;
3699 rm = (modrm & 7) | REX_B(s);
3700 tcg_gen_ld16u_tl(s->T0, cpu_env,
3701 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3702 } else {
3703 val &= 3;
3704 rm = (modrm & 7);
3705 tcg_gen_ld16u_tl(s->T0, cpu_env,
3706 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3708 reg = ((modrm >> 3) & 7) | REX_R(s);
3709 gen_op_mov_reg_v(s, ot, reg, s->T0);
3710 break;
3711 case 0x1d6: /* movq ea, xmm */
3712 if (mod != 3) {
3713 gen_lea_modrm(env, s, modrm);
3714 gen_stq_env_A0(s, offsetof(CPUX86State,
3715 xmm_regs[reg].ZMM_Q(0)));
3716 } else {
3717 rm = (modrm & 7) | REX_B(s);
3718 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3719 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3720 gen_op_movq_env_0(s,
3721 offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(1)));
3723 break;
3724 case 0x2d6: /* movq2dq */
3725 gen_helper_enter_mmx(cpu_env);
3726 rm = (modrm & 7);
3727 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3728 offsetof(CPUX86State,fpregs[rm].mmx));
3729 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3730 break;
3731 case 0x3d6: /* movdq2q */
3732 gen_helper_enter_mmx(cpu_env);
3733 rm = (modrm & 7) | REX_B(s);
3734 gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx),
3735 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3736 break;
3737 case 0xd7: /* pmovmskb */
3738 case 0x1d7:
3739 if (mod != 3)
3740 goto illegal_op;
3741 if (b1) {
3742 rm = (modrm & 7) | REX_B(s);
3743 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3744 offsetof(CPUX86State, xmm_regs[rm]));
3745 gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0);
3746 } else {
3747 rm = (modrm & 7);
3748 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3749 offsetof(CPUX86State, fpregs[rm].mmx));
3750 gen_helper_pmovmskb_mmx(s->tmp2_i32, cpu_env, s->ptr0);
3752 reg = ((modrm >> 3) & 7) | REX_R(s);
3753 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3754 break;
3756 case 0x138:
3757 case 0x038:
3758 b = modrm;
3759 if ((b & 0xf0) == 0xf0) {
3760 goto do_0f_38_fx;
3762 modrm = x86_ldub_code(env, s);
3763 rm = modrm & 7;
3764 reg = ((modrm >> 3) & 7) | REX_R(s);
3765 mod = (modrm >> 6) & 3;
3766 if (b1 >= 2) {
3767 goto unknown_op;
3770 sse_fn_epp = sse_op_table6[b].op[b1];
3771 if (!sse_fn_epp) {
3772 goto unknown_op;
3774 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3775 goto illegal_op;
3777 if (b1) {
3778 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3779 if (mod == 3) {
3780 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3781 } else {
3782 op2_offset = offsetof(CPUX86State,xmm_t0);
3783 gen_lea_modrm(env, s, modrm);
3784 switch (b) {
3785 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3786 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3787 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3788 gen_ldq_env_A0(s, op2_offset +
3789 offsetof(ZMMReg, ZMM_Q(0)));
3790 break;
3791 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3792 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3793 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
3794 s->mem_index, MO_LEUL);
3795 tcg_gen_st_i32(s->tmp2_i32, cpu_env, op2_offset +
3796 offsetof(ZMMReg, ZMM_L(0)));
3797 break;
3798 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3799 tcg_gen_qemu_ld_tl(s->tmp0, s->A0,
3800 s->mem_index, MO_LEUW);
3801 tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset +
3802 offsetof(ZMMReg, ZMM_W(0)));
3803 break;
3804 case 0x2a: /* movntqda */
3805 gen_ldo_env_A0(s, op1_offset);
3806 return;
3807 default:
3808 gen_ldo_env_A0(s, op2_offset);
3811 } else {
3812 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3813 if (mod == 3) {
3814 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3815 } else {
3816 op2_offset = offsetof(CPUX86State,mmx_t0);
3817 gen_lea_modrm(env, s, modrm);
3818 gen_ldq_env_A0(s, op2_offset);
3821 if (sse_fn_epp == SSE_SPECIAL) {
3822 goto unknown_op;
3825 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3826 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3827 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3829 if (b == 0x17) {
3830 set_cc_op(s, CC_OP_EFLAGS);
3832 break;
3834 case 0x238:
3835 case 0x338:
3836 do_0f_38_fx:
3837 /* Various integer extensions at 0f 38 f[0-f]. */
3838 b = modrm | (b1 << 8);
3839 modrm = x86_ldub_code(env, s);
3840 reg = ((modrm >> 3) & 7) | REX_R(s);
3842 switch (b) {
3843 case 0x3f0: /* crc32 Gd,Eb */
3844 case 0x3f1: /* crc32 Gd,Ey */
3845 do_crc32:
3846 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3847 goto illegal_op;
3849 if ((b & 0xff) == 0xf0) {
3850 ot = MO_8;
3851 } else if (s->dflag != MO_64) {
3852 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3853 } else {
3854 ot = MO_64;
3857 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[reg]);
3858 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3859 gen_helper_crc32(s->T0, s->tmp2_i32,
3860 s->T0, tcg_const_i32(8 << ot));
3862 ot = mo_64_32(s->dflag);
3863 gen_op_mov_reg_v(s, ot, reg, s->T0);
3864 break;
3866 case 0x1f0: /* crc32 or movbe */
3867 case 0x1f1:
3868 /* For these insns, the f3 prefix is supposed to have priority
3869 over the 66 prefix, but that's not what we implement above
3870 setting b1. */
3871 if (s->prefix & PREFIX_REPNZ) {
3872 goto do_crc32;
3874 /* FALLTHRU */
3875 case 0x0f0: /* movbe Gy,My */
3876 case 0x0f1: /* movbe My,Gy */
3877 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3878 goto illegal_op;
3880 if (s->dflag != MO_64) {
3881 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3882 } else {
3883 ot = MO_64;
3886 gen_lea_modrm(env, s, modrm);
3887 if ((b & 1) == 0) {
3888 tcg_gen_qemu_ld_tl(s->T0, s->A0,
3889 s->mem_index, ot | MO_BE);
3890 gen_op_mov_reg_v(s, ot, reg, s->T0);
3891 } else {
3892 tcg_gen_qemu_st_tl(cpu_regs[reg], s->A0,
3893 s->mem_index, ot | MO_BE);
3895 break;
3897 case 0x0f2: /* andn Gy, By, Ey */
3898 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3899 || !(s->prefix & PREFIX_VEX)
3900 || s->vex_l != 0) {
3901 goto illegal_op;
3903 ot = mo_64_32(s->dflag);
3904 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3905 tcg_gen_andc_tl(s->T0, s->T0, cpu_regs[s->vex_v]);
3906 gen_op_mov_reg_v(s, ot, reg, s->T0);
3907 gen_op_update1_cc(s);
3908 set_cc_op(s, CC_OP_LOGICB + ot);
3909 break;
3911 case 0x0f7: /* bextr Gy, Ey, By */
3912 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3913 || !(s->prefix & PREFIX_VEX)
3914 || s->vex_l != 0) {
3915 goto illegal_op;
3917 ot = mo_64_32(s->dflag);
3919 TCGv bound, zero;
3921 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3922 /* Extract START, and shift the operand.
3923 Shifts larger than operand size get zeros. */
3924 tcg_gen_ext8u_tl(s->A0, cpu_regs[s->vex_v]);
3925 tcg_gen_shr_tl(s->T0, s->T0, s->A0);
3927 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3928 zero = tcg_const_tl(0);
3929 tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound,
3930 s->T0, zero);
3931 tcg_temp_free(zero);
3933 /* Extract the LEN into a mask. Lengths larger than
3934 operand size get all ones. */
3935 tcg_gen_extract_tl(s->A0, cpu_regs[s->vex_v], 8, 8);
3936 tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound,
3937 s->A0, bound);
3938 tcg_temp_free(bound);
3939 tcg_gen_movi_tl(s->T1, 1);
3940 tcg_gen_shl_tl(s->T1, s->T1, s->A0);
3941 tcg_gen_subi_tl(s->T1, s->T1, 1);
3942 tcg_gen_and_tl(s->T0, s->T0, s->T1);
3944 gen_op_mov_reg_v(s, ot, reg, s->T0);
3945 gen_op_update1_cc(s);
3946 set_cc_op(s, CC_OP_LOGICB + ot);
3948 break;
3950 case 0x0f5: /* bzhi Gy, Ey, By */
3951 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3952 || !(s->prefix & PREFIX_VEX)
3953 || s->vex_l != 0) {
3954 goto illegal_op;
3956 ot = mo_64_32(s->dflag);
3957 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3958 tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]);
3960 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3961 /* Note that since we're using BMILG (in order to get O
3962 cleared) we need to store the inverse into C. */
3963 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3964 s->T1, bound);
3965 tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1,
3966 bound, bound, s->T1);
3967 tcg_temp_free(bound);
3969 tcg_gen_movi_tl(s->A0, -1);
3970 tcg_gen_shl_tl(s->A0, s->A0, s->T1);
3971 tcg_gen_andc_tl(s->T0, s->T0, s->A0);
3972 gen_op_mov_reg_v(s, ot, reg, s->T0);
3973 gen_op_update1_cc(s);
3974 set_cc_op(s, CC_OP_BMILGB + ot);
3975 break;
3977 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3978 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3979 || !(s->prefix & PREFIX_VEX)
3980 || s->vex_l != 0) {
3981 goto illegal_op;
3983 ot = mo_64_32(s->dflag);
3984 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3985 switch (ot) {
3986 default:
3987 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3988 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EDX]);
3989 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
3990 s->tmp2_i32, s->tmp3_i32);
3991 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32);
3992 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp3_i32);
3993 break;
3994 #ifdef TARGET_X86_64
3995 case MO_64:
3996 tcg_gen_mulu2_i64(s->T0, s->T1,
3997 s->T0, cpu_regs[R_EDX]);
3998 tcg_gen_mov_i64(cpu_regs[s->vex_v], s->T0);
3999 tcg_gen_mov_i64(cpu_regs[reg], s->T1);
4000 break;
4001 #endif
4003 break;
4005 case 0x3f5: /* pdep Gy, By, Ey */
4006 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4007 || !(s->prefix & PREFIX_VEX)
4008 || s->vex_l != 0) {
4009 goto illegal_op;
4011 ot = mo_64_32(s->dflag);
4012 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4013 /* Note that by zero-extending the source operand, we
4014 automatically handle zero-extending the result. */
4015 if (ot == MO_64) {
4016 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
4017 } else {
4018 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
4020 gen_helper_pdep(cpu_regs[reg], s->T1, s->T0);
4021 break;
4023 case 0x2f5: /* pext Gy, By, Ey */
4024 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4025 || !(s->prefix & PREFIX_VEX)
4026 || s->vex_l != 0) {
4027 goto illegal_op;
4029 ot = mo_64_32(s->dflag);
4030 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4031 /* Note that by zero-extending the source operand, we
4032 automatically handle zero-extending the result. */
4033 if (ot == MO_64) {
4034 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
4035 } else {
4036 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
4038 gen_helper_pext(cpu_regs[reg], s->T1, s->T0);
4039 break;
4041 case 0x1f6: /* adcx Gy, Ey */
4042 case 0x2f6: /* adox Gy, Ey */
4043 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
4044 goto illegal_op;
4045 } else {
4046 TCGv carry_in, carry_out, zero;
4047 int end_op;
4049 ot = mo_64_32(s->dflag);
4050 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4052 /* Re-use the carry-out from a previous round. */
4053 carry_in = NULL;
4054 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
4055 switch (s->cc_op) {
4056 case CC_OP_ADCX:
4057 if (b == 0x1f6) {
4058 carry_in = cpu_cc_dst;
4059 end_op = CC_OP_ADCX;
4060 } else {
4061 end_op = CC_OP_ADCOX;
4063 break;
4064 case CC_OP_ADOX:
4065 if (b == 0x1f6) {
4066 end_op = CC_OP_ADCOX;
4067 } else {
4068 carry_in = cpu_cc_src2;
4069 end_op = CC_OP_ADOX;
4071 break;
4072 case CC_OP_ADCOX:
4073 end_op = CC_OP_ADCOX;
4074 carry_in = carry_out;
4075 break;
4076 default:
4077 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
4078 break;
4080 /* If we can't reuse carry-out, get it out of EFLAGS. */
4081 if (!carry_in) {
4082 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4083 gen_compute_eflags(s);
4085 carry_in = s->tmp0;
4086 tcg_gen_extract_tl(carry_in, cpu_cc_src,
4087 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
4090 switch (ot) {
4091 #ifdef TARGET_X86_64
4092 case MO_32:
4093 /* If we know TL is 64-bit, and we want a 32-bit
4094 result, just do everything in 64-bit arithmetic. */
4095 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4096 tcg_gen_ext32u_i64(s->T0, s->T0);
4097 tcg_gen_add_i64(s->T0, s->T0, cpu_regs[reg]);
4098 tcg_gen_add_i64(s->T0, s->T0, carry_in);
4099 tcg_gen_ext32u_i64(cpu_regs[reg], s->T0);
4100 tcg_gen_shri_i64(carry_out, s->T0, 32);
4101 break;
4102 #endif
4103 default:
4104 /* Otherwise compute the carry-out in two steps. */
4105 zero = tcg_const_tl(0);
4106 tcg_gen_add2_tl(s->T0, carry_out,
4107 s->T0, zero,
4108 carry_in, zero);
4109 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4110 cpu_regs[reg], carry_out,
4111 s->T0, zero);
4112 tcg_temp_free(zero);
4113 break;
4115 set_cc_op(s, end_op);
4117 break;
4119 case 0x1f7: /* shlx Gy, Ey, By */
4120 case 0x2f7: /* sarx Gy, Ey, By */
4121 case 0x3f7: /* shrx Gy, Ey, By */
4122 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4123 || !(s->prefix & PREFIX_VEX)
4124 || s->vex_l != 0) {
4125 goto illegal_op;
4127 ot = mo_64_32(s->dflag);
4128 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4129 if (ot == MO_64) {
4130 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 63);
4131 } else {
4132 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 31);
4134 if (b == 0x1f7) {
4135 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
4136 } else if (b == 0x2f7) {
4137 if (ot != MO_64) {
4138 tcg_gen_ext32s_tl(s->T0, s->T0);
4140 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
4141 } else {
4142 if (ot != MO_64) {
4143 tcg_gen_ext32u_tl(s->T0, s->T0);
4145 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
4147 gen_op_mov_reg_v(s, ot, reg, s->T0);
4148 break;
4150 case 0x0f3:
4151 case 0x1f3:
4152 case 0x2f3:
4153 case 0x3f3: /* Group 17 */
4154 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4155 || !(s->prefix & PREFIX_VEX)
4156 || s->vex_l != 0) {
4157 goto illegal_op;
4159 ot = mo_64_32(s->dflag);
4160 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4162 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4163 switch (reg & 7) {
4164 case 1: /* blsr By,Ey */
4165 tcg_gen_subi_tl(s->T1, s->T0, 1);
4166 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4167 break;
4168 case 2: /* blsmsk By,Ey */
4169 tcg_gen_subi_tl(s->T1, s->T0, 1);
4170 tcg_gen_xor_tl(s->T0, s->T0, s->T1);
4171 break;
4172 case 3: /* blsi By, Ey */
4173 tcg_gen_neg_tl(s->T1, s->T0);
4174 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4175 break;
4176 default:
4177 goto unknown_op;
4179 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4180 gen_op_mov_reg_v(s, ot, s->vex_v, s->T0);
4181 set_cc_op(s, CC_OP_BMILGB + ot);
4182 break;
4184 default:
4185 goto unknown_op;
4187 break;
4189 case 0x03a:
4190 case 0x13a:
4191 b = modrm;
4192 modrm = x86_ldub_code(env, s);
4193 rm = modrm & 7;
4194 reg = ((modrm >> 3) & 7) | REX_R(s);
4195 mod = (modrm >> 6) & 3;
4196 if (b1 >= 2) {
4197 goto unknown_op;
4200 sse_fn_eppi = sse_op_table7[b].op[b1];
4201 if (!sse_fn_eppi) {
4202 goto unknown_op;
4204 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4205 goto illegal_op;
4207 s->rip_offset = 1;
4209 if (sse_fn_eppi == SSE_SPECIAL) {
4210 ot = mo_64_32(s->dflag);
4211 rm = (modrm & 7) | REX_B(s);
4212 if (mod != 3)
4213 gen_lea_modrm(env, s, modrm);
4214 reg = ((modrm >> 3) & 7) | REX_R(s);
4215 val = x86_ldub_code(env, s);
4216 switch (b) {
4217 case 0x14: /* pextrb */
4218 tcg_gen_ld8u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4219 xmm_regs[reg].ZMM_B(val & 15)));
4220 if (mod == 3) {
4221 gen_op_mov_reg_v(s, ot, rm, s->T0);
4222 } else {
4223 tcg_gen_qemu_st_tl(s->T0, s->A0,
4224 s->mem_index, MO_UB);
4226 break;
4227 case 0x15: /* pextrw */
4228 tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4229 xmm_regs[reg].ZMM_W(val & 7)));
4230 if (mod == 3) {
4231 gen_op_mov_reg_v(s, ot, rm, s->T0);
4232 } else {
4233 tcg_gen_qemu_st_tl(s->T0, s->A0,
4234 s->mem_index, MO_LEUW);
4236 break;
4237 case 0x16:
4238 if (ot == MO_32) { /* pextrd */
4239 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4240 offsetof(CPUX86State,
4241 xmm_regs[reg].ZMM_L(val & 3)));
4242 if (mod == 3) {
4243 tcg_gen_extu_i32_tl(cpu_regs[rm], s->tmp2_i32);
4244 } else {
4245 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4246 s->mem_index, MO_LEUL);
4248 } else { /* pextrq */
4249 #ifdef TARGET_X86_64
4250 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
4251 offsetof(CPUX86State,
4252 xmm_regs[reg].ZMM_Q(val & 1)));
4253 if (mod == 3) {
4254 tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64);
4255 } else {
4256 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4257 s->mem_index, MO_LEQ);
4259 #else
4260 goto illegal_op;
4261 #endif
4263 break;
4264 case 0x17: /* extractps */
4265 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4266 xmm_regs[reg].ZMM_L(val & 3)));
4267 if (mod == 3) {
4268 gen_op_mov_reg_v(s, ot, rm, s->T0);
4269 } else {
4270 tcg_gen_qemu_st_tl(s->T0, s->A0,
4271 s->mem_index, MO_LEUL);
4273 break;
4274 case 0x20: /* pinsrb */
4275 if (mod == 3) {
4276 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
4277 } else {
4278 tcg_gen_qemu_ld_tl(s->T0, s->A0,
4279 s->mem_index, MO_UB);
4281 tcg_gen_st8_tl(s->T0, cpu_env, offsetof(CPUX86State,
4282 xmm_regs[reg].ZMM_B(val & 15)));
4283 break;
4284 case 0x21: /* insertps */
4285 if (mod == 3) {
4286 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4287 offsetof(CPUX86State,xmm_regs[rm]
4288 .ZMM_L((val >> 6) & 3)));
4289 } else {
4290 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4291 s->mem_index, MO_LEUL);
4293 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4294 offsetof(CPUX86State,xmm_regs[reg]
4295 .ZMM_L((val >> 4) & 3)));
4296 if ((val >> 0) & 1)
4297 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4298 cpu_env, offsetof(CPUX86State,
4299 xmm_regs[reg].ZMM_L(0)));
4300 if ((val >> 1) & 1)
4301 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4302 cpu_env, offsetof(CPUX86State,
4303 xmm_regs[reg].ZMM_L(1)));
4304 if ((val >> 2) & 1)
4305 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4306 cpu_env, offsetof(CPUX86State,
4307 xmm_regs[reg].ZMM_L(2)));
4308 if ((val >> 3) & 1)
4309 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4310 cpu_env, offsetof(CPUX86State,
4311 xmm_regs[reg].ZMM_L(3)));
4312 break;
4313 case 0x22:
4314 if (ot == MO_32) { /* pinsrd */
4315 if (mod == 3) {
4316 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[rm]);
4317 } else {
4318 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4319 s->mem_index, MO_LEUL);
4321 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4322 offsetof(CPUX86State,
4323 xmm_regs[reg].ZMM_L(val & 3)));
4324 } else { /* pinsrq */
4325 #ifdef TARGET_X86_64
4326 if (mod == 3) {
4327 gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm);
4328 } else {
4329 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4330 s->mem_index, MO_LEQ);
4332 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
4333 offsetof(CPUX86State,
4334 xmm_regs[reg].ZMM_Q(val & 1)));
4335 #else
4336 goto illegal_op;
4337 #endif
4339 break;
4341 return;
4344 if (b1) {
4345 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4346 if (mod == 3) {
4347 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4348 } else {
4349 op2_offset = offsetof(CPUX86State,xmm_t0);
4350 gen_lea_modrm(env, s, modrm);
4351 gen_ldo_env_A0(s, op2_offset);
4353 } else {
4354 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4355 if (mod == 3) {
4356 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4357 } else {
4358 op2_offset = offsetof(CPUX86State,mmx_t0);
4359 gen_lea_modrm(env, s, modrm);
4360 gen_ldq_env_A0(s, op2_offset);
4363 val = x86_ldub_code(env, s);
4365 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4366 set_cc_op(s, CC_OP_EFLAGS);
4368 if (s->dflag == MO_64) {
4369 /* The helper must use entire 64-bit gp registers */
4370 val |= 1 << 8;
4374 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4375 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4376 sse_fn_eppi(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val));
4377 break;
4379 case 0x33a:
4380 /* Various integer extensions at 0f 3a f[0-f]. */
4381 b = modrm | (b1 << 8);
4382 modrm = x86_ldub_code(env, s);
4383 reg = ((modrm >> 3) & 7) | REX_R(s);
4385 switch (b) {
4386 case 0x3f0: /* rorx Gy,Ey, Ib */
4387 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4388 || !(s->prefix & PREFIX_VEX)
4389 || s->vex_l != 0) {
4390 goto illegal_op;
4392 ot = mo_64_32(s->dflag);
4393 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4394 b = x86_ldub_code(env, s);
4395 if (ot == MO_64) {
4396 tcg_gen_rotri_tl(s->T0, s->T0, b & 63);
4397 } else {
4398 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4399 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b & 31);
4400 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
4402 gen_op_mov_reg_v(s, ot, reg, s->T0);
4403 break;
4405 default:
4406 goto unknown_op;
4408 break;
4410 default:
4411 unknown_op:
4412 gen_unknown_opcode(env, s);
4413 return;
4415 } else {
4416 /* generic MMX or SSE operation */
4417 switch(b) {
4418 case 0x70: /* pshufx insn */
4419 case 0xc6: /* pshufx insn */
4420 case 0xc2: /* compare insns */
4421 s->rip_offset = 1;
4422 break;
4423 default:
4424 break;
4426 if (is_xmm) {
4427 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4428 if (mod != 3) {
4429 int sz = 4;
4431 gen_lea_modrm(env, s, modrm);
4432 op2_offset = offsetof(CPUX86State,xmm_t0);
4434 switch (b) {
4435 case 0x50 ... 0x5a:
4436 case 0x5c ... 0x5f:
4437 case 0xc2:
4438 /* Most sse scalar operations. */
4439 if (b1 == 2) {
4440 sz = 2;
4441 } else if (b1 == 3) {
4442 sz = 3;
4444 break;
4446 case 0x2e: /* ucomis[sd] */
4447 case 0x2f: /* comis[sd] */
4448 if (b1 == 0) {
4449 sz = 2;
4450 } else {
4451 sz = 3;
4453 break;
4456 switch (sz) {
4457 case 2:
4458 /* 32 bit access */
4459 gen_op_ld_v(s, MO_32, s->T0, s->A0);
4460 tcg_gen_st32_tl(s->T0, cpu_env,
4461 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4462 break;
4463 case 3:
4464 /* 64 bit access */
4465 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4466 break;
4467 default:
4468 /* 128 bit access */
4469 gen_ldo_env_A0(s, op2_offset);
4470 break;
4472 } else {
4473 rm = (modrm & 7) | REX_B(s);
4474 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4476 } else {
4477 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4478 if (mod != 3) {
4479 gen_lea_modrm(env, s, modrm);
4480 op2_offset = offsetof(CPUX86State,mmx_t0);
4481 gen_ldq_env_A0(s, op2_offset);
4482 } else {
4483 rm = (modrm & 7);
4484 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4487 switch(b) {
4488 case 0x0f: /* 3DNow! data insns */
4489 val = x86_ldub_code(env, s);
4490 sse_fn_epp = sse_op_table5[val];
4491 if (!sse_fn_epp) {
4492 goto unknown_op;
4494 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4495 goto illegal_op;
4497 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4498 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4499 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4500 break;
4501 case 0x70: /* pshufx insn */
4502 case 0xc6: /* pshufx insn */
4503 val = x86_ldub_code(env, s);
4504 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4505 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4506 /* XXX: introduce a new table? */
4507 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4508 sse_fn_ppi(s->ptr0, s->ptr1, tcg_const_i32(val));
4509 break;
4510 case 0xc2:
4511 /* compare insns */
4512 val = x86_ldub_code(env, s);
4513 if (val >= 8)
4514 goto unknown_op;
4515 sse_fn_epp = sse_op_table4[val][b1];
4517 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4518 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4519 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4520 break;
4521 case 0xf7:
4522 /* maskmov : we must prepare A0 */
4523 if (mod != 3)
4524 goto illegal_op;
4525 tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]);
4526 gen_extu(s->aflag, s->A0);
4527 gen_add_A0_ds_seg(s);
4529 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4530 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4531 /* XXX: introduce a new table? */
4532 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4533 sse_fn_eppt(cpu_env, s->ptr0, s->ptr1, s->A0);
4534 break;
4535 default:
4536 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4537 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4538 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4539 break;
4541 if (b == 0x2e || b == 0x2f) {
4542 set_cc_op(s, CC_OP_EFLAGS);
4547 /* convert one instruction. s->base.is_jmp is set if the translation must
4548 be stopped. Return the next pc value */
4549 static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
4551 CPUX86State *env = cpu->env_ptr;
4552 int b, prefixes;
4553 int shift;
4554 MemOp ot, aflag, dflag;
4555 int modrm, reg, rm, mod, op, opreg, val;
4556 target_ulong next_eip, tval;
4557 target_ulong pc_start = s->base.pc_next;
4559 s->pc_start = s->pc = pc_start;
4560 s->override = -1;
4561 #ifdef TARGET_X86_64
4562 s->rex_w = false;
4563 s->rex_r = 0;
4564 s->rex_x = 0;
4565 s->rex_b = 0;
4566 #endif
4567 s->rip_offset = 0; /* for relative ip address */
4568 s->vex_l = 0;
4569 s->vex_v = 0;
4570 if (sigsetjmp(s->jmpbuf, 0) != 0) {
4571 gen_exception_gpf(s);
4572 return s->pc;
4575 prefixes = 0;
4577 next_byte:
4578 b = x86_ldub_code(env, s);
4579 /* Collect prefixes. */
4580 switch (b) {
4581 case 0xf3:
4582 prefixes |= PREFIX_REPZ;
4583 goto next_byte;
4584 case 0xf2:
4585 prefixes |= PREFIX_REPNZ;
4586 goto next_byte;
4587 case 0xf0:
4588 prefixes |= PREFIX_LOCK;
4589 goto next_byte;
4590 case 0x2e:
4591 s->override = R_CS;
4592 goto next_byte;
4593 case 0x36:
4594 s->override = R_SS;
4595 goto next_byte;
4596 case 0x3e:
4597 s->override = R_DS;
4598 goto next_byte;
4599 case 0x26:
4600 s->override = R_ES;
4601 goto next_byte;
4602 case 0x64:
4603 s->override = R_FS;
4604 goto next_byte;
4605 case 0x65:
4606 s->override = R_GS;
4607 goto next_byte;
4608 case 0x66:
4609 prefixes |= PREFIX_DATA;
4610 goto next_byte;
4611 case 0x67:
4612 prefixes |= PREFIX_ADR;
4613 goto next_byte;
4614 #ifdef TARGET_X86_64
4615 case 0x40 ... 0x4f:
4616 if (CODE64(s)) {
4617 /* REX prefix */
4618 prefixes |= PREFIX_REX;
4619 s->rex_w = (b >> 3) & 1;
4620 s->rex_r = (b & 0x4) << 1;
4621 s->rex_x = (b & 0x2) << 2;
4622 s->rex_b = (b & 0x1) << 3;
4623 goto next_byte;
4625 break;
4626 #endif
4627 case 0xc5: /* 2-byte VEX */
4628 case 0xc4: /* 3-byte VEX */
4629 /* VEX prefixes cannot be used except in 32-bit mode.
4630 Otherwise the instruction is LES or LDS. */
4631 if (CODE32(s) && !VM86(s)) {
4632 static const int pp_prefix[4] = {
4633 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4635 int vex3, vex2 = x86_ldub_code(env, s);
4637 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4638 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4639 otherwise the instruction is LES or LDS. */
4640 s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
4641 break;
4644 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4645 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4646 | PREFIX_LOCK | PREFIX_DATA | PREFIX_REX)) {
4647 goto illegal_op;
4649 #ifdef TARGET_X86_64
4650 s->rex_r = (~vex2 >> 4) & 8;
4651 #endif
4652 if (b == 0xc5) {
4653 /* 2-byte VEX prefix: RVVVVlpp, implied 0f leading opcode byte */
4654 vex3 = vex2;
4655 b = x86_ldub_code(env, s) | 0x100;
4656 } else {
4657 /* 3-byte VEX prefix: RXBmmmmm wVVVVlpp */
4658 vex3 = x86_ldub_code(env, s);
4659 #ifdef TARGET_X86_64
4660 s->rex_x = (~vex2 >> 3) & 8;
4661 s->rex_b = (~vex2 >> 2) & 8;
4662 s->rex_w = (vex3 >> 7) & 1;
4663 #endif
4664 switch (vex2 & 0x1f) {
4665 case 0x01: /* Implied 0f leading opcode bytes. */
4666 b = x86_ldub_code(env, s) | 0x100;
4667 break;
4668 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4669 b = 0x138;
4670 break;
4671 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4672 b = 0x13a;
4673 break;
4674 default: /* Reserved for future use. */
4675 goto unknown_op;
4678 s->vex_v = (~vex3 >> 3) & 0xf;
4679 s->vex_l = (vex3 >> 2) & 1;
4680 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4682 break;
4685 /* Post-process prefixes. */
4686 if (CODE64(s)) {
4687 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4688 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4689 over 0x66 if both are present. */
4690 dflag = (REX_W(s) ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4691 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4692 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4693 } else {
4694 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4695 if (CODE32(s) ^ ((prefixes & PREFIX_DATA) != 0)) {
4696 dflag = MO_32;
4697 } else {
4698 dflag = MO_16;
4700 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4701 if (CODE32(s) ^ ((prefixes & PREFIX_ADR) != 0)) {
4702 aflag = MO_32;
4703 } else {
4704 aflag = MO_16;
4708 s->prefix = prefixes;
4709 s->aflag = aflag;
4710 s->dflag = dflag;
4712 /* now check op code */
4713 reswitch:
4714 switch(b) {
4715 case 0x0f:
4716 /**************************/
4717 /* extended op code */
4718 b = x86_ldub_code(env, s) | 0x100;
4719 goto reswitch;
4721 /**************************/
4722 /* arith & logic */
4723 case 0x00 ... 0x05:
4724 case 0x08 ... 0x0d:
4725 case 0x10 ... 0x15:
4726 case 0x18 ... 0x1d:
4727 case 0x20 ... 0x25:
4728 case 0x28 ... 0x2d:
4729 case 0x30 ... 0x35:
4730 case 0x38 ... 0x3d:
4732 int op, f, val;
4733 op = (b >> 3) & 7;
4734 f = (b >> 1) & 3;
4736 ot = mo_b_d(b, dflag);
4738 switch(f) {
4739 case 0: /* OP Ev, Gv */
4740 modrm = x86_ldub_code(env, s);
4741 reg = ((modrm >> 3) & 7) | REX_R(s);
4742 mod = (modrm >> 6) & 3;
4743 rm = (modrm & 7) | REX_B(s);
4744 if (mod != 3) {
4745 gen_lea_modrm(env, s, modrm);
4746 opreg = OR_TMP0;
4747 } else if (op == OP_XORL && rm == reg) {
4748 xor_zero:
4749 /* xor reg, reg optimisation */
4750 set_cc_op(s, CC_OP_CLR);
4751 tcg_gen_movi_tl(s->T0, 0);
4752 gen_op_mov_reg_v(s, ot, reg, s->T0);
4753 break;
4754 } else {
4755 opreg = rm;
4757 gen_op_mov_v_reg(s, ot, s->T1, reg);
4758 gen_op(s, op, ot, opreg);
4759 break;
4760 case 1: /* OP Gv, Ev */
4761 modrm = x86_ldub_code(env, s);
4762 mod = (modrm >> 6) & 3;
4763 reg = ((modrm >> 3) & 7) | REX_R(s);
4764 rm = (modrm & 7) | REX_B(s);
4765 if (mod != 3) {
4766 gen_lea_modrm(env, s, modrm);
4767 gen_op_ld_v(s, ot, s->T1, s->A0);
4768 } else if (op == OP_XORL && rm == reg) {
4769 goto xor_zero;
4770 } else {
4771 gen_op_mov_v_reg(s, ot, s->T1, rm);
4773 gen_op(s, op, ot, reg);
4774 break;
4775 case 2: /* OP A, Iv */
4776 val = insn_get(env, s, ot);
4777 tcg_gen_movi_tl(s->T1, val);
4778 gen_op(s, op, ot, OR_EAX);
4779 break;
4782 break;
4784 case 0x82:
4785 if (CODE64(s))
4786 goto illegal_op;
4787 /* fall through */
4788 case 0x80: /* GRP1 */
4789 case 0x81:
4790 case 0x83:
4792 int val;
4794 ot = mo_b_d(b, dflag);
4796 modrm = x86_ldub_code(env, s);
4797 mod = (modrm >> 6) & 3;
4798 rm = (modrm & 7) | REX_B(s);
4799 op = (modrm >> 3) & 7;
4801 if (mod != 3) {
4802 if (b == 0x83)
4803 s->rip_offset = 1;
4804 else
4805 s->rip_offset = insn_const_size(ot);
4806 gen_lea_modrm(env, s, modrm);
4807 opreg = OR_TMP0;
4808 } else {
4809 opreg = rm;
4812 switch(b) {
4813 default:
4814 case 0x80:
4815 case 0x81:
4816 case 0x82:
4817 val = insn_get(env, s, ot);
4818 break;
4819 case 0x83:
4820 val = (int8_t)insn_get(env, s, MO_8);
4821 break;
4823 tcg_gen_movi_tl(s->T1, val);
4824 gen_op(s, op, ot, opreg);
4826 break;
4828 /**************************/
4829 /* inc, dec, and other misc arith */
4830 case 0x40 ... 0x47: /* inc Gv */
4831 ot = dflag;
4832 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4833 break;
4834 case 0x48 ... 0x4f: /* dec Gv */
4835 ot = dflag;
4836 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4837 break;
4838 case 0xf6: /* GRP3 */
4839 case 0xf7:
4840 ot = mo_b_d(b, dflag);
4842 modrm = x86_ldub_code(env, s);
4843 mod = (modrm >> 6) & 3;
4844 rm = (modrm & 7) | REX_B(s);
4845 op = (modrm >> 3) & 7;
4846 if (mod != 3) {
4847 if (op == 0) {
4848 s->rip_offset = insn_const_size(ot);
4850 gen_lea_modrm(env, s, modrm);
4851 /* For those below that handle locked memory, don't load here. */
4852 if (!(s->prefix & PREFIX_LOCK)
4853 || op != 2) {
4854 gen_op_ld_v(s, ot, s->T0, s->A0);
4856 } else {
4857 gen_op_mov_v_reg(s, ot, s->T0, rm);
4860 switch(op) {
4861 case 0: /* test */
4862 val = insn_get(env, s, ot);
4863 tcg_gen_movi_tl(s->T1, val);
4864 gen_op_testl_T0_T1_cc(s);
4865 set_cc_op(s, CC_OP_LOGICB + ot);
4866 break;
4867 case 2: /* not */
4868 if (s->prefix & PREFIX_LOCK) {
4869 if (mod == 3) {
4870 goto illegal_op;
4872 tcg_gen_movi_tl(s->T0, ~0);
4873 tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0,
4874 s->mem_index, ot | MO_LE);
4875 } else {
4876 tcg_gen_not_tl(s->T0, s->T0);
4877 if (mod != 3) {
4878 gen_op_st_v(s, ot, s->T0, s->A0);
4879 } else {
4880 gen_op_mov_reg_v(s, ot, rm, s->T0);
4883 break;
4884 case 3: /* neg */
4885 if (s->prefix & PREFIX_LOCK) {
4886 TCGLabel *label1;
4887 TCGv a0, t0, t1, t2;
4889 if (mod == 3) {
4890 goto illegal_op;
4892 a0 = tcg_temp_local_new();
4893 t0 = tcg_temp_local_new();
4894 label1 = gen_new_label();
4896 tcg_gen_mov_tl(a0, s->A0);
4897 tcg_gen_mov_tl(t0, s->T0);
4899 gen_set_label(label1);
4900 t1 = tcg_temp_new();
4901 t2 = tcg_temp_new();
4902 tcg_gen_mov_tl(t2, t0);
4903 tcg_gen_neg_tl(t1, t0);
4904 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4905 s->mem_index, ot | MO_LE);
4906 tcg_temp_free(t1);
4907 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4909 tcg_temp_free(t2);
4910 tcg_temp_free(a0);
4911 tcg_gen_mov_tl(s->T0, t0);
4912 tcg_temp_free(t0);
4913 } else {
4914 tcg_gen_neg_tl(s->T0, s->T0);
4915 if (mod != 3) {
4916 gen_op_st_v(s, ot, s->T0, s->A0);
4917 } else {
4918 gen_op_mov_reg_v(s, ot, rm, s->T0);
4921 gen_op_update_neg_cc(s);
4922 set_cc_op(s, CC_OP_SUBB + ot);
4923 break;
4924 case 4: /* mul */
4925 switch(ot) {
4926 case MO_8:
4927 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4928 tcg_gen_ext8u_tl(s->T0, s->T0);
4929 tcg_gen_ext8u_tl(s->T1, s->T1);
4930 /* XXX: use 32 bit mul which could be faster */
4931 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4932 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4933 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4934 tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00);
4935 set_cc_op(s, CC_OP_MULB);
4936 break;
4937 case MO_16:
4938 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
4939 tcg_gen_ext16u_tl(s->T0, s->T0);
4940 tcg_gen_ext16u_tl(s->T1, s->T1);
4941 /* XXX: use 32 bit mul which could be faster */
4942 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4943 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4944 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4945 tcg_gen_shri_tl(s->T0, s->T0, 16);
4946 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
4947 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4948 set_cc_op(s, CC_OP_MULW);
4949 break;
4950 default:
4951 case MO_32:
4952 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4953 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
4954 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
4955 s->tmp2_i32, s->tmp3_i32);
4956 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
4957 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
4958 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4959 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4960 set_cc_op(s, CC_OP_MULL);
4961 break;
4962 #ifdef TARGET_X86_64
4963 case MO_64:
4964 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4965 s->T0, cpu_regs[R_EAX]);
4966 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4967 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4968 set_cc_op(s, CC_OP_MULQ);
4969 break;
4970 #endif
4972 break;
4973 case 5: /* imul */
4974 switch(ot) {
4975 case MO_8:
4976 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4977 tcg_gen_ext8s_tl(s->T0, s->T0);
4978 tcg_gen_ext8s_tl(s->T1, s->T1);
4979 /* XXX: use 32 bit mul which could be faster */
4980 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4981 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4982 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4983 tcg_gen_ext8s_tl(s->tmp0, s->T0);
4984 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
4985 set_cc_op(s, CC_OP_MULB);
4986 break;
4987 case MO_16:
4988 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
4989 tcg_gen_ext16s_tl(s->T0, s->T0);
4990 tcg_gen_ext16s_tl(s->T1, s->T1);
4991 /* XXX: use 32 bit mul which could be faster */
4992 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4993 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4994 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4995 tcg_gen_ext16s_tl(s->tmp0, s->T0);
4996 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
4997 tcg_gen_shri_tl(s->T0, s->T0, 16);
4998 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
4999 set_cc_op(s, CC_OP_MULW);
5000 break;
5001 default:
5002 case MO_32:
5003 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5004 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
5005 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5006 s->tmp2_i32, s->tmp3_i32);
5007 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
5008 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
5009 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5010 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5011 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5012 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5013 set_cc_op(s, CC_OP_MULL);
5014 break;
5015 #ifdef TARGET_X86_64
5016 case MO_64:
5017 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5018 s->T0, cpu_regs[R_EAX]);
5019 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5020 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
5021 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
5022 set_cc_op(s, CC_OP_MULQ);
5023 break;
5024 #endif
5026 break;
5027 case 6: /* div */
5028 switch(ot) {
5029 case MO_8:
5030 gen_helper_divb_AL(cpu_env, s->T0);
5031 break;
5032 case MO_16:
5033 gen_helper_divw_AX(cpu_env, s->T0);
5034 break;
5035 default:
5036 case MO_32:
5037 gen_helper_divl_EAX(cpu_env, s->T0);
5038 break;
5039 #ifdef TARGET_X86_64
5040 case MO_64:
5041 gen_helper_divq_EAX(cpu_env, s->T0);
5042 break;
5043 #endif
5045 break;
5046 case 7: /* idiv */
5047 switch(ot) {
5048 case MO_8:
5049 gen_helper_idivb_AL(cpu_env, s->T0);
5050 break;
5051 case MO_16:
5052 gen_helper_idivw_AX(cpu_env, s->T0);
5053 break;
5054 default:
5055 case MO_32:
5056 gen_helper_idivl_EAX(cpu_env, s->T0);
5057 break;
5058 #ifdef TARGET_X86_64
5059 case MO_64:
5060 gen_helper_idivq_EAX(cpu_env, s->T0);
5061 break;
5062 #endif
5064 break;
5065 default:
5066 goto unknown_op;
5068 break;
5070 case 0xfe: /* GRP4 */
5071 case 0xff: /* GRP5 */
5072 ot = mo_b_d(b, dflag);
5074 modrm = x86_ldub_code(env, s);
5075 mod = (modrm >> 6) & 3;
5076 rm = (modrm & 7) | REX_B(s);
5077 op = (modrm >> 3) & 7;
5078 if (op >= 2 && b == 0xfe) {
5079 goto unknown_op;
5081 if (CODE64(s)) {
5082 if (op == 2 || op == 4) {
5083 /* operand size for jumps is 64 bit */
5084 ot = MO_64;
5085 } else if (op == 3 || op == 5) {
5086 ot = dflag != MO_16 ? MO_32 + REX_W(s) : MO_16;
5087 } else if (op == 6) {
5088 /* default push size is 64 bit */
5089 ot = mo_pushpop(s, dflag);
5092 if (mod != 3) {
5093 gen_lea_modrm(env, s, modrm);
5094 if (op >= 2 && op != 3 && op != 5)
5095 gen_op_ld_v(s, ot, s->T0, s->A0);
5096 } else {
5097 gen_op_mov_v_reg(s, ot, s->T0, rm);
5100 switch(op) {
5101 case 0: /* inc Ev */
5102 if (mod != 3)
5103 opreg = OR_TMP0;
5104 else
5105 opreg = rm;
5106 gen_inc(s, ot, opreg, 1);
5107 break;
5108 case 1: /* dec Ev */
5109 if (mod != 3)
5110 opreg = OR_TMP0;
5111 else
5112 opreg = rm;
5113 gen_inc(s, ot, opreg, -1);
5114 break;
5115 case 2: /* call Ev */
5116 /* XXX: optimize if memory (no 'and' is necessary) */
5117 if (dflag == MO_16) {
5118 tcg_gen_ext16u_tl(s->T0, s->T0);
5120 next_eip = s->pc - s->cs_base;
5121 tcg_gen_movi_tl(s->T1, next_eip);
5122 gen_push_v(s, s->T1);
5123 gen_op_jmp_v(s->T0);
5124 gen_bnd_jmp(s);
5125 gen_jr(s, s->T0);
5126 break;
5127 case 3: /* lcall Ev */
5128 if (mod == 3) {
5129 goto illegal_op;
5131 gen_op_ld_v(s, ot, s->T1, s->A0);
5132 gen_add_A0_im(s, 1 << ot);
5133 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5134 do_lcall:
5135 if (PE(s) && !VM86(s)) {
5136 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5137 gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
5138 tcg_const_i32(dflag - 1),
5139 tcg_const_tl(s->pc - s->cs_base));
5140 } else {
5141 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5142 gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1,
5143 tcg_const_i32(dflag - 1),
5144 tcg_const_i32(s->pc - s->cs_base));
5146 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5147 gen_jr(s, s->tmp4);
5148 break;
5149 case 4: /* jmp Ev */
5150 if (dflag == MO_16) {
5151 tcg_gen_ext16u_tl(s->T0, s->T0);
5153 gen_op_jmp_v(s->T0);
5154 gen_bnd_jmp(s);
5155 gen_jr(s, s->T0);
5156 break;
5157 case 5: /* ljmp Ev */
5158 if (mod == 3) {
5159 goto illegal_op;
5161 gen_op_ld_v(s, ot, s->T1, s->A0);
5162 gen_add_A0_im(s, 1 << ot);
5163 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5164 do_ljmp:
5165 if (PE(s) && !VM86(s)) {
5166 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5167 gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1,
5168 tcg_const_tl(s->pc - s->cs_base));
5169 } else {
5170 gen_op_movl_seg_T0_vm(s, R_CS);
5171 gen_op_jmp_v(s->T1);
5173 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5174 gen_jr(s, s->tmp4);
5175 break;
5176 case 6: /* push Ev */
5177 gen_push_v(s, s->T0);
5178 break;
5179 default:
5180 goto unknown_op;
5182 break;
5184 case 0x84: /* test Ev, Gv */
5185 case 0x85:
5186 ot = mo_b_d(b, dflag);
5188 modrm = x86_ldub_code(env, s);
5189 reg = ((modrm >> 3) & 7) | REX_R(s);
5191 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5192 gen_op_mov_v_reg(s, ot, s->T1, reg);
5193 gen_op_testl_T0_T1_cc(s);
5194 set_cc_op(s, CC_OP_LOGICB + ot);
5195 break;
5197 case 0xa8: /* test eAX, Iv */
5198 case 0xa9:
5199 ot = mo_b_d(b, dflag);
5200 val = insn_get(env, s, ot);
5202 gen_op_mov_v_reg(s, ot, s->T0, OR_EAX);
5203 tcg_gen_movi_tl(s->T1, val);
5204 gen_op_testl_T0_T1_cc(s);
5205 set_cc_op(s, CC_OP_LOGICB + ot);
5206 break;
5208 case 0x98: /* CWDE/CBW */
5209 switch (dflag) {
5210 #ifdef TARGET_X86_64
5211 case MO_64:
5212 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5213 tcg_gen_ext32s_tl(s->T0, s->T0);
5214 gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0);
5215 break;
5216 #endif
5217 case MO_32:
5218 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5219 tcg_gen_ext16s_tl(s->T0, s->T0);
5220 gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0);
5221 break;
5222 case MO_16:
5223 gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX);
5224 tcg_gen_ext8s_tl(s->T0, s->T0);
5225 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5226 break;
5227 default:
5228 tcg_abort();
5230 break;
5231 case 0x99: /* CDQ/CWD */
5232 switch (dflag) {
5233 #ifdef TARGET_X86_64
5234 case MO_64:
5235 gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX);
5236 tcg_gen_sari_tl(s->T0, s->T0, 63);
5237 gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0);
5238 break;
5239 #endif
5240 case MO_32:
5241 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5242 tcg_gen_ext32s_tl(s->T0, s->T0);
5243 tcg_gen_sari_tl(s->T0, s->T0, 31);
5244 gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0);
5245 break;
5246 case MO_16:
5247 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5248 tcg_gen_ext16s_tl(s->T0, s->T0);
5249 tcg_gen_sari_tl(s->T0, s->T0, 15);
5250 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5251 break;
5252 default:
5253 tcg_abort();
5255 break;
5256 case 0x1af: /* imul Gv, Ev */
5257 case 0x69: /* imul Gv, Ev, I */
5258 case 0x6b:
5259 ot = dflag;
5260 modrm = x86_ldub_code(env, s);
5261 reg = ((modrm >> 3) & 7) | REX_R(s);
5262 if (b == 0x69)
5263 s->rip_offset = insn_const_size(ot);
5264 else if (b == 0x6b)
5265 s->rip_offset = 1;
5266 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5267 if (b == 0x69) {
5268 val = insn_get(env, s, ot);
5269 tcg_gen_movi_tl(s->T1, val);
5270 } else if (b == 0x6b) {
5271 val = (int8_t)insn_get(env, s, MO_8);
5272 tcg_gen_movi_tl(s->T1, val);
5273 } else {
5274 gen_op_mov_v_reg(s, ot, s->T1, reg);
5276 switch (ot) {
5277 #ifdef TARGET_X86_64
5278 case MO_64:
5279 tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1);
5280 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5281 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5282 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1);
5283 break;
5284 #endif
5285 case MO_32:
5286 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5287 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
5288 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5289 s->tmp2_i32, s->tmp3_i32);
5290 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
5291 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5292 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5293 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5294 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5295 break;
5296 default:
5297 tcg_gen_ext16s_tl(s->T0, s->T0);
5298 tcg_gen_ext16s_tl(s->T1, s->T1);
5299 /* XXX: use 32 bit mul which could be faster */
5300 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5301 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5302 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5303 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5304 gen_op_mov_reg_v(s, ot, reg, s->T0);
5305 break;
5307 set_cc_op(s, CC_OP_MULB + ot);
5308 break;
5309 case 0x1c0:
5310 case 0x1c1: /* xadd Ev, Gv */
5311 ot = mo_b_d(b, dflag);
5312 modrm = x86_ldub_code(env, s);
5313 reg = ((modrm >> 3) & 7) | REX_R(s);
5314 mod = (modrm >> 6) & 3;
5315 gen_op_mov_v_reg(s, ot, s->T0, reg);
5316 if (mod == 3) {
5317 rm = (modrm & 7) | REX_B(s);
5318 gen_op_mov_v_reg(s, ot, s->T1, rm);
5319 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5320 gen_op_mov_reg_v(s, ot, reg, s->T1);
5321 gen_op_mov_reg_v(s, ot, rm, s->T0);
5322 } else {
5323 gen_lea_modrm(env, s, modrm);
5324 if (s->prefix & PREFIX_LOCK) {
5325 tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0,
5326 s->mem_index, ot | MO_LE);
5327 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5328 } else {
5329 gen_op_ld_v(s, ot, s->T1, s->A0);
5330 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5331 gen_op_st_v(s, ot, s->T0, s->A0);
5333 gen_op_mov_reg_v(s, ot, reg, s->T1);
5335 gen_op_update2_cc(s);
5336 set_cc_op(s, CC_OP_ADDB + ot);
5337 break;
5338 case 0x1b0:
5339 case 0x1b1: /* cmpxchg Ev, Gv */
5341 TCGv oldv, newv, cmpv;
5343 ot = mo_b_d(b, dflag);
5344 modrm = x86_ldub_code(env, s);
5345 reg = ((modrm >> 3) & 7) | REX_R(s);
5346 mod = (modrm >> 6) & 3;
5347 oldv = tcg_temp_new();
5348 newv = tcg_temp_new();
5349 cmpv = tcg_temp_new();
5350 gen_op_mov_v_reg(s, ot, newv, reg);
5351 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5353 if (s->prefix & PREFIX_LOCK) {
5354 if (mod == 3) {
5355 goto illegal_op;
5357 gen_lea_modrm(env, s, modrm);
5358 tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
5359 s->mem_index, ot | MO_LE);
5360 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5361 } else {
5362 if (mod == 3) {
5363 rm = (modrm & 7) | REX_B(s);
5364 gen_op_mov_v_reg(s, ot, oldv, rm);
5365 } else {
5366 gen_lea_modrm(env, s, modrm);
5367 gen_op_ld_v(s, ot, oldv, s->A0);
5368 rm = 0; /* avoid warning */
5370 gen_extu(ot, oldv);
5371 gen_extu(ot, cmpv);
5372 /* store value = (old == cmp ? new : old); */
5373 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5374 if (mod == 3) {
5375 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5376 gen_op_mov_reg_v(s, ot, rm, newv);
5377 } else {
5378 /* Perform an unconditional store cycle like physical cpu;
5379 must be before changing accumulator to ensure
5380 idempotency if the store faults and the instruction
5381 is restarted */
5382 gen_op_st_v(s, ot, newv, s->A0);
5383 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5386 tcg_gen_mov_tl(cpu_cc_src, oldv);
5387 tcg_gen_mov_tl(s->cc_srcT, cmpv);
5388 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5389 set_cc_op(s, CC_OP_SUBB + ot);
5390 tcg_temp_free(oldv);
5391 tcg_temp_free(newv);
5392 tcg_temp_free(cmpv);
5394 break;
5395 case 0x1c7: /* cmpxchg8b */
5396 modrm = x86_ldub_code(env, s);
5397 mod = (modrm >> 6) & 3;
5398 switch ((modrm >> 3) & 7) {
5399 case 1: /* CMPXCHG8, CMPXCHG16 */
5400 if (mod == 3) {
5401 goto illegal_op;
5403 #ifdef TARGET_X86_64
5404 if (dflag == MO_64) {
5405 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) {
5406 goto illegal_op;
5408 gen_lea_modrm(env, s, modrm);
5409 if ((s->prefix & PREFIX_LOCK) &&
5410 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5411 gen_helper_cmpxchg16b(cpu_env, s->A0);
5412 } else {
5413 gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0);
5415 set_cc_op(s, CC_OP_EFLAGS);
5416 break;
5418 #endif
5419 if (!(s->cpuid_features & CPUID_CX8)) {
5420 goto illegal_op;
5422 gen_lea_modrm(env, s, modrm);
5423 if ((s->prefix & PREFIX_LOCK) &&
5424 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5425 gen_helper_cmpxchg8b(cpu_env, s->A0);
5426 } else {
5427 gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0);
5429 set_cc_op(s, CC_OP_EFLAGS);
5430 break;
5432 case 7: /* RDSEED */
5433 case 6: /* RDRAND */
5434 if (mod != 3 ||
5435 (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
5436 !(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
5437 goto illegal_op;
5439 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5440 gen_io_start();
5442 gen_helper_rdrand(s->T0, cpu_env);
5443 rm = (modrm & 7) | REX_B(s);
5444 gen_op_mov_reg_v(s, dflag, rm, s->T0);
5445 set_cc_op(s, CC_OP_EFLAGS);
5446 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5447 gen_jmp(s, s->pc - s->cs_base);
5449 break;
5451 default:
5452 goto illegal_op;
5454 break;
5456 /**************************/
5457 /* push/pop */
5458 case 0x50 ... 0x57: /* push */
5459 gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s));
5460 gen_push_v(s, s->T0);
5461 break;
5462 case 0x58 ... 0x5f: /* pop */
5463 ot = gen_pop_T0(s);
5464 /* NOTE: order is important for pop %sp */
5465 gen_pop_update(s, ot);
5466 gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0);
5467 break;
5468 case 0x60: /* pusha */
5469 if (CODE64(s))
5470 goto illegal_op;
5471 gen_pusha(s);
5472 break;
5473 case 0x61: /* popa */
5474 if (CODE64(s))
5475 goto illegal_op;
5476 gen_popa(s);
5477 break;
5478 case 0x68: /* push Iv */
5479 case 0x6a:
5480 ot = mo_pushpop(s, dflag);
5481 if (b == 0x68)
5482 val = insn_get(env, s, ot);
5483 else
5484 val = (int8_t)insn_get(env, s, MO_8);
5485 tcg_gen_movi_tl(s->T0, val);
5486 gen_push_v(s, s->T0);
5487 break;
5488 case 0x8f: /* pop Ev */
5489 modrm = x86_ldub_code(env, s);
5490 mod = (modrm >> 6) & 3;
5491 ot = gen_pop_T0(s);
5492 if (mod == 3) {
5493 /* NOTE: order is important for pop %sp */
5494 gen_pop_update(s, ot);
5495 rm = (modrm & 7) | REX_B(s);
5496 gen_op_mov_reg_v(s, ot, rm, s->T0);
5497 } else {
5498 /* NOTE: order is important too for MMU exceptions */
5499 s->popl_esp_hack = 1 << ot;
5500 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5501 s->popl_esp_hack = 0;
5502 gen_pop_update(s, ot);
5504 break;
5505 case 0xc8: /* enter */
5507 int level;
5508 val = x86_lduw_code(env, s);
5509 level = x86_ldub_code(env, s);
5510 gen_enter(s, val, level);
5512 break;
5513 case 0xc9: /* leave */
5514 gen_leave(s);
5515 break;
5516 case 0x06: /* push es */
5517 case 0x0e: /* push cs */
5518 case 0x16: /* push ss */
5519 case 0x1e: /* push ds */
5520 if (CODE64(s))
5521 goto illegal_op;
5522 gen_op_movl_T0_seg(s, b >> 3);
5523 gen_push_v(s, s->T0);
5524 break;
5525 case 0x1a0: /* push fs */
5526 case 0x1a8: /* push gs */
5527 gen_op_movl_T0_seg(s, (b >> 3) & 7);
5528 gen_push_v(s, s->T0);
5529 break;
5530 case 0x07: /* pop es */
5531 case 0x17: /* pop ss */
5532 case 0x1f: /* pop ds */
5533 if (CODE64(s))
5534 goto illegal_op;
5535 reg = b >> 3;
5536 ot = gen_pop_T0(s);
5537 gen_movl_seg_T0(s, reg);
5538 gen_pop_update(s, ot);
5539 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5540 if (s->base.is_jmp) {
5541 gen_jmp_im(s, s->pc - s->cs_base);
5542 if (reg == R_SS) {
5543 s->tf = 0;
5544 gen_eob_inhibit_irq(s, true);
5545 } else {
5546 gen_eob(s);
5549 break;
5550 case 0x1a1: /* pop fs */
5551 case 0x1a9: /* pop gs */
5552 ot = gen_pop_T0(s);
5553 gen_movl_seg_T0(s, (b >> 3) & 7);
5554 gen_pop_update(s, ot);
5555 if (s->base.is_jmp) {
5556 gen_jmp_im(s, s->pc - s->cs_base);
5557 gen_eob(s);
5559 break;
5561 /**************************/
5562 /* mov */
5563 case 0x88:
5564 case 0x89: /* mov Gv, Ev */
5565 ot = mo_b_d(b, dflag);
5566 modrm = x86_ldub_code(env, s);
5567 reg = ((modrm >> 3) & 7) | REX_R(s);
5569 /* generate a generic store */
5570 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5571 break;
5572 case 0xc6:
5573 case 0xc7: /* mov Ev, Iv */
5574 ot = mo_b_d(b, dflag);
5575 modrm = x86_ldub_code(env, s);
5576 mod = (modrm >> 6) & 3;
5577 if (mod != 3) {
5578 s->rip_offset = insn_const_size(ot);
5579 gen_lea_modrm(env, s, modrm);
5581 val = insn_get(env, s, ot);
5582 tcg_gen_movi_tl(s->T0, val);
5583 if (mod != 3) {
5584 gen_op_st_v(s, ot, s->T0, s->A0);
5585 } else {
5586 gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0);
5588 break;
5589 case 0x8a:
5590 case 0x8b: /* mov Ev, Gv */
5591 ot = mo_b_d(b, dflag);
5592 modrm = x86_ldub_code(env, s);
5593 reg = ((modrm >> 3) & 7) | REX_R(s);
5595 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5596 gen_op_mov_reg_v(s, ot, reg, s->T0);
5597 break;
5598 case 0x8e: /* mov seg, Gv */
5599 modrm = x86_ldub_code(env, s);
5600 reg = (modrm >> 3) & 7;
5601 if (reg >= 6 || reg == R_CS)
5602 goto illegal_op;
5603 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5604 gen_movl_seg_T0(s, reg);
5605 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5606 if (s->base.is_jmp) {
5607 gen_jmp_im(s, s->pc - s->cs_base);
5608 if (reg == R_SS) {
5609 s->tf = 0;
5610 gen_eob_inhibit_irq(s, true);
5611 } else {
5612 gen_eob(s);
5615 break;
5616 case 0x8c: /* mov Gv, seg */
5617 modrm = x86_ldub_code(env, s);
5618 reg = (modrm >> 3) & 7;
5619 mod = (modrm >> 6) & 3;
5620 if (reg >= 6)
5621 goto illegal_op;
5622 gen_op_movl_T0_seg(s, reg);
5623 ot = mod == 3 ? dflag : MO_16;
5624 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5625 break;
5627 case 0x1b6: /* movzbS Gv, Eb */
5628 case 0x1b7: /* movzwS Gv, Eb */
5629 case 0x1be: /* movsbS Gv, Eb */
5630 case 0x1bf: /* movswS Gv, Eb */
5632 MemOp d_ot;
5633 MemOp s_ot;
5635 /* d_ot is the size of destination */
5636 d_ot = dflag;
5637 /* ot is the size of source */
5638 ot = (b & 1) + MO_8;
5639 /* s_ot is the sign+size of source */
5640 s_ot = b & 8 ? MO_SIGN | ot : ot;
5642 modrm = x86_ldub_code(env, s);
5643 reg = ((modrm >> 3) & 7) | REX_R(s);
5644 mod = (modrm >> 6) & 3;
5645 rm = (modrm & 7) | REX_B(s);
5647 if (mod == 3) {
5648 if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) {
5649 tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8);
5650 } else {
5651 gen_op_mov_v_reg(s, ot, s->T0, rm);
5652 switch (s_ot) {
5653 case MO_UB:
5654 tcg_gen_ext8u_tl(s->T0, s->T0);
5655 break;
5656 case MO_SB:
5657 tcg_gen_ext8s_tl(s->T0, s->T0);
5658 break;
5659 case MO_UW:
5660 tcg_gen_ext16u_tl(s->T0, s->T0);
5661 break;
5662 default:
5663 case MO_SW:
5664 tcg_gen_ext16s_tl(s->T0, s->T0);
5665 break;
5668 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5669 } else {
5670 gen_lea_modrm(env, s, modrm);
5671 gen_op_ld_v(s, s_ot, s->T0, s->A0);
5672 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5675 break;
5677 case 0x8d: /* lea */
5678 modrm = x86_ldub_code(env, s);
5679 mod = (modrm >> 6) & 3;
5680 if (mod == 3)
5681 goto illegal_op;
5682 reg = ((modrm >> 3) & 7) | REX_R(s);
5684 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5685 TCGv ea = gen_lea_modrm_1(s, a);
5686 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5687 gen_op_mov_reg_v(s, dflag, reg, s->A0);
5689 break;
5691 case 0xa0: /* mov EAX, Ov */
5692 case 0xa1:
5693 case 0xa2: /* mov Ov, EAX */
5694 case 0xa3:
5696 target_ulong offset_addr;
5698 ot = mo_b_d(b, dflag);
5699 switch (s->aflag) {
5700 #ifdef TARGET_X86_64
5701 case MO_64:
5702 offset_addr = x86_ldq_code(env, s);
5703 break;
5704 #endif
5705 default:
5706 offset_addr = insn_get(env, s, s->aflag);
5707 break;
5709 tcg_gen_movi_tl(s->A0, offset_addr);
5710 gen_add_A0_ds_seg(s);
5711 if ((b & 2) == 0) {
5712 gen_op_ld_v(s, ot, s->T0, s->A0);
5713 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
5714 } else {
5715 gen_op_mov_v_reg(s, ot, s->T0, R_EAX);
5716 gen_op_st_v(s, ot, s->T0, s->A0);
5719 break;
5720 case 0xd7: /* xlat */
5721 tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]);
5722 tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]);
5723 tcg_gen_add_tl(s->A0, s->A0, s->T0);
5724 gen_extu(s->aflag, s->A0);
5725 gen_add_A0_ds_seg(s);
5726 gen_op_ld_v(s, MO_8, s->T0, s->A0);
5727 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
5728 break;
5729 case 0xb0 ... 0xb7: /* mov R, Ib */
5730 val = insn_get(env, s, MO_8);
5731 tcg_gen_movi_tl(s->T0, val);
5732 gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0);
5733 break;
5734 case 0xb8 ... 0xbf: /* mov R, Iv */
5735 #ifdef TARGET_X86_64
5736 if (dflag == MO_64) {
5737 uint64_t tmp;
5738 /* 64 bit case */
5739 tmp = x86_ldq_code(env, s);
5740 reg = (b & 7) | REX_B(s);
5741 tcg_gen_movi_tl(s->T0, tmp);
5742 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
5743 } else
5744 #endif
5746 ot = dflag;
5747 val = insn_get(env, s, ot);
5748 reg = (b & 7) | REX_B(s);
5749 tcg_gen_movi_tl(s->T0, val);
5750 gen_op_mov_reg_v(s, ot, reg, s->T0);
5752 break;
5754 case 0x91 ... 0x97: /* xchg R, EAX */
5755 do_xchg_reg_eax:
5756 ot = dflag;
5757 reg = (b & 7) | REX_B(s);
5758 rm = R_EAX;
5759 goto do_xchg_reg;
5760 case 0x86:
5761 case 0x87: /* xchg Ev, Gv */
5762 ot = mo_b_d(b, dflag);
5763 modrm = x86_ldub_code(env, s);
5764 reg = ((modrm >> 3) & 7) | REX_R(s);
5765 mod = (modrm >> 6) & 3;
5766 if (mod == 3) {
5767 rm = (modrm & 7) | REX_B(s);
5768 do_xchg_reg:
5769 gen_op_mov_v_reg(s, ot, s->T0, reg);
5770 gen_op_mov_v_reg(s, ot, s->T1, rm);
5771 gen_op_mov_reg_v(s, ot, rm, s->T0);
5772 gen_op_mov_reg_v(s, ot, reg, s->T1);
5773 } else {
5774 gen_lea_modrm(env, s, modrm);
5775 gen_op_mov_v_reg(s, ot, s->T0, reg);
5776 /* for xchg, lock is implicit */
5777 tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0,
5778 s->mem_index, ot | MO_LE);
5779 gen_op_mov_reg_v(s, ot, reg, s->T1);
5781 break;
5782 case 0xc4: /* les Gv */
5783 /* In CODE64 this is VEX3; see above. */
5784 op = R_ES;
5785 goto do_lxx;
5786 case 0xc5: /* lds Gv */
5787 /* In CODE64 this is VEX2; see above. */
5788 op = R_DS;
5789 goto do_lxx;
5790 case 0x1b2: /* lss Gv */
5791 op = R_SS;
5792 goto do_lxx;
5793 case 0x1b4: /* lfs Gv */
5794 op = R_FS;
5795 goto do_lxx;
5796 case 0x1b5: /* lgs Gv */
5797 op = R_GS;
5798 do_lxx:
5799 ot = dflag != MO_16 ? MO_32 : MO_16;
5800 modrm = x86_ldub_code(env, s);
5801 reg = ((modrm >> 3) & 7) | REX_R(s);
5802 mod = (modrm >> 6) & 3;
5803 if (mod == 3)
5804 goto illegal_op;
5805 gen_lea_modrm(env, s, modrm);
5806 gen_op_ld_v(s, ot, s->T1, s->A0);
5807 gen_add_A0_im(s, 1 << ot);
5808 /* load the segment first to handle exceptions properly */
5809 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5810 gen_movl_seg_T0(s, op);
5811 /* then put the data */
5812 gen_op_mov_reg_v(s, ot, reg, s->T1);
5813 if (s->base.is_jmp) {
5814 gen_jmp_im(s, s->pc - s->cs_base);
5815 gen_eob(s);
5817 break;
5819 /************************/
5820 /* shifts */
5821 case 0xc0:
5822 case 0xc1:
5823 /* shift Ev,Ib */
5824 shift = 2;
5825 grp2:
5827 ot = mo_b_d(b, dflag);
5828 modrm = x86_ldub_code(env, s);
5829 mod = (modrm >> 6) & 3;
5830 op = (modrm >> 3) & 7;
5832 if (mod != 3) {
5833 if (shift == 2) {
5834 s->rip_offset = 1;
5836 gen_lea_modrm(env, s, modrm);
5837 opreg = OR_TMP0;
5838 } else {
5839 opreg = (modrm & 7) | REX_B(s);
5842 /* simpler op */
5843 if (shift == 0) {
5844 gen_shift(s, op, ot, opreg, OR_ECX);
5845 } else {
5846 if (shift == 2) {
5847 shift = x86_ldub_code(env, s);
5849 gen_shifti(s, op, ot, opreg, shift);
5852 break;
5853 case 0xd0:
5854 case 0xd1:
5855 /* shift Ev,1 */
5856 shift = 1;
5857 goto grp2;
5858 case 0xd2:
5859 case 0xd3:
5860 /* shift Ev,cl */
5861 shift = 0;
5862 goto grp2;
5864 case 0x1a4: /* shld imm */
5865 op = 0;
5866 shift = 1;
5867 goto do_shiftd;
5868 case 0x1a5: /* shld cl */
5869 op = 0;
5870 shift = 0;
5871 goto do_shiftd;
5872 case 0x1ac: /* shrd imm */
5873 op = 1;
5874 shift = 1;
5875 goto do_shiftd;
5876 case 0x1ad: /* shrd cl */
5877 op = 1;
5878 shift = 0;
5879 do_shiftd:
5880 ot = dflag;
5881 modrm = x86_ldub_code(env, s);
5882 mod = (modrm >> 6) & 3;
5883 rm = (modrm & 7) | REX_B(s);
5884 reg = ((modrm >> 3) & 7) | REX_R(s);
5885 if (mod != 3) {
5886 gen_lea_modrm(env, s, modrm);
5887 opreg = OR_TMP0;
5888 } else {
5889 opreg = rm;
5891 gen_op_mov_v_reg(s, ot, s->T1, reg);
5893 if (shift) {
5894 TCGv imm = tcg_const_tl(x86_ldub_code(env, s));
5895 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5896 tcg_temp_free(imm);
5897 } else {
5898 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5900 break;
5902 /************************/
5903 /* floats */
5904 case 0xd8 ... 0xdf:
5905 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5906 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5907 /* XXX: what to do if illegal op ? */
5908 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5909 break;
5911 modrm = x86_ldub_code(env, s);
5912 mod = (modrm >> 6) & 3;
5913 rm = modrm & 7;
5914 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5915 if (mod != 3) {
5916 /* memory op */
5917 gen_lea_modrm(env, s, modrm);
5918 switch(op) {
5919 case 0x00 ... 0x07: /* fxxxs */
5920 case 0x10 ... 0x17: /* fixxxl */
5921 case 0x20 ... 0x27: /* fxxxl */
5922 case 0x30 ... 0x37: /* fixxx */
5924 int op1;
5925 op1 = op & 7;
5927 switch(op >> 4) {
5928 case 0:
5929 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5930 s->mem_index, MO_LEUL);
5931 gen_helper_flds_FT0(cpu_env, s->tmp2_i32);
5932 break;
5933 case 1:
5934 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5935 s->mem_index, MO_LEUL);
5936 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5937 break;
5938 case 2:
5939 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5940 s->mem_index, MO_LEQ);
5941 gen_helper_fldl_FT0(cpu_env, s->tmp1_i64);
5942 break;
5943 case 3:
5944 default:
5945 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5946 s->mem_index, MO_LESW);
5947 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5948 break;
5951 gen_helper_fp_arith_ST0_FT0(op1);
5952 if (op1 == 3) {
5953 /* fcomp needs pop */
5954 gen_helper_fpop(cpu_env);
5957 break;
5958 case 0x08: /* flds */
5959 case 0x0a: /* fsts */
5960 case 0x0b: /* fstps */
5961 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5962 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5963 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5964 switch(op & 7) {
5965 case 0:
5966 switch(op >> 4) {
5967 case 0:
5968 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5969 s->mem_index, MO_LEUL);
5970 gen_helper_flds_ST0(cpu_env, s->tmp2_i32);
5971 break;
5972 case 1:
5973 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5974 s->mem_index, MO_LEUL);
5975 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
5976 break;
5977 case 2:
5978 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5979 s->mem_index, MO_LEQ);
5980 gen_helper_fldl_ST0(cpu_env, s->tmp1_i64);
5981 break;
5982 case 3:
5983 default:
5984 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5985 s->mem_index, MO_LESW);
5986 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
5987 break;
5989 break;
5990 case 1:
5991 /* XXX: the corresponding CPUID bit must be tested ! */
5992 switch(op >> 4) {
5993 case 1:
5994 gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env);
5995 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5996 s->mem_index, MO_LEUL);
5997 break;
5998 case 2:
5999 gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env);
6000 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6001 s->mem_index, MO_LEQ);
6002 break;
6003 case 3:
6004 default:
6005 gen_helper_fistt_ST0(s->tmp2_i32, cpu_env);
6006 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6007 s->mem_index, MO_LEUW);
6008 break;
6010 gen_helper_fpop(cpu_env);
6011 break;
6012 default:
6013 switch(op >> 4) {
6014 case 0:
6015 gen_helper_fsts_ST0(s->tmp2_i32, cpu_env);
6016 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6017 s->mem_index, MO_LEUL);
6018 break;
6019 case 1:
6020 gen_helper_fistl_ST0(s->tmp2_i32, cpu_env);
6021 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6022 s->mem_index, MO_LEUL);
6023 break;
6024 case 2:
6025 gen_helper_fstl_ST0(s->tmp1_i64, cpu_env);
6026 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6027 s->mem_index, MO_LEQ);
6028 break;
6029 case 3:
6030 default:
6031 gen_helper_fist_ST0(s->tmp2_i32, cpu_env);
6032 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6033 s->mem_index, MO_LEUW);
6034 break;
6036 if ((op & 7) == 3)
6037 gen_helper_fpop(cpu_env);
6038 break;
6040 break;
6041 case 0x0c: /* fldenv mem */
6042 gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6043 break;
6044 case 0x0d: /* fldcw mem */
6045 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6046 s->mem_index, MO_LEUW);
6047 gen_helper_fldcw(cpu_env, s->tmp2_i32);
6048 break;
6049 case 0x0e: /* fnstenv mem */
6050 gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6051 break;
6052 case 0x0f: /* fnstcw mem */
6053 gen_helper_fnstcw(s->tmp2_i32, cpu_env);
6054 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6055 s->mem_index, MO_LEUW);
6056 break;
6057 case 0x1d: /* fldt mem */
6058 gen_helper_fldt_ST0(cpu_env, s->A0);
6059 break;
6060 case 0x1f: /* fstpt mem */
6061 gen_helper_fstt_ST0(cpu_env, s->A0);
6062 gen_helper_fpop(cpu_env);
6063 break;
6064 case 0x2c: /* frstor mem */
6065 gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6066 break;
6067 case 0x2e: /* fnsave mem */
6068 gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6069 break;
6070 case 0x2f: /* fnstsw mem */
6071 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6072 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6073 s->mem_index, MO_LEUW);
6074 break;
6075 case 0x3c: /* fbld */
6076 gen_helper_fbld_ST0(cpu_env, s->A0);
6077 break;
6078 case 0x3e: /* fbstp */
6079 gen_helper_fbst_ST0(cpu_env, s->A0);
6080 gen_helper_fpop(cpu_env);
6081 break;
6082 case 0x3d: /* fildll */
6083 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6084 gen_helper_fildll_ST0(cpu_env, s->tmp1_i64);
6085 break;
6086 case 0x3f: /* fistpll */
6087 gen_helper_fistll_ST0(s->tmp1_i64, cpu_env);
6088 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6089 gen_helper_fpop(cpu_env);
6090 break;
6091 default:
6092 goto unknown_op;
6094 } else {
6095 /* register float ops */
6096 opreg = rm;
6098 switch(op) {
6099 case 0x08: /* fld sti */
6100 gen_helper_fpush(cpu_env);
6101 gen_helper_fmov_ST0_STN(cpu_env,
6102 tcg_const_i32((opreg + 1) & 7));
6103 break;
6104 case 0x09: /* fxchg sti */
6105 case 0x29: /* fxchg4 sti, undocumented op */
6106 case 0x39: /* fxchg7 sti, undocumented op */
6107 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
6108 break;
6109 case 0x0a: /* grp d9/2 */
6110 switch(rm) {
6111 case 0: /* fnop */
6112 /* check exceptions (FreeBSD FPU probe) */
6113 gen_helper_fwait(cpu_env);
6114 break;
6115 default:
6116 goto unknown_op;
6118 break;
6119 case 0x0c: /* grp d9/4 */
6120 switch(rm) {
6121 case 0: /* fchs */
6122 gen_helper_fchs_ST0(cpu_env);
6123 break;
6124 case 1: /* fabs */
6125 gen_helper_fabs_ST0(cpu_env);
6126 break;
6127 case 4: /* ftst */
6128 gen_helper_fldz_FT0(cpu_env);
6129 gen_helper_fcom_ST0_FT0(cpu_env);
6130 break;
6131 case 5: /* fxam */
6132 gen_helper_fxam_ST0(cpu_env);
6133 break;
6134 default:
6135 goto unknown_op;
6137 break;
6138 case 0x0d: /* grp d9/5 */
6140 switch(rm) {
6141 case 0:
6142 gen_helper_fpush(cpu_env);
6143 gen_helper_fld1_ST0(cpu_env);
6144 break;
6145 case 1:
6146 gen_helper_fpush(cpu_env);
6147 gen_helper_fldl2t_ST0(cpu_env);
6148 break;
6149 case 2:
6150 gen_helper_fpush(cpu_env);
6151 gen_helper_fldl2e_ST0(cpu_env);
6152 break;
6153 case 3:
6154 gen_helper_fpush(cpu_env);
6155 gen_helper_fldpi_ST0(cpu_env);
6156 break;
6157 case 4:
6158 gen_helper_fpush(cpu_env);
6159 gen_helper_fldlg2_ST0(cpu_env);
6160 break;
6161 case 5:
6162 gen_helper_fpush(cpu_env);
6163 gen_helper_fldln2_ST0(cpu_env);
6164 break;
6165 case 6:
6166 gen_helper_fpush(cpu_env);
6167 gen_helper_fldz_ST0(cpu_env);
6168 break;
6169 default:
6170 goto unknown_op;
6173 break;
6174 case 0x0e: /* grp d9/6 */
6175 switch(rm) {
6176 case 0: /* f2xm1 */
6177 gen_helper_f2xm1(cpu_env);
6178 break;
6179 case 1: /* fyl2x */
6180 gen_helper_fyl2x(cpu_env);
6181 break;
6182 case 2: /* fptan */
6183 gen_helper_fptan(cpu_env);
6184 break;
6185 case 3: /* fpatan */
6186 gen_helper_fpatan(cpu_env);
6187 break;
6188 case 4: /* fxtract */
6189 gen_helper_fxtract(cpu_env);
6190 break;
6191 case 5: /* fprem1 */
6192 gen_helper_fprem1(cpu_env);
6193 break;
6194 case 6: /* fdecstp */
6195 gen_helper_fdecstp(cpu_env);
6196 break;
6197 default:
6198 case 7: /* fincstp */
6199 gen_helper_fincstp(cpu_env);
6200 break;
6202 break;
6203 case 0x0f: /* grp d9/7 */
6204 switch(rm) {
6205 case 0: /* fprem */
6206 gen_helper_fprem(cpu_env);
6207 break;
6208 case 1: /* fyl2xp1 */
6209 gen_helper_fyl2xp1(cpu_env);
6210 break;
6211 case 2: /* fsqrt */
6212 gen_helper_fsqrt(cpu_env);
6213 break;
6214 case 3: /* fsincos */
6215 gen_helper_fsincos(cpu_env);
6216 break;
6217 case 5: /* fscale */
6218 gen_helper_fscale(cpu_env);
6219 break;
6220 case 4: /* frndint */
6221 gen_helper_frndint(cpu_env);
6222 break;
6223 case 6: /* fsin */
6224 gen_helper_fsin(cpu_env);
6225 break;
6226 default:
6227 case 7: /* fcos */
6228 gen_helper_fcos(cpu_env);
6229 break;
6231 break;
6232 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6233 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6234 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6236 int op1;
6238 op1 = op & 7;
6239 if (op >= 0x20) {
6240 gen_helper_fp_arith_STN_ST0(op1, opreg);
6241 if (op >= 0x30)
6242 gen_helper_fpop(cpu_env);
6243 } else {
6244 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6245 gen_helper_fp_arith_ST0_FT0(op1);
6248 break;
6249 case 0x02: /* fcom */
6250 case 0x22: /* fcom2, undocumented op */
6251 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6252 gen_helper_fcom_ST0_FT0(cpu_env);
6253 break;
6254 case 0x03: /* fcomp */
6255 case 0x23: /* fcomp3, undocumented op */
6256 case 0x32: /* fcomp5, undocumented op */
6257 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6258 gen_helper_fcom_ST0_FT0(cpu_env);
6259 gen_helper_fpop(cpu_env);
6260 break;
6261 case 0x15: /* da/5 */
6262 switch(rm) {
6263 case 1: /* fucompp */
6264 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6265 gen_helper_fucom_ST0_FT0(cpu_env);
6266 gen_helper_fpop(cpu_env);
6267 gen_helper_fpop(cpu_env);
6268 break;
6269 default:
6270 goto unknown_op;
6272 break;
6273 case 0x1c:
6274 switch(rm) {
6275 case 0: /* feni (287 only, just do nop here) */
6276 break;
6277 case 1: /* fdisi (287 only, just do nop here) */
6278 break;
6279 case 2: /* fclex */
6280 gen_helper_fclex(cpu_env);
6281 break;
6282 case 3: /* fninit */
6283 gen_helper_fninit(cpu_env);
6284 break;
6285 case 4: /* fsetpm (287 only, just do nop here) */
6286 break;
6287 default:
6288 goto unknown_op;
6290 break;
6291 case 0x1d: /* fucomi */
6292 if (!(s->cpuid_features & CPUID_CMOV)) {
6293 goto illegal_op;
6295 gen_update_cc_op(s);
6296 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6297 gen_helper_fucomi_ST0_FT0(cpu_env);
6298 set_cc_op(s, CC_OP_EFLAGS);
6299 break;
6300 case 0x1e: /* fcomi */
6301 if (!(s->cpuid_features & CPUID_CMOV)) {
6302 goto illegal_op;
6304 gen_update_cc_op(s);
6305 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6306 gen_helper_fcomi_ST0_FT0(cpu_env);
6307 set_cc_op(s, CC_OP_EFLAGS);
6308 break;
6309 case 0x28: /* ffree sti */
6310 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6311 break;
6312 case 0x2a: /* fst sti */
6313 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6314 break;
6315 case 0x2b: /* fstp sti */
6316 case 0x0b: /* fstp1 sti, undocumented op */
6317 case 0x3a: /* fstp8 sti, undocumented op */
6318 case 0x3b: /* fstp9 sti, undocumented op */
6319 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6320 gen_helper_fpop(cpu_env);
6321 break;
6322 case 0x2c: /* fucom st(i) */
6323 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6324 gen_helper_fucom_ST0_FT0(cpu_env);
6325 break;
6326 case 0x2d: /* fucomp st(i) */
6327 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6328 gen_helper_fucom_ST0_FT0(cpu_env);
6329 gen_helper_fpop(cpu_env);
6330 break;
6331 case 0x33: /* de/3 */
6332 switch(rm) {
6333 case 1: /* fcompp */
6334 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6335 gen_helper_fcom_ST0_FT0(cpu_env);
6336 gen_helper_fpop(cpu_env);
6337 gen_helper_fpop(cpu_env);
6338 break;
6339 default:
6340 goto unknown_op;
6342 break;
6343 case 0x38: /* ffreep sti, undocumented op */
6344 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6345 gen_helper_fpop(cpu_env);
6346 break;
6347 case 0x3c: /* df/4 */
6348 switch(rm) {
6349 case 0:
6350 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6351 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
6352 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
6353 break;
6354 default:
6355 goto unknown_op;
6357 break;
6358 case 0x3d: /* fucomip */
6359 if (!(s->cpuid_features & CPUID_CMOV)) {
6360 goto illegal_op;
6362 gen_update_cc_op(s);
6363 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6364 gen_helper_fucomi_ST0_FT0(cpu_env);
6365 gen_helper_fpop(cpu_env);
6366 set_cc_op(s, CC_OP_EFLAGS);
6367 break;
6368 case 0x3e: /* fcomip */
6369 if (!(s->cpuid_features & CPUID_CMOV)) {
6370 goto illegal_op;
6372 gen_update_cc_op(s);
6373 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6374 gen_helper_fcomi_ST0_FT0(cpu_env);
6375 gen_helper_fpop(cpu_env);
6376 set_cc_op(s, CC_OP_EFLAGS);
6377 break;
6378 case 0x10 ... 0x13: /* fcmovxx */
6379 case 0x18 ... 0x1b:
6381 int op1;
6382 TCGLabel *l1;
6383 static const uint8_t fcmov_cc[8] = {
6384 (JCC_B << 1),
6385 (JCC_Z << 1),
6386 (JCC_BE << 1),
6387 (JCC_P << 1),
6390 if (!(s->cpuid_features & CPUID_CMOV)) {
6391 goto illegal_op;
6393 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6394 l1 = gen_new_label();
6395 gen_jcc1_noeob(s, op1, l1);
6396 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6397 gen_set_label(l1);
6399 break;
6400 default:
6401 goto unknown_op;
6404 break;
6405 /************************/
6406 /* string ops */
6408 case 0xa4: /* movsS */
6409 case 0xa5:
6410 ot = mo_b_d(b, dflag);
6411 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6412 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6413 } else {
6414 gen_movs(s, ot);
6416 break;
6418 case 0xaa: /* stosS */
6419 case 0xab:
6420 ot = mo_b_d(b, dflag);
6421 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6422 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6423 } else {
6424 gen_stos(s, ot);
6426 break;
6427 case 0xac: /* lodsS */
6428 case 0xad:
6429 ot = mo_b_d(b, dflag);
6430 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6431 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6432 } else {
6433 gen_lods(s, ot);
6435 break;
6436 case 0xae: /* scasS */
6437 case 0xaf:
6438 ot = mo_b_d(b, dflag);
6439 if (prefixes & PREFIX_REPNZ) {
6440 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6441 } else if (prefixes & PREFIX_REPZ) {
6442 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6443 } else {
6444 gen_scas(s, ot);
6446 break;
6448 case 0xa6: /* cmpsS */
6449 case 0xa7:
6450 ot = mo_b_d(b, dflag);
6451 if (prefixes & PREFIX_REPNZ) {
6452 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6453 } else if (prefixes & PREFIX_REPZ) {
6454 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6455 } else {
6456 gen_cmps(s, ot);
6458 break;
6459 case 0x6c: /* insS */
6460 case 0x6d:
6461 ot = mo_b_d32(b, dflag);
6462 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6463 gen_check_io(s, ot, pc_start - s->cs_base,
6464 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6465 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6466 gen_io_start();
6468 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6469 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6470 /* jump generated by gen_repz_ins */
6471 } else {
6472 gen_ins(s, ot);
6473 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6474 gen_jmp(s, s->pc - s->cs_base);
6477 break;
6478 case 0x6e: /* outsS */
6479 case 0x6f:
6480 ot = mo_b_d32(b, dflag);
6481 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6482 gen_check_io(s, ot, pc_start - s->cs_base,
6483 svm_is_rep(prefixes) | 4);
6484 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6485 gen_io_start();
6487 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6488 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6489 /* jump generated by gen_repz_outs */
6490 } else {
6491 gen_outs(s, ot);
6492 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6493 gen_jmp(s, s->pc - s->cs_base);
6496 break;
6498 /************************/
6499 /* port I/O */
6501 case 0xe4:
6502 case 0xe5:
6503 ot = mo_b_d32(b, dflag);
6504 val = x86_ldub_code(env, s);
6505 tcg_gen_movi_tl(s->T0, val);
6506 gen_check_io(s, ot, pc_start - s->cs_base,
6507 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6508 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6509 gen_io_start();
6511 tcg_gen_movi_i32(s->tmp2_i32, val);
6512 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6513 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6514 gen_bpt_io(s, s->tmp2_i32, ot);
6515 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6516 gen_jmp(s, s->pc - s->cs_base);
6518 break;
6519 case 0xe6:
6520 case 0xe7:
6521 ot = mo_b_d32(b, dflag);
6522 val = x86_ldub_code(env, s);
6523 tcg_gen_movi_tl(s->T0, val);
6524 gen_check_io(s, ot, pc_start - s->cs_base,
6525 svm_is_rep(prefixes));
6526 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6528 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6529 gen_io_start();
6531 tcg_gen_movi_i32(s->tmp2_i32, val);
6532 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6533 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6534 gen_bpt_io(s, s->tmp2_i32, ot);
6535 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6536 gen_jmp(s, s->pc - s->cs_base);
6538 break;
6539 case 0xec:
6540 case 0xed:
6541 ot = mo_b_d32(b, dflag);
6542 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6543 gen_check_io(s, ot, pc_start - s->cs_base,
6544 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6545 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6546 gen_io_start();
6548 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
6549 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6550 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6551 gen_bpt_io(s, s->tmp2_i32, ot);
6552 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6553 gen_jmp(s, s->pc - s->cs_base);
6555 break;
6556 case 0xee:
6557 case 0xef:
6558 ot = mo_b_d32(b, dflag);
6559 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6560 gen_check_io(s, ot, pc_start - s->cs_base,
6561 svm_is_rep(prefixes));
6562 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6564 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6565 gen_io_start();
6567 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
6568 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6569 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6570 gen_bpt_io(s, s->tmp2_i32, ot);
6571 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6572 gen_jmp(s, s->pc - s->cs_base);
6574 break;
6576 /************************/
6577 /* control */
6578 case 0xc2: /* ret im */
6579 val = x86_ldsw_code(env, s);
6580 ot = gen_pop_T0(s);
6581 gen_stack_update(s, val + (1 << ot));
6582 /* Note that gen_pop_T0 uses a zero-extending load. */
6583 gen_op_jmp_v(s->T0);
6584 gen_bnd_jmp(s);
6585 gen_jr(s, s->T0);
6586 break;
6587 case 0xc3: /* ret */
6588 ot = gen_pop_T0(s);
6589 gen_pop_update(s, ot);
6590 /* Note that gen_pop_T0 uses a zero-extending load. */
6591 gen_op_jmp_v(s->T0);
6592 gen_bnd_jmp(s);
6593 gen_jr(s, s->T0);
6594 break;
6595 case 0xca: /* lret im */
6596 val = x86_ldsw_code(env, s);
6597 do_lret:
6598 if (PE(s) && !VM86(s)) {
6599 gen_update_cc_op(s);
6600 gen_jmp_im(s, pc_start - s->cs_base);
6601 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6602 tcg_const_i32(val));
6603 } else {
6604 gen_stack_A0(s);
6605 /* pop offset */
6606 gen_op_ld_v(s, dflag, s->T0, s->A0);
6607 /* NOTE: keeping EIP updated is not a problem in case of
6608 exception */
6609 gen_op_jmp_v(s->T0);
6610 /* pop selector */
6611 gen_add_A0_im(s, 1 << dflag);
6612 gen_op_ld_v(s, dflag, s->T0, s->A0);
6613 gen_op_movl_seg_T0_vm(s, R_CS);
6614 /* add stack offset */
6615 gen_stack_update(s, val + (2 << dflag));
6617 gen_eob(s);
6618 break;
6619 case 0xcb: /* lret */
6620 val = 0;
6621 goto do_lret;
6622 case 0xcf: /* iret */
6623 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6624 if (!PE(s) || VM86(s)) {
6625 /* real mode or vm86 mode */
6626 if (!check_vm86_iopl(s)) {
6627 break;
6629 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6630 } else {
6631 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6632 tcg_const_i32(s->pc - s->cs_base));
6634 set_cc_op(s, CC_OP_EFLAGS);
6635 gen_eob(s);
6636 break;
6637 case 0xe8: /* call im */
6639 if (dflag != MO_16) {
6640 tval = (int32_t)insn_get(env, s, MO_32);
6641 } else {
6642 tval = (int16_t)insn_get(env, s, MO_16);
6644 next_eip = s->pc - s->cs_base;
6645 tval += next_eip;
6646 if (dflag == MO_16) {
6647 tval &= 0xffff;
6648 } else if (!CODE64(s)) {
6649 tval &= 0xffffffff;
6651 tcg_gen_movi_tl(s->T0, next_eip);
6652 gen_push_v(s, s->T0);
6653 gen_bnd_jmp(s);
6654 gen_jmp(s, tval);
6656 break;
6657 case 0x9a: /* lcall im */
6659 unsigned int selector, offset;
6661 if (CODE64(s))
6662 goto illegal_op;
6663 ot = dflag;
6664 offset = insn_get(env, s, ot);
6665 selector = insn_get(env, s, MO_16);
6667 tcg_gen_movi_tl(s->T0, selector);
6668 tcg_gen_movi_tl(s->T1, offset);
6670 goto do_lcall;
6671 case 0xe9: /* jmp im */
6672 if (dflag != MO_16) {
6673 tval = (int32_t)insn_get(env, s, MO_32);
6674 } else {
6675 tval = (int16_t)insn_get(env, s, MO_16);
6677 tval += s->pc - s->cs_base;
6678 if (dflag == MO_16) {
6679 tval &= 0xffff;
6680 } else if (!CODE64(s)) {
6681 tval &= 0xffffffff;
6683 gen_bnd_jmp(s);
6684 gen_jmp(s, tval);
6685 break;
6686 case 0xea: /* ljmp im */
6688 unsigned int selector, offset;
6690 if (CODE64(s))
6691 goto illegal_op;
6692 ot = dflag;
6693 offset = insn_get(env, s, ot);
6694 selector = insn_get(env, s, MO_16);
6696 tcg_gen_movi_tl(s->T0, selector);
6697 tcg_gen_movi_tl(s->T1, offset);
6699 goto do_ljmp;
6700 case 0xeb: /* jmp Jb */
6701 tval = (int8_t)insn_get(env, s, MO_8);
6702 tval += s->pc - s->cs_base;
6703 if (dflag == MO_16) {
6704 tval &= 0xffff;
6706 gen_jmp(s, tval);
6707 break;
6708 case 0x70 ... 0x7f: /* jcc Jb */
6709 tval = (int8_t)insn_get(env, s, MO_8);
6710 goto do_jcc;
6711 case 0x180 ... 0x18f: /* jcc Jv */
6712 if (dflag != MO_16) {
6713 tval = (int32_t)insn_get(env, s, MO_32);
6714 } else {
6715 tval = (int16_t)insn_get(env, s, MO_16);
6717 do_jcc:
6718 next_eip = s->pc - s->cs_base;
6719 tval += next_eip;
6720 if (dflag == MO_16) {
6721 tval &= 0xffff;
6723 gen_bnd_jmp(s);
6724 gen_jcc(s, b, tval, next_eip);
6725 break;
6727 case 0x190 ... 0x19f: /* setcc Gv */
6728 modrm = x86_ldub_code(env, s);
6729 gen_setcc1(s, b, s->T0);
6730 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6731 break;
6732 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6733 if (!(s->cpuid_features & CPUID_CMOV)) {
6734 goto illegal_op;
6736 ot = dflag;
6737 modrm = x86_ldub_code(env, s);
6738 reg = ((modrm >> 3) & 7) | REX_R(s);
6739 gen_cmovcc1(env, s, ot, b, modrm, reg);
6740 break;
6742 /************************/
6743 /* flags */
6744 case 0x9c: /* pushf */
6745 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6746 if (check_vm86_iopl(s)) {
6747 gen_update_cc_op(s);
6748 gen_helper_read_eflags(s->T0, cpu_env);
6749 gen_push_v(s, s->T0);
6751 break;
6752 case 0x9d: /* popf */
6753 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6754 if (check_vm86_iopl(s)) {
6755 ot = gen_pop_T0(s);
6756 if (CPL(s) == 0) {
6757 if (dflag != MO_16) {
6758 gen_helper_write_eflags(cpu_env, s->T0,
6759 tcg_const_i32((TF_MASK | AC_MASK |
6760 ID_MASK | NT_MASK |
6761 IF_MASK |
6762 IOPL_MASK)));
6763 } else {
6764 gen_helper_write_eflags(cpu_env, s->T0,
6765 tcg_const_i32((TF_MASK | AC_MASK |
6766 ID_MASK | NT_MASK |
6767 IF_MASK | IOPL_MASK)
6768 & 0xffff));
6770 } else {
6771 if (CPL(s) <= IOPL(s)) {
6772 if (dflag != MO_16) {
6773 gen_helper_write_eflags(cpu_env, s->T0,
6774 tcg_const_i32((TF_MASK |
6775 AC_MASK |
6776 ID_MASK |
6777 NT_MASK |
6778 IF_MASK)));
6779 } else {
6780 gen_helper_write_eflags(cpu_env, s->T0,
6781 tcg_const_i32((TF_MASK |
6782 AC_MASK |
6783 ID_MASK |
6784 NT_MASK |
6785 IF_MASK)
6786 & 0xffff));
6788 } else {
6789 if (dflag != MO_16) {
6790 gen_helper_write_eflags(cpu_env, s->T0,
6791 tcg_const_i32((TF_MASK | AC_MASK |
6792 ID_MASK | NT_MASK)));
6793 } else {
6794 gen_helper_write_eflags(cpu_env, s->T0,
6795 tcg_const_i32((TF_MASK | AC_MASK |
6796 ID_MASK | NT_MASK)
6797 & 0xffff));
6801 gen_pop_update(s, ot);
6802 set_cc_op(s, CC_OP_EFLAGS);
6803 /* abort translation because TF/AC flag may change */
6804 gen_jmp_im(s, s->pc - s->cs_base);
6805 gen_eob(s);
6807 break;
6808 case 0x9e: /* sahf */
6809 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6810 goto illegal_op;
6811 gen_op_mov_v_reg(s, MO_8, s->T0, R_AH);
6812 gen_compute_eflags(s);
6813 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6814 tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6815 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
6816 break;
6817 case 0x9f: /* lahf */
6818 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6819 goto illegal_op;
6820 gen_compute_eflags(s);
6821 /* Note: gen_compute_eflags() only gives the condition codes */
6822 tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02);
6823 gen_op_mov_reg_v(s, MO_8, R_AH, s->T0);
6824 break;
6825 case 0xf5: /* cmc */
6826 gen_compute_eflags(s);
6827 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6828 break;
6829 case 0xf8: /* clc */
6830 gen_compute_eflags(s);
6831 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6832 break;
6833 case 0xf9: /* stc */
6834 gen_compute_eflags(s);
6835 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6836 break;
6837 case 0xfc: /* cld */
6838 tcg_gen_movi_i32(s->tmp2_i32, 1);
6839 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6840 break;
6841 case 0xfd: /* std */
6842 tcg_gen_movi_i32(s->tmp2_i32, -1);
6843 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6844 break;
6846 /************************/
6847 /* bit operations */
6848 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6849 ot = dflag;
6850 modrm = x86_ldub_code(env, s);
6851 op = (modrm >> 3) & 7;
6852 mod = (modrm >> 6) & 3;
6853 rm = (modrm & 7) | REX_B(s);
6854 if (mod != 3) {
6855 s->rip_offset = 1;
6856 gen_lea_modrm(env, s, modrm);
6857 if (!(s->prefix & PREFIX_LOCK)) {
6858 gen_op_ld_v(s, ot, s->T0, s->A0);
6860 } else {
6861 gen_op_mov_v_reg(s, ot, s->T0, rm);
6863 /* load shift */
6864 val = x86_ldub_code(env, s);
6865 tcg_gen_movi_tl(s->T1, val);
6866 if (op < 4)
6867 goto unknown_op;
6868 op -= 4;
6869 goto bt_op;
6870 case 0x1a3: /* bt Gv, Ev */
6871 op = 0;
6872 goto do_btx;
6873 case 0x1ab: /* bts */
6874 op = 1;
6875 goto do_btx;
6876 case 0x1b3: /* btr */
6877 op = 2;
6878 goto do_btx;
6879 case 0x1bb: /* btc */
6880 op = 3;
6881 do_btx:
6882 ot = dflag;
6883 modrm = x86_ldub_code(env, s);
6884 reg = ((modrm >> 3) & 7) | REX_R(s);
6885 mod = (modrm >> 6) & 3;
6886 rm = (modrm & 7) | REX_B(s);
6887 gen_op_mov_v_reg(s, MO_32, s->T1, reg);
6888 if (mod != 3) {
6889 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6890 /* specific case: we need to add a displacement */
6891 gen_exts(ot, s->T1);
6892 tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
6893 tcg_gen_shli_tl(s->tmp0, s->tmp0, ot);
6894 tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a), s->tmp0);
6895 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
6896 if (!(s->prefix & PREFIX_LOCK)) {
6897 gen_op_ld_v(s, ot, s->T0, s->A0);
6899 } else {
6900 gen_op_mov_v_reg(s, ot, s->T0, rm);
6902 bt_op:
6903 tcg_gen_andi_tl(s->T1, s->T1, (1 << (3 + ot)) - 1);
6904 tcg_gen_movi_tl(s->tmp0, 1);
6905 tcg_gen_shl_tl(s->tmp0, s->tmp0, s->T1);
6906 if (s->prefix & PREFIX_LOCK) {
6907 switch (op) {
6908 case 0: /* bt */
6909 /* Needs no atomic ops; we surpressed the normal
6910 memory load for LOCK above so do it now. */
6911 gen_op_ld_v(s, ot, s->T0, s->A0);
6912 break;
6913 case 1: /* bts */
6914 tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, s->tmp0,
6915 s->mem_index, ot | MO_LE);
6916 break;
6917 case 2: /* btr */
6918 tcg_gen_not_tl(s->tmp0, s->tmp0);
6919 tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, s->tmp0,
6920 s->mem_index, ot | MO_LE);
6921 break;
6922 default:
6923 case 3: /* btc */
6924 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0,
6925 s->mem_index, ot | MO_LE);
6926 break;
6928 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6929 } else {
6930 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6931 switch (op) {
6932 case 0: /* bt */
6933 /* Data already loaded; nothing to do. */
6934 break;
6935 case 1: /* bts */
6936 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
6937 break;
6938 case 2: /* btr */
6939 tcg_gen_andc_tl(s->T0, s->T0, s->tmp0);
6940 break;
6941 default:
6942 case 3: /* btc */
6943 tcg_gen_xor_tl(s->T0, s->T0, s->tmp0);
6944 break;
6946 if (op != 0) {
6947 if (mod != 3) {
6948 gen_op_st_v(s, ot, s->T0, s->A0);
6949 } else {
6950 gen_op_mov_reg_v(s, ot, rm, s->T0);
6955 /* Delay all CC updates until after the store above. Note that
6956 C is the result of the test, Z is unchanged, and the others
6957 are all undefined. */
6958 switch (s->cc_op) {
6959 case CC_OP_MULB ... CC_OP_MULQ:
6960 case CC_OP_ADDB ... CC_OP_ADDQ:
6961 case CC_OP_ADCB ... CC_OP_ADCQ:
6962 case CC_OP_SUBB ... CC_OP_SUBQ:
6963 case CC_OP_SBBB ... CC_OP_SBBQ:
6964 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6965 case CC_OP_INCB ... CC_OP_INCQ:
6966 case CC_OP_DECB ... CC_OP_DECQ:
6967 case CC_OP_SHLB ... CC_OP_SHLQ:
6968 case CC_OP_SARB ... CC_OP_SARQ:
6969 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6970 /* Z was going to be computed from the non-zero status of CC_DST.
6971 We can get that same Z value (and the new C value) by leaving
6972 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6973 same width. */
6974 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
6975 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6976 break;
6977 default:
6978 /* Otherwise, generate EFLAGS and replace the C bit. */
6979 gen_compute_eflags(s);
6980 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, s->tmp4,
6981 ctz32(CC_C), 1);
6982 break;
6984 break;
6985 case 0x1bc: /* bsf / tzcnt */
6986 case 0x1bd: /* bsr / lzcnt */
6987 ot = dflag;
6988 modrm = x86_ldub_code(env, s);
6989 reg = ((modrm >> 3) & 7) | REX_R(s);
6990 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6991 gen_extu(ot, s->T0);
6993 /* Note that lzcnt and tzcnt are in different extensions. */
6994 if ((prefixes & PREFIX_REPZ)
6995 && (b & 1
6996 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6997 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6998 int size = 8 << ot;
6999 /* For lzcnt/tzcnt, C bit is defined related to the input. */
7000 tcg_gen_mov_tl(cpu_cc_src, s->T0);
7001 if (b & 1) {
7002 /* For lzcnt, reduce the target_ulong result by the
7003 number of zeros that we expect to find at the top. */
7004 tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
7005 tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
7006 } else {
7007 /* For tzcnt, a zero input must return the operand size. */
7008 tcg_gen_ctzi_tl(s->T0, s->T0, size);
7010 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
7011 gen_op_update1_cc(s);
7012 set_cc_op(s, CC_OP_BMILGB + ot);
7013 } else {
7014 /* For bsr/bsf, only the Z bit is defined and it is related
7015 to the input and not the result. */
7016 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
7017 set_cc_op(s, CC_OP_LOGICB + ot);
7019 /* ??? The manual says that the output is undefined when the
7020 input is zero, but real hardware leaves it unchanged, and
7021 real programs appear to depend on that. Accomplish this
7022 by passing the output as the value to return upon zero. */
7023 if (b & 1) {
7024 /* For bsr, return the bit index of the first 1 bit,
7025 not the count of leading zeros. */
7026 tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
7027 tcg_gen_clz_tl(s->T0, s->T0, s->T1);
7028 tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
7029 } else {
7030 tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
7033 gen_op_mov_reg_v(s, ot, reg, s->T0);
7034 break;
7035 /************************/
7036 /* bcd */
7037 case 0x27: /* daa */
7038 if (CODE64(s))
7039 goto illegal_op;
7040 gen_update_cc_op(s);
7041 gen_helper_daa(cpu_env);
7042 set_cc_op(s, CC_OP_EFLAGS);
7043 break;
7044 case 0x2f: /* das */
7045 if (CODE64(s))
7046 goto illegal_op;
7047 gen_update_cc_op(s);
7048 gen_helper_das(cpu_env);
7049 set_cc_op(s, CC_OP_EFLAGS);
7050 break;
7051 case 0x37: /* aaa */
7052 if (CODE64(s))
7053 goto illegal_op;
7054 gen_update_cc_op(s);
7055 gen_helper_aaa(cpu_env);
7056 set_cc_op(s, CC_OP_EFLAGS);
7057 break;
7058 case 0x3f: /* aas */
7059 if (CODE64(s))
7060 goto illegal_op;
7061 gen_update_cc_op(s);
7062 gen_helper_aas(cpu_env);
7063 set_cc_op(s, CC_OP_EFLAGS);
7064 break;
7065 case 0xd4: /* aam */
7066 if (CODE64(s))
7067 goto illegal_op;
7068 val = x86_ldub_code(env, s);
7069 if (val == 0) {
7070 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7071 } else {
7072 gen_helper_aam(cpu_env, tcg_const_i32(val));
7073 set_cc_op(s, CC_OP_LOGICB);
7075 break;
7076 case 0xd5: /* aad */
7077 if (CODE64(s))
7078 goto illegal_op;
7079 val = x86_ldub_code(env, s);
7080 gen_helper_aad(cpu_env, tcg_const_i32(val));
7081 set_cc_op(s, CC_OP_LOGICB);
7082 break;
7083 /************************/
7084 /* misc */
7085 case 0x90: /* nop */
7086 /* XXX: correct lock test for all insn */
7087 if (prefixes & PREFIX_LOCK) {
7088 goto illegal_op;
7090 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
7091 if (REX_B(s)) {
7092 goto do_xchg_reg_eax;
7094 if (prefixes & PREFIX_REPZ) {
7095 gen_update_cc_op(s);
7096 gen_jmp_im(s, pc_start - s->cs_base);
7097 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
7098 s->base.is_jmp = DISAS_NORETURN;
7100 break;
7101 case 0x9b: /* fwait */
7102 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7103 (HF_MP_MASK | HF_TS_MASK)) {
7104 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7105 } else {
7106 gen_helper_fwait(cpu_env);
7108 break;
7109 case 0xcc: /* int3 */
7110 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7111 break;
7112 case 0xcd: /* int N */
7113 val = x86_ldub_code(env, s);
7114 if (check_vm86_iopl(s)) {
7115 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7117 break;
7118 case 0xce: /* into */
7119 if (CODE64(s))
7120 goto illegal_op;
7121 gen_update_cc_op(s);
7122 gen_jmp_im(s, pc_start - s->cs_base);
7123 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
7124 break;
7125 #ifdef WANT_ICEBP
7126 case 0xf1: /* icebp (undocumented, exits to external debugger) */
7127 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
7128 gen_debug(s, pc_start - s->cs_base);
7129 break;
7130 #endif
7131 case 0xfa: /* cli */
7132 if (check_iopl(s)) {
7133 gen_helper_cli(cpu_env);
7135 break;
7136 case 0xfb: /* sti */
7137 if (check_iopl(s)) {
7138 gen_helper_sti(cpu_env);
7139 /* interruptions are enabled only the first insn after sti */
7140 gen_jmp_im(s, s->pc - s->cs_base);
7141 gen_eob_inhibit_irq(s, true);
7143 break;
7144 case 0x62: /* bound */
7145 if (CODE64(s))
7146 goto illegal_op;
7147 ot = dflag;
7148 modrm = x86_ldub_code(env, s);
7149 reg = (modrm >> 3) & 7;
7150 mod = (modrm >> 6) & 3;
7151 if (mod == 3)
7152 goto illegal_op;
7153 gen_op_mov_v_reg(s, ot, s->T0, reg);
7154 gen_lea_modrm(env, s, modrm);
7155 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7156 if (ot == MO_16) {
7157 gen_helper_boundw(cpu_env, s->A0, s->tmp2_i32);
7158 } else {
7159 gen_helper_boundl(cpu_env, s->A0, s->tmp2_i32);
7161 break;
7162 case 0x1c8 ... 0x1cf: /* bswap reg */
7163 reg = (b & 7) | REX_B(s);
7164 #ifdef TARGET_X86_64
7165 if (dflag == MO_64) {
7166 gen_op_mov_v_reg(s, MO_64, s->T0, reg);
7167 tcg_gen_bswap64_i64(s->T0, s->T0);
7168 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
7169 } else
7170 #endif
7172 gen_op_mov_v_reg(s, MO_32, s->T0, reg);
7173 tcg_gen_ext32u_tl(s->T0, s->T0);
7174 tcg_gen_bswap32_tl(s->T0, s->T0);
7175 gen_op_mov_reg_v(s, MO_32, reg, s->T0);
7177 break;
7178 case 0xd6: /* salc */
7179 if (CODE64(s))
7180 goto illegal_op;
7181 gen_compute_eflags_c(s, s->T0);
7182 tcg_gen_neg_tl(s->T0, s->T0);
7183 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
7184 break;
7185 case 0xe0: /* loopnz */
7186 case 0xe1: /* loopz */
7187 case 0xe2: /* loop */
7188 case 0xe3: /* jecxz */
7190 TCGLabel *l1, *l2, *l3;
7192 tval = (int8_t)insn_get(env, s, MO_8);
7193 next_eip = s->pc - s->cs_base;
7194 tval += next_eip;
7195 if (dflag == MO_16) {
7196 tval &= 0xffff;
7199 l1 = gen_new_label();
7200 l2 = gen_new_label();
7201 l3 = gen_new_label();
7202 gen_update_cc_op(s);
7203 b &= 3;
7204 switch(b) {
7205 case 0: /* loopnz */
7206 case 1: /* loopz */
7207 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7208 gen_op_jz_ecx(s, s->aflag, l3);
7209 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7210 break;
7211 case 2: /* loop */
7212 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7213 gen_op_jnz_ecx(s, s->aflag, l1);
7214 break;
7215 default:
7216 case 3: /* jcxz */
7217 gen_op_jz_ecx(s, s->aflag, l1);
7218 break;
7221 gen_set_label(l3);
7222 gen_jmp_im(s, next_eip);
7223 tcg_gen_br(l2);
7225 gen_set_label(l1);
7226 gen_jmp_im(s, tval);
7227 gen_set_label(l2);
7228 gen_eob(s);
7230 break;
7231 case 0x130: /* wrmsr */
7232 case 0x132: /* rdmsr */
7233 if (check_cpl0(s)) {
7234 gen_update_cc_op(s);
7235 gen_jmp_im(s, pc_start - s->cs_base);
7236 if (b & 2) {
7237 gen_helper_rdmsr(cpu_env);
7238 } else {
7239 gen_helper_wrmsr(cpu_env);
7242 break;
7243 case 0x131: /* rdtsc */
7244 gen_update_cc_op(s);
7245 gen_jmp_im(s, pc_start - s->cs_base);
7246 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7247 gen_io_start();
7249 gen_helper_rdtsc(cpu_env);
7250 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7251 gen_jmp(s, s->pc - s->cs_base);
7253 break;
7254 case 0x133: /* rdpmc */
7255 gen_update_cc_op(s);
7256 gen_jmp_im(s, pc_start - s->cs_base);
7257 gen_helper_rdpmc(cpu_env);
7258 break;
7259 case 0x134: /* sysenter */
7260 /* For Intel SYSENTER is valid on 64-bit */
7261 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7262 goto illegal_op;
7263 if (!PE(s)) {
7264 gen_exception_gpf(s);
7265 } else {
7266 gen_helper_sysenter(cpu_env);
7267 gen_eob(s);
7269 break;
7270 case 0x135: /* sysexit */
7271 /* For Intel SYSEXIT is valid on 64-bit */
7272 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7273 goto illegal_op;
7274 if (!PE(s)) {
7275 gen_exception_gpf(s);
7276 } else {
7277 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7278 gen_eob(s);
7280 break;
7281 #ifdef TARGET_X86_64
7282 case 0x105: /* syscall */
7283 /* XXX: is it usable in real mode ? */
7284 gen_update_cc_op(s);
7285 gen_jmp_im(s, pc_start - s->cs_base);
7286 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7287 /* TF handling for the syscall insn is different. The TF bit is checked
7288 after the syscall insn completes. This allows #DB to not be
7289 generated after one has entered CPL0 if TF is set in FMASK. */
7290 gen_eob_worker(s, false, true);
7291 break;
7292 case 0x107: /* sysret */
7293 if (!PE(s)) {
7294 gen_exception_gpf(s);
7295 } else {
7296 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7297 /* condition codes are modified only in long mode */
7298 if (LMA(s)) {
7299 set_cc_op(s, CC_OP_EFLAGS);
7301 /* TF handling for the sysret insn is different. The TF bit is
7302 checked after the sysret insn completes. This allows #DB to be
7303 generated "as if" the syscall insn in userspace has just
7304 completed. */
7305 gen_eob_worker(s, false, true);
7307 break;
7308 #endif
7309 case 0x1a2: /* cpuid */
7310 gen_update_cc_op(s);
7311 gen_jmp_im(s, pc_start - s->cs_base);
7312 gen_helper_cpuid(cpu_env);
7313 break;
7314 case 0xf4: /* hlt */
7315 if (check_cpl0(s)) {
7316 gen_update_cc_op(s);
7317 gen_jmp_im(s, pc_start - s->cs_base);
7318 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7319 s->base.is_jmp = DISAS_NORETURN;
7321 break;
7322 case 0x100:
7323 modrm = x86_ldub_code(env, s);
7324 mod = (modrm >> 6) & 3;
7325 op = (modrm >> 3) & 7;
7326 switch(op) {
7327 case 0: /* sldt */
7328 if (!PE(s) || VM86(s))
7329 goto illegal_op;
7330 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7331 tcg_gen_ld32u_tl(s->T0, cpu_env,
7332 offsetof(CPUX86State, ldt.selector));
7333 ot = mod == 3 ? dflag : MO_16;
7334 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7335 break;
7336 case 2: /* lldt */
7337 if (!PE(s) || VM86(s))
7338 goto illegal_op;
7339 if (check_cpl0(s)) {
7340 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7341 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7342 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7343 gen_helper_lldt(cpu_env, s->tmp2_i32);
7345 break;
7346 case 1: /* str */
7347 if (!PE(s) || VM86(s))
7348 goto illegal_op;
7349 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7350 tcg_gen_ld32u_tl(s->T0, cpu_env,
7351 offsetof(CPUX86State, tr.selector));
7352 ot = mod == 3 ? dflag : MO_16;
7353 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7354 break;
7355 case 3: /* ltr */
7356 if (!PE(s) || VM86(s))
7357 goto illegal_op;
7358 if (check_cpl0(s)) {
7359 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7360 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7361 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7362 gen_helper_ltr(cpu_env, s->tmp2_i32);
7364 break;
7365 case 4: /* verr */
7366 case 5: /* verw */
7367 if (!PE(s) || VM86(s))
7368 goto illegal_op;
7369 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7370 gen_update_cc_op(s);
7371 if (op == 4) {
7372 gen_helper_verr(cpu_env, s->T0);
7373 } else {
7374 gen_helper_verw(cpu_env, s->T0);
7376 set_cc_op(s, CC_OP_EFLAGS);
7377 break;
7378 default:
7379 goto unknown_op;
7381 break;
7383 case 0x101:
7384 modrm = x86_ldub_code(env, s);
7385 switch (modrm) {
7386 CASE_MODRM_MEM_OP(0): /* sgdt */
7387 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7388 gen_lea_modrm(env, s, modrm);
7389 tcg_gen_ld32u_tl(s->T0,
7390 cpu_env, offsetof(CPUX86State, gdt.limit));
7391 gen_op_st_v(s, MO_16, s->T0, s->A0);
7392 gen_add_A0_im(s, 2);
7393 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7394 if (dflag == MO_16) {
7395 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7397 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7398 break;
7400 case 0xc8: /* monitor */
7401 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
7402 goto illegal_op;
7404 gen_update_cc_op(s);
7405 gen_jmp_im(s, pc_start - s->cs_base);
7406 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7407 gen_extu(s->aflag, s->A0);
7408 gen_add_A0_ds_seg(s);
7409 gen_helper_monitor(cpu_env, s->A0);
7410 break;
7412 case 0xc9: /* mwait */
7413 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
7414 goto illegal_op;
7416 gen_update_cc_op(s);
7417 gen_jmp_im(s, pc_start - s->cs_base);
7418 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7419 gen_eob(s);
7420 break;
7422 case 0xca: /* clac */
7423 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7424 || CPL(s) != 0) {
7425 goto illegal_op;
7427 gen_helper_clac(cpu_env);
7428 gen_jmp_im(s, s->pc - s->cs_base);
7429 gen_eob(s);
7430 break;
7432 case 0xcb: /* stac */
7433 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7434 || CPL(s) != 0) {
7435 goto illegal_op;
7437 gen_helper_stac(cpu_env);
7438 gen_jmp_im(s, s->pc - s->cs_base);
7439 gen_eob(s);
7440 break;
7442 CASE_MODRM_MEM_OP(1): /* sidt */
7443 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7444 gen_lea_modrm(env, s, modrm);
7445 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit));
7446 gen_op_st_v(s, MO_16, s->T0, s->A0);
7447 gen_add_A0_im(s, 2);
7448 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7449 if (dflag == MO_16) {
7450 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7452 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7453 break;
7455 case 0xd0: /* xgetbv */
7456 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7457 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7458 | PREFIX_REPZ | PREFIX_REPNZ))) {
7459 goto illegal_op;
7461 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7462 gen_helper_xgetbv(s->tmp1_i64, cpu_env, s->tmp2_i32);
7463 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7464 break;
7466 case 0xd1: /* xsetbv */
7467 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7468 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7469 | PREFIX_REPZ | PREFIX_REPNZ))) {
7470 goto illegal_op;
7472 if (!check_cpl0(s)) {
7473 break;
7475 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7476 cpu_regs[R_EDX]);
7477 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7478 gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
7479 /* End TB because translation flags may change. */
7480 gen_jmp_im(s, s->pc - s->cs_base);
7481 gen_eob(s);
7482 break;
7484 case 0xd8: /* VMRUN */
7485 if (!(s->flags & HF_SVME_MASK) || !PE(s)) {
7486 goto illegal_op;
7488 if (!check_cpl0(s)) {
7489 break;
7491 gen_update_cc_op(s);
7492 gen_jmp_im(s, pc_start - s->cs_base);
7493 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7494 tcg_const_i32(s->pc - pc_start));
7495 tcg_gen_exit_tb(NULL, 0);
7496 s->base.is_jmp = DISAS_NORETURN;
7497 break;
7499 case 0xd9: /* VMMCALL */
7500 if (!(s->flags & HF_SVME_MASK)) {
7501 goto illegal_op;
7503 gen_update_cc_op(s);
7504 gen_jmp_im(s, pc_start - s->cs_base);
7505 gen_helper_vmmcall(cpu_env);
7506 break;
7508 case 0xda: /* VMLOAD */
7509 if (!(s->flags & HF_SVME_MASK) || !PE(s)) {
7510 goto illegal_op;
7512 if (!check_cpl0(s)) {
7513 break;
7515 gen_update_cc_op(s);
7516 gen_jmp_im(s, pc_start - s->cs_base);
7517 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7518 break;
7520 case 0xdb: /* VMSAVE */
7521 if (!(s->flags & HF_SVME_MASK) || !PE(s)) {
7522 goto illegal_op;
7524 if (!check_cpl0(s)) {
7525 break;
7527 gen_update_cc_op(s);
7528 gen_jmp_im(s, pc_start - s->cs_base);
7529 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7530 break;
7532 case 0xdc: /* STGI */
7533 if ((!(s->flags & HF_SVME_MASK)
7534 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7535 || !PE(s)) {
7536 goto illegal_op;
7538 if (!check_cpl0(s)) {
7539 break;
7541 gen_update_cc_op(s);
7542 gen_helper_stgi(cpu_env);
7543 gen_jmp_im(s, s->pc - s->cs_base);
7544 gen_eob(s);
7545 break;
7547 case 0xdd: /* CLGI */
7548 if (!(s->flags & HF_SVME_MASK) || !PE(s)) {
7549 goto illegal_op;
7551 if (!check_cpl0(s)) {
7552 break;
7554 gen_update_cc_op(s);
7555 gen_jmp_im(s, pc_start - s->cs_base);
7556 gen_helper_clgi(cpu_env);
7557 break;
7559 case 0xde: /* SKINIT */
7560 if ((!(s->flags & HF_SVME_MASK)
7561 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7562 || !PE(s)) {
7563 goto illegal_op;
7565 gen_update_cc_op(s);
7566 gen_jmp_im(s, pc_start - s->cs_base);
7567 gen_helper_skinit(cpu_env);
7568 break;
7570 case 0xdf: /* INVLPGA */
7571 if (!(s->flags & HF_SVME_MASK) || !PE(s)) {
7572 goto illegal_op;
7574 if (!check_cpl0(s)) {
7575 break;
7577 gen_update_cc_op(s);
7578 gen_jmp_im(s, pc_start - s->cs_base);
7579 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7580 break;
7582 CASE_MODRM_MEM_OP(2): /* lgdt */
7583 if (!check_cpl0(s)) {
7584 break;
7586 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE);
7587 gen_lea_modrm(env, s, modrm);
7588 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7589 gen_add_A0_im(s, 2);
7590 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7591 if (dflag == MO_16) {
7592 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7594 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7595 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7596 break;
7598 CASE_MODRM_MEM_OP(3): /* lidt */
7599 if (!check_cpl0(s)) {
7600 break;
7602 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7603 gen_lea_modrm(env, s, modrm);
7604 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7605 gen_add_A0_im(s, 2);
7606 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7607 if (dflag == MO_16) {
7608 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7610 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7611 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, idt.limit));
7612 break;
7614 CASE_MODRM_OP(4): /* smsw */
7615 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7616 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
7618 * In 32-bit mode, the higher 16 bits of the destination
7619 * register are undefined. In practice CR0[31:0] is stored
7620 * just like in 64-bit mode.
7622 mod = (modrm >> 6) & 3;
7623 ot = (mod != 3 ? MO_16 : s->dflag);
7624 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7625 break;
7626 case 0xee: /* rdpkru */
7627 if (prefixes & PREFIX_LOCK) {
7628 goto illegal_op;
7630 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7631 gen_helper_rdpkru(s->tmp1_i64, cpu_env, s->tmp2_i32);
7632 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7633 break;
7634 case 0xef: /* wrpkru */
7635 if (prefixes & PREFIX_LOCK) {
7636 goto illegal_op;
7638 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7639 cpu_regs[R_EDX]);
7640 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7641 gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64);
7642 break;
7643 CASE_MODRM_OP(6): /* lmsw */
7644 if (!check_cpl0(s)) {
7645 break;
7647 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7648 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7649 gen_helper_lmsw(cpu_env, s->T0);
7650 gen_jmp_im(s, s->pc - s->cs_base);
7651 gen_eob(s);
7652 break;
7654 CASE_MODRM_MEM_OP(7): /* invlpg */
7655 if (!check_cpl0(s)) {
7656 break;
7658 gen_update_cc_op(s);
7659 gen_jmp_im(s, pc_start - s->cs_base);
7660 gen_lea_modrm(env, s, modrm);
7661 gen_helper_invlpg(cpu_env, s->A0);
7662 gen_jmp_im(s, s->pc - s->cs_base);
7663 gen_eob(s);
7664 break;
7666 case 0xf8: /* swapgs */
7667 #ifdef TARGET_X86_64
7668 if (CODE64(s)) {
7669 if (check_cpl0(s)) {
7670 tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]);
7671 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7672 offsetof(CPUX86State, kernelgsbase));
7673 tcg_gen_st_tl(s->T0, cpu_env,
7674 offsetof(CPUX86State, kernelgsbase));
7676 break;
7678 #endif
7679 goto illegal_op;
7681 case 0xf9: /* rdtscp */
7682 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7683 goto illegal_op;
7685 gen_update_cc_op(s);
7686 gen_jmp_im(s, pc_start - s->cs_base);
7687 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7688 gen_io_start();
7690 gen_helper_rdtscp(cpu_env);
7691 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7692 gen_jmp(s, s->pc - s->cs_base);
7694 break;
7696 default:
7697 goto unknown_op;
7699 break;
7701 case 0x108: /* invd */
7702 case 0x109: /* wbinvd */
7703 if (check_cpl0(s)) {
7704 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7705 /* nothing to do */
7707 break;
7708 case 0x63: /* arpl or movslS (x86_64) */
7709 #ifdef TARGET_X86_64
7710 if (CODE64(s)) {
7711 int d_ot;
7712 /* d_ot is the size of destination */
7713 d_ot = dflag;
7715 modrm = x86_ldub_code(env, s);
7716 reg = ((modrm >> 3) & 7) | REX_R(s);
7717 mod = (modrm >> 6) & 3;
7718 rm = (modrm & 7) | REX_B(s);
7720 if (mod == 3) {
7721 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
7722 /* sign extend */
7723 if (d_ot == MO_64) {
7724 tcg_gen_ext32s_tl(s->T0, s->T0);
7726 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7727 } else {
7728 gen_lea_modrm(env, s, modrm);
7729 gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0);
7730 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7732 } else
7733 #endif
7735 TCGLabel *label1;
7736 TCGv t0, t1, t2, a0;
7738 if (!PE(s) || VM86(s))
7739 goto illegal_op;
7740 t0 = tcg_temp_local_new();
7741 t1 = tcg_temp_local_new();
7742 t2 = tcg_temp_local_new();
7743 ot = MO_16;
7744 modrm = x86_ldub_code(env, s);
7745 reg = (modrm >> 3) & 7;
7746 mod = (modrm >> 6) & 3;
7747 rm = modrm & 7;
7748 if (mod != 3) {
7749 gen_lea_modrm(env, s, modrm);
7750 gen_op_ld_v(s, ot, t0, s->A0);
7751 a0 = tcg_temp_local_new();
7752 tcg_gen_mov_tl(a0, s->A0);
7753 } else {
7754 gen_op_mov_v_reg(s, ot, t0, rm);
7755 a0 = NULL;
7757 gen_op_mov_v_reg(s, ot, t1, reg);
7758 tcg_gen_andi_tl(s->tmp0, t0, 3);
7759 tcg_gen_andi_tl(t1, t1, 3);
7760 tcg_gen_movi_tl(t2, 0);
7761 label1 = gen_new_label();
7762 tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1);
7763 tcg_gen_andi_tl(t0, t0, ~3);
7764 tcg_gen_or_tl(t0, t0, t1);
7765 tcg_gen_movi_tl(t2, CC_Z);
7766 gen_set_label(label1);
7767 if (mod != 3) {
7768 gen_op_st_v(s, ot, t0, a0);
7769 tcg_temp_free(a0);
7770 } else {
7771 gen_op_mov_reg_v(s, ot, rm, t0);
7773 gen_compute_eflags(s);
7774 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7775 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7776 tcg_temp_free(t0);
7777 tcg_temp_free(t1);
7778 tcg_temp_free(t2);
7780 break;
7781 case 0x102: /* lar */
7782 case 0x103: /* lsl */
7784 TCGLabel *label1;
7785 TCGv t0;
7786 if (!PE(s) || VM86(s))
7787 goto illegal_op;
7788 ot = dflag != MO_16 ? MO_32 : MO_16;
7789 modrm = x86_ldub_code(env, s);
7790 reg = ((modrm >> 3) & 7) | REX_R(s);
7791 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7792 t0 = tcg_temp_local_new();
7793 gen_update_cc_op(s);
7794 if (b == 0x102) {
7795 gen_helper_lar(t0, cpu_env, s->T0);
7796 } else {
7797 gen_helper_lsl(t0, cpu_env, s->T0);
7799 tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z);
7800 label1 = gen_new_label();
7801 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
7802 gen_op_mov_reg_v(s, ot, reg, t0);
7803 gen_set_label(label1);
7804 set_cc_op(s, CC_OP_EFLAGS);
7805 tcg_temp_free(t0);
7807 break;
7808 case 0x118:
7809 modrm = x86_ldub_code(env, s);
7810 mod = (modrm >> 6) & 3;
7811 op = (modrm >> 3) & 7;
7812 switch(op) {
7813 case 0: /* prefetchnta */
7814 case 1: /* prefetchnt0 */
7815 case 2: /* prefetchnt0 */
7816 case 3: /* prefetchnt0 */
7817 if (mod == 3)
7818 goto illegal_op;
7819 gen_nop_modrm(env, s, modrm);
7820 /* nothing more to do */
7821 break;
7822 default: /* nop (multi byte) */
7823 gen_nop_modrm(env, s, modrm);
7824 break;
7826 break;
7827 case 0x11a:
7828 modrm = x86_ldub_code(env, s);
7829 if (s->flags & HF_MPX_EN_MASK) {
7830 mod = (modrm >> 6) & 3;
7831 reg = ((modrm >> 3) & 7) | REX_R(s);
7832 if (prefixes & PREFIX_REPZ) {
7833 /* bndcl */
7834 if (reg >= 4
7835 || (prefixes & PREFIX_LOCK)
7836 || s->aflag == MO_16) {
7837 goto illegal_op;
7839 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7840 } else if (prefixes & PREFIX_REPNZ) {
7841 /* bndcu */
7842 if (reg >= 4
7843 || (prefixes & PREFIX_LOCK)
7844 || s->aflag == MO_16) {
7845 goto illegal_op;
7847 TCGv_i64 notu = tcg_temp_new_i64();
7848 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7849 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7850 tcg_temp_free_i64(notu);
7851 } else if (prefixes & PREFIX_DATA) {
7852 /* bndmov -- from reg/mem */
7853 if (reg >= 4 || s->aflag == MO_16) {
7854 goto illegal_op;
7856 if (mod == 3) {
7857 int reg2 = (modrm & 7) | REX_B(s);
7858 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7859 goto illegal_op;
7861 if (s->flags & HF_MPX_IU_MASK) {
7862 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7863 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7865 } else {
7866 gen_lea_modrm(env, s, modrm);
7867 if (CODE64(s)) {
7868 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7869 s->mem_index, MO_LEQ);
7870 tcg_gen_addi_tl(s->A0, s->A0, 8);
7871 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7872 s->mem_index, MO_LEQ);
7873 } else {
7874 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7875 s->mem_index, MO_LEUL);
7876 tcg_gen_addi_tl(s->A0, s->A0, 4);
7877 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7878 s->mem_index, MO_LEUL);
7880 /* bnd registers are now in-use */
7881 gen_set_hflag(s, HF_MPX_IU_MASK);
7883 } else if (mod != 3) {
7884 /* bndldx */
7885 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7886 if (reg >= 4
7887 || (prefixes & PREFIX_LOCK)
7888 || s->aflag == MO_16
7889 || a.base < -1) {
7890 goto illegal_op;
7892 if (a.base >= 0) {
7893 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
7894 } else {
7895 tcg_gen_movi_tl(s->A0, 0);
7897 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
7898 if (a.index >= 0) {
7899 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
7900 } else {
7901 tcg_gen_movi_tl(s->T0, 0);
7903 if (CODE64(s)) {
7904 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0);
7905 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7906 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7907 } else {
7908 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0);
7909 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7910 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7912 gen_set_hflag(s, HF_MPX_IU_MASK);
7915 gen_nop_modrm(env, s, modrm);
7916 break;
7917 case 0x11b:
7918 modrm = x86_ldub_code(env, s);
7919 if (s->flags & HF_MPX_EN_MASK) {
7920 mod = (modrm >> 6) & 3;
7921 reg = ((modrm >> 3) & 7) | REX_R(s);
7922 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7923 /* bndmk */
7924 if (reg >= 4
7925 || (prefixes & PREFIX_LOCK)
7926 || s->aflag == MO_16) {
7927 goto illegal_op;
7929 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7930 if (a.base >= 0) {
7931 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7932 if (!CODE64(s)) {
7933 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7935 } else if (a.base == -1) {
7936 /* no base register has lower bound of 0 */
7937 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7938 } else {
7939 /* rip-relative generates #ud */
7940 goto illegal_op;
7942 tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a));
7943 if (!CODE64(s)) {
7944 tcg_gen_ext32u_tl(s->A0, s->A0);
7946 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
7947 /* bnd registers are now in-use */
7948 gen_set_hflag(s, HF_MPX_IU_MASK);
7949 break;
7950 } else if (prefixes & PREFIX_REPNZ) {
7951 /* bndcn */
7952 if (reg >= 4
7953 || (prefixes & PREFIX_LOCK)
7954 || s->aflag == MO_16) {
7955 goto illegal_op;
7957 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
7958 } else if (prefixes & PREFIX_DATA) {
7959 /* bndmov -- to reg/mem */
7960 if (reg >= 4 || s->aflag == MO_16) {
7961 goto illegal_op;
7963 if (mod == 3) {
7964 int reg2 = (modrm & 7) | REX_B(s);
7965 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7966 goto illegal_op;
7968 if (s->flags & HF_MPX_IU_MASK) {
7969 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7970 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7972 } else {
7973 gen_lea_modrm(env, s, modrm);
7974 if (CODE64(s)) {
7975 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
7976 s->mem_index, MO_LEQ);
7977 tcg_gen_addi_tl(s->A0, s->A0, 8);
7978 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
7979 s->mem_index, MO_LEQ);
7980 } else {
7981 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
7982 s->mem_index, MO_LEUL);
7983 tcg_gen_addi_tl(s->A0, s->A0, 4);
7984 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
7985 s->mem_index, MO_LEUL);
7988 } else if (mod != 3) {
7989 /* bndstx */
7990 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7991 if (reg >= 4
7992 || (prefixes & PREFIX_LOCK)
7993 || s->aflag == MO_16
7994 || a.base < -1) {
7995 goto illegal_op;
7997 if (a.base >= 0) {
7998 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
7999 } else {
8000 tcg_gen_movi_tl(s->A0, 0);
8002 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
8003 if (a.index >= 0) {
8004 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
8005 } else {
8006 tcg_gen_movi_tl(s->T0, 0);
8008 if (CODE64(s)) {
8009 gen_helper_bndstx64(cpu_env, s->A0, s->T0,
8010 cpu_bndl[reg], cpu_bndu[reg]);
8011 } else {
8012 gen_helper_bndstx32(cpu_env, s->A0, s->T0,
8013 cpu_bndl[reg], cpu_bndu[reg]);
8017 gen_nop_modrm(env, s, modrm);
8018 break;
8019 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
8020 modrm = x86_ldub_code(env, s);
8021 gen_nop_modrm(env, s, modrm);
8022 break;
8023 case 0x120: /* mov reg, crN */
8024 case 0x122: /* mov crN, reg */
8025 if (check_cpl0(s)) {
8026 modrm = x86_ldub_code(env, s);
8027 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8028 * AMD documentation (24594.pdf) and testing of
8029 * intel 386 and 486 processors all show that the mod bits
8030 * are assumed to be 1's, regardless of actual values.
8032 rm = (modrm & 7) | REX_B(s);
8033 reg = ((modrm >> 3) & 7) | REX_R(s);
8034 if (CODE64(s))
8035 ot = MO_64;
8036 else
8037 ot = MO_32;
8038 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
8039 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
8040 reg = 8;
8042 switch(reg) {
8043 case 0:
8044 case 2:
8045 case 3:
8046 case 4:
8047 case 8:
8048 gen_update_cc_op(s);
8049 gen_jmp_im(s, pc_start - s->cs_base);
8050 if (b & 2) {
8051 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8052 gen_io_start();
8054 gen_op_mov_v_reg(s, ot, s->T0, rm);
8055 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
8056 s->T0);
8057 gen_jmp_im(s, s->pc - s->cs_base);
8058 gen_eob(s);
8059 } else {
8060 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8061 gen_io_start();
8063 gen_helper_read_crN(s->T0, cpu_env, tcg_const_i32(reg));
8064 gen_op_mov_reg_v(s, ot, rm, s->T0);
8065 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8066 gen_jmp(s, s->pc - s->cs_base);
8069 break;
8070 default:
8071 goto unknown_op;
8074 break;
8075 case 0x121: /* mov reg, drN */
8076 case 0x123: /* mov drN, reg */
8077 if (check_cpl0(s)) {
8078 #ifndef CONFIG_USER_ONLY
8079 modrm = x86_ldub_code(env, s);
8080 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8081 * AMD documentation (24594.pdf) and testing of
8082 * intel 386 and 486 processors all show that the mod bits
8083 * are assumed to be 1's, regardless of actual values.
8085 rm = (modrm & 7) | REX_B(s);
8086 reg = ((modrm >> 3) & 7) | REX_R(s);
8087 if (CODE64(s))
8088 ot = MO_64;
8089 else
8090 ot = MO_32;
8091 if (reg >= 8) {
8092 goto illegal_op;
8094 if (b & 2) {
8095 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
8096 gen_op_mov_v_reg(s, ot, s->T0, rm);
8097 tcg_gen_movi_i32(s->tmp2_i32, reg);
8098 gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
8099 gen_jmp_im(s, s->pc - s->cs_base);
8100 gen_eob(s);
8101 } else {
8102 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
8103 tcg_gen_movi_i32(s->tmp2_i32, reg);
8104 gen_helper_get_dr(s->T0, cpu_env, s->tmp2_i32);
8105 gen_op_mov_reg_v(s, ot, rm, s->T0);
8107 #endif /* !CONFIG_USER_ONLY */
8109 break;
8110 case 0x106: /* clts */
8111 if (check_cpl0(s)) {
8112 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
8113 gen_helper_clts(cpu_env);
8114 /* abort block because static cpu state changed */
8115 gen_jmp_im(s, s->pc - s->cs_base);
8116 gen_eob(s);
8118 break;
8119 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
8120 case 0x1c3: /* MOVNTI reg, mem */
8121 if (!(s->cpuid_features & CPUID_SSE2))
8122 goto illegal_op;
8123 ot = mo_64_32(dflag);
8124 modrm = x86_ldub_code(env, s);
8125 mod = (modrm >> 6) & 3;
8126 if (mod == 3)
8127 goto illegal_op;
8128 reg = ((modrm >> 3) & 7) | REX_R(s);
8129 /* generate a generic store */
8130 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8131 break;
8132 case 0x1ae:
8133 modrm = x86_ldub_code(env, s);
8134 switch (modrm) {
8135 CASE_MODRM_MEM_OP(0): /* fxsave */
8136 if (!(s->cpuid_features & CPUID_FXSR)
8137 || (prefixes & PREFIX_LOCK)) {
8138 goto illegal_op;
8140 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8141 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8142 break;
8144 gen_lea_modrm(env, s, modrm);
8145 gen_helper_fxsave(cpu_env, s->A0);
8146 break;
8148 CASE_MODRM_MEM_OP(1): /* fxrstor */
8149 if (!(s->cpuid_features & CPUID_FXSR)
8150 || (prefixes & PREFIX_LOCK)) {
8151 goto illegal_op;
8153 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8154 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8155 break;
8157 gen_lea_modrm(env, s, modrm);
8158 gen_helper_fxrstor(cpu_env, s->A0);
8159 break;
8161 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
8162 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8163 goto illegal_op;
8165 if (s->flags & HF_TS_MASK) {
8166 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8167 break;
8169 gen_lea_modrm(env, s, modrm);
8170 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
8171 gen_helper_ldmxcsr(cpu_env, s->tmp2_i32);
8172 break;
8174 CASE_MODRM_MEM_OP(3): /* stmxcsr */
8175 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8176 goto illegal_op;
8178 if (s->flags & HF_TS_MASK) {
8179 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8180 break;
8182 gen_helper_update_mxcsr(cpu_env);
8183 gen_lea_modrm(env, s, modrm);
8184 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr));
8185 gen_op_st_v(s, MO_32, s->T0, s->A0);
8186 break;
8188 CASE_MODRM_MEM_OP(4): /* xsave */
8189 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8190 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8191 | PREFIX_REPZ | PREFIX_REPNZ))) {
8192 goto illegal_op;
8194 gen_lea_modrm(env, s, modrm);
8195 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8196 cpu_regs[R_EDX]);
8197 gen_helper_xsave(cpu_env, s->A0, s->tmp1_i64);
8198 break;
8200 CASE_MODRM_MEM_OP(5): /* xrstor */
8201 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8202 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8203 | PREFIX_REPZ | PREFIX_REPNZ))) {
8204 goto illegal_op;
8206 gen_lea_modrm(env, s, modrm);
8207 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8208 cpu_regs[R_EDX]);
8209 gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64);
8210 /* XRSTOR is how MPX is enabled, which changes how
8211 we translate. Thus we need to end the TB. */
8212 gen_update_cc_op(s);
8213 gen_jmp_im(s, s->pc - s->cs_base);
8214 gen_eob(s);
8215 break;
8217 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
8218 if (prefixes & PREFIX_LOCK) {
8219 goto illegal_op;
8221 if (prefixes & PREFIX_DATA) {
8222 /* clwb */
8223 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8224 goto illegal_op;
8226 gen_nop_modrm(env, s, modrm);
8227 } else {
8228 /* xsaveopt */
8229 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8230 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8231 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8232 goto illegal_op;
8234 gen_lea_modrm(env, s, modrm);
8235 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8236 cpu_regs[R_EDX]);
8237 gen_helper_xsaveopt(cpu_env, s->A0, s->tmp1_i64);
8239 break;
8241 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
8242 if (prefixes & PREFIX_LOCK) {
8243 goto illegal_op;
8245 if (prefixes & PREFIX_DATA) {
8246 /* clflushopt */
8247 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8248 goto illegal_op;
8250 } else {
8251 /* clflush */
8252 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8253 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8254 goto illegal_op;
8257 gen_nop_modrm(env, s, modrm);
8258 break;
8260 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
8261 case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
8262 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
8263 case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
8264 if (CODE64(s)
8265 && (prefixes & PREFIX_REPZ)
8266 && !(prefixes & PREFIX_LOCK)
8267 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8268 TCGv base, treg, src, dst;
8270 /* Preserve hflags bits by testing CR4 at runtime. */
8271 tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
8272 gen_helper_cr4_testbit(cpu_env, s->tmp2_i32);
8274 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8275 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8277 if (modrm & 0x10) {
8278 /* wr*base */
8279 dst = base, src = treg;
8280 } else {
8281 /* rd*base */
8282 dst = treg, src = base;
8285 if (s->dflag == MO_32) {
8286 tcg_gen_ext32u_tl(dst, src);
8287 } else {
8288 tcg_gen_mov_tl(dst, src);
8290 break;
8292 goto unknown_op;
8294 case 0xf8: /* sfence / pcommit */
8295 if (prefixes & PREFIX_DATA) {
8296 /* pcommit */
8297 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8298 || (prefixes & PREFIX_LOCK)) {
8299 goto illegal_op;
8301 break;
8303 /* fallthru */
8304 case 0xf9 ... 0xff: /* sfence */
8305 if (!(s->cpuid_features & CPUID_SSE)
8306 || (prefixes & PREFIX_LOCK)) {
8307 goto illegal_op;
8309 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8310 break;
8311 case 0xe8 ... 0xef: /* lfence */
8312 if (!(s->cpuid_features & CPUID_SSE)
8313 || (prefixes & PREFIX_LOCK)) {
8314 goto illegal_op;
8316 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8317 break;
8318 case 0xf0 ... 0xf7: /* mfence */
8319 if (!(s->cpuid_features & CPUID_SSE2)
8320 || (prefixes & PREFIX_LOCK)) {
8321 goto illegal_op;
8323 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8324 break;
8326 default:
8327 goto unknown_op;
8329 break;
8331 case 0x10d: /* 3DNow! prefetch(w) */
8332 modrm = x86_ldub_code(env, s);
8333 mod = (modrm >> 6) & 3;
8334 if (mod == 3)
8335 goto illegal_op;
8336 gen_nop_modrm(env, s, modrm);
8337 break;
8338 case 0x1aa: /* rsm */
8339 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8340 if (!(s->flags & HF_SMM_MASK))
8341 goto illegal_op;
8342 #ifdef CONFIG_USER_ONLY
8343 /* we should not be in SMM mode */
8344 g_assert_not_reached();
8345 #else
8346 gen_update_cc_op(s);
8347 gen_jmp_im(s, s->pc - s->cs_base);
8348 gen_helper_rsm(cpu_env);
8349 #endif /* CONFIG_USER_ONLY */
8350 gen_eob(s);
8351 break;
8352 case 0x1b8: /* SSE4.2 popcnt */
8353 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8354 PREFIX_REPZ)
8355 goto illegal_op;
8356 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8357 goto illegal_op;
8359 modrm = x86_ldub_code(env, s);
8360 reg = ((modrm >> 3) & 7) | REX_R(s);
8362 if (s->prefix & PREFIX_DATA) {
8363 ot = MO_16;
8364 } else {
8365 ot = mo_64_32(dflag);
8368 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8369 gen_extu(ot, s->T0);
8370 tcg_gen_mov_tl(cpu_cc_src, s->T0);
8371 tcg_gen_ctpop_tl(s->T0, s->T0);
8372 gen_op_mov_reg_v(s, ot, reg, s->T0);
8374 set_cc_op(s, CC_OP_POPCNT);
8375 break;
8376 case 0x10e ... 0x10f:
8377 /* 3DNow! instructions, ignore prefixes */
8378 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8379 /* fall through */
8380 case 0x110 ... 0x117:
8381 case 0x128 ... 0x12f:
8382 case 0x138 ... 0x13a:
8383 case 0x150 ... 0x179:
8384 case 0x17c ... 0x17f:
8385 case 0x1c2:
8386 case 0x1c4 ... 0x1c6:
8387 case 0x1d0 ... 0x1fe:
8388 gen_sse(env, s, b, pc_start);
8389 break;
8390 default:
8391 goto unknown_op;
8393 return s->pc;
8394 illegal_op:
8395 gen_illegal_opcode(s);
8396 return s->pc;
8397 unknown_op:
8398 gen_unknown_opcode(env, s);
8399 return s->pc;
8402 void tcg_x86_init(void)
8404 static const char reg_names[CPU_NB_REGS][4] = {
8405 #ifdef TARGET_X86_64
8406 [R_EAX] = "rax",
8407 [R_EBX] = "rbx",
8408 [R_ECX] = "rcx",
8409 [R_EDX] = "rdx",
8410 [R_ESI] = "rsi",
8411 [R_EDI] = "rdi",
8412 [R_EBP] = "rbp",
8413 [R_ESP] = "rsp",
8414 [8] = "r8",
8415 [9] = "r9",
8416 [10] = "r10",
8417 [11] = "r11",
8418 [12] = "r12",
8419 [13] = "r13",
8420 [14] = "r14",
8421 [15] = "r15",
8422 #else
8423 [R_EAX] = "eax",
8424 [R_EBX] = "ebx",
8425 [R_ECX] = "ecx",
8426 [R_EDX] = "edx",
8427 [R_ESI] = "esi",
8428 [R_EDI] = "edi",
8429 [R_EBP] = "ebp",
8430 [R_ESP] = "esp",
8431 #endif
8433 static const char seg_base_names[6][8] = {
8434 [R_CS] = "cs_base",
8435 [R_DS] = "ds_base",
8436 [R_ES] = "es_base",
8437 [R_FS] = "fs_base",
8438 [R_GS] = "gs_base",
8439 [R_SS] = "ss_base",
8441 static const char bnd_regl_names[4][8] = {
8442 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8444 static const char bnd_regu_names[4][8] = {
8445 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8447 int i;
8449 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8450 offsetof(CPUX86State, cc_op), "cc_op");
8451 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8452 "cc_dst");
8453 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8454 "cc_src");
8455 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8456 "cc_src2");
8458 for (i = 0; i < CPU_NB_REGS; ++i) {
8459 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8460 offsetof(CPUX86State, regs[i]),
8461 reg_names[i]);
8464 for (i = 0; i < 6; ++i) {
8465 cpu_seg_base[i]
8466 = tcg_global_mem_new(cpu_env,
8467 offsetof(CPUX86State, segs[i].base),
8468 seg_base_names[i]);
8471 for (i = 0; i < 4; ++i) {
8472 cpu_bndl[i]
8473 = tcg_global_mem_new_i64(cpu_env,
8474 offsetof(CPUX86State, bnd_regs[i].lb),
8475 bnd_regl_names[i]);
8476 cpu_bndu[i]
8477 = tcg_global_mem_new_i64(cpu_env,
8478 offsetof(CPUX86State, bnd_regs[i].ub),
8479 bnd_regu_names[i]);
8483 static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
8485 DisasContext *dc = container_of(dcbase, DisasContext, base);
8486 CPUX86State *env = cpu->env_ptr;
8487 uint32_t flags = dc->base.tb->flags;
8488 int cpl = (flags >> HF_CPL_SHIFT) & 3;
8489 int iopl = (flags >> IOPL_SHIFT) & 3;
8491 dc->cs_base = dc->base.tb->cs_base;
8492 dc->flags = flags;
8493 #ifndef CONFIG_USER_ONLY
8494 dc->cpl = cpl;
8495 dc->iopl = iopl;
8496 #endif
8498 /* We make some simplifying assumptions; validate they're correct. */
8499 g_assert(PE(dc) == ((flags & HF_PE_MASK) != 0));
8500 g_assert(CPL(dc) == cpl);
8501 g_assert(IOPL(dc) == iopl);
8502 g_assert(VM86(dc) == ((flags & HF_VM_MASK) != 0));
8503 g_assert(CODE32(dc) == ((flags & HF_CS32_MASK) != 0));
8504 g_assert(CODE64(dc) == ((flags & HF_CS64_MASK) != 0));
8505 g_assert(SS32(dc) == ((flags & HF_SS32_MASK) != 0));
8506 g_assert(LMA(dc) == ((flags & HF_LMA_MASK) != 0));
8507 g_assert(ADDSEG(dc) == ((flags & HF_ADDSEG_MASK) != 0));
8509 dc->tf = (flags >> TF_SHIFT) & 1;
8510 dc->cc_op = CC_OP_DYNAMIC;
8511 dc->cc_op_dirty = false;
8512 dc->popl_esp_hack = 0;
8513 /* select memory access functions */
8514 dc->mem_index = 0;
8515 #ifdef CONFIG_SOFTMMU
8516 dc->mem_index = cpu_mmu_index(env, false);
8517 #endif
8518 dc->cpuid_features = env->features[FEAT_1_EDX];
8519 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8520 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8521 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8522 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8523 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8524 dc->jmp_opt = !(dc->tf || dc->base.singlestep_enabled ||
8525 (flags & HF_INHIBIT_IRQ_MASK));
8526 /* Do not optimize repz jumps at all in icount mode, because
8527 rep movsS instructions are execured with different paths
8528 in !repz_opt and repz_opt modes. The first one was used
8529 always except single step mode. And this setting
8530 disables jumps optimization and control paths become
8531 equivalent in run and single step modes.
8532 Now there will be no jump optimization for repz in
8533 record/replay modes and there will always be an
8534 additional step for ecx=0 when icount is enabled.
8536 dc->repz_opt = !dc->jmp_opt && !(tb_cflags(dc->base.tb) & CF_USE_ICOUNT);
8538 dc->T0 = tcg_temp_new();
8539 dc->T1 = tcg_temp_new();
8540 dc->A0 = tcg_temp_new();
8542 dc->tmp0 = tcg_temp_new();
8543 dc->tmp1_i64 = tcg_temp_new_i64();
8544 dc->tmp2_i32 = tcg_temp_new_i32();
8545 dc->tmp3_i32 = tcg_temp_new_i32();
8546 dc->tmp4 = tcg_temp_new();
8547 dc->ptr0 = tcg_temp_new_ptr();
8548 dc->ptr1 = tcg_temp_new_ptr();
8549 dc->cc_srcT = tcg_temp_local_new();
8552 static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
8556 static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8558 DisasContext *dc = container_of(dcbase, DisasContext, base);
8560 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
8563 static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8564 const CPUBreakpoint *bp)
8566 DisasContext *dc = container_of(dcbase, DisasContext, base);
8567 /* If RF is set, suppress an internally generated breakpoint. */
8568 int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
8569 if (bp->flags & flags) {
8570 gen_debug(dc, dc->base.pc_next - dc->cs_base);
8571 dc->base.is_jmp = DISAS_NORETURN;
8572 /* The address covered by the breakpoint must be included in
8573 [tb->pc, tb->pc + tb->size) in order to for it to be
8574 properly cleared -- thus we increment the PC here so that
8575 the generic logic setting tb->size later does the right thing. */
8576 dc->base.pc_next += 1;
8577 return true;
8578 } else {
8579 return false;
8583 static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8585 DisasContext *dc = container_of(dcbase, DisasContext, base);
8586 target_ulong pc_next;
8588 #ifdef TARGET_VSYSCALL_PAGE
8590 * Detect entry into the vsyscall page and invoke the syscall.
8592 if ((dc->base.pc_next & TARGET_PAGE_MASK) == TARGET_VSYSCALL_PAGE) {
8593 gen_exception(dc, EXCP_VSYSCALL, dc->base.pc_next);
8594 return;
8596 #endif
8598 pc_next = disas_insn(dc, cpu);
8600 if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
8601 /* if single step mode, we generate only one instruction and
8602 generate an exception */
8603 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8604 the flag and abort the translation to give the irqs a
8605 chance to happen */
8606 dc->base.is_jmp = DISAS_TOO_MANY;
8607 } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
8608 && ((pc_next & TARGET_PAGE_MASK)
8609 != ((pc_next + TARGET_MAX_INSN_SIZE - 1)
8610 & TARGET_PAGE_MASK)
8611 || (pc_next & ~TARGET_PAGE_MASK) == 0)) {
8612 /* Do not cross the boundary of the pages in icount mode,
8613 it can cause an exception. Do it only when boundary is
8614 crossed by the first instruction in the block.
8615 If current instruction already crossed the bound - it's ok,
8616 because an exception hasn't stopped this code.
8618 dc->base.is_jmp = DISAS_TOO_MANY;
8619 } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
8620 dc->base.is_jmp = DISAS_TOO_MANY;
8623 dc->base.pc_next = pc_next;
8626 static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8628 DisasContext *dc = container_of(dcbase, DisasContext, base);
8630 if (dc->base.is_jmp == DISAS_TOO_MANY) {
8631 gen_jmp_im(dc, dc->base.pc_next - dc->cs_base);
8632 gen_eob(dc);
8636 static void i386_tr_disas_log(const DisasContextBase *dcbase,
8637 CPUState *cpu)
8639 DisasContext *dc = container_of(dcbase, DisasContext, base);
8641 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
8642 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
8645 static const TranslatorOps i386_tr_ops = {
8646 .init_disas_context = i386_tr_init_disas_context,
8647 .tb_start = i386_tr_tb_start,
8648 .insn_start = i386_tr_insn_start,
8649 .breakpoint_check = i386_tr_breakpoint_check,
8650 .translate_insn = i386_tr_translate_insn,
8651 .tb_stop = i386_tr_tb_stop,
8652 .disas_log = i386_tr_disas_log,
8655 /* generate intermediate code for basic block 'tb'. */
8656 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
8658 DisasContext dc;
8660 translator_loop(&i386_tr_ops, &dc.base, cpu, tb, max_insns);
8663 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8664 target_ulong *data)
8666 int cc_op = data[1];
8667 env->eip = data[0] - tb->cs_base;
8668 if (cc_op != CC_OP_DYNAMIC) {
8669 env->cc_op = cc_op;