target/i386: Assert !GUEST for user-only
[qemu/ar7.git] / target / i386 / tcg / translate.c
blob200d205d7e6656df9a0965415f734eb7d524f59e
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 target_ulong pc; /* pc = eip + cs_base */
80 target_ulong pc_start; /* pc at TB entry */
81 target_ulong cs_base; /* base of CS segment */
83 MemOp aflag;
84 MemOp dflag;
86 int8_t override; /* -1 if no override, else R_CS, R_DS, etc */
87 uint8_t prefix;
89 #ifndef CONFIG_USER_ONLY
90 uint8_t cpl; /* code priv level */
91 uint8_t iopl; /* i/o priv level */
92 #endif
93 uint8_t vex_l; /* vex vector length */
94 uint8_t vex_v; /* vex vvvv register, without 1's complement. */
95 uint8_t popl_esp_hack; /* for correct popl with esp base handling */
96 uint8_t rip_offset; /* only used in x86_64, but left for simplicity */
98 #ifdef TARGET_X86_64
99 uint8_t rex_r;
100 uint8_t rex_x;
101 uint8_t rex_b;
102 bool rex_w;
103 #endif
104 bool jmp_opt; /* use direct block chaining for direct jumps */
105 bool repz_opt; /* optimize jumps within repz instructions */
106 bool cc_op_dirty;
108 CCOp cc_op; /* current CC operation */
109 int mem_index; /* select memory access functions */
110 uint32_t flags; /* all execution flags */
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 #define SVME(S) false
142 #define GUEST(S) false
143 #else
144 #define PE(S) (((S)->flags & HF_PE_MASK) != 0)
145 #define CPL(S) ((S)->cpl)
146 #define IOPL(S) ((S)->iopl)
147 #define SVME(S) (((S)->flags & HF_SVME_MASK) != 0)
148 #define GUEST(S) (((S)->flags & HF_GUEST_MASK) != 0)
149 #endif
150 #if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
151 #define VM86(S) false
152 #define CODE32(S) true
153 #define SS32(S) true
154 #define ADDSEG(S) false
155 #else
156 #define VM86(S) (((S)->flags & HF_VM_MASK) != 0)
157 #define CODE32(S) (((S)->flags & HF_CS32_MASK) != 0)
158 #define SS32(S) (((S)->flags & HF_SS32_MASK) != 0)
159 #define ADDSEG(S) (((S)->flags & HF_ADDSEG_MASK) != 0)
160 #endif
161 #if !defined(TARGET_X86_64)
162 #define CODE64(S) false
163 #define LMA(S) false
164 #elif defined(CONFIG_USER_ONLY)
165 #define CODE64(S) true
166 #define LMA(S) true
167 #else
168 #define CODE64(S) (((S)->flags & HF_CS64_MASK) != 0)
169 #define LMA(S) (((S)->flags & HF_LMA_MASK) != 0)
170 #endif
172 #ifdef TARGET_X86_64
173 #define REX_PREFIX(S) (((S)->prefix & PREFIX_REX) != 0)
174 #define REX_W(S) ((S)->rex_w)
175 #define REX_R(S) ((S)->rex_r + 0)
176 #define REX_X(S) ((S)->rex_x + 0)
177 #define REX_B(S) ((S)->rex_b + 0)
178 #else
179 #define REX_PREFIX(S) false
180 #define REX_W(S) false
181 #define REX_R(S) 0
182 #define REX_X(S) 0
183 #define REX_B(S) 0
184 #endif
187 * Many sysemu-only helpers are not reachable for user-only.
188 * Define stub generators here, so that we need not either sprinkle
189 * ifdefs through the translator, nor provide the helper function.
191 #define STUB_HELPER(NAME, ...) \
192 static inline void gen_helper_##NAME(__VA_ARGS__) \
193 { qemu_build_not_reached(); }
195 #ifdef CONFIG_USER_ONLY
196 STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
197 #endif
199 static void gen_eob(DisasContext *s);
200 static void gen_jr(DisasContext *s, TCGv dest);
201 static void gen_jmp(DisasContext *s, target_ulong eip);
202 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
203 static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
205 /* i386 arith/logic operations */
206 enum {
207 OP_ADDL,
208 OP_ORL,
209 OP_ADCL,
210 OP_SBBL,
211 OP_ANDL,
212 OP_SUBL,
213 OP_XORL,
214 OP_CMPL,
217 /* i386 shift ops */
218 enum {
219 OP_ROL,
220 OP_ROR,
221 OP_RCL,
222 OP_RCR,
223 OP_SHL,
224 OP_SHR,
225 OP_SHL1, /* undocumented */
226 OP_SAR = 7,
229 enum {
230 JCC_O,
231 JCC_B,
232 JCC_Z,
233 JCC_BE,
234 JCC_S,
235 JCC_P,
236 JCC_L,
237 JCC_LE,
240 enum {
241 /* I386 int registers */
242 OR_EAX, /* MUST be even numbered */
243 OR_ECX,
244 OR_EDX,
245 OR_EBX,
246 OR_ESP,
247 OR_EBP,
248 OR_ESI,
249 OR_EDI,
251 OR_TMP0 = 16, /* temporary operand register */
252 OR_TMP1,
253 OR_A0, /* temporary register used when doing address evaluation */
256 enum {
257 USES_CC_DST = 1,
258 USES_CC_SRC = 2,
259 USES_CC_SRC2 = 4,
260 USES_CC_SRCT = 8,
263 /* Bit set if the global variable is live after setting CC_OP to X. */
264 static const uint8_t cc_op_live[CC_OP_NB] = {
265 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
266 [CC_OP_EFLAGS] = USES_CC_SRC,
267 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
268 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
269 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
270 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
271 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
272 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
273 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
274 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
275 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
276 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
277 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
278 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
279 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
280 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
281 [CC_OP_CLR] = 0,
282 [CC_OP_POPCNT] = USES_CC_SRC,
285 static void set_cc_op(DisasContext *s, CCOp op)
287 int dead;
289 if (s->cc_op == op) {
290 return;
293 /* Discard CC computation that will no longer be used. */
294 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
295 if (dead & USES_CC_DST) {
296 tcg_gen_discard_tl(cpu_cc_dst);
298 if (dead & USES_CC_SRC) {
299 tcg_gen_discard_tl(cpu_cc_src);
301 if (dead & USES_CC_SRC2) {
302 tcg_gen_discard_tl(cpu_cc_src2);
304 if (dead & USES_CC_SRCT) {
305 tcg_gen_discard_tl(s->cc_srcT);
308 if (op == CC_OP_DYNAMIC) {
309 /* The DYNAMIC setting is translator only, and should never be
310 stored. Thus we always consider it clean. */
311 s->cc_op_dirty = false;
312 } else {
313 /* Discard any computed CC_OP value (see shifts). */
314 if (s->cc_op == CC_OP_DYNAMIC) {
315 tcg_gen_discard_i32(cpu_cc_op);
317 s->cc_op_dirty = true;
319 s->cc_op = op;
322 static void gen_update_cc_op(DisasContext *s)
324 if (s->cc_op_dirty) {
325 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
326 s->cc_op_dirty = false;
330 #ifdef TARGET_X86_64
332 #define NB_OP_SIZES 4
334 #else /* !TARGET_X86_64 */
336 #define NB_OP_SIZES 3
338 #endif /* !TARGET_X86_64 */
340 #if defined(HOST_WORDS_BIGENDIAN)
341 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
342 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
343 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
344 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
345 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
346 #else
347 #define REG_B_OFFSET 0
348 #define REG_H_OFFSET 1
349 #define REG_W_OFFSET 0
350 #define REG_L_OFFSET 0
351 #define REG_LH_OFFSET 4
352 #endif
354 /* In instruction encodings for byte register accesses the
355 * register number usually indicates "low 8 bits of register N";
356 * however there are some special cases where N 4..7 indicates
357 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
358 * true for this special case, false otherwise.
360 static inline bool byte_reg_is_xH(DisasContext *s, int reg)
362 /* Any time the REX prefix is present, byte registers are uniform */
363 if (reg < 4 || REX_PREFIX(s)) {
364 return false;
366 return true;
369 /* Select the size of a push/pop operation. */
370 static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
372 if (CODE64(s)) {
373 return ot == MO_16 ? MO_16 : MO_64;
374 } else {
375 return ot;
379 /* Select the size of the stack pointer. */
380 static inline MemOp mo_stacksize(DisasContext *s)
382 return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
385 /* Select only size 64 else 32. Used for SSE operand sizes. */
386 static inline MemOp mo_64_32(MemOp ot)
388 #ifdef TARGET_X86_64
389 return ot == MO_64 ? MO_64 : MO_32;
390 #else
391 return MO_32;
392 #endif
395 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
396 byte vs word opcodes. */
397 static inline MemOp mo_b_d(int b, MemOp ot)
399 return b & 1 ? ot : MO_8;
402 /* Select size 8 if lsb of B is clear, else OT capped at 32.
403 Used for decoding operand size of port opcodes. */
404 static inline MemOp mo_b_d32(int b, MemOp ot)
406 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
409 static void gen_op_mov_reg_v(DisasContext *s, MemOp ot, int reg, TCGv t0)
411 switch(ot) {
412 case MO_8:
413 if (!byte_reg_is_xH(s, reg)) {
414 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
415 } else {
416 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
418 break;
419 case MO_16:
420 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
421 break;
422 case MO_32:
423 /* For x86_64, this sets the higher half of register to zero.
424 For i386, this is equivalent to a mov. */
425 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
426 break;
427 #ifdef TARGET_X86_64
428 case MO_64:
429 tcg_gen_mov_tl(cpu_regs[reg], t0);
430 break;
431 #endif
432 default:
433 tcg_abort();
437 static inline
438 void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg)
440 if (ot == MO_8 && byte_reg_is_xH(s, reg)) {
441 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
442 } else {
443 tcg_gen_mov_tl(t0, cpu_regs[reg]);
447 static void gen_add_A0_im(DisasContext *s, int val)
449 tcg_gen_addi_tl(s->A0, s->A0, val);
450 if (!CODE64(s)) {
451 tcg_gen_ext32u_tl(s->A0, s->A0);
455 static inline void gen_op_jmp_v(TCGv dest)
457 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
460 static inline
461 void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val)
463 tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val);
464 gen_op_mov_reg_v(s, size, reg, s->tmp0);
467 static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg)
469 tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0);
470 gen_op_mov_reg_v(s, size, reg, s->tmp0);
473 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
475 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
478 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
480 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
483 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
485 if (d == OR_TMP0) {
486 gen_op_st_v(s, idx, s->T0, s->A0);
487 } else {
488 gen_op_mov_reg_v(s, idx, d, s->T0);
492 static inline void gen_jmp_im(DisasContext *s, target_ulong pc)
494 tcg_gen_movi_tl(s->tmp0, pc);
495 gen_op_jmp_v(s->tmp0);
498 /* Compute SEG:REG into A0. SEG is selected from the override segment
499 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
500 indicate no override. */
501 static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
502 int def_seg, int ovr_seg)
504 switch (aflag) {
505 #ifdef TARGET_X86_64
506 case MO_64:
507 if (ovr_seg < 0) {
508 tcg_gen_mov_tl(s->A0, a0);
509 return;
511 break;
512 #endif
513 case MO_32:
514 /* 32 bit address */
515 if (ovr_seg < 0 && ADDSEG(s)) {
516 ovr_seg = def_seg;
518 if (ovr_seg < 0) {
519 tcg_gen_ext32u_tl(s->A0, a0);
520 return;
522 break;
523 case MO_16:
524 /* 16 bit address */
525 tcg_gen_ext16u_tl(s->A0, a0);
526 a0 = s->A0;
527 if (ovr_seg < 0) {
528 if (ADDSEG(s)) {
529 ovr_seg = def_seg;
530 } else {
531 return;
534 break;
535 default:
536 tcg_abort();
539 if (ovr_seg >= 0) {
540 TCGv seg = cpu_seg_base[ovr_seg];
542 if (aflag == MO_64) {
543 tcg_gen_add_tl(s->A0, a0, seg);
544 } else if (CODE64(s)) {
545 tcg_gen_ext32u_tl(s->A0, a0);
546 tcg_gen_add_tl(s->A0, s->A0, seg);
547 } else {
548 tcg_gen_add_tl(s->A0, a0, seg);
549 tcg_gen_ext32u_tl(s->A0, s->A0);
554 static inline void gen_string_movl_A0_ESI(DisasContext *s)
556 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
559 static inline void gen_string_movl_A0_EDI(DisasContext *s)
561 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
564 static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
566 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
567 tcg_gen_shli_tl(s->T0, s->T0, ot);
570 static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
572 switch (size) {
573 case MO_8:
574 if (sign) {
575 tcg_gen_ext8s_tl(dst, src);
576 } else {
577 tcg_gen_ext8u_tl(dst, src);
579 return dst;
580 case MO_16:
581 if (sign) {
582 tcg_gen_ext16s_tl(dst, src);
583 } else {
584 tcg_gen_ext16u_tl(dst, src);
586 return dst;
587 #ifdef TARGET_X86_64
588 case MO_32:
589 if (sign) {
590 tcg_gen_ext32s_tl(dst, src);
591 } else {
592 tcg_gen_ext32u_tl(dst, src);
594 return dst;
595 #endif
596 default:
597 return src;
601 static void gen_extu(MemOp ot, TCGv reg)
603 gen_ext_tl(reg, reg, ot, false);
606 static void gen_exts(MemOp ot, TCGv reg)
608 gen_ext_tl(reg, reg, ot, true);
611 static inline
612 void gen_op_jnz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
614 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
615 gen_extu(size, s->tmp0);
616 tcg_gen_brcondi_tl(TCG_COND_NE, s->tmp0, 0, label1);
619 static inline
620 void gen_op_jz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
622 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
623 gen_extu(size, s->tmp0);
624 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
627 static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
629 switch (ot) {
630 case MO_8:
631 gen_helper_inb(v, cpu_env, n);
632 break;
633 case MO_16:
634 gen_helper_inw(v, cpu_env, n);
635 break;
636 case MO_32:
637 gen_helper_inl(v, cpu_env, n);
638 break;
639 default:
640 tcg_abort();
644 static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
646 switch (ot) {
647 case MO_8:
648 gen_helper_outb(cpu_env, v, n);
649 break;
650 case MO_16:
651 gen_helper_outw(cpu_env, v, n);
652 break;
653 case MO_32:
654 gen_helper_outl(cpu_env, v, n);
655 break;
656 default:
657 tcg_abort();
661 static void gen_check_io(DisasContext *s, MemOp ot, target_ulong cur_eip,
662 uint32_t svm_flags)
664 target_ulong next_eip;
666 if (PE(s) && (CPL(s) > IOPL(s) || VM86(s))) {
667 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
668 switch (ot) {
669 case MO_8:
670 gen_helper_check_iob(cpu_env, s->tmp2_i32);
671 break;
672 case MO_16:
673 gen_helper_check_iow(cpu_env, s->tmp2_i32);
674 break;
675 case MO_32:
676 gen_helper_check_iol(cpu_env, s->tmp2_i32);
677 break;
678 default:
679 tcg_abort();
682 if (GUEST(s)) {
683 gen_update_cc_op(s);
684 gen_jmp_im(s, cur_eip);
685 svm_flags |= (1 << (4 + ot));
686 next_eip = s->pc - s->cs_base;
687 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
688 gen_helper_svm_check_io(cpu_env, s->tmp2_i32,
689 tcg_const_i32(svm_flags),
690 tcg_const_i32(next_eip - cur_eip));
694 static inline void gen_movs(DisasContext *s, MemOp ot)
696 gen_string_movl_A0_ESI(s);
697 gen_op_ld_v(s, ot, s->T0, s->A0);
698 gen_string_movl_A0_EDI(s);
699 gen_op_st_v(s, ot, s->T0, s->A0);
700 gen_op_movl_T0_Dshift(s, ot);
701 gen_op_add_reg_T0(s, s->aflag, R_ESI);
702 gen_op_add_reg_T0(s, s->aflag, R_EDI);
705 static void gen_op_update1_cc(DisasContext *s)
707 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
710 static void gen_op_update2_cc(DisasContext *s)
712 tcg_gen_mov_tl(cpu_cc_src, s->T1);
713 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
716 static void gen_op_update3_cc(DisasContext *s, TCGv reg)
718 tcg_gen_mov_tl(cpu_cc_src2, reg);
719 tcg_gen_mov_tl(cpu_cc_src, s->T1);
720 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
723 static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
725 tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1);
728 static void gen_op_update_neg_cc(DisasContext *s)
730 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
731 tcg_gen_neg_tl(cpu_cc_src, s->T0);
732 tcg_gen_movi_tl(s->cc_srcT, 0);
735 /* compute all eflags to cc_src */
736 static void gen_compute_eflags(DisasContext *s)
738 TCGv zero, dst, src1, src2;
739 int live, dead;
741 if (s->cc_op == CC_OP_EFLAGS) {
742 return;
744 if (s->cc_op == CC_OP_CLR) {
745 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
746 set_cc_op(s, CC_OP_EFLAGS);
747 return;
750 zero = NULL;
751 dst = cpu_cc_dst;
752 src1 = cpu_cc_src;
753 src2 = cpu_cc_src2;
755 /* Take care to not read values that are not live. */
756 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
757 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
758 if (dead) {
759 zero = tcg_const_tl(0);
760 if (dead & USES_CC_DST) {
761 dst = zero;
763 if (dead & USES_CC_SRC) {
764 src1 = zero;
766 if (dead & USES_CC_SRC2) {
767 src2 = zero;
771 gen_update_cc_op(s);
772 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
773 set_cc_op(s, CC_OP_EFLAGS);
775 if (dead) {
776 tcg_temp_free(zero);
780 typedef struct CCPrepare {
781 TCGCond cond;
782 TCGv reg;
783 TCGv reg2;
784 target_ulong imm;
785 target_ulong mask;
786 bool use_reg2;
787 bool no_setcond;
788 } CCPrepare;
790 /* compute eflags.C to reg */
791 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
793 TCGv t0, t1;
794 int size, shift;
796 switch (s->cc_op) {
797 case CC_OP_SUBB ... CC_OP_SUBQ:
798 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
799 size = s->cc_op - CC_OP_SUBB;
800 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
801 /* If no temporary was used, be careful not to alias t1 and t0. */
802 t0 = t1 == cpu_cc_src ? s->tmp0 : reg;
803 tcg_gen_mov_tl(t0, s->cc_srcT);
804 gen_extu(size, t0);
805 goto add_sub;
807 case CC_OP_ADDB ... CC_OP_ADDQ:
808 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
809 size = s->cc_op - CC_OP_ADDB;
810 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
811 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
812 add_sub:
813 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
814 .reg2 = t1, .mask = -1, .use_reg2 = true };
816 case CC_OP_LOGICB ... CC_OP_LOGICQ:
817 case CC_OP_CLR:
818 case CC_OP_POPCNT:
819 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
821 case CC_OP_INCB ... CC_OP_INCQ:
822 case CC_OP_DECB ... CC_OP_DECQ:
823 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
824 .mask = -1, .no_setcond = true };
826 case CC_OP_SHLB ... CC_OP_SHLQ:
827 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
828 size = s->cc_op - CC_OP_SHLB;
829 shift = (8 << size) - 1;
830 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
831 .mask = (target_ulong)1 << shift };
833 case CC_OP_MULB ... CC_OP_MULQ:
834 return (CCPrepare) { .cond = TCG_COND_NE,
835 .reg = cpu_cc_src, .mask = -1 };
837 case CC_OP_BMILGB ... CC_OP_BMILGQ:
838 size = s->cc_op - CC_OP_BMILGB;
839 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
840 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
842 case CC_OP_ADCX:
843 case CC_OP_ADCOX:
844 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
845 .mask = -1, .no_setcond = true };
847 case CC_OP_EFLAGS:
848 case CC_OP_SARB ... CC_OP_SARQ:
849 /* CC_SRC & 1 */
850 return (CCPrepare) { .cond = TCG_COND_NE,
851 .reg = cpu_cc_src, .mask = CC_C };
853 default:
854 /* The need to compute only C from CC_OP_DYNAMIC is important
855 in efficiently implementing e.g. INC at the start of a TB. */
856 gen_update_cc_op(s);
857 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
858 cpu_cc_src2, cpu_cc_op);
859 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
860 .mask = -1, .no_setcond = true };
864 /* compute eflags.P to reg */
865 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
867 gen_compute_eflags(s);
868 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
869 .mask = CC_P };
872 /* compute eflags.S to reg */
873 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
875 switch (s->cc_op) {
876 case CC_OP_DYNAMIC:
877 gen_compute_eflags(s);
878 /* FALLTHRU */
879 case CC_OP_EFLAGS:
880 case CC_OP_ADCX:
881 case CC_OP_ADOX:
882 case CC_OP_ADCOX:
883 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
884 .mask = CC_S };
885 case CC_OP_CLR:
886 case CC_OP_POPCNT:
887 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
888 default:
890 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
891 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
892 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
897 /* compute eflags.O to reg */
898 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
900 switch (s->cc_op) {
901 case CC_OP_ADOX:
902 case CC_OP_ADCOX:
903 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
904 .mask = -1, .no_setcond = true };
905 case CC_OP_CLR:
906 case CC_OP_POPCNT:
907 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
908 default:
909 gen_compute_eflags(s);
910 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
911 .mask = CC_O };
915 /* compute eflags.Z to reg */
916 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
918 switch (s->cc_op) {
919 case CC_OP_DYNAMIC:
920 gen_compute_eflags(s);
921 /* FALLTHRU */
922 case CC_OP_EFLAGS:
923 case CC_OP_ADCX:
924 case CC_OP_ADOX:
925 case CC_OP_ADCOX:
926 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
927 .mask = CC_Z };
928 case CC_OP_CLR:
929 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
930 case CC_OP_POPCNT:
931 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
932 .mask = -1 };
933 default:
935 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
936 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
937 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
942 /* perform a conditional store into register 'reg' according to jump opcode
943 value 'b'. In the fast case, T0 is guaranted not to be used. */
944 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
946 int inv, jcc_op, cond;
947 MemOp size;
948 CCPrepare cc;
949 TCGv t0;
951 inv = b & 1;
952 jcc_op = (b >> 1) & 7;
954 switch (s->cc_op) {
955 case CC_OP_SUBB ... CC_OP_SUBQ:
956 /* We optimize relational operators for the cmp/jcc case. */
957 size = s->cc_op - CC_OP_SUBB;
958 switch (jcc_op) {
959 case JCC_BE:
960 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
961 gen_extu(size, s->tmp4);
962 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
963 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4,
964 .reg2 = t0, .mask = -1, .use_reg2 = true };
965 break;
967 case JCC_L:
968 cond = TCG_COND_LT;
969 goto fast_jcc_l;
970 case JCC_LE:
971 cond = TCG_COND_LE;
972 fast_jcc_l:
973 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
974 gen_exts(size, s->tmp4);
975 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true);
976 cc = (CCPrepare) { .cond = cond, .reg = s->tmp4,
977 .reg2 = t0, .mask = -1, .use_reg2 = true };
978 break;
980 default:
981 goto slow_jcc;
983 break;
985 default:
986 slow_jcc:
987 /* This actually generates good code for JC, JZ and JS. */
988 switch (jcc_op) {
989 case JCC_O:
990 cc = gen_prepare_eflags_o(s, reg);
991 break;
992 case JCC_B:
993 cc = gen_prepare_eflags_c(s, reg);
994 break;
995 case JCC_Z:
996 cc = gen_prepare_eflags_z(s, reg);
997 break;
998 case JCC_BE:
999 gen_compute_eflags(s);
1000 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1001 .mask = CC_Z | CC_C };
1002 break;
1003 case JCC_S:
1004 cc = gen_prepare_eflags_s(s, reg);
1005 break;
1006 case JCC_P:
1007 cc = gen_prepare_eflags_p(s, reg);
1008 break;
1009 case JCC_L:
1010 gen_compute_eflags(s);
1011 if (reg == cpu_cc_src) {
1012 reg = s->tmp0;
1014 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1015 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1016 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1017 .mask = CC_S };
1018 break;
1019 default:
1020 case JCC_LE:
1021 gen_compute_eflags(s);
1022 if (reg == cpu_cc_src) {
1023 reg = s->tmp0;
1025 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1026 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1027 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1028 .mask = CC_S | CC_Z };
1029 break;
1031 break;
1034 if (inv) {
1035 cc.cond = tcg_invert_cond(cc.cond);
1037 return cc;
1040 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1042 CCPrepare cc = gen_prepare_cc(s, b, reg);
1044 if (cc.no_setcond) {
1045 if (cc.cond == TCG_COND_EQ) {
1046 tcg_gen_xori_tl(reg, cc.reg, 1);
1047 } else {
1048 tcg_gen_mov_tl(reg, cc.reg);
1050 return;
1053 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1054 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1055 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1056 tcg_gen_andi_tl(reg, reg, 1);
1057 return;
1059 if (cc.mask != -1) {
1060 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1061 cc.reg = reg;
1063 if (cc.use_reg2) {
1064 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1065 } else {
1066 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1070 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1072 gen_setcc1(s, JCC_B << 1, reg);
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 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1079 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1081 if (cc.mask != -1) {
1082 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1083 cc.reg = s->T0;
1085 if (cc.use_reg2) {
1086 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1087 } else {
1088 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1092 /* Generate a conditional jump to label 'l1' according to jump opcode
1093 value 'b'. In the fast case, T0 is guaranted not to be used.
1094 A translation block must end soon. */
1095 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1097 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1099 gen_update_cc_op(s);
1100 if (cc.mask != -1) {
1101 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1102 cc.reg = s->T0;
1104 set_cc_op(s, CC_OP_DYNAMIC);
1105 if (cc.use_reg2) {
1106 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1107 } else {
1108 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1112 /* XXX: does not work with gdbstub "ice" single step - not a
1113 serious problem */
1114 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1116 TCGLabel *l1 = gen_new_label();
1117 TCGLabel *l2 = gen_new_label();
1118 gen_op_jnz_ecx(s, s->aflag, l1);
1119 gen_set_label(l2);
1120 gen_jmp_tb(s, next_eip, 1);
1121 gen_set_label(l1);
1122 return l2;
1125 static inline void gen_stos(DisasContext *s, MemOp ot)
1127 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
1128 gen_string_movl_A0_EDI(s);
1129 gen_op_st_v(s, ot, s->T0, s->A0);
1130 gen_op_movl_T0_Dshift(s, ot);
1131 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1134 static inline void gen_lods(DisasContext *s, MemOp ot)
1136 gen_string_movl_A0_ESI(s);
1137 gen_op_ld_v(s, ot, s->T0, s->A0);
1138 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
1139 gen_op_movl_T0_Dshift(s, ot);
1140 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1143 static inline void gen_scas(DisasContext *s, MemOp ot)
1145 gen_string_movl_A0_EDI(s);
1146 gen_op_ld_v(s, ot, s->T1, s->A0);
1147 gen_op(s, OP_CMPL, ot, R_EAX);
1148 gen_op_movl_T0_Dshift(s, ot);
1149 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1152 static inline void gen_cmps(DisasContext *s, MemOp ot)
1154 gen_string_movl_A0_EDI(s);
1155 gen_op_ld_v(s, ot, s->T1, s->A0);
1156 gen_string_movl_A0_ESI(s);
1157 gen_op(s, OP_CMPL, ot, OR_TMP0);
1158 gen_op_movl_T0_Dshift(s, ot);
1159 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1160 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1163 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1165 if (s->flags & HF_IOBPT_MASK) {
1166 #ifdef CONFIG_USER_ONLY
1167 /* user-mode cpu should not be in IOBPT mode */
1168 g_assert_not_reached();
1169 #else
1170 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1171 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1173 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1174 tcg_temp_free_i32(t_size);
1175 tcg_temp_free(t_next);
1176 #endif /* CONFIG_USER_ONLY */
1180 static inline void gen_ins(DisasContext *s, MemOp ot)
1182 gen_string_movl_A0_EDI(s);
1183 /* Note: we must do this dummy write first to be restartable in
1184 case of page fault. */
1185 tcg_gen_movi_tl(s->T0, 0);
1186 gen_op_st_v(s, ot, s->T0, s->A0);
1187 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1188 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1189 gen_helper_in_func(ot, s->T0, s->tmp2_i32);
1190 gen_op_st_v(s, ot, s->T0, s->A0);
1191 gen_op_movl_T0_Dshift(s, ot);
1192 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1193 gen_bpt_io(s, s->tmp2_i32, ot);
1196 static inline void gen_outs(DisasContext *s, MemOp ot)
1198 gen_string_movl_A0_ESI(s);
1199 gen_op_ld_v(s, ot, s->T0, s->A0);
1201 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1202 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1203 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0);
1204 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
1205 gen_op_movl_T0_Dshift(s, ot);
1206 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1207 gen_bpt_io(s, s->tmp2_i32, ot);
1210 /* same method as Valgrind : we generate jumps to current or next
1211 instruction */
1212 #define GEN_REPZ(op) \
1213 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1214 target_ulong cur_eip, target_ulong next_eip) \
1216 TCGLabel *l2; \
1217 gen_update_cc_op(s); \
1218 l2 = gen_jz_ecx_string(s, next_eip); \
1219 gen_ ## op(s, ot); \
1220 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1221 /* a loop would cause two single step exceptions if ECX = 1 \
1222 before rep string_insn */ \
1223 if (s->repz_opt) \
1224 gen_op_jz_ecx(s, s->aflag, l2); \
1225 gen_jmp(s, cur_eip); \
1228 #define GEN_REPZ2(op) \
1229 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1230 target_ulong cur_eip, \
1231 target_ulong next_eip, \
1232 int nz) \
1234 TCGLabel *l2; \
1235 gen_update_cc_op(s); \
1236 l2 = gen_jz_ecx_string(s, next_eip); \
1237 gen_ ## op(s, ot); \
1238 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1239 gen_update_cc_op(s); \
1240 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1241 if (s->repz_opt) \
1242 gen_op_jz_ecx(s, s->aflag, l2); \
1243 gen_jmp(s, cur_eip); \
1246 GEN_REPZ(movs)
1247 GEN_REPZ(stos)
1248 GEN_REPZ(lods)
1249 GEN_REPZ(ins)
1250 GEN_REPZ(outs)
1251 GEN_REPZ2(scas)
1252 GEN_REPZ2(cmps)
1254 static void gen_helper_fp_arith_ST0_FT0(int op)
1256 switch (op) {
1257 case 0:
1258 gen_helper_fadd_ST0_FT0(cpu_env);
1259 break;
1260 case 1:
1261 gen_helper_fmul_ST0_FT0(cpu_env);
1262 break;
1263 case 2:
1264 gen_helper_fcom_ST0_FT0(cpu_env);
1265 break;
1266 case 3:
1267 gen_helper_fcom_ST0_FT0(cpu_env);
1268 break;
1269 case 4:
1270 gen_helper_fsub_ST0_FT0(cpu_env);
1271 break;
1272 case 5:
1273 gen_helper_fsubr_ST0_FT0(cpu_env);
1274 break;
1275 case 6:
1276 gen_helper_fdiv_ST0_FT0(cpu_env);
1277 break;
1278 case 7:
1279 gen_helper_fdivr_ST0_FT0(cpu_env);
1280 break;
1284 /* NOTE the exception in "r" op ordering */
1285 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1287 TCGv_i32 tmp = tcg_const_i32(opreg);
1288 switch (op) {
1289 case 0:
1290 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1291 break;
1292 case 1:
1293 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1294 break;
1295 case 4:
1296 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1297 break;
1298 case 5:
1299 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1300 break;
1301 case 6:
1302 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1303 break;
1304 case 7:
1305 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1306 break;
1310 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
1312 gen_update_cc_op(s);
1313 gen_jmp_im(s, cur_eip);
1314 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
1315 s->base.is_jmp = DISAS_NORETURN;
1318 /* Generate #UD for the current instruction. The assumption here is that
1319 the instruction is known, but it isn't allowed in the current cpu mode. */
1320 static void gen_illegal_opcode(DisasContext *s)
1322 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
1325 /* Generate #GP for the current instruction. */
1326 static void gen_exception_gpf(DisasContext *s)
1328 gen_exception(s, EXCP0D_GPF, s->pc_start - s->cs_base);
1331 /* Check for cpl == 0; if not, raise #GP and return false. */
1332 static bool check_cpl0(DisasContext *s)
1334 if (CPL(s) == 0) {
1335 return true;
1337 gen_exception_gpf(s);
1338 return false;
1341 /* If vm86, check for iopl == 3; if not, raise #GP and return false. */
1342 static bool check_vm86_iopl(DisasContext *s)
1344 if (!VM86(s) || IOPL(s) == 3) {
1345 return true;
1347 gen_exception_gpf(s);
1348 return false;
1351 /* Check for iopl allowing access; if not, raise #GP and return false. */
1352 static bool check_iopl(DisasContext *s)
1354 if (VM86(s) ? IOPL(s) == 3 : CPL(s) <= IOPL(s)) {
1355 return true;
1357 gen_exception_gpf(s);
1358 return false;
1361 /* if d == OR_TMP0, it means memory operand (address in A0) */
1362 static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
1364 if (d != OR_TMP0) {
1365 if (s1->prefix & PREFIX_LOCK) {
1366 /* Lock prefix when destination is not memory. */
1367 gen_illegal_opcode(s1);
1368 return;
1370 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1371 } else if (!(s1->prefix & PREFIX_LOCK)) {
1372 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1374 switch(op) {
1375 case OP_ADCL:
1376 gen_compute_eflags_c(s1, s1->tmp4);
1377 if (s1->prefix & PREFIX_LOCK) {
1378 tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1);
1379 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1380 s1->mem_index, ot | MO_LE);
1381 } else {
1382 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1383 tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4);
1384 gen_op_st_rm_T0_A0(s1, ot, d);
1386 gen_op_update3_cc(s1, s1->tmp4);
1387 set_cc_op(s1, CC_OP_ADCB + ot);
1388 break;
1389 case OP_SBBL:
1390 gen_compute_eflags_c(s1, s1->tmp4);
1391 if (s1->prefix & PREFIX_LOCK) {
1392 tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4);
1393 tcg_gen_neg_tl(s1->T0, s1->T0);
1394 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1395 s1->mem_index, ot | MO_LE);
1396 } else {
1397 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1398 tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4);
1399 gen_op_st_rm_T0_A0(s1, ot, d);
1401 gen_op_update3_cc(s1, s1->tmp4);
1402 set_cc_op(s1, CC_OP_SBBB + ot);
1403 break;
1404 case OP_ADDL:
1405 if (s1->prefix & PREFIX_LOCK) {
1406 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1,
1407 s1->mem_index, ot | MO_LE);
1408 } else {
1409 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1410 gen_op_st_rm_T0_A0(s1, ot, d);
1412 gen_op_update2_cc(s1);
1413 set_cc_op(s1, CC_OP_ADDB + ot);
1414 break;
1415 case OP_SUBL:
1416 if (s1->prefix & PREFIX_LOCK) {
1417 tcg_gen_neg_tl(s1->T0, s1->T1);
1418 tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
1419 s1->mem_index, ot | MO_LE);
1420 tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
1421 } else {
1422 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1423 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1424 gen_op_st_rm_T0_A0(s1, ot, d);
1426 gen_op_update2_cc(s1);
1427 set_cc_op(s1, CC_OP_SUBB + ot);
1428 break;
1429 default:
1430 case OP_ANDL:
1431 if (s1->prefix & PREFIX_LOCK) {
1432 tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1,
1433 s1->mem_index, ot | MO_LE);
1434 } else {
1435 tcg_gen_and_tl(s1->T0, s1->T0, s1->T1);
1436 gen_op_st_rm_T0_A0(s1, ot, d);
1438 gen_op_update1_cc(s1);
1439 set_cc_op(s1, CC_OP_LOGICB + ot);
1440 break;
1441 case OP_ORL:
1442 if (s1->prefix & PREFIX_LOCK) {
1443 tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1,
1444 s1->mem_index, ot | MO_LE);
1445 } else {
1446 tcg_gen_or_tl(s1->T0, s1->T0, s1->T1);
1447 gen_op_st_rm_T0_A0(s1, ot, d);
1449 gen_op_update1_cc(s1);
1450 set_cc_op(s1, CC_OP_LOGICB + ot);
1451 break;
1452 case OP_XORL:
1453 if (s1->prefix & PREFIX_LOCK) {
1454 tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1,
1455 s1->mem_index, ot | MO_LE);
1456 } else {
1457 tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1);
1458 gen_op_st_rm_T0_A0(s1, ot, d);
1460 gen_op_update1_cc(s1);
1461 set_cc_op(s1, CC_OP_LOGICB + ot);
1462 break;
1463 case OP_CMPL:
1464 tcg_gen_mov_tl(cpu_cc_src, s1->T1);
1465 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1466 tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
1467 set_cc_op(s1, CC_OP_SUBB + ot);
1468 break;
1472 /* if d == OR_TMP0, it means memory operand (address in A0) */
1473 static void gen_inc(DisasContext *s1, MemOp ot, int d, int c)
1475 if (s1->prefix & PREFIX_LOCK) {
1476 if (d != OR_TMP0) {
1477 /* Lock prefix when destination is not memory */
1478 gen_illegal_opcode(s1);
1479 return;
1481 tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
1482 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1483 s1->mem_index, ot | MO_LE);
1484 } else {
1485 if (d != OR_TMP0) {
1486 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1487 } else {
1488 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1490 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
1491 gen_op_st_rm_T0_A0(s1, ot, d);
1494 gen_compute_eflags_c(s1, cpu_cc_src);
1495 tcg_gen_mov_tl(cpu_cc_dst, s1->T0);
1496 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1499 static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
1500 TCGv shm1, TCGv count, bool is_right)
1502 TCGv_i32 z32, s32, oldop;
1503 TCGv z_tl;
1505 /* Store the results into the CC variables. If we know that the
1506 variable must be dead, store unconditionally. Otherwise we'll
1507 need to not disrupt the current contents. */
1508 z_tl = tcg_const_tl(0);
1509 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1510 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1511 result, cpu_cc_dst);
1512 } else {
1513 tcg_gen_mov_tl(cpu_cc_dst, result);
1515 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1516 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1517 shm1, cpu_cc_src);
1518 } else {
1519 tcg_gen_mov_tl(cpu_cc_src, shm1);
1521 tcg_temp_free(z_tl);
1523 /* Get the two potential CC_OP values into temporaries. */
1524 tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1525 if (s->cc_op == CC_OP_DYNAMIC) {
1526 oldop = cpu_cc_op;
1527 } else {
1528 tcg_gen_movi_i32(s->tmp3_i32, s->cc_op);
1529 oldop = s->tmp3_i32;
1532 /* Conditionally store the CC_OP value. */
1533 z32 = tcg_const_i32(0);
1534 s32 = tcg_temp_new_i32();
1535 tcg_gen_trunc_tl_i32(s32, count);
1536 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop);
1537 tcg_temp_free_i32(z32);
1538 tcg_temp_free_i32(s32);
1540 /* The CC_OP value is no longer predictable. */
1541 set_cc_op(s, CC_OP_DYNAMIC);
1544 static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1,
1545 int is_right, int is_arith)
1547 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1549 /* load */
1550 if (op1 == OR_TMP0) {
1551 gen_op_ld_v(s, ot, s->T0, s->A0);
1552 } else {
1553 gen_op_mov_v_reg(s, ot, s->T0, op1);
1556 tcg_gen_andi_tl(s->T1, s->T1, mask);
1557 tcg_gen_subi_tl(s->tmp0, s->T1, 1);
1559 if (is_right) {
1560 if (is_arith) {
1561 gen_exts(ot, s->T0);
1562 tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0);
1563 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
1564 } else {
1565 gen_extu(ot, s->T0);
1566 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1567 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
1569 } else {
1570 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1571 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
1574 /* store */
1575 gen_op_st_rm_T0_A0(s, ot, op1);
1577 gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right);
1580 static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1581 int is_right, int is_arith)
1583 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1585 /* load */
1586 if (op1 == OR_TMP0)
1587 gen_op_ld_v(s, ot, s->T0, s->A0);
1588 else
1589 gen_op_mov_v_reg(s, ot, s->T0, op1);
1591 op2 &= mask;
1592 if (op2 != 0) {
1593 if (is_right) {
1594 if (is_arith) {
1595 gen_exts(ot, s->T0);
1596 tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1);
1597 tcg_gen_sari_tl(s->T0, s->T0, op2);
1598 } else {
1599 gen_extu(ot, s->T0);
1600 tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1);
1601 tcg_gen_shri_tl(s->T0, s->T0, op2);
1603 } else {
1604 tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1);
1605 tcg_gen_shli_tl(s->T0, s->T0, op2);
1609 /* store */
1610 gen_op_st_rm_T0_A0(s, ot, op1);
1612 /* update eflags if non zero shift */
1613 if (op2 != 0) {
1614 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
1615 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
1616 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1620 static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right)
1622 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1623 TCGv_i32 t0, t1;
1625 /* load */
1626 if (op1 == OR_TMP0) {
1627 gen_op_ld_v(s, ot, s->T0, s->A0);
1628 } else {
1629 gen_op_mov_v_reg(s, ot, s->T0, op1);
1632 tcg_gen_andi_tl(s->T1, s->T1, mask);
1634 switch (ot) {
1635 case MO_8:
1636 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1637 tcg_gen_ext8u_tl(s->T0, s->T0);
1638 tcg_gen_muli_tl(s->T0, s->T0, 0x01010101);
1639 goto do_long;
1640 case MO_16:
1641 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1642 tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16);
1643 goto do_long;
1644 do_long:
1645 #ifdef TARGET_X86_64
1646 case MO_32:
1647 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1648 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
1649 if (is_right) {
1650 tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1651 } else {
1652 tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1654 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1655 break;
1656 #endif
1657 default:
1658 if (is_right) {
1659 tcg_gen_rotr_tl(s->T0, s->T0, s->T1);
1660 } else {
1661 tcg_gen_rotl_tl(s->T0, s->T0, s->T1);
1663 break;
1666 /* store */
1667 gen_op_st_rm_T0_A0(s, ot, op1);
1669 /* We'll need the flags computed into CC_SRC. */
1670 gen_compute_eflags(s);
1672 /* The value that was "rotated out" is now present at the other end
1673 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1674 since we've computed the flags into CC_SRC, these variables are
1675 currently dead. */
1676 if (is_right) {
1677 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1678 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1679 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1680 } else {
1681 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1682 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1684 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1685 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1687 /* Now conditionally store the new CC_OP value. If the shift count
1688 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1689 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1690 exactly as we computed above. */
1691 t0 = tcg_const_i32(0);
1692 t1 = tcg_temp_new_i32();
1693 tcg_gen_trunc_tl_i32(t1, s->T1);
1694 tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX);
1695 tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS);
1696 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1697 s->tmp2_i32, s->tmp3_i32);
1698 tcg_temp_free_i32(t0);
1699 tcg_temp_free_i32(t1);
1701 /* The CC_OP value is no longer predictable. */
1702 set_cc_op(s, CC_OP_DYNAMIC);
1705 static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1706 int is_right)
1708 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1709 int shift;
1711 /* load */
1712 if (op1 == OR_TMP0) {
1713 gen_op_ld_v(s, ot, s->T0, s->A0);
1714 } else {
1715 gen_op_mov_v_reg(s, ot, s->T0, op1);
1718 op2 &= mask;
1719 if (op2 != 0) {
1720 switch (ot) {
1721 #ifdef TARGET_X86_64
1722 case MO_32:
1723 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1724 if (is_right) {
1725 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2);
1726 } else {
1727 tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2);
1729 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1730 break;
1731 #endif
1732 default:
1733 if (is_right) {
1734 tcg_gen_rotri_tl(s->T0, s->T0, op2);
1735 } else {
1736 tcg_gen_rotli_tl(s->T0, s->T0, op2);
1738 break;
1739 case MO_8:
1740 mask = 7;
1741 goto do_shifts;
1742 case MO_16:
1743 mask = 15;
1744 do_shifts:
1745 shift = op2 & mask;
1746 if (is_right) {
1747 shift = mask + 1 - shift;
1749 gen_extu(ot, s->T0);
1750 tcg_gen_shli_tl(s->tmp0, s->T0, shift);
1751 tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift);
1752 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
1753 break;
1757 /* store */
1758 gen_op_st_rm_T0_A0(s, ot, op1);
1760 if (op2 != 0) {
1761 /* Compute the flags into CC_SRC. */
1762 gen_compute_eflags(s);
1764 /* The value that was "rotated out" is now present at the other end
1765 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1766 since we've computed the flags into CC_SRC, these variables are
1767 currently dead. */
1768 if (is_right) {
1769 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1770 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1771 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1772 } else {
1773 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1774 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1776 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1777 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1778 set_cc_op(s, CC_OP_ADCOX);
1782 /* XXX: add faster immediate = 1 case */
1783 static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
1784 int is_right)
1786 gen_compute_eflags(s);
1787 assert(s->cc_op == CC_OP_EFLAGS);
1789 /* load */
1790 if (op1 == OR_TMP0)
1791 gen_op_ld_v(s, ot, s->T0, s->A0);
1792 else
1793 gen_op_mov_v_reg(s, ot, s->T0, op1);
1795 if (is_right) {
1796 switch (ot) {
1797 case MO_8:
1798 gen_helper_rcrb(s->T0, cpu_env, s->T0, s->T1);
1799 break;
1800 case MO_16:
1801 gen_helper_rcrw(s->T0, cpu_env, s->T0, s->T1);
1802 break;
1803 case MO_32:
1804 gen_helper_rcrl(s->T0, cpu_env, s->T0, s->T1);
1805 break;
1806 #ifdef TARGET_X86_64
1807 case MO_64:
1808 gen_helper_rcrq(s->T0, cpu_env, s->T0, s->T1);
1809 break;
1810 #endif
1811 default:
1812 tcg_abort();
1814 } else {
1815 switch (ot) {
1816 case MO_8:
1817 gen_helper_rclb(s->T0, cpu_env, s->T0, s->T1);
1818 break;
1819 case MO_16:
1820 gen_helper_rclw(s->T0, cpu_env, s->T0, s->T1);
1821 break;
1822 case MO_32:
1823 gen_helper_rcll(s->T0, cpu_env, s->T0, s->T1);
1824 break;
1825 #ifdef TARGET_X86_64
1826 case MO_64:
1827 gen_helper_rclq(s->T0, cpu_env, s->T0, s->T1);
1828 break;
1829 #endif
1830 default:
1831 tcg_abort();
1834 /* store */
1835 gen_op_st_rm_T0_A0(s, ot, op1);
1838 /* XXX: add faster immediate case */
1839 static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
1840 bool is_right, TCGv count_in)
1842 target_ulong mask = (ot == MO_64 ? 63 : 31);
1843 TCGv count;
1845 /* load */
1846 if (op1 == OR_TMP0) {
1847 gen_op_ld_v(s, ot, s->T0, s->A0);
1848 } else {
1849 gen_op_mov_v_reg(s, ot, s->T0, op1);
1852 count = tcg_temp_new();
1853 tcg_gen_andi_tl(count, count_in, mask);
1855 switch (ot) {
1856 case MO_16:
1857 /* Note: we implement the Intel behaviour for shift count > 16.
1858 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1859 portion by constructing it as a 32-bit value. */
1860 if (is_right) {
1861 tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16);
1862 tcg_gen_mov_tl(s->T1, s->T0);
1863 tcg_gen_mov_tl(s->T0, s->tmp0);
1864 } else {
1865 tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
1868 * If TARGET_X86_64 defined then fall through into MO_32 case,
1869 * otherwise fall through default case.
1871 case MO_32:
1872 #ifdef TARGET_X86_64
1873 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1874 tcg_gen_subi_tl(s->tmp0, count, 1);
1875 if (is_right) {
1876 tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1);
1877 tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0);
1878 tcg_gen_shr_i64(s->T0, s->T0, count);
1879 } else {
1880 tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0);
1881 tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0);
1882 tcg_gen_shl_i64(s->T0, s->T0, count);
1883 tcg_gen_shri_i64(s->tmp0, s->tmp0, 32);
1884 tcg_gen_shri_i64(s->T0, s->T0, 32);
1886 break;
1887 #endif
1888 default:
1889 tcg_gen_subi_tl(s->tmp0, count, 1);
1890 if (is_right) {
1891 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1893 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1894 tcg_gen_shr_tl(s->T0, s->T0, count);
1895 tcg_gen_shl_tl(s->T1, s->T1, s->tmp4);
1896 } else {
1897 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1898 if (ot == MO_16) {
1899 /* Only needed if count > 16, for Intel behaviour. */
1900 tcg_gen_subfi_tl(s->tmp4, 33, count);
1901 tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4);
1902 tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4);
1905 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1906 tcg_gen_shl_tl(s->T0, s->T0, count);
1907 tcg_gen_shr_tl(s->T1, s->T1, s->tmp4);
1909 tcg_gen_movi_tl(s->tmp4, 0);
1910 tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4,
1911 s->tmp4, s->T1);
1912 tcg_gen_or_tl(s->T0, s->T0, s->T1);
1913 break;
1916 /* store */
1917 gen_op_st_rm_T0_A0(s, ot, op1);
1919 gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
1920 tcg_temp_free(count);
1923 static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s)
1925 if (s != OR_TMP1)
1926 gen_op_mov_v_reg(s1, ot, s1->T1, s);
1927 switch(op) {
1928 case OP_ROL:
1929 gen_rot_rm_T1(s1, ot, d, 0);
1930 break;
1931 case OP_ROR:
1932 gen_rot_rm_T1(s1, ot, d, 1);
1933 break;
1934 case OP_SHL:
1935 case OP_SHL1:
1936 gen_shift_rm_T1(s1, ot, d, 0, 0);
1937 break;
1938 case OP_SHR:
1939 gen_shift_rm_T1(s1, ot, d, 1, 0);
1940 break;
1941 case OP_SAR:
1942 gen_shift_rm_T1(s1, ot, d, 1, 1);
1943 break;
1944 case OP_RCL:
1945 gen_rotc_rm_T1(s1, ot, d, 0);
1946 break;
1947 case OP_RCR:
1948 gen_rotc_rm_T1(s1, ot, d, 1);
1949 break;
1953 static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c)
1955 switch(op) {
1956 case OP_ROL:
1957 gen_rot_rm_im(s1, ot, d, c, 0);
1958 break;
1959 case OP_ROR:
1960 gen_rot_rm_im(s1, ot, d, c, 1);
1961 break;
1962 case OP_SHL:
1963 case OP_SHL1:
1964 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1965 break;
1966 case OP_SHR:
1967 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1968 break;
1969 case OP_SAR:
1970 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1971 break;
1972 default:
1973 /* currently not optimized */
1974 tcg_gen_movi_tl(s1->T1, c);
1975 gen_shift(s1, op, ot, d, OR_TMP1);
1976 break;
1980 #define X86_MAX_INSN_LENGTH 15
1982 static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
1984 uint64_t pc = s->pc;
1986 s->pc += num_bytes;
1987 if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
1988 /* If the instruction's 16th byte is on a different page than the 1st, a
1989 * page fault on the second page wins over the general protection fault
1990 * caused by the instruction being too long.
1991 * This can happen even if the operand is only one byte long!
1993 if (((s->pc - 1) ^ (pc - 1)) & TARGET_PAGE_MASK) {
1994 volatile uint8_t unused =
1995 cpu_ldub_code(env, (s->pc - 1) & TARGET_PAGE_MASK);
1996 (void) unused;
1998 siglongjmp(s->jmpbuf, 1);
2001 return pc;
2004 static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
2006 return translator_ldub(env, advance_pc(env, s, 1));
2009 static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
2011 return translator_ldsw(env, advance_pc(env, s, 2));
2014 static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
2016 return translator_lduw(env, advance_pc(env, s, 2));
2019 static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
2021 return translator_ldl(env, advance_pc(env, s, 4));
2024 #ifdef TARGET_X86_64
2025 static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
2027 return translator_ldq(env, advance_pc(env, s, 8));
2029 #endif
2031 /* Decompose an address. */
2033 typedef struct AddressParts {
2034 int def_seg;
2035 int base;
2036 int index;
2037 int scale;
2038 target_long disp;
2039 } AddressParts;
2041 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
2042 int modrm)
2044 int def_seg, base, index, scale, mod, rm;
2045 target_long disp;
2046 bool havesib;
2048 def_seg = R_DS;
2049 index = -1;
2050 scale = 0;
2051 disp = 0;
2053 mod = (modrm >> 6) & 3;
2054 rm = modrm & 7;
2055 base = rm | REX_B(s);
2057 if (mod == 3) {
2058 /* Normally filtered out earlier, but including this path
2059 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
2060 goto done;
2063 switch (s->aflag) {
2064 case MO_64:
2065 case MO_32:
2066 havesib = 0;
2067 if (rm == 4) {
2068 int code = x86_ldub_code(env, s);
2069 scale = (code >> 6) & 3;
2070 index = ((code >> 3) & 7) | REX_X(s);
2071 if (index == 4) {
2072 index = -1; /* no index */
2074 base = (code & 7) | REX_B(s);
2075 havesib = 1;
2078 switch (mod) {
2079 case 0:
2080 if ((base & 7) == 5) {
2081 base = -1;
2082 disp = (int32_t)x86_ldl_code(env, s);
2083 if (CODE64(s) && !havesib) {
2084 base = -2;
2085 disp += s->pc + s->rip_offset;
2088 break;
2089 case 1:
2090 disp = (int8_t)x86_ldub_code(env, s);
2091 break;
2092 default:
2093 case 2:
2094 disp = (int32_t)x86_ldl_code(env, s);
2095 break;
2098 /* For correct popl handling with esp. */
2099 if (base == R_ESP && s->popl_esp_hack) {
2100 disp += s->popl_esp_hack;
2102 if (base == R_EBP || base == R_ESP) {
2103 def_seg = R_SS;
2105 break;
2107 case MO_16:
2108 if (mod == 0) {
2109 if (rm == 6) {
2110 base = -1;
2111 disp = x86_lduw_code(env, s);
2112 break;
2114 } else if (mod == 1) {
2115 disp = (int8_t)x86_ldub_code(env, s);
2116 } else {
2117 disp = (int16_t)x86_lduw_code(env, s);
2120 switch (rm) {
2121 case 0:
2122 base = R_EBX;
2123 index = R_ESI;
2124 break;
2125 case 1:
2126 base = R_EBX;
2127 index = R_EDI;
2128 break;
2129 case 2:
2130 base = R_EBP;
2131 index = R_ESI;
2132 def_seg = R_SS;
2133 break;
2134 case 3:
2135 base = R_EBP;
2136 index = R_EDI;
2137 def_seg = R_SS;
2138 break;
2139 case 4:
2140 base = R_ESI;
2141 break;
2142 case 5:
2143 base = R_EDI;
2144 break;
2145 case 6:
2146 base = R_EBP;
2147 def_seg = R_SS;
2148 break;
2149 default:
2150 case 7:
2151 base = R_EBX;
2152 break;
2154 break;
2156 default:
2157 tcg_abort();
2160 done:
2161 return (AddressParts){ def_seg, base, index, scale, disp };
2164 /* Compute the address, with a minimum number of TCG ops. */
2165 static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a)
2167 TCGv ea = NULL;
2169 if (a.index >= 0) {
2170 if (a.scale == 0) {
2171 ea = cpu_regs[a.index];
2172 } else {
2173 tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale);
2174 ea = s->A0;
2176 if (a.base >= 0) {
2177 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2178 ea = s->A0;
2180 } else if (a.base >= 0) {
2181 ea = cpu_regs[a.base];
2183 if (!ea) {
2184 tcg_gen_movi_tl(s->A0, a.disp);
2185 ea = s->A0;
2186 } else if (a.disp != 0) {
2187 tcg_gen_addi_tl(s->A0, ea, a.disp);
2188 ea = s->A0;
2191 return ea;
2194 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2196 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2197 TCGv ea = gen_lea_modrm_1(s, a);
2198 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2201 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2203 (void)gen_lea_modrm_0(env, s, modrm);
2206 /* Used for BNDCL, BNDCU, BNDCN. */
2207 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2208 TCGCond cond, TCGv_i64 bndv)
2210 TCGv ea = gen_lea_modrm_1(s, gen_lea_modrm_0(env, s, modrm));
2212 tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
2213 if (!CODE64(s)) {
2214 tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64);
2216 tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv);
2217 tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64);
2218 gen_helper_bndck(cpu_env, s->tmp2_i32);
2221 /* used for LEA and MOV AX, mem */
2222 static void gen_add_A0_ds_seg(DisasContext *s)
2224 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
2227 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2228 OR_TMP0 */
2229 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2230 MemOp ot, int reg, int is_store)
2232 int mod, rm;
2234 mod = (modrm >> 6) & 3;
2235 rm = (modrm & 7) | REX_B(s);
2236 if (mod == 3) {
2237 if (is_store) {
2238 if (reg != OR_TMP0)
2239 gen_op_mov_v_reg(s, ot, s->T0, reg);
2240 gen_op_mov_reg_v(s, ot, rm, s->T0);
2241 } else {
2242 gen_op_mov_v_reg(s, ot, s->T0, rm);
2243 if (reg != OR_TMP0)
2244 gen_op_mov_reg_v(s, ot, reg, s->T0);
2246 } else {
2247 gen_lea_modrm(env, s, modrm);
2248 if (is_store) {
2249 if (reg != OR_TMP0)
2250 gen_op_mov_v_reg(s, ot, s->T0, reg);
2251 gen_op_st_v(s, ot, s->T0, s->A0);
2252 } else {
2253 gen_op_ld_v(s, ot, s->T0, s->A0);
2254 if (reg != OR_TMP0)
2255 gen_op_mov_reg_v(s, ot, reg, s->T0);
2260 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
2262 uint32_t ret;
2264 switch (ot) {
2265 case MO_8:
2266 ret = x86_ldub_code(env, s);
2267 break;
2268 case MO_16:
2269 ret = x86_lduw_code(env, s);
2270 break;
2271 case MO_32:
2272 #ifdef TARGET_X86_64
2273 case MO_64:
2274 #endif
2275 ret = x86_ldl_code(env, s);
2276 break;
2277 default:
2278 tcg_abort();
2280 return ret;
2283 static inline int insn_const_size(MemOp ot)
2285 if (ot <= MO_32) {
2286 return 1 << ot;
2287 } else {
2288 return 4;
2292 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2294 #ifndef CONFIG_USER_ONLY
2295 return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
2296 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2297 #else
2298 return true;
2299 #endif
2302 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2304 target_ulong pc = s->cs_base + eip;
2306 if (use_goto_tb(s, pc)) {
2307 /* jump to same page: we can use a direct jump */
2308 tcg_gen_goto_tb(tb_num);
2309 gen_jmp_im(s, eip);
2310 tcg_gen_exit_tb(s->base.tb, tb_num);
2311 s->base.is_jmp = DISAS_NORETURN;
2312 } else {
2313 /* jump to another page */
2314 gen_jmp_im(s, eip);
2315 gen_jr(s, s->tmp0);
2319 static inline void gen_jcc(DisasContext *s, int b,
2320 target_ulong val, target_ulong next_eip)
2322 TCGLabel *l1, *l2;
2324 if (s->jmp_opt) {
2325 l1 = gen_new_label();
2326 gen_jcc1(s, b, l1);
2328 gen_goto_tb(s, 0, next_eip);
2330 gen_set_label(l1);
2331 gen_goto_tb(s, 1, val);
2332 } else {
2333 l1 = gen_new_label();
2334 l2 = gen_new_label();
2335 gen_jcc1(s, b, l1);
2337 gen_jmp_im(s, next_eip);
2338 tcg_gen_br(l2);
2340 gen_set_label(l1);
2341 gen_jmp_im(s, val);
2342 gen_set_label(l2);
2343 gen_eob(s);
2347 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
2348 int modrm, int reg)
2350 CCPrepare cc;
2352 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2354 cc = gen_prepare_cc(s, b, s->T1);
2355 if (cc.mask != -1) {
2356 TCGv t0 = tcg_temp_new();
2357 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2358 cc.reg = t0;
2360 if (!cc.use_reg2) {
2361 cc.reg2 = tcg_const_tl(cc.imm);
2364 tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2,
2365 s->T0, cpu_regs[reg]);
2366 gen_op_mov_reg_v(s, ot, reg, s->T0);
2368 if (cc.mask != -1) {
2369 tcg_temp_free(cc.reg);
2371 if (!cc.use_reg2) {
2372 tcg_temp_free(cc.reg2);
2376 static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg)
2378 tcg_gen_ld32u_tl(s->T0, cpu_env,
2379 offsetof(CPUX86State,segs[seg_reg].selector));
2382 static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg)
2384 tcg_gen_ext16u_tl(s->T0, s->T0);
2385 tcg_gen_st32_tl(s->T0, cpu_env,
2386 offsetof(CPUX86State,segs[seg_reg].selector));
2387 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
2390 /* move T0 to seg_reg and compute if the CPU state may change. Never
2391 call this function with seg_reg == R_CS */
2392 static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg)
2394 if (PE(s) && !VM86(s)) {
2395 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
2396 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), s->tmp2_i32);
2397 /* abort translation because the addseg value may change or
2398 because ss32 may change. For R_SS, translation must always
2399 stop as a special handling must be done to disable hardware
2400 interrupts for the next instruction */
2401 if (seg_reg == R_SS || (CODE32(s) && seg_reg < R_FS)) {
2402 s->base.is_jmp = DISAS_TOO_MANY;
2404 } else {
2405 gen_op_movl_seg_T0_vm(s, seg_reg);
2406 if (seg_reg == R_SS) {
2407 s->base.is_jmp = DISAS_TOO_MANY;
2412 static inline int svm_is_rep(int prefixes)
2414 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2417 static inline void
2418 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2419 uint32_t type, uint64_t param)
2421 /* no SVM activated; fast case */
2422 if (likely(!GUEST(s))) {
2423 return;
2425 gen_update_cc_op(s);
2426 gen_jmp_im(s, pc_start - s->cs_base);
2427 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2428 tcg_const_i64(param));
2431 static inline void
2432 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2434 gen_svm_check_intercept_param(s, pc_start, type, 0);
2437 static inline void gen_stack_update(DisasContext *s, int addend)
2439 gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend);
2442 /* Generate a push. It depends on ss32, addseg and dflag. */
2443 static void gen_push_v(DisasContext *s, TCGv val)
2445 MemOp d_ot = mo_pushpop(s, s->dflag);
2446 MemOp a_ot = mo_stacksize(s);
2447 int size = 1 << d_ot;
2448 TCGv new_esp = s->A0;
2450 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2452 if (!CODE64(s)) {
2453 if (ADDSEG(s)) {
2454 new_esp = s->tmp4;
2455 tcg_gen_mov_tl(new_esp, s->A0);
2457 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2460 gen_op_st_v(s, d_ot, val, s->A0);
2461 gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp);
2464 /* two step pop is necessary for precise exceptions */
2465 static MemOp gen_pop_T0(DisasContext *s)
2467 MemOp d_ot = mo_pushpop(s, s->dflag);
2469 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2470 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2472 return d_ot;
2475 static inline void gen_pop_update(DisasContext *s, MemOp ot)
2477 gen_stack_update(s, 1 << ot);
2480 static inline void gen_stack_A0(DisasContext *s)
2482 gen_lea_v_seg(s, SS32(s) ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2485 static void gen_pusha(DisasContext *s)
2487 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2488 MemOp d_ot = s->dflag;
2489 int size = 1 << d_ot;
2490 int i;
2492 for (i = 0; i < 8; i++) {
2493 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size);
2494 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2495 gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0);
2498 gen_stack_update(s, -8 * size);
2501 static void gen_popa(DisasContext *s)
2503 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2504 MemOp d_ot = s->dflag;
2505 int size = 1 << d_ot;
2506 int i;
2508 for (i = 0; i < 8; i++) {
2509 /* ESP is not reloaded */
2510 if (7 - i == R_ESP) {
2511 continue;
2513 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size);
2514 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2515 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2516 gen_op_mov_reg_v(s, d_ot, 7 - i, s->T0);
2519 gen_stack_update(s, 8 * size);
2522 static void gen_enter(DisasContext *s, int esp_addend, int level)
2524 MemOp d_ot = mo_pushpop(s, s->dflag);
2525 MemOp a_ot = CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
2526 int size = 1 << d_ot;
2528 /* Push BP; compute FrameTemp into T1. */
2529 tcg_gen_subi_tl(s->T1, cpu_regs[R_ESP], size);
2530 gen_lea_v_seg(s, a_ot, s->T1, R_SS, -1);
2531 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0);
2533 level &= 31;
2534 if (level != 0) {
2535 int i;
2537 /* Copy level-1 pointers from the previous frame. */
2538 for (i = 1; i < level; ++i) {
2539 tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i);
2540 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2541 gen_op_ld_v(s, d_ot, s->tmp0, s->A0);
2543 tcg_gen_subi_tl(s->A0, s->T1, size * i);
2544 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2545 gen_op_st_v(s, d_ot, s->tmp0, s->A0);
2548 /* Push the current FrameTemp as the last level. */
2549 tcg_gen_subi_tl(s->A0, s->T1, size * level);
2550 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2551 gen_op_st_v(s, d_ot, s->T1, s->A0);
2554 /* Copy the FrameTemp value to EBP. */
2555 gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
2557 /* Compute the final value of ESP. */
2558 tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
2559 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2562 static void gen_leave(DisasContext *s)
2564 MemOp d_ot = mo_pushpop(s, s->dflag);
2565 MemOp a_ot = mo_stacksize(s);
2567 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2568 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2570 tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot);
2572 gen_op_mov_reg_v(s, d_ot, R_EBP, s->T0);
2573 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2576 /* Similarly, except that the assumption here is that we don't decode
2577 the instruction at all -- either a missing opcode, an unimplemented
2578 feature, or just a bogus instruction stream. */
2579 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2581 gen_illegal_opcode(s);
2583 if (qemu_loglevel_mask(LOG_UNIMP)) {
2584 FILE *logfile = qemu_log_lock();
2585 target_ulong pc = s->pc_start, end = s->pc;
2587 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2588 for (; pc < end; ++pc) {
2589 qemu_log(" %02x", cpu_ldub_code(env, pc));
2591 qemu_log("\n");
2592 qemu_log_unlock(logfile);
2596 /* an interrupt is different from an exception because of the
2597 privilege checks */
2598 static void gen_interrupt(DisasContext *s, int intno,
2599 target_ulong cur_eip, target_ulong next_eip)
2601 gen_update_cc_op(s);
2602 gen_jmp_im(s, cur_eip);
2603 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2604 tcg_const_i32(next_eip - cur_eip));
2605 s->base.is_jmp = DISAS_NORETURN;
2608 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2610 gen_update_cc_op(s);
2611 gen_jmp_im(s, cur_eip);
2612 gen_helper_debug(cpu_env);
2613 s->base.is_jmp = DISAS_NORETURN;
2616 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2618 if ((s->flags & mask) == 0) {
2619 TCGv_i32 t = tcg_temp_new_i32();
2620 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2621 tcg_gen_ori_i32(t, t, mask);
2622 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2623 tcg_temp_free_i32(t);
2624 s->flags |= mask;
2628 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2630 if (s->flags & mask) {
2631 TCGv_i32 t = tcg_temp_new_i32();
2632 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2633 tcg_gen_andi_i32(t, t, ~mask);
2634 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2635 tcg_temp_free_i32(t);
2636 s->flags &= ~mask;
2640 /* Clear BND registers during legacy branches. */
2641 static void gen_bnd_jmp(DisasContext *s)
2643 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2644 and if the BNDREGs are known to be in use (non-zero) already.
2645 The helper itself will check BNDPRESERVE at runtime. */
2646 if ((s->prefix & PREFIX_REPNZ) == 0
2647 && (s->flags & HF_MPX_EN_MASK) != 0
2648 && (s->flags & HF_MPX_IU_MASK) != 0) {
2649 gen_helper_bnd_jmp(cpu_env);
2653 /* Generate an end of block. Trace exception is also generated if needed.
2654 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.
2655 If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
2656 S->TF. This is used by the syscall/sysret insns. */
2657 static void
2658 do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2660 gen_update_cc_op(s);
2662 /* If several instructions disable interrupts, only the first does it. */
2663 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2664 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2665 } else {
2666 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2669 if (s->base.tb->flags & HF_RF_MASK) {
2670 gen_helper_reset_rf(cpu_env);
2672 if (s->base.singlestep_enabled) {
2673 gen_helper_debug(cpu_env);
2674 } else if (recheck_tf) {
2675 gen_helper_rechecking_single_step(cpu_env);
2676 tcg_gen_exit_tb(NULL, 0);
2677 } else if (s->flags & HF_TF_MASK) {
2678 gen_helper_single_step(cpu_env);
2679 } else if (jr) {
2680 tcg_gen_lookup_and_goto_ptr();
2681 } else {
2682 tcg_gen_exit_tb(NULL, 0);
2684 s->base.is_jmp = DISAS_NORETURN;
2687 static inline void
2688 gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2690 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2693 /* End of block.
2694 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2695 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2697 gen_eob_worker(s, inhibit, false);
2700 /* End of block, resetting the inhibit irq flag. */
2701 static void gen_eob(DisasContext *s)
2703 gen_eob_worker(s, false, false);
2706 /* Jump to register */
2707 static void gen_jr(DisasContext *s, TCGv dest)
2709 do_gen_eob_worker(s, false, false, true);
2712 /* generate a jump to eip. No segment change must happen before as a
2713 direct call to the next block may occur */
2714 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2716 gen_update_cc_op(s);
2717 set_cc_op(s, CC_OP_DYNAMIC);
2718 if (s->jmp_opt) {
2719 gen_goto_tb(s, tb_num, eip);
2720 } else {
2721 gen_jmp_im(s, eip);
2722 gen_eob(s);
2726 static void gen_jmp(DisasContext *s, target_ulong eip)
2728 gen_jmp_tb(s, eip, 0);
2731 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2733 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2734 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset);
2737 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2739 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset);
2740 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2743 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2745 int mem_index = s->mem_index;
2746 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2747 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2748 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2749 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2750 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2753 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2755 int mem_index = s->mem_index;
2756 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2757 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2758 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2759 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2760 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2763 static inline void gen_op_movo(DisasContext *s, int d_offset, int s_offset)
2765 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2766 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2767 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2768 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2771 static inline void gen_op_movq(DisasContext *s, int d_offset, int s_offset)
2773 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset);
2774 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2777 static inline void gen_op_movl(DisasContext *s, int d_offset, int s_offset)
2779 tcg_gen_ld_i32(s->tmp2_i32, cpu_env, s_offset);
2780 tcg_gen_st_i32(s->tmp2_i32, cpu_env, d_offset);
2783 static inline void gen_op_movq_env_0(DisasContext *s, int d_offset)
2785 tcg_gen_movi_i64(s->tmp1_i64, 0);
2786 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2789 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2790 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2791 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2792 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2793 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2794 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2795 TCGv_i32 val);
2796 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2797 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2798 TCGv val);
2800 #define SSE_SPECIAL ((void *)1)
2801 #define SSE_DUMMY ((void *)2)
2803 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2804 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2805 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2807 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2808 /* 3DNow! extensions */
2809 [0x0e] = { SSE_DUMMY }, /* femms */
2810 [0x0f] = { SSE_DUMMY }, /* pf... */
2811 /* pure SSE operations */
2812 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2813 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2814 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2815 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2816 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2817 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2818 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2819 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2821 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2822 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2823 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2824 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2825 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2826 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2827 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2828 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2829 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2830 [0x51] = SSE_FOP(sqrt),
2831 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2832 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2833 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2834 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2835 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2836 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2837 [0x58] = SSE_FOP(add),
2838 [0x59] = SSE_FOP(mul),
2839 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2840 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2841 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2842 [0x5c] = SSE_FOP(sub),
2843 [0x5d] = SSE_FOP(min),
2844 [0x5e] = SSE_FOP(div),
2845 [0x5f] = SSE_FOP(max),
2847 [0xc2] = SSE_FOP(cmpeq),
2848 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2849 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2851 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2852 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2853 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2855 /* MMX ops and their SSE extensions */
2856 [0x60] = MMX_OP2(punpcklbw),
2857 [0x61] = MMX_OP2(punpcklwd),
2858 [0x62] = MMX_OP2(punpckldq),
2859 [0x63] = MMX_OP2(packsswb),
2860 [0x64] = MMX_OP2(pcmpgtb),
2861 [0x65] = MMX_OP2(pcmpgtw),
2862 [0x66] = MMX_OP2(pcmpgtl),
2863 [0x67] = MMX_OP2(packuswb),
2864 [0x68] = MMX_OP2(punpckhbw),
2865 [0x69] = MMX_OP2(punpckhwd),
2866 [0x6a] = MMX_OP2(punpckhdq),
2867 [0x6b] = MMX_OP2(packssdw),
2868 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2869 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2870 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2871 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2872 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2873 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2874 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2875 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2876 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2877 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2878 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2879 [0x74] = MMX_OP2(pcmpeqb),
2880 [0x75] = MMX_OP2(pcmpeqw),
2881 [0x76] = MMX_OP2(pcmpeql),
2882 [0x77] = { SSE_DUMMY }, /* emms */
2883 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2884 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2885 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2886 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2887 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2888 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2889 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2890 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2891 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2892 [0xd1] = MMX_OP2(psrlw),
2893 [0xd2] = MMX_OP2(psrld),
2894 [0xd3] = MMX_OP2(psrlq),
2895 [0xd4] = MMX_OP2(paddq),
2896 [0xd5] = MMX_OP2(pmullw),
2897 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2898 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2899 [0xd8] = MMX_OP2(psubusb),
2900 [0xd9] = MMX_OP2(psubusw),
2901 [0xda] = MMX_OP2(pminub),
2902 [0xdb] = MMX_OP2(pand),
2903 [0xdc] = MMX_OP2(paddusb),
2904 [0xdd] = MMX_OP2(paddusw),
2905 [0xde] = MMX_OP2(pmaxub),
2906 [0xdf] = MMX_OP2(pandn),
2907 [0xe0] = MMX_OP2(pavgb),
2908 [0xe1] = MMX_OP2(psraw),
2909 [0xe2] = MMX_OP2(psrad),
2910 [0xe3] = MMX_OP2(pavgw),
2911 [0xe4] = MMX_OP2(pmulhuw),
2912 [0xe5] = MMX_OP2(pmulhw),
2913 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2914 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2915 [0xe8] = MMX_OP2(psubsb),
2916 [0xe9] = MMX_OP2(psubsw),
2917 [0xea] = MMX_OP2(pminsw),
2918 [0xeb] = MMX_OP2(por),
2919 [0xec] = MMX_OP2(paddsb),
2920 [0xed] = MMX_OP2(paddsw),
2921 [0xee] = MMX_OP2(pmaxsw),
2922 [0xef] = MMX_OP2(pxor),
2923 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2924 [0xf1] = MMX_OP2(psllw),
2925 [0xf2] = MMX_OP2(pslld),
2926 [0xf3] = MMX_OP2(psllq),
2927 [0xf4] = MMX_OP2(pmuludq),
2928 [0xf5] = MMX_OP2(pmaddwd),
2929 [0xf6] = MMX_OP2(psadbw),
2930 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2931 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2932 [0xf8] = MMX_OP2(psubb),
2933 [0xf9] = MMX_OP2(psubw),
2934 [0xfa] = MMX_OP2(psubl),
2935 [0xfb] = MMX_OP2(psubq),
2936 [0xfc] = MMX_OP2(paddb),
2937 [0xfd] = MMX_OP2(paddw),
2938 [0xfe] = MMX_OP2(paddl),
2941 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2942 [0 + 2] = MMX_OP2(psrlw),
2943 [0 + 4] = MMX_OP2(psraw),
2944 [0 + 6] = MMX_OP2(psllw),
2945 [8 + 2] = MMX_OP2(psrld),
2946 [8 + 4] = MMX_OP2(psrad),
2947 [8 + 6] = MMX_OP2(pslld),
2948 [16 + 2] = MMX_OP2(psrlq),
2949 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2950 [16 + 6] = MMX_OP2(psllq),
2951 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2954 static const SSEFunc_0_epi sse_op_table3ai[] = {
2955 gen_helper_cvtsi2ss,
2956 gen_helper_cvtsi2sd
2959 #ifdef TARGET_X86_64
2960 static const SSEFunc_0_epl sse_op_table3aq[] = {
2961 gen_helper_cvtsq2ss,
2962 gen_helper_cvtsq2sd
2964 #endif
2966 static const SSEFunc_i_ep sse_op_table3bi[] = {
2967 gen_helper_cvttss2si,
2968 gen_helper_cvtss2si,
2969 gen_helper_cvttsd2si,
2970 gen_helper_cvtsd2si
2973 #ifdef TARGET_X86_64
2974 static const SSEFunc_l_ep sse_op_table3bq[] = {
2975 gen_helper_cvttss2sq,
2976 gen_helper_cvtss2sq,
2977 gen_helper_cvttsd2sq,
2978 gen_helper_cvtsd2sq
2980 #endif
2982 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2983 SSE_FOP(cmpeq),
2984 SSE_FOP(cmplt),
2985 SSE_FOP(cmple),
2986 SSE_FOP(cmpunord),
2987 SSE_FOP(cmpneq),
2988 SSE_FOP(cmpnlt),
2989 SSE_FOP(cmpnle),
2990 SSE_FOP(cmpord),
2993 static const SSEFunc_0_epp sse_op_table5[256] = {
2994 [0x0c] = gen_helper_pi2fw,
2995 [0x0d] = gen_helper_pi2fd,
2996 [0x1c] = gen_helper_pf2iw,
2997 [0x1d] = gen_helper_pf2id,
2998 [0x8a] = gen_helper_pfnacc,
2999 [0x8e] = gen_helper_pfpnacc,
3000 [0x90] = gen_helper_pfcmpge,
3001 [0x94] = gen_helper_pfmin,
3002 [0x96] = gen_helper_pfrcp,
3003 [0x97] = gen_helper_pfrsqrt,
3004 [0x9a] = gen_helper_pfsub,
3005 [0x9e] = gen_helper_pfadd,
3006 [0xa0] = gen_helper_pfcmpgt,
3007 [0xa4] = gen_helper_pfmax,
3008 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
3009 [0xa7] = gen_helper_movq, /* pfrsqit1 */
3010 [0xaa] = gen_helper_pfsubr,
3011 [0xae] = gen_helper_pfacc,
3012 [0xb0] = gen_helper_pfcmpeq,
3013 [0xb4] = gen_helper_pfmul,
3014 [0xb6] = gen_helper_movq, /* pfrcpit2 */
3015 [0xb7] = gen_helper_pmulhrw_mmx,
3016 [0xbb] = gen_helper_pswapd,
3017 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
3020 struct SSEOpHelper_epp {
3021 SSEFunc_0_epp op[2];
3022 uint32_t ext_mask;
3025 struct SSEOpHelper_eppi {
3026 SSEFunc_0_eppi op[2];
3027 uint32_t ext_mask;
3030 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
3031 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
3032 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
3033 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
3034 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
3035 CPUID_EXT_PCLMULQDQ }
3036 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
3038 static const struct SSEOpHelper_epp sse_op_table6[256] = {
3039 [0x00] = SSSE3_OP(pshufb),
3040 [0x01] = SSSE3_OP(phaddw),
3041 [0x02] = SSSE3_OP(phaddd),
3042 [0x03] = SSSE3_OP(phaddsw),
3043 [0x04] = SSSE3_OP(pmaddubsw),
3044 [0x05] = SSSE3_OP(phsubw),
3045 [0x06] = SSSE3_OP(phsubd),
3046 [0x07] = SSSE3_OP(phsubsw),
3047 [0x08] = SSSE3_OP(psignb),
3048 [0x09] = SSSE3_OP(psignw),
3049 [0x0a] = SSSE3_OP(psignd),
3050 [0x0b] = SSSE3_OP(pmulhrsw),
3051 [0x10] = SSE41_OP(pblendvb),
3052 [0x14] = SSE41_OP(blendvps),
3053 [0x15] = SSE41_OP(blendvpd),
3054 [0x17] = SSE41_OP(ptest),
3055 [0x1c] = SSSE3_OP(pabsb),
3056 [0x1d] = SSSE3_OP(pabsw),
3057 [0x1e] = SSSE3_OP(pabsd),
3058 [0x20] = SSE41_OP(pmovsxbw),
3059 [0x21] = SSE41_OP(pmovsxbd),
3060 [0x22] = SSE41_OP(pmovsxbq),
3061 [0x23] = SSE41_OP(pmovsxwd),
3062 [0x24] = SSE41_OP(pmovsxwq),
3063 [0x25] = SSE41_OP(pmovsxdq),
3064 [0x28] = SSE41_OP(pmuldq),
3065 [0x29] = SSE41_OP(pcmpeqq),
3066 [0x2a] = SSE41_SPECIAL, /* movntqda */
3067 [0x2b] = SSE41_OP(packusdw),
3068 [0x30] = SSE41_OP(pmovzxbw),
3069 [0x31] = SSE41_OP(pmovzxbd),
3070 [0x32] = SSE41_OP(pmovzxbq),
3071 [0x33] = SSE41_OP(pmovzxwd),
3072 [0x34] = SSE41_OP(pmovzxwq),
3073 [0x35] = SSE41_OP(pmovzxdq),
3074 [0x37] = SSE42_OP(pcmpgtq),
3075 [0x38] = SSE41_OP(pminsb),
3076 [0x39] = SSE41_OP(pminsd),
3077 [0x3a] = SSE41_OP(pminuw),
3078 [0x3b] = SSE41_OP(pminud),
3079 [0x3c] = SSE41_OP(pmaxsb),
3080 [0x3d] = SSE41_OP(pmaxsd),
3081 [0x3e] = SSE41_OP(pmaxuw),
3082 [0x3f] = SSE41_OP(pmaxud),
3083 [0x40] = SSE41_OP(pmulld),
3084 [0x41] = SSE41_OP(phminposuw),
3085 [0xdb] = AESNI_OP(aesimc),
3086 [0xdc] = AESNI_OP(aesenc),
3087 [0xdd] = AESNI_OP(aesenclast),
3088 [0xde] = AESNI_OP(aesdec),
3089 [0xdf] = AESNI_OP(aesdeclast),
3092 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
3093 [0x08] = SSE41_OP(roundps),
3094 [0x09] = SSE41_OP(roundpd),
3095 [0x0a] = SSE41_OP(roundss),
3096 [0x0b] = SSE41_OP(roundsd),
3097 [0x0c] = SSE41_OP(blendps),
3098 [0x0d] = SSE41_OP(blendpd),
3099 [0x0e] = SSE41_OP(pblendw),
3100 [0x0f] = SSSE3_OP(palignr),
3101 [0x14] = SSE41_SPECIAL, /* pextrb */
3102 [0x15] = SSE41_SPECIAL, /* pextrw */
3103 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3104 [0x17] = SSE41_SPECIAL, /* extractps */
3105 [0x20] = SSE41_SPECIAL, /* pinsrb */
3106 [0x21] = SSE41_SPECIAL, /* insertps */
3107 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3108 [0x40] = SSE41_OP(dpps),
3109 [0x41] = SSE41_OP(dppd),
3110 [0x42] = SSE41_OP(mpsadbw),
3111 [0x44] = PCLMULQDQ_OP(pclmulqdq),
3112 [0x60] = SSE42_OP(pcmpestrm),
3113 [0x61] = SSE42_OP(pcmpestri),
3114 [0x62] = SSE42_OP(pcmpistrm),
3115 [0x63] = SSE42_OP(pcmpistri),
3116 [0xdf] = AESNI_OP(aeskeygenassist),
3119 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3120 target_ulong pc_start)
3122 int b1, op1_offset, op2_offset, is_xmm, val;
3123 int modrm, mod, rm, reg;
3124 SSEFunc_0_epp sse_fn_epp;
3125 SSEFunc_0_eppi sse_fn_eppi;
3126 SSEFunc_0_ppi sse_fn_ppi;
3127 SSEFunc_0_eppt sse_fn_eppt;
3128 MemOp ot;
3130 b &= 0xff;
3131 if (s->prefix & PREFIX_DATA)
3132 b1 = 1;
3133 else if (s->prefix & PREFIX_REPZ)
3134 b1 = 2;
3135 else if (s->prefix & PREFIX_REPNZ)
3136 b1 = 3;
3137 else
3138 b1 = 0;
3139 sse_fn_epp = sse_op_table1[b][b1];
3140 if (!sse_fn_epp) {
3141 goto unknown_op;
3143 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3144 is_xmm = 1;
3145 } else {
3146 if (b1 == 0) {
3147 /* MMX case */
3148 is_xmm = 0;
3149 } else {
3150 is_xmm = 1;
3153 /* simple MMX/SSE operation */
3154 if (s->flags & HF_TS_MASK) {
3155 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3156 return;
3158 if (s->flags & HF_EM_MASK) {
3159 illegal_op:
3160 gen_illegal_opcode(s);
3161 return;
3163 if (is_xmm
3164 && !(s->flags & HF_OSFXSR_MASK)
3165 && (b != 0x38 && b != 0x3a)) {
3166 goto unknown_op;
3168 if (b == 0x0e) {
3169 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3170 /* If we were fully decoding this we might use illegal_op. */
3171 goto unknown_op;
3173 /* femms */
3174 gen_helper_emms(cpu_env);
3175 return;
3177 if (b == 0x77) {
3178 /* emms */
3179 gen_helper_emms(cpu_env);
3180 return;
3182 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3183 the static cpu state) */
3184 if (!is_xmm) {
3185 gen_helper_enter_mmx(cpu_env);
3188 modrm = x86_ldub_code(env, s);
3189 reg = ((modrm >> 3) & 7);
3190 if (is_xmm) {
3191 reg |= REX_R(s);
3193 mod = (modrm >> 6) & 3;
3194 if (sse_fn_epp == SSE_SPECIAL) {
3195 b |= (b1 << 8);
3196 switch(b) {
3197 case 0x0e7: /* movntq */
3198 if (mod == 3) {
3199 goto illegal_op;
3201 gen_lea_modrm(env, s, modrm);
3202 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3203 break;
3204 case 0x1e7: /* movntdq */
3205 case 0x02b: /* movntps */
3206 case 0x12b: /* movntps */
3207 if (mod == 3)
3208 goto illegal_op;
3209 gen_lea_modrm(env, s, modrm);
3210 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3211 break;
3212 case 0x3f0: /* lddqu */
3213 if (mod == 3)
3214 goto illegal_op;
3215 gen_lea_modrm(env, s, modrm);
3216 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3217 break;
3218 case 0x22b: /* movntss */
3219 case 0x32b: /* movntsd */
3220 if (mod == 3)
3221 goto illegal_op;
3222 gen_lea_modrm(env, s, modrm);
3223 if (b1 & 1) {
3224 gen_stq_env_A0(s, offsetof(CPUX86State,
3225 xmm_regs[reg].ZMM_Q(0)));
3226 } else {
3227 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
3228 xmm_regs[reg].ZMM_L(0)));
3229 gen_op_st_v(s, MO_32, s->T0, s->A0);
3231 break;
3232 case 0x6e: /* movd mm, ea */
3233 #ifdef TARGET_X86_64
3234 if (s->dflag == MO_64) {
3235 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3236 tcg_gen_st_tl(s->T0, cpu_env,
3237 offsetof(CPUX86State, fpregs[reg].mmx));
3238 } else
3239 #endif
3241 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3242 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3243 offsetof(CPUX86State,fpregs[reg].mmx));
3244 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3245 gen_helper_movl_mm_T0_mmx(s->ptr0, s->tmp2_i32);
3247 break;
3248 case 0x16e: /* movd xmm, ea */
3249 #ifdef TARGET_X86_64
3250 if (s->dflag == MO_64) {
3251 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3252 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3253 offsetof(CPUX86State,xmm_regs[reg]));
3254 gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0);
3255 } else
3256 #endif
3258 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3259 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3260 offsetof(CPUX86State,xmm_regs[reg]));
3261 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3262 gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32);
3264 break;
3265 case 0x6f: /* movq mm, ea */
3266 if (mod != 3) {
3267 gen_lea_modrm(env, s, modrm);
3268 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3269 } else {
3270 rm = (modrm & 7);
3271 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
3272 offsetof(CPUX86State,fpregs[rm].mmx));
3273 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
3274 offsetof(CPUX86State,fpregs[reg].mmx));
3276 break;
3277 case 0x010: /* movups */
3278 case 0x110: /* movupd */
3279 case 0x028: /* movaps */
3280 case 0x128: /* movapd */
3281 case 0x16f: /* movdqa xmm, ea */
3282 case 0x26f: /* movdqu xmm, ea */
3283 if (mod != 3) {
3284 gen_lea_modrm(env, s, modrm);
3285 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3286 } else {
3287 rm = (modrm & 7) | REX_B(s);
3288 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[reg]),
3289 offsetof(CPUX86State,xmm_regs[rm]));
3291 break;
3292 case 0x210: /* movss xmm, ea */
3293 if (mod != 3) {
3294 gen_lea_modrm(env, s, modrm);
3295 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3296 tcg_gen_st32_tl(s->T0, cpu_env,
3297 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(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(1)));
3301 tcg_gen_st32_tl(s->T0, cpu_env,
3302 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3303 tcg_gen_st32_tl(s->T0, cpu_env,
3304 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3305 } else {
3306 rm = (modrm & 7) | REX_B(s);
3307 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3308 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3310 break;
3311 case 0x310: /* movsd xmm, ea */
3312 if (mod != 3) {
3313 gen_lea_modrm(env, s, modrm);
3314 gen_ldq_env_A0(s, offsetof(CPUX86State,
3315 xmm_regs[reg].ZMM_Q(0)));
3316 tcg_gen_movi_tl(s->T0, 0);
3317 tcg_gen_st32_tl(s->T0, cpu_env,
3318 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3319 tcg_gen_st32_tl(s->T0, cpu_env,
3320 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3321 } else {
3322 rm = (modrm & 7) | REX_B(s);
3323 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3324 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3326 break;
3327 case 0x012: /* movlps */
3328 case 0x112: /* movlpd */
3329 if (mod != 3) {
3330 gen_lea_modrm(env, s, modrm);
3331 gen_ldq_env_A0(s, offsetof(CPUX86State,
3332 xmm_regs[reg].ZMM_Q(0)));
3333 } else {
3334 /* movhlps */
3335 rm = (modrm & 7) | REX_B(s);
3336 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3337 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3339 break;
3340 case 0x212: /* movsldup */
3341 if (mod != 3) {
3342 gen_lea_modrm(env, s, modrm);
3343 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3344 } else {
3345 rm = (modrm & 7) | REX_B(s);
3346 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3347 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3348 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3349 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3351 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3352 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3353 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3354 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3355 break;
3356 case 0x312: /* movddup */
3357 if (mod != 3) {
3358 gen_lea_modrm(env, s, modrm);
3359 gen_ldq_env_A0(s, offsetof(CPUX86State,
3360 xmm_regs[reg].ZMM_Q(0)));
3361 } else {
3362 rm = (modrm & 7) | REX_B(s);
3363 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3364 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3366 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3367 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3368 break;
3369 case 0x016: /* movhps */
3370 case 0x116: /* movhpd */
3371 if (mod != 3) {
3372 gen_lea_modrm(env, s, modrm);
3373 gen_ldq_env_A0(s, offsetof(CPUX86State,
3374 xmm_regs[reg].ZMM_Q(1)));
3375 } else {
3376 /* movlhps */
3377 rm = (modrm & 7) | REX_B(s);
3378 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3379 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3381 break;
3382 case 0x216: /* movshdup */
3383 if (mod != 3) {
3384 gen_lea_modrm(env, s, modrm);
3385 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3386 } else {
3387 rm = (modrm & 7) | REX_B(s);
3388 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3389 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3390 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3391 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3393 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3394 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3395 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3396 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3397 break;
3398 case 0x178:
3399 case 0x378:
3401 int bit_index, field_length;
3403 if (b1 == 1 && reg != 0)
3404 goto illegal_op;
3405 field_length = x86_ldub_code(env, s) & 0x3F;
3406 bit_index = x86_ldub_code(env, s) & 0x3F;
3407 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3408 offsetof(CPUX86State,xmm_regs[reg]));
3409 if (b1 == 1)
3410 gen_helper_extrq_i(cpu_env, s->ptr0,
3411 tcg_const_i32(bit_index),
3412 tcg_const_i32(field_length));
3413 else
3414 gen_helper_insertq_i(cpu_env, s->ptr0,
3415 tcg_const_i32(bit_index),
3416 tcg_const_i32(field_length));
3418 break;
3419 case 0x7e: /* movd ea, mm */
3420 #ifdef TARGET_X86_64
3421 if (s->dflag == MO_64) {
3422 tcg_gen_ld_i64(s->T0, cpu_env,
3423 offsetof(CPUX86State,fpregs[reg].mmx));
3424 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3425 } else
3426 #endif
3428 tcg_gen_ld32u_tl(s->T0, cpu_env,
3429 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3430 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3432 break;
3433 case 0x17e: /* movd ea, xmm */
3434 #ifdef TARGET_X86_64
3435 if (s->dflag == MO_64) {
3436 tcg_gen_ld_i64(s->T0, cpu_env,
3437 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3438 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3439 } else
3440 #endif
3442 tcg_gen_ld32u_tl(s->T0, cpu_env,
3443 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3444 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3446 break;
3447 case 0x27e: /* movq xmm, ea */
3448 if (mod != 3) {
3449 gen_lea_modrm(env, s, modrm);
3450 gen_ldq_env_A0(s, offsetof(CPUX86State,
3451 xmm_regs[reg].ZMM_Q(0)));
3452 } else {
3453 rm = (modrm & 7) | REX_B(s);
3454 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3455 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3457 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3458 break;
3459 case 0x7f: /* movq ea, mm */
3460 if (mod != 3) {
3461 gen_lea_modrm(env, s, modrm);
3462 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3463 } else {
3464 rm = (modrm & 7);
3465 gen_op_movq(s, offsetof(CPUX86State, fpregs[rm].mmx),
3466 offsetof(CPUX86State,fpregs[reg].mmx));
3468 break;
3469 case 0x011: /* movups */
3470 case 0x111: /* movupd */
3471 case 0x029: /* movaps */
3472 case 0x129: /* movapd */
3473 case 0x17f: /* movdqa ea, xmm */
3474 case 0x27f: /* movdqu ea, xmm */
3475 if (mod != 3) {
3476 gen_lea_modrm(env, s, modrm);
3477 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3478 } else {
3479 rm = (modrm & 7) | REX_B(s);
3480 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[rm]),
3481 offsetof(CPUX86State,xmm_regs[reg]));
3483 break;
3484 case 0x211: /* movss ea, xmm */
3485 if (mod != 3) {
3486 gen_lea_modrm(env, s, modrm);
3487 tcg_gen_ld32u_tl(s->T0, cpu_env,
3488 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3489 gen_op_st_v(s, MO_32, s->T0, s->A0);
3490 } else {
3491 rm = (modrm & 7) | REX_B(s);
3492 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0)),
3493 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3495 break;
3496 case 0x311: /* movsd ea, xmm */
3497 if (mod != 3) {
3498 gen_lea_modrm(env, s, modrm);
3499 gen_stq_env_A0(s, offsetof(CPUX86State,
3500 xmm_regs[reg].ZMM_Q(0)));
3501 } else {
3502 rm = (modrm & 7) | REX_B(s);
3503 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3504 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3506 break;
3507 case 0x013: /* movlps */
3508 case 0x113: /* movlpd */
3509 if (mod != 3) {
3510 gen_lea_modrm(env, s, modrm);
3511 gen_stq_env_A0(s, offsetof(CPUX86State,
3512 xmm_regs[reg].ZMM_Q(0)));
3513 } else {
3514 goto illegal_op;
3516 break;
3517 case 0x017: /* movhps */
3518 case 0x117: /* movhpd */
3519 if (mod != 3) {
3520 gen_lea_modrm(env, s, modrm);
3521 gen_stq_env_A0(s, offsetof(CPUX86State,
3522 xmm_regs[reg].ZMM_Q(1)));
3523 } else {
3524 goto illegal_op;
3526 break;
3527 case 0x71: /* shift mm, im */
3528 case 0x72:
3529 case 0x73:
3530 case 0x171: /* shift xmm, im */
3531 case 0x172:
3532 case 0x173:
3533 if (b1 >= 2) {
3534 goto unknown_op;
3536 val = x86_ldub_code(env, s);
3537 if (is_xmm) {
3538 tcg_gen_movi_tl(s->T0, val);
3539 tcg_gen_st32_tl(s->T0, cpu_env,
3540 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3541 tcg_gen_movi_tl(s->T0, 0);
3542 tcg_gen_st32_tl(s->T0, cpu_env,
3543 offsetof(CPUX86State, xmm_t0.ZMM_L(1)));
3544 op1_offset = offsetof(CPUX86State,xmm_t0);
3545 } else {
3546 tcg_gen_movi_tl(s->T0, val);
3547 tcg_gen_st32_tl(s->T0, cpu_env,
3548 offsetof(CPUX86State, mmx_t0.MMX_L(0)));
3549 tcg_gen_movi_tl(s->T0, 0);
3550 tcg_gen_st32_tl(s->T0, cpu_env,
3551 offsetof(CPUX86State, mmx_t0.MMX_L(1)));
3552 op1_offset = offsetof(CPUX86State,mmx_t0);
3554 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3555 (((modrm >> 3)) & 7)][b1];
3556 if (!sse_fn_epp) {
3557 goto unknown_op;
3559 if (is_xmm) {
3560 rm = (modrm & 7) | REX_B(s);
3561 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3562 } else {
3563 rm = (modrm & 7);
3564 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3566 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3567 tcg_gen_addi_ptr(s->ptr1, cpu_env, op1_offset);
3568 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3569 break;
3570 case 0x050: /* movmskps */
3571 rm = (modrm & 7) | REX_B(s);
3572 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3573 offsetof(CPUX86State,xmm_regs[rm]));
3574 gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0);
3575 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3576 break;
3577 case 0x150: /* movmskpd */
3578 rm = (modrm & 7) | REX_B(s);
3579 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3580 offsetof(CPUX86State,xmm_regs[rm]));
3581 gen_helper_movmskpd(s->tmp2_i32, cpu_env, s->ptr0);
3582 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3583 break;
3584 case 0x02a: /* cvtpi2ps */
3585 case 0x12a: /* cvtpi2pd */
3586 gen_helper_enter_mmx(cpu_env);
3587 if (mod != 3) {
3588 gen_lea_modrm(env, s, modrm);
3589 op2_offset = offsetof(CPUX86State,mmx_t0);
3590 gen_ldq_env_A0(s, op2_offset);
3591 } else {
3592 rm = (modrm & 7);
3593 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3595 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3596 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3597 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3598 switch(b >> 8) {
3599 case 0x0:
3600 gen_helper_cvtpi2ps(cpu_env, s->ptr0, s->ptr1);
3601 break;
3602 default:
3603 case 0x1:
3604 gen_helper_cvtpi2pd(cpu_env, s->ptr0, s->ptr1);
3605 break;
3607 break;
3608 case 0x22a: /* cvtsi2ss */
3609 case 0x32a: /* cvtsi2sd */
3610 ot = mo_64_32(s->dflag);
3611 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3612 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3613 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3614 if (ot == MO_32) {
3615 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3616 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3617 sse_fn_epi(cpu_env, s->ptr0, s->tmp2_i32);
3618 } else {
3619 #ifdef TARGET_X86_64
3620 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3621 sse_fn_epl(cpu_env, s->ptr0, s->T0);
3622 #else
3623 goto illegal_op;
3624 #endif
3626 break;
3627 case 0x02c: /* cvttps2pi */
3628 case 0x12c: /* cvttpd2pi */
3629 case 0x02d: /* cvtps2pi */
3630 case 0x12d: /* cvtpd2pi */
3631 gen_helper_enter_mmx(cpu_env);
3632 if (mod != 3) {
3633 gen_lea_modrm(env, s, modrm);
3634 op2_offset = offsetof(CPUX86State,xmm_t0);
3635 gen_ldo_env_A0(s, op2_offset);
3636 } else {
3637 rm = (modrm & 7) | REX_B(s);
3638 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3640 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3641 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3642 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3643 switch(b) {
3644 case 0x02c:
3645 gen_helper_cvttps2pi(cpu_env, s->ptr0, s->ptr1);
3646 break;
3647 case 0x12c:
3648 gen_helper_cvttpd2pi(cpu_env, s->ptr0, s->ptr1);
3649 break;
3650 case 0x02d:
3651 gen_helper_cvtps2pi(cpu_env, s->ptr0, s->ptr1);
3652 break;
3653 case 0x12d:
3654 gen_helper_cvtpd2pi(cpu_env, s->ptr0, s->ptr1);
3655 break;
3657 break;
3658 case 0x22c: /* cvttss2si */
3659 case 0x32c: /* cvttsd2si */
3660 case 0x22d: /* cvtss2si */
3661 case 0x32d: /* cvtsd2si */
3662 ot = mo_64_32(s->dflag);
3663 if (mod != 3) {
3664 gen_lea_modrm(env, s, modrm);
3665 if ((b >> 8) & 1) {
3666 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3667 } else {
3668 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3669 tcg_gen_st32_tl(s->T0, cpu_env,
3670 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3672 op2_offset = offsetof(CPUX86State,xmm_t0);
3673 } else {
3674 rm = (modrm & 7) | REX_B(s);
3675 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3677 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3678 if (ot == MO_32) {
3679 SSEFunc_i_ep sse_fn_i_ep =
3680 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3681 sse_fn_i_ep(s->tmp2_i32, cpu_env, s->ptr0);
3682 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
3683 } else {
3684 #ifdef TARGET_X86_64
3685 SSEFunc_l_ep sse_fn_l_ep =
3686 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3687 sse_fn_l_ep(s->T0, cpu_env, s->ptr0);
3688 #else
3689 goto illegal_op;
3690 #endif
3692 gen_op_mov_reg_v(s, ot, reg, s->T0);
3693 break;
3694 case 0xc4: /* pinsrw */
3695 case 0x1c4:
3696 s->rip_offset = 1;
3697 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3698 val = x86_ldub_code(env, s);
3699 if (b1) {
3700 val &= 7;
3701 tcg_gen_st16_tl(s->T0, cpu_env,
3702 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3703 } else {
3704 val &= 3;
3705 tcg_gen_st16_tl(s->T0, cpu_env,
3706 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3708 break;
3709 case 0xc5: /* pextrw */
3710 case 0x1c5:
3711 if (mod != 3)
3712 goto illegal_op;
3713 ot = mo_64_32(s->dflag);
3714 val = x86_ldub_code(env, s);
3715 if (b1) {
3716 val &= 7;
3717 rm = (modrm & 7) | REX_B(s);
3718 tcg_gen_ld16u_tl(s->T0, cpu_env,
3719 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3720 } else {
3721 val &= 3;
3722 rm = (modrm & 7);
3723 tcg_gen_ld16u_tl(s->T0, cpu_env,
3724 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3726 reg = ((modrm >> 3) & 7) | REX_R(s);
3727 gen_op_mov_reg_v(s, ot, reg, s->T0);
3728 break;
3729 case 0x1d6: /* movq ea, xmm */
3730 if (mod != 3) {
3731 gen_lea_modrm(env, s, modrm);
3732 gen_stq_env_A0(s, offsetof(CPUX86State,
3733 xmm_regs[reg].ZMM_Q(0)));
3734 } else {
3735 rm = (modrm & 7) | REX_B(s);
3736 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3737 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3738 gen_op_movq_env_0(s,
3739 offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(1)));
3741 break;
3742 case 0x2d6: /* movq2dq */
3743 gen_helper_enter_mmx(cpu_env);
3744 rm = (modrm & 7);
3745 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3746 offsetof(CPUX86State,fpregs[rm].mmx));
3747 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3748 break;
3749 case 0x3d6: /* movdq2q */
3750 gen_helper_enter_mmx(cpu_env);
3751 rm = (modrm & 7) | REX_B(s);
3752 gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx),
3753 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3754 break;
3755 case 0xd7: /* pmovmskb */
3756 case 0x1d7:
3757 if (mod != 3)
3758 goto illegal_op;
3759 if (b1) {
3760 rm = (modrm & 7) | REX_B(s);
3761 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3762 offsetof(CPUX86State, xmm_regs[rm]));
3763 gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0);
3764 } else {
3765 rm = (modrm & 7);
3766 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3767 offsetof(CPUX86State, fpregs[rm].mmx));
3768 gen_helper_pmovmskb_mmx(s->tmp2_i32, cpu_env, s->ptr0);
3770 reg = ((modrm >> 3) & 7) | REX_R(s);
3771 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3772 break;
3774 case 0x138:
3775 case 0x038:
3776 b = modrm;
3777 if ((b & 0xf0) == 0xf0) {
3778 goto do_0f_38_fx;
3780 modrm = x86_ldub_code(env, s);
3781 rm = modrm & 7;
3782 reg = ((modrm >> 3) & 7) | REX_R(s);
3783 mod = (modrm >> 6) & 3;
3784 if (b1 >= 2) {
3785 goto unknown_op;
3788 sse_fn_epp = sse_op_table6[b].op[b1];
3789 if (!sse_fn_epp) {
3790 goto unknown_op;
3792 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3793 goto illegal_op;
3795 if (b1) {
3796 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3797 if (mod == 3) {
3798 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3799 } else {
3800 op2_offset = offsetof(CPUX86State,xmm_t0);
3801 gen_lea_modrm(env, s, modrm);
3802 switch (b) {
3803 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3804 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3805 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3806 gen_ldq_env_A0(s, op2_offset +
3807 offsetof(ZMMReg, ZMM_Q(0)));
3808 break;
3809 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3810 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3811 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
3812 s->mem_index, MO_LEUL);
3813 tcg_gen_st_i32(s->tmp2_i32, cpu_env, op2_offset +
3814 offsetof(ZMMReg, ZMM_L(0)));
3815 break;
3816 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3817 tcg_gen_qemu_ld_tl(s->tmp0, s->A0,
3818 s->mem_index, MO_LEUW);
3819 tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset +
3820 offsetof(ZMMReg, ZMM_W(0)));
3821 break;
3822 case 0x2a: /* movntqda */
3823 gen_ldo_env_A0(s, op1_offset);
3824 return;
3825 default:
3826 gen_ldo_env_A0(s, op2_offset);
3829 } else {
3830 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3831 if (mod == 3) {
3832 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3833 } else {
3834 op2_offset = offsetof(CPUX86State,mmx_t0);
3835 gen_lea_modrm(env, s, modrm);
3836 gen_ldq_env_A0(s, op2_offset);
3839 if (sse_fn_epp == SSE_SPECIAL) {
3840 goto unknown_op;
3843 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3844 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3845 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3847 if (b == 0x17) {
3848 set_cc_op(s, CC_OP_EFLAGS);
3850 break;
3852 case 0x238:
3853 case 0x338:
3854 do_0f_38_fx:
3855 /* Various integer extensions at 0f 38 f[0-f]. */
3856 b = modrm | (b1 << 8);
3857 modrm = x86_ldub_code(env, s);
3858 reg = ((modrm >> 3) & 7) | REX_R(s);
3860 switch (b) {
3861 case 0x3f0: /* crc32 Gd,Eb */
3862 case 0x3f1: /* crc32 Gd,Ey */
3863 do_crc32:
3864 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3865 goto illegal_op;
3867 if ((b & 0xff) == 0xf0) {
3868 ot = MO_8;
3869 } else if (s->dflag != MO_64) {
3870 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3871 } else {
3872 ot = MO_64;
3875 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[reg]);
3876 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3877 gen_helper_crc32(s->T0, s->tmp2_i32,
3878 s->T0, tcg_const_i32(8 << ot));
3880 ot = mo_64_32(s->dflag);
3881 gen_op_mov_reg_v(s, ot, reg, s->T0);
3882 break;
3884 case 0x1f0: /* crc32 or movbe */
3885 case 0x1f1:
3886 /* For these insns, the f3 prefix is supposed to have priority
3887 over the 66 prefix, but that's not what we implement above
3888 setting b1. */
3889 if (s->prefix & PREFIX_REPNZ) {
3890 goto do_crc32;
3892 /* FALLTHRU */
3893 case 0x0f0: /* movbe Gy,My */
3894 case 0x0f1: /* movbe My,Gy */
3895 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3896 goto illegal_op;
3898 if (s->dflag != MO_64) {
3899 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3900 } else {
3901 ot = MO_64;
3904 gen_lea_modrm(env, s, modrm);
3905 if ((b & 1) == 0) {
3906 tcg_gen_qemu_ld_tl(s->T0, s->A0,
3907 s->mem_index, ot | MO_BE);
3908 gen_op_mov_reg_v(s, ot, reg, s->T0);
3909 } else {
3910 tcg_gen_qemu_st_tl(cpu_regs[reg], s->A0,
3911 s->mem_index, ot | MO_BE);
3913 break;
3915 case 0x0f2: /* andn Gy, By, Ey */
3916 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3917 || !(s->prefix & PREFIX_VEX)
3918 || s->vex_l != 0) {
3919 goto illegal_op;
3921 ot = mo_64_32(s->dflag);
3922 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3923 tcg_gen_andc_tl(s->T0, s->T0, cpu_regs[s->vex_v]);
3924 gen_op_mov_reg_v(s, ot, reg, s->T0);
3925 gen_op_update1_cc(s);
3926 set_cc_op(s, CC_OP_LOGICB + ot);
3927 break;
3929 case 0x0f7: /* bextr Gy, Ey, By */
3930 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3931 || !(s->prefix & PREFIX_VEX)
3932 || s->vex_l != 0) {
3933 goto illegal_op;
3935 ot = mo_64_32(s->dflag);
3937 TCGv bound, zero;
3939 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3940 /* Extract START, and shift the operand.
3941 Shifts larger than operand size get zeros. */
3942 tcg_gen_ext8u_tl(s->A0, cpu_regs[s->vex_v]);
3943 tcg_gen_shr_tl(s->T0, s->T0, s->A0);
3945 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3946 zero = tcg_const_tl(0);
3947 tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound,
3948 s->T0, zero);
3949 tcg_temp_free(zero);
3951 /* Extract the LEN into a mask. Lengths larger than
3952 operand size get all ones. */
3953 tcg_gen_extract_tl(s->A0, cpu_regs[s->vex_v], 8, 8);
3954 tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound,
3955 s->A0, bound);
3956 tcg_temp_free(bound);
3957 tcg_gen_movi_tl(s->T1, 1);
3958 tcg_gen_shl_tl(s->T1, s->T1, s->A0);
3959 tcg_gen_subi_tl(s->T1, s->T1, 1);
3960 tcg_gen_and_tl(s->T0, s->T0, s->T1);
3962 gen_op_mov_reg_v(s, ot, reg, s->T0);
3963 gen_op_update1_cc(s);
3964 set_cc_op(s, CC_OP_LOGICB + ot);
3966 break;
3968 case 0x0f5: /* bzhi Gy, Ey, By */
3969 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3970 || !(s->prefix & PREFIX_VEX)
3971 || s->vex_l != 0) {
3972 goto illegal_op;
3974 ot = mo_64_32(s->dflag);
3975 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3976 tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]);
3978 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3979 /* Note that since we're using BMILG (in order to get O
3980 cleared) we need to store the inverse into C. */
3981 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3982 s->T1, bound);
3983 tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1,
3984 bound, bound, s->T1);
3985 tcg_temp_free(bound);
3987 tcg_gen_movi_tl(s->A0, -1);
3988 tcg_gen_shl_tl(s->A0, s->A0, s->T1);
3989 tcg_gen_andc_tl(s->T0, s->T0, s->A0);
3990 gen_op_mov_reg_v(s, ot, reg, s->T0);
3991 gen_op_update1_cc(s);
3992 set_cc_op(s, CC_OP_BMILGB + ot);
3993 break;
3995 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3996 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3997 || !(s->prefix & PREFIX_VEX)
3998 || s->vex_l != 0) {
3999 goto illegal_op;
4001 ot = mo_64_32(s->dflag);
4002 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4003 switch (ot) {
4004 default:
4005 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4006 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EDX]);
4007 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
4008 s->tmp2_i32, s->tmp3_i32);
4009 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32);
4010 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp3_i32);
4011 break;
4012 #ifdef TARGET_X86_64
4013 case MO_64:
4014 tcg_gen_mulu2_i64(s->T0, s->T1,
4015 s->T0, cpu_regs[R_EDX]);
4016 tcg_gen_mov_i64(cpu_regs[s->vex_v], s->T0);
4017 tcg_gen_mov_i64(cpu_regs[reg], s->T1);
4018 break;
4019 #endif
4021 break;
4023 case 0x3f5: /* pdep 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_pdep(cpu_regs[reg], s->T1, s->T0);
4039 break;
4041 case 0x2f5: /* pext Gy, By, Ey */
4042 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4043 || !(s->prefix & PREFIX_VEX)
4044 || s->vex_l != 0) {
4045 goto illegal_op;
4047 ot = mo_64_32(s->dflag);
4048 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4049 /* Note that by zero-extending the source operand, we
4050 automatically handle zero-extending the result. */
4051 if (ot == MO_64) {
4052 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
4053 } else {
4054 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
4056 gen_helper_pext(cpu_regs[reg], s->T1, s->T0);
4057 break;
4059 case 0x1f6: /* adcx Gy, Ey */
4060 case 0x2f6: /* adox Gy, Ey */
4061 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
4062 goto illegal_op;
4063 } else {
4064 TCGv carry_in, carry_out, zero;
4065 int end_op;
4067 ot = mo_64_32(s->dflag);
4068 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4070 /* Re-use the carry-out from a previous round. */
4071 carry_in = NULL;
4072 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
4073 switch (s->cc_op) {
4074 case CC_OP_ADCX:
4075 if (b == 0x1f6) {
4076 carry_in = cpu_cc_dst;
4077 end_op = CC_OP_ADCX;
4078 } else {
4079 end_op = CC_OP_ADCOX;
4081 break;
4082 case CC_OP_ADOX:
4083 if (b == 0x1f6) {
4084 end_op = CC_OP_ADCOX;
4085 } else {
4086 carry_in = cpu_cc_src2;
4087 end_op = CC_OP_ADOX;
4089 break;
4090 case CC_OP_ADCOX:
4091 end_op = CC_OP_ADCOX;
4092 carry_in = carry_out;
4093 break;
4094 default:
4095 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
4096 break;
4098 /* If we can't reuse carry-out, get it out of EFLAGS. */
4099 if (!carry_in) {
4100 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4101 gen_compute_eflags(s);
4103 carry_in = s->tmp0;
4104 tcg_gen_extract_tl(carry_in, cpu_cc_src,
4105 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
4108 switch (ot) {
4109 #ifdef TARGET_X86_64
4110 case MO_32:
4111 /* If we know TL is 64-bit, and we want a 32-bit
4112 result, just do everything in 64-bit arithmetic. */
4113 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4114 tcg_gen_ext32u_i64(s->T0, s->T0);
4115 tcg_gen_add_i64(s->T0, s->T0, cpu_regs[reg]);
4116 tcg_gen_add_i64(s->T0, s->T0, carry_in);
4117 tcg_gen_ext32u_i64(cpu_regs[reg], s->T0);
4118 tcg_gen_shri_i64(carry_out, s->T0, 32);
4119 break;
4120 #endif
4121 default:
4122 /* Otherwise compute the carry-out in two steps. */
4123 zero = tcg_const_tl(0);
4124 tcg_gen_add2_tl(s->T0, carry_out,
4125 s->T0, zero,
4126 carry_in, zero);
4127 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4128 cpu_regs[reg], carry_out,
4129 s->T0, zero);
4130 tcg_temp_free(zero);
4131 break;
4133 set_cc_op(s, end_op);
4135 break;
4137 case 0x1f7: /* shlx Gy, Ey, By */
4138 case 0x2f7: /* sarx Gy, Ey, By */
4139 case 0x3f7: /* shrx Gy, Ey, By */
4140 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4141 || !(s->prefix & PREFIX_VEX)
4142 || s->vex_l != 0) {
4143 goto illegal_op;
4145 ot = mo_64_32(s->dflag);
4146 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4147 if (ot == MO_64) {
4148 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 63);
4149 } else {
4150 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 31);
4152 if (b == 0x1f7) {
4153 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
4154 } else if (b == 0x2f7) {
4155 if (ot != MO_64) {
4156 tcg_gen_ext32s_tl(s->T0, s->T0);
4158 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
4159 } else {
4160 if (ot != MO_64) {
4161 tcg_gen_ext32u_tl(s->T0, s->T0);
4163 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
4165 gen_op_mov_reg_v(s, ot, reg, s->T0);
4166 break;
4168 case 0x0f3:
4169 case 0x1f3:
4170 case 0x2f3:
4171 case 0x3f3: /* Group 17 */
4172 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4173 || !(s->prefix & PREFIX_VEX)
4174 || s->vex_l != 0) {
4175 goto illegal_op;
4177 ot = mo_64_32(s->dflag);
4178 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4180 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4181 switch (reg & 7) {
4182 case 1: /* blsr By,Ey */
4183 tcg_gen_subi_tl(s->T1, s->T0, 1);
4184 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4185 break;
4186 case 2: /* blsmsk By,Ey */
4187 tcg_gen_subi_tl(s->T1, s->T0, 1);
4188 tcg_gen_xor_tl(s->T0, s->T0, s->T1);
4189 break;
4190 case 3: /* blsi By, Ey */
4191 tcg_gen_neg_tl(s->T1, s->T0);
4192 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4193 break;
4194 default:
4195 goto unknown_op;
4197 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4198 gen_op_mov_reg_v(s, ot, s->vex_v, s->T0);
4199 set_cc_op(s, CC_OP_BMILGB + ot);
4200 break;
4202 default:
4203 goto unknown_op;
4205 break;
4207 case 0x03a:
4208 case 0x13a:
4209 b = modrm;
4210 modrm = x86_ldub_code(env, s);
4211 rm = modrm & 7;
4212 reg = ((modrm >> 3) & 7) | REX_R(s);
4213 mod = (modrm >> 6) & 3;
4214 if (b1 >= 2) {
4215 goto unknown_op;
4218 sse_fn_eppi = sse_op_table7[b].op[b1];
4219 if (!sse_fn_eppi) {
4220 goto unknown_op;
4222 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4223 goto illegal_op;
4225 s->rip_offset = 1;
4227 if (sse_fn_eppi == SSE_SPECIAL) {
4228 ot = mo_64_32(s->dflag);
4229 rm = (modrm & 7) | REX_B(s);
4230 if (mod != 3)
4231 gen_lea_modrm(env, s, modrm);
4232 reg = ((modrm >> 3) & 7) | REX_R(s);
4233 val = x86_ldub_code(env, s);
4234 switch (b) {
4235 case 0x14: /* pextrb */
4236 tcg_gen_ld8u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4237 xmm_regs[reg].ZMM_B(val & 15)));
4238 if (mod == 3) {
4239 gen_op_mov_reg_v(s, ot, rm, s->T0);
4240 } else {
4241 tcg_gen_qemu_st_tl(s->T0, s->A0,
4242 s->mem_index, MO_UB);
4244 break;
4245 case 0x15: /* pextrw */
4246 tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4247 xmm_regs[reg].ZMM_W(val & 7)));
4248 if (mod == 3) {
4249 gen_op_mov_reg_v(s, ot, rm, s->T0);
4250 } else {
4251 tcg_gen_qemu_st_tl(s->T0, s->A0,
4252 s->mem_index, MO_LEUW);
4254 break;
4255 case 0x16:
4256 if (ot == MO_32) { /* pextrd */
4257 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4258 offsetof(CPUX86State,
4259 xmm_regs[reg].ZMM_L(val & 3)));
4260 if (mod == 3) {
4261 tcg_gen_extu_i32_tl(cpu_regs[rm], s->tmp2_i32);
4262 } else {
4263 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4264 s->mem_index, MO_LEUL);
4266 } else { /* pextrq */
4267 #ifdef TARGET_X86_64
4268 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
4269 offsetof(CPUX86State,
4270 xmm_regs[reg].ZMM_Q(val & 1)));
4271 if (mod == 3) {
4272 tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64);
4273 } else {
4274 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4275 s->mem_index, MO_LEQ);
4277 #else
4278 goto illegal_op;
4279 #endif
4281 break;
4282 case 0x17: /* extractps */
4283 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4284 xmm_regs[reg].ZMM_L(val & 3)));
4285 if (mod == 3) {
4286 gen_op_mov_reg_v(s, ot, rm, s->T0);
4287 } else {
4288 tcg_gen_qemu_st_tl(s->T0, s->A0,
4289 s->mem_index, MO_LEUL);
4291 break;
4292 case 0x20: /* pinsrb */
4293 if (mod == 3) {
4294 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
4295 } else {
4296 tcg_gen_qemu_ld_tl(s->T0, s->A0,
4297 s->mem_index, MO_UB);
4299 tcg_gen_st8_tl(s->T0, cpu_env, offsetof(CPUX86State,
4300 xmm_regs[reg].ZMM_B(val & 15)));
4301 break;
4302 case 0x21: /* insertps */
4303 if (mod == 3) {
4304 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4305 offsetof(CPUX86State,xmm_regs[rm]
4306 .ZMM_L((val >> 6) & 3)));
4307 } else {
4308 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4309 s->mem_index, MO_LEUL);
4311 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4312 offsetof(CPUX86State,xmm_regs[reg]
4313 .ZMM_L((val >> 4) & 3)));
4314 if ((val >> 0) & 1)
4315 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4316 cpu_env, offsetof(CPUX86State,
4317 xmm_regs[reg].ZMM_L(0)));
4318 if ((val >> 1) & 1)
4319 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4320 cpu_env, offsetof(CPUX86State,
4321 xmm_regs[reg].ZMM_L(1)));
4322 if ((val >> 2) & 1)
4323 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4324 cpu_env, offsetof(CPUX86State,
4325 xmm_regs[reg].ZMM_L(2)));
4326 if ((val >> 3) & 1)
4327 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4328 cpu_env, offsetof(CPUX86State,
4329 xmm_regs[reg].ZMM_L(3)));
4330 break;
4331 case 0x22:
4332 if (ot == MO_32) { /* pinsrd */
4333 if (mod == 3) {
4334 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[rm]);
4335 } else {
4336 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4337 s->mem_index, MO_LEUL);
4339 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4340 offsetof(CPUX86State,
4341 xmm_regs[reg].ZMM_L(val & 3)));
4342 } else { /* pinsrq */
4343 #ifdef TARGET_X86_64
4344 if (mod == 3) {
4345 gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm);
4346 } else {
4347 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4348 s->mem_index, MO_LEQ);
4350 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
4351 offsetof(CPUX86State,
4352 xmm_regs[reg].ZMM_Q(val & 1)));
4353 #else
4354 goto illegal_op;
4355 #endif
4357 break;
4359 return;
4362 if (b1) {
4363 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4364 if (mod == 3) {
4365 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4366 } else {
4367 op2_offset = offsetof(CPUX86State,xmm_t0);
4368 gen_lea_modrm(env, s, modrm);
4369 gen_ldo_env_A0(s, op2_offset);
4371 } else {
4372 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4373 if (mod == 3) {
4374 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4375 } else {
4376 op2_offset = offsetof(CPUX86State,mmx_t0);
4377 gen_lea_modrm(env, s, modrm);
4378 gen_ldq_env_A0(s, op2_offset);
4381 val = x86_ldub_code(env, s);
4383 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4384 set_cc_op(s, CC_OP_EFLAGS);
4386 if (s->dflag == MO_64) {
4387 /* The helper must use entire 64-bit gp registers */
4388 val |= 1 << 8;
4392 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4393 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4394 sse_fn_eppi(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val));
4395 break;
4397 case 0x33a:
4398 /* Various integer extensions at 0f 3a f[0-f]. */
4399 b = modrm | (b1 << 8);
4400 modrm = x86_ldub_code(env, s);
4401 reg = ((modrm >> 3) & 7) | REX_R(s);
4403 switch (b) {
4404 case 0x3f0: /* rorx Gy,Ey, Ib */
4405 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4406 || !(s->prefix & PREFIX_VEX)
4407 || s->vex_l != 0) {
4408 goto illegal_op;
4410 ot = mo_64_32(s->dflag);
4411 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4412 b = x86_ldub_code(env, s);
4413 if (ot == MO_64) {
4414 tcg_gen_rotri_tl(s->T0, s->T0, b & 63);
4415 } else {
4416 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4417 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b & 31);
4418 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
4420 gen_op_mov_reg_v(s, ot, reg, s->T0);
4421 break;
4423 default:
4424 goto unknown_op;
4426 break;
4428 default:
4429 unknown_op:
4430 gen_unknown_opcode(env, s);
4431 return;
4433 } else {
4434 /* generic MMX or SSE operation */
4435 switch(b) {
4436 case 0x70: /* pshufx insn */
4437 case 0xc6: /* pshufx insn */
4438 case 0xc2: /* compare insns */
4439 s->rip_offset = 1;
4440 break;
4441 default:
4442 break;
4444 if (is_xmm) {
4445 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4446 if (mod != 3) {
4447 int sz = 4;
4449 gen_lea_modrm(env, s, modrm);
4450 op2_offset = offsetof(CPUX86State,xmm_t0);
4452 switch (b) {
4453 case 0x50 ... 0x5a:
4454 case 0x5c ... 0x5f:
4455 case 0xc2:
4456 /* Most sse scalar operations. */
4457 if (b1 == 2) {
4458 sz = 2;
4459 } else if (b1 == 3) {
4460 sz = 3;
4462 break;
4464 case 0x2e: /* ucomis[sd] */
4465 case 0x2f: /* comis[sd] */
4466 if (b1 == 0) {
4467 sz = 2;
4468 } else {
4469 sz = 3;
4471 break;
4474 switch (sz) {
4475 case 2:
4476 /* 32 bit access */
4477 gen_op_ld_v(s, MO_32, s->T0, s->A0);
4478 tcg_gen_st32_tl(s->T0, cpu_env,
4479 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4480 break;
4481 case 3:
4482 /* 64 bit access */
4483 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4484 break;
4485 default:
4486 /* 128 bit access */
4487 gen_ldo_env_A0(s, op2_offset);
4488 break;
4490 } else {
4491 rm = (modrm & 7) | REX_B(s);
4492 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4494 } else {
4495 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4496 if (mod != 3) {
4497 gen_lea_modrm(env, s, modrm);
4498 op2_offset = offsetof(CPUX86State,mmx_t0);
4499 gen_ldq_env_A0(s, op2_offset);
4500 } else {
4501 rm = (modrm & 7);
4502 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4505 switch(b) {
4506 case 0x0f: /* 3DNow! data insns */
4507 val = x86_ldub_code(env, s);
4508 sse_fn_epp = sse_op_table5[val];
4509 if (!sse_fn_epp) {
4510 goto unknown_op;
4512 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4513 goto illegal_op;
4515 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4516 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4517 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4518 break;
4519 case 0x70: /* pshufx insn */
4520 case 0xc6: /* pshufx insn */
4521 val = x86_ldub_code(env, s);
4522 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4523 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4524 /* XXX: introduce a new table? */
4525 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4526 sse_fn_ppi(s->ptr0, s->ptr1, tcg_const_i32(val));
4527 break;
4528 case 0xc2:
4529 /* compare insns */
4530 val = x86_ldub_code(env, s);
4531 if (val >= 8)
4532 goto unknown_op;
4533 sse_fn_epp = sse_op_table4[val][b1];
4535 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4536 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4537 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4538 break;
4539 case 0xf7:
4540 /* maskmov : we must prepare A0 */
4541 if (mod != 3)
4542 goto illegal_op;
4543 tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]);
4544 gen_extu(s->aflag, s->A0);
4545 gen_add_A0_ds_seg(s);
4547 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4548 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4549 /* XXX: introduce a new table? */
4550 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4551 sse_fn_eppt(cpu_env, s->ptr0, s->ptr1, s->A0);
4552 break;
4553 default:
4554 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4555 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4556 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4557 break;
4559 if (b == 0x2e || b == 0x2f) {
4560 set_cc_op(s, CC_OP_EFLAGS);
4565 /* convert one instruction. s->base.is_jmp is set if the translation must
4566 be stopped. Return the next pc value */
4567 static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
4569 CPUX86State *env = cpu->env_ptr;
4570 int b, prefixes;
4571 int shift;
4572 MemOp ot, aflag, dflag;
4573 int modrm, reg, rm, mod, op, opreg, val;
4574 target_ulong next_eip, tval;
4575 target_ulong pc_start = s->base.pc_next;
4577 s->pc_start = s->pc = pc_start;
4578 s->override = -1;
4579 #ifdef TARGET_X86_64
4580 s->rex_w = false;
4581 s->rex_r = 0;
4582 s->rex_x = 0;
4583 s->rex_b = 0;
4584 #endif
4585 s->rip_offset = 0; /* for relative ip address */
4586 s->vex_l = 0;
4587 s->vex_v = 0;
4588 if (sigsetjmp(s->jmpbuf, 0) != 0) {
4589 gen_exception_gpf(s);
4590 return s->pc;
4593 prefixes = 0;
4595 next_byte:
4596 b = x86_ldub_code(env, s);
4597 /* Collect prefixes. */
4598 switch (b) {
4599 case 0xf3:
4600 prefixes |= PREFIX_REPZ;
4601 goto next_byte;
4602 case 0xf2:
4603 prefixes |= PREFIX_REPNZ;
4604 goto next_byte;
4605 case 0xf0:
4606 prefixes |= PREFIX_LOCK;
4607 goto next_byte;
4608 case 0x2e:
4609 s->override = R_CS;
4610 goto next_byte;
4611 case 0x36:
4612 s->override = R_SS;
4613 goto next_byte;
4614 case 0x3e:
4615 s->override = R_DS;
4616 goto next_byte;
4617 case 0x26:
4618 s->override = R_ES;
4619 goto next_byte;
4620 case 0x64:
4621 s->override = R_FS;
4622 goto next_byte;
4623 case 0x65:
4624 s->override = R_GS;
4625 goto next_byte;
4626 case 0x66:
4627 prefixes |= PREFIX_DATA;
4628 goto next_byte;
4629 case 0x67:
4630 prefixes |= PREFIX_ADR;
4631 goto next_byte;
4632 #ifdef TARGET_X86_64
4633 case 0x40 ... 0x4f:
4634 if (CODE64(s)) {
4635 /* REX prefix */
4636 prefixes |= PREFIX_REX;
4637 s->rex_w = (b >> 3) & 1;
4638 s->rex_r = (b & 0x4) << 1;
4639 s->rex_x = (b & 0x2) << 2;
4640 s->rex_b = (b & 0x1) << 3;
4641 goto next_byte;
4643 break;
4644 #endif
4645 case 0xc5: /* 2-byte VEX */
4646 case 0xc4: /* 3-byte VEX */
4647 /* VEX prefixes cannot be used except in 32-bit mode.
4648 Otherwise the instruction is LES or LDS. */
4649 if (CODE32(s) && !VM86(s)) {
4650 static const int pp_prefix[4] = {
4651 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4653 int vex3, vex2 = x86_ldub_code(env, s);
4655 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4656 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4657 otherwise the instruction is LES or LDS. */
4658 s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
4659 break;
4662 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4663 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4664 | PREFIX_LOCK | PREFIX_DATA | PREFIX_REX)) {
4665 goto illegal_op;
4667 #ifdef TARGET_X86_64
4668 s->rex_r = (~vex2 >> 4) & 8;
4669 #endif
4670 if (b == 0xc5) {
4671 /* 2-byte VEX prefix: RVVVVlpp, implied 0f leading opcode byte */
4672 vex3 = vex2;
4673 b = x86_ldub_code(env, s) | 0x100;
4674 } else {
4675 /* 3-byte VEX prefix: RXBmmmmm wVVVVlpp */
4676 vex3 = x86_ldub_code(env, s);
4677 #ifdef TARGET_X86_64
4678 s->rex_x = (~vex2 >> 3) & 8;
4679 s->rex_b = (~vex2 >> 2) & 8;
4680 s->rex_w = (vex3 >> 7) & 1;
4681 #endif
4682 switch (vex2 & 0x1f) {
4683 case 0x01: /* Implied 0f leading opcode bytes. */
4684 b = x86_ldub_code(env, s) | 0x100;
4685 break;
4686 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4687 b = 0x138;
4688 break;
4689 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4690 b = 0x13a;
4691 break;
4692 default: /* Reserved for future use. */
4693 goto unknown_op;
4696 s->vex_v = (~vex3 >> 3) & 0xf;
4697 s->vex_l = (vex3 >> 2) & 1;
4698 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4700 break;
4703 /* Post-process prefixes. */
4704 if (CODE64(s)) {
4705 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4706 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4707 over 0x66 if both are present. */
4708 dflag = (REX_W(s) ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4709 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4710 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4711 } else {
4712 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4713 if (CODE32(s) ^ ((prefixes & PREFIX_DATA) != 0)) {
4714 dflag = MO_32;
4715 } else {
4716 dflag = MO_16;
4718 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4719 if (CODE32(s) ^ ((prefixes & PREFIX_ADR) != 0)) {
4720 aflag = MO_32;
4721 } else {
4722 aflag = MO_16;
4726 s->prefix = prefixes;
4727 s->aflag = aflag;
4728 s->dflag = dflag;
4730 /* now check op code */
4731 reswitch:
4732 switch(b) {
4733 case 0x0f:
4734 /**************************/
4735 /* extended op code */
4736 b = x86_ldub_code(env, s) | 0x100;
4737 goto reswitch;
4739 /**************************/
4740 /* arith & logic */
4741 case 0x00 ... 0x05:
4742 case 0x08 ... 0x0d:
4743 case 0x10 ... 0x15:
4744 case 0x18 ... 0x1d:
4745 case 0x20 ... 0x25:
4746 case 0x28 ... 0x2d:
4747 case 0x30 ... 0x35:
4748 case 0x38 ... 0x3d:
4750 int op, f, val;
4751 op = (b >> 3) & 7;
4752 f = (b >> 1) & 3;
4754 ot = mo_b_d(b, dflag);
4756 switch(f) {
4757 case 0: /* OP Ev, Gv */
4758 modrm = x86_ldub_code(env, s);
4759 reg = ((modrm >> 3) & 7) | REX_R(s);
4760 mod = (modrm >> 6) & 3;
4761 rm = (modrm & 7) | REX_B(s);
4762 if (mod != 3) {
4763 gen_lea_modrm(env, s, modrm);
4764 opreg = OR_TMP0;
4765 } else if (op == OP_XORL && rm == reg) {
4766 xor_zero:
4767 /* xor reg, reg optimisation */
4768 set_cc_op(s, CC_OP_CLR);
4769 tcg_gen_movi_tl(s->T0, 0);
4770 gen_op_mov_reg_v(s, ot, reg, s->T0);
4771 break;
4772 } else {
4773 opreg = rm;
4775 gen_op_mov_v_reg(s, ot, s->T1, reg);
4776 gen_op(s, op, ot, opreg);
4777 break;
4778 case 1: /* OP Gv, Ev */
4779 modrm = x86_ldub_code(env, s);
4780 mod = (modrm >> 6) & 3;
4781 reg = ((modrm >> 3) & 7) | REX_R(s);
4782 rm = (modrm & 7) | REX_B(s);
4783 if (mod != 3) {
4784 gen_lea_modrm(env, s, modrm);
4785 gen_op_ld_v(s, ot, s->T1, s->A0);
4786 } else if (op == OP_XORL && rm == reg) {
4787 goto xor_zero;
4788 } else {
4789 gen_op_mov_v_reg(s, ot, s->T1, rm);
4791 gen_op(s, op, ot, reg);
4792 break;
4793 case 2: /* OP A, Iv */
4794 val = insn_get(env, s, ot);
4795 tcg_gen_movi_tl(s->T1, val);
4796 gen_op(s, op, ot, OR_EAX);
4797 break;
4800 break;
4802 case 0x82:
4803 if (CODE64(s))
4804 goto illegal_op;
4805 /* fall through */
4806 case 0x80: /* GRP1 */
4807 case 0x81:
4808 case 0x83:
4810 int val;
4812 ot = mo_b_d(b, dflag);
4814 modrm = x86_ldub_code(env, s);
4815 mod = (modrm >> 6) & 3;
4816 rm = (modrm & 7) | REX_B(s);
4817 op = (modrm >> 3) & 7;
4819 if (mod != 3) {
4820 if (b == 0x83)
4821 s->rip_offset = 1;
4822 else
4823 s->rip_offset = insn_const_size(ot);
4824 gen_lea_modrm(env, s, modrm);
4825 opreg = OR_TMP0;
4826 } else {
4827 opreg = rm;
4830 switch(b) {
4831 default:
4832 case 0x80:
4833 case 0x81:
4834 case 0x82:
4835 val = insn_get(env, s, ot);
4836 break;
4837 case 0x83:
4838 val = (int8_t)insn_get(env, s, MO_8);
4839 break;
4841 tcg_gen_movi_tl(s->T1, val);
4842 gen_op(s, op, ot, opreg);
4844 break;
4846 /**************************/
4847 /* inc, dec, and other misc arith */
4848 case 0x40 ... 0x47: /* inc Gv */
4849 ot = dflag;
4850 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4851 break;
4852 case 0x48 ... 0x4f: /* dec Gv */
4853 ot = dflag;
4854 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4855 break;
4856 case 0xf6: /* GRP3 */
4857 case 0xf7:
4858 ot = mo_b_d(b, dflag);
4860 modrm = x86_ldub_code(env, s);
4861 mod = (modrm >> 6) & 3;
4862 rm = (modrm & 7) | REX_B(s);
4863 op = (modrm >> 3) & 7;
4864 if (mod != 3) {
4865 if (op == 0) {
4866 s->rip_offset = insn_const_size(ot);
4868 gen_lea_modrm(env, s, modrm);
4869 /* For those below that handle locked memory, don't load here. */
4870 if (!(s->prefix & PREFIX_LOCK)
4871 || op != 2) {
4872 gen_op_ld_v(s, ot, s->T0, s->A0);
4874 } else {
4875 gen_op_mov_v_reg(s, ot, s->T0, rm);
4878 switch(op) {
4879 case 0: /* test */
4880 val = insn_get(env, s, ot);
4881 tcg_gen_movi_tl(s->T1, val);
4882 gen_op_testl_T0_T1_cc(s);
4883 set_cc_op(s, CC_OP_LOGICB + ot);
4884 break;
4885 case 2: /* not */
4886 if (s->prefix & PREFIX_LOCK) {
4887 if (mod == 3) {
4888 goto illegal_op;
4890 tcg_gen_movi_tl(s->T0, ~0);
4891 tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0,
4892 s->mem_index, ot | MO_LE);
4893 } else {
4894 tcg_gen_not_tl(s->T0, s->T0);
4895 if (mod != 3) {
4896 gen_op_st_v(s, ot, s->T0, s->A0);
4897 } else {
4898 gen_op_mov_reg_v(s, ot, rm, s->T0);
4901 break;
4902 case 3: /* neg */
4903 if (s->prefix & PREFIX_LOCK) {
4904 TCGLabel *label1;
4905 TCGv a0, t0, t1, t2;
4907 if (mod == 3) {
4908 goto illegal_op;
4910 a0 = tcg_temp_local_new();
4911 t0 = tcg_temp_local_new();
4912 label1 = gen_new_label();
4914 tcg_gen_mov_tl(a0, s->A0);
4915 tcg_gen_mov_tl(t0, s->T0);
4917 gen_set_label(label1);
4918 t1 = tcg_temp_new();
4919 t2 = tcg_temp_new();
4920 tcg_gen_mov_tl(t2, t0);
4921 tcg_gen_neg_tl(t1, t0);
4922 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4923 s->mem_index, ot | MO_LE);
4924 tcg_temp_free(t1);
4925 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4927 tcg_temp_free(t2);
4928 tcg_temp_free(a0);
4929 tcg_gen_mov_tl(s->T0, t0);
4930 tcg_temp_free(t0);
4931 } else {
4932 tcg_gen_neg_tl(s->T0, s->T0);
4933 if (mod != 3) {
4934 gen_op_st_v(s, ot, s->T0, s->A0);
4935 } else {
4936 gen_op_mov_reg_v(s, ot, rm, s->T0);
4939 gen_op_update_neg_cc(s);
4940 set_cc_op(s, CC_OP_SUBB + ot);
4941 break;
4942 case 4: /* mul */
4943 switch(ot) {
4944 case MO_8:
4945 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4946 tcg_gen_ext8u_tl(s->T0, s->T0);
4947 tcg_gen_ext8u_tl(s->T1, s->T1);
4948 /* XXX: use 32 bit mul which could be faster */
4949 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4950 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4951 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4952 tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00);
4953 set_cc_op(s, CC_OP_MULB);
4954 break;
4955 case MO_16:
4956 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
4957 tcg_gen_ext16u_tl(s->T0, s->T0);
4958 tcg_gen_ext16u_tl(s->T1, s->T1);
4959 /* XXX: use 32 bit mul which could be faster */
4960 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4961 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4962 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4963 tcg_gen_shri_tl(s->T0, s->T0, 16);
4964 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
4965 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4966 set_cc_op(s, CC_OP_MULW);
4967 break;
4968 default:
4969 case MO_32:
4970 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4971 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
4972 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
4973 s->tmp2_i32, s->tmp3_i32);
4974 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
4975 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
4976 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4977 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4978 set_cc_op(s, CC_OP_MULL);
4979 break;
4980 #ifdef TARGET_X86_64
4981 case MO_64:
4982 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4983 s->T0, cpu_regs[R_EAX]);
4984 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4985 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4986 set_cc_op(s, CC_OP_MULQ);
4987 break;
4988 #endif
4990 break;
4991 case 5: /* imul */
4992 switch(ot) {
4993 case MO_8:
4994 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4995 tcg_gen_ext8s_tl(s->T0, s->T0);
4996 tcg_gen_ext8s_tl(s->T1, s->T1);
4997 /* XXX: use 32 bit mul which could be faster */
4998 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4999 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5000 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5001 tcg_gen_ext8s_tl(s->tmp0, s->T0);
5002 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5003 set_cc_op(s, CC_OP_MULB);
5004 break;
5005 case MO_16:
5006 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
5007 tcg_gen_ext16s_tl(s->T0, s->T0);
5008 tcg_gen_ext16s_tl(s->T1, s->T1);
5009 /* XXX: use 32 bit mul which could be faster */
5010 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5011 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5012 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5013 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5014 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5015 tcg_gen_shri_tl(s->T0, s->T0, 16);
5016 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5017 set_cc_op(s, CC_OP_MULW);
5018 break;
5019 default:
5020 case MO_32:
5021 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5022 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
5023 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5024 s->tmp2_i32, s->tmp3_i32);
5025 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
5026 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
5027 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5028 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5029 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5030 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5031 set_cc_op(s, CC_OP_MULL);
5032 break;
5033 #ifdef TARGET_X86_64
5034 case MO_64:
5035 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5036 s->T0, cpu_regs[R_EAX]);
5037 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5038 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
5039 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
5040 set_cc_op(s, CC_OP_MULQ);
5041 break;
5042 #endif
5044 break;
5045 case 6: /* div */
5046 switch(ot) {
5047 case MO_8:
5048 gen_helper_divb_AL(cpu_env, s->T0);
5049 break;
5050 case MO_16:
5051 gen_helper_divw_AX(cpu_env, s->T0);
5052 break;
5053 default:
5054 case MO_32:
5055 gen_helper_divl_EAX(cpu_env, s->T0);
5056 break;
5057 #ifdef TARGET_X86_64
5058 case MO_64:
5059 gen_helper_divq_EAX(cpu_env, s->T0);
5060 break;
5061 #endif
5063 break;
5064 case 7: /* idiv */
5065 switch(ot) {
5066 case MO_8:
5067 gen_helper_idivb_AL(cpu_env, s->T0);
5068 break;
5069 case MO_16:
5070 gen_helper_idivw_AX(cpu_env, s->T0);
5071 break;
5072 default:
5073 case MO_32:
5074 gen_helper_idivl_EAX(cpu_env, s->T0);
5075 break;
5076 #ifdef TARGET_X86_64
5077 case MO_64:
5078 gen_helper_idivq_EAX(cpu_env, s->T0);
5079 break;
5080 #endif
5082 break;
5083 default:
5084 goto unknown_op;
5086 break;
5088 case 0xfe: /* GRP4 */
5089 case 0xff: /* GRP5 */
5090 ot = mo_b_d(b, dflag);
5092 modrm = x86_ldub_code(env, s);
5093 mod = (modrm >> 6) & 3;
5094 rm = (modrm & 7) | REX_B(s);
5095 op = (modrm >> 3) & 7;
5096 if (op >= 2 && b == 0xfe) {
5097 goto unknown_op;
5099 if (CODE64(s)) {
5100 if (op == 2 || op == 4) {
5101 /* operand size for jumps is 64 bit */
5102 ot = MO_64;
5103 } else if (op == 3 || op == 5) {
5104 ot = dflag != MO_16 ? MO_32 + REX_W(s) : MO_16;
5105 } else if (op == 6) {
5106 /* default push size is 64 bit */
5107 ot = mo_pushpop(s, dflag);
5110 if (mod != 3) {
5111 gen_lea_modrm(env, s, modrm);
5112 if (op >= 2 && op != 3 && op != 5)
5113 gen_op_ld_v(s, ot, s->T0, s->A0);
5114 } else {
5115 gen_op_mov_v_reg(s, ot, s->T0, rm);
5118 switch(op) {
5119 case 0: /* inc Ev */
5120 if (mod != 3)
5121 opreg = OR_TMP0;
5122 else
5123 opreg = rm;
5124 gen_inc(s, ot, opreg, 1);
5125 break;
5126 case 1: /* dec Ev */
5127 if (mod != 3)
5128 opreg = OR_TMP0;
5129 else
5130 opreg = rm;
5131 gen_inc(s, ot, opreg, -1);
5132 break;
5133 case 2: /* call Ev */
5134 /* XXX: optimize if memory (no 'and' is necessary) */
5135 if (dflag == MO_16) {
5136 tcg_gen_ext16u_tl(s->T0, s->T0);
5138 next_eip = s->pc - s->cs_base;
5139 tcg_gen_movi_tl(s->T1, next_eip);
5140 gen_push_v(s, s->T1);
5141 gen_op_jmp_v(s->T0);
5142 gen_bnd_jmp(s);
5143 gen_jr(s, s->T0);
5144 break;
5145 case 3: /* lcall Ev */
5146 if (mod == 3) {
5147 goto illegal_op;
5149 gen_op_ld_v(s, ot, s->T1, s->A0);
5150 gen_add_A0_im(s, 1 << ot);
5151 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5152 do_lcall:
5153 if (PE(s) && !VM86(s)) {
5154 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5155 gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
5156 tcg_const_i32(dflag - 1),
5157 tcg_const_tl(s->pc - s->cs_base));
5158 } else {
5159 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5160 gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1,
5161 tcg_const_i32(dflag - 1),
5162 tcg_const_i32(s->pc - s->cs_base));
5164 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5165 gen_jr(s, s->tmp4);
5166 break;
5167 case 4: /* jmp Ev */
5168 if (dflag == MO_16) {
5169 tcg_gen_ext16u_tl(s->T0, s->T0);
5171 gen_op_jmp_v(s->T0);
5172 gen_bnd_jmp(s);
5173 gen_jr(s, s->T0);
5174 break;
5175 case 5: /* ljmp Ev */
5176 if (mod == 3) {
5177 goto illegal_op;
5179 gen_op_ld_v(s, ot, s->T1, s->A0);
5180 gen_add_A0_im(s, 1 << ot);
5181 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5182 do_ljmp:
5183 if (PE(s) && !VM86(s)) {
5184 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5185 gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1,
5186 tcg_const_tl(s->pc - s->cs_base));
5187 } else {
5188 gen_op_movl_seg_T0_vm(s, R_CS);
5189 gen_op_jmp_v(s->T1);
5191 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5192 gen_jr(s, s->tmp4);
5193 break;
5194 case 6: /* push Ev */
5195 gen_push_v(s, s->T0);
5196 break;
5197 default:
5198 goto unknown_op;
5200 break;
5202 case 0x84: /* test Ev, Gv */
5203 case 0x85:
5204 ot = mo_b_d(b, dflag);
5206 modrm = x86_ldub_code(env, s);
5207 reg = ((modrm >> 3) & 7) | REX_R(s);
5209 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5210 gen_op_mov_v_reg(s, ot, s->T1, reg);
5211 gen_op_testl_T0_T1_cc(s);
5212 set_cc_op(s, CC_OP_LOGICB + ot);
5213 break;
5215 case 0xa8: /* test eAX, Iv */
5216 case 0xa9:
5217 ot = mo_b_d(b, dflag);
5218 val = insn_get(env, s, ot);
5220 gen_op_mov_v_reg(s, ot, s->T0, OR_EAX);
5221 tcg_gen_movi_tl(s->T1, val);
5222 gen_op_testl_T0_T1_cc(s);
5223 set_cc_op(s, CC_OP_LOGICB + ot);
5224 break;
5226 case 0x98: /* CWDE/CBW */
5227 switch (dflag) {
5228 #ifdef TARGET_X86_64
5229 case MO_64:
5230 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5231 tcg_gen_ext32s_tl(s->T0, s->T0);
5232 gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0);
5233 break;
5234 #endif
5235 case MO_32:
5236 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5237 tcg_gen_ext16s_tl(s->T0, s->T0);
5238 gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0);
5239 break;
5240 case MO_16:
5241 gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX);
5242 tcg_gen_ext8s_tl(s->T0, s->T0);
5243 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5244 break;
5245 default:
5246 tcg_abort();
5248 break;
5249 case 0x99: /* CDQ/CWD */
5250 switch (dflag) {
5251 #ifdef TARGET_X86_64
5252 case MO_64:
5253 gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX);
5254 tcg_gen_sari_tl(s->T0, s->T0, 63);
5255 gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0);
5256 break;
5257 #endif
5258 case MO_32:
5259 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5260 tcg_gen_ext32s_tl(s->T0, s->T0);
5261 tcg_gen_sari_tl(s->T0, s->T0, 31);
5262 gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0);
5263 break;
5264 case MO_16:
5265 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5266 tcg_gen_ext16s_tl(s->T0, s->T0);
5267 tcg_gen_sari_tl(s->T0, s->T0, 15);
5268 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5269 break;
5270 default:
5271 tcg_abort();
5273 break;
5274 case 0x1af: /* imul Gv, Ev */
5275 case 0x69: /* imul Gv, Ev, I */
5276 case 0x6b:
5277 ot = dflag;
5278 modrm = x86_ldub_code(env, s);
5279 reg = ((modrm >> 3) & 7) | REX_R(s);
5280 if (b == 0x69)
5281 s->rip_offset = insn_const_size(ot);
5282 else if (b == 0x6b)
5283 s->rip_offset = 1;
5284 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5285 if (b == 0x69) {
5286 val = insn_get(env, s, ot);
5287 tcg_gen_movi_tl(s->T1, val);
5288 } else if (b == 0x6b) {
5289 val = (int8_t)insn_get(env, s, MO_8);
5290 tcg_gen_movi_tl(s->T1, val);
5291 } else {
5292 gen_op_mov_v_reg(s, ot, s->T1, reg);
5294 switch (ot) {
5295 #ifdef TARGET_X86_64
5296 case MO_64:
5297 tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1);
5298 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5299 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5300 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1);
5301 break;
5302 #endif
5303 case MO_32:
5304 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5305 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
5306 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5307 s->tmp2_i32, s->tmp3_i32);
5308 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
5309 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5310 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5311 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5312 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5313 break;
5314 default:
5315 tcg_gen_ext16s_tl(s->T0, s->T0);
5316 tcg_gen_ext16s_tl(s->T1, s->T1);
5317 /* XXX: use 32 bit mul which could be faster */
5318 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5319 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5320 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5321 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5322 gen_op_mov_reg_v(s, ot, reg, s->T0);
5323 break;
5325 set_cc_op(s, CC_OP_MULB + ot);
5326 break;
5327 case 0x1c0:
5328 case 0x1c1: /* xadd Ev, Gv */
5329 ot = mo_b_d(b, dflag);
5330 modrm = x86_ldub_code(env, s);
5331 reg = ((modrm >> 3) & 7) | REX_R(s);
5332 mod = (modrm >> 6) & 3;
5333 gen_op_mov_v_reg(s, ot, s->T0, reg);
5334 if (mod == 3) {
5335 rm = (modrm & 7) | REX_B(s);
5336 gen_op_mov_v_reg(s, ot, s->T1, rm);
5337 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5338 gen_op_mov_reg_v(s, ot, reg, s->T1);
5339 gen_op_mov_reg_v(s, ot, rm, s->T0);
5340 } else {
5341 gen_lea_modrm(env, s, modrm);
5342 if (s->prefix & PREFIX_LOCK) {
5343 tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0,
5344 s->mem_index, ot | MO_LE);
5345 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5346 } else {
5347 gen_op_ld_v(s, ot, s->T1, s->A0);
5348 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5349 gen_op_st_v(s, ot, s->T0, s->A0);
5351 gen_op_mov_reg_v(s, ot, reg, s->T1);
5353 gen_op_update2_cc(s);
5354 set_cc_op(s, CC_OP_ADDB + ot);
5355 break;
5356 case 0x1b0:
5357 case 0x1b1: /* cmpxchg Ev, Gv */
5359 TCGv oldv, newv, cmpv;
5361 ot = mo_b_d(b, dflag);
5362 modrm = x86_ldub_code(env, s);
5363 reg = ((modrm >> 3) & 7) | REX_R(s);
5364 mod = (modrm >> 6) & 3;
5365 oldv = tcg_temp_new();
5366 newv = tcg_temp_new();
5367 cmpv = tcg_temp_new();
5368 gen_op_mov_v_reg(s, ot, newv, reg);
5369 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5371 if (s->prefix & PREFIX_LOCK) {
5372 if (mod == 3) {
5373 goto illegal_op;
5375 gen_lea_modrm(env, s, modrm);
5376 tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
5377 s->mem_index, ot | MO_LE);
5378 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5379 } else {
5380 if (mod == 3) {
5381 rm = (modrm & 7) | REX_B(s);
5382 gen_op_mov_v_reg(s, ot, oldv, rm);
5383 } else {
5384 gen_lea_modrm(env, s, modrm);
5385 gen_op_ld_v(s, ot, oldv, s->A0);
5386 rm = 0; /* avoid warning */
5388 gen_extu(ot, oldv);
5389 gen_extu(ot, cmpv);
5390 /* store value = (old == cmp ? new : old); */
5391 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5392 if (mod == 3) {
5393 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5394 gen_op_mov_reg_v(s, ot, rm, newv);
5395 } else {
5396 /* Perform an unconditional store cycle like physical cpu;
5397 must be before changing accumulator to ensure
5398 idempotency if the store faults and the instruction
5399 is restarted */
5400 gen_op_st_v(s, ot, newv, s->A0);
5401 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5404 tcg_gen_mov_tl(cpu_cc_src, oldv);
5405 tcg_gen_mov_tl(s->cc_srcT, cmpv);
5406 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5407 set_cc_op(s, CC_OP_SUBB + ot);
5408 tcg_temp_free(oldv);
5409 tcg_temp_free(newv);
5410 tcg_temp_free(cmpv);
5412 break;
5413 case 0x1c7: /* cmpxchg8b */
5414 modrm = x86_ldub_code(env, s);
5415 mod = (modrm >> 6) & 3;
5416 switch ((modrm >> 3) & 7) {
5417 case 1: /* CMPXCHG8, CMPXCHG16 */
5418 if (mod == 3) {
5419 goto illegal_op;
5421 #ifdef TARGET_X86_64
5422 if (dflag == MO_64) {
5423 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) {
5424 goto illegal_op;
5426 gen_lea_modrm(env, s, modrm);
5427 if ((s->prefix & PREFIX_LOCK) &&
5428 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5429 gen_helper_cmpxchg16b(cpu_env, s->A0);
5430 } else {
5431 gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0);
5433 set_cc_op(s, CC_OP_EFLAGS);
5434 break;
5436 #endif
5437 if (!(s->cpuid_features & CPUID_CX8)) {
5438 goto illegal_op;
5440 gen_lea_modrm(env, s, modrm);
5441 if ((s->prefix & PREFIX_LOCK) &&
5442 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5443 gen_helper_cmpxchg8b(cpu_env, s->A0);
5444 } else {
5445 gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0);
5447 set_cc_op(s, CC_OP_EFLAGS);
5448 break;
5450 case 7: /* RDSEED */
5451 case 6: /* RDRAND */
5452 if (mod != 3 ||
5453 (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
5454 !(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
5455 goto illegal_op;
5457 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5458 gen_io_start();
5460 gen_helper_rdrand(s->T0, cpu_env);
5461 rm = (modrm & 7) | REX_B(s);
5462 gen_op_mov_reg_v(s, dflag, rm, s->T0);
5463 set_cc_op(s, CC_OP_EFLAGS);
5464 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5465 gen_jmp(s, s->pc - s->cs_base);
5467 break;
5469 default:
5470 goto illegal_op;
5472 break;
5474 /**************************/
5475 /* push/pop */
5476 case 0x50 ... 0x57: /* push */
5477 gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s));
5478 gen_push_v(s, s->T0);
5479 break;
5480 case 0x58 ... 0x5f: /* pop */
5481 ot = gen_pop_T0(s);
5482 /* NOTE: order is important for pop %sp */
5483 gen_pop_update(s, ot);
5484 gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0);
5485 break;
5486 case 0x60: /* pusha */
5487 if (CODE64(s))
5488 goto illegal_op;
5489 gen_pusha(s);
5490 break;
5491 case 0x61: /* popa */
5492 if (CODE64(s))
5493 goto illegal_op;
5494 gen_popa(s);
5495 break;
5496 case 0x68: /* push Iv */
5497 case 0x6a:
5498 ot = mo_pushpop(s, dflag);
5499 if (b == 0x68)
5500 val = insn_get(env, s, ot);
5501 else
5502 val = (int8_t)insn_get(env, s, MO_8);
5503 tcg_gen_movi_tl(s->T0, val);
5504 gen_push_v(s, s->T0);
5505 break;
5506 case 0x8f: /* pop Ev */
5507 modrm = x86_ldub_code(env, s);
5508 mod = (modrm >> 6) & 3;
5509 ot = gen_pop_T0(s);
5510 if (mod == 3) {
5511 /* NOTE: order is important for pop %sp */
5512 gen_pop_update(s, ot);
5513 rm = (modrm & 7) | REX_B(s);
5514 gen_op_mov_reg_v(s, ot, rm, s->T0);
5515 } else {
5516 /* NOTE: order is important too for MMU exceptions */
5517 s->popl_esp_hack = 1 << ot;
5518 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5519 s->popl_esp_hack = 0;
5520 gen_pop_update(s, ot);
5522 break;
5523 case 0xc8: /* enter */
5525 int level;
5526 val = x86_lduw_code(env, s);
5527 level = x86_ldub_code(env, s);
5528 gen_enter(s, val, level);
5530 break;
5531 case 0xc9: /* leave */
5532 gen_leave(s);
5533 break;
5534 case 0x06: /* push es */
5535 case 0x0e: /* push cs */
5536 case 0x16: /* push ss */
5537 case 0x1e: /* push ds */
5538 if (CODE64(s))
5539 goto illegal_op;
5540 gen_op_movl_T0_seg(s, b >> 3);
5541 gen_push_v(s, s->T0);
5542 break;
5543 case 0x1a0: /* push fs */
5544 case 0x1a8: /* push gs */
5545 gen_op_movl_T0_seg(s, (b >> 3) & 7);
5546 gen_push_v(s, s->T0);
5547 break;
5548 case 0x07: /* pop es */
5549 case 0x17: /* pop ss */
5550 case 0x1f: /* pop ds */
5551 if (CODE64(s))
5552 goto illegal_op;
5553 reg = b >> 3;
5554 ot = gen_pop_T0(s);
5555 gen_movl_seg_T0(s, reg);
5556 gen_pop_update(s, ot);
5557 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5558 if (s->base.is_jmp) {
5559 gen_jmp_im(s, s->pc - s->cs_base);
5560 if (reg == R_SS) {
5561 s->flags &= ~HF_TF_MASK;
5562 gen_eob_inhibit_irq(s, true);
5563 } else {
5564 gen_eob(s);
5567 break;
5568 case 0x1a1: /* pop fs */
5569 case 0x1a9: /* pop gs */
5570 ot = gen_pop_T0(s);
5571 gen_movl_seg_T0(s, (b >> 3) & 7);
5572 gen_pop_update(s, ot);
5573 if (s->base.is_jmp) {
5574 gen_jmp_im(s, s->pc - s->cs_base);
5575 gen_eob(s);
5577 break;
5579 /**************************/
5580 /* mov */
5581 case 0x88:
5582 case 0x89: /* mov Gv, Ev */
5583 ot = mo_b_d(b, dflag);
5584 modrm = x86_ldub_code(env, s);
5585 reg = ((modrm >> 3) & 7) | REX_R(s);
5587 /* generate a generic store */
5588 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5589 break;
5590 case 0xc6:
5591 case 0xc7: /* mov Ev, Iv */
5592 ot = mo_b_d(b, dflag);
5593 modrm = x86_ldub_code(env, s);
5594 mod = (modrm >> 6) & 3;
5595 if (mod != 3) {
5596 s->rip_offset = insn_const_size(ot);
5597 gen_lea_modrm(env, s, modrm);
5599 val = insn_get(env, s, ot);
5600 tcg_gen_movi_tl(s->T0, val);
5601 if (mod != 3) {
5602 gen_op_st_v(s, ot, s->T0, s->A0);
5603 } else {
5604 gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0);
5606 break;
5607 case 0x8a:
5608 case 0x8b: /* mov Ev, Gv */
5609 ot = mo_b_d(b, dflag);
5610 modrm = x86_ldub_code(env, s);
5611 reg = ((modrm >> 3) & 7) | REX_R(s);
5613 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5614 gen_op_mov_reg_v(s, ot, reg, s->T0);
5615 break;
5616 case 0x8e: /* mov seg, Gv */
5617 modrm = x86_ldub_code(env, s);
5618 reg = (modrm >> 3) & 7;
5619 if (reg >= 6 || reg == R_CS)
5620 goto illegal_op;
5621 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5622 gen_movl_seg_T0(s, reg);
5623 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5624 if (s->base.is_jmp) {
5625 gen_jmp_im(s, s->pc - s->cs_base);
5626 if (reg == R_SS) {
5627 s->flags &= ~HF_TF_MASK;
5628 gen_eob_inhibit_irq(s, true);
5629 } else {
5630 gen_eob(s);
5633 break;
5634 case 0x8c: /* mov Gv, seg */
5635 modrm = x86_ldub_code(env, s);
5636 reg = (modrm >> 3) & 7;
5637 mod = (modrm >> 6) & 3;
5638 if (reg >= 6)
5639 goto illegal_op;
5640 gen_op_movl_T0_seg(s, reg);
5641 ot = mod == 3 ? dflag : MO_16;
5642 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5643 break;
5645 case 0x1b6: /* movzbS Gv, Eb */
5646 case 0x1b7: /* movzwS Gv, Eb */
5647 case 0x1be: /* movsbS Gv, Eb */
5648 case 0x1bf: /* movswS Gv, Eb */
5650 MemOp d_ot;
5651 MemOp s_ot;
5653 /* d_ot is the size of destination */
5654 d_ot = dflag;
5655 /* ot is the size of source */
5656 ot = (b & 1) + MO_8;
5657 /* s_ot is the sign+size of source */
5658 s_ot = b & 8 ? MO_SIGN | ot : ot;
5660 modrm = x86_ldub_code(env, s);
5661 reg = ((modrm >> 3) & 7) | REX_R(s);
5662 mod = (modrm >> 6) & 3;
5663 rm = (modrm & 7) | REX_B(s);
5665 if (mod == 3) {
5666 if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) {
5667 tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8);
5668 } else {
5669 gen_op_mov_v_reg(s, ot, s->T0, rm);
5670 switch (s_ot) {
5671 case MO_UB:
5672 tcg_gen_ext8u_tl(s->T0, s->T0);
5673 break;
5674 case MO_SB:
5675 tcg_gen_ext8s_tl(s->T0, s->T0);
5676 break;
5677 case MO_UW:
5678 tcg_gen_ext16u_tl(s->T0, s->T0);
5679 break;
5680 default:
5681 case MO_SW:
5682 tcg_gen_ext16s_tl(s->T0, s->T0);
5683 break;
5686 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5687 } else {
5688 gen_lea_modrm(env, s, modrm);
5689 gen_op_ld_v(s, s_ot, s->T0, s->A0);
5690 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5693 break;
5695 case 0x8d: /* lea */
5696 modrm = x86_ldub_code(env, s);
5697 mod = (modrm >> 6) & 3;
5698 if (mod == 3)
5699 goto illegal_op;
5700 reg = ((modrm >> 3) & 7) | REX_R(s);
5702 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5703 TCGv ea = gen_lea_modrm_1(s, a);
5704 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5705 gen_op_mov_reg_v(s, dflag, reg, s->A0);
5707 break;
5709 case 0xa0: /* mov EAX, Ov */
5710 case 0xa1:
5711 case 0xa2: /* mov Ov, EAX */
5712 case 0xa3:
5714 target_ulong offset_addr;
5716 ot = mo_b_d(b, dflag);
5717 switch (s->aflag) {
5718 #ifdef TARGET_X86_64
5719 case MO_64:
5720 offset_addr = x86_ldq_code(env, s);
5721 break;
5722 #endif
5723 default:
5724 offset_addr = insn_get(env, s, s->aflag);
5725 break;
5727 tcg_gen_movi_tl(s->A0, offset_addr);
5728 gen_add_A0_ds_seg(s);
5729 if ((b & 2) == 0) {
5730 gen_op_ld_v(s, ot, s->T0, s->A0);
5731 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
5732 } else {
5733 gen_op_mov_v_reg(s, ot, s->T0, R_EAX);
5734 gen_op_st_v(s, ot, s->T0, s->A0);
5737 break;
5738 case 0xd7: /* xlat */
5739 tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]);
5740 tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]);
5741 tcg_gen_add_tl(s->A0, s->A0, s->T0);
5742 gen_extu(s->aflag, s->A0);
5743 gen_add_A0_ds_seg(s);
5744 gen_op_ld_v(s, MO_8, s->T0, s->A0);
5745 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
5746 break;
5747 case 0xb0 ... 0xb7: /* mov R, Ib */
5748 val = insn_get(env, s, MO_8);
5749 tcg_gen_movi_tl(s->T0, val);
5750 gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0);
5751 break;
5752 case 0xb8 ... 0xbf: /* mov R, Iv */
5753 #ifdef TARGET_X86_64
5754 if (dflag == MO_64) {
5755 uint64_t tmp;
5756 /* 64 bit case */
5757 tmp = x86_ldq_code(env, s);
5758 reg = (b & 7) | REX_B(s);
5759 tcg_gen_movi_tl(s->T0, tmp);
5760 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
5761 } else
5762 #endif
5764 ot = dflag;
5765 val = insn_get(env, s, ot);
5766 reg = (b & 7) | REX_B(s);
5767 tcg_gen_movi_tl(s->T0, val);
5768 gen_op_mov_reg_v(s, ot, reg, s->T0);
5770 break;
5772 case 0x91 ... 0x97: /* xchg R, EAX */
5773 do_xchg_reg_eax:
5774 ot = dflag;
5775 reg = (b & 7) | REX_B(s);
5776 rm = R_EAX;
5777 goto do_xchg_reg;
5778 case 0x86:
5779 case 0x87: /* xchg Ev, Gv */
5780 ot = mo_b_d(b, dflag);
5781 modrm = x86_ldub_code(env, s);
5782 reg = ((modrm >> 3) & 7) | REX_R(s);
5783 mod = (modrm >> 6) & 3;
5784 if (mod == 3) {
5785 rm = (modrm & 7) | REX_B(s);
5786 do_xchg_reg:
5787 gen_op_mov_v_reg(s, ot, s->T0, reg);
5788 gen_op_mov_v_reg(s, ot, s->T1, rm);
5789 gen_op_mov_reg_v(s, ot, rm, s->T0);
5790 gen_op_mov_reg_v(s, ot, reg, s->T1);
5791 } else {
5792 gen_lea_modrm(env, s, modrm);
5793 gen_op_mov_v_reg(s, ot, s->T0, reg);
5794 /* for xchg, lock is implicit */
5795 tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0,
5796 s->mem_index, ot | MO_LE);
5797 gen_op_mov_reg_v(s, ot, reg, s->T1);
5799 break;
5800 case 0xc4: /* les Gv */
5801 /* In CODE64 this is VEX3; see above. */
5802 op = R_ES;
5803 goto do_lxx;
5804 case 0xc5: /* lds Gv */
5805 /* In CODE64 this is VEX2; see above. */
5806 op = R_DS;
5807 goto do_lxx;
5808 case 0x1b2: /* lss Gv */
5809 op = R_SS;
5810 goto do_lxx;
5811 case 0x1b4: /* lfs Gv */
5812 op = R_FS;
5813 goto do_lxx;
5814 case 0x1b5: /* lgs Gv */
5815 op = R_GS;
5816 do_lxx:
5817 ot = dflag != MO_16 ? MO_32 : MO_16;
5818 modrm = x86_ldub_code(env, s);
5819 reg = ((modrm >> 3) & 7) | REX_R(s);
5820 mod = (modrm >> 6) & 3;
5821 if (mod == 3)
5822 goto illegal_op;
5823 gen_lea_modrm(env, s, modrm);
5824 gen_op_ld_v(s, ot, s->T1, s->A0);
5825 gen_add_A0_im(s, 1 << ot);
5826 /* load the segment first to handle exceptions properly */
5827 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5828 gen_movl_seg_T0(s, op);
5829 /* then put the data */
5830 gen_op_mov_reg_v(s, ot, reg, s->T1);
5831 if (s->base.is_jmp) {
5832 gen_jmp_im(s, s->pc - s->cs_base);
5833 gen_eob(s);
5835 break;
5837 /************************/
5838 /* shifts */
5839 case 0xc0:
5840 case 0xc1:
5841 /* shift Ev,Ib */
5842 shift = 2;
5843 grp2:
5845 ot = mo_b_d(b, dflag);
5846 modrm = x86_ldub_code(env, s);
5847 mod = (modrm >> 6) & 3;
5848 op = (modrm >> 3) & 7;
5850 if (mod != 3) {
5851 if (shift == 2) {
5852 s->rip_offset = 1;
5854 gen_lea_modrm(env, s, modrm);
5855 opreg = OR_TMP0;
5856 } else {
5857 opreg = (modrm & 7) | REX_B(s);
5860 /* simpler op */
5861 if (shift == 0) {
5862 gen_shift(s, op, ot, opreg, OR_ECX);
5863 } else {
5864 if (shift == 2) {
5865 shift = x86_ldub_code(env, s);
5867 gen_shifti(s, op, ot, opreg, shift);
5870 break;
5871 case 0xd0:
5872 case 0xd1:
5873 /* shift Ev,1 */
5874 shift = 1;
5875 goto grp2;
5876 case 0xd2:
5877 case 0xd3:
5878 /* shift Ev,cl */
5879 shift = 0;
5880 goto grp2;
5882 case 0x1a4: /* shld imm */
5883 op = 0;
5884 shift = 1;
5885 goto do_shiftd;
5886 case 0x1a5: /* shld cl */
5887 op = 0;
5888 shift = 0;
5889 goto do_shiftd;
5890 case 0x1ac: /* shrd imm */
5891 op = 1;
5892 shift = 1;
5893 goto do_shiftd;
5894 case 0x1ad: /* shrd cl */
5895 op = 1;
5896 shift = 0;
5897 do_shiftd:
5898 ot = dflag;
5899 modrm = x86_ldub_code(env, s);
5900 mod = (modrm >> 6) & 3;
5901 rm = (modrm & 7) | REX_B(s);
5902 reg = ((modrm >> 3) & 7) | REX_R(s);
5903 if (mod != 3) {
5904 gen_lea_modrm(env, s, modrm);
5905 opreg = OR_TMP0;
5906 } else {
5907 opreg = rm;
5909 gen_op_mov_v_reg(s, ot, s->T1, reg);
5911 if (shift) {
5912 TCGv imm = tcg_const_tl(x86_ldub_code(env, s));
5913 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5914 tcg_temp_free(imm);
5915 } else {
5916 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5918 break;
5920 /************************/
5921 /* floats */
5922 case 0xd8 ... 0xdf:
5923 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5924 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5925 /* XXX: what to do if illegal op ? */
5926 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5927 break;
5929 modrm = x86_ldub_code(env, s);
5930 mod = (modrm >> 6) & 3;
5931 rm = modrm & 7;
5932 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5933 if (mod != 3) {
5934 /* memory op */
5935 gen_lea_modrm(env, s, modrm);
5936 switch(op) {
5937 case 0x00 ... 0x07: /* fxxxs */
5938 case 0x10 ... 0x17: /* fixxxl */
5939 case 0x20 ... 0x27: /* fxxxl */
5940 case 0x30 ... 0x37: /* fixxx */
5942 int op1;
5943 op1 = op & 7;
5945 switch(op >> 4) {
5946 case 0:
5947 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5948 s->mem_index, MO_LEUL);
5949 gen_helper_flds_FT0(cpu_env, s->tmp2_i32);
5950 break;
5951 case 1:
5952 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5953 s->mem_index, MO_LEUL);
5954 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5955 break;
5956 case 2:
5957 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5958 s->mem_index, MO_LEQ);
5959 gen_helper_fldl_FT0(cpu_env, s->tmp1_i64);
5960 break;
5961 case 3:
5962 default:
5963 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5964 s->mem_index, MO_LESW);
5965 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5966 break;
5969 gen_helper_fp_arith_ST0_FT0(op1);
5970 if (op1 == 3) {
5971 /* fcomp needs pop */
5972 gen_helper_fpop(cpu_env);
5975 break;
5976 case 0x08: /* flds */
5977 case 0x0a: /* fsts */
5978 case 0x0b: /* fstps */
5979 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5980 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5981 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5982 switch(op & 7) {
5983 case 0:
5984 switch(op >> 4) {
5985 case 0:
5986 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5987 s->mem_index, MO_LEUL);
5988 gen_helper_flds_ST0(cpu_env, s->tmp2_i32);
5989 break;
5990 case 1:
5991 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5992 s->mem_index, MO_LEUL);
5993 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
5994 break;
5995 case 2:
5996 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5997 s->mem_index, MO_LEQ);
5998 gen_helper_fldl_ST0(cpu_env, s->tmp1_i64);
5999 break;
6000 case 3:
6001 default:
6002 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6003 s->mem_index, MO_LESW);
6004 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
6005 break;
6007 break;
6008 case 1:
6009 /* XXX: the corresponding CPUID bit must be tested ! */
6010 switch(op >> 4) {
6011 case 1:
6012 gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env);
6013 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6014 s->mem_index, MO_LEUL);
6015 break;
6016 case 2:
6017 gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env);
6018 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6019 s->mem_index, MO_LEQ);
6020 break;
6021 case 3:
6022 default:
6023 gen_helper_fistt_ST0(s->tmp2_i32, cpu_env);
6024 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6025 s->mem_index, MO_LEUW);
6026 break;
6028 gen_helper_fpop(cpu_env);
6029 break;
6030 default:
6031 switch(op >> 4) {
6032 case 0:
6033 gen_helper_fsts_ST0(s->tmp2_i32, cpu_env);
6034 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6035 s->mem_index, MO_LEUL);
6036 break;
6037 case 1:
6038 gen_helper_fistl_ST0(s->tmp2_i32, cpu_env);
6039 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6040 s->mem_index, MO_LEUL);
6041 break;
6042 case 2:
6043 gen_helper_fstl_ST0(s->tmp1_i64, cpu_env);
6044 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6045 s->mem_index, MO_LEQ);
6046 break;
6047 case 3:
6048 default:
6049 gen_helper_fist_ST0(s->tmp2_i32, cpu_env);
6050 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6051 s->mem_index, MO_LEUW);
6052 break;
6054 if ((op & 7) == 3)
6055 gen_helper_fpop(cpu_env);
6056 break;
6058 break;
6059 case 0x0c: /* fldenv mem */
6060 gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6061 break;
6062 case 0x0d: /* fldcw mem */
6063 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6064 s->mem_index, MO_LEUW);
6065 gen_helper_fldcw(cpu_env, s->tmp2_i32);
6066 break;
6067 case 0x0e: /* fnstenv mem */
6068 gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6069 break;
6070 case 0x0f: /* fnstcw mem */
6071 gen_helper_fnstcw(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 0x1d: /* fldt mem */
6076 gen_helper_fldt_ST0(cpu_env, s->A0);
6077 break;
6078 case 0x1f: /* fstpt mem */
6079 gen_helper_fstt_ST0(cpu_env, s->A0);
6080 gen_helper_fpop(cpu_env);
6081 break;
6082 case 0x2c: /* frstor mem */
6083 gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6084 break;
6085 case 0x2e: /* fnsave mem */
6086 gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6087 break;
6088 case 0x2f: /* fnstsw mem */
6089 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6090 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6091 s->mem_index, MO_LEUW);
6092 break;
6093 case 0x3c: /* fbld */
6094 gen_helper_fbld_ST0(cpu_env, s->A0);
6095 break;
6096 case 0x3e: /* fbstp */
6097 gen_helper_fbst_ST0(cpu_env, s->A0);
6098 gen_helper_fpop(cpu_env);
6099 break;
6100 case 0x3d: /* fildll */
6101 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6102 gen_helper_fildll_ST0(cpu_env, s->tmp1_i64);
6103 break;
6104 case 0x3f: /* fistpll */
6105 gen_helper_fistll_ST0(s->tmp1_i64, cpu_env);
6106 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6107 gen_helper_fpop(cpu_env);
6108 break;
6109 default:
6110 goto unknown_op;
6112 } else {
6113 /* register float ops */
6114 opreg = rm;
6116 switch(op) {
6117 case 0x08: /* fld sti */
6118 gen_helper_fpush(cpu_env);
6119 gen_helper_fmov_ST0_STN(cpu_env,
6120 tcg_const_i32((opreg + 1) & 7));
6121 break;
6122 case 0x09: /* fxchg sti */
6123 case 0x29: /* fxchg4 sti, undocumented op */
6124 case 0x39: /* fxchg7 sti, undocumented op */
6125 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
6126 break;
6127 case 0x0a: /* grp d9/2 */
6128 switch(rm) {
6129 case 0: /* fnop */
6130 /* check exceptions (FreeBSD FPU probe) */
6131 gen_helper_fwait(cpu_env);
6132 break;
6133 default:
6134 goto unknown_op;
6136 break;
6137 case 0x0c: /* grp d9/4 */
6138 switch(rm) {
6139 case 0: /* fchs */
6140 gen_helper_fchs_ST0(cpu_env);
6141 break;
6142 case 1: /* fabs */
6143 gen_helper_fabs_ST0(cpu_env);
6144 break;
6145 case 4: /* ftst */
6146 gen_helper_fldz_FT0(cpu_env);
6147 gen_helper_fcom_ST0_FT0(cpu_env);
6148 break;
6149 case 5: /* fxam */
6150 gen_helper_fxam_ST0(cpu_env);
6151 break;
6152 default:
6153 goto unknown_op;
6155 break;
6156 case 0x0d: /* grp d9/5 */
6158 switch(rm) {
6159 case 0:
6160 gen_helper_fpush(cpu_env);
6161 gen_helper_fld1_ST0(cpu_env);
6162 break;
6163 case 1:
6164 gen_helper_fpush(cpu_env);
6165 gen_helper_fldl2t_ST0(cpu_env);
6166 break;
6167 case 2:
6168 gen_helper_fpush(cpu_env);
6169 gen_helper_fldl2e_ST0(cpu_env);
6170 break;
6171 case 3:
6172 gen_helper_fpush(cpu_env);
6173 gen_helper_fldpi_ST0(cpu_env);
6174 break;
6175 case 4:
6176 gen_helper_fpush(cpu_env);
6177 gen_helper_fldlg2_ST0(cpu_env);
6178 break;
6179 case 5:
6180 gen_helper_fpush(cpu_env);
6181 gen_helper_fldln2_ST0(cpu_env);
6182 break;
6183 case 6:
6184 gen_helper_fpush(cpu_env);
6185 gen_helper_fldz_ST0(cpu_env);
6186 break;
6187 default:
6188 goto unknown_op;
6191 break;
6192 case 0x0e: /* grp d9/6 */
6193 switch(rm) {
6194 case 0: /* f2xm1 */
6195 gen_helper_f2xm1(cpu_env);
6196 break;
6197 case 1: /* fyl2x */
6198 gen_helper_fyl2x(cpu_env);
6199 break;
6200 case 2: /* fptan */
6201 gen_helper_fptan(cpu_env);
6202 break;
6203 case 3: /* fpatan */
6204 gen_helper_fpatan(cpu_env);
6205 break;
6206 case 4: /* fxtract */
6207 gen_helper_fxtract(cpu_env);
6208 break;
6209 case 5: /* fprem1 */
6210 gen_helper_fprem1(cpu_env);
6211 break;
6212 case 6: /* fdecstp */
6213 gen_helper_fdecstp(cpu_env);
6214 break;
6215 default:
6216 case 7: /* fincstp */
6217 gen_helper_fincstp(cpu_env);
6218 break;
6220 break;
6221 case 0x0f: /* grp d9/7 */
6222 switch(rm) {
6223 case 0: /* fprem */
6224 gen_helper_fprem(cpu_env);
6225 break;
6226 case 1: /* fyl2xp1 */
6227 gen_helper_fyl2xp1(cpu_env);
6228 break;
6229 case 2: /* fsqrt */
6230 gen_helper_fsqrt(cpu_env);
6231 break;
6232 case 3: /* fsincos */
6233 gen_helper_fsincos(cpu_env);
6234 break;
6235 case 5: /* fscale */
6236 gen_helper_fscale(cpu_env);
6237 break;
6238 case 4: /* frndint */
6239 gen_helper_frndint(cpu_env);
6240 break;
6241 case 6: /* fsin */
6242 gen_helper_fsin(cpu_env);
6243 break;
6244 default:
6245 case 7: /* fcos */
6246 gen_helper_fcos(cpu_env);
6247 break;
6249 break;
6250 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6251 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6252 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6254 int op1;
6256 op1 = op & 7;
6257 if (op >= 0x20) {
6258 gen_helper_fp_arith_STN_ST0(op1, opreg);
6259 if (op >= 0x30)
6260 gen_helper_fpop(cpu_env);
6261 } else {
6262 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6263 gen_helper_fp_arith_ST0_FT0(op1);
6266 break;
6267 case 0x02: /* fcom */
6268 case 0x22: /* fcom2, undocumented op */
6269 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6270 gen_helper_fcom_ST0_FT0(cpu_env);
6271 break;
6272 case 0x03: /* fcomp */
6273 case 0x23: /* fcomp3, undocumented op */
6274 case 0x32: /* fcomp5, undocumented op */
6275 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6276 gen_helper_fcom_ST0_FT0(cpu_env);
6277 gen_helper_fpop(cpu_env);
6278 break;
6279 case 0x15: /* da/5 */
6280 switch(rm) {
6281 case 1: /* fucompp */
6282 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6283 gen_helper_fucom_ST0_FT0(cpu_env);
6284 gen_helper_fpop(cpu_env);
6285 gen_helper_fpop(cpu_env);
6286 break;
6287 default:
6288 goto unknown_op;
6290 break;
6291 case 0x1c:
6292 switch(rm) {
6293 case 0: /* feni (287 only, just do nop here) */
6294 break;
6295 case 1: /* fdisi (287 only, just do nop here) */
6296 break;
6297 case 2: /* fclex */
6298 gen_helper_fclex(cpu_env);
6299 break;
6300 case 3: /* fninit */
6301 gen_helper_fninit(cpu_env);
6302 break;
6303 case 4: /* fsetpm (287 only, just do nop here) */
6304 break;
6305 default:
6306 goto unknown_op;
6308 break;
6309 case 0x1d: /* fucomi */
6310 if (!(s->cpuid_features & CPUID_CMOV)) {
6311 goto illegal_op;
6313 gen_update_cc_op(s);
6314 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6315 gen_helper_fucomi_ST0_FT0(cpu_env);
6316 set_cc_op(s, CC_OP_EFLAGS);
6317 break;
6318 case 0x1e: /* fcomi */
6319 if (!(s->cpuid_features & CPUID_CMOV)) {
6320 goto illegal_op;
6322 gen_update_cc_op(s);
6323 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6324 gen_helper_fcomi_ST0_FT0(cpu_env);
6325 set_cc_op(s, CC_OP_EFLAGS);
6326 break;
6327 case 0x28: /* ffree sti */
6328 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6329 break;
6330 case 0x2a: /* fst sti */
6331 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6332 break;
6333 case 0x2b: /* fstp sti */
6334 case 0x0b: /* fstp1 sti, undocumented op */
6335 case 0x3a: /* fstp8 sti, undocumented op */
6336 case 0x3b: /* fstp9 sti, undocumented op */
6337 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6338 gen_helper_fpop(cpu_env);
6339 break;
6340 case 0x2c: /* fucom st(i) */
6341 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6342 gen_helper_fucom_ST0_FT0(cpu_env);
6343 break;
6344 case 0x2d: /* fucomp st(i) */
6345 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6346 gen_helper_fucom_ST0_FT0(cpu_env);
6347 gen_helper_fpop(cpu_env);
6348 break;
6349 case 0x33: /* de/3 */
6350 switch(rm) {
6351 case 1: /* fcompp */
6352 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6353 gen_helper_fcom_ST0_FT0(cpu_env);
6354 gen_helper_fpop(cpu_env);
6355 gen_helper_fpop(cpu_env);
6356 break;
6357 default:
6358 goto unknown_op;
6360 break;
6361 case 0x38: /* ffreep sti, undocumented op */
6362 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6363 gen_helper_fpop(cpu_env);
6364 break;
6365 case 0x3c: /* df/4 */
6366 switch(rm) {
6367 case 0:
6368 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6369 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
6370 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
6371 break;
6372 default:
6373 goto unknown_op;
6375 break;
6376 case 0x3d: /* fucomip */
6377 if (!(s->cpuid_features & CPUID_CMOV)) {
6378 goto illegal_op;
6380 gen_update_cc_op(s);
6381 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6382 gen_helper_fucomi_ST0_FT0(cpu_env);
6383 gen_helper_fpop(cpu_env);
6384 set_cc_op(s, CC_OP_EFLAGS);
6385 break;
6386 case 0x3e: /* fcomip */
6387 if (!(s->cpuid_features & CPUID_CMOV)) {
6388 goto illegal_op;
6390 gen_update_cc_op(s);
6391 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6392 gen_helper_fcomi_ST0_FT0(cpu_env);
6393 gen_helper_fpop(cpu_env);
6394 set_cc_op(s, CC_OP_EFLAGS);
6395 break;
6396 case 0x10 ... 0x13: /* fcmovxx */
6397 case 0x18 ... 0x1b:
6399 int op1;
6400 TCGLabel *l1;
6401 static const uint8_t fcmov_cc[8] = {
6402 (JCC_B << 1),
6403 (JCC_Z << 1),
6404 (JCC_BE << 1),
6405 (JCC_P << 1),
6408 if (!(s->cpuid_features & CPUID_CMOV)) {
6409 goto illegal_op;
6411 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6412 l1 = gen_new_label();
6413 gen_jcc1_noeob(s, op1, l1);
6414 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6415 gen_set_label(l1);
6417 break;
6418 default:
6419 goto unknown_op;
6422 break;
6423 /************************/
6424 /* string ops */
6426 case 0xa4: /* movsS */
6427 case 0xa5:
6428 ot = mo_b_d(b, dflag);
6429 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6430 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6431 } else {
6432 gen_movs(s, ot);
6434 break;
6436 case 0xaa: /* stosS */
6437 case 0xab:
6438 ot = mo_b_d(b, dflag);
6439 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6440 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6441 } else {
6442 gen_stos(s, ot);
6444 break;
6445 case 0xac: /* lodsS */
6446 case 0xad:
6447 ot = mo_b_d(b, dflag);
6448 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6449 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6450 } else {
6451 gen_lods(s, ot);
6453 break;
6454 case 0xae: /* scasS */
6455 case 0xaf:
6456 ot = mo_b_d(b, dflag);
6457 if (prefixes & PREFIX_REPNZ) {
6458 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6459 } else if (prefixes & PREFIX_REPZ) {
6460 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6461 } else {
6462 gen_scas(s, ot);
6464 break;
6466 case 0xa6: /* cmpsS */
6467 case 0xa7:
6468 ot = mo_b_d(b, dflag);
6469 if (prefixes & PREFIX_REPNZ) {
6470 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6471 } else if (prefixes & PREFIX_REPZ) {
6472 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6473 } else {
6474 gen_cmps(s, ot);
6476 break;
6477 case 0x6c: /* insS */
6478 case 0x6d:
6479 ot = mo_b_d32(b, dflag);
6480 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6481 gen_check_io(s, ot, pc_start - s->cs_base,
6482 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6483 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6484 gen_io_start();
6486 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6487 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6488 /* jump generated by gen_repz_ins */
6489 } else {
6490 gen_ins(s, ot);
6491 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6492 gen_jmp(s, s->pc - s->cs_base);
6495 break;
6496 case 0x6e: /* outsS */
6497 case 0x6f:
6498 ot = mo_b_d32(b, dflag);
6499 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6500 gen_check_io(s, ot, pc_start - s->cs_base,
6501 svm_is_rep(prefixes) | 4);
6502 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6503 gen_io_start();
6505 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6506 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6507 /* jump generated by gen_repz_outs */
6508 } else {
6509 gen_outs(s, ot);
6510 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6511 gen_jmp(s, s->pc - s->cs_base);
6514 break;
6516 /************************/
6517 /* port I/O */
6519 case 0xe4:
6520 case 0xe5:
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_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6526 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6527 gen_io_start();
6529 tcg_gen_movi_i32(s->tmp2_i32, val);
6530 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6531 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6532 gen_bpt_io(s, s->tmp2_i32, ot);
6533 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6534 gen_jmp(s, s->pc - s->cs_base);
6536 break;
6537 case 0xe6:
6538 case 0xe7:
6539 ot = mo_b_d32(b, dflag);
6540 val = x86_ldub_code(env, s);
6541 tcg_gen_movi_tl(s->T0, val);
6542 gen_check_io(s, ot, pc_start - s->cs_base,
6543 svm_is_rep(prefixes));
6544 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6546 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6547 gen_io_start();
6549 tcg_gen_movi_i32(s->tmp2_i32, val);
6550 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6551 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6552 gen_bpt_io(s, s->tmp2_i32, ot);
6553 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6554 gen_jmp(s, s->pc - s->cs_base);
6556 break;
6557 case 0xec:
6558 case 0xed:
6559 ot = mo_b_d32(b, dflag);
6560 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6561 gen_check_io(s, ot, pc_start - s->cs_base,
6562 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6563 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6564 gen_io_start();
6566 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
6567 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6568 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6569 gen_bpt_io(s, s->tmp2_i32, ot);
6570 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6571 gen_jmp(s, s->pc - s->cs_base);
6573 break;
6574 case 0xee:
6575 case 0xef:
6576 ot = mo_b_d32(b, dflag);
6577 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6578 gen_check_io(s, ot, pc_start - s->cs_base,
6579 svm_is_rep(prefixes));
6580 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6582 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6583 gen_io_start();
6585 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
6586 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6587 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6588 gen_bpt_io(s, s->tmp2_i32, ot);
6589 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6590 gen_jmp(s, s->pc - s->cs_base);
6592 break;
6594 /************************/
6595 /* control */
6596 case 0xc2: /* ret im */
6597 val = x86_ldsw_code(env, s);
6598 ot = gen_pop_T0(s);
6599 gen_stack_update(s, val + (1 << ot));
6600 /* Note that gen_pop_T0 uses a zero-extending load. */
6601 gen_op_jmp_v(s->T0);
6602 gen_bnd_jmp(s);
6603 gen_jr(s, s->T0);
6604 break;
6605 case 0xc3: /* ret */
6606 ot = gen_pop_T0(s);
6607 gen_pop_update(s, ot);
6608 /* Note that gen_pop_T0 uses a zero-extending load. */
6609 gen_op_jmp_v(s->T0);
6610 gen_bnd_jmp(s);
6611 gen_jr(s, s->T0);
6612 break;
6613 case 0xca: /* lret im */
6614 val = x86_ldsw_code(env, s);
6615 do_lret:
6616 if (PE(s) && !VM86(s)) {
6617 gen_update_cc_op(s);
6618 gen_jmp_im(s, pc_start - s->cs_base);
6619 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6620 tcg_const_i32(val));
6621 } else {
6622 gen_stack_A0(s);
6623 /* pop offset */
6624 gen_op_ld_v(s, dflag, s->T0, s->A0);
6625 /* NOTE: keeping EIP updated is not a problem in case of
6626 exception */
6627 gen_op_jmp_v(s->T0);
6628 /* pop selector */
6629 gen_add_A0_im(s, 1 << dflag);
6630 gen_op_ld_v(s, dflag, s->T0, s->A0);
6631 gen_op_movl_seg_T0_vm(s, R_CS);
6632 /* add stack offset */
6633 gen_stack_update(s, val + (2 << dflag));
6635 gen_eob(s);
6636 break;
6637 case 0xcb: /* lret */
6638 val = 0;
6639 goto do_lret;
6640 case 0xcf: /* iret */
6641 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6642 if (!PE(s) || VM86(s)) {
6643 /* real mode or vm86 mode */
6644 if (!check_vm86_iopl(s)) {
6645 break;
6647 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6648 } else {
6649 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6650 tcg_const_i32(s->pc - s->cs_base));
6652 set_cc_op(s, CC_OP_EFLAGS);
6653 gen_eob(s);
6654 break;
6655 case 0xe8: /* call im */
6657 if (dflag != MO_16) {
6658 tval = (int32_t)insn_get(env, s, MO_32);
6659 } else {
6660 tval = (int16_t)insn_get(env, s, MO_16);
6662 next_eip = s->pc - s->cs_base;
6663 tval += next_eip;
6664 if (dflag == MO_16) {
6665 tval &= 0xffff;
6666 } else if (!CODE64(s)) {
6667 tval &= 0xffffffff;
6669 tcg_gen_movi_tl(s->T0, next_eip);
6670 gen_push_v(s, s->T0);
6671 gen_bnd_jmp(s);
6672 gen_jmp(s, tval);
6674 break;
6675 case 0x9a: /* lcall im */
6677 unsigned int selector, offset;
6679 if (CODE64(s))
6680 goto illegal_op;
6681 ot = dflag;
6682 offset = insn_get(env, s, ot);
6683 selector = insn_get(env, s, MO_16);
6685 tcg_gen_movi_tl(s->T0, selector);
6686 tcg_gen_movi_tl(s->T1, offset);
6688 goto do_lcall;
6689 case 0xe9: /* jmp im */
6690 if (dflag != MO_16) {
6691 tval = (int32_t)insn_get(env, s, MO_32);
6692 } else {
6693 tval = (int16_t)insn_get(env, s, MO_16);
6695 tval += s->pc - s->cs_base;
6696 if (dflag == MO_16) {
6697 tval &= 0xffff;
6698 } else if (!CODE64(s)) {
6699 tval &= 0xffffffff;
6701 gen_bnd_jmp(s);
6702 gen_jmp(s, tval);
6703 break;
6704 case 0xea: /* ljmp im */
6706 unsigned int selector, offset;
6708 if (CODE64(s))
6709 goto illegal_op;
6710 ot = dflag;
6711 offset = insn_get(env, s, ot);
6712 selector = insn_get(env, s, MO_16);
6714 tcg_gen_movi_tl(s->T0, selector);
6715 tcg_gen_movi_tl(s->T1, offset);
6717 goto do_ljmp;
6718 case 0xeb: /* jmp Jb */
6719 tval = (int8_t)insn_get(env, s, MO_8);
6720 tval += s->pc - s->cs_base;
6721 if (dflag == MO_16) {
6722 tval &= 0xffff;
6724 gen_jmp(s, tval);
6725 break;
6726 case 0x70 ... 0x7f: /* jcc Jb */
6727 tval = (int8_t)insn_get(env, s, MO_8);
6728 goto do_jcc;
6729 case 0x180 ... 0x18f: /* jcc Jv */
6730 if (dflag != MO_16) {
6731 tval = (int32_t)insn_get(env, s, MO_32);
6732 } else {
6733 tval = (int16_t)insn_get(env, s, MO_16);
6735 do_jcc:
6736 next_eip = s->pc - s->cs_base;
6737 tval += next_eip;
6738 if (dflag == MO_16) {
6739 tval &= 0xffff;
6741 gen_bnd_jmp(s);
6742 gen_jcc(s, b, tval, next_eip);
6743 break;
6745 case 0x190 ... 0x19f: /* setcc Gv */
6746 modrm = x86_ldub_code(env, s);
6747 gen_setcc1(s, b, s->T0);
6748 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6749 break;
6750 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6751 if (!(s->cpuid_features & CPUID_CMOV)) {
6752 goto illegal_op;
6754 ot = dflag;
6755 modrm = x86_ldub_code(env, s);
6756 reg = ((modrm >> 3) & 7) | REX_R(s);
6757 gen_cmovcc1(env, s, ot, b, modrm, reg);
6758 break;
6760 /************************/
6761 /* flags */
6762 case 0x9c: /* pushf */
6763 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6764 if (check_vm86_iopl(s)) {
6765 gen_update_cc_op(s);
6766 gen_helper_read_eflags(s->T0, cpu_env);
6767 gen_push_v(s, s->T0);
6769 break;
6770 case 0x9d: /* popf */
6771 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6772 if (check_vm86_iopl(s)) {
6773 ot = gen_pop_T0(s);
6774 if (CPL(s) == 0) {
6775 if (dflag != MO_16) {
6776 gen_helper_write_eflags(cpu_env, s->T0,
6777 tcg_const_i32((TF_MASK | AC_MASK |
6778 ID_MASK | NT_MASK |
6779 IF_MASK |
6780 IOPL_MASK)));
6781 } else {
6782 gen_helper_write_eflags(cpu_env, s->T0,
6783 tcg_const_i32((TF_MASK | AC_MASK |
6784 ID_MASK | NT_MASK |
6785 IF_MASK | IOPL_MASK)
6786 & 0xffff));
6788 } else {
6789 if (CPL(s) <= IOPL(s)) {
6790 if (dflag != MO_16) {
6791 gen_helper_write_eflags(cpu_env, s->T0,
6792 tcg_const_i32((TF_MASK |
6793 AC_MASK |
6794 ID_MASK |
6795 NT_MASK |
6796 IF_MASK)));
6797 } else {
6798 gen_helper_write_eflags(cpu_env, s->T0,
6799 tcg_const_i32((TF_MASK |
6800 AC_MASK |
6801 ID_MASK |
6802 NT_MASK |
6803 IF_MASK)
6804 & 0xffff));
6806 } else {
6807 if (dflag != MO_16) {
6808 gen_helper_write_eflags(cpu_env, s->T0,
6809 tcg_const_i32((TF_MASK | AC_MASK |
6810 ID_MASK | NT_MASK)));
6811 } else {
6812 gen_helper_write_eflags(cpu_env, s->T0,
6813 tcg_const_i32((TF_MASK | AC_MASK |
6814 ID_MASK | NT_MASK)
6815 & 0xffff));
6819 gen_pop_update(s, ot);
6820 set_cc_op(s, CC_OP_EFLAGS);
6821 /* abort translation because TF/AC flag may change */
6822 gen_jmp_im(s, s->pc - s->cs_base);
6823 gen_eob(s);
6825 break;
6826 case 0x9e: /* sahf */
6827 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6828 goto illegal_op;
6829 gen_op_mov_v_reg(s, MO_8, s->T0, R_AH);
6830 gen_compute_eflags(s);
6831 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6832 tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6833 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
6834 break;
6835 case 0x9f: /* lahf */
6836 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6837 goto illegal_op;
6838 gen_compute_eflags(s);
6839 /* Note: gen_compute_eflags() only gives the condition codes */
6840 tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02);
6841 gen_op_mov_reg_v(s, MO_8, R_AH, s->T0);
6842 break;
6843 case 0xf5: /* cmc */
6844 gen_compute_eflags(s);
6845 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6846 break;
6847 case 0xf8: /* clc */
6848 gen_compute_eflags(s);
6849 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6850 break;
6851 case 0xf9: /* stc */
6852 gen_compute_eflags(s);
6853 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6854 break;
6855 case 0xfc: /* cld */
6856 tcg_gen_movi_i32(s->tmp2_i32, 1);
6857 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6858 break;
6859 case 0xfd: /* std */
6860 tcg_gen_movi_i32(s->tmp2_i32, -1);
6861 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6862 break;
6864 /************************/
6865 /* bit operations */
6866 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6867 ot = dflag;
6868 modrm = x86_ldub_code(env, s);
6869 op = (modrm >> 3) & 7;
6870 mod = (modrm >> 6) & 3;
6871 rm = (modrm & 7) | REX_B(s);
6872 if (mod != 3) {
6873 s->rip_offset = 1;
6874 gen_lea_modrm(env, s, modrm);
6875 if (!(s->prefix & PREFIX_LOCK)) {
6876 gen_op_ld_v(s, ot, s->T0, s->A0);
6878 } else {
6879 gen_op_mov_v_reg(s, ot, s->T0, rm);
6881 /* load shift */
6882 val = x86_ldub_code(env, s);
6883 tcg_gen_movi_tl(s->T1, val);
6884 if (op < 4)
6885 goto unknown_op;
6886 op -= 4;
6887 goto bt_op;
6888 case 0x1a3: /* bt Gv, Ev */
6889 op = 0;
6890 goto do_btx;
6891 case 0x1ab: /* bts */
6892 op = 1;
6893 goto do_btx;
6894 case 0x1b3: /* btr */
6895 op = 2;
6896 goto do_btx;
6897 case 0x1bb: /* btc */
6898 op = 3;
6899 do_btx:
6900 ot = dflag;
6901 modrm = x86_ldub_code(env, s);
6902 reg = ((modrm >> 3) & 7) | REX_R(s);
6903 mod = (modrm >> 6) & 3;
6904 rm = (modrm & 7) | REX_B(s);
6905 gen_op_mov_v_reg(s, MO_32, s->T1, reg);
6906 if (mod != 3) {
6907 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6908 /* specific case: we need to add a displacement */
6909 gen_exts(ot, s->T1);
6910 tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
6911 tcg_gen_shli_tl(s->tmp0, s->tmp0, ot);
6912 tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a), s->tmp0);
6913 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
6914 if (!(s->prefix & PREFIX_LOCK)) {
6915 gen_op_ld_v(s, ot, s->T0, s->A0);
6917 } else {
6918 gen_op_mov_v_reg(s, ot, s->T0, rm);
6920 bt_op:
6921 tcg_gen_andi_tl(s->T1, s->T1, (1 << (3 + ot)) - 1);
6922 tcg_gen_movi_tl(s->tmp0, 1);
6923 tcg_gen_shl_tl(s->tmp0, s->tmp0, s->T1);
6924 if (s->prefix & PREFIX_LOCK) {
6925 switch (op) {
6926 case 0: /* bt */
6927 /* Needs no atomic ops; we surpressed the normal
6928 memory load for LOCK above so do it now. */
6929 gen_op_ld_v(s, ot, s->T0, s->A0);
6930 break;
6931 case 1: /* bts */
6932 tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, s->tmp0,
6933 s->mem_index, ot | MO_LE);
6934 break;
6935 case 2: /* btr */
6936 tcg_gen_not_tl(s->tmp0, s->tmp0);
6937 tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, s->tmp0,
6938 s->mem_index, ot | MO_LE);
6939 break;
6940 default:
6941 case 3: /* btc */
6942 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0,
6943 s->mem_index, ot | MO_LE);
6944 break;
6946 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6947 } else {
6948 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6949 switch (op) {
6950 case 0: /* bt */
6951 /* Data already loaded; nothing to do. */
6952 break;
6953 case 1: /* bts */
6954 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
6955 break;
6956 case 2: /* btr */
6957 tcg_gen_andc_tl(s->T0, s->T0, s->tmp0);
6958 break;
6959 default:
6960 case 3: /* btc */
6961 tcg_gen_xor_tl(s->T0, s->T0, s->tmp0);
6962 break;
6964 if (op != 0) {
6965 if (mod != 3) {
6966 gen_op_st_v(s, ot, s->T0, s->A0);
6967 } else {
6968 gen_op_mov_reg_v(s, ot, rm, s->T0);
6973 /* Delay all CC updates until after the store above. Note that
6974 C is the result of the test, Z is unchanged, and the others
6975 are all undefined. */
6976 switch (s->cc_op) {
6977 case CC_OP_MULB ... CC_OP_MULQ:
6978 case CC_OP_ADDB ... CC_OP_ADDQ:
6979 case CC_OP_ADCB ... CC_OP_ADCQ:
6980 case CC_OP_SUBB ... CC_OP_SUBQ:
6981 case CC_OP_SBBB ... CC_OP_SBBQ:
6982 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6983 case CC_OP_INCB ... CC_OP_INCQ:
6984 case CC_OP_DECB ... CC_OP_DECQ:
6985 case CC_OP_SHLB ... CC_OP_SHLQ:
6986 case CC_OP_SARB ... CC_OP_SARQ:
6987 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6988 /* Z was going to be computed from the non-zero status of CC_DST.
6989 We can get that same Z value (and the new C value) by leaving
6990 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6991 same width. */
6992 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
6993 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6994 break;
6995 default:
6996 /* Otherwise, generate EFLAGS and replace the C bit. */
6997 gen_compute_eflags(s);
6998 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, s->tmp4,
6999 ctz32(CC_C), 1);
7000 break;
7002 break;
7003 case 0x1bc: /* bsf / tzcnt */
7004 case 0x1bd: /* bsr / lzcnt */
7005 ot = dflag;
7006 modrm = x86_ldub_code(env, s);
7007 reg = ((modrm >> 3) & 7) | REX_R(s);
7008 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7009 gen_extu(ot, s->T0);
7011 /* Note that lzcnt and tzcnt are in different extensions. */
7012 if ((prefixes & PREFIX_REPZ)
7013 && (b & 1
7014 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
7015 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
7016 int size = 8 << ot;
7017 /* For lzcnt/tzcnt, C bit is defined related to the input. */
7018 tcg_gen_mov_tl(cpu_cc_src, s->T0);
7019 if (b & 1) {
7020 /* For lzcnt, reduce the target_ulong result by the
7021 number of zeros that we expect to find at the top. */
7022 tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
7023 tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
7024 } else {
7025 /* For tzcnt, a zero input must return the operand size. */
7026 tcg_gen_ctzi_tl(s->T0, s->T0, size);
7028 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
7029 gen_op_update1_cc(s);
7030 set_cc_op(s, CC_OP_BMILGB + ot);
7031 } else {
7032 /* For bsr/bsf, only the Z bit is defined and it is related
7033 to the input and not the result. */
7034 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
7035 set_cc_op(s, CC_OP_LOGICB + ot);
7037 /* ??? The manual says that the output is undefined when the
7038 input is zero, but real hardware leaves it unchanged, and
7039 real programs appear to depend on that. Accomplish this
7040 by passing the output as the value to return upon zero. */
7041 if (b & 1) {
7042 /* For bsr, return the bit index of the first 1 bit,
7043 not the count of leading zeros. */
7044 tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
7045 tcg_gen_clz_tl(s->T0, s->T0, s->T1);
7046 tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
7047 } else {
7048 tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
7051 gen_op_mov_reg_v(s, ot, reg, s->T0);
7052 break;
7053 /************************/
7054 /* bcd */
7055 case 0x27: /* daa */
7056 if (CODE64(s))
7057 goto illegal_op;
7058 gen_update_cc_op(s);
7059 gen_helper_daa(cpu_env);
7060 set_cc_op(s, CC_OP_EFLAGS);
7061 break;
7062 case 0x2f: /* das */
7063 if (CODE64(s))
7064 goto illegal_op;
7065 gen_update_cc_op(s);
7066 gen_helper_das(cpu_env);
7067 set_cc_op(s, CC_OP_EFLAGS);
7068 break;
7069 case 0x37: /* aaa */
7070 if (CODE64(s))
7071 goto illegal_op;
7072 gen_update_cc_op(s);
7073 gen_helper_aaa(cpu_env);
7074 set_cc_op(s, CC_OP_EFLAGS);
7075 break;
7076 case 0x3f: /* aas */
7077 if (CODE64(s))
7078 goto illegal_op;
7079 gen_update_cc_op(s);
7080 gen_helper_aas(cpu_env);
7081 set_cc_op(s, CC_OP_EFLAGS);
7082 break;
7083 case 0xd4: /* aam */
7084 if (CODE64(s))
7085 goto illegal_op;
7086 val = x86_ldub_code(env, s);
7087 if (val == 0) {
7088 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7089 } else {
7090 gen_helper_aam(cpu_env, tcg_const_i32(val));
7091 set_cc_op(s, CC_OP_LOGICB);
7093 break;
7094 case 0xd5: /* aad */
7095 if (CODE64(s))
7096 goto illegal_op;
7097 val = x86_ldub_code(env, s);
7098 gen_helper_aad(cpu_env, tcg_const_i32(val));
7099 set_cc_op(s, CC_OP_LOGICB);
7100 break;
7101 /************************/
7102 /* misc */
7103 case 0x90: /* nop */
7104 /* XXX: correct lock test for all insn */
7105 if (prefixes & PREFIX_LOCK) {
7106 goto illegal_op;
7108 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
7109 if (REX_B(s)) {
7110 goto do_xchg_reg_eax;
7112 if (prefixes & PREFIX_REPZ) {
7113 gen_update_cc_op(s);
7114 gen_jmp_im(s, pc_start - s->cs_base);
7115 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
7116 s->base.is_jmp = DISAS_NORETURN;
7118 break;
7119 case 0x9b: /* fwait */
7120 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7121 (HF_MP_MASK | HF_TS_MASK)) {
7122 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7123 } else {
7124 gen_helper_fwait(cpu_env);
7126 break;
7127 case 0xcc: /* int3 */
7128 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7129 break;
7130 case 0xcd: /* int N */
7131 val = x86_ldub_code(env, s);
7132 if (check_vm86_iopl(s)) {
7133 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7135 break;
7136 case 0xce: /* into */
7137 if (CODE64(s))
7138 goto illegal_op;
7139 gen_update_cc_op(s);
7140 gen_jmp_im(s, pc_start - s->cs_base);
7141 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
7142 break;
7143 #ifdef WANT_ICEBP
7144 case 0xf1: /* icebp (undocumented, exits to external debugger) */
7145 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
7146 gen_debug(s, pc_start - s->cs_base);
7147 break;
7148 #endif
7149 case 0xfa: /* cli */
7150 if (check_iopl(s)) {
7151 gen_helper_cli(cpu_env);
7153 break;
7154 case 0xfb: /* sti */
7155 if (check_iopl(s)) {
7156 gen_helper_sti(cpu_env);
7157 /* interruptions are enabled only the first insn after sti */
7158 gen_jmp_im(s, s->pc - s->cs_base);
7159 gen_eob_inhibit_irq(s, true);
7161 break;
7162 case 0x62: /* bound */
7163 if (CODE64(s))
7164 goto illegal_op;
7165 ot = dflag;
7166 modrm = x86_ldub_code(env, s);
7167 reg = (modrm >> 3) & 7;
7168 mod = (modrm >> 6) & 3;
7169 if (mod == 3)
7170 goto illegal_op;
7171 gen_op_mov_v_reg(s, ot, s->T0, reg);
7172 gen_lea_modrm(env, s, modrm);
7173 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7174 if (ot == MO_16) {
7175 gen_helper_boundw(cpu_env, s->A0, s->tmp2_i32);
7176 } else {
7177 gen_helper_boundl(cpu_env, s->A0, s->tmp2_i32);
7179 break;
7180 case 0x1c8 ... 0x1cf: /* bswap reg */
7181 reg = (b & 7) | REX_B(s);
7182 #ifdef TARGET_X86_64
7183 if (dflag == MO_64) {
7184 gen_op_mov_v_reg(s, MO_64, s->T0, reg);
7185 tcg_gen_bswap64_i64(s->T0, s->T0);
7186 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
7187 } else
7188 #endif
7190 gen_op_mov_v_reg(s, MO_32, s->T0, reg);
7191 tcg_gen_ext32u_tl(s->T0, s->T0);
7192 tcg_gen_bswap32_tl(s->T0, s->T0);
7193 gen_op_mov_reg_v(s, MO_32, reg, s->T0);
7195 break;
7196 case 0xd6: /* salc */
7197 if (CODE64(s))
7198 goto illegal_op;
7199 gen_compute_eflags_c(s, s->T0);
7200 tcg_gen_neg_tl(s->T0, s->T0);
7201 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
7202 break;
7203 case 0xe0: /* loopnz */
7204 case 0xe1: /* loopz */
7205 case 0xe2: /* loop */
7206 case 0xe3: /* jecxz */
7208 TCGLabel *l1, *l2, *l3;
7210 tval = (int8_t)insn_get(env, s, MO_8);
7211 next_eip = s->pc - s->cs_base;
7212 tval += next_eip;
7213 if (dflag == MO_16) {
7214 tval &= 0xffff;
7217 l1 = gen_new_label();
7218 l2 = gen_new_label();
7219 l3 = gen_new_label();
7220 gen_update_cc_op(s);
7221 b &= 3;
7222 switch(b) {
7223 case 0: /* loopnz */
7224 case 1: /* loopz */
7225 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7226 gen_op_jz_ecx(s, s->aflag, l3);
7227 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7228 break;
7229 case 2: /* loop */
7230 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7231 gen_op_jnz_ecx(s, s->aflag, l1);
7232 break;
7233 default:
7234 case 3: /* jcxz */
7235 gen_op_jz_ecx(s, s->aflag, l1);
7236 break;
7239 gen_set_label(l3);
7240 gen_jmp_im(s, next_eip);
7241 tcg_gen_br(l2);
7243 gen_set_label(l1);
7244 gen_jmp_im(s, tval);
7245 gen_set_label(l2);
7246 gen_eob(s);
7248 break;
7249 case 0x130: /* wrmsr */
7250 case 0x132: /* rdmsr */
7251 if (check_cpl0(s)) {
7252 gen_update_cc_op(s);
7253 gen_jmp_im(s, pc_start - s->cs_base);
7254 if (b & 2) {
7255 gen_helper_rdmsr(cpu_env);
7256 } else {
7257 gen_helper_wrmsr(cpu_env);
7260 break;
7261 case 0x131: /* rdtsc */
7262 gen_update_cc_op(s);
7263 gen_jmp_im(s, pc_start - s->cs_base);
7264 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7265 gen_io_start();
7267 gen_helper_rdtsc(cpu_env);
7268 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7269 gen_jmp(s, s->pc - s->cs_base);
7271 break;
7272 case 0x133: /* rdpmc */
7273 gen_update_cc_op(s);
7274 gen_jmp_im(s, pc_start - s->cs_base);
7275 gen_helper_rdpmc(cpu_env);
7276 break;
7277 case 0x134: /* sysenter */
7278 /* For Intel SYSENTER is valid on 64-bit */
7279 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7280 goto illegal_op;
7281 if (!PE(s)) {
7282 gen_exception_gpf(s);
7283 } else {
7284 gen_helper_sysenter(cpu_env);
7285 gen_eob(s);
7287 break;
7288 case 0x135: /* sysexit */
7289 /* For Intel SYSEXIT is valid on 64-bit */
7290 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7291 goto illegal_op;
7292 if (!PE(s)) {
7293 gen_exception_gpf(s);
7294 } else {
7295 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7296 gen_eob(s);
7298 break;
7299 #ifdef TARGET_X86_64
7300 case 0x105: /* syscall */
7301 /* XXX: is it usable in real mode ? */
7302 gen_update_cc_op(s);
7303 gen_jmp_im(s, pc_start - s->cs_base);
7304 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7305 /* TF handling for the syscall insn is different. The TF bit is checked
7306 after the syscall insn completes. This allows #DB to not be
7307 generated after one has entered CPL0 if TF is set in FMASK. */
7308 gen_eob_worker(s, false, true);
7309 break;
7310 case 0x107: /* sysret */
7311 if (!PE(s)) {
7312 gen_exception_gpf(s);
7313 } else {
7314 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7315 /* condition codes are modified only in long mode */
7316 if (LMA(s)) {
7317 set_cc_op(s, CC_OP_EFLAGS);
7319 /* TF handling for the sysret insn is different. The TF bit is
7320 checked after the sysret insn completes. This allows #DB to be
7321 generated "as if" the syscall insn in userspace has just
7322 completed. */
7323 gen_eob_worker(s, false, true);
7325 break;
7326 #endif
7327 case 0x1a2: /* cpuid */
7328 gen_update_cc_op(s);
7329 gen_jmp_im(s, pc_start - s->cs_base);
7330 gen_helper_cpuid(cpu_env);
7331 break;
7332 case 0xf4: /* hlt */
7333 if (check_cpl0(s)) {
7334 gen_update_cc_op(s);
7335 gen_jmp_im(s, pc_start - s->cs_base);
7336 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7337 s->base.is_jmp = DISAS_NORETURN;
7339 break;
7340 case 0x100:
7341 modrm = x86_ldub_code(env, s);
7342 mod = (modrm >> 6) & 3;
7343 op = (modrm >> 3) & 7;
7344 switch(op) {
7345 case 0: /* sldt */
7346 if (!PE(s) || VM86(s))
7347 goto illegal_op;
7348 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7349 tcg_gen_ld32u_tl(s->T0, cpu_env,
7350 offsetof(CPUX86State, ldt.selector));
7351 ot = mod == 3 ? dflag : MO_16;
7352 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7353 break;
7354 case 2: /* lldt */
7355 if (!PE(s) || VM86(s))
7356 goto illegal_op;
7357 if (check_cpl0(s)) {
7358 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7359 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7360 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7361 gen_helper_lldt(cpu_env, s->tmp2_i32);
7363 break;
7364 case 1: /* str */
7365 if (!PE(s) || VM86(s))
7366 goto illegal_op;
7367 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7368 tcg_gen_ld32u_tl(s->T0, cpu_env,
7369 offsetof(CPUX86State, tr.selector));
7370 ot = mod == 3 ? dflag : MO_16;
7371 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7372 break;
7373 case 3: /* ltr */
7374 if (!PE(s) || VM86(s))
7375 goto illegal_op;
7376 if (check_cpl0(s)) {
7377 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7378 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7379 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7380 gen_helper_ltr(cpu_env, s->tmp2_i32);
7382 break;
7383 case 4: /* verr */
7384 case 5: /* verw */
7385 if (!PE(s) || VM86(s))
7386 goto illegal_op;
7387 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7388 gen_update_cc_op(s);
7389 if (op == 4) {
7390 gen_helper_verr(cpu_env, s->T0);
7391 } else {
7392 gen_helper_verw(cpu_env, s->T0);
7394 set_cc_op(s, CC_OP_EFLAGS);
7395 break;
7396 default:
7397 goto unknown_op;
7399 break;
7401 case 0x101:
7402 modrm = x86_ldub_code(env, s);
7403 switch (modrm) {
7404 CASE_MODRM_MEM_OP(0): /* sgdt */
7405 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7406 gen_lea_modrm(env, s, modrm);
7407 tcg_gen_ld32u_tl(s->T0,
7408 cpu_env, offsetof(CPUX86State, gdt.limit));
7409 gen_op_st_v(s, MO_16, s->T0, s->A0);
7410 gen_add_A0_im(s, 2);
7411 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7412 if (dflag == MO_16) {
7413 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7415 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7416 break;
7418 case 0xc8: /* monitor */
7419 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
7420 goto illegal_op;
7422 gen_update_cc_op(s);
7423 gen_jmp_im(s, pc_start - s->cs_base);
7424 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7425 gen_extu(s->aflag, s->A0);
7426 gen_add_A0_ds_seg(s);
7427 gen_helper_monitor(cpu_env, s->A0);
7428 break;
7430 case 0xc9: /* mwait */
7431 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
7432 goto illegal_op;
7434 gen_update_cc_op(s);
7435 gen_jmp_im(s, pc_start - s->cs_base);
7436 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7437 gen_eob(s);
7438 break;
7440 case 0xca: /* clac */
7441 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7442 || CPL(s) != 0) {
7443 goto illegal_op;
7445 gen_helper_clac(cpu_env);
7446 gen_jmp_im(s, s->pc - s->cs_base);
7447 gen_eob(s);
7448 break;
7450 case 0xcb: /* stac */
7451 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7452 || CPL(s) != 0) {
7453 goto illegal_op;
7455 gen_helper_stac(cpu_env);
7456 gen_jmp_im(s, s->pc - s->cs_base);
7457 gen_eob(s);
7458 break;
7460 CASE_MODRM_MEM_OP(1): /* sidt */
7461 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7462 gen_lea_modrm(env, s, modrm);
7463 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit));
7464 gen_op_st_v(s, MO_16, s->T0, s->A0);
7465 gen_add_A0_im(s, 2);
7466 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7467 if (dflag == MO_16) {
7468 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7470 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7471 break;
7473 case 0xd0: /* xgetbv */
7474 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7475 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7476 | PREFIX_REPZ | PREFIX_REPNZ))) {
7477 goto illegal_op;
7479 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7480 gen_helper_xgetbv(s->tmp1_i64, cpu_env, s->tmp2_i32);
7481 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7482 break;
7484 case 0xd1: /* xsetbv */
7485 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7486 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7487 | PREFIX_REPZ | PREFIX_REPNZ))) {
7488 goto illegal_op;
7490 if (!check_cpl0(s)) {
7491 break;
7493 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7494 cpu_regs[R_EDX]);
7495 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7496 gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
7497 /* End TB because translation flags may change. */
7498 gen_jmp_im(s, s->pc - s->cs_base);
7499 gen_eob(s);
7500 break;
7502 case 0xd8: /* VMRUN */
7503 if (!SVME(s) || !PE(s)) {
7504 goto illegal_op;
7506 if (!check_cpl0(s)) {
7507 break;
7509 gen_update_cc_op(s);
7510 gen_jmp_im(s, pc_start - s->cs_base);
7511 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7512 tcg_const_i32(s->pc - pc_start));
7513 tcg_gen_exit_tb(NULL, 0);
7514 s->base.is_jmp = DISAS_NORETURN;
7515 break;
7517 case 0xd9: /* VMMCALL */
7518 if (!SVME(s)) {
7519 goto illegal_op;
7521 gen_update_cc_op(s);
7522 gen_jmp_im(s, pc_start - s->cs_base);
7523 gen_helper_vmmcall(cpu_env);
7524 break;
7526 case 0xda: /* VMLOAD */
7527 if (!SVME(s) || !PE(s)) {
7528 goto illegal_op;
7530 if (!check_cpl0(s)) {
7531 break;
7533 gen_update_cc_op(s);
7534 gen_jmp_im(s, pc_start - s->cs_base);
7535 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7536 break;
7538 case 0xdb: /* VMSAVE */
7539 if (!SVME(s) || !PE(s)) {
7540 goto illegal_op;
7542 if (!check_cpl0(s)) {
7543 break;
7545 gen_update_cc_op(s);
7546 gen_jmp_im(s, pc_start - s->cs_base);
7547 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7548 break;
7550 case 0xdc: /* STGI */
7551 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7552 || !PE(s)) {
7553 goto illegal_op;
7555 if (!check_cpl0(s)) {
7556 break;
7558 gen_update_cc_op(s);
7559 gen_helper_stgi(cpu_env);
7560 gen_jmp_im(s, s->pc - s->cs_base);
7561 gen_eob(s);
7562 break;
7564 case 0xdd: /* CLGI */
7565 if (!SVME(s) || !PE(s)) {
7566 goto illegal_op;
7568 if (!check_cpl0(s)) {
7569 break;
7571 gen_update_cc_op(s);
7572 gen_jmp_im(s, pc_start - s->cs_base);
7573 gen_helper_clgi(cpu_env);
7574 break;
7576 case 0xde: /* SKINIT */
7577 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7578 || !PE(s)) {
7579 goto illegal_op;
7581 gen_update_cc_op(s);
7582 gen_jmp_im(s, pc_start - s->cs_base);
7583 gen_helper_skinit(cpu_env);
7584 break;
7586 case 0xdf: /* INVLPGA */
7587 if (!SVME(s) || !PE(s)) {
7588 goto illegal_op;
7590 if (!check_cpl0(s)) {
7591 break;
7593 gen_update_cc_op(s);
7594 gen_jmp_im(s, pc_start - s->cs_base);
7595 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7596 break;
7598 CASE_MODRM_MEM_OP(2): /* lgdt */
7599 if (!check_cpl0(s)) {
7600 break;
7602 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_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, gdt.base));
7611 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7612 break;
7614 CASE_MODRM_MEM_OP(3): /* lidt */
7615 if (!check_cpl0(s)) {
7616 break;
7618 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7619 gen_lea_modrm(env, s, modrm);
7620 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7621 gen_add_A0_im(s, 2);
7622 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7623 if (dflag == MO_16) {
7624 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7626 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7627 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, idt.limit));
7628 break;
7630 CASE_MODRM_OP(4): /* smsw */
7631 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7632 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
7634 * In 32-bit mode, the higher 16 bits of the destination
7635 * register are undefined. In practice CR0[31:0] is stored
7636 * just like in 64-bit mode.
7638 mod = (modrm >> 6) & 3;
7639 ot = (mod != 3 ? MO_16 : s->dflag);
7640 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7641 break;
7642 case 0xee: /* rdpkru */
7643 if (prefixes & PREFIX_LOCK) {
7644 goto illegal_op;
7646 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7647 gen_helper_rdpkru(s->tmp1_i64, cpu_env, s->tmp2_i32);
7648 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7649 break;
7650 case 0xef: /* wrpkru */
7651 if (prefixes & PREFIX_LOCK) {
7652 goto illegal_op;
7654 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7655 cpu_regs[R_EDX]);
7656 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7657 gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64);
7658 break;
7659 CASE_MODRM_OP(6): /* lmsw */
7660 if (!check_cpl0(s)) {
7661 break;
7663 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7664 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7665 gen_helper_lmsw(cpu_env, s->T0);
7666 gen_jmp_im(s, s->pc - s->cs_base);
7667 gen_eob(s);
7668 break;
7670 CASE_MODRM_MEM_OP(7): /* invlpg */
7671 if (!check_cpl0(s)) {
7672 break;
7674 gen_update_cc_op(s);
7675 gen_jmp_im(s, pc_start - s->cs_base);
7676 gen_lea_modrm(env, s, modrm);
7677 gen_helper_invlpg(cpu_env, s->A0);
7678 gen_jmp_im(s, s->pc - s->cs_base);
7679 gen_eob(s);
7680 break;
7682 case 0xf8: /* swapgs */
7683 #ifdef TARGET_X86_64
7684 if (CODE64(s)) {
7685 if (check_cpl0(s)) {
7686 tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]);
7687 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7688 offsetof(CPUX86State, kernelgsbase));
7689 tcg_gen_st_tl(s->T0, cpu_env,
7690 offsetof(CPUX86State, kernelgsbase));
7692 break;
7694 #endif
7695 goto illegal_op;
7697 case 0xf9: /* rdtscp */
7698 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7699 goto illegal_op;
7701 gen_update_cc_op(s);
7702 gen_jmp_im(s, pc_start - s->cs_base);
7703 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7704 gen_io_start();
7706 gen_helper_rdtscp(cpu_env);
7707 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7708 gen_jmp(s, s->pc - s->cs_base);
7710 break;
7712 default:
7713 goto unknown_op;
7715 break;
7717 case 0x108: /* invd */
7718 case 0x109: /* wbinvd */
7719 if (check_cpl0(s)) {
7720 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7721 /* nothing to do */
7723 break;
7724 case 0x63: /* arpl or movslS (x86_64) */
7725 #ifdef TARGET_X86_64
7726 if (CODE64(s)) {
7727 int d_ot;
7728 /* d_ot is the size of destination */
7729 d_ot = dflag;
7731 modrm = x86_ldub_code(env, s);
7732 reg = ((modrm >> 3) & 7) | REX_R(s);
7733 mod = (modrm >> 6) & 3;
7734 rm = (modrm & 7) | REX_B(s);
7736 if (mod == 3) {
7737 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
7738 /* sign extend */
7739 if (d_ot == MO_64) {
7740 tcg_gen_ext32s_tl(s->T0, s->T0);
7742 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7743 } else {
7744 gen_lea_modrm(env, s, modrm);
7745 gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0);
7746 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7748 } else
7749 #endif
7751 TCGLabel *label1;
7752 TCGv t0, t1, t2, a0;
7754 if (!PE(s) || VM86(s))
7755 goto illegal_op;
7756 t0 = tcg_temp_local_new();
7757 t1 = tcg_temp_local_new();
7758 t2 = tcg_temp_local_new();
7759 ot = MO_16;
7760 modrm = x86_ldub_code(env, s);
7761 reg = (modrm >> 3) & 7;
7762 mod = (modrm >> 6) & 3;
7763 rm = modrm & 7;
7764 if (mod != 3) {
7765 gen_lea_modrm(env, s, modrm);
7766 gen_op_ld_v(s, ot, t0, s->A0);
7767 a0 = tcg_temp_local_new();
7768 tcg_gen_mov_tl(a0, s->A0);
7769 } else {
7770 gen_op_mov_v_reg(s, ot, t0, rm);
7771 a0 = NULL;
7773 gen_op_mov_v_reg(s, ot, t1, reg);
7774 tcg_gen_andi_tl(s->tmp0, t0, 3);
7775 tcg_gen_andi_tl(t1, t1, 3);
7776 tcg_gen_movi_tl(t2, 0);
7777 label1 = gen_new_label();
7778 tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1);
7779 tcg_gen_andi_tl(t0, t0, ~3);
7780 tcg_gen_or_tl(t0, t0, t1);
7781 tcg_gen_movi_tl(t2, CC_Z);
7782 gen_set_label(label1);
7783 if (mod != 3) {
7784 gen_op_st_v(s, ot, t0, a0);
7785 tcg_temp_free(a0);
7786 } else {
7787 gen_op_mov_reg_v(s, ot, rm, t0);
7789 gen_compute_eflags(s);
7790 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7791 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7792 tcg_temp_free(t0);
7793 tcg_temp_free(t1);
7794 tcg_temp_free(t2);
7796 break;
7797 case 0x102: /* lar */
7798 case 0x103: /* lsl */
7800 TCGLabel *label1;
7801 TCGv t0;
7802 if (!PE(s) || VM86(s))
7803 goto illegal_op;
7804 ot = dflag != MO_16 ? MO_32 : MO_16;
7805 modrm = x86_ldub_code(env, s);
7806 reg = ((modrm >> 3) & 7) | REX_R(s);
7807 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7808 t0 = tcg_temp_local_new();
7809 gen_update_cc_op(s);
7810 if (b == 0x102) {
7811 gen_helper_lar(t0, cpu_env, s->T0);
7812 } else {
7813 gen_helper_lsl(t0, cpu_env, s->T0);
7815 tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z);
7816 label1 = gen_new_label();
7817 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
7818 gen_op_mov_reg_v(s, ot, reg, t0);
7819 gen_set_label(label1);
7820 set_cc_op(s, CC_OP_EFLAGS);
7821 tcg_temp_free(t0);
7823 break;
7824 case 0x118:
7825 modrm = x86_ldub_code(env, s);
7826 mod = (modrm >> 6) & 3;
7827 op = (modrm >> 3) & 7;
7828 switch(op) {
7829 case 0: /* prefetchnta */
7830 case 1: /* prefetchnt0 */
7831 case 2: /* prefetchnt0 */
7832 case 3: /* prefetchnt0 */
7833 if (mod == 3)
7834 goto illegal_op;
7835 gen_nop_modrm(env, s, modrm);
7836 /* nothing more to do */
7837 break;
7838 default: /* nop (multi byte) */
7839 gen_nop_modrm(env, s, modrm);
7840 break;
7842 break;
7843 case 0x11a:
7844 modrm = x86_ldub_code(env, s);
7845 if (s->flags & HF_MPX_EN_MASK) {
7846 mod = (modrm >> 6) & 3;
7847 reg = ((modrm >> 3) & 7) | REX_R(s);
7848 if (prefixes & PREFIX_REPZ) {
7849 /* bndcl */
7850 if (reg >= 4
7851 || (prefixes & PREFIX_LOCK)
7852 || s->aflag == MO_16) {
7853 goto illegal_op;
7855 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7856 } else if (prefixes & PREFIX_REPNZ) {
7857 /* bndcu */
7858 if (reg >= 4
7859 || (prefixes & PREFIX_LOCK)
7860 || s->aflag == MO_16) {
7861 goto illegal_op;
7863 TCGv_i64 notu = tcg_temp_new_i64();
7864 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7865 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7866 tcg_temp_free_i64(notu);
7867 } else if (prefixes & PREFIX_DATA) {
7868 /* bndmov -- from reg/mem */
7869 if (reg >= 4 || s->aflag == MO_16) {
7870 goto illegal_op;
7872 if (mod == 3) {
7873 int reg2 = (modrm & 7) | REX_B(s);
7874 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7875 goto illegal_op;
7877 if (s->flags & HF_MPX_IU_MASK) {
7878 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7879 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7881 } else {
7882 gen_lea_modrm(env, s, modrm);
7883 if (CODE64(s)) {
7884 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7885 s->mem_index, MO_LEQ);
7886 tcg_gen_addi_tl(s->A0, s->A0, 8);
7887 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7888 s->mem_index, MO_LEQ);
7889 } else {
7890 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7891 s->mem_index, MO_LEUL);
7892 tcg_gen_addi_tl(s->A0, s->A0, 4);
7893 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7894 s->mem_index, MO_LEUL);
7896 /* bnd registers are now in-use */
7897 gen_set_hflag(s, HF_MPX_IU_MASK);
7899 } else if (mod != 3) {
7900 /* bndldx */
7901 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7902 if (reg >= 4
7903 || (prefixes & PREFIX_LOCK)
7904 || s->aflag == MO_16
7905 || a.base < -1) {
7906 goto illegal_op;
7908 if (a.base >= 0) {
7909 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
7910 } else {
7911 tcg_gen_movi_tl(s->A0, 0);
7913 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
7914 if (a.index >= 0) {
7915 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
7916 } else {
7917 tcg_gen_movi_tl(s->T0, 0);
7919 if (CODE64(s)) {
7920 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0);
7921 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7922 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7923 } else {
7924 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0);
7925 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7926 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7928 gen_set_hflag(s, HF_MPX_IU_MASK);
7931 gen_nop_modrm(env, s, modrm);
7932 break;
7933 case 0x11b:
7934 modrm = x86_ldub_code(env, s);
7935 if (s->flags & HF_MPX_EN_MASK) {
7936 mod = (modrm >> 6) & 3;
7937 reg = ((modrm >> 3) & 7) | REX_R(s);
7938 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7939 /* bndmk */
7940 if (reg >= 4
7941 || (prefixes & PREFIX_LOCK)
7942 || s->aflag == MO_16) {
7943 goto illegal_op;
7945 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7946 if (a.base >= 0) {
7947 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7948 if (!CODE64(s)) {
7949 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7951 } else if (a.base == -1) {
7952 /* no base register has lower bound of 0 */
7953 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7954 } else {
7955 /* rip-relative generates #ud */
7956 goto illegal_op;
7958 tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a));
7959 if (!CODE64(s)) {
7960 tcg_gen_ext32u_tl(s->A0, s->A0);
7962 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
7963 /* bnd registers are now in-use */
7964 gen_set_hflag(s, HF_MPX_IU_MASK);
7965 break;
7966 } else if (prefixes & PREFIX_REPNZ) {
7967 /* bndcn */
7968 if (reg >= 4
7969 || (prefixes & PREFIX_LOCK)
7970 || s->aflag == MO_16) {
7971 goto illegal_op;
7973 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
7974 } else if (prefixes & PREFIX_DATA) {
7975 /* bndmov -- to reg/mem */
7976 if (reg >= 4 || s->aflag == MO_16) {
7977 goto illegal_op;
7979 if (mod == 3) {
7980 int reg2 = (modrm & 7) | REX_B(s);
7981 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7982 goto illegal_op;
7984 if (s->flags & HF_MPX_IU_MASK) {
7985 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7986 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7988 } else {
7989 gen_lea_modrm(env, s, modrm);
7990 if (CODE64(s)) {
7991 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
7992 s->mem_index, MO_LEQ);
7993 tcg_gen_addi_tl(s->A0, s->A0, 8);
7994 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
7995 s->mem_index, MO_LEQ);
7996 } else {
7997 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
7998 s->mem_index, MO_LEUL);
7999 tcg_gen_addi_tl(s->A0, s->A0, 4);
8000 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
8001 s->mem_index, MO_LEUL);
8004 } else if (mod != 3) {
8005 /* bndstx */
8006 AddressParts a = gen_lea_modrm_0(env, s, modrm);
8007 if (reg >= 4
8008 || (prefixes & PREFIX_LOCK)
8009 || s->aflag == MO_16
8010 || a.base < -1) {
8011 goto illegal_op;
8013 if (a.base >= 0) {
8014 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
8015 } else {
8016 tcg_gen_movi_tl(s->A0, 0);
8018 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
8019 if (a.index >= 0) {
8020 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
8021 } else {
8022 tcg_gen_movi_tl(s->T0, 0);
8024 if (CODE64(s)) {
8025 gen_helper_bndstx64(cpu_env, s->A0, s->T0,
8026 cpu_bndl[reg], cpu_bndu[reg]);
8027 } else {
8028 gen_helper_bndstx32(cpu_env, s->A0, s->T0,
8029 cpu_bndl[reg], cpu_bndu[reg]);
8033 gen_nop_modrm(env, s, modrm);
8034 break;
8035 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
8036 modrm = x86_ldub_code(env, s);
8037 gen_nop_modrm(env, s, modrm);
8038 break;
8039 case 0x120: /* mov reg, crN */
8040 case 0x122: /* mov crN, reg */
8041 if (check_cpl0(s)) {
8042 modrm = x86_ldub_code(env, s);
8043 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8044 * AMD documentation (24594.pdf) and testing of
8045 * intel 386 and 486 processors all show that the mod bits
8046 * are assumed to be 1's, regardless of actual values.
8048 rm = (modrm & 7) | REX_B(s);
8049 reg = ((modrm >> 3) & 7) | REX_R(s);
8050 if (CODE64(s))
8051 ot = MO_64;
8052 else
8053 ot = MO_32;
8054 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
8055 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
8056 reg = 8;
8058 switch(reg) {
8059 case 0:
8060 case 2:
8061 case 3:
8062 case 4:
8063 case 8:
8064 gen_update_cc_op(s);
8065 gen_jmp_im(s, pc_start - s->cs_base);
8066 if (b & 2) {
8067 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8068 gen_io_start();
8070 gen_op_mov_v_reg(s, ot, s->T0, rm);
8071 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
8072 s->T0);
8073 gen_jmp_im(s, s->pc - s->cs_base);
8074 gen_eob(s);
8075 } else {
8076 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8077 gen_io_start();
8079 gen_helper_read_crN(s->T0, cpu_env, tcg_const_i32(reg));
8080 gen_op_mov_reg_v(s, ot, rm, s->T0);
8081 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8082 gen_jmp(s, s->pc - s->cs_base);
8085 break;
8086 default:
8087 goto unknown_op;
8090 break;
8091 case 0x121: /* mov reg, drN */
8092 case 0x123: /* mov drN, reg */
8093 if (check_cpl0(s)) {
8094 modrm = x86_ldub_code(env, s);
8095 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8096 * AMD documentation (24594.pdf) and testing of
8097 * intel 386 and 486 processors all show that the mod bits
8098 * are assumed to be 1's, regardless of actual values.
8100 rm = (modrm & 7) | REX_B(s);
8101 reg = ((modrm >> 3) & 7) | REX_R(s);
8102 if (CODE64(s))
8103 ot = MO_64;
8104 else
8105 ot = MO_32;
8106 if (reg >= 8) {
8107 goto illegal_op;
8109 if (b & 2) {
8110 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
8111 gen_op_mov_v_reg(s, ot, s->T0, rm);
8112 tcg_gen_movi_i32(s->tmp2_i32, reg);
8113 gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
8114 gen_jmp_im(s, s->pc - s->cs_base);
8115 gen_eob(s);
8116 } else {
8117 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
8118 tcg_gen_movi_i32(s->tmp2_i32, reg);
8119 gen_helper_get_dr(s->T0, cpu_env, s->tmp2_i32);
8120 gen_op_mov_reg_v(s, ot, rm, s->T0);
8123 break;
8124 case 0x106: /* clts */
8125 if (check_cpl0(s)) {
8126 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
8127 gen_helper_clts(cpu_env);
8128 /* abort block because static cpu state changed */
8129 gen_jmp_im(s, s->pc - s->cs_base);
8130 gen_eob(s);
8132 break;
8133 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
8134 case 0x1c3: /* MOVNTI reg, mem */
8135 if (!(s->cpuid_features & CPUID_SSE2))
8136 goto illegal_op;
8137 ot = mo_64_32(dflag);
8138 modrm = x86_ldub_code(env, s);
8139 mod = (modrm >> 6) & 3;
8140 if (mod == 3)
8141 goto illegal_op;
8142 reg = ((modrm >> 3) & 7) | REX_R(s);
8143 /* generate a generic store */
8144 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8145 break;
8146 case 0x1ae:
8147 modrm = x86_ldub_code(env, s);
8148 switch (modrm) {
8149 CASE_MODRM_MEM_OP(0): /* fxsave */
8150 if (!(s->cpuid_features & CPUID_FXSR)
8151 || (prefixes & PREFIX_LOCK)) {
8152 goto illegal_op;
8154 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8155 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8156 break;
8158 gen_lea_modrm(env, s, modrm);
8159 gen_helper_fxsave(cpu_env, s->A0);
8160 break;
8162 CASE_MODRM_MEM_OP(1): /* fxrstor */
8163 if (!(s->cpuid_features & CPUID_FXSR)
8164 || (prefixes & PREFIX_LOCK)) {
8165 goto illegal_op;
8167 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8168 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8169 break;
8171 gen_lea_modrm(env, s, modrm);
8172 gen_helper_fxrstor(cpu_env, s->A0);
8173 break;
8175 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
8176 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8177 goto illegal_op;
8179 if (s->flags & HF_TS_MASK) {
8180 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8181 break;
8183 gen_lea_modrm(env, s, modrm);
8184 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
8185 gen_helper_ldmxcsr(cpu_env, s->tmp2_i32);
8186 break;
8188 CASE_MODRM_MEM_OP(3): /* stmxcsr */
8189 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8190 goto illegal_op;
8192 if (s->flags & HF_TS_MASK) {
8193 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8194 break;
8196 gen_helper_update_mxcsr(cpu_env);
8197 gen_lea_modrm(env, s, modrm);
8198 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr));
8199 gen_op_st_v(s, MO_32, s->T0, s->A0);
8200 break;
8202 CASE_MODRM_MEM_OP(4): /* xsave */
8203 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8204 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8205 | PREFIX_REPZ | PREFIX_REPNZ))) {
8206 goto illegal_op;
8208 gen_lea_modrm(env, s, modrm);
8209 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8210 cpu_regs[R_EDX]);
8211 gen_helper_xsave(cpu_env, s->A0, s->tmp1_i64);
8212 break;
8214 CASE_MODRM_MEM_OP(5): /* xrstor */
8215 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8216 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8217 | PREFIX_REPZ | PREFIX_REPNZ))) {
8218 goto illegal_op;
8220 gen_lea_modrm(env, s, modrm);
8221 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8222 cpu_regs[R_EDX]);
8223 gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64);
8224 /* XRSTOR is how MPX is enabled, which changes how
8225 we translate. Thus we need to end the TB. */
8226 gen_update_cc_op(s);
8227 gen_jmp_im(s, s->pc - s->cs_base);
8228 gen_eob(s);
8229 break;
8231 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
8232 if (prefixes & PREFIX_LOCK) {
8233 goto illegal_op;
8235 if (prefixes & PREFIX_DATA) {
8236 /* clwb */
8237 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8238 goto illegal_op;
8240 gen_nop_modrm(env, s, modrm);
8241 } else {
8242 /* xsaveopt */
8243 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8244 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8245 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8246 goto illegal_op;
8248 gen_lea_modrm(env, s, modrm);
8249 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8250 cpu_regs[R_EDX]);
8251 gen_helper_xsaveopt(cpu_env, s->A0, s->tmp1_i64);
8253 break;
8255 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
8256 if (prefixes & PREFIX_LOCK) {
8257 goto illegal_op;
8259 if (prefixes & PREFIX_DATA) {
8260 /* clflushopt */
8261 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8262 goto illegal_op;
8264 } else {
8265 /* clflush */
8266 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8267 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8268 goto illegal_op;
8271 gen_nop_modrm(env, s, modrm);
8272 break;
8274 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
8275 case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
8276 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
8277 case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
8278 if (CODE64(s)
8279 && (prefixes & PREFIX_REPZ)
8280 && !(prefixes & PREFIX_LOCK)
8281 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8282 TCGv base, treg, src, dst;
8284 /* Preserve hflags bits by testing CR4 at runtime. */
8285 tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
8286 gen_helper_cr4_testbit(cpu_env, s->tmp2_i32);
8288 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8289 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8291 if (modrm & 0x10) {
8292 /* wr*base */
8293 dst = base, src = treg;
8294 } else {
8295 /* rd*base */
8296 dst = treg, src = base;
8299 if (s->dflag == MO_32) {
8300 tcg_gen_ext32u_tl(dst, src);
8301 } else {
8302 tcg_gen_mov_tl(dst, src);
8304 break;
8306 goto unknown_op;
8308 case 0xf8: /* sfence / pcommit */
8309 if (prefixes & PREFIX_DATA) {
8310 /* pcommit */
8311 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8312 || (prefixes & PREFIX_LOCK)) {
8313 goto illegal_op;
8315 break;
8317 /* fallthru */
8318 case 0xf9 ... 0xff: /* sfence */
8319 if (!(s->cpuid_features & CPUID_SSE)
8320 || (prefixes & PREFIX_LOCK)) {
8321 goto illegal_op;
8323 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8324 break;
8325 case 0xe8 ... 0xef: /* lfence */
8326 if (!(s->cpuid_features & CPUID_SSE)
8327 || (prefixes & PREFIX_LOCK)) {
8328 goto illegal_op;
8330 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8331 break;
8332 case 0xf0 ... 0xf7: /* mfence */
8333 if (!(s->cpuid_features & CPUID_SSE2)
8334 || (prefixes & PREFIX_LOCK)) {
8335 goto illegal_op;
8337 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8338 break;
8340 default:
8341 goto unknown_op;
8343 break;
8345 case 0x10d: /* 3DNow! prefetch(w) */
8346 modrm = x86_ldub_code(env, s);
8347 mod = (modrm >> 6) & 3;
8348 if (mod == 3)
8349 goto illegal_op;
8350 gen_nop_modrm(env, s, modrm);
8351 break;
8352 case 0x1aa: /* rsm */
8353 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8354 if (!(s->flags & HF_SMM_MASK))
8355 goto illegal_op;
8356 #ifdef CONFIG_USER_ONLY
8357 /* we should not be in SMM mode */
8358 g_assert_not_reached();
8359 #else
8360 gen_update_cc_op(s);
8361 gen_jmp_im(s, s->pc - s->cs_base);
8362 gen_helper_rsm(cpu_env);
8363 #endif /* CONFIG_USER_ONLY */
8364 gen_eob(s);
8365 break;
8366 case 0x1b8: /* SSE4.2 popcnt */
8367 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8368 PREFIX_REPZ)
8369 goto illegal_op;
8370 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8371 goto illegal_op;
8373 modrm = x86_ldub_code(env, s);
8374 reg = ((modrm >> 3) & 7) | REX_R(s);
8376 if (s->prefix & PREFIX_DATA) {
8377 ot = MO_16;
8378 } else {
8379 ot = mo_64_32(dflag);
8382 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8383 gen_extu(ot, s->T0);
8384 tcg_gen_mov_tl(cpu_cc_src, s->T0);
8385 tcg_gen_ctpop_tl(s->T0, s->T0);
8386 gen_op_mov_reg_v(s, ot, reg, s->T0);
8388 set_cc_op(s, CC_OP_POPCNT);
8389 break;
8390 case 0x10e ... 0x10f:
8391 /* 3DNow! instructions, ignore prefixes */
8392 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8393 /* fall through */
8394 case 0x110 ... 0x117:
8395 case 0x128 ... 0x12f:
8396 case 0x138 ... 0x13a:
8397 case 0x150 ... 0x179:
8398 case 0x17c ... 0x17f:
8399 case 0x1c2:
8400 case 0x1c4 ... 0x1c6:
8401 case 0x1d0 ... 0x1fe:
8402 gen_sse(env, s, b, pc_start);
8403 break;
8404 default:
8405 goto unknown_op;
8407 return s->pc;
8408 illegal_op:
8409 gen_illegal_opcode(s);
8410 return s->pc;
8411 unknown_op:
8412 gen_unknown_opcode(env, s);
8413 return s->pc;
8416 void tcg_x86_init(void)
8418 static const char reg_names[CPU_NB_REGS][4] = {
8419 #ifdef TARGET_X86_64
8420 [R_EAX] = "rax",
8421 [R_EBX] = "rbx",
8422 [R_ECX] = "rcx",
8423 [R_EDX] = "rdx",
8424 [R_ESI] = "rsi",
8425 [R_EDI] = "rdi",
8426 [R_EBP] = "rbp",
8427 [R_ESP] = "rsp",
8428 [8] = "r8",
8429 [9] = "r9",
8430 [10] = "r10",
8431 [11] = "r11",
8432 [12] = "r12",
8433 [13] = "r13",
8434 [14] = "r14",
8435 [15] = "r15",
8436 #else
8437 [R_EAX] = "eax",
8438 [R_EBX] = "ebx",
8439 [R_ECX] = "ecx",
8440 [R_EDX] = "edx",
8441 [R_ESI] = "esi",
8442 [R_EDI] = "edi",
8443 [R_EBP] = "ebp",
8444 [R_ESP] = "esp",
8445 #endif
8447 static const char seg_base_names[6][8] = {
8448 [R_CS] = "cs_base",
8449 [R_DS] = "ds_base",
8450 [R_ES] = "es_base",
8451 [R_FS] = "fs_base",
8452 [R_GS] = "gs_base",
8453 [R_SS] = "ss_base",
8455 static const char bnd_regl_names[4][8] = {
8456 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8458 static const char bnd_regu_names[4][8] = {
8459 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8461 int i;
8463 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8464 offsetof(CPUX86State, cc_op), "cc_op");
8465 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8466 "cc_dst");
8467 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8468 "cc_src");
8469 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8470 "cc_src2");
8472 for (i = 0; i < CPU_NB_REGS; ++i) {
8473 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8474 offsetof(CPUX86State, regs[i]),
8475 reg_names[i]);
8478 for (i = 0; i < 6; ++i) {
8479 cpu_seg_base[i]
8480 = tcg_global_mem_new(cpu_env,
8481 offsetof(CPUX86State, segs[i].base),
8482 seg_base_names[i]);
8485 for (i = 0; i < 4; ++i) {
8486 cpu_bndl[i]
8487 = tcg_global_mem_new_i64(cpu_env,
8488 offsetof(CPUX86State, bnd_regs[i].lb),
8489 bnd_regl_names[i]);
8490 cpu_bndu[i]
8491 = tcg_global_mem_new_i64(cpu_env,
8492 offsetof(CPUX86State, bnd_regs[i].ub),
8493 bnd_regu_names[i]);
8497 static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
8499 DisasContext *dc = container_of(dcbase, DisasContext, base);
8500 CPUX86State *env = cpu->env_ptr;
8501 uint32_t flags = dc->base.tb->flags;
8502 int cpl = (flags >> HF_CPL_SHIFT) & 3;
8503 int iopl = (flags >> IOPL_SHIFT) & 3;
8505 dc->cs_base = dc->base.tb->cs_base;
8506 dc->flags = flags;
8507 #ifndef CONFIG_USER_ONLY
8508 dc->cpl = cpl;
8509 dc->iopl = iopl;
8510 #endif
8512 /* We make some simplifying assumptions; validate they're correct. */
8513 g_assert(PE(dc) == ((flags & HF_PE_MASK) != 0));
8514 g_assert(CPL(dc) == cpl);
8515 g_assert(IOPL(dc) == iopl);
8516 g_assert(VM86(dc) == ((flags & HF_VM_MASK) != 0));
8517 g_assert(CODE32(dc) == ((flags & HF_CS32_MASK) != 0));
8518 g_assert(CODE64(dc) == ((flags & HF_CS64_MASK) != 0));
8519 g_assert(SS32(dc) == ((flags & HF_SS32_MASK) != 0));
8520 g_assert(LMA(dc) == ((flags & HF_LMA_MASK) != 0));
8521 g_assert(ADDSEG(dc) == ((flags & HF_ADDSEG_MASK) != 0));
8522 g_assert(SVME(dc) == ((flags & HF_SVME_MASK) != 0));
8523 g_assert(GUEST(dc) == ((flags & HF_GUEST_MASK) != 0));
8525 dc->cc_op = CC_OP_DYNAMIC;
8526 dc->cc_op_dirty = false;
8527 dc->popl_esp_hack = 0;
8528 /* select memory access functions */
8529 dc->mem_index = 0;
8530 #ifdef CONFIG_SOFTMMU
8531 dc->mem_index = cpu_mmu_index(env, false);
8532 #endif
8533 dc->cpuid_features = env->features[FEAT_1_EDX];
8534 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8535 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8536 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8537 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8538 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8539 dc->jmp_opt = !(dc->base.singlestep_enabled ||
8540 (flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)));
8542 * If jmp_opt, we want to handle each string instruction individually.
8543 * For icount also disable repz optimization so that each iteration
8544 * is accounted separately.
8546 dc->repz_opt = !dc->jmp_opt && !(tb_cflags(dc->base.tb) & CF_USE_ICOUNT);
8548 dc->T0 = tcg_temp_new();
8549 dc->T1 = tcg_temp_new();
8550 dc->A0 = tcg_temp_new();
8552 dc->tmp0 = tcg_temp_new();
8553 dc->tmp1_i64 = tcg_temp_new_i64();
8554 dc->tmp2_i32 = tcg_temp_new_i32();
8555 dc->tmp3_i32 = tcg_temp_new_i32();
8556 dc->tmp4 = tcg_temp_new();
8557 dc->ptr0 = tcg_temp_new_ptr();
8558 dc->ptr1 = tcg_temp_new_ptr();
8559 dc->cc_srcT = tcg_temp_local_new();
8562 static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
8566 static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8568 DisasContext *dc = container_of(dcbase, DisasContext, base);
8570 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
8573 static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8574 const CPUBreakpoint *bp)
8576 DisasContext *dc = container_of(dcbase, DisasContext, base);
8577 /* If RF is set, suppress an internally generated breakpoint. */
8578 int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
8579 if (bp->flags & flags) {
8580 gen_debug(dc, dc->base.pc_next - dc->cs_base);
8581 dc->base.is_jmp = DISAS_NORETURN;
8582 /* The address covered by the breakpoint must be included in
8583 [tb->pc, tb->pc + tb->size) in order to for it to be
8584 properly cleared -- thus we increment the PC here so that
8585 the generic logic setting tb->size later does the right thing. */
8586 dc->base.pc_next += 1;
8587 return true;
8588 } else {
8589 return false;
8593 static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8595 DisasContext *dc = container_of(dcbase, DisasContext, base);
8596 target_ulong pc_next;
8598 #ifdef TARGET_VSYSCALL_PAGE
8600 * Detect entry into the vsyscall page and invoke the syscall.
8602 if ((dc->base.pc_next & TARGET_PAGE_MASK) == TARGET_VSYSCALL_PAGE) {
8603 gen_exception(dc, EXCP_VSYSCALL, dc->base.pc_next);
8604 return;
8606 #endif
8608 pc_next = disas_insn(dc, cpu);
8610 if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
8611 /* if single step mode, we generate only one instruction and
8612 generate an exception */
8613 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8614 the flag and abort the translation to give the irqs a
8615 chance to happen */
8616 dc->base.is_jmp = DISAS_TOO_MANY;
8617 } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
8618 && ((pc_next & TARGET_PAGE_MASK)
8619 != ((pc_next + TARGET_MAX_INSN_SIZE - 1)
8620 & TARGET_PAGE_MASK)
8621 || (pc_next & ~TARGET_PAGE_MASK) == 0)) {
8622 /* Do not cross the boundary of the pages in icount mode,
8623 it can cause an exception. Do it only when boundary is
8624 crossed by the first instruction in the block.
8625 If current instruction already crossed the bound - it's ok,
8626 because an exception hasn't stopped this code.
8628 dc->base.is_jmp = DISAS_TOO_MANY;
8629 } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
8630 dc->base.is_jmp = DISAS_TOO_MANY;
8633 dc->base.pc_next = pc_next;
8636 static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8638 DisasContext *dc = container_of(dcbase, DisasContext, base);
8640 if (dc->base.is_jmp == DISAS_TOO_MANY) {
8641 gen_jmp_im(dc, dc->base.pc_next - dc->cs_base);
8642 gen_eob(dc);
8646 static void i386_tr_disas_log(const DisasContextBase *dcbase,
8647 CPUState *cpu)
8649 DisasContext *dc = container_of(dcbase, DisasContext, base);
8651 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
8652 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
8655 static const TranslatorOps i386_tr_ops = {
8656 .init_disas_context = i386_tr_init_disas_context,
8657 .tb_start = i386_tr_tb_start,
8658 .insn_start = i386_tr_insn_start,
8659 .breakpoint_check = i386_tr_breakpoint_check,
8660 .translate_insn = i386_tr_translate_insn,
8661 .tb_stop = i386_tr_tb_stop,
8662 .disas_log = i386_tr_disas_log,
8665 /* generate intermediate code for basic block 'tb'. */
8666 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
8668 DisasContext dc;
8670 translator_loop(&i386_tr_ops, &dc.base, cpu, tb, max_insns);
8673 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8674 target_ulong *data)
8676 int cc_op = data[1];
8677 env->eip = data[0] - tb->cs_base;
8678 if (cc_op != CC_OP_DYNAMIC) {
8679 env->cc_op = cc_op;