target/i386: REPZ and REPNZ are mutually exclusive
[qemu.git] / target / i386 / tcg / translate.c
blobeaa56b0f4884a5b301f1a14a4b27d67bda181052
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 "exec/log.h"
35 #define PREFIX_REPZ 0x01
36 #define PREFIX_REPNZ 0x02
37 #define PREFIX_LOCK 0x04
38 #define PREFIX_DATA 0x08
39 #define PREFIX_ADR 0x10
40 #define PREFIX_VEX 0x20
41 #define PREFIX_REX 0x40
43 #ifdef TARGET_X86_64
44 # define ctztl ctz64
45 # define clztl clz64
46 #else
47 # define ctztl ctz32
48 # define clztl clz32
49 #endif
51 /* For a switch indexed by MODRM, match all memory operands for a given OP. */
52 #define CASE_MODRM_MEM_OP(OP) \
53 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
54 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
55 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
57 #define CASE_MODRM_OP(OP) \
58 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
59 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
60 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
61 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
63 //#define MACRO_TEST 1
65 /* global register indexes */
66 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
67 static TCGv_i32 cpu_cc_op;
68 static TCGv cpu_regs[CPU_NB_REGS];
69 static TCGv cpu_seg_base[6];
70 static TCGv_i64 cpu_bndl[4];
71 static TCGv_i64 cpu_bndu[4];
73 #include "exec/gen-icount.h"
75 typedef struct DisasContext {
76 DisasContextBase base;
78 target_ulong pc; /* pc = eip + cs_base */
79 target_ulong pc_start; /* pc at TB entry */
80 target_ulong cs_base; /* base of CS segment */
82 MemOp aflag;
83 MemOp dflag;
85 int8_t override; /* -1 if no override, else R_CS, R_DS, etc */
86 uint8_t prefix;
88 #ifndef CONFIG_USER_ONLY
89 uint8_t cpl; /* code priv level */
90 uint8_t iopl; /* i/o priv level */
91 #endif
92 uint8_t vex_l; /* vex vector length */
93 uint8_t vex_v; /* vex vvvv register, without 1's complement. */
94 uint8_t popl_esp_hack; /* for correct popl with esp base handling */
95 uint8_t rip_offset; /* only used in x86_64, but left for simplicity */
97 #ifdef TARGET_X86_64
98 uint8_t rex_r;
99 uint8_t rex_x;
100 uint8_t rex_b;
101 bool rex_w;
102 #endif
103 bool jmp_opt; /* use direct block chaining for direct jumps */
104 bool repz_opt; /* optimize jumps within repz instructions */
105 bool cc_op_dirty;
107 CCOp cc_op; /* current CC operation */
108 int mem_index; /* select memory access functions */
109 uint32_t flags; /* all execution flags */
110 int cpuid_features;
111 int cpuid_ext_features;
112 int cpuid_ext2_features;
113 int cpuid_ext3_features;
114 int cpuid_7_0_ebx_features;
115 int cpuid_xsave_features;
117 /* TCG local temps */
118 TCGv cc_srcT;
119 TCGv A0;
120 TCGv T0;
121 TCGv T1;
123 /* TCG local register indexes (only used inside old micro ops) */
124 TCGv tmp0;
125 TCGv tmp4;
126 TCGv_ptr ptr0;
127 TCGv_ptr ptr1;
128 TCGv_i32 tmp2_i32;
129 TCGv_i32 tmp3_i32;
130 TCGv_i64 tmp1_i64;
132 sigjmp_buf jmpbuf;
133 TCGOp *prev_insn_end;
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(clgi, TCGv_env env)
197 STUB_HELPER(flush_page, TCGv_env env, TCGv addr)
198 STUB_HELPER(hlt, TCGv_env env, TCGv_i32 pc_ofs)
199 STUB_HELPER(inb, TCGv ret, TCGv_env env, TCGv_i32 port)
200 STUB_HELPER(inw, TCGv ret, TCGv_env env, TCGv_i32 port)
201 STUB_HELPER(inl, TCGv ret, TCGv_env env, TCGv_i32 port)
202 STUB_HELPER(monitor, TCGv_env env, TCGv addr)
203 STUB_HELPER(mwait, TCGv_env env, TCGv_i32 pc_ofs)
204 STUB_HELPER(outb, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
205 STUB_HELPER(outw, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
206 STUB_HELPER(outl, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
207 STUB_HELPER(rdmsr, TCGv_env env)
208 STUB_HELPER(read_crN, TCGv ret, TCGv_env env, TCGv_i32 reg)
209 STUB_HELPER(get_dr, TCGv ret, TCGv_env env, TCGv_i32 reg)
210 STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
211 STUB_HELPER(stgi, TCGv_env env)
212 STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
213 STUB_HELPER(vmload, TCGv_env env, TCGv_i32 aflag)
214 STUB_HELPER(vmmcall, TCGv_env env)
215 STUB_HELPER(vmrun, TCGv_env env, TCGv_i32 aflag, TCGv_i32 pc_ofs)
216 STUB_HELPER(vmsave, TCGv_env env, TCGv_i32 aflag)
217 STUB_HELPER(write_crN, TCGv_env env, TCGv_i32 reg, TCGv val)
218 STUB_HELPER(wrmsr, TCGv_env env)
219 #endif
221 static void gen_eob(DisasContext *s);
222 static void gen_jr(DisasContext *s, TCGv dest);
223 static void gen_jmp(DisasContext *s, target_ulong eip);
224 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
225 static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
226 static void gen_exception_gpf(DisasContext *s);
228 /* i386 arith/logic operations */
229 enum {
230 OP_ADDL,
231 OP_ORL,
232 OP_ADCL,
233 OP_SBBL,
234 OP_ANDL,
235 OP_SUBL,
236 OP_XORL,
237 OP_CMPL,
240 /* i386 shift ops */
241 enum {
242 OP_ROL,
243 OP_ROR,
244 OP_RCL,
245 OP_RCR,
246 OP_SHL,
247 OP_SHR,
248 OP_SHL1, /* undocumented */
249 OP_SAR = 7,
252 enum {
253 JCC_O,
254 JCC_B,
255 JCC_Z,
256 JCC_BE,
257 JCC_S,
258 JCC_P,
259 JCC_L,
260 JCC_LE,
263 enum {
264 /* I386 int registers */
265 OR_EAX, /* MUST be even numbered */
266 OR_ECX,
267 OR_EDX,
268 OR_EBX,
269 OR_ESP,
270 OR_EBP,
271 OR_ESI,
272 OR_EDI,
274 OR_TMP0 = 16, /* temporary operand register */
275 OR_TMP1,
276 OR_A0, /* temporary register used when doing address evaluation */
279 enum {
280 USES_CC_DST = 1,
281 USES_CC_SRC = 2,
282 USES_CC_SRC2 = 4,
283 USES_CC_SRCT = 8,
286 /* Bit set if the global variable is live after setting CC_OP to X. */
287 static const uint8_t cc_op_live[CC_OP_NB] = {
288 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
289 [CC_OP_EFLAGS] = USES_CC_SRC,
290 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
291 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
292 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
293 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
294 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
295 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
296 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
297 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
298 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
299 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
300 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
301 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
302 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
303 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
304 [CC_OP_CLR] = 0,
305 [CC_OP_POPCNT] = USES_CC_SRC,
308 static void set_cc_op(DisasContext *s, CCOp op)
310 int dead;
312 if (s->cc_op == op) {
313 return;
316 /* Discard CC computation that will no longer be used. */
317 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
318 if (dead & USES_CC_DST) {
319 tcg_gen_discard_tl(cpu_cc_dst);
321 if (dead & USES_CC_SRC) {
322 tcg_gen_discard_tl(cpu_cc_src);
324 if (dead & USES_CC_SRC2) {
325 tcg_gen_discard_tl(cpu_cc_src2);
327 if (dead & USES_CC_SRCT) {
328 tcg_gen_discard_tl(s->cc_srcT);
331 if (op == CC_OP_DYNAMIC) {
332 /* The DYNAMIC setting is translator only, and should never be
333 stored. Thus we always consider it clean. */
334 s->cc_op_dirty = false;
335 } else {
336 /* Discard any computed CC_OP value (see shifts). */
337 if (s->cc_op == CC_OP_DYNAMIC) {
338 tcg_gen_discard_i32(cpu_cc_op);
340 s->cc_op_dirty = true;
342 s->cc_op = op;
345 static void gen_update_cc_op(DisasContext *s)
347 if (s->cc_op_dirty) {
348 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
349 s->cc_op_dirty = false;
353 #ifdef TARGET_X86_64
355 #define NB_OP_SIZES 4
357 #else /* !TARGET_X86_64 */
359 #define NB_OP_SIZES 3
361 #endif /* !TARGET_X86_64 */
363 #if HOST_BIG_ENDIAN
364 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
365 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
366 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
367 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
368 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
369 #else
370 #define REG_B_OFFSET 0
371 #define REG_H_OFFSET 1
372 #define REG_W_OFFSET 0
373 #define REG_L_OFFSET 0
374 #define REG_LH_OFFSET 4
375 #endif
377 /* In instruction encodings for byte register accesses the
378 * register number usually indicates "low 8 bits of register N";
379 * however there are some special cases where N 4..7 indicates
380 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
381 * true for this special case, false otherwise.
383 static inline bool byte_reg_is_xH(DisasContext *s, int reg)
385 /* Any time the REX prefix is present, byte registers are uniform */
386 if (reg < 4 || REX_PREFIX(s)) {
387 return false;
389 return true;
392 /* Select the size of a push/pop operation. */
393 static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
395 if (CODE64(s)) {
396 return ot == MO_16 ? MO_16 : MO_64;
397 } else {
398 return ot;
402 /* Select the size of the stack pointer. */
403 static inline MemOp mo_stacksize(DisasContext *s)
405 return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
408 /* Select only size 64 else 32. Used for SSE operand sizes. */
409 static inline MemOp mo_64_32(MemOp ot)
411 #ifdef TARGET_X86_64
412 return ot == MO_64 ? MO_64 : MO_32;
413 #else
414 return MO_32;
415 #endif
418 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
419 byte vs word opcodes. */
420 static inline MemOp mo_b_d(int b, MemOp ot)
422 return b & 1 ? ot : MO_8;
425 /* Select size 8 if lsb of B is clear, else OT capped at 32.
426 Used for decoding operand size of port opcodes. */
427 static inline MemOp mo_b_d32(int b, MemOp ot)
429 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
432 static void gen_op_mov_reg_v(DisasContext *s, MemOp ot, int reg, TCGv t0)
434 switch(ot) {
435 case MO_8:
436 if (!byte_reg_is_xH(s, reg)) {
437 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
438 } else {
439 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
441 break;
442 case MO_16:
443 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
444 break;
445 case MO_32:
446 /* For x86_64, this sets the higher half of register to zero.
447 For i386, this is equivalent to a mov. */
448 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
449 break;
450 #ifdef TARGET_X86_64
451 case MO_64:
452 tcg_gen_mov_tl(cpu_regs[reg], t0);
453 break;
454 #endif
455 default:
456 tcg_abort();
460 static inline
461 void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg)
463 if (ot == MO_8 && byte_reg_is_xH(s, reg)) {
464 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
465 } else {
466 tcg_gen_mov_tl(t0, cpu_regs[reg]);
470 static void gen_add_A0_im(DisasContext *s, int val)
472 tcg_gen_addi_tl(s->A0, s->A0, val);
473 if (!CODE64(s)) {
474 tcg_gen_ext32u_tl(s->A0, s->A0);
478 static inline void gen_op_jmp_v(TCGv dest)
480 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
483 static inline
484 void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val)
486 tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val);
487 gen_op_mov_reg_v(s, size, reg, s->tmp0);
490 static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg)
492 tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0);
493 gen_op_mov_reg_v(s, size, reg, s->tmp0);
496 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
498 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
501 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
503 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
506 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
508 if (d == OR_TMP0) {
509 gen_op_st_v(s, idx, s->T0, s->A0);
510 } else {
511 gen_op_mov_reg_v(s, idx, d, s->T0);
515 static inline void gen_jmp_im(DisasContext *s, target_ulong pc)
517 tcg_gen_movi_tl(s->tmp0, pc);
518 gen_op_jmp_v(s->tmp0);
521 /* Compute SEG:REG into A0. SEG is selected from the override segment
522 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
523 indicate no override. */
524 static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
525 int def_seg, int ovr_seg)
527 switch (aflag) {
528 #ifdef TARGET_X86_64
529 case MO_64:
530 if (ovr_seg < 0) {
531 tcg_gen_mov_tl(s->A0, a0);
532 return;
534 break;
535 #endif
536 case MO_32:
537 /* 32 bit address */
538 if (ovr_seg < 0 && ADDSEG(s)) {
539 ovr_seg = def_seg;
541 if (ovr_seg < 0) {
542 tcg_gen_ext32u_tl(s->A0, a0);
543 return;
545 break;
546 case MO_16:
547 /* 16 bit address */
548 tcg_gen_ext16u_tl(s->A0, a0);
549 a0 = s->A0;
550 if (ovr_seg < 0) {
551 if (ADDSEG(s)) {
552 ovr_seg = def_seg;
553 } else {
554 return;
557 break;
558 default:
559 tcg_abort();
562 if (ovr_seg >= 0) {
563 TCGv seg = cpu_seg_base[ovr_seg];
565 if (aflag == MO_64) {
566 tcg_gen_add_tl(s->A0, a0, seg);
567 } else if (CODE64(s)) {
568 tcg_gen_ext32u_tl(s->A0, a0);
569 tcg_gen_add_tl(s->A0, s->A0, seg);
570 } else {
571 tcg_gen_add_tl(s->A0, a0, seg);
572 tcg_gen_ext32u_tl(s->A0, s->A0);
577 static inline void gen_string_movl_A0_ESI(DisasContext *s)
579 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
582 static inline void gen_string_movl_A0_EDI(DisasContext *s)
584 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
587 static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
589 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
590 tcg_gen_shli_tl(s->T0, s->T0, ot);
593 static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
595 switch (size) {
596 case MO_8:
597 if (sign) {
598 tcg_gen_ext8s_tl(dst, src);
599 } else {
600 tcg_gen_ext8u_tl(dst, src);
602 return dst;
603 case MO_16:
604 if (sign) {
605 tcg_gen_ext16s_tl(dst, src);
606 } else {
607 tcg_gen_ext16u_tl(dst, src);
609 return dst;
610 #ifdef TARGET_X86_64
611 case MO_32:
612 if (sign) {
613 tcg_gen_ext32s_tl(dst, src);
614 } else {
615 tcg_gen_ext32u_tl(dst, src);
617 return dst;
618 #endif
619 default:
620 return src;
624 static void gen_extu(MemOp ot, TCGv reg)
626 gen_ext_tl(reg, reg, ot, false);
629 static void gen_exts(MemOp ot, TCGv reg)
631 gen_ext_tl(reg, reg, ot, true);
634 static inline
635 void gen_op_jnz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
637 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
638 gen_extu(size, s->tmp0);
639 tcg_gen_brcondi_tl(TCG_COND_NE, s->tmp0, 0, label1);
642 static inline
643 void gen_op_jz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
645 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
646 gen_extu(size, s->tmp0);
647 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
650 static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
652 switch (ot) {
653 case MO_8:
654 gen_helper_inb(v, cpu_env, n);
655 break;
656 case MO_16:
657 gen_helper_inw(v, cpu_env, n);
658 break;
659 case MO_32:
660 gen_helper_inl(v, cpu_env, n);
661 break;
662 default:
663 tcg_abort();
667 static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
669 switch (ot) {
670 case MO_8:
671 gen_helper_outb(cpu_env, v, n);
672 break;
673 case MO_16:
674 gen_helper_outw(cpu_env, v, n);
675 break;
676 case MO_32:
677 gen_helper_outl(cpu_env, v, n);
678 break;
679 default:
680 tcg_abort();
685 * Validate that access to [port, port + 1<<ot) is allowed.
686 * Raise #GP, or VMM exit if not.
688 static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
689 uint32_t svm_flags)
691 #ifdef CONFIG_USER_ONLY
693 * We do not implement the ioperm(2) syscall, so the TSS check
694 * will always fail.
696 gen_exception_gpf(s);
697 return false;
698 #else
699 if (PE(s) && (CPL(s) > IOPL(s) || VM86(s))) {
700 gen_helper_check_io(cpu_env, port, tcg_constant_i32(1 << ot));
702 if (GUEST(s)) {
703 target_ulong cur_eip = s->base.pc_next - s->cs_base;
704 target_ulong next_eip = s->pc - s->cs_base;
706 gen_update_cc_op(s);
707 gen_jmp_im(s, cur_eip);
708 if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
709 svm_flags |= SVM_IOIO_REP_MASK;
711 svm_flags |= 1 << (SVM_IOIO_SIZE_SHIFT + ot);
712 gen_helper_svm_check_io(cpu_env, port,
713 tcg_constant_i32(svm_flags),
714 tcg_constant_i32(next_eip - cur_eip));
716 return true;
717 #endif
720 static inline void gen_movs(DisasContext *s, MemOp ot)
722 gen_string_movl_A0_ESI(s);
723 gen_op_ld_v(s, ot, s->T0, s->A0);
724 gen_string_movl_A0_EDI(s);
725 gen_op_st_v(s, ot, s->T0, s->A0);
726 gen_op_movl_T0_Dshift(s, ot);
727 gen_op_add_reg_T0(s, s->aflag, R_ESI);
728 gen_op_add_reg_T0(s, s->aflag, R_EDI);
731 static void gen_op_update1_cc(DisasContext *s)
733 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
736 static void gen_op_update2_cc(DisasContext *s)
738 tcg_gen_mov_tl(cpu_cc_src, s->T1);
739 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
742 static void gen_op_update3_cc(DisasContext *s, TCGv reg)
744 tcg_gen_mov_tl(cpu_cc_src2, reg);
745 tcg_gen_mov_tl(cpu_cc_src, s->T1);
746 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
749 static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
751 tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1);
754 static void gen_op_update_neg_cc(DisasContext *s)
756 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
757 tcg_gen_neg_tl(cpu_cc_src, s->T0);
758 tcg_gen_movi_tl(s->cc_srcT, 0);
761 /* compute all eflags to cc_src */
762 static void gen_compute_eflags(DisasContext *s)
764 TCGv zero, dst, src1, src2;
765 int live, dead;
767 if (s->cc_op == CC_OP_EFLAGS) {
768 return;
770 if (s->cc_op == CC_OP_CLR) {
771 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
772 set_cc_op(s, CC_OP_EFLAGS);
773 return;
776 zero = NULL;
777 dst = cpu_cc_dst;
778 src1 = cpu_cc_src;
779 src2 = cpu_cc_src2;
781 /* Take care to not read values that are not live. */
782 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
783 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
784 if (dead) {
785 zero = tcg_const_tl(0);
786 if (dead & USES_CC_DST) {
787 dst = zero;
789 if (dead & USES_CC_SRC) {
790 src1 = zero;
792 if (dead & USES_CC_SRC2) {
793 src2 = zero;
797 gen_update_cc_op(s);
798 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
799 set_cc_op(s, CC_OP_EFLAGS);
801 if (dead) {
802 tcg_temp_free(zero);
806 typedef struct CCPrepare {
807 TCGCond cond;
808 TCGv reg;
809 TCGv reg2;
810 target_ulong imm;
811 target_ulong mask;
812 bool use_reg2;
813 bool no_setcond;
814 } CCPrepare;
816 /* compute eflags.C to reg */
817 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
819 TCGv t0, t1;
820 int size, shift;
822 switch (s->cc_op) {
823 case CC_OP_SUBB ... CC_OP_SUBQ:
824 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
825 size = s->cc_op - CC_OP_SUBB;
826 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
827 /* If no temporary was used, be careful not to alias t1 and t0. */
828 t0 = t1 == cpu_cc_src ? s->tmp0 : reg;
829 tcg_gen_mov_tl(t0, s->cc_srcT);
830 gen_extu(size, t0);
831 goto add_sub;
833 case CC_OP_ADDB ... CC_OP_ADDQ:
834 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
835 size = s->cc_op - CC_OP_ADDB;
836 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
837 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
838 add_sub:
839 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
840 .reg2 = t1, .mask = -1, .use_reg2 = true };
842 case CC_OP_LOGICB ... CC_OP_LOGICQ:
843 case CC_OP_CLR:
844 case CC_OP_POPCNT:
845 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
847 case CC_OP_INCB ... CC_OP_INCQ:
848 case CC_OP_DECB ... CC_OP_DECQ:
849 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
850 .mask = -1, .no_setcond = true };
852 case CC_OP_SHLB ... CC_OP_SHLQ:
853 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
854 size = s->cc_op - CC_OP_SHLB;
855 shift = (8 << size) - 1;
856 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
857 .mask = (target_ulong)1 << shift };
859 case CC_OP_MULB ... CC_OP_MULQ:
860 return (CCPrepare) { .cond = TCG_COND_NE,
861 .reg = cpu_cc_src, .mask = -1 };
863 case CC_OP_BMILGB ... CC_OP_BMILGQ:
864 size = s->cc_op - CC_OP_BMILGB;
865 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
866 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
868 case CC_OP_ADCX:
869 case CC_OP_ADCOX:
870 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
871 .mask = -1, .no_setcond = true };
873 case CC_OP_EFLAGS:
874 case CC_OP_SARB ... CC_OP_SARQ:
875 /* CC_SRC & 1 */
876 return (CCPrepare) { .cond = TCG_COND_NE,
877 .reg = cpu_cc_src, .mask = CC_C };
879 default:
880 /* The need to compute only C from CC_OP_DYNAMIC is important
881 in efficiently implementing e.g. INC at the start of a TB. */
882 gen_update_cc_op(s);
883 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
884 cpu_cc_src2, cpu_cc_op);
885 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
886 .mask = -1, .no_setcond = true };
890 /* compute eflags.P to reg */
891 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
893 gen_compute_eflags(s);
894 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
895 .mask = CC_P };
898 /* compute eflags.S to reg */
899 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
901 switch (s->cc_op) {
902 case CC_OP_DYNAMIC:
903 gen_compute_eflags(s);
904 /* FALLTHRU */
905 case CC_OP_EFLAGS:
906 case CC_OP_ADCX:
907 case CC_OP_ADOX:
908 case CC_OP_ADCOX:
909 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
910 .mask = CC_S };
911 case CC_OP_CLR:
912 case CC_OP_POPCNT:
913 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
914 default:
916 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
917 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
918 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
923 /* compute eflags.O to reg */
924 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
926 switch (s->cc_op) {
927 case CC_OP_ADOX:
928 case CC_OP_ADCOX:
929 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
930 .mask = -1, .no_setcond = true };
931 case CC_OP_CLR:
932 case CC_OP_POPCNT:
933 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
934 default:
935 gen_compute_eflags(s);
936 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
937 .mask = CC_O };
941 /* compute eflags.Z to reg */
942 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
944 switch (s->cc_op) {
945 case CC_OP_DYNAMIC:
946 gen_compute_eflags(s);
947 /* FALLTHRU */
948 case CC_OP_EFLAGS:
949 case CC_OP_ADCX:
950 case CC_OP_ADOX:
951 case CC_OP_ADCOX:
952 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
953 .mask = CC_Z };
954 case CC_OP_CLR:
955 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
956 case CC_OP_POPCNT:
957 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
958 .mask = -1 };
959 default:
961 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
962 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
963 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
968 /* perform a conditional store into register 'reg' according to jump opcode
969 value 'b'. In the fast case, T0 is guaranted not to be used. */
970 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
972 int inv, jcc_op, cond;
973 MemOp size;
974 CCPrepare cc;
975 TCGv t0;
977 inv = b & 1;
978 jcc_op = (b >> 1) & 7;
980 switch (s->cc_op) {
981 case CC_OP_SUBB ... CC_OP_SUBQ:
982 /* We optimize relational operators for the cmp/jcc case. */
983 size = s->cc_op - CC_OP_SUBB;
984 switch (jcc_op) {
985 case JCC_BE:
986 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
987 gen_extu(size, s->tmp4);
988 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
989 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4,
990 .reg2 = t0, .mask = -1, .use_reg2 = true };
991 break;
993 case JCC_L:
994 cond = TCG_COND_LT;
995 goto fast_jcc_l;
996 case JCC_LE:
997 cond = TCG_COND_LE;
998 fast_jcc_l:
999 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
1000 gen_exts(size, s->tmp4);
1001 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true);
1002 cc = (CCPrepare) { .cond = cond, .reg = s->tmp4,
1003 .reg2 = t0, .mask = -1, .use_reg2 = true };
1004 break;
1006 default:
1007 goto slow_jcc;
1009 break;
1011 default:
1012 slow_jcc:
1013 /* This actually generates good code for JC, JZ and JS. */
1014 switch (jcc_op) {
1015 case JCC_O:
1016 cc = gen_prepare_eflags_o(s, reg);
1017 break;
1018 case JCC_B:
1019 cc = gen_prepare_eflags_c(s, reg);
1020 break;
1021 case JCC_Z:
1022 cc = gen_prepare_eflags_z(s, reg);
1023 break;
1024 case JCC_BE:
1025 gen_compute_eflags(s);
1026 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1027 .mask = CC_Z | CC_C };
1028 break;
1029 case JCC_S:
1030 cc = gen_prepare_eflags_s(s, reg);
1031 break;
1032 case JCC_P:
1033 cc = gen_prepare_eflags_p(s, reg);
1034 break;
1035 case JCC_L:
1036 gen_compute_eflags(s);
1037 if (reg == cpu_cc_src) {
1038 reg = s->tmp0;
1040 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1041 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1042 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1043 .mask = CC_S };
1044 break;
1045 default:
1046 case JCC_LE:
1047 gen_compute_eflags(s);
1048 if (reg == cpu_cc_src) {
1049 reg = s->tmp0;
1051 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1052 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1053 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1054 .mask = CC_S | CC_Z };
1055 break;
1057 break;
1060 if (inv) {
1061 cc.cond = tcg_invert_cond(cc.cond);
1063 return cc;
1066 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1068 CCPrepare cc = gen_prepare_cc(s, b, reg);
1070 if (cc.no_setcond) {
1071 if (cc.cond == TCG_COND_EQ) {
1072 tcg_gen_xori_tl(reg, cc.reg, 1);
1073 } else {
1074 tcg_gen_mov_tl(reg, cc.reg);
1076 return;
1079 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1080 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1081 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1082 tcg_gen_andi_tl(reg, reg, 1);
1083 return;
1085 if (cc.mask != -1) {
1086 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1087 cc.reg = reg;
1089 if (cc.use_reg2) {
1090 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1091 } else {
1092 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1096 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1098 gen_setcc1(s, JCC_B << 1, reg);
1101 /* generate a conditional jump to label 'l1' according to jump opcode
1102 value 'b'. In the fast case, T0 is guaranted not to be used. */
1103 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1105 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1107 if (cc.mask != -1) {
1108 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1109 cc.reg = s->T0;
1111 if (cc.use_reg2) {
1112 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1113 } else {
1114 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1118 /* Generate a conditional jump to label 'l1' according to jump opcode
1119 value 'b'. In the fast case, T0 is guaranted not to be used.
1120 A translation block must end soon. */
1121 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1123 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1125 gen_update_cc_op(s);
1126 if (cc.mask != -1) {
1127 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1128 cc.reg = s->T0;
1130 set_cc_op(s, CC_OP_DYNAMIC);
1131 if (cc.use_reg2) {
1132 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1133 } else {
1134 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1138 /* XXX: does not work with gdbstub "ice" single step - not a
1139 serious problem */
1140 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1142 TCGLabel *l1 = gen_new_label();
1143 TCGLabel *l2 = gen_new_label();
1144 gen_op_jnz_ecx(s, s->aflag, l1);
1145 gen_set_label(l2);
1146 gen_jmp_tb(s, next_eip, 1);
1147 gen_set_label(l1);
1148 return l2;
1151 static inline void gen_stos(DisasContext *s, MemOp ot)
1153 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
1154 gen_string_movl_A0_EDI(s);
1155 gen_op_st_v(s, ot, s->T0, s->A0);
1156 gen_op_movl_T0_Dshift(s, ot);
1157 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1160 static inline void gen_lods(DisasContext *s, MemOp ot)
1162 gen_string_movl_A0_ESI(s);
1163 gen_op_ld_v(s, ot, s->T0, s->A0);
1164 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
1165 gen_op_movl_T0_Dshift(s, ot);
1166 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1169 static inline void gen_scas(DisasContext *s, MemOp ot)
1171 gen_string_movl_A0_EDI(s);
1172 gen_op_ld_v(s, ot, s->T1, s->A0);
1173 gen_op(s, OP_CMPL, ot, R_EAX);
1174 gen_op_movl_T0_Dshift(s, ot);
1175 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1178 static inline void gen_cmps(DisasContext *s, MemOp ot)
1180 gen_string_movl_A0_EDI(s);
1181 gen_op_ld_v(s, ot, s->T1, s->A0);
1182 gen_string_movl_A0_ESI(s);
1183 gen_op(s, OP_CMPL, ot, OR_TMP0);
1184 gen_op_movl_T0_Dshift(s, ot);
1185 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1186 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1189 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1191 if (s->flags & HF_IOBPT_MASK) {
1192 #ifdef CONFIG_USER_ONLY
1193 /* user-mode cpu should not be in IOBPT mode */
1194 g_assert_not_reached();
1195 #else
1196 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1197 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1199 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1200 tcg_temp_free_i32(t_size);
1201 tcg_temp_free(t_next);
1202 #endif /* CONFIG_USER_ONLY */
1206 static inline void gen_ins(DisasContext *s, MemOp ot)
1208 gen_string_movl_A0_EDI(s);
1209 /* Note: we must do this dummy write first to be restartable in
1210 case of page fault. */
1211 tcg_gen_movi_tl(s->T0, 0);
1212 gen_op_st_v(s, ot, s->T0, s->A0);
1213 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1214 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1215 gen_helper_in_func(ot, s->T0, s->tmp2_i32);
1216 gen_op_st_v(s, ot, s->T0, s->A0);
1217 gen_op_movl_T0_Dshift(s, ot);
1218 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1219 gen_bpt_io(s, s->tmp2_i32, ot);
1222 static inline void gen_outs(DisasContext *s, MemOp ot)
1224 gen_string_movl_A0_ESI(s);
1225 gen_op_ld_v(s, ot, s->T0, s->A0);
1227 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1228 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1229 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0);
1230 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
1231 gen_op_movl_T0_Dshift(s, ot);
1232 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1233 gen_bpt_io(s, s->tmp2_i32, ot);
1236 /* same method as Valgrind : we generate jumps to current or next
1237 instruction */
1238 #define GEN_REPZ(op) \
1239 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1240 target_ulong cur_eip, target_ulong next_eip) \
1242 TCGLabel *l2; \
1243 gen_update_cc_op(s); \
1244 l2 = gen_jz_ecx_string(s, next_eip); \
1245 gen_ ## op(s, ot); \
1246 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1247 /* a loop would cause two single step exceptions if ECX = 1 \
1248 before rep string_insn */ \
1249 if (s->repz_opt) \
1250 gen_op_jz_ecx(s, s->aflag, l2); \
1251 gen_jmp(s, cur_eip); \
1254 #define GEN_REPZ2(op) \
1255 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1256 target_ulong cur_eip, \
1257 target_ulong next_eip, \
1258 int nz) \
1260 TCGLabel *l2; \
1261 gen_update_cc_op(s); \
1262 l2 = gen_jz_ecx_string(s, next_eip); \
1263 gen_ ## op(s, ot); \
1264 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1265 gen_update_cc_op(s); \
1266 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1267 if (s->repz_opt) \
1268 gen_op_jz_ecx(s, s->aflag, l2); \
1269 gen_jmp(s, cur_eip); \
1272 GEN_REPZ(movs)
1273 GEN_REPZ(stos)
1274 GEN_REPZ(lods)
1275 GEN_REPZ(ins)
1276 GEN_REPZ(outs)
1277 GEN_REPZ2(scas)
1278 GEN_REPZ2(cmps)
1280 static void gen_helper_fp_arith_ST0_FT0(int op)
1282 switch (op) {
1283 case 0:
1284 gen_helper_fadd_ST0_FT0(cpu_env);
1285 break;
1286 case 1:
1287 gen_helper_fmul_ST0_FT0(cpu_env);
1288 break;
1289 case 2:
1290 gen_helper_fcom_ST0_FT0(cpu_env);
1291 break;
1292 case 3:
1293 gen_helper_fcom_ST0_FT0(cpu_env);
1294 break;
1295 case 4:
1296 gen_helper_fsub_ST0_FT0(cpu_env);
1297 break;
1298 case 5:
1299 gen_helper_fsubr_ST0_FT0(cpu_env);
1300 break;
1301 case 6:
1302 gen_helper_fdiv_ST0_FT0(cpu_env);
1303 break;
1304 case 7:
1305 gen_helper_fdivr_ST0_FT0(cpu_env);
1306 break;
1310 /* NOTE the exception in "r" op ordering */
1311 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1313 TCGv_i32 tmp = tcg_const_i32(opreg);
1314 switch (op) {
1315 case 0:
1316 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1317 break;
1318 case 1:
1319 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1320 break;
1321 case 4:
1322 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1323 break;
1324 case 5:
1325 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1326 break;
1327 case 6:
1328 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1329 break;
1330 case 7:
1331 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1332 break;
1336 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
1338 gen_update_cc_op(s);
1339 gen_jmp_im(s, cur_eip);
1340 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
1341 s->base.is_jmp = DISAS_NORETURN;
1344 /* Generate #UD for the current instruction. The assumption here is that
1345 the instruction is known, but it isn't allowed in the current cpu mode. */
1346 static void gen_illegal_opcode(DisasContext *s)
1348 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
1351 /* Generate #GP for the current instruction. */
1352 static void gen_exception_gpf(DisasContext *s)
1354 gen_exception(s, EXCP0D_GPF, s->pc_start - s->cs_base);
1357 /* Check for cpl == 0; if not, raise #GP and return false. */
1358 static bool check_cpl0(DisasContext *s)
1360 if (CPL(s) == 0) {
1361 return true;
1363 gen_exception_gpf(s);
1364 return false;
1367 /* If vm86, check for iopl == 3; if not, raise #GP and return false. */
1368 static bool check_vm86_iopl(DisasContext *s)
1370 if (!VM86(s) || IOPL(s) == 3) {
1371 return true;
1373 gen_exception_gpf(s);
1374 return false;
1377 /* Check for iopl allowing access; if not, raise #GP and return false. */
1378 static bool check_iopl(DisasContext *s)
1380 if (VM86(s) ? IOPL(s) == 3 : CPL(s) <= IOPL(s)) {
1381 return true;
1383 gen_exception_gpf(s);
1384 return false;
1387 /* if d == OR_TMP0, it means memory operand (address in A0) */
1388 static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
1390 if (d != OR_TMP0) {
1391 if (s1->prefix & PREFIX_LOCK) {
1392 /* Lock prefix when destination is not memory. */
1393 gen_illegal_opcode(s1);
1394 return;
1396 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1397 } else if (!(s1->prefix & PREFIX_LOCK)) {
1398 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1400 switch(op) {
1401 case OP_ADCL:
1402 gen_compute_eflags_c(s1, s1->tmp4);
1403 if (s1->prefix & PREFIX_LOCK) {
1404 tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1);
1405 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1406 s1->mem_index, ot | MO_LE);
1407 } else {
1408 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1409 tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4);
1410 gen_op_st_rm_T0_A0(s1, ot, d);
1412 gen_op_update3_cc(s1, s1->tmp4);
1413 set_cc_op(s1, CC_OP_ADCB + ot);
1414 break;
1415 case OP_SBBL:
1416 gen_compute_eflags_c(s1, s1->tmp4);
1417 if (s1->prefix & PREFIX_LOCK) {
1418 tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4);
1419 tcg_gen_neg_tl(s1->T0, s1->T0);
1420 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1421 s1->mem_index, ot | MO_LE);
1422 } else {
1423 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1424 tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4);
1425 gen_op_st_rm_T0_A0(s1, ot, d);
1427 gen_op_update3_cc(s1, s1->tmp4);
1428 set_cc_op(s1, CC_OP_SBBB + ot);
1429 break;
1430 case OP_ADDL:
1431 if (s1->prefix & PREFIX_LOCK) {
1432 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1,
1433 s1->mem_index, ot | MO_LE);
1434 } else {
1435 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1436 gen_op_st_rm_T0_A0(s1, ot, d);
1438 gen_op_update2_cc(s1);
1439 set_cc_op(s1, CC_OP_ADDB + ot);
1440 break;
1441 case OP_SUBL:
1442 if (s1->prefix & PREFIX_LOCK) {
1443 tcg_gen_neg_tl(s1->T0, s1->T1);
1444 tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
1445 s1->mem_index, ot | MO_LE);
1446 tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
1447 } else {
1448 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1449 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1450 gen_op_st_rm_T0_A0(s1, ot, d);
1452 gen_op_update2_cc(s1);
1453 set_cc_op(s1, CC_OP_SUBB + ot);
1454 break;
1455 default:
1456 case OP_ANDL:
1457 if (s1->prefix & PREFIX_LOCK) {
1458 tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1,
1459 s1->mem_index, ot | MO_LE);
1460 } else {
1461 tcg_gen_and_tl(s1->T0, s1->T0, s1->T1);
1462 gen_op_st_rm_T0_A0(s1, ot, d);
1464 gen_op_update1_cc(s1);
1465 set_cc_op(s1, CC_OP_LOGICB + ot);
1466 break;
1467 case OP_ORL:
1468 if (s1->prefix & PREFIX_LOCK) {
1469 tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1,
1470 s1->mem_index, ot | MO_LE);
1471 } else {
1472 tcg_gen_or_tl(s1->T0, s1->T0, s1->T1);
1473 gen_op_st_rm_T0_A0(s1, ot, d);
1475 gen_op_update1_cc(s1);
1476 set_cc_op(s1, CC_OP_LOGICB + ot);
1477 break;
1478 case OP_XORL:
1479 if (s1->prefix & PREFIX_LOCK) {
1480 tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1,
1481 s1->mem_index, ot | MO_LE);
1482 } else {
1483 tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1);
1484 gen_op_st_rm_T0_A0(s1, ot, d);
1486 gen_op_update1_cc(s1);
1487 set_cc_op(s1, CC_OP_LOGICB + ot);
1488 break;
1489 case OP_CMPL:
1490 tcg_gen_mov_tl(cpu_cc_src, s1->T1);
1491 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1492 tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
1493 set_cc_op(s1, CC_OP_SUBB + ot);
1494 break;
1498 /* if d == OR_TMP0, it means memory operand (address in A0) */
1499 static void gen_inc(DisasContext *s1, MemOp ot, int d, int c)
1501 if (s1->prefix & PREFIX_LOCK) {
1502 if (d != OR_TMP0) {
1503 /* Lock prefix when destination is not memory */
1504 gen_illegal_opcode(s1);
1505 return;
1507 tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
1508 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1509 s1->mem_index, ot | MO_LE);
1510 } else {
1511 if (d != OR_TMP0) {
1512 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1513 } else {
1514 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1516 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
1517 gen_op_st_rm_T0_A0(s1, ot, d);
1520 gen_compute_eflags_c(s1, cpu_cc_src);
1521 tcg_gen_mov_tl(cpu_cc_dst, s1->T0);
1522 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1525 static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
1526 TCGv shm1, TCGv count, bool is_right)
1528 TCGv_i32 z32, s32, oldop;
1529 TCGv z_tl;
1531 /* Store the results into the CC variables. If we know that the
1532 variable must be dead, store unconditionally. Otherwise we'll
1533 need to not disrupt the current contents. */
1534 z_tl = tcg_const_tl(0);
1535 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1536 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1537 result, cpu_cc_dst);
1538 } else {
1539 tcg_gen_mov_tl(cpu_cc_dst, result);
1541 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1542 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1543 shm1, cpu_cc_src);
1544 } else {
1545 tcg_gen_mov_tl(cpu_cc_src, shm1);
1547 tcg_temp_free(z_tl);
1549 /* Get the two potential CC_OP values into temporaries. */
1550 tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1551 if (s->cc_op == CC_OP_DYNAMIC) {
1552 oldop = cpu_cc_op;
1553 } else {
1554 tcg_gen_movi_i32(s->tmp3_i32, s->cc_op);
1555 oldop = s->tmp3_i32;
1558 /* Conditionally store the CC_OP value. */
1559 z32 = tcg_const_i32(0);
1560 s32 = tcg_temp_new_i32();
1561 tcg_gen_trunc_tl_i32(s32, count);
1562 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop);
1563 tcg_temp_free_i32(z32);
1564 tcg_temp_free_i32(s32);
1566 /* The CC_OP value is no longer predictable. */
1567 set_cc_op(s, CC_OP_DYNAMIC);
1570 static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1,
1571 int is_right, int is_arith)
1573 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1575 /* load */
1576 if (op1 == OR_TMP0) {
1577 gen_op_ld_v(s, ot, s->T0, s->A0);
1578 } else {
1579 gen_op_mov_v_reg(s, ot, s->T0, op1);
1582 tcg_gen_andi_tl(s->T1, s->T1, mask);
1583 tcg_gen_subi_tl(s->tmp0, s->T1, 1);
1585 if (is_right) {
1586 if (is_arith) {
1587 gen_exts(ot, s->T0);
1588 tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0);
1589 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
1590 } else {
1591 gen_extu(ot, s->T0);
1592 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1593 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
1595 } else {
1596 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1597 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
1600 /* store */
1601 gen_op_st_rm_T0_A0(s, ot, op1);
1603 gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right);
1606 static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1607 int is_right, int is_arith)
1609 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1611 /* load */
1612 if (op1 == OR_TMP0)
1613 gen_op_ld_v(s, ot, s->T0, s->A0);
1614 else
1615 gen_op_mov_v_reg(s, ot, s->T0, op1);
1617 op2 &= mask;
1618 if (op2 != 0) {
1619 if (is_right) {
1620 if (is_arith) {
1621 gen_exts(ot, s->T0);
1622 tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1);
1623 tcg_gen_sari_tl(s->T0, s->T0, op2);
1624 } else {
1625 gen_extu(ot, s->T0);
1626 tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1);
1627 tcg_gen_shri_tl(s->T0, s->T0, op2);
1629 } else {
1630 tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1);
1631 tcg_gen_shli_tl(s->T0, s->T0, op2);
1635 /* store */
1636 gen_op_st_rm_T0_A0(s, ot, op1);
1638 /* update eflags if non zero shift */
1639 if (op2 != 0) {
1640 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
1641 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
1642 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1646 static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right)
1648 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1649 TCGv_i32 t0, t1;
1651 /* load */
1652 if (op1 == OR_TMP0) {
1653 gen_op_ld_v(s, ot, s->T0, s->A0);
1654 } else {
1655 gen_op_mov_v_reg(s, ot, s->T0, op1);
1658 tcg_gen_andi_tl(s->T1, s->T1, mask);
1660 switch (ot) {
1661 case MO_8:
1662 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1663 tcg_gen_ext8u_tl(s->T0, s->T0);
1664 tcg_gen_muli_tl(s->T0, s->T0, 0x01010101);
1665 goto do_long;
1666 case MO_16:
1667 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1668 tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16);
1669 goto do_long;
1670 do_long:
1671 #ifdef TARGET_X86_64
1672 case MO_32:
1673 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1674 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
1675 if (is_right) {
1676 tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1677 } else {
1678 tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1680 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1681 break;
1682 #endif
1683 default:
1684 if (is_right) {
1685 tcg_gen_rotr_tl(s->T0, s->T0, s->T1);
1686 } else {
1687 tcg_gen_rotl_tl(s->T0, s->T0, s->T1);
1689 break;
1692 /* store */
1693 gen_op_st_rm_T0_A0(s, ot, op1);
1695 /* We'll need the flags computed into CC_SRC. */
1696 gen_compute_eflags(s);
1698 /* The value that was "rotated out" is now present at the other end
1699 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1700 since we've computed the flags into CC_SRC, these variables are
1701 currently dead. */
1702 if (is_right) {
1703 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1704 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1705 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1706 } else {
1707 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1708 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1710 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1711 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1713 /* Now conditionally store the new CC_OP value. If the shift count
1714 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1715 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1716 exactly as we computed above. */
1717 t0 = tcg_const_i32(0);
1718 t1 = tcg_temp_new_i32();
1719 tcg_gen_trunc_tl_i32(t1, s->T1);
1720 tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX);
1721 tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS);
1722 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1723 s->tmp2_i32, s->tmp3_i32);
1724 tcg_temp_free_i32(t0);
1725 tcg_temp_free_i32(t1);
1727 /* The CC_OP value is no longer predictable. */
1728 set_cc_op(s, CC_OP_DYNAMIC);
1731 static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1732 int is_right)
1734 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1735 int shift;
1737 /* load */
1738 if (op1 == OR_TMP0) {
1739 gen_op_ld_v(s, ot, s->T0, s->A0);
1740 } else {
1741 gen_op_mov_v_reg(s, ot, s->T0, op1);
1744 op2 &= mask;
1745 if (op2 != 0) {
1746 switch (ot) {
1747 #ifdef TARGET_X86_64
1748 case MO_32:
1749 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1750 if (is_right) {
1751 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2);
1752 } else {
1753 tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2);
1755 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1756 break;
1757 #endif
1758 default:
1759 if (is_right) {
1760 tcg_gen_rotri_tl(s->T0, s->T0, op2);
1761 } else {
1762 tcg_gen_rotli_tl(s->T0, s->T0, op2);
1764 break;
1765 case MO_8:
1766 mask = 7;
1767 goto do_shifts;
1768 case MO_16:
1769 mask = 15;
1770 do_shifts:
1771 shift = op2 & mask;
1772 if (is_right) {
1773 shift = mask + 1 - shift;
1775 gen_extu(ot, s->T0);
1776 tcg_gen_shli_tl(s->tmp0, s->T0, shift);
1777 tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift);
1778 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
1779 break;
1783 /* store */
1784 gen_op_st_rm_T0_A0(s, ot, op1);
1786 if (op2 != 0) {
1787 /* Compute the flags into CC_SRC. */
1788 gen_compute_eflags(s);
1790 /* The value that was "rotated out" is now present at the other end
1791 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1792 since we've computed the flags into CC_SRC, these variables are
1793 currently dead. */
1794 if (is_right) {
1795 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1796 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1797 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1798 } else {
1799 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1800 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1802 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1803 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1804 set_cc_op(s, CC_OP_ADCOX);
1808 /* XXX: add faster immediate = 1 case */
1809 static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
1810 int is_right)
1812 gen_compute_eflags(s);
1813 assert(s->cc_op == CC_OP_EFLAGS);
1815 /* load */
1816 if (op1 == OR_TMP0)
1817 gen_op_ld_v(s, ot, s->T0, s->A0);
1818 else
1819 gen_op_mov_v_reg(s, ot, s->T0, op1);
1821 if (is_right) {
1822 switch (ot) {
1823 case MO_8:
1824 gen_helper_rcrb(s->T0, cpu_env, s->T0, s->T1);
1825 break;
1826 case MO_16:
1827 gen_helper_rcrw(s->T0, cpu_env, s->T0, s->T1);
1828 break;
1829 case MO_32:
1830 gen_helper_rcrl(s->T0, cpu_env, s->T0, s->T1);
1831 break;
1832 #ifdef TARGET_X86_64
1833 case MO_64:
1834 gen_helper_rcrq(s->T0, cpu_env, s->T0, s->T1);
1835 break;
1836 #endif
1837 default:
1838 tcg_abort();
1840 } else {
1841 switch (ot) {
1842 case MO_8:
1843 gen_helper_rclb(s->T0, cpu_env, s->T0, s->T1);
1844 break;
1845 case MO_16:
1846 gen_helper_rclw(s->T0, cpu_env, s->T0, s->T1);
1847 break;
1848 case MO_32:
1849 gen_helper_rcll(s->T0, cpu_env, s->T0, s->T1);
1850 break;
1851 #ifdef TARGET_X86_64
1852 case MO_64:
1853 gen_helper_rclq(s->T0, cpu_env, s->T0, s->T1);
1854 break;
1855 #endif
1856 default:
1857 tcg_abort();
1860 /* store */
1861 gen_op_st_rm_T0_A0(s, ot, op1);
1864 /* XXX: add faster immediate case */
1865 static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
1866 bool is_right, TCGv count_in)
1868 target_ulong mask = (ot == MO_64 ? 63 : 31);
1869 TCGv count;
1871 /* load */
1872 if (op1 == OR_TMP0) {
1873 gen_op_ld_v(s, ot, s->T0, s->A0);
1874 } else {
1875 gen_op_mov_v_reg(s, ot, s->T0, op1);
1878 count = tcg_temp_new();
1879 tcg_gen_andi_tl(count, count_in, mask);
1881 switch (ot) {
1882 case MO_16:
1883 /* Note: we implement the Intel behaviour for shift count > 16.
1884 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1885 portion by constructing it as a 32-bit value. */
1886 if (is_right) {
1887 tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16);
1888 tcg_gen_mov_tl(s->T1, s->T0);
1889 tcg_gen_mov_tl(s->T0, s->tmp0);
1890 } else {
1891 tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
1894 * If TARGET_X86_64 defined then fall through into MO_32 case,
1895 * otherwise fall through default case.
1897 case MO_32:
1898 #ifdef TARGET_X86_64
1899 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1900 tcg_gen_subi_tl(s->tmp0, count, 1);
1901 if (is_right) {
1902 tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1);
1903 tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0);
1904 tcg_gen_shr_i64(s->T0, s->T0, count);
1905 } else {
1906 tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0);
1907 tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0);
1908 tcg_gen_shl_i64(s->T0, s->T0, count);
1909 tcg_gen_shri_i64(s->tmp0, s->tmp0, 32);
1910 tcg_gen_shri_i64(s->T0, s->T0, 32);
1912 break;
1913 #endif
1914 default:
1915 tcg_gen_subi_tl(s->tmp0, count, 1);
1916 if (is_right) {
1917 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1919 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1920 tcg_gen_shr_tl(s->T0, s->T0, count);
1921 tcg_gen_shl_tl(s->T1, s->T1, s->tmp4);
1922 } else {
1923 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1924 if (ot == MO_16) {
1925 /* Only needed if count > 16, for Intel behaviour. */
1926 tcg_gen_subfi_tl(s->tmp4, 33, count);
1927 tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4);
1928 tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4);
1931 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1932 tcg_gen_shl_tl(s->T0, s->T0, count);
1933 tcg_gen_shr_tl(s->T1, s->T1, s->tmp4);
1935 tcg_gen_movi_tl(s->tmp4, 0);
1936 tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4,
1937 s->tmp4, s->T1);
1938 tcg_gen_or_tl(s->T0, s->T0, s->T1);
1939 break;
1942 /* store */
1943 gen_op_st_rm_T0_A0(s, ot, op1);
1945 gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
1946 tcg_temp_free(count);
1949 static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s)
1951 if (s != OR_TMP1)
1952 gen_op_mov_v_reg(s1, ot, s1->T1, s);
1953 switch(op) {
1954 case OP_ROL:
1955 gen_rot_rm_T1(s1, ot, d, 0);
1956 break;
1957 case OP_ROR:
1958 gen_rot_rm_T1(s1, ot, d, 1);
1959 break;
1960 case OP_SHL:
1961 case OP_SHL1:
1962 gen_shift_rm_T1(s1, ot, d, 0, 0);
1963 break;
1964 case OP_SHR:
1965 gen_shift_rm_T1(s1, ot, d, 1, 0);
1966 break;
1967 case OP_SAR:
1968 gen_shift_rm_T1(s1, ot, d, 1, 1);
1969 break;
1970 case OP_RCL:
1971 gen_rotc_rm_T1(s1, ot, d, 0);
1972 break;
1973 case OP_RCR:
1974 gen_rotc_rm_T1(s1, ot, d, 1);
1975 break;
1979 static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c)
1981 switch(op) {
1982 case OP_ROL:
1983 gen_rot_rm_im(s1, ot, d, c, 0);
1984 break;
1985 case OP_ROR:
1986 gen_rot_rm_im(s1, ot, d, c, 1);
1987 break;
1988 case OP_SHL:
1989 case OP_SHL1:
1990 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1991 break;
1992 case OP_SHR:
1993 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1994 break;
1995 case OP_SAR:
1996 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1997 break;
1998 default:
1999 /* currently not optimized */
2000 tcg_gen_movi_tl(s1->T1, c);
2001 gen_shift(s1, op, ot, d, OR_TMP1);
2002 break;
2006 #define X86_MAX_INSN_LENGTH 15
2008 static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
2010 uint64_t pc = s->pc;
2012 /* This is a subsequent insn that crosses a page boundary. */
2013 if (s->base.num_insns > 1 &&
2014 !is_same_page(&s->base, s->pc + num_bytes - 1)) {
2015 siglongjmp(s->jmpbuf, 2);
2018 s->pc += num_bytes;
2019 if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
2020 /* If the instruction's 16th byte is on a different page than the 1st, a
2021 * page fault on the second page wins over the general protection fault
2022 * caused by the instruction being too long.
2023 * This can happen even if the operand is only one byte long!
2025 if (((s->pc - 1) ^ (pc - 1)) & TARGET_PAGE_MASK) {
2026 volatile uint8_t unused =
2027 cpu_ldub_code(env, (s->pc - 1) & TARGET_PAGE_MASK);
2028 (void) unused;
2030 siglongjmp(s->jmpbuf, 1);
2033 return pc;
2036 static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
2038 return translator_ldub(env, &s->base, advance_pc(env, s, 1));
2041 static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
2043 return translator_lduw(env, &s->base, advance_pc(env, s, 2));
2046 static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
2048 return translator_lduw(env, &s->base, advance_pc(env, s, 2));
2051 static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
2053 return translator_ldl(env, &s->base, advance_pc(env, s, 4));
2056 #ifdef TARGET_X86_64
2057 static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
2059 return translator_ldq(env, &s->base, advance_pc(env, s, 8));
2061 #endif
2063 /* Decompose an address. */
2065 typedef struct AddressParts {
2066 int def_seg;
2067 int base;
2068 int index;
2069 int scale;
2070 target_long disp;
2071 } AddressParts;
2073 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
2074 int modrm)
2076 int def_seg, base, index, scale, mod, rm;
2077 target_long disp;
2078 bool havesib;
2080 def_seg = R_DS;
2081 index = -1;
2082 scale = 0;
2083 disp = 0;
2085 mod = (modrm >> 6) & 3;
2086 rm = modrm & 7;
2087 base = rm | REX_B(s);
2089 if (mod == 3) {
2090 /* Normally filtered out earlier, but including this path
2091 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
2092 goto done;
2095 switch (s->aflag) {
2096 case MO_64:
2097 case MO_32:
2098 havesib = 0;
2099 if (rm == 4) {
2100 int code = x86_ldub_code(env, s);
2101 scale = (code >> 6) & 3;
2102 index = ((code >> 3) & 7) | REX_X(s);
2103 if (index == 4) {
2104 index = -1; /* no index */
2106 base = (code & 7) | REX_B(s);
2107 havesib = 1;
2110 switch (mod) {
2111 case 0:
2112 if ((base & 7) == 5) {
2113 base = -1;
2114 disp = (int32_t)x86_ldl_code(env, s);
2115 if (CODE64(s) && !havesib) {
2116 base = -2;
2117 disp += s->pc + s->rip_offset;
2120 break;
2121 case 1:
2122 disp = (int8_t)x86_ldub_code(env, s);
2123 break;
2124 default:
2125 case 2:
2126 disp = (int32_t)x86_ldl_code(env, s);
2127 break;
2130 /* For correct popl handling with esp. */
2131 if (base == R_ESP && s->popl_esp_hack) {
2132 disp += s->popl_esp_hack;
2134 if (base == R_EBP || base == R_ESP) {
2135 def_seg = R_SS;
2137 break;
2139 case MO_16:
2140 if (mod == 0) {
2141 if (rm == 6) {
2142 base = -1;
2143 disp = x86_lduw_code(env, s);
2144 break;
2146 } else if (mod == 1) {
2147 disp = (int8_t)x86_ldub_code(env, s);
2148 } else {
2149 disp = (int16_t)x86_lduw_code(env, s);
2152 switch (rm) {
2153 case 0:
2154 base = R_EBX;
2155 index = R_ESI;
2156 break;
2157 case 1:
2158 base = R_EBX;
2159 index = R_EDI;
2160 break;
2161 case 2:
2162 base = R_EBP;
2163 index = R_ESI;
2164 def_seg = R_SS;
2165 break;
2166 case 3:
2167 base = R_EBP;
2168 index = R_EDI;
2169 def_seg = R_SS;
2170 break;
2171 case 4:
2172 base = R_ESI;
2173 break;
2174 case 5:
2175 base = R_EDI;
2176 break;
2177 case 6:
2178 base = R_EBP;
2179 def_seg = R_SS;
2180 break;
2181 default:
2182 case 7:
2183 base = R_EBX;
2184 break;
2186 break;
2188 default:
2189 tcg_abort();
2192 done:
2193 return (AddressParts){ def_seg, base, index, scale, disp };
2196 /* Compute the address, with a minimum number of TCG ops. */
2197 static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a)
2199 TCGv ea = NULL;
2201 if (a.index >= 0) {
2202 if (a.scale == 0) {
2203 ea = cpu_regs[a.index];
2204 } else {
2205 tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale);
2206 ea = s->A0;
2208 if (a.base >= 0) {
2209 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2210 ea = s->A0;
2212 } else if (a.base >= 0) {
2213 ea = cpu_regs[a.base];
2215 if (!ea) {
2216 tcg_gen_movi_tl(s->A0, a.disp);
2217 ea = s->A0;
2218 } else if (a.disp != 0) {
2219 tcg_gen_addi_tl(s->A0, ea, a.disp);
2220 ea = s->A0;
2223 return ea;
2226 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2228 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2229 TCGv ea = gen_lea_modrm_1(s, a);
2230 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2233 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2235 (void)gen_lea_modrm_0(env, s, modrm);
2238 /* Used for BNDCL, BNDCU, BNDCN. */
2239 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2240 TCGCond cond, TCGv_i64 bndv)
2242 TCGv ea = gen_lea_modrm_1(s, gen_lea_modrm_0(env, s, modrm));
2244 tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
2245 if (!CODE64(s)) {
2246 tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64);
2248 tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv);
2249 tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64);
2250 gen_helper_bndck(cpu_env, s->tmp2_i32);
2253 /* used for LEA and MOV AX, mem */
2254 static void gen_add_A0_ds_seg(DisasContext *s)
2256 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
2259 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2260 OR_TMP0 */
2261 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2262 MemOp ot, int reg, int is_store)
2264 int mod, rm;
2266 mod = (modrm >> 6) & 3;
2267 rm = (modrm & 7) | REX_B(s);
2268 if (mod == 3) {
2269 if (is_store) {
2270 if (reg != OR_TMP0)
2271 gen_op_mov_v_reg(s, ot, s->T0, reg);
2272 gen_op_mov_reg_v(s, ot, rm, s->T0);
2273 } else {
2274 gen_op_mov_v_reg(s, ot, s->T0, rm);
2275 if (reg != OR_TMP0)
2276 gen_op_mov_reg_v(s, ot, reg, s->T0);
2278 } else {
2279 gen_lea_modrm(env, s, modrm);
2280 if (is_store) {
2281 if (reg != OR_TMP0)
2282 gen_op_mov_v_reg(s, ot, s->T0, reg);
2283 gen_op_st_v(s, ot, s->T0, s->A0);
2284 } else {
2285 gen_op_ld_v(s, ot, s->T0, s->A0);
2286 if (reg != OR_TMP0)
2287 gen_op_mov_reg_v(s, ot, reg, s->T0);
2292 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
2294 uint32_t ret;
2296 switch (ot) {
2297 case MO_8:
2298 ret = x86_ldub_code(env, s);
2299 break;
2300 case MO_16:
2301 ret = x86_lduw_code(env, s);
2302 break;
2303 case MO_32:
2304 #ifdef TARGET_X86_64
2305 case MO_64:
2306 #endif
2307 ret = x86_ldl_code(env, s);
2308 break;
2309 default:
2310 tcg_abort();
2312 return ret;
2315 static inline int insn_const_size(MemOp ot)
2317 if (ot <= MO_32) {
2318 return 1 << ot;
2319 } else {
2320 return 4;
2324 static void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2326 target_ulong pc = s->cs_base + eip;
2328 if (translator_use_goto_tb(&s->base, pc)) {
2329 /* jump to same page: we can use a direct jump */
2330 tcg_gen_goto_tb(tb_num);
2331 gen_jmp_im(s, eip);
2332 tcg_gen_exit_tb(s->base.tb, tb_num);
2333 s->base.is_jmp = DISAS_NORETURN;
2334 } else {
2335 /* jump to another page */
2336 gen_jmp_im(s, eip);
2337 gen_jr(s, s->tmp0);
2341 static inline void gen_jcc(DisasContext *s, int b,
2342 target_ulong val, target_ulong next_eip)
2344 TCGLabel *l1, *l2;
2346 if (s->jmp_opt) {
2347 l1 = gen_new_label();
2348 gen_jcc1(s, b, l1);
2350 gen_goto_tb(s, 0, next_eip);
2352 gen_set_label(l1);
2353 gen_goto_tb(s, 1, val);
2354 } else {
2355 l1 = gen_new_label();
2356 l2 = gen_new_label();
2357 gen_jcc1(s, b, l1);
2359 gen_jmp_im(s, next_eip);
2360 tcg_gen_br(l2);
2362 gen_set_label(l1);
2363 gen_jmp_im(s, val);
2364 gen_set_label(l2);
2365 gen_eob(s);
2369 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
2370 int modrm, int reg)
2372 CCPrepare cc;
2374 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2376 cc = gen_prepare_cc(s, b, s->T1);
2377 if (cc.mask != -1) {
2378 TCGv t0 = tcg_temp_new();
2379 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2380 cc.reg = t0;
2382 if (!cc.use_reg2) {
2383 cc.reg2 = tcg_const_tl(cc.imm);
2386 tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2,
2387 s->T0, cpu_regs[reg]);
2388 gen_op_mov_reg_v(s, ot, reg, s->T0);
2390 if (cc.mask != -1) {
2391 tcg_temp_free(cc.reg);
2393 if (!cc.use_reg2) {
2394 tcg_temp_free(cc.reg2);
2398 static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg)
2400 tcg_gen_ld32u_tl(s->T0, cpu_env,
2401 offsetof(CPUX86State,segs[seg_reg].selector));
2404 static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg)
2406 tcg_gen_ext16u_tl(s->T0, s->T0);
2407 tcg_gen_st32_tl(s->T0, cpu_env,
2408 offsetof(CPUX86State,segs[seg_reg].selector));
2409 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
2412 /* move T0 to seg_reg and compute if the CPU state may change. Never
2413 call this function with seg_reg == R_CS */
2414 static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg)
2416 if (PE(s) && !VM86(s)) {
2417 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
2418 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), s->tmp2_i32);
2419 /* abort translation because the addseg value may change or
2420 because ss32 may change. For R_SS, translation must always
2421 stop as a special handling must be done to disable hardware
2422 interrupts for the next instruction */
2423 if (seg_reg == R_SS || (CODE32(s) && seg_reg < R_FS)) {
2424 s->base.is_jmp = DISAS_TOO_MANY;
2426 } else {
2427 gen_op_movl_seg_T0_vm(s, seg_reg);
2428 if (seg_reg == R_SS) {
2429 s->base.is_jmp = DISAS_TOO_MANY;
2434 static void gen_svm_check_intercept(DisasContext *s, uint32_t type)
2436 /* no SVM activated; fast case */
2437 if (likely(!GUEST(s))) {
2438 return;
2440 gen_helper_svm_check_intercept(cpu_env, tcg_constant_i32(type));
2443 static inline void gen_stack_update(DisasContext *s, int addend)
2445 gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend);
2448 /* Generate a push. It depends on ss32, addseg and dflag. */
2449 static void gen_push_v(DisasContext *s, TCGv val)
2451 MemOp d_ot = mo_pushpop(s, s->dflag);
2452 MemOp a_ot = mo_stacksize(s);
2453 int size = 1 << d_ot;
2454 TCGv new_esp = s->A0;
2456 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2458 if (!CODE64(s)) {
2459 if (ADDSEG(s)) {
2460 new_esp = s->tmp4;
2461 tcg_gen_mov_tl(new_esp, s->A0);
2463 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2466 gen_op_st_v(s, d_ot, val, s->A0);
2467 gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp);
2470 /* two step pop is necessary for precise exceptions */
2471 static MemOp gen_pop_T0(DisasContext *s)
2473 MemOp d_ot = mo_pushpop(s, s->dflag);
2475 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2476 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2478 return d_ot;
2481 static inline void gen_pop_update(DisasContext *s, MemOp ot)
2483 gen_stack_update(s, 1 << ot);
2486 static inline void gen_stack_A0(DisasContext *s)
2488 gen_lea_v_seg(s, SS32(s) ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2491 static void gen_pusha(DisasContext *s)
2493 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2494 MemOp d_ot = s->dflag;
2495 int size = 1 << d_ot;
2496 int i;
2498 for (i = 0; i < 8; i++) {
2499 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size);
2500 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2501 gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0);
2504 gen_stack_update(s, -8 * size);
2507 static void gen_popa(DisasContext *s)
2509 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2510 MemOp d_ot = s->dflag;
2511 int size = 1 << d_ot;
2512 int i;
2514 for (i = 0; i < 8; i++) {
2515 /* ESP is not reloaded */
2516 if (7 - i == R_ESP) {
2517 continue;
2519 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size);
2520 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2521 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2522 gen_op_mov_reg_v(s, d_ot, 7 - i, s->T0);
2525 gen_stack_update(s, 8 * size);
2528 static void gen_enter(DisasContext *s, int esp_addend, int level)
2530 MemOp d_ot = mo_pushpop(s, s->dflag);
2531 MemOp a_ot = CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
2532 int size = 1 << d_ot;
2534 /* Push BP; compute FrameTemp into T1. */
2535 tcg_gen_subi_tl(s->T1, cpu_regs[R_ESP], size);
2536 gen_lea_v_seg(s, a_ot, s->T1, R_SS, -1);
2537 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0);
2539 level &= 31;
2540 if (level != 0) {
2541 int i;
2543 /* Copy level-1 pointers from the previous frame. */
2544 for (i = 1; i < level; ++i) {
2545 tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i);
2546 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2547 gen_op_ld_v(s, d_ot, s->tmp0, s->A0);
2549 tcg_gen_subi_tl(s->A0, s->T1, size * i);
2550 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2551 gen_op_st_v(s, d_ot, s->tmp0, s->A0);
2554 /* Push the current FrameTemp as the last level. */
2555 tcg_gen_subi_tl(s->A0, s->T1, size * level);
2556 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2557 gen_op_st_v(s, d_ot, s->T1, s->A0);
2560 /* Copy the FrameTemp value to EBP. */
2561 gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
2563 /* Compute the final value of ESP. */
2564 tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
2565 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2568 static void gen_leave(DisasContext *s)
2570 MemOp d_ot = mo_pushpop(s, s->dflag);
2571 MemOp a_ot = mo_stacksize(s);
2573 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2574 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2576 tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot);
2578 gen_op_mov_reg_v(s, d_ot, R_EBP, s->T0);
2579 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2582 /* Similarly, except that the assumption here is that we don't decode
2583 the instruction at all -- either a missing opcode, an unimplemented
2584 feature, or just a bogus instruction stream. */
2585 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2587 gen_illegal_opcode(s);
2589 if (qemu_loglevel_mask(LOG_UNIMP)) {
2590 FILE *logfile = qemu_log_trylock();
2591 if (logfile) {
2592 target_ulong pc = s->pc_start, end = s->pc;
2594 fprintf(logfile, "ILLOPC: " TARGET_FMT_lx ":", pc);
2595 for (; pc < end; ++pc) {
2596 fprintf(logfile, " %02x", cpu_ldub_code(env, pc));
2598 fprintf(logfile, "\n");
2599 qemu_log_unlock(logfile);
2604 /* an interrupt is different from an exception because of the
2605 privilege checks */
2606 static void gen_interrupt(DisasContext *s, int intno,
2607 target_ulong cur_eip, target_ulong next_eip)
2609 gen_update_cc_op(s);
2610 gen_jmp_im(s, cur_eip);
2611 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2612 tcg_const_i32(next_eip - cur_eip));
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 (recheck_tf) {
2673 gen_helper_rechecking_single_step(cpu_env);
2674 tcg_gen_exit_tb(NULL, 0);
2675 } else if (s->flags & HF_TF_MASK) {
2676 gen_helper_single_step(cpu_env);
2677 } else if (jr) {
2678 tcg_gen_lookup_and_goto_ptr();
2679 } else {
2680 tcg_gen_exit_tb(NULL, 0);
2682 s->base.is_jmp = DISAS_NORETURN;
2685 static inline void
2686 gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2688 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2691 /* End of block.
2692 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2693 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2695 gen_eob_worker(s, inhibit, false);
2698 /* End of block, resetting the inhibit irq flag. */
2699 static void gen_eob(DisasContext *s)
2701 gen_eob_worker(s, false, false);
2704 /* Jump to register */
2705 static void gen_jr(DisasContext *s, TCGv dest)
2707 do_gen_eob_worker(s, false, false, true);
2710 /* generate a jump to eip. No segment change must happen before as a
2711 direct call to the next block may occur */
2712 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2714 gen_update_cc_op(s);
2715 set_cc_op(s, CC_OP_DYNAMIC);
2716 if (s->jmp_opt) {
2717 gen_goto_tb(s, tb_num, eip);
2718 } else {
2719 gen_jmp_im(s, eip);
2720 gen_eob(s);
2724 static void gen_jmp(DisasContext *s, target_ulong eip)
2726 gen_jmp_tb(s, eip, 0);
2729 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2731 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
2732 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset);
2735 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2737 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset);
2738 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
2741 static inline void gen_ldo_env_A0(DisasContext *s, int offset, bool align)
2743 int mem_index = s->mem_index;
2744 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index,
2745 MO_LEUQ | (align ? MO_ALIGN_16 : 0));
2746 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2747 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2748 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2749 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2752 static inline void gen_sto_env_A0(DisasContext *s, int offset, bool align)
2754 int mem_index = s->mem_index;
2755 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2756 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index,
2757 MO_LEUQ | (align ? MO_ALIGN_16 : 0));
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_LEUQ);
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 #define ZMM_OFFSET(reg) offsetof(CPUX86State, xmm_regs[reg])
2791 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2792 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2793 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2794 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2795 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2796 typedef void (*SSEFunc_0_eppp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2797 TCGv_ptr reg_c);
2798 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2799 TCGv_i32 val);
2800 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2801 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2802 TCGv val);
2804 #define SSE_OPF_CMP (1 << 1) /* does not write for first operand */
2805 #define SSE_OPF_SPECIAL (1 << 3) /* magic */
2806 #define SSE_OPF_3DNOW (1 << 4) /* 3DNow! instruction */
2807 #define SSE_OPF_MMX (1 << 5) /* MMX/integer/AVX2 instruction */
2808 #define SSE_OPF_SCALAR (1 << 6) /* Has SSE scalar variants */
2809 #define SSE_OPF_SHUF (1 << 9) /* pshufx/shufpx */
2811 #define OP(op, flags, a, b, c, d) \
2812 {flags, {{.op = a}, {.op = b}, {.op = c}, {.op = d} } }
2814 #define MMX_OP(x) OP(op1, SSE_OPF_MMX, \
2815 gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm, NULL, NULL)
2817 #define SSE_FOP(name) OP(op1, SSE_OPF_SCALAR, \
2818 gen_helper_##name##ps##_xmm, gen_helper_##name##pd##_xmm, \
2819 gen_helper_##name##ss, gen_helper_##name##sd)
2820 #define SSE_OP(sname, dname, op, flags) OP(op, flags, \
2821 gen_helper_##sname##_xmm, gen_helper_##dname##_xmm, NULL, NULL)
2823 typedef union SSEFuncs {
2824 SSEFunc_0_epp op1;
2825 SSEFunc_0_ppi op1i;
2826 SSEFunc_0_eppt op1t;
2827 } SSEFuncs;
2829 struct SSEOpHelper_table1 {
2830 int flags;
2831 SSEFuncs fn[4];
2834 #define SSE_3DNOW { SSE_OPF_3DNOW }
2835 #define SSE_SPECIAL { SSE_OPF_SPECIAL }
2837 static const struct SSEOpHelper_table1 sse_op_table1[256] = {
2838 /* 3DNow! extensions */
2839 [0x0e] = SSE_SPECIAL, /* femms */
2840 [0x0f] = SSE_3DNOW, /* pf... (sse_op_table5) */
2841 /* pure SSE operations */
2842 [0x10] = SSE_SPECIAL, /* movups, movupd, movss, movsd */
2843 [0x11] = SSE_SPECIAL, /* movups, movupd, movss, movsd */
2844 [0x12] = SSE_SPECIAL, /* movlps, movlpd, movsldup, movddup */
2845 [0x13] = SSE_SPECIAL, /* movlps, movlpd */
2846 [0x14] = SSE_OP(punpckldq, punpcklqdq, op1, 0), /* unpcklps, unpcklpd */
2847 [0x15] = SSE_OP(punpckhdq, punpckhqdq, op1, 0), /* unpckhps, unpckhpd */
2848 [0x16] = SSE_SPECIAL, /* movhps, movhpd, movshdup */
2849 [0x17] = SSE_SPECIAL, /* movhps, movhpd */
2851 [0x28] = SSE_SPECIAL, /* movaps, movapd */
2852 [0x29] = SSE_SPECIAL, /* movaps, movapd */
2853 [0x2a] = SSE_SPECIAL, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2854 [0x2b] = SSE_SPECIAL, /* movntps, movntpd, movntss, movntsd */
2855 [0x2c] = SSE_SPECIAL, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2856 [0x2d] = SSE_SPECIAL, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2857 [0x2e] = OP(op1, SSE_OPF_CMP | SSE_OPF_SCALAR,
2858 gen_helper_ucomiss, gen_helper_ucomisd, NULL, NULL),
2859 [0x2f] = OP(op1, SSE_OPF_CMP | SSE_OPF_SCALAR,
2860 gen_helper_comiss, gen_helper_comisd, NULL, NULL),
2861 [0x50] = SSE_SPECIAL, /* movmskps, movmskpd */
2862 [0x51] = OP(op1, SSE_OPF_SCALAR,
2863 gen_helper_sqrtps_xmm, gen_helper_sqrtpd_xmm,
2864 gen_helper_sqrtss, gen_helper_sqrtsd),
2865 [0x52] = OP(op1, SSE_OPF_SCALAR,
2866 gen_helper_rsqrtps_xmm, NULL, gen_helper_rsqrtss, NULL),
2867 [0x53] = OP(op1, SSE_OPF_SCALAR,
2868 gen_helper_rcpps_xmm, NULL, gen_helper_rcpss, NULL),
2869 [0x54] = SSE_OP(pand, pand, op1, 0), /* andps, andpd */
2870 [0x55] = SSE_OP(pandn, pandn, op1, 0), /* andnps, andnpd */
2871 [0x56] = SSE_OP(por, por, op1, 0), /* orps, orpd */
2872 [0x57] = SSE_OP(pxor, pxor, op1, 0), /* xorps, xorpd */
2873 [0x58] = SSE_FOP(add),
2874 [0x59] = SSE_FOP(mul),
2875 [0x5a] = OP(op1, SSE_OPF_SCALAR,
2876 gen_helper_cvtps2pd_xmm, gen_helper_cvtpd2ps_xmm,
2877 gen_helper_cvtss2sd, gen_helper_cvtsd2ss),
2878 [0x5b] = OP(op1, 0,
2879 gen_helper_cvtdq2ps_xmm, gen_helper_cvtps2dq_xmm,
2880 gen_helper_cvttps2dq_xmm, NULL),
2881 [0x5c] = SSE_FOP(sub),
2882 [0x5d] = SSE_FOP(min),
2883 [0x5e] = SSE_FOP(div),
2884 [0x5f] = SSE_FOP(max),
2886 [0xc2] = SSE_FOP(cmpeq), /* sse_op_table4 */
2887 [0xc6] = SSE_OP(shufps, shufpd, op1i, SSE_OPF_SHUF),
2889 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2890 [0x38] = SSE_SPECIAL,
2891 [0x3a] = SSE_SPECIAL,
2893 /* MMX ops and their SSE extensions */
2894 [0x60] = MMX_OP(punpcklbw),
2895 [0x61] = MMX_OP(punpcklwd),
2896 [0x62] = MMX_OP(punpckldq),
2897 [0x63] = MMX_OP(packsswb),
2898 [0x64] = MMX_OP(pcmpgtb),
2899 [0x65] = MMX_OP(pcmpgtw),
2900 [0x66] = MMX_OP(pcmpgtl),
2901 [0x67] = MMX_OP(packuswb),
2902 [0x68] = MMX_OP(punpckhbw),
2903 [0x69] = MMX_OP(punpckhwd),
2904 [0x6a] = MMX_OP(punpckhdq),
2905 [0x6b] = MMX_OP(packssdw),
2906 [0x6c] = OP(op1, SSE_OPF_MMX,
2907 NULL, gen_helper_punpcklqdq_xmm, NULL, NULL),
2908 [0x6d] = OP(op1, SSE_OPF_MMX,
2909 NULL, gen_helper_punpckhqdq_xmm, NULL, NULL),
2910 [0x6e] = SSE_SPECIAL, /* movd mm, ea */
2911 [0x6f] = SSE_SPECIAL, /* movq, movdqa, , movqdu */
2912 [0x70] = OP(op1i, SSE_OPF_SHUF | SSE_OPF_MMX,
2913 gen_helper_pshufw_mmx, gen_helper_pshufd_xmm,
2914 gen_helper_pshufhw_xmm, gen_helper_pshuflw_xmm),
2915 [0x71] = SSE_SPECIAL, /* shiftw */
2916 [0x72] = SSE_SPECIAL, /* shiftd */
2917 [0x73] = SSE_SPECIAL, /* shiftq */
2918 [0x74] = MMX_OP(pcmpeqb),
2919 [0x75] = MMX_OP(pcmpeqw),
2920 [0x76] = MMX_OP(pcmpeql),
2921 [0x77] = SSE_SPECIAL, /* emms */
2922 [0x78] = SSE_SPECIAL, /* extrq_i, insertq_i (sse4a) */
2923 [0x79] = OP(op1, 0,
2924 NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r),
2925 [0x7c] = OP(op1, 0,
2926 NULL, gen_helper_haddpd_xmm, NULL, gen_helper_haddps_xmm),
2927 [0x7d] = OP(op1, 0,
2928 NULL, gen_helper_hsubpd_xmm, NULL, gen_helper_hsubps_xmm),
2929 [0x7e] = SSE_SPECIAL, /* movd, movd, , movq */
2930 [0x7f] = SSE_SPECIAL, /* movq, movdqa, movdqu */
2931 [0xc4] = SSE_SPECIAL, /* pinsrw */
2932 [0xc5] = SSE_SPECIAL, /* pextrw */
2933 [0xd0] = OP(op1, 0,
2934 NULL, gen_helper_addsubpd_xmm, NULL, gen_helper_addsubps_xmm),
2935 [0xd1] = MMX_OP(psrlw),
2936 [0xd2] = MMX_OP(psrld),
2937 [0xd3] = MMX_OP(psrlq),
2938 [0xd4] = MMX_OP(paddq),
2939 [0xd5] = MMX_OP(pmullw),
2940 [0xd6] = SSE_SPECIAL,
2941 [0xd7] = SSE_SPECIAL, /* pmovmskb */
2942 [0xd8] = MMX_OP(psubusb),
2943 [0xd9] = MMX_OP(psubusw),
2944 [0xda] = MMX_OP(pminub),
2945 [0xdb] = MMX_OP(pand),
2946 [0xdc] = MMX_OP(paddusb),
2947 [0xdd] = MMX_OP(paddusw),
2948 [0xde] = MMX_OP(pmaxub),
2949 [0xdf] = MMX_OP(pandn),
2950 [0xe0] = MMX_OP(pavgb),
2951 [0xe1] = MMX_OP(psraw),
2952 [0xe2] = MMX_OP(psrad),
2953 [0xe3] = MMX_OP(pavgw),
2954 [0xe4] = MMX_OP(pmulhuw),
2955 [0xe5] = MMX_OP(pmulhw),
2956 [0xe6] = OP(op1, 0,
2957 NULL, gen_helper_cvttpd2dq_xmm,
2958 gen_helper_cvtdq2pd_xmm, gen_helper_cvtpd2dq_xmm),
2959 [0xe7] = SSE_SPECIAL, /* movntq, movntq */
2960 [0xe8] = MMX_OP(psubsb),
2961 [0xe9] = MMX_OP(psubsw),
2962 [0xea] = MMX_OP(pminsw),
2963 [0xeb] = MMX_OP(por),
2964 [0xec] = MMX_OP(paddsb),
2965 [0xed] = MMX_OP(paddsw),
2966 [0xee] = MMX_OP(pmaxsw),
2967 [0xef] = MMX_OP(pxor),
2968 [0xf0] = SSE_SPECIAL, /* lddqu */
2969 [0xf1] = MMX_OP(psllw),
2970 [0xf2] = MMX_OP(pslld),
2971 [0xf3] = MMX_OP(psllq),
2972 [0xf4] = MMX_OP(pmuludq),
2973 [0xf5] = MMX_OP(pmaddwd),
2974 [0xf6] = MMX_OP(psadbw),
2975 [0xf7] = OP(op1t, SSE_OPF_MMX,
2976 gen_helper_maskmov_mmx, gen_helper_maskmov_xmm, NULL, NULL),
2977 [0xf8] = MMX_OP(psubb),
2978 [0xf9] = MMX_OP(psubw),
2979 [0xfa] = MMX_OP(psubl),
2980 [0xfb] = MMX_OP(psubq),
2981 [0xfc] = MMX_OP(paddb),
2982 [0xfd] = MMX_OP(paddw),
2983 [0xfe] = MMX_OP(paddl),
2985 #undef MMX_OP
2986 #undef OP
2987 #undef SSE_FOP
2988 #undef SSE_OP
2989 #undef SSE_SPECIAL
2991 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2993 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2994 [0 + 2] = MMX_OP2(psrlw),
2995 [0 + 4] = MMX_OP2(psraw),
2996 [0 + 6] = MMX_OP2(psllw),
2997 [8 + 2] = MMX_OP2(psrld),
2998 [8 + 4] = MMX_OP2(psrad),
2999 [8 + 6] = MMX_OP2(pslld),
3000 [16 + 2] = MMX_OP2(psrlq),
3001 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
3002 [16 + 6] = MMX_OP2(psllq),
3003 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
3006 static const SSEFunc_0_epi sse_op_table3ai[] = {
3007 gen_helper_cvtsi2ss,
3008 gen_helper_cvtsi2sd
3011 #ifdef TARGET_X86_64
3012 static const SSEFunc_0_epl sse_op_table3aq[] = {
3013 gen_helper_cvtsq2ss,
3014 gen_helper_cvtsq2sd
3016 #endif
3018 static const SSEFunc_i_ep sse_op_table3bi[] = {
3019 gen_helper_cvttss2si,
3020 gen_helper_cvtss2si,
3021 gen_helper_cvttsd2si,
3022 gen_helper_cvtsd2si
3025 #ifdef TARGET_X86_64
3026 static const SSEFunc_l_ep sse_op_table3bq[] = {
3027 gen_helper_cvttss2sq,
3028 gen_helper_cvtss2sq,
3029 gen_helper_cvttsd2sq,
3030 gen_helper_cvtsd2sq
3032 #endif
3034 #define SSE_CMP(x) { \
3035 gen_helper_ ## x ## ps ## _xmm, gen_helper_ ## x ## pd ## _xmm, \
3036 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd}
3037 static const SSEFunc_0_epp sse_op_table4[8][4] = {
3038 SSE_CMP(cmpeq),
3039 SSE_CMP(cmplt),
3040 SSE_CMP(cmple),
3041 SSE_CMP(cmpunord),
3042 SSE_CMP(cmpneq),
3043 SSE_CMP(cmpnlt),
3044 SSE_CMP(cmpnle),
3045 SSE_CMP(cmpord),
3047 #undef SSE_CMP
3049 static const SSEFunc_0_epp sse_op_table5[256] = {
3050 [0x0c] = gen_helper_pi2fw,
3051 [0x0d] = gen_helper_pi2fd,
3052 [0x1c] = gen_helper_pf2iw,
3053 [0x1d] = gen_helper_pf2id,
3054 [0x8a] = gen_helper_pfnacc,
3055 [0x8e] = gen_helper_pfpnacc,
3056 [0x90] = gen_helper_pfcmpge,
3057 [0x94] = gen_helper_pfmin,
3058 [0x96] = gen_helper_pfrcp,
3059 [0x97] = gen_helper_pfrsqrt,
3060 [0x9a] = gen_helper_pfsub,
3061 [0x9e] = gen_helper_pfadd,
3062 [0xa0] = gen_helper_pfcmpgt,
3063 [0xa4] = gen_helper_pfmax,
3064 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
3065 [0xa7] = gen_helper_movq, /* pfrsqit1 */
3066 [0xaa] = gen_helper_pfsubr,
3067 [0xae] = gen_helper_pfacc,
3068 [0xb0] = gen_helper_pfcmpeq,
3069 [0xb4] = gen_helper_pfmul,
3070 [0xb6] = gen_helper_movq, /* pfrcpit2 */
3071 [0xb7] = gen_helper_pmulhrw_mmx,
3072 [0xbb] = gen_helper_pswapd,
3073 [0xbf] = gen_helper_pavgb_mmx,
3076 struct SSEOpHelper_table6 {
3077 SSEFuncs fn[2];
3078 uint32_t ext_mask;
3079 int flags;
3082 struct SSEOpHelper_table7 {
3083 union {
3084 SSEFunc_0_eppi op1;
3085 } fn[2];
3086 uint32_t ext_mask;
3087 int flags;
3090 #define gen_helper_special_xmm NULL
3092 #define OP(name, op, flags, ext, mmx_name) \
3093 {{{.op = mmx_name}, {.op = gen_helper_ ## name ## _xmm} }, \
3094 CPUID_EXT_ ## ext, flags}
3095 #define BINARY_OP_MMX(name, ext) \
3096 OP(name, op1, SSE_OPF_MMX, ext, gen_helper_ ## name ## _mmx)
3097 #define BINARY_OP(name, ext, flags) \
3098 OP(name, op1, flags, ext, NULL)
3099 #define UNARY_OP_MMX(name, ext) \
3100 OP(name, op1, SSE_OPF_MMX, ext, gen_helper_ ## name ## _mmx)
3101 #define UNARY_OP(name, ext, flags) \
3102 OP(name, op1, flags, ext, NULL)
3103 #define BLENDV_OP(name, ext, flags) OP(name, op1, 0, ext, NULL)
3104 #define CMP_OP(name, ext) OP(name, op1, SSE_OPF_CMP, ext, NULL)
3105 #define SPECIAL_OP(ext) OP(special, op1, SSE_OPF_SPECIAL, ext, NULL)
3107 /* prefix [66] 0f 38 */
3108 static const struct SSEOpHelper_table6 sse_op_table6[256] = {
3109 [0x00] = BINARY_OP_MMX(pshufb, SSSE3),
3110 [0x01] = BINARY_OP_MMX(phaddw, SSSE3),
3111 [0x02] = BINARY_OP_MMX(phaddd, SSSE3),
3112 [0x03] = BINARY_OP_MMX(phaddsw, SSSE3),
3113 [0x04] = BINARY_OP_MMX(pmaddubsw, SSSE3),
3114 [0x05] = BINARY_OP_MMX(phsubw, SSSE3),
3115 [0x06] = BINARY_OP_MMX(phsubd, SSSE3),
3116 [0x07] = BINARY_OP_MMX(phsubsw, SSSE3),
3117 [0x08] = BINARY_OP_MMX(psignb, SSSE3),
3118 [0x09] = BINARY_OP_MMX(psignw, SSSE3),
3119 [0x0a] = BINARY_OP_MMX(psignd, SSSE3),
3120 [0x0b] = BINARY_OP_MMX(pmulhrsw, SSSE3),
3121 [0x10] = BLENDV_OP(pblendvb, SSE41, SSE_OPF_MMX),
3122 [0x14] = BLENDV_OP(blendvps, SSE41, 0),
3123 [0x15] = BLENDV_OP(blendvpd, SSE41, 0),
3124 [0x17] = CMP_OP(ptest, SSE41),
3125 [0x1c] = UNARY_OP_MMX(pabsb, SSSE3),
3126 [0x1d] = UNARY_OP_MMX(pabsw, SSSE3),
3127 [0x1e] = UNARY_OP_MMX(pabsd, SSSE3),
3128 [0x20] = UNARY_OP(pmovsxbw, SSE41, SSE_OPF_MMX),
3129 [0x21] = UNARY_OP(pmovsxbd, SSE41, SSE_OPF_MMX),
3130 [0x22] = UNARY_OP(pmovsxbq, SSE41, SSE_OPF_MMX),
3131 [0x23] = UNARY_OP(pmovsxwd, SSE41, SSE_OPF_MMX),
3132 [0x24] = UNARY_OP(pmovsxwq, SSE41, SSE_OPF_MMX),
3133 [0x25] = UNARY_OP(pmovsxdq, SSE41, SSE_OPF_MMX),
3134 [0x28] = BINARY_OP(pmuldq, SSE41, SSE_OPF_MMX),
3135 [0x29] = BINARY_OP(pcmpeqq, SSE41, SSE_OPF_MMX),
3136 [0x2a] = SPECIAL_OP(SSE41), /* movntdqa */
3137 [0x2b] = BINARY_OP(packusdw, SSE41, SSE_OPF_MMX),
3138 [0x30] = UNARY_OP(pmovzxbw, SSE41, SSE_OPF_MMX),
3139 [0x31] = UNARY_OP(pmovzxbd, SSE41, SSE_OPF_MMX),
3140 [0x32] = UNARY_OP(pmovzxbq, SSE41, SSE_OPF_MMX),
3141 [0x33] = UNARY_OP(pmovzxwd, SSE41, SSE_OPF_MMX),
3142 [0x34] = UNARY_OP(pmovzxwq, SSE41, SSE_OPF_MMX),
3143 [0x35] = UNARY_OP(pmovzxdq, SSE41, SSE_OPF_MMX),
3144 [0x37] = BINARY_OP(pcmpgtq, SSE41, SSE_OPF_MMX),
3145 [0x38] = BINARY_OP(pminsb, SSE41, SSE_OPF_MMX),
3146 [0x39] = BINARY_OP(pminsd, SSE41, SSE_OPF_MMX),
3147 [0x3a] = BINARY_OP(pminuw, SSE41, SSE_OPF_MMX),
3148 [0x3b] = BINARY_OP(pminud, SSE41, SSE_OPF_MMX),
3149 [0x3c] = BINARY_OP(pmaxsb, SSE41, SSE_OPF_MMX),
3150 [0x3d] = BINARY_OP(pmaxsd, SSE41, SSE_OPF_MMX),
3151 [0x3e] = BINARY_OP(pmaxuw, SSE41, SSE_OPF_MMX),
3152 [0x3f] = BINARY_OP(pmaxud, SSE41, SSE_OPF_MMX),
3153 [0x40] = BINARY_OP(pmulld, SSE41, SSE_OPF_MMX),
3154 [0x41] = UNARY_OP(phminposuw, SSE41, 0),
3155 [0xdb] = UNARY_OP(aesimc, AES, 0),
3156 [0xdc] = BINARY_OP(aesenc, AES, 0),
3157 [0xdd] = BINARY_OP(aesenclast, AES, 0),
3158 [0xde] = BINARY_OP(aesdec, AES, 0),
3159 [0xdf] = BINARY_OP(aesdeclast, AES, 0),
3162 /* prefix [66] 0f 3a */
3163 static const struct SSEOpHelper_table7 sse_op_table7[256] = {
3164 [0x08] = UNARY_OP(roundps, SSE41, 0),
3165 [0x09] = UNARY_OP(roundpd, SSE41, 0),
3166 [0x0a] = UNARY_OP(roundss, SSE41, SSE_OPF_SCALAR),
3167 [0x0b] = UNARY_OP(roundsd, SSE41, SSE_OPF_SCALAR),
3168 [0x0c] = BINARY_OP(blendps, SSE41, 0),
3169 [0x0d] = BINARY_OP(blendpd, SSE41, 0),
3170 [0x0e] = BINARY_OP(pblendw, SSE41, SSE_OPF_MMX),
3171 [0x0f] = BINARY_OP_MMX(palignr, SSSE3),
3172 [0x14] = SPECIAL_OP(SSE41), /* pextrb */
3173 [0x15] = SPECIAL_OP(SSE41), /* pextrw */
3174 [0x16] = SPECIAL_OP(SSE41), /* pextrd/pextrq */
3175 [0x17] = SPECIAL_OP(SSE41), /* extractps */
3176 [0x20] = SPECIAL_OP(SSE41), /* pinsrb */
3177 [0x21] = SPECIAL_OP(SSE41), /* insertps */
3178 [0x22] = SPECIAL_OP(SSE41), /* pinsrd/pinsrq */
3179 [0x40] = BINARY_OP(dpps, SSE41, 0),
3180 [0x41] = BINARY_OP(dppd, SSE41, 0),
3181 [0x42] = BINARY_OP(mpsadbw, SSE41, SSE_OPF_MMX),
3182 [0x44] = BINARY_OP(pclmulqdq, PCLMULQDQ, 0),
3183 [0x60] = CMP_OP(pcmpestrm, SSE42),
3184 [0x61] = CMP_OP(pcmpestri, SSE42),
3185 [0x62] = CMP_OP(pcmpistrm, SSE42),
3186 [0x63] = CMP_OP(pcmpistri, SSE42),
3187 [0xdf] = UNARY_OP(aeskeygenassist, AES, 0),
3190 #undef OP
3191 #undef BINARY_OP_MMX
3192 #undef BINARY_OP
3193 #undef UNARY_OP_MMX
3194 #undef UNARY_OP
3195 #undef BLENDV_OP
3196 #undef SPECIAL_OP
3198 /* VEX prefix not allowed */
3199 #define CHECK_NO_VEX(s) do { \
3200 if (s->prefix & PREFIX_VEX) \
3201 goto illegal_op; \
3202 } while (0)
3204 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3205 target_ulong pc_start)
3207 int b1, op1_offset, op2_offset, is_xmm, val;
3208 int modrm, mod, rm, reg;
3209 int sse_op_flags;
3210 SSEFuncs sse_op_fn;
3211 const struct SSEOpHelper_table6 *op6;
3212 const struct SSEOpHelper_table7 *op7;
3213 MemOp ot;
3215 b &= 0xff;
3216 if (s->prefix & PREFIX_DATA)
3217 b1 = 1;
3218 else if (s->prefix & PREFIX_REPZ)
3219 b1 = 2;
3220 else if (s->prefix & PREFIX_REPNZ)
3221 b1 = 3;
3222 else
3223 b1 = 0;
3224 sse_op_flags = sse_op_table1[b].flags;
3225 sse_op_fn = sse_op_table1[b].fn[b1];
3226 if ((sse_op_flags & (SSE_OPF_SPECIAL | SSE_OPF_3DNOW)) == 0
3227 && !sse_op_fn.op1) {
3228 goto unknown_op;
3230 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3231 is_xmm = 1;
3232 } else {
3233 if (b1 == 0) {
3234 /* MMX case */
3235 is_xmm = 0;
3236 } else {
3237 is_xmm = 1;
3240 if (sse_op_flags & SSE_OPF_3DNOW) {
3241 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3242 goto illegal_op;
3245 /* simple MMX/SSE operation */
3246 if (s->flags & HF_TS_MASK) {
3247 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3248 return;
3250 if (s->flags & HF_EM_MASK) {
3251 illegal_op:
3252 gen_illegal_opcode(s);
3253 return;
3255 if (is_xmm
3256 && !(s->flags & HF_OSFXSR_MASK)
3257 && (b != 0x38 && b != 0x3a)) {
3258 goto unknown_op;
3260 if (b == 0x0e) {
3261 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3262 /* If we were fully decoding this we might use illegal_op. */
3263 goto unknown_op;
3265 /* femms */
3266 gen_helper_emms(cpu_env);
3267 return;
3269 if (b == 0x77) {
3270 /* emms */
3271 gen_helper_emms(cpu_env);
3272 return;
3274 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3275 the static cpu state) */
3276 if (!is_xmm) {
3277 gen_helper_enter_mmx(cpu_env);
3280 modrm = x86_ldub_code(env, s);
3281 reg = ((modrm >> 3) & 7);
3282 if (is_xmm) {
3283 reg |= REX_R(s);
3285 mod = (modrm >> 6) & 3;
3286 if (sse_op_flags & SSE_OPF_SPECIAL) {
3287 b |= (b1 << 8);
3288 switch(b) {
3289 case 0x0e7: /* movntq */
3290 CHECK_NO_VEX(s);
3291 if (mod == 3) {
3292 goto illegal_op;
3294 gen_lea_modrm(env, s, modrm);
3295 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3296 break;
3297 case 0x1e7: /* movntdq */
3298 case 0x02b: /* movntps */
3299 case 0x12b: /* movntpd */
3300 if (mod == 3)
3301 goto illegal_op;
3302 gen_lea_modrm(env, s, modrm);
3303 gen_sto_env_A0(s, ZMM_OFFSET(reg), true);
3304 break;
3305 case 0x3f0: /* lddqu */
3306 if (mod == 3)
3307 goto illegal_op;
3308 gen_lea_modrm(env, s, modrm);
3309 gen_ldo_env_A0(s, ZMM_OFFSET(reg), false);
3310 break;
3311 case 0x22b: /* movntss */
3312 case 0x32b: /* movntsd */
3313 if (mod == 3)
3314 goto illegal_op;
3315 gen_lea_modrm(env, s, modrm);
3316 if (b1 & 1) {
3317 gen_stq_env_A0(s, offsetof(CPUX86State,
3318 xmm_regs[reg].ZMM_Q(0)));
3319 } else {
3320 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
3321 xmm_regs[reg].ZMM_L(0)));
3322 gen_op_st_v(s, MO_32, s->T0, s->A0);
3324 break;
3325 case 0x6e: /* movd mm, ea */
3326 CHECK_NO_VEX(s);
3327 #ifdef TARGET_X86_64
3328 if (s->dflag == MO_64) {
3329 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3330 tcg_gen_st_tl(s->T0, cpu_env,
3331 offsetof(CPUX86State, fpregs[reg].mmx));
3332 } else
3333 #endif
3335 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3336 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3337 offsetof(CPUX86State,fpregs[reg].mmx));
3338 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3339 gen_helper_movl_mm_T0_mmx(s->ptr0, s->tmp2_i32);
3341 break;
3342 case 0x16e: /* movd xmm, ea */
3343 #ifdef TARGET_X86_64
3344 if (s->dflag == MO_64) {
3345 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3346 tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(reg));
3347 gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0);
3348 } else
3349 #endif
3351 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3352 tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(reg));
3353 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3354 gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32);
3356 break;
3357 case 0x6f: /* movq mm, ea */
3358 CHECK_NO_VEX(s);
3359 if (mod != 3) {
3360 gen_lea_modrm(env, s, modrm);
3361 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3362 } else {
3363 rm = (modrm & 7);
3364 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
3365 offsetof(CPUX86State,fpregs[rm].mmx));
3366 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
3367 offsetof(CPUX86State,fpregs[reg].mmx));
3369 break;
3370 case 0x010: /* movups */
3371 case 0x110: /* movupd */
3372 case 0x028: /* movaps */
3373 case 0x128: /* movapd */
3374 case 0x16f: /* movdqa xmm, ea */
3375 case 0x26f: /* movdqu xmm, ea */
3376 if (mod != 3) {
3377 gen_lea_modrm(env, s, modrm);
3378 gen_ldo_env_A0(s, ZMM_OFFSET(reg),
3379 /* movaps, movapd, movdqa */
3380 b == 0x028 || b == 0x128 || b == 0x16f);
3381 } else {
3382 rm = (modrm & 7) | REX_B(s);
3383 gen_op_movo(s, ZMM_OFFSET(reg), ZMM_OFFSET(rm));
3385 break;
3386 case 0x210: /* movss xmm, ea */
3387 if (mod != 3) {
3388 gen_lea_modrm(env, s, modrm);
3389 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3390 tcg_gen_st32_tl(s->T0, cpu_env,
3391 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3392 tcg_gen_movi_tl(s->T0, 0);
3393 tcg_gen_st32_tl(s->T0, cpu_env,
3394 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)));
3395 tcg_gen_st32_tl(s->T0, cpu_env,
3396 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3397 tcg_gen_st32_tl(s->T0, cpu_env,
3398 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3399 } else {
3400 rm = (modrm & 7) | REX_B(s);
3401 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
3402 offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0)));
3403 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
3404 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3406 break;
3407 case 0x310: /* movsd xmm, ea */
3408 if (mod != 3) {
3409 gen_lea_modrm(env, s, modrm);
3410 gen_ldq_env_A0(s, offsetof(CPUX86State,
3411 xmm_regs[reg].ZMM_Q(0)));
3412 tcg_gen_movi_tl(s->T0, 0);
3413 tcg_gen_st32_tl(s->T0, cpu_env,
3414 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3415 tcg_gen_st32_tl(s->T0, cpu_env,
3416 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3417 } else {
3418 rm = (modrm & 7) | REX_B(s);
3419 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3420 offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)));
3422 break;
3423 case 0x012: /* movlps */
3424 case 0x112: /* movlpd */
3425 if (mod != 3) {
3426 gen_lea_modrm(env, s, modrm);
3427 gen_ldq_env_A0(s, offsetof(CPUX86State,
3428 xmm_regs[reg].ZMM_Q(0)));
3429 } else {
3430 /* movhlps */
3431 rm = (modrm & 7) | REX_B(s);
3432 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3433 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3435 break;
3436 case 0x212: /* movsldup */
3437 if (mod != 3) {
3438 gen_lea_modrm(env, s, modrm);
3439 gen_ldo_env_A0(s, ZMM_OFFSET(reg), true);
3440 } else {
3441 rm = (modrm & 7) | REX_B(s);
3442 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3443 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3444 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3445 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3447 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3448 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3449 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3450 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3451 break;
3452 case 0x312: /* movddup */
3453 if (mod != 3) {
3454 gen_lea_modrm(env, s, modrm);
3455 gen_ldq_env_A0(s, offsetof(CPUX86State,
3456 xmm_regs[reg].ZMM_Q(0)));
3457 } else {
3458 rm = (modrm & 7) | REX_B(s);
3459 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3460 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3462 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3463 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3464 break;
3465 case 0x016: /* movhps */
3466 case 0x116: /* movhpd */
3467 if (mod != 3) {
3468 gen_lea_modrm(env, s, modrm);
3469 gen_ldq_env_A0(s, offsetof(CPUX86State,
3470 xmm_regs[reg].ZMM_Q(1)));
3471 } else {
3472 /* movlhps */
3473 rm = (modrm & 7) | REX_B(s);
3474 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3475 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3477 break;
3478 case 0x216: /* movshdup */
3479 if (mod != 3) {
3480 gen_lea_modrm(env, s, modrm);
3481 gen_ldo_env_A0(s, ZMM_OFFSET(reg), true);
3482 } else {
3483 rm = (modrm & 7) | REX_B(s);
3484 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3485 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3486 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3487 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3489 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3490 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3491 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3492 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3493 break;
3494 case 0x178:
3495 case 0x378:
3496 CHECK_NO_VEX(s);
3498 int bit_index, field_length;
3500 if (b1 == 1 && reg != 0)
3501 goto illegal_op;
3502 field_length = x86_ldub_code(env, s) & 0x3F;
3503 bit_index = x86_ldub_code(env, s) & 0x3F;
3504 tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(reg));
3505 if (b1 == 1)
3506 gen_helper_extrq_i(cpu_env, s->ptr0,
3507 tcg_const_i32(bit_index),
3508 tcg_const_i32(field_length));
3509 else {
3510 if (mod != 3) {
3511 gen_lea_modrm(env, s, modrm);
3512 op2_offset = offsetof(CPUX86State, xmm_t0);
3513 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
3514 } else {
3515 rm = (modrm & 7) | REX_B(s);
3516 op2_offset = ZMM_OFFSET(rm);
3518 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3519 gen_helper_insertq_i(cpu_env, s->ptr0, s->ptr1,
3520 tcg_const_i32(bit_index),
3521 tcg_const_i32(field_length));
3524 break;
3525 case 0x7e: /* movd ea, mm */
3526 CHECK_NO_VEX(s);
3527 #ifdef TARGET_X86_64
3528 if (s->dflag == MO_64) {
3529 tcg_gen_ld_i64(s->T0, cpu_env,
3530 offsetof(CPUX86State,fpregs[reg].mmx));
3531 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3532 } else
3533 #endif
3535 tcg_gen_ld32u_tl(s->T0, cpu_env,
3536 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3537 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3539 break;
3540 case 0x17e: /* movd ea, xmm */
3541 #ifdef TARGET_X86_64
3542 if (s->dflag == MO_64) {
3543 tcg_gen_ld_i64(s->T0, cpu_env,
3544 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3545 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3546 } else
3547 #endif
3549 tcg_gen_ld32u_tl(s->T0, cpu_env,
3550 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3551 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3553 break;
3554 case 0x27e: /* movq xmm, ea */
3555 if (mod != 3) {
3556 gen_lea_modrm(env, s, modrm);
3557 gen_ldq_env_A0(s, offsetof(CPUX86State,
3558 xmm_regs[reg].ZMM_Q(0)));
3559 } else {
3560 rm = (modrm & 7) | REX_B(s);
3561 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3562 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3564 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3565 break;
3566 case 0x7f: /* movq ea, mm */
3567 CHECK_NO_VEX(s);
3568 if (mod != 3) {
3569 gen_lea_modrm(env, s, modrm);
3570 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3571 } else {
3572 rm = (modrm & 7);
3573 gen_op_movq(s, offsetof(CPUX86State, fpregs[rm].mmx),
3574 offsetof(CPUX86State,fpregs[reg].mmx));
3576 break;
3577 case 0x011: /* movups */
3578 case 0x111: /* movupd */
3579 case 0x029: /* movaps */
3580 case 0x129: /* movapd */
3581 case 0x17f: /* movdqa ea, xmm */
3582 case 0x27f: /* movdqu ea, xmm */
3583 if (mod != 3) {
3584 gen_lea_modrm(env, s, modrm);
3585 gen_sto_env_A0(s, ZMM_OFFSET(reg),
3586 /* movaps, movapd, movdqa */
3587 b == 0x029 || b == 0x129 || b == 0x17f);
3588 } else {
3589 rm = (modrm & 7) | REX_B(s);
3590 gen_op_movo(s, ZMM_OFFSET(rm), ZMM_OFFSET(reg));
3592 break;
3593 case 0x211: /* movss ea, xmm */
3594 if (mod != 3) {
3595 gen_lea_modrm(env, s, modrm);
3596 tcg_gen_ld32u_tl(s->T0, cpu_env,
3597 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3598 gen_op_st_v(s, MO_32, s->T0, s->A0);
3599 } else {
3600 rm = (modrm & 7) | REX_B(s);
3601 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0)),
3602 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3604 break;
3605 case 0x311: /* movsd ea, xmm */
3606 if (mod != 3) {
3607 gen_lea_modrm(env, s, modrm);
3608 gen_stq_env_A0(s, offsetof(CPUX86State,
3609 xmm_regs[reg].ZMM_Q(0)));
3610 } else {
3611 rm = (modrm & 7) | REX_B(s);
3612 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3613 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3615 break;
3616 case 0x013: /* movlps */
3617 case 0x113: /* movlpd */
3618 if (mod != 3) {
3619 gen_lea_modrm(env, s, modrm);
3620 gen_stq_env_A0(s, offsetof(CPUX86State,
3621 xmm_regs[reg].ZMM_Q(0)));
3622 } else {
3623 goto illegal_op;
3625 break;
3626 case 0x017: /* movhps */
3627 case 0x117: /* movhpd */
3628 if (mod != 3) {
3629 gen_lea_modrm(env, s, modrm);
3630 gen_stq_env_A0(s, offsetof(CPUX86State,
3631 xmm_regs[reg].ZMM_Q(1)));
3632 } else {
3633 goto illegal_op;
3635 break;
3636 case 0x71: /* shift mm, im */
3637 case 0x72:
3638 case 0x73:
3639 case 0x171: /* shift xmm, im */
3640 case 0x172:
3641 case 0x173:
3642 val = x86_ldub_code(env, s);
3643 if (is_xmm) {
3644 tcg_gen_movi_tl(s->T0, val);
3645 tcg_gen_st32_tl(s->T0, cpu_env,
3646 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3647 tcg_gen_movi_tl(s->T0, 0);
3648 tcg_gen_st32_tl(s->T0, cpu_env,
3649 offsetof(CPUX86State, xmm_t0.ZMM_L(1)));
3650 op1_offset = offsetof(CPUX86State,xmm_t0);
3651 } else {
3652 CHECK_NO_VEX(s);
3653 tcg_gen_movi_tl(s->T0, val);
3654 tcg_gen_st32_tl(s->T0, cpu_env,
3655 offsetof(CPUX86State, mmx_t0.MMX_L(0)));
3656 tcg_gen_movi_tl(s->T0, 0);
3657 tcg_gen_st32_tl(s->T0, cpu_env,
3658 offsetof(CPUX86State, mmx_t0.MMX_L(1)));
3659 op1_offset = offsetof(CPUX86State,mmx_t0);
3661 assert(b1 < 2);
3662 SSEFunc_0_epp fn = sse_op_table2[((b - 1) & 3) * 8 +
3663 (((modrm >> 3)) & 7)][b1];
3664 if (!fn) {
3665 goto unknown_op;
3667 if (is_xmm) {
3668 rm = (modrm & 7) | REX_B(s);
3669 op2_offset = ZMM_OFFSET(rm);
3670 } else {
3671 rm = (modrm & 7);
3672 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3674 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3675 tcg_gen_addi_ptr(s->ptr1, cpu_env, op1_offset);
3676 fn(cpu_env, s->ptr0, s->ptr1);
3677 break;
3678 case 0x050: /* movmskps */
3679 rm = (modrm & 7) | REX_B(s);
3680 tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm));
3681 gen_helper_movmskps_xmm(s->tmp2_i32, cpu_env, s->ptr0);
3682 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3683 break;
3684 case 0x150: /* movmskpd */
3685 rm = (modrm & 7) | REX_B(s);
3686 tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm));
3687 gen_helper_movmskpd_xmm(s->tmp2_i32, cpu_env, s->ptr0);
3688 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3689 break;
3690 case 0x02a: /* cvtpi2ps */
3691 case 0x12a: /* cvtpi2pd */
3692 CHECK_NO_VEX(s);
3693 gen_helper_enter_mmx(cpu_env);
3694 if (mod != 3) {
3695 gen_lea_modrm(env, s, modrm);
3696 op2_offset = offsetof(CPUX86State,mmx_t0);
3697 gen_ldq_env_A0(s, op2_offset);
3698 } else {
3699 rm = (modrm & 7);
3700 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3702 op1_offset = ZMM_OFFSET(reg);
3703 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3704 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3705 switch(b >> 8) {
3706 case 0x0:
3707 gen_helper_cvtpi2ps(cpu_env, s->ptr0, s->ptr1);
3708 break;
3709 default:
3710 case 0x1:
3711 gen_helper_cvtpi2pd(cpu_env, s->ptr0, s->ptr1);
3712 break;
3714 break;
3715 case 0x22a: /* cvtsi2ss */
3716 case 0x32a: /* cvtsi2sd */
3717 ot = mo_64_32(s->dflag);
3718 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3719 op1_offset = ZMM_OFFSET(reg);
3720 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3721 if (ot == MO_32) {
3722 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3723 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3724 sse_fn_epi(cpu_env, s->ptr0, s->tmp2_i32);
3725 } else {
3726 #ifdef TARGET_X86_64
3727 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3728 sse_fn_epl(cpu_env, s->ptr0, s->T0);
3729 #else
3730 goto illegal_op;
3731 #endif
3733 break;
3734 case 0x02c: /* cvttps2pi */
3735 case 0x12c: /* cvttpd2pi */
3736 case 0x02d: /* cvtps2pi */
3737 case 0x12d: /* cvtpd2pi */
3738 CHECK_NO_VEX(s);
3739 gen_helper_enter_mmx(cpu_env);
3740 if (mod != 3) {
3741 gen_lea_modrm(env, s, modrm);
3742 op2_offset = offsetof(CPUX86State,xmm_t0);
3743 /* FIXME: should be 64-bit access if b1 == 0. */
3744 gen_ldo_env_A0(s, op2_offset, !!b1);
3745 } else {
3746 rm = (modrm & 7) | REX_B(s);
3747 op2_offset = ZMM_OFFSET(rm);
3749 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3750 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3751 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3752 switch(b) {
3753 case 0x02c:
3754 gen_helper_cvttps2pi(cpu_env, s->ptr0, s->ptr1);
3755 break;
3756 case 0x12c:
3757 gen_helper_cvttpd2pi(cpu_env, s->ptr0, s->ptr1);
3758 break;
3759 case 0x02d:
3760 gen_helper_cvtps2pi(cpu_env, s->ptr0, s->ptr1);
3761 break;
3762 case 0x12d:
3763 gen_helper_cvtpd2pi(cpu_env, s->ptr0, s->ptr1);
3764 break;
3766 break;
3767 case 0x22c: /* cvttss2si */
3768 case 0x32c: /* cvttsd2si */
3769 case 0x22d: /* cvtss2si */
3770 case 0x32d: /* cvtsd2si */
3771 ot = mo_64_32(s->dflag);
3772 if (mod != 3) {
3773 gen_lea_modrm(env, s, modrm);
3774 if ((b >> 8) & 1) {
3775 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3776 } else {
3777 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3778 tcg_gen_st32_tl(s->T0, cpu_env,
3779 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3781 op2_offset = offsetof(CPUX86State,xmm_t0);
3782 } else {
3783 rm = (modrm & 7) | REX_B(s);
3784 op2_offset = ZMM_OFFSET(rm);
3786 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3787 if (ot == MO_32) {
3788 SSEFunc_i_ep sse_fn_i_ep =
3789 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3790 sse_fn_i_ep(s->tmp2_i32, cpu_env, s->ptr0);
3791 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
3792 } else {
3793 #ifdef TARGET_X86_64
3794 SSEFunc_l_ep sse_fn_l_ep =
3795 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3796 sse_fn_l_ep(s->T0, cpu_env, s->ptr0);
3797 #else
3798 goto illegal_op;
3799 #endif
3801 gen_op_mov_reg_v(s, ot, reg, s->T0);
3802 break;
3803 case 0xc4: /* pinsrw */
3804 case 0x1c4:
3805 s->rip_offset = 1;
3806 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3807 val = x86_ldub_code(env, s);
3808 if (b1) {
3809 val &= 7;
3810 tcg_gen_st16_tl(s->T0, cpu_env,
3811 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3812 } else {
3813 CHECK_NO_VEX(s);
3814 val &= 3;
3815 tcg_gen_st16_tl(s->T0, cpu_env,
3816 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3818 break;
3819 case 0xc5: /* pextrw */
3820 case 0x1c5:
3821 if (mod != 3)
3822 goto illegal_op;
3823 ot = mo_64_32(s->dflag);
3824 val = x86_ldub_code(env, s);
3825 if (b1) {
3826 val &= 7;
3827 rm = (modrm & 7) | REX_B(s);
3828 tcg_gen_ld16u_tl(s->T0, cpu_env,
3829 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3830 } else {
3831 val &= 3;
3832 rm = (modrm & 7);
3833 tcg_gen_ld16u_tl(s->T0, cpu_env,
3834 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3836 reg = ((modrm >> 3) & 7) | REX_R(s);
3837 gen_op_mov_reg_v(s, ot, reg, s->T0);
3838 break;
3839 case 0x1d6: /* movq ea, xmm */
3840 if (mod != 3) {
3841 gen_lea_modrm(env, s, modrm);
3842 gen_stq_env_A0(s, offsetof(CPUX86State,
3843 xmm_regs[reg].ZMM_Q(0)));
3844 } else {
3845 rm = (modrm & 7) | REX_B(s);
3846 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3847 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3848 gen_op_movq_env_0(s,
3849 offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(1)));
3851 break;
3852 case 0x2d6: /* movq2dq */
3853 CHECK_NO_VEX(s);
3854 gen_helper_enter_mmx(cpu_env);
3855 rm = (modrm & 7);
3856 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3857 offsetof(CPUX86State,fpregs[rm].mmx));
3858 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3859 break;
3860 case 0x3d6: /* movdq2q */
3861 CHECK_NO_VEX(s);
3862 gen_helper_enter_mmx(cpu_env);
3863 rm = (modrm & 7) | REX_B(s);
3864 gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx),
3865 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3866 break;
3867 case 0xd7: /* pmovmskb */
3868 case 0x1d7:
3869 if (mod != 3)
3870 goto illegal_op;
3871 if (b1) {
3872 rm = (modrm & 7) | REX_B(s);
3873 tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm));
3874 gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0);
3875 } else {
3876 CHECK_NO_VEX(s);
3877 rm = (modrm & 7);
3878 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3879 offsetof(CPUX86State, fpregs[rm].mmx));
3880 gen_helper_pmovmskb_mmx(s->tmp2_i32, cpu_env, s->ptr0);
3882 reg = ((modrm >> 3) & 7) | REX_R(s);
3883 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3884 break;
3886 case 0x138:
3887 case 0x038:
3888 b = modrm;
3889 if ((b & 0xf0) == 0xf0) {
3890 goto do_0f_38_fx;
3892 modrm = x86_ldub_code(env, s);
3893 rm = modrm & 7;
3894 reg = ((modrm >> 3) & 7) | REX_R(s);
3895 mod = (modrm >> 6) & 3;
3897 assert(b1 < 2);
3898 op6 = &sse_op_table6[b];
3899 if (op6->ext_mask == 0) {
3900 goto unknown_op;
3902 if (!(s->cpuid_ext_features & op6->ext_mask)) {
3903 goto illegal_op;
3906 if (b1) {
3907 op1_offset = ZMM_OFFSET(reg);
3908 if (mod == 3) {
3909 op2_offset = ZMM_OFFSET(rm | REX_B(s));
3910 } else {
3911 op2_offset = offsetof(CPUX86State,xmm_t0);
3912 gen_lea_modrm(env, s, modrm);
3913 switch (b) {
3914 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3915 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3916 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3917 gen_ldq_env_A0(s, op2_offset +
3918 offsetof(ZMMReg, ZMM_Q(0)));
3919 break;
3920 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3921 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3922 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
3923 s->mem_index, MO_LEUL);
3924 tcg_gen_st_i32(s->tmp2_i32, cpu_env, op2_offset +
3925 offsetof(ZMMReg, ZMM_L(0)));
3926 break;
3927 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3928 tcg_gen_qemu_ld_tl(s->tmp0, s->A0,
3929 s->mem_index, MO_LEUW);
3930 tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset +
3931 offsetof(ZMMReg, ZMM_W(0)));
3932 break;
3933 case 0x2a: /* movntdqa */
3934 gen_ldo_env_A0(s, op1_offset, true);
3935 return;
3936 default:
3937 gen_ldo_env_A0(s, op2_offset, true);
3940 if (!op6->fn[b1].op1) {
3941 goto illegal_op;
3943 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3944 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3945 op6->fn[b1].op1(cpu_env, s->ptr0, s->ptr1);
3946 } else {
3947 CHECK_NO_VEX(s);
3948 if ((op6->flags & SSE_OPF_MMX) == 0) {
3949 goto unknown_op;
3951 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3952 if (mod == 3) {
3953 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3954 } else {
3955 op2_offset = offsetof(CPUX86State,mmx_t0);
3956 gen_lea_modrm(env, s, modrm);
3957 gen_ldq_env_A0(s, op2_offset);
3959 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3960 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3961 op6->fn[0].op1(cpu_env, s->ptr0, s->ptr1);
3964 if (op6->flags & SSE_OPF_CMP) {
3965 set_cc_op(s, CC_OP_EFLAGS);
3967 break;
3969 case 0x238:
3970 case 0x338:
3971 do_0f_38_fx:
3972 /* Various integer extensions at 0f 38 f[0-f]. */
3973 b = modrm | (b1 << 8);
3974 modrm = x86_ldub_code(env, s);
3975 reg = ((modrm >> 3) & 7) | REX_R(s);
3977 switch (b) {
3978 case 0x3f0: /* crc32 Gd,Eb */
3979 case 0x3f1: /* crc32 Gd,Ey */
3980 do_crc32:
3981 CHECK_NO_VEX(s);
3982 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3983 goto illegal_op;
3985 if ((b & 0xff) == 0xf0) {
3986 ot = MO_8;
3987 } else if (s->dflag != MO_64) {
3988 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3989 } else {
3990 ot = MO_64;
3993 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[reg]);
3994 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3995 gen_helper_crc32(s->T0, s->tmp2_i32,
3996 s->T0, tcg_const_i32(8 << ot));
3998 ot = mo_64_32(s->dflag);
3999 gen_op_mov_reg_v(s, ot, reg, s->T0);
4000 break;
4002 case 0x1f0: /* crc32 or movbe */
4003 case 0x1f1:
4004 CHECK_NO_VEX(s);
4005 /* For these insns, the f3 prefix is supposed to have priority
4006 over the 66 prefix, but that's not what we implement above
4007 setting b1. */
4008 if (s->prefix & PREFIX_REPNZ) {
4009 goto do_crc32;
4011 /* FALLTHRU */
4012 case 0x0f0: /* movbe Gy,My */
4013 case 0x0f1: /* movbe My,Gy */
4014 CHECK_NO_VEX(s);
4015 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
4016 goto illegal_op;
4018 if (s->dflag != MO_64) {
4019 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
4020 } else {
4021 ot = MO_64;
4024 gen_lea_modrm(env, s, modrm);
4025 if ((b & 1) == 0) {
4026 tcg_gen_qemu_ld_tl(s->T0, s->A0,
4027 s->mem_index, ot | MO_BE);
4028 gen_op_mov_reg_v(s, ot, reg, s->T0);
4029 } else {
4030 tcg_gen_qemu_st_tl(cpu_regs[reg], s->A0,
4031 s->mem_index, ot | MO_BE);
4033 break;
4035 case 0x0f2: /* andn Gy, By, Ey */
4036 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4037 || !(s->prefix & PREFIX_VEX)
4038 || s->vex_l != 0) {
4039 goto illegal_op;
4041 ot = mo_64_32(s->dflag);
4042 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4043 tcg_gen_andc_tl(s->T0, s->T0, cpu_regs[s->vex_v]);
4044 gen_op_mov_reg_v(s, ot, reg, s->T0);
4045 gen_op_update1_cc(s);
4046 set_cc_op(s, CC_OP_LOGICB + ot);
4047 break;
4049 case 0x0f7: /* bextr Gy, Ey, By */
4050 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4051 || !(s->prefix & PREFIX_VEX)
4052 || s->vex_l != 0) {
4053 goto illegal_op;
4055 ot = mo_64_32(s->dflag);
4057 TCGv bound, zero;
4059 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4060 /* Extract START, and shift the operand.
4061 Shifts larger than operand size get zeros. */
4062 tcg_gen_ext8u_tl(s->A0, cpu_regs[s->vex_v]);
4063 tcg_gen_shr_tl(s->T0, s->T0, s->A0);
4065 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
4066 zero = tcg_const_tl(0);
4067 tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound,
4068 s->T0, zero);
4069 tcg_temp_free(zero);
4071 /* Extract the LEN into a mask. Lengths larger than
4072 operand size get all ones. */
4073 tcg_gen_extract_tl(s->A0, cpu_regs[s->vex_v], 8, 8);
4074 tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound,
4075 s->A0, bound);
4076 tcg_temp_free(bound);
4077 tcg_gen_movi_tl(s->T1, 1);
4078 tcg_gen_shl_tl(s->T1, s->T1, s->A0);
4079 tcg_gen_subi_tl(s->T1, s->T1, 1);
4080 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4082 gen_op_mov_reg_v(s, ot, reg, s->T0);
4083 gen_op_update1_cc(s);
4084 set_cc_op(s, CC_OP_LOGICB + ot);
4086 break;
4088 case 0x0f5: /* bzhi Gy, Ey, By */
4089 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4090 || !(s->prefix & PREFIX_VEX)
4091 || s->vex_l != 0) {
4092 goto illegal_op;
4094 ot = mo_64_32(s->dflag);
4095 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4096 tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]);
4098 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
4099 /* Note that since we're using BMILG (in order to get O
4100 cleared) we need to store the inverse into C. */
4101 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
4102 s->T1, bound);
4103 tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1,
4104 bound, bound, s->T1);
4105 tcg_temp_free(bound);
4107 tcg_gen_movi_tl(s->A0, -1);
4108 tcg_gen_shl_tl(s->A0, s->A0, s->T1);
4109 tcg_gen_andc_tl(s->T0, s->T0, s->A0);
4110 gen_op_mov_reg_v(s, ot, reg, s->T0);
4111 gen_op_update1_cc(s);
4112 set_cc_op(s, CC_OP_BMILGB + ot);
4113 break;
4115 case 0x3f6: /* mulx By, Gy, rdx, Ey */
4116 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4117 || !(s->prefix & PREFIX_VEX)
4118 || s->vex_l != 0) {
4119 goto illegal_op;
4121 ot = mo_64_32(s->dflag);
4122 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4123 switch (ot) {
4124 default:
4125 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4126 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EDX]);
4127 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
4128 s->tmp2_i32, s->tmp3_i32);
4129 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32);
4130 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp3_i32);
4131 break;
4132 #ifdef TARGET_X86_64
4133 case MO_64:
4134 tcg_gen_mulu2_i64(s->T0, s->T1,
4135 s->T0, cpu_regs[R_EDX]);
4136 tcg_gen_mov_i64(cpu_regs[s->vex_v], s->T0);
4137 tcg_gen_mov_i64(cpu_regs[reg], s->T1);
4138 break;
4139 #endif
4141 break;
4143 case 0x3f5: /* pdep Gy, By, Ey */
4144 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4145 || !(s->prefix & PREFIX_VEX)
4146 || s->vex_l != 0) {
4147 goto illegal_op;
4149 ot = mo_64_32(s->dflag);
4150 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4151 /* Note that by zero-extending the source operand, we
4152 automatically handle zero-extending the result. */
4153 if (ot == MO_64) {
4154 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
4155 } else {
4156 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
4158 gen_helper_pdep(cpu_regs[reg], s->T1, s->T0);
4159 break;
4161 case 0x2f5: /* pext Gy, By, Ey */
4162 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4163 || !(s->prefix & PREFIX_VEX)
4164 || s->vex_l != 0) {
4165 goto illegal_op;
4167 ot = mo_64_32(s->dflag);
4168 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4169 /* Note that by zero-extending the source operand, we
4170 automatically handle zero-extending the result. */
4171 if (ot == MO_64) {
4172 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
4173 } else {
4174 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
4176 gen_helper_pext(cpu_regs[reg], s->T1, s->T0);
4177 break;
4179 case 0x1f6: /* adcx Gy, Ey */
4180 case 0x2f6: /* adox Gy, Ey */
4181 CHECK_NO_VEX(s);
4182 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
4183 goto illegal_op;
4184 } else {
4185 TCGv carry_in, carry_out, zero;
4186 int end_op;
4188 ot = mo_64_32(s->dflag);
4189 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4191 /* Re-use the carry-out from a previous round. */
4192 carry_in = NULL;
4193 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
4194 switch (s->cc_op) {
4195 case CC_OP_ADCX:
4196 if (b == 0x1f6) {
4197 carry_in = cpu_cc_dst;
4198 end_op = CC_OP_ADCX;
4199 } else {
4200 end_op = CC_OP_ADCOX;
4202 break;
4203 case CC_OP_ADOX:
4204 if (b == 0x1f6) {
4205 end_op = CC_OP_ADCOX;
4206 } else {
4207 carry_in = cpu_cc_src2;
4208 end_op = CC_OP_ADOX;
4210 break;
4211 case CC_OP_ADCOX:
4212 end_op = CC_OP_ADCOX;
4213 carry_in = carry_out;
4214 break;
4215 default:
4216 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
4217 break;
4219 /* If we can't reuse carry-out, get it out of EFLAGS. */
4220 if (!carry_in) {
4221 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4222 gen_compute_eflags(s);
4224 carry_in = s->tmp0;
4225 tcg_gen_extract_tl(carry_in, cpu_cc_src,
4226 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
4229 switch (ot) {
4230 #ifdef TARGET_X86_64
4231 case MO_32:
4232 /* If we know TL is 64-bit, and we want a 32-bit
4233 result, just do everything in 64-bit arithmetic. */
4234 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4235 tcg_gen_ext32u_i64(s->T0, s->T0);
4236 tcg_gen_add_i64(s->T0, s->T0, cpu_regs[reg]);
4237 tcg_gen_add_i64(s->T0, s->T0, carry_in);
4238 tcg_gen_ext32u_i64(cpu_regs[reg], s->T0);
4239 tcg_gen_shri_i64(carry_out, s->T0, 32);
4240 break;
4241 #endif
4242 default:
4243 /* Otherwise compute the carry-out in two steps. */
4244 zero = tcg_const_tl(0);
4245 tcg_gen_add2_tl(s->T0, carry_out,
4246 s->T0, zero,
4247 carry_in, zero);
4248 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4249 cpu_regs[reg], carry_out,
4250 s->T0, zero);
4251 tcg_temp_free(zero);
4252 break;
4254 set_cc_op(s, end_op);
4256 break;
4258 case 0x1f7: /* shlx Gy, Ey, By */
4259 case 0x2f7: /* sarx Gy, Ey, By */
4260 case 0x3f7: /* shrx Gy, Ey, By */
4261 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4262 || !(s->prefix & PREFIX_VEX)
4263 || s->vex_l != 0) {
4264 goto illegal_op;
4266 ot = mo_64_32(s->dflag);
4267 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4268 if (ot == MO_64) {
4269 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 63);
4270 } else {
4271 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 31);
4273 if (b == 0x1f7) {
4274 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
4275 } else if (b == 0x2f7) {
4276 if (ot != MO_64) {
4277 tcg_gen_ext32s_tl(s->T0, s->T0);
4279 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
4280 } else {
4281 if (ot != MO_64) {
4282 tcg_gen_ext32u_tl(s->T0, s->T0);
4284 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
4286 gen_op_mov_reg_v(s, ot, reg, s->T0);
4287 break;
4289 case 0x0f3:
4290 case 0x1f3:
4291 case 0x2f3:
4292 case 0x3f3: /* Group 17 */
4293 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4294 || !(s->prefix & PREFIX_VEX)
4295 || s->vex_l != 0) {
4296 goto illegal_op;
4298 ot = mo_64_32(s->dflag);
4299 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4301 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4302 switch (reg & 7) {
4303 case 1: /* blsr By,Ey */
4304 tcg_gen_subi_tl(s->T1, s->T0, 1);
4305 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4306 break;
4307 case 2: /* blsmsk By,Ey */
4308 tcg_gen_subi_tl(s->T1, s->T0, 1);
4309 tcg_gen_xor_tl(s->T0, s->T0, s->T1);
4310 break;
4311 case 3: /* blsi By, Ey */
4312 tcg_gen_neg_tl(s->T1, s->T0);
4313 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4314 break;
4315 default:
4316 goto unknown_op;
4318 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4319 gen_op_mov_reg_v(s, ot, s->vex_v, s->T0);
4320 set_cc_op(s, CC_OP_BMILGB + ot);
4321 break;
4323 default:
4324 goto unknown_op;
4326 break;
4328 case 0x03a:
4329 case 0x13a:
4330 b = modrm;
4331 modrm = x86_ldub_code(env, s);
4332 rm = modrm & 7;
4333 reg = ((modrm >> 3) & 7) | REX_R(s);
4334 mod = (modrm >> 6) & 3;
4336 assert(b1 < 2);
4337 op7 = &sse_op_table7[b];
4338 if (op7->ext_mask == 0) {
4339 goto unknown_op;
4341 if (!(s->cpuid_ext_features & op7->ext_mask)) {
4342 goto illegal_op;
4345 s->rip_offset = 1;
4347 if (op7->flags & SSE_OPF_SPECIAL) {
4348 /* None of the "special" ops are valid on mmx registers */
4349 if (b1 == 0) {
4350 goto illegal_op;
4352 ot = mo_64_32(s->dflag);
4353 rm = (modrm & 7) | REX_B(s);
4354 if (mod != 3)
4355 gen_lea_modrm(env, s, modrm);
4356 reg = ((modrm >> 3) & 7) | REX_R(s);
4357 val = x86_ldub_code(env, s);
4358 switch (b) {
4359 case 0x14: /* pextrb */
4360 tcg_gen_ld8u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4361 xmm_regs[reg].ZMM_B(val & 15)));
4362 if (mod == 3) {
4363 gen_op_mov_reg_v(s, ot, rm, s->T0);
4364 } else {
4365 tcg_gen_qemu_st_tl(s->T0, s->A0,
4366 s->mem_index, MO_UB);
4368 break;
4369 case 0x15: /* pextrw */
4370 tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4371 xmm_regs[reg].ZMM_W(val & 7)));
4372 if (mod == 3) {
4373 gen_op_mov_reg_v(s, ot, rm, s->T0);
4374 } else {
4375 tcg_gen_qemu_st_tl(s->T0, s->A0,
4376 s->mem_index, MO_LEUW);
4378 break;
4379 case 0x16:
4380 if (ot == MO_32) { /* pextrd */
4381 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4382 offsetof(CPUX86State,
4383 xmm_regs[reg].ZMM_L(val & 3)));
4384 if (mod == 3) {
4385 tcg_gen_extu_i32_tl(cpu_regs[rm], s->tmp2_i32);
4386 } else {
4387 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4388 s->mem_index, MO_LEUL);
4390 } else { /* pextrq */
4391 #ifdef TARGET_X86_64
4392 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
4393 offsetof(CPUX86State,
4394 xmm_regs[reg].ZMM_Q(val & 1)));
4395 if (mod == 3) {
4396 tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64);
4397 } else {
4398 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4399 s->mem_index, MO_LEUQ);
4401 #else
4402 goto illegal_op;
4403 #endif
4405 break;
4406 case 0x17: /* extractps */
4407 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4408 xmm_regs[reg].ZMM_L(val & 3)));
4409 if (mod == 3) {
4410 gen_op_mov_reg_v(s, ot, rm, s->T0);
4411 } else {
4412 tcg_gen_qemu_st_tl(s->T0, s->A0,
4413 s->mem_index, MO_LEUL);
4415 break;
4416 case 0x20: /* pinsrb */
4417 if (mod == 3) {
4418 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
4419 } else {
4420 tcg_gen_qemu_ld_tl(s->T0, s->A0,
4421 s->mem_index, MO_UB);
4423 tcg_gen_st8_tl(s->T0, cpu_env, offsetof(CPUX86State,
4424 xmm_regs[reg].ZMM_B(val & 15)));
4425 break;
4426 case 0x21: /* insertps */
4427 if (mod == 3) {
4428 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4429 offsetof(CPUX86State,xmm_regs[rm]
4430 .ZMM_L((val >> 6) & 3)));
4431 } else {
4432 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4433 s->mem_index, MO_LEUL);
4435 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4436 offsetof(CPUX86State,xmm_regs[reg]
4437 .ZMM_L((val >> 4) & 3)));
4438 if ((val >> 0) & 1)
4439 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4440 cpu_env, offsetof(CPUX86State,
4441 xmm_regs[reg].ZMM_L(0)));
4442 if ((val >> 1) & 1)
4443 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4444 cpu_env, offsetof(CPUX86State,
4445 xmm_regs[reg].ZMM_L(1)));
4446 if ((val >> 2) & 1)
4447 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4448 cpu_env, offsetof(CPUX86State,
4449 xmm_regs[reg].ZMM_L(2)));
4450 if ((val >> 3) & 1)
4451 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4452 cpu_env, offsetof(CPUX86State,
4453 xmm_regs[reg].ZMM_L(3)));
4454 break;
4455 case 0x22:
4456 if (ot == MO_32) { /* pinsrd */
4457 if (mod == 3) {
4458 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[rm]);
4459 } else {
4460 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4461 s->mem_index, MO_LEUL);
4463 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4464 offsetof(CPUX86State,
4465 xmm_regs[reg].ZMM_L(val & 3)));
4466 } else { /* pinsrq */
4467 #ifdef TARGET_X86_64
4468 if (mod == 3) {
4469 gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm);
4470 } else {
4471 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4472 s->mem_index, MO_LEUQ);
4474 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
4475 offsetof(CPUX86State,
4476 xmm_regs[reg].ZMM_Q(val & 1)));
4477 #else
4478 goto illegal_op;
4479 #endif
4481 break;
4483 return;
4486 if (b1 == 0) {
4487 CHECK_NO_VEX(s);
4488 /* MMX */
4489 if ((op7->flags & SSE_OPF_MMX) == 0) {
4490 goto illegal_op;
4492 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4493 if (mod == 3) {
4494 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4495 } else {
4496 op2_offset = offsetof(CPUX86State,mmx_t0);
4497 gen_lea_modrm(env, s, modrm);
4498 gen_ldq_env_A0(s, op2_offset);
4500 val = x86_ldub_code(env, s);
4501 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4502 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4504 /* We only actually have one MMX instuction (palignr) */
4505 assert(b == 0x0f);
4507 op7->fn[0].op1(cpu_env, s->ptr0, s->ptr1,
4508 tcg_const_i32(val));
4509 break;
4512 /* SSE */
4513 op1_offset = ZMM_OFFSET(reg);
4514 if (mod == 3) {
4515 op2_offset = ZMM_OFFSET(rm | REX_B(s));
4516 } else {
4517 op2_offset = offsetof(CPUX86State, xmm_t0);
4518 gen_lea_modrm(env, s, modrm);
4519 gen_ldo_env_A0(s, op2_offset, true);
4522 val = x86_ldub_code(env, s);
4523 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4524 set_cc_op(s, CC_OP_EFLAGS);
4526 if (s->dflag == MO_64) {
4527 /* The helper must use entire 64-bit gp registers */
4528 val |= 1 << 8;
4532 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4533 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4534 op7->fn[b1].op1(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val));
4535 if (op7->flags & SSE_OPF_CMP) {
4536 set_cc_op(s, CC_OP_EFLAGS);
4538 break;
4540 case 0x33a:
4541 /* Various integer extensions at 0f 3a f[0-f]. */
4542 b = modrm | (b1 << 8);
4543 modrm = x86_ldub_code(env, s);
4544 reg = ((modrm >> 3) & 7) | REX_R(s);
4546 switch (b) {
4547 case 0x3f0: /* rorx Gy,Ey, Ib */
4548 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4549 || !(s->prefix & PREFIX_VEX)
4550 || s->vex_l != 0) {
4551 goto illegal_op;
4553 ot = mo_64_32(s->dflag);
4554 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4555 b = x86_ldub_code(env, s);
4556 if (ot == MO_64) {
4557 tcg_gen_rotri_tl(s->T0, s->T0, b & 63);
4558 } else {
4559 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4560 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b & 31);
4561 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
4563 gen_op_mov_reg_v(s, ot, reg, s->T0);
4564 break;
4566 default:
4567 goto unknown_op;
4569 break;
4571 default:
4572 unknown_op:
4573 gen_unknown_opcode(env, s);
4574 return;
4576 } else {
4577 /* generic MMX or SSE operation */
4578 switch(b) {
4579 case 0x70: /* pshufx insn */
4580 case 0xc6: /* pshufx insn */
4581 case 0xc2: /* compare insns */
4582 s->rip_offset = 1;
4583 break;
4584 default:
4585 break;
4587 if (is_xmm) {
4588 op1_offset = ZMM_OFFSET(reg);
4589 if (mod != 3) {
4590 int sz = 4;
4592 gen_lea_modrm(env, s, modrm);
4593 op2_offset = offsetof(CPUX86State, xmm_t0);
4595 if (sse_op_flags & SSE_OPF_SCALAR) {
4596 if (sse_op_flags & SSE_OPF_CMP) {
4597 /* ucomis[sd], comis[sd] */
4598 if (b1 == 0) {
4599 sz = 2;
4600 } else {
4601 sz = 3;
4603 } else {
4604 /* Most sse scalar operations. */
4605 if (b1 == 2) {
4606 sz = 2;
4607 } else if (b1 == 3) {
4608 sz = 3;
4613 switch (sz) {
4614 case 2:
4615 /* 32 bit access */
4616 gen_op_ld_v(s, MO_32, s->T0, s->A0);
4617 tcg_gen_st32_tl(s->T0, cpu_env,
4618 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
4619 break;
4620 case 3:
4621 /* 64 bit access */
4622 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4623 break;
4624 default:
4625 /* 128 bit access */
4626 gen_ldo_env_A0(s, op2_offset, true);
4627 break;
4629 } else {
4630 rm = (modrm & 7) | REX_B(s);
4631 op2_offset = ZMM_OFFSET(rm);
4633 } else {
4634 CHECK_NO_VEX(s);
4635 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4636 if (mod != 3) {
4637 gen_lea_modrm(env, s, modrm);
4638 op2_offset = offsetof(CPUX86State,mmx_t0);
4639 gen_ldq_env_A0(s, op2_offset);
4640 } else {
4641 rm = (modrm & 7);
4642 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4644 if (sse_op_flags & SSE_OPF_3DNOW) {
4645 /* 3DNow! data insns */
4646 val = x86_ldub_code(env, s);
4647 SSEFunc_0_epp op_3dnow = sse_op_table5[val];
4648 if (!op_3dnow) {
4649 goto unknown_op;
4651 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4652 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4653 op_3dnow(cpu_env, s->ptr0, s->ptr1);
4654 return;
4657 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4658 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4659 if (sse_op_flags & SSE_OPF_SHUF) {
4660 val = x86_ldub_code(env, s);
4661 sse_op_fn.op1i(s->ptr0, s->ptr1, tcg_const_i32(val));
4662 } else if (b == 0xf7) {
4663 /* maskmov : we must prepare A0 */
4664 if (mod != 3) {
4665 goto illegal_op;
4667 tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]);
4668 gen_extu(s->aflag, s->A0);
4669 gen_add_A0_ds_seg(s);
4670 sse_op_fn.op1t(cpu_env, s->ptr0, s->ptr1, s->A0);
4671 } else if (b == 0xc2) {
4672 /* compare insns, bits 7:3 (7:5 for AVX) are ignored */
4673 val = x86_ldub_code(env, s) & 7;
4674 sse_op_table4[val][b1](cpu_env, s->ptr0, s->ptr1);
4675 } else {
4676 sse_op_fn.op1(cpu_env, s->ptr0, s->ptr1);
4679 if (sse_op_flags & SSE_OPF_CMP) {
4680 set_cc_op(s, CC_OP_EFLAGS);
4685 /* convert one instruction. s->base.is_jmp is set if the translation must
4686 be stopped. Return the next pc value */
4687 static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
4689 CPUX86State *env = cpu->env_ptr;
4690 int b, prefixes;
4691 int shift;
4692 MemOp ot, aflag, dflag;
4693 int modrm, reg, rm, mod, op, opreg, val;
4694 target_ulong next_eip, tval;
4695 target_ulong pc_start = s->base.pc_next;
4696 bool orig_cc_op_dirty = s->cc_op_dirty;
4697 CCOp orig_cc_op = s->cc_op;
4699 s->pc_start = s->pc = pc_start;
4700 s->override = -1;
4701 #ifdef TARGET_X86_64
4702 s->rex_w = false;
4703 s->rex_r = 0;
4704 s->rex_x = 0;
4705 s->rex_b = 0;
4706 #endif
4707 s->rip_offset = 0; /* for relative ip address */
4708 s->vex_l = 0;
4709 s->vex_v = 0;
4710 switch (sigsetjmp(s->jmpbuf, 0)) {
4711 case 0:
4712 break;
4713 case 1:
4714 gen_exception_gpf(s);
4715 return s->pc;
4716 case 2:
4717 /* Restore state that may affect the next instruction. */
4718 s->cc_op_dirty = orig_cc_op_dirty;
4719 s->cc_op = orig_cc_op;
4720 s->base.num_insns--;
4721 tcg_remove_ops_after(s->prev_insn_end);
4722 s->base.is_jmp = DISAS_TOO_MANY;
4723 return pc_start;
4724 default:
4725 g_assert_not_reached();
4728 prefixes = 0;
4730 next_byte:
4731 b = x86_ldub_code(env, s);
4732 /* Collect prefixes. */
4733 switch (b) {
4734 case 0xf3:
4735 prefixes |= PREFIX_REPZ;
4736 prefixes &= ~PREFIX_REPNZ;
4737 goto next_byte;
4738 case 0xf2:
4739 prefixes |= PREFIX_REPNZ;
4740 prefixes &= ~PREFIX_REPZ;
4741 goto next_byte;
4742 case 0xf0:
4743 prefixes |= PREFIX_LOCK;
4744 goto next_byte;
4745 case 0x2e:
4746 s->override = R_CS;
4747 goto next_byte;
4748 case 0x36:
4749 s->override = R_SS;
4750 goto next_byte;
4751 case 0x3e:
4752 s->override = R_DS;
4753 goto next_byte;
4754 case 0x26:
4755 s->override = R_ES;
4756 goto next_byte;
4757 case 0x64:
4758 s->override = R_FS;
4759 goto next_byte;
4760 case 0x65:
4761 s->override = R_GS;
4762 goto next_byte;
4763 case 0x66:
4764 prefixes |= PREFIX_DATA;
4765 goto next_byte;
4766 case 0x67:
4767 prefixes |= PREFIX_ADR;
4768 goto next_byte;
4769 #ifdef TARGET_X86_64
4770 case 0x40 ... 0x4f:
4771 if (CODE64(s)) {
4772 /* REX prefix */
4773 prefixes |= PREFIX_REX;
4774 s->rex_w = (b >> 3) & 1;
4775 s->rex_r = (b & 0x4) << 1;
4776 s->rex_x = (b & 0x2) << 2;
4777 s->rex_b = (b & 0x1) << 3;
4778 goto next_byte;
4780 break;
4781 #endif
4782 case 0xc5: /* 2-byte VEX */
4783 case 0xc4: /* 3-byte VEX */
4784 /* VEX prefixes cannot be used except in 32-bit mode.
4785 Otherwise the instruction is LES or LDS. */
4786 if (CODE32(s) && !VM86(s)) {
4787 static const int pp_prefix[4] = {
4788 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4790 int vex3, vex2 = x86_ldub_code(env, s);
4792 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4793 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4794 otherwise the instruction is LES or LDS. */
4795 s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
4796 break;
4799 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4800 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4801 | PREFIX_LOCK | PREFIX_DATA | PREFIX_REX)) {
4802 goto illegal_op;
4804 #ifdef TARGET_X86_64
4805 s->rex_r = (~vex2 >> 4) & 8;
4806 #endif
4807 if (b == 0xc5) {
4808 /* 2-byte VEX prefix: RVVVVlpp, implied 0f leading opcode byte */
4809 vex3 = vex2;
4810 b = x86_ldub_code(env, s) | 0x100;
4811 } else {
4812 /* 3-byte VEX prefix: RXBmmmmm wVVVVlpp */
4813 vex3 = x86_ldub_code(env, s);
4814 #ifdef TARGET_X86_64
4815 s->rex_x = (~vex2 >> 3) & 8;
4816 s->rex_b = (~vex2 >> 2) & 8;
4817 s->rex_w = (vex3 >> 7) & 1;
4818 #endif
4819 switch (vex2 & 0x1f) {
4820 case 0x01: /* Implied 0f leading opcode bytes. */
4821 b = x86_ldub_code(env, s) | 0x100;
4822 break;
4823 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4824 b = 0x138;
4825 break;
4826 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4827 b = 0x13a;
4828 break;
4829 default: /* Reserved for future use. */
4830 goto unknown_op;
4833 s->vex_v = (~vex3 >> 3) & 0xf;
4834 s->vex_l = (vex3 >> 2) & 1;
4835 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4837 break;
4840 /* Post-process prefixes. */
4841 if (CODE64(s)) {
4842 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4843 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4844 over 0x66 if both are present. */
4845 dflag = (REX_W(s) ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4846 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4847 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4848 } else {
4849 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4850 if (CODE32(s) ^ ((prefixes & PREFIX_DATA) != 0)) {
4851 dflag = MO_32;
4852 } else {
4853 dflag = MO_16;
4855 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4856 if (CODE32(s) ^ ((prefixes & PREFIX_ADR) != 0)) {
4857 aflag = MO_32;
4858 } else {
4859 aflag = MO_16;
4863 s->prefix = prefixes;
4864 s->aflag = aflag;
4865 s->dflag = dflag;
4867 /* now check op code */
4868 reswitch:
4869 switch(b) {
4870 case 0x0f:
4871 /**************************/
4872 /* extended op code */
4873 b = x86_ldub_code(env, s) | 0x100;
4874 goto reswitch;
4876 /**************************/
4877 /* arith & logic */
4878 case 0x00 ... 0x05:
4879 case 0x08 ... 0x0d:
4880 case 0x10 ... 0x15:
4881 case 0x18 ... 0x1d:
4882 case 0x20 ... 0x25:
4883 case 0x28 ... 0x2d:
4884 case 0x30 ... 0x35:
4885 case 0x38 ... 0x3d:
4887 int op, f, val;
4888 op = (b >> 3) & 7;
4889 f = (b >> 1) & 3;
4891 ot = mo_b_d(b, dflag);
4893 switch(f) {
4894 case 0: /* OP Ev, Gv */
4895 modrm = x86_ldub_code(env, s);
4896 reg = ((modrm >> 3) & 7) | REX_R(s);
4897 mod = (modrm >> 6) & 3;
4898 rm = (modrm & 7) | REX_B(s);
4899 if (mod != 3) {
4900 gen_lea_modrm(env, s, modrm);
4901 opreg = OR_TMP0;
4902 } else if (op == OP_XORL && rm == reg) {
4903 xor_zero:
4904 /* xor reg, reg optimisation */
4905 set_cc_op(s, CC_OP_CLR);
4906 tcg_gen_movi_tl(s->T0, 0);
4907 gen_op_mov_reg_v(s, ot, reg, s->T0);
4908 break;
4909 } else {
4910 opreg = rm;
4912 gen_op_mov_v_reg(s, ot, s->T1, reg);
4913 gen_op(s, op, ot, opreg);
4914 break;
4915 case 1: /* OP Gv, Ev */
4916 modrm = x86_ldub_code(env, s);
4917 mod = (modrm >> 6) & 3;
4918 reg = ((modrm >> 3) & 7) | REX_R(s);
4919 rm = (modrm & 7) | REX_B(s);
4920 if (mod != 3) {
4921 gen_lea_modrm(env, s, modrm);
4922 gen_op_ld_v(s, ot, s->T1, s->A0);
4923 } else if (op == OP_XORL && rm == reg) {
4924 goto xor_zero;
4925 } else {
4926 gen_op_mov_v_reg(s, ot, s->T1, rm);
4928 gen_op(s, op, ot, reg);
4929 break;
4930 case 2: /* OP A, Iv */
4931 val = insn_get(env, s, ot);
4932 tcg_gen_movi_tl(s->T1, val);
4933 gen_op(s, op, ot, OR_EAX);
4934 break;
4937 break;
4939 case 0x82:
4940 if (CODE64(s))
4941 goto illegal_op;
4942 /* fall through */
4943 case 0x80: /* GRP1 */
4944 case 0x81:
4945 case 0x83:
4947 int val;
4949 ot = mo_b_d(b, dflag);
4951 modrm = x86_ldub_code(env, s);
4952 mod = (modrm >> 6) & 3;
4953 rm = (modrm & 7) | REX_B(s);
4954 op = (modrm >> 3) & 7;
4956 if (mod != 3) {
4957 if (b == 0x83)
4958 s->rip_offset = 1;
4959 else
4960 s->rip_offset = insn_const_size(ot);
4961 gen_lea_modrm(env, s, modrm);
4962 opreg = OR_TMP0;
4963 } else {
4964 opreg = rm;
4967 switch(b) {
4968 default:
4969 case 0x80:
4970 case 0x81:
4971 case 0x82:
4972 val = insn_get(env, s, ot);
4973 break;
4974 case 0x83:
4975 val = (int8_t)insn_get(env, s, MO_8);
4976 break;
4978 tcg_gen_movi_tl(s->T1, val);
4979 gen_op(s, op, ot, opreg);
4981 break;
4983 /**************************/
4984 /* inc, dec, and other misc arith */
4985 case 0x40 ... 0x47: /* inc Gv */
4986 ot = dflag;
4987 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4988 break;
4989 case 0x48 ... 0x4f: /* dec Gv */
4990 ot = dflag;
4991 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4992 break;
4993 case 0xf6: /* GRP3 */
4994 case 0xf7:
4995 ot = mo_b_d(b, dflag);
4997 modrm = x86_ldub_code(env, s);
4998 mod = (modrm >> 6) & 3;
4999 rm = (modrm & 7) | REX_B(s);
5000 op = (modrm >> 3) & 7;
5001 if (mod != 3) {
5002 if (op == 0) {
5003 s->rip_offset = insn_const_size(ot);
5005 gen_lea_modrm(env, s, modrm);
5006 /* For those below that handle locked memory, don't load here. */
5007 if (!(s->prefix & PREFIX_LOCK)
5008 || op != 2) {
5009 gen_op_ld_v(s, ot, s->T0, s->A0);
5011 } else {
5012 gen_op_mov_v_reg(s, ot, s->T0, rm);
5015 switch(op) {
5016 case 0: /* test */
5017 val = insn_get(env, s, ot);
5018 tcg_gen_movi_tl(s->T1, val);
5019 gen_op_testl_T0_T1_cc(s);
5020 set_cc_op(s, CC_OP_LOGICB + ot);
5021 break;
5022 case 2: /* not */
5023 if (s->prefix & PREFIX_LOCK) {
5024 if (mod == 3) {
5025 goto illegal_op;
5027 tcg_gen_movi_tl(s->T0, ~0);
5028 tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0,
5029 s->mem_index, ot | MO_LE);
5030 } else {
5031 tcg_gen_not_tl(s->T0, s->T0);
5032 if (mod != 3) {
5033 gen_op_st_v(s, ot, s->T0, s->A0);
5034 } else {
5035 gen_op_mov_reg_v(s, ot, rm, s->T0);
5038 break;
5039 case 3: /* neg */
5040 if (s->prefix & PREFIX_LOCK) {
5041 TCGLabel *label1;
5042 TCGv a0, t0, t1, t2;
5044 if (mod == 3) {
5045 goto illegal_op;
5047 a0 = tcg_temp_local_new();
5048 t0 = tcg_temp_local_new();
5049 label1 = gen_new_label();
5051 tcg_gen_mov_tl(a0, s->A0);
5052 tcg_gen_mov_tl(t0, s->T0);
5054 gen_set_label(label1);
5055 t1 = tcg_temp_new();
5056 t2 = tcg_temp_new();
5057 tcg_gen_mov_tl(t2, t0);
5058 tcg_gen_neg_tl(t1, t0);
5059 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
5060 s->mem_index, ot | MO_LE);
5061 tcg_temp_free(t1);
5062 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
5064 tcg_temp_free(t2);
5065 tcg_temp_free(a0);
5066 tcg_gen_mov_tl(s->T0, t0);
5067 tcg_temp_free(t0);
5068 } else {
5069 tcg_gen_neg_tl(s->T0, s->T0);
5070 if (mod != 3) {
5071 gen_op_st_v(s, ot, s->T0, s->A0);
5072 } else {
5073 gen_op_mov_reg_v(s, ot, rm, s->T0);
5076 gen_op_update_neg_cc(s);
5077 set_cc_op(s, CC_OP_SUBB + ot);
5078 break;
5079 case 4: /* mul */
5080 switch(ot) {
5081 case MO_8:
5082 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
5083 tcg_gen_ext8u_tl(s->T0, s->T0);
5084 tcg_gen_ext8u_tl(s->T1, s->T1);
5085 /* XXX: use 32 bit mul which could be faster */
5086 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5087 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5088 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5089 tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00);
5090 set_cc_op(s, CC_OP_MULB);
5091 break;
5092 case MO_16:
5093 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
5094 tcg_gen_ext16u_tl(s->T0, s->T0);
5095 tcg_gen_ext16u_tl(s->T1, s->T1);
5096 /* XXX: use 32 bit mul which could be faster */
5097 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5098 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5099 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5100 tcg_gen_shri_tl(s->T0, s->T0, 16);
5101 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5102 tcg_gen_mov_tl(cpu_cc_src, s->T0);
5103 set_cc_op(s, CC_OP_MULW);
5104 break;
5105 default:
5106 case MO_32:
5107 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5108 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
5109 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
5110 s->tmp2_i32, s->tmp3_i32);
5111 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
5112 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
5113 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5114 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
5115 set_cc_op(s, CC_OP_MULL);
5116 break;
5117 #ifdef TARGET_X86_64
5118 case MO_64:
5119 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5120 s->T0, cpu_regs[R_EAX]);
5121 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5122 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
5123 set_cc_op(s, CC_OP_MULQ);
5124 break;
5125 #endif
5127 break;
5128 case 5: /* imul */
5129 switch(ot) {
5130 case MO_8:
5131 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
5132 tcg_gen_ext8s_tl(s->T0, s->T0);
5133 tcg_gen_ext8s_tl(s->T1, s->T1);
5134 /* XXX: use 32 bit mul which could be faster */
5135 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5136 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5137 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5138 tcg_gen_ext8s_tl(s->tmp0, s->T0);
5139 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5140 set_cc_op(s, CC_OP_MULB);
5141 break;
5142 case MO_16:
5143 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
5144 tcg_gen_ext16s_tl(s->T0, s->T0);
5145 tcg_gen_ext16s_tl(s->T1, s->T1);
5146 /* XXX: use 32 bit mul which could be faster */
5147 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5148 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5149 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5150 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5151 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5152 tcg_gen_shri_tl(s->T0, s->T0, 16);
5153 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5154 set_cc_op(s, CC_OP_MULW);
5155 break;
5156 default:
5157 case MO_32:
5158 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5159 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
5160 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5161 s->tmp2_i32, s->tmp3_i32);
5162 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
5163 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
5164 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5165 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5166 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5167 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5168 set_cc_op(s, CC_OP_MULL);
5169 break;
5170 #ifdef TARGET_X86_64
5171 case MO_64:
5172 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5173 s->T0, cpu_regs[R_EAX]);
5174 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5175 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
5176 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
5177 set_cc_op(s, CC_OP_MULQ);
5178 break;
5179 #endif
5181 break;
5182 case 6: /* div */
5183 switch(ot) {
5184 case MO_8:
5185 gen_helper_divb_AL(cpu_env, s->T0);
5186 break;
5187 case MO_16:
5188 gen_helper_divw_AX(cpu_env, s->T0);
5189 break;
5190 default:
5191 case MO_32:
5192 gen_helper_divl_EAX(cpu_env, s->T0);
5193 break;
5194 #ifdef TARGET_X86_64
5195 case MO_64:
5196 gen_helper_divq_EAX(cpu_env, s->T0);
5197 break;
5198 #endif
5200 break;
5201 case 7: /* idiv */
5202 switch(ot) {
5203 case MO_8:
5204 gen_helper_idivb_AL(cpu_env, s->T0);
5205 break;
5206 case MO_16:
5207 gen_helper_idivw_AX(cpu_env, s->T0);
5208 break;
5209 default:
5210 case MO_32:
5211 gen_helper_idivl_EAX(cpu_env, s->T0);
5212 break;
5213 #ifdef TARGET_X86_64
5214 case MO_64:
5215 gen_helper_idivq_EAX(cpu_env, s->T0);
5216 break;
5217 #endif
5219 break;
5220 default:
5221 goto unknown_op;
5223 break;
5225 case 0xfe: /* GRP4 */
5226 case 0xff: /* GRP5 */
5227 ot = mo_b_d(b, dflag);
5229 modrm = x86_ldub_code(env, s);
5230 mod = (modrm >> 6) & 3;
5231 rm = (modrm & 7) | REX_B(s);
5232 op = (modrm >> 3) & 7;
5233 if (op >= 2 && b == 0xfe) {
5234 goto unknown_op;
5236 if (CODE64(s)) {
5237 if (op == 2 || op == 4) {
5238 /* operand size for jumps is 64 bit */
5239 ot = MO_64;
5240 } else if (op == 3 || op == 5) {
5241 ot = dflag != MO_16 ? MO_32 + REX_W(s) : MO_16;
5242 } else if (op == 6) {
5243 /* default push size is 64 bit */
5244 ot = mo_pushpop(s, dflag);
5247 if (mod != 3) {
5248 gen_lea_modrm(env, s, modrm);
5249 if (op >= 2 && op != 3 && op != 5)
5250 gen_op_ld_v(s, ot, s->T0, s->A0);
5251 } else {
5252 gen_op_mov_v_reg(s, ot, s->T0, rm);
5255 switch(op) {
5256 case 0: /* inc Ev */
5257 if (mod != 3)
5258 opreg = OR_TMP0;
5259 else
5260 opreg = rm;
5261 gen_inc(s, ot, opreg, 1);
5262 break;
5263 case 1: /* dec Ev */
5264 if (mod != 3)
5265 opreg = OR_TMP0;
5266 else
5267 opreg = rm;
5268 gen_inc(s, ot, opreg, -1);
5269 break;
5270 case 2: /* call Ev */
5271 /* XXX: optimize if memory (no 'and' is necessary) */
5272 if (dflag == MO_16) {
5273 tcg_gen_ext16u_tl(s->T0, s->T0);
5275 next_eip = s->pc - s->cs_base;
5276 tcg_gen_movi_tl(s->T1, next_eip);
5277 gen_push_v(s, s->T1);
5278 gen_op_jmp_v(s->T0);
5279 gen_bnd_jmp(s);
5280 gen_jr(s, s->T0);
5281 break;
5282 case 3: /* lcall Ev */
5283 if (mod == 3) {
5284 goto illegal_op;
5286 gen_op_ld_v(s, ot, s->T1, s->A0);
5287 gen_add_A0_im(s, 1 << ot);
5288 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5289 do_lcall:
5290 if (PE(s) && !VM86(s)) {
5291 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5292 gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
5293 tcg_const_i32(dflag - 1),
5294 tcg_const_tl(s->pc - s->cs_base));
5295 } else {
5296 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5297 gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1,
5298 tcg_const_i32(dflag - 1),
5299 tcg_const_i32(s->pc - s->cs_base));
5301 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5302 gen_jr(s, s->tmp4);
5303 break;
5304 case 4: /* jmp Ev */
5305 if (dflag == MO_16) {
5306 tcg_gen_ext16u_tl(s->T0, s->T0);
5308 gen_op_jmp_v(s->T0);
5309 gen_bnd_jmp(s);
5310 gen_jr(s, s->T0);
5311 break;
5312 case 5: /* ljmp Ev */
5313 if (mod == 3) {
5314 goto illegal_op;
5316 gen_op_ld_v(s, ot, s->T1, s->A0);
5317 gen_add_A0_im(s, 1 << ot);
5318 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5319 do_ljmp:
5320 if (PE(s) && !VM86(s)) {
5321 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5322 gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1,
5323 tcg_const_tl(s->pc - s->cs_base));
5324 } else {
5325 gen_op_movl_seg_T0_vm(s, R_CS);
5326 gen_op_jmp_v(s->T1);
5328 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5329 gen_jr(s, s->tmp4);
5330 break;
5331 case 6: /* push Ev */
5332 gen_push_v(s, s->T0);
5333 break;
5334 default:
5335 goto unknown_op;
5337 break;
5339 case 0x84: /* test Ev, Gv */
5340 case 0x85:
5341 ot = mo_b_d(b, dflag);
5343 modrm = x86_ldub_code(env, s);
5344 reg = ((modrm >> 3) & 7) | REX_R(s);
5346 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5347 gen_op_mov_v_reg(s, ot, s->T1, reg);
5348 gen_op_testl_T0_T1_cc(s);
5349 set_cc_op(s, CC_OP_LOGICB + ot);
5350 break;
5352 case 0xa8: /* test eAX, Iv */
5353 case 0xa9:
5354 ot = mo_b_d(b, dflag);
5355 val = insn_get(env, s, ot);
5357 gen_op_mov_v_reg(s, ot, s->T0, OR_EAX);
5358 tcg_gen_movi_tl(s->T1, val);
5359 gen_op_testl_T0_T1_cc(s);
5360 set_cc_op(s, CC_OP_LOGICB + ot);
5361 break;
5363 case 0x98: /* CWDE/CBW */
5364 switch (dflag) {
5365 #ifdef TARGET_X86_64
5366 case MO_64:
5367 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5368 tcg_gen_ext32s_tl(s->T0, s->T0);
5369 gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0);
5370 break;
5371 #endif
5372 case MO_32:
5373 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5374 tcg_gen_ext16s_tl(s->T0, s->T0);
5375 gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0);
5376 break;
5377 case MO_16:
5378 gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX);
5379 tcg_gen_ext8s_tl(s->T0, s->T0);
5380 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5381 break;
5382 default:
5383 tcg_abort();
5385 break;
5386 case 0x99: /* CDQ/CWD */
5387 switch (dflag) {
5388 #ifdef TARGET_X86_64
5389 case MO_64:
5390 gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX);
5391 tcg_gen_sari_tl(s->T0, s->T0, 63);
5392 gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0);
5393 break;
5394 #endif
5395 case MO_32:
5396 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5397 tcg_gen_ext32s_tl(s->T0, s->T0);
5398 tcg_gen_sari_tl(s->T0, s->T0, 31);
5399 gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0);
5400 break;
5401 case MO_16:
5402 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5403 tcg_gen_ext16s_tl(s->T0, s->T0);
5404 tcg_gen_sari_tl(s->T0, s->T0, 15);
5405 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5406 break;
5407 default:
5408 tcg_abort();
5410 break;
5411 case 0x1af: /* imul Gv, Ev */
5412 case 0x69: /* imul Gv, Ev, I */
5413 case 0x6b:
5414 ot = dflag;
5415 modrm = x86_ldub_code(env, s);
5416 reg = ((modrm >> 3) & 7) | REX_R(s);
5417 if (b == 0x69)
5418 s->rip_offset = insn_const_size(ot);
5419 else if (b == 0x6b)
5420 s->rip_offset = 1;
5421 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5422 if (b == 0x69) {
5423 val = insn_get(env, s, ot);
5424 tcg_gen_movi_tl(s->T1, val);
5425 } else if (b == 0x6b) {
5426 val = (int8_t)insn_get(env, s, MO_8);
5427 tcg_gen_movi_tl(s->T1, val);
5428 } else {
5429 gen_op_mov_v_reg(s, ot, s->T1, reg);
5431 switch (ot) {
5432 #ifdef TARGET_X86_64
5433 case MO_64:
5434 tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1);
5435 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5436 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5437 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1);
5438 break;
5439 #endif
5440 case MO_32:
5441 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5442 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
5443 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5444 s->tmp2_i32, s->tmp3_i32);
5445 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
5446 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5447 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5448 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5449 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5450 break;
5451 default:
5452 tcg_gen_ext16s_tl(s->T0, s->T0);
5453 tcg_gen_ext16s_tl(s->T1, s->T1);
5454 /* XXX: use 32 bit mul which could be faster */
5455 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5456 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5457 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5458 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5459 gen_op_mov_reg_v(s, ot, reg, s->T0);
5460 break;
5462 set_cc_op(s, CC_OP_MULB + ot);
5463 break;
5464 case 0x1c0:
5465 case 0x1c1: /* xadd Ev, Gv */
5466 ot = mo_b_d(b, dflag);
5467 modrm = x86_ldub_code(env, s);
5468 reg = ((modrm >> 3) & 7) | REX_R(s);
5469 mod = (modrm >> 6) & 3;
5470 gen_op_mov_v_reg(s, ot, s->T0, reg);
5471 if (mod == 3) {
5472 rm = (modrm & 7) | REX_B(s);
5473 gen_op_mov_v_reg(s, ot, s->T1, rm);
5474 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5475 gen_op_mov_reg_v(s, ot, reg, s->T1);
5476 gen_op_mov_reg_v(s, ot, rm, s->T0);
5477 } else {
5478 gen_lea_modrm(env, s, modrm);
5479 if (s->prefix & PREFIX_LOCK) {
5480 tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0,
5481 s->mem_index, ot | MO_LE);
5482 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5483 } else {
5484 gen_op_ld_v(s, ot, s->T1, s->A0);
5485 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5486 gen_op_st_v(s, ot, s->T0, s->A0);
5488 gen_op_mov_reg_v(s, ot, reg, s->T1);
5490 gen_op_update2_cc(s);
5491 set_cc_op(s, CC_OP_ADDB + ot);
5492 break;
5493 case 0x1b0:
5494 case 0x1b1: /* cmpxchg Ev, Gv */
5496 TCGv oldv, newv, cmpv;
5498 ot = mo_b_d(b, dflag);
5499 modrm = x86_ldub_code(env, s);
5500 reg = ((modrm >> 3) & 7) | REX_R(s);
5501 mod = (modrm >> 6) & 3;
5502 oldv = tcg_temp_new();
5503 newv = tcg_temp_new();
5504 cmpv = tcg_temp_new();
5505 gen_op_mov_v_reg(s, ot, newv, reg);
5506 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5508 if (s->prefix & PREFIX_LOCK) {
5509 if (mod == 3) {
5510 goto illegal_op;
5512 gen_lea_modrm(env, s, modrm);
5513 tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
5514 s->mem_index, ot | MO_LE);
5515 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5516 } else {
5517 if (mod == 3) {
5518 rm = (modrm & 7) | REX_B(s);
5519 gen_op_mov_v_reg(s, ot, oldv, rm);
5520 } else {
5521 gen_lea_modrm(env, s, modrm);
5522 gen_op_ld_v(s, ot, oldv, s->A0);
5523 rm = 0; /* avoid warning */
5525 gen_extu(ot, oldv);
5526 gen_extu(ot, cmpv);
5527 /* store value = (old == cmp ? new : old); */
5528 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5529 if (mod == 3) {
5530 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5531 gen_op_mov_reg_v(s, ot, rm, newv);
5532 } else {
5533 /* Perform an unconditional store cycle like physical cpu;
5534 must be before changing accumulator to ensure
5535 idempotency if the store faults and the instruction
5536 is restarted */
5537 gen_op_st_v(s, ot, newv, s->A0);
5538 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5541 tcg_gen_mov_tl(cpu_cc_src, oldv);
5542 tcg_gen_mov_tl(s->cc_srcT, cmpv);
5543 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5544 set_cc_op(s, CC_OP_SUBB + ot);
5545 tcg_temp_free(oldv);
5546 tcg_temp_free(newv);
5547 tcg_temp_free(cmpv);
5549 break;
5550 case 0x1c7: /* cmpxchg8b */
5551 modrm = x86_ldub_code(env, s);
5552 mod = (modrm >> 6) & 3;
5553 switch ((modrm >> 3) & 7) {
5554 case 1: /* CMPXCHG8, CMPXCHG16 */
5555 if (mod == 3) {
5556 goto illegal_op;
5558 #ifdef TARGET_X86_64
5559 if (dflag == MO_64) {
5560 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) {
5561 goto illegal_op;
5563 gen_lea_modrm(env, s, modrm);
5564 if ((s->prefix & PREFIX_LOCK) &&
5565 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5566 gen_helper_cmpxchg16b(cpu_env, s->A0);
5567 } else {
5568 gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0);
5570 set_cc_op(s, CC_OP_EFLAGS);
5571 break;
5573 #endif
5574 if (!(s->cpuid_features & CPUID_CX8)) {
5575 goto illegal_op;
5577 gen_lea_modrm(env, s, modrm);
5578 if ((s->prefix & PREFIX_LOCK) &&
5579 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5580 gen_helper_cmpxchg8b(cpu_env, s->A0);
5581 } else {
5582 gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0);
5584 set_cc_op(s, CC_OP_EFLAGS);
5585 break;
5587 case 7: /* RDSEED */
5588 case 6: /* RDRAND */
5589 if (mod != 3 ||
5590 (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
5591 !(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
5592 goto illegal_op;
5594 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5595 gen_io_start();
5597 gen_helper_rdrand(s->T0, cpu_env);
5598 rm = (modrm & 7) | REX_B(s);
5599 gen_op_mov_reg_v(s, dflag, rm, s->T0);
5600 set_cc_op(s, CC_OP_EFLAGS);
5601 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5602 gen_jmp(s, s->pc - s->cs_base);
5604 break;
5606 default:
5607 goto illegal_op;
5609 break;
5611 /**************************/
5612 /* push/pop */
5613 case 0x50 ... 0x57: /* push */
5614 gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s));
5615 gen_push_v(s, s->T0);
5616 break;
5617 case 0x58 ... 0x5f: /* pop */
5618 ot = gen_pop_T0(s);
5619 /* NOTE: order is important for pop %sp */
5620 gen_pop_update(s, ot);
5621 gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0);
5622 break;
5623 case 0x60: /* pusha */
5624 if (CODE64(s))
5625 goto illegal_op;
5626 gen_pusha(s);
5627 break;
5628 case 0x61: /* popa */
5629 if (CODE64(s))
5630 goto illegal_op;
5631 gen_popa(s);
5632 break;
5633 case 0x68: /* push Iv */
5634 case 0x6a:
5635 ot = mo_pushpop(s, dflag);
5636 if (b == 0x68)
5637 val = insn_get(env, s, ot);
5638 else
5639 val = (int8_t)insn_get(env, s, MO_8);
5640 tcg_gen_movi_tl(s->T0, val);
5641 gen_push_v(s, s->T0);
5642 break;
5643 case 0x8f: /* pop Ev */
5644 modrm = x86_ldub_code(env, s);
5645 mod = (modrm >> 6) & 3;
5646 ot = gen_pop_T0(s);
5647 if (mod == 3) {
5648 /* NOTE: order is important for pop %sp */
5649 gen_pop_update(s, ot);
5650 rm = (modrm & 7) | REX_B(s);
5651 gen_op_mov_reg_v(s, ot, rm, s->T0);
5652 } else {
5653 /* NOTE: order is important too for MMU exceptions */
5654 s->popl_esp_hack = 1 << ot;
5655 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5656 s->popl_esp_hack = 0;
5657 gen_pop_update(s, ot);
5659 break;
5660 case 0xc8: /* enter */
5662 int level;
5663 val = x86_lduw_code(env, s);
5664 level = x86_ldub_code(env, s);
5665 gen_enter(s, val, level);
5667 break;
5668 case 0xc9: /* leave */
5669 gen_leave(s);
5670 break;
5671 case 0x06: /* push es */
5672 case 0x0e: /* push cs */
5673 case 0x16: /* push ss */
5674 case 0x1e: /* push ds */
5675 if (CODE64(s))
5676 goto illegal_op;
5677 gen_op_movl_T0_seg(s, b >> 3);
5678 gen_push_v(s, s->T0);
5679 break;
5680 case 0x1a0: /* push fs */
5681 case 0x1a8: /* push gs */
5682 gen_op_movl_T0_seg(s, (b >> 3) & 7);
5683 gen_push_v(s, s->T0);
5684 break;
5685 case 0x07: /* pop es */
5686 case 0x17: /* pop ss */
5687 case 0x1f: /* pop ds */
5688 if (CODE64(s))
5689 goto illegal_op;
5690 reg = b >> 3;
5691 ot = gen_pop_T0(s);
5692 gen_movl_seg_T0(s, reg);
5693 gen_pop_update(s, ot);
5694 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5695 if (s->base.is_jmp) {
5696 gen_jmp_im(s, s->pc - s->cs_base);
5697 if (reg == R_SS) {
5698 s->flags &= ~HF_TF_MASK;
5699 gen_eob_inhibit_irq(s, true);
5700 } else {
5701 gen_eob(s);
5704 break;
5705 case 0x1a1: /* pop fs */
5706 case 0x1a9: /* pop gs */
5707 ot = gen_pop_T0(s);
5708 gen_movl_seg_T0(s, (b >> 3) & 7);
5709 gen_pop_update(s, ot);
5710 if (s->base.is_jmp) {
5711 gen_jmp_im(s, s->pc - s->cs_base);
5712 gen_eob(s);
5714 break;
5716 /**************************/
5717 /* mov */
5718 case 0x88:
5719 case 0x89: /* mov Gv, Ev */
5720 ot = mo_b_d(b, dflag);
5721 modrm = x86_ldub_code(env, s);
5722 reg = ((modrm >> 3) & 7) | REX_R(s);
5724 /* generate a generic store */
5725 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5726 break;
5727 case 0xc6:
5728 case 0xc7: /* mov Ev, Iv */
5729 ot = mo_b_d(b, dflag);
5730 modrm = x86_ldub_code(env, s);
5731 mod = (modrm >> 6) & 3;
5732 if (mod != 3) {
5733 s->rip_offset = insn_const_size(ot);
5734 gen_lea_modrm(env, s, modrm);
5736 val = insn_get(env, s, ot);
5737 tcg_gen_movi_tl(s->T0, val);
5738 if (mod != 3) {
5739 gen_op_st_v(s, ot, s->T0, s->A0);
5740 } else {
5741 gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0);
5743 break;
5744 case 0x8a:
5745 case 0x8b: /* mov Ev, Gv */
5746 ot = mo_b_d(b, dflag);
5747 modrm = x86_ldub_code(env, s);
5748 reg = ((modrm >> 3) & 7) | REX_R(s);
5750 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5751 gen_op_mov_reg_v(s, ot, reg, s->T0);
5752 break;
5753 case 0x8e: /* mov seg, Gv */
5754 modrm = x86_ldub_code(env, s);
5755 reg = (modrm >> 3) & 7;
5756 if (reg >= 6 || reg == R_CS)
5757 goto illegal_op;
5758 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5759 gen_movl_seg_T0(s, reg);
5760 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5761 if (s->base.is_jmp) {
5762 gen_jmp_im(s, s->pc - s->cs_base);
5763 if (reg == R_SS) {
5764 s->flags &= ~HF_TF_MASK;
5765 gen_eob_inhibit_irq(s, true);
5766 } else {
5767 gen_eob(s);
5770 break;
5771 case 0x8c: /* mov Gv, seg */
5772 modrm = x86_ldub_code(env, s);
5773 reg = (modrm >> 3) & 7;
5774 mod = (modrm >> 6) & 3;
5775 if (reg >= 6)
5776 goto illegal_op;
5777 gen_op_movl_T0_seg(s, reg);
5778 ot = mod == 3 ? dflag : MO_16;
5779 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5780 break;
5782 case 0x1b6: /* movzbS Gv, Eb */
5783 case 0x1b7: /* movzwS Gv, Eb */
5784 case 0x1be: /* movsbS Gv, Eb */
5785 case 0x1bf: /* movswS Gv, Eb */
5787 MemOp d_ot;
5788 MemOp s_ot;
5790 /* d_ot is the size of destination */
5791 d_ot = dflag;
5792 /* ot is the size of source */
5793 ot = (b & 1) + MO_8;
5794 /* s_ot is the sign+size of source */
5795 s_ot = b & 8 ? MO_SIGN | ot : ot;
5797 modrm = x86_ldub_code(env, s);
5798 reg = ((modrm >> 3) & 7) | REX_R(s);
5799 mod = (modrm >> 6) & 3;
5800 rm = (modrm & 7) | REX_B(s);
5802 if (mod == 3) {
5803 if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) {
5804 tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8);
5805 } else {
5806 gen_op_mov_v_reg(s, ot, s->T0, rm);
5807 switch (s_ot) {
5808 case MO_UB:
5809 tcg_gen_ext8u_tl(s->T0, s->T0);
5810 break;
5811 case MO_SB:
5812 tcg_gen_ext8s_tl(s->T0, s->T0);
5813 break;
5814 case MO_UW:
5815 tcg_gen_ext16u_tl(s->T0, s->T0);
5816 break;
5817 default:
5818 case MO_SW:
5819 tcg_gen_ext16s_tl(s->T0, s->T0);
5820 break;
5823 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5824 } else {
5825 gen_lea_modrm(env, s, modrm);
5826 gen_op_ld_v(s, s_ot, s->T0, s->A0);
5827 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5830 break;
5832 case 0x8d: /* lea */
5833 modrm = x86_ldub_code(env, s);
5834 mod = (modrm >> 6) & 3;
5835 if (mod == 3)
5836 goto illegal_op;
5837 reg = ((modrm >> 3) & 7) | REX_R(s);
5839 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5840 TCGv ea = gen_lea_modrm_1(s, a);
5841 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5842 gen_op_mov_reg_v(s, dflag, reg, s->A0);
5844 break;
5846 case 0xa0: /* mov EAX, Ov */
5847 case 0xa1:
5848 case 0xa2: /* mov Ov, EAX */
5849 case 0xa3:
5851 target_ulong offset_addr;
5853 ot = mo_b_d(b, dflag);
5854 switch (s->aflag) {
5855 #ifdef TARGET_X86_64
5856 case MO_64:
5857 offset_addr = x86_ldq_code(env, s);
5858 break;
5859 #endif
5860 default:
5861 offset_addr = insn_get(env, s, s->aflag);
5862 break;
5864 tcg_gen_movi_tl(s->A0, offset_addr);
5865 gen_add_A0_ds_seg(s);
5866 if ((b & 2) == 0) {
5867 gen_op_ld_v(s, ot, s->T0, s->A0);
5868 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
5869 } else {
5870 gen_op_mov_v_reg(s, ot, s->T0, R_EAX);
5871 gen_op_st_v(s, ot, s->T0, s->A0);
5874 break;
5875 case 0xd7: /* xlat */
5876 tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]);
5877 tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]);
5878 tcg_gen_add_tl(s->A0, s->A0, s->T0);
5879 gen_extu(s->aflag, s->A0);
5880 gen_add_A0_ds_seg(s);
5881 gen_op_ld_v(s, MO_8, s->T0, s->A0);
5882 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
5883 break;
5884 case 0xb0 ... 0xb7: /* mov R, Ib */
5885 val = insn_get(env, s, MO_8);
5886 tcg_gen_movi_tl(s->T0, val);
5887 gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0);
5888 break;
5889 case 0xb8 ... 0xbf: /* mov R, Iv */
5890 #ifdef TARGET_X86_64
5891 if (dflag == MO_64) {
5892 uint64_t tmp;
5893 /* 64 bit case */
5894 tmp = x86_ldq_code(env, s);
5895 reg = (b & 7) | REX_B(s);
5896 tcg_gen_movi_tl(s->T0, tmp);
5897 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
5898 } else
5899 #endif
5901 ot = dflag;
5902 val = insn_get(env, s, ot);
5903 reg = (b & 7) | REX_B(s);
5904 tcg_gen_movi_tl(s->T0, val);
5905 gen_op_mov_reg_v(s, ot, reg, s->T0);
5907 break;
5909 case 0x91 ... 0x97: /* xchg R, EAX */
5910 do_xchg_reg_eax:
5911 ot = dflag;
5912 reg = (b & 7) | REX_B(s);
5913 rm = R_EAX;
5914 goto do_xchg_reg;
5915 case 0x86:
5916 case 0x87: /* xchg Ev, Gv */
5917 ot = mo_b_d(b, dflag);
5918 modrm = x86_ldub_code(env, s);
5919 reg = ((modrm >> 3) & 7) | REX_R(s);
5920 mod = (modrm >> 6) & 3;
5921 if (mod == 3) {
5922 rm = (modrm & 7) | REX_B(s);
5923 do_xchg_reg:
5924 gen_op_mov_v_reg(s, ot, s->T0, reg);
5925 gen_op_mov_v_reg(s, ot, s->T1, rm);
5926 gen_op_mov_reg_v(s, ot, rm, s->T0);
5927 gen_op_mov_reg_v(s, ot, reg, s->T1);
5928 } else {
5929 gen_lea_modrm(env, s, modrm);
5930 gen_op_mov_v_reg(s, ot, s->T0, reg);
5931 /* for xchg, lock is implicit */
5932 tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0,
5933 s->mem_index, ot | MO_LE);
5934 gen_op_mov_reg_v(s, ot, reg, s->T1);
5936 break;
5937 case 0xc4: /* les Gv */
5938 /* In CODE64 this is VEX3; see above. */
5939 op = R_ES;
5940 goto do_lxx;
5941 case 0xc5: /* lds Gv */
5942 /* In CODE64 this is VEX2; see above. */
5943 op = R_DS;
5944 goto do_lxx;
5945 case 0x1b2: /* lss Gv */
5946 op = R_SS;
5947 goto do_lxx;
5948 case 0x1b4: /* lfs Gv */
5949 op = R_FS;
5950 goto do_lxx;
5951 case 0x1b5: /* lgs Gv */
5952 op = R_GS;
5953 do_lxx:
5954 ot = dflag != MO_16 ? MO_32 : MO_16;
5955 modrm = x86_ldub_code(env, s);
5956 reg = ((modrm >> 3) & 7) | REX_R(s);
5957 mod = (modrm >> 6) & 3;
5958 if (mod == 3)
5959 goto illegal_op;
5960 gen_lea_modrm(env, s, modrm);
5961 gen_op_ld_v(s, ot, s->T1, s->A0);
5962 gen_add_A0_im(s, 1 << ot);
5963 /* load the segment first to handle exceptions properly */
5964 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5965 gen_movl_seg_T0(s, op);
5966 /* then put the data */
5967 gen_op_mov_reg_v(s, ot, reg, s->T1);
5968 if (s->base.is_jmp) {
5969 gen_jmp_im(s, s->pc - s->cs_base);
5970 gen_eob(s);
5972 break;
5974 /************************/
5975 /* shifts */
5976 case 0xc0:
5977 case 0xc1:
5978 /* shift Ev,Ib */
5979 shift = 2;
5980 grp2:
5982 ot = mo_b_d(b, dflag);
5983 modrm = x86_ldub_code(env, s);
5984 mod = (modrm >> 6) & 3;
5985 op = (modrm >> 3) & 7;
5987 if (mod != 3) {
5988 if (shift == 2) {
5989 s->rip_offset = 1;
5991 gen_lea_modrm(env, s, modrm);
5992 opreg = OR_TMP0;
5993 } else {
5994 opreg = (modrm & 7) | REX_B(s);
5997 /* simpler op */
5998 if (shift == 0) {
5999 gen_shift(s, op, ot, opreg, OR_ECX);
6000 } else {
6001 if (shift == 2) {
6002 shift = x86_ldub_code(env, s);
6004 gen_shifti(s, op, ot, opreg, shift);
6007 break;
6008 case 0xd0:
6009 case 0xd1:
6010 /* shift Ev,1 */
6011 shift = 1;
6012 goto grp2;
6013 case 0xd2:
6014 case 0xd3:
6015 /* shift Ev,cl */
6016 shift = 0;
6017 goto grp2;
6019 case 0x1a4: /* shld imm */
6020 op = 0;
6021 shift = 1;
6022 goto do_shiftd;
6023 case 0x1a5: /* shld cl */
6024 op = 0;
6025 shift = 0;
6026 goto do_shiftd;
6027 case 0x1ac: /* shrd imm */
6028 op = 1;
6029 shift = 1;
6030 goto do_shiftd;
6031 case 0x1ad: /* shrd cl */
6032 op = 1;
6033 shift = 0;
6034 do_shiftd:
6035 ot = dflag;
6036 modrm = x86_ldub_code(env, s);
6037 mod = (modrm >> 6) & 3;
6038 rm = (modrm & 7) | REX_B(s);
6039 reg = ((modrm >> 3) & 7) | REX_R(s);
6040 if (mod != 3) {
6041 gen_lea_modrm(env, s, modrm);
6042 opreg = OR_TMP0;
6043 } else {
6044 opreg = rm;
6046 gen_op_mov_v_reg(s, ot, s->T1, reg);
6048 if (shift) {
6049 TCGv imm = tcg_const_tl(x86_ldub_code(env, s));
6050 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
6051 tcg_temp_free(imm);
6052 } else {
6053 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
6055 break;
6057 /************************/
6058 /* floats */
6059 case 0xd8 ... 0xdf:
6061 bool update_fip = true;
6063 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
6064 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
6065 /* XXX: what to do if illegal op ? */
6066 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6067 break;
6069 modrm = x86_ldub_code(env, s);
6070 mod = (modrm >> 6) & 3;
6071 rm = modrm & 7;
6072 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
6073 if (mod != 3) {
6074 /* memory op */
6075 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6076 TCGv ea = gen_lea_modrm_1(s, a);
6077 TCGv last_addr = tcg_temp_new();
6078 bool update_fdp = true;
6080 tcg_gen_mov_tl(last_addr, ea);
6081 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
6083 switch (op) {
6084 case 0x00 ... 0x07: /* fxxxs */
6085 case 0x10 ... 0x17: /* fixxxl */
6086 case 0x20 ... 0x27: /* fxxxl */
6087 case 0x30 ... 0x37: /* fixxx */
6089 int op1;
6090 op1 = op & 7;
6092 switch (op >> 4) {
6093 case 0:
6094 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6095 s->mem_index, MO_LEUL);
6096 gen_helper_flds_FT0(cpu_env, s->tmp2_i32);
6097 break;
6098 case 1:
6099 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6100 s->mem_index, MO_LEUL);
6101 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
6102 break;
6103 case 2:
6104 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
6105 s->mem_index, MO_LEUQ);
6106 gen_helper_fldl_FT0(cpu_env, s->tmp1_i64);
6107 break;
6108 case 3:
6109 default:
6110 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6111 s->mem_index, MO_LESW);
6112 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
6113 break;
6116 gen_helper_fp_arith_ST0_FT0(op1);
6117 if (op1 == 3) {
6118 /* fcomp needs pop */
6119 gen_helper_fpop(cpu_env);
6122 break;
6123 case 0x08: /* flds */
6124 case 0x0a: /* fsts */
6125 case 0x0b: /* fstps */
6126 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
6127 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
6128 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
6129 switch (op & 7) {
6130 case 0:
6131 switch (op >> 4) {
6132 case 0:
6133 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6134 s->mem_index, MO_LEUL);
6135 gen_helper_flds_ST0(cpu_env, s->tmp2_i32);
6136 break;
6137 case 1:
6138 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6139 s->mem_index, MO_LEUL);
6140 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
6141 break;
6142 case 2:
6143 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
6144 s->mem_index, MO_LEUQ);
6145 gen_helper_fldl_ST0(cpu_env, s->tmp1_i64);
6146 break;
6147 case 3:
6148 default:
6149 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6150 s->mem_index, MO_LESW);
6151 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
6152 break;
6154 break;
6155 case 1:
6156 /* XXX: the corresponding CPUID bit must be tested ! */
6157 switch (op >> 4) {
6158 case 1:
6159 gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env);
6160 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6161 s->mem_index, MO_LEUL);
6162 break;
6163 case 2:
6164 gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env);
6165 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6166 s->mem_index, MO_LEUQ);
6167 break;
6168 case 3:
6169 default:
6170 gen_helper_fistt_ST0(s->tmp2_i32, cpu_env);
6171 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6172 s->mem_index, MO_LEUW);
6173 break;
6175 gen_helper_fpop(cpu_env);
6176 break;
6177 default:
6178 switch (op >> 4) {
6179 case 0:
6180 gen_helper_fsts_ST0(s->tmp2_i32, cpu_env);
6181 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6182 s->mem_index, MO_LEUL);
6183 break;
6184 case 1:
6185 gen_helper_fistl_ST0(s->tmp2_i32, cpu_env);
6186 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6187 s->mem_index, MO_LEUL);
6188 break;
6189 case 2:
6190 gen_helper_fstl_ST0(s->tmp1_i64, cpu_env);
6191 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6192 s->mem_index, MO_LEUQ);
6193 break;
6194 case 3:
6195 default:
6196 gen_helper_fist_ST0(s->tmp2_i32, cpu_env);
6197 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6198 s->mem_index, MO_LEUW);
6199 break;
6201 if ((op & 7) == 3) {
6202 gen_helper_fpop(cpu_env);
6204 break;
6206 break;
6207 case 0x0c: /* fldenv mem */
6208 gen_helper_fldenv(cpu_env, s->A0,
6209 tcg_const_i32(dflag - 1));
6210 update_fip = update_fdp = false;
6211 break;
6212 case 0x0d: /* fldcw mem */
6213 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6214 s->mem_index, MO_LEUW);
6215 gen_helper_fldcw(cpu_env, s->tmp2_i32);
6216 update_fip = update_fdp = false;
6217 break;
6218 case 0x0e: /* fnstenv mem */
6219 gen_helper_fstenv(cpu_env, s->A0,
6220 tcg_const_i32(dflag - 1));
6221 update_fip = update_fdp = false;
6222 break;
6223 case 0x0f: /* fnstcw mem */
6224 gen_helper_fnstcw(s->tmp2_i32, cpu_env);
6225 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6226 s->mem_index, MO_LEUW);
6227 update_fip = update_fdp = false;
6228 break;
6229 case 0x1d: /* fldt mem */
6230 gen_helper_fldt_ST0(cpu_env, s->A0);
6231 break;
6232 case 0x1f: /* fstpt mem */
6233 gen_helper_fstt_ST0(cpu_env, s->A0);
6234 gen_helper_fpop(cpu_env);
6235 break;
6236 case 0x2c: /* frstor mem */
6237 gen_helper_frstor(cpu_env, s->A0,
6238 tcg_const_i32(dflag - 1));
6239 update_fip = update_fdp = false;
6240 break;
6241 case 0x2e: /* fnsave mem */
6242 gen_helper_fsave(cpu_env, s->A0,
6243 tcg_const_i32(dflag - 1));
6244 update_fip = update_fdp = false;
6245 break;
6246 case 0x2f: /* fnstsw mem */
6247 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6248 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6249 s->mem_index, MO_LEUW);
6250 update_fip = update_fdp = false;
6251 break;
6252 case 0x3c: /* fbld */
6253 gen_helper_fbld_ST0(cpu_env, s->A0);
6254 break;
6255 case 0x3e: /* fbstp */
6256 gen_helper_fbst_ST0(cpu_env, s->A0);
6257 gen_helper_fpop(cpu_env);
6258 break;
6259 case 0x3d: /* fildll */
6260 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
6261 s->mem_index, MO_LEUQ);
6262 gen_helper_fildll_ST0(cpu_env, s->tmp1_i64);
6263 break;
6264 case 0x3f: /* fistpll */
6265 gen_helper_fistll_ST0(s->tmp1_i64, cpu_env);
6266 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6267 s->mem_index, MO_LEUQ);
6268 gen_helper_fpop(cpu_env);
6269 break;
6270 default:
6271 goto unknown_op;
6274 if (update_fdp) {
6275 int last_seg = s->override >= 0 ? s->override : a.def_seg;
6277 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
6278 offsetof(CPUX86State,
6279 segs[last_seg].selector));
6280 tcg_gen_st16_i32(s->tmp2_i32, cpu_env,
6281 offsetof(CPUX86State, fpds));
6282 tcg_gen_st_tl(last_addr, cpu_env,
6283 offsetof(CPUX86State, fpdp));
6285 tcg_temp_free(last_addr);
6286 } else {
6287 /* register float ops */
6288 opreg = rm;
6290 switch (op) {
6291 case 0x08: /* fld sti */
6292 gen_helper_fpush(cpu_env);
6293 gen_helper_fmov_ST0_STN(cpu_env,
6294 tcg_const_i32((opreg + 1) & 7));
6295 break;
6296 case 0x09: /* fxchg sti */
6297 case 0x29: /* fxchg4 sti, undocumented op */
6298 case 0x39: /* fxchg7 sti, undocumented op */
6299 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
6300 break;
6301 case 0x0a: /* grp d9/2 */
6302 switch (rm) {
6303 case 0: /* fnop */
6304 /* check exceptions (FreeBSD FPU probe) */
6305 gen_helper_fwait(cpu_env);
6306 update_fip = false;
6307 break;
6308 default:
6309 goto unknown_op;
6311 break;
6312 case 0x0c: /* grp d9/4 */
6313 switch (rm) {
6314 case 0: /* fchs */
6315 gen_helper_fchs_ST0(cpu_env);
6316 break;
6317 case 1: /* fabs */
6318 gen_helper_fabs_ST0(cpu_env);
6319 break;
6320 case 4: /* ftst */
6321 gen_helper_fldz_FT0(cpu_env);
6322 gen_helper_fcom_ST0_FT0(cpu_env);
6323 break;
6324 case 5: /* fxam */
6325 gen_helper_fxam_ST0(cpu_env);
6326 break;
6327 default:
6328 goto unknown_op;
6330 break;
6331 case 0x0d: /* grp d9/5 */
6333 switch (rm) {
6334 case 0:
6335 gen_helper_fpush(cpu_env);
6336 gen_helper_fld1_ST0(cpu_env);
6337 break;
6338 case 1:
6339 gen_helper_fpush(cpu_env);
6340 gen_helper_fldl2t_ST0(cpu_env);
6341 break;
6342 case 2:
6343 gen_helper_fpush(cpu_env);
6344 gen_helper_fldl2e_ST0(cpu_env);
6345 break;
6346 case 3:
6347 gen_helper_fpush(cpu_env);
6348 gen_helper_fldpi_ST0(cpu_env);
6349 break;
6350 case 4:
6351 gen_helper_fpush(cpu_env);
6352 gen_helper_fldlg2_ST0(cpu_env);
6353 break;
6354 case 5:
6355 gen_helper_fpush(cpu_env);
6356 gen_helper_fldln2_ST0(cpu_env);
6357 break;
6358 case 6:
6359 gen_helper_fpush(cpu_env);
6360 gen_helper_fldz_ST0(cpu_env);
6361 break;
6362 default:
6363 goto unknown_op;
6366 break;
6367 case 0x0e: /* grp d9/6 */
6368 switch (rm) {
6369 case 0: /* f2xm1 */
6370 gen_helper_f2xm1(cpu_env);
6371 break;
6372 case 1: /* fyl2x */
6373 gen_helper_fyl2x(cpu_env);
6374 break;
6375 case 2: /* fptan */
6376 gen_helper_fptan(cpu_env);
6377 break;
6378 case 3: /* fpatan */
6379 gen_helper_fpatan(cpu_env);
6380 break;
6381 case 4: /* fxtract */
6382 gen_helper_fxtract(cpu_env);
6383 break;
6384 case 5: /* fprem1 */
6385 gen_helper_fprem1(cpu_env);
6386 break;
6387 case 6: /* fdecstp */
6388 gen_helper_fdecstp(cpu_env);
6389 break;
6390 default:
6391 case 7: /* fincstp */
6392 gen_helper_fincstp(cpu_env);
6393 break;
6395 break;
6396 case 0x0f: /* grp d9/7 */
6397 switch (rm) {
6398 case 0: /* fprem */
6399 gen_helper_fprem(cpu_env);
6400 break;
6401 case 1: /* fyl2xp1 */
6402 gen_helper_fyl2xp1(cpu_env);
6403 break;
6404 case 2: /* fsqrt */
6405 gen_helper_fsqrt(cpu_env);
6406 break;
6407 case 3: /* fsincos */
6408 gen_helper_fsincos(cpu_env);
6409 break;
6410 case 5: /* fscale */
6411 gen_helper_fscale(cpu_env);
6412 break;
6413 case 4: /* frndint */
6414 gen_helper_frndint(cpu_env);
6415 break;
6416 case 6: /* fsin */
6417 gen_helper_fsin(cpu_env);
6418 break;
6419 default:
6420 case 7: /* fcos */
6421 gen_helper_fcos(cpu_env);
6422 break;
6424 break;
6425 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6426 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6427 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6429 int op1;
6431 op1 = op & 7;
6432 if (op >= 0x20) {
6433 gen_helper_fp_arith_STN_ST0(op1, opreg);
6434 if (op >= 0x30) {
6435 gen_helper_fpop(cpu_env);
6437 } else {
6438 gen_helper_fmov_FT0_STN(cpu_env,
6439 tcg_const_i32(opreg));
6440 gen_helper_fp_arith_ST0_FT0(op1);
6443 break;
6444 case 0x02: /* fcom */
6445 case 0x22: /* fcom2, undocumented op */
6446 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6447 gen_helper_fcom_ST0_FT0(cpu_env);
6448 break;
6449 case 0x03: /* fcomp */
6450 case 0x23: /* fcomp3, undocumented op */
6451 case 0x32: /* fcomp5, undocumented op */
6452 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6453 gen_helper_fcom_ST0_FT0(cpu_env);
6454 gen_helper_fpop(cpu_env);
6455 break;
6456 case 0x15: /* da/5 */
6457 switch (rm) {
6458 case 1: /* fucompp */
6459 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6460 gen_helper_fucom_ST0_FT0(cpu_env);
6461 gen_helper_fpop(cpu_env);
6462 gen_helper_fpop(cpu_env);
6463 break;
6464 default:
6465 goto unknown_op;
6467 break;
6468 case 0x1c:
6469 switch (rm) {
6470 case 0: /* feni (287 only, just do nop here) */
6471 break;
6472 case 1: /* fdisi (287 only, just do nop here) */
6473 break;
6474 case 2: /* fclex */
6475 gen_helper_fclex(cpu_env);
6476 update_fip = false;
6477 break;
6478 case 3: /* fninit */
6479 gen_helper_fninit(cpu_env);
6480 update_fip = false;
6481 break;
6482 case 4: /* fsetpm (287 only, just do nop here) */
6483 break;
6484 default:
6485 goto unknown_op;
6487 break;
6488 case 0x1d: /* fucomi */
6489 if (!(s->cpuid_features & CPUID_CMOV)) {
6490 goto illegal_op;
6492 gen_update_cc_op(s);
6493 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6494 gen_helper_fucomi_ST0_FT0(cpu_env);
6495 set_cc_op(s, CC_OP_EFLAGS);
6496 break;
6497 case 0x1e: /* fcomi */
6498 if (!(s->cpuid_features & CPUID_CMOV)) {
6499 goto illegal_op;
6501 gen_update_cc_op(s);
6502 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6503 gen_helper_fcomi_ST0_FT0(cpu_env);
6504 set_cc_op(s, CC_OP_EFLAGS);
6505 break;
6506 case 0x28: /* ffree sti */
6507 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6508 break;
6509 case 0x2a: /* fst sti */
6510 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6511 break;
6512 case 0x2b: /* fstp sti */
6513 case 0x0b: /* fstp1 sti, undocumented op */
6514 case 0x3a: /* fstp8 sti, undocumented op */
6515 case 0x3b: /* fstp9 sti, undocumented op */
6516 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6517 gen_helper_fpop(cpu_env);
6518 break;
6519 case 0x2c: /* fucom st(i) */
6520 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6521 gen_helper_fucom_ST0_FT0(cpu_env);
6522 break;
6523 case 0x2d: /* fucomp st(i) */
6524 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6525 gen_helper_fucom_ST0_FT0(cpu_env);
6526 gen_helper_fpop(cpu_env);
6527 break;
6528 case 0x33: /* de/3 */
6529 switch (rm) {
6530 case 1: /* fcompp */
6531 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6532 gen_helper_fcom_ST0_FT0(cpu_env);
6533 gen_helper_fpop(cpu_env);
6534 gen_helper_fpop(cpu_env);
6535 break;
6536 default:
6537 goto unknown_op;
6539 break;
6540 case 0x38: /* ffreep sti, undocumented op */
6541 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6542 gen_helper_fpop(cpu_env);
6543 break;
6544 case 0x3c: /* df/4 */
6545 switch (rm) {
6546 case 0:
6547 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6548 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
6549 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
6550 break;
6551 default:
6552 goto unknown_op;
6554 break;
6555 case 0x3d: /* fucomip */
6556 if (!(s->cpuid_features & CPUID_CMOV)) {
6557 goto illegal_op;
6559 gen_update_cc_op(s);
6560 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6561 gen_helper_fucomi_ST0_FT0(cpu_env);
6562 gen_helper_fpop(cpu_env);
6563 set_cc_op(s, CC_OP_EFLAGS);
6564 break;
6565 case 0x3e: /* fcomip */
6566 if (!(s->cpuid_features & CPUID_CMOV)) {
6567 goto illegal_op;
6569 gen_update_cc_op(s);
6570 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6571 gen_helper_fcomi_ST0_FT0(cpu_env);
6572 gen_helper_fpop(cpu_env);
6573 set_cc_op(s, CC_OP_EFLAGS);
6574 break;
6575 case 0x10 ... 0x13: /* fcmovxx */
6576 case 0x18 ... 0x1b:
6578 int op1;
6579 TCGLabel *l1;
6580 static const uint8_t fcmov_cc[8] = {
6581 (JCC_B << 1),
6582 (JCC_Z << 1),
6583 (JCC_BE << 1),
6584 (JCC_P << 1),
6587 if (!(s->cpuid_features & CPUID_CMOV)) {
6588 goto illegal_op;
6590 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6591 l1 = gen_new_label();
6592 gen_jcc1_noeob(s, op1, l1);
6593 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6594 gen_set_label(l1);
6596 break;
6597 default:
6598 goto unknown_op;
6602 if (update_fip) {
6603 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
6604 offsetof(CPUX86State, segs[R_CS].selector));
6605 tcg_gen_st16_i32(s->tmp2_i32, cpu_env,
6606 offsetof(CPUX86State, fpcs));
6607 tcg_gen_st_tl(tcg_constant_tl(pc_start - s->cs_base),
6608 cpu_env, offsetof(CPUX86State, fpip));
6611 break;
6612 /************************/
6613 /* string ops */
6615 case 0xa4: /* movsS */
6616 case 0xa5:
6617 ot = mo_b_d(b, dflag);
6618 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6619 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6620 } else {
6621 gen_movs(s, ot);
6623 break;
6625 case 0xaa: /* stosS */
6626 case 0xab:
6627 ot = mo_b_d(b, dflag);
6628 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6629 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6630 } else {
6631 gen_stos(s, ot);
6633 break;
6634 case 0xac: /* lodsS */
6635 case 0xad:
6636 ot = mo_b_d(b, dflag);
6637 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6638 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6639 } else {
6640 gen_lods(s, ot);
6642 break;
6643 case 0xae: /* scasS */
6644 case 0xaf:
6645 ot = mo_b_d(b, dflag);
6646 if (prefixes & PREFIX_REPNZ) {
6647 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6648 } else if (prefixes & PREFIX_REPZ) {
6649 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6650 } else {
6651 gen_scas(s, ot);
6653 break;
6655 case 0xa6: /* cmpsS */
6656 case 0xa7:
6657 ot = mo_b_d(b, dflag);
6658 if (prefixes & PREFIX_REPNZ) {
6659 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6660 } else if (prefixes & PREFIX_REPZ) {
6661 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6662 } else {
6663 gen_cmps(s, ot);
6665 break;
6666 case 0x6c: /* insS */
6667 case 0x6d:
6668 ot = mo_b_d32(b, dflag);
6669 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
6670 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
6671 if (!gen_check_io(s, ot, s->tmp2_i32,
6672 SVM_IOIO_TYPE_MASK | SVM_IOIO_STR_MASK)) {
6673 break;
6675 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6676 gen_io_start();
6678 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6679 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6680 /* jump generated by gen_repz_ins */
6681 } else {
6682 gen_ins(s, ot);
6683 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6684 gen_jmp(s, s->pc - s->cs_base);
6687 break;
6688 case 0x6e: /* outsS */
6689 case 0x6f:
6690 ot = mo_b_d32(b, dflag);
6691 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
6692 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
6693 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_STR_MASK)) {
6694 break;
6696 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6697 gen_io_start();
6699 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6700 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6701 /* jump generated by gen_repz_outs */
6702 } else {
6703 gen_outs(s, ot);
6704 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6705 gen_jmp(s, s->pc - s->cs_base);
6708 break;
6710 /************************/
6711 /* port I/O */
6713 case 0xe4:
6714 case 0xe5:
6715 ot = mo_b_d32(b, dflag);
6716 val = x86_ldub_code(env, s);
6717 tcg_gen_movi_i32(s->tmp2_i32, val);
6718 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) {
6719 break;
6721 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6722 gen_io_start();
6724 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6725 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6726 gen_bpt_io(s, s->tmp2_i32, ot);
6727 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6728 gen_jmp(s, s->pc - s->cs_base);
6730 break;
6731 case 0xe6:
6732 case 0xe7:
6733 ot = mo_b_d32(b, dflag);
6734 val = x86_ldub_code(env, s);
6735 tcg_gen_movi_i32(s->tmp2_i32, val);
6736 if (!gen_check_io(s, ot, s->tmp2_i32, 0)) {
6737 break;
6739 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6740 gen_io_start();
6742 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6743 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6744 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6745 gen_bpt_io(s, s->tmp2_i32, ot);
6746 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6747 gen_jmp(s, s->pc - s->cs_base);
6749 break;
6750 case 0xec:
6751 case 0xed:
6752 ot = mo_b_d32(b, dflag);
6753 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
6754 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
6755 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) {
6756 break;
6758 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6759 gen_io_start();
6761 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6762 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6763 gen_bpt_io(s, s->tmp2_i32, ot);
6764 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6765 gen_jmp(s, s->pc - s->cs_base);
6767 break;
6768 case 0xee:
6769 case 0xef:
6770 ot = mo_b_d32(b, dflag);
6771 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
6772 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
6773 if (!gen_check_io(s, ot, s->tmp2_i32, 0)) {
6774 break;
6776 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6777 gen_io_start();
6779 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6780 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6781 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6782 gen_bpt_io(s, s->tmp2_i32, ot);
6783 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6784 gen_jmp(s, s->pc - s->cs_base);
6786 break;
6788 /************************/
6789 /* control */
6790 case 0xc2: /* ret im */
6791 val = x86_ldsw_code(env, s);
6792 ot = gen_pop_T0(s);
6793 gen_stack_update(s, val + (1 << ot));
6794 /* Note that gen_pop_T0 uses a zero-extending load. */
6795 gen_op_jmp_v(s->T0);
6796 gen_bnd_jmp(s);
6797 gen_jr(s, s->T0);
6798 break;
6799 case 0xc3: /* ret */
6800 ot = gen_pop_T0(s);
6801 gen_pop_update(s, ot);
6802 /* Note that gen_pop_T0 uses a zero-extending load. */
6803 gen_op_jmp_v(s->T0);
6804 gen_bnd_jmp(s);
6805 gen_jr(s, s->T0);
6806 break;
6807 case 0xca: /* lret im */
6808 val = x86_ldsw_code(env, s);
6809 do_lret:
6810 if (PE(s) && !VM86(s)) {
6811 gen_update_cc_op(s);
6812 gen_jmp_im(s, pc_start - s->cs_base);
6813 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6814 tcg_const_i32(val));
6815 } else {
6816 gen_stack_A0(s);
6817 /* pop offset */
6818 gen_op_ld_v(s, dflag, s->T0, s->A0);
6819 /* NOTE: keeping EIP updated is not a problem in case of
6820 exception */
6821 gen_op_jmp_v(s->T0);
6822 /* pop selector */
6823 gen_add_A0_im(s, 1 << dflag);
6824 gen_op_ld_v(s, dflag, s->T0, s->A0);
6825 gen_op_movl_seg_T0_vm(s, R_CS);
6826 /* add stack offset */
6827 gen_stack_update(s, val + (2 << dflag));
6829 gen_eob(s);
6830 break;
6831 case 0xcb: /* lret */
6832 val = 0;
6833 goto do_lret;
6834 case 0xcf: /* iret */
6835 gen_svm_check_intercept(s, SVM_EXIT_IRET);
6836 if (!PE(s) || VM86(s)) {
6837 /* real mode or vm86 mode */
6838 if (!check_vm86_iopl(s)) {
6839 break;
6841 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6842 } else {
6843 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6844 tcg_const_i32(s->pc - s->cs_base));
6846 set_cc_op(s, CC_OP_EFLAGS);
6847 gen_eob(s);
6848 break;
6849 case 0xe8: /* call im */
6851 if (dflag != MO_16) {
6852 tval = (int32_t)insn_get(env, s, MO_32);
6853 } else {
6854 tval = (int16_t)insn_get(env, s, MO_16);
6856 next_eip = s->pc - s->cs_base;
6857 tval += next_eip;
6858 if (dflag == MO_16) {
6859 tval &= 0xffff;
6860 } else if (!CODE64(s)) {
6861 tval &= 0xffffffff;
6863 tcg_gen_movi_tl(s->T0, next_eip);
6864 gen_push_v(s, s->T0);
6865 gen_bnd_jmp(s);
6866 gen_jmp(s, tval);
6868 break;
6869 case 0x9a: /* lcall im */
6871 unsigned int selector, offset;
6873 if (CODE64(s))
6874 goto illegal_op;
6875 ot = dflag;
6876 offset = insn_get(env, s, ot);
6877 selector = insn_get(env, s, MO_16);
6879 tcg_gen_movi_tl(s->T0, selector);
6880 tcg_gen_movi_tl(s->T1, offset);
6882 goto do_lcall;
6883 case 0xe9: /* jmp im */
6884 if (dflag != MO_16) {
6885 tval = (int32_t)insn_get(env, s, MO_32);
6886 } else {
6887 tval = (int16_t)insn_get(env, s, MO_16);
6889 tval += s->pc - s->cs_base;
6890 if (dflag == MO_16) {
6891 tval &= 0xffff;
6892 } else if (!CODE64(s)) {
6893 tval &= 0xffffffff;
6895 gen_bnd_jmp(s);
6896 gen_jmp(s, tval);
6897 break;
6898 case 0xea: /* ljmp im */
6900 unsigned int selector, offset;
6902 if (CODE64(s))
6903 goto illegal_op;
6904 ot = dflag;
6905 offset = insn_get(env, s, ot);
6906 selector = insn_get(env, s, MO_16);
6908 tcg_gen_movi_tl(s->T0, selector);
6909 tcg_gen_movi_tl(s->T1, offset);
6911 goto do_ljmp;
6912 case 0xeb: /* jmp Jb */
6913 tval = (int8_t)insn_get(env, s, MO_8);
6914 tval += s->pc - s->cs_base;
6915 if (dflag == MO_16) {
6916 tval &= 0xffff;
6918 gen_jmp(s, tval);
6919 break;
6920 case 0x70 ... 0x7f: /* jcc Jb */
6921 tval = (int8_t)insn_get(env, s, MO_8);
6922 goto do_jcc;
6923 case 0x180 ... 0x18f: /* jcc Jv */
6924 if (dflag != MO_16) {
6925 tval = (int32_t)insn_get(env, s, MO_32);
6926 } else {
6927 tval = (int16_t)insn_get(env, s, MO_16);
6929 do_jcc:
6930 next_eip = s->pc - s->cs_base;
6931 tval += next_eip;
6932 if (dflag == MO_16) {
6933 tval &= 0xffff;
6935 gen_bnd_jmp(s);
6936 gen_jcc(s, b, tval, next_eip);
6937 break;
6939 case 0x190 ... 0x19f: /* setcc Gv */
6940 modrm = x86_ldub_code(env, s);
6941 gen_setcc1(s, b, s->T0);
6942 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6943 break;
6944 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6945 if (!(s->cpuid_features & CPUID_CMOV)) {
6946 goto illegal_op;
6948 ot = dflag;
6949 modrm = x86_ldub_code(env, s);
6950 reg = ((modrm >> 3) & 7) | REX_R(s);
6951 gen_cmovcc1(env, s, ot, b, modrm, reg);
6952 break;
6954 /************************/
6955 /* flags */
6956 case 0x9c: /* pushf */
6957 gen_svm_check_intercept(s, SVM_EXIT_PUSHF);
6958 if (check_vm86_iopl(s)) {
6959 gen_update_cc_op(s);
6960 gen_helper_read_eflags(s->T0, cpu_env);
6961 gen_push_v(s, s->T0);
6963 break;
6964 case 0x9d: /* popf */
6965 gen_svm_check_intercept(s, SVM_EXIT_POPF);
6966 if (check_vm86_iopl(s)) {
6967 ot = gen_pop_T0(s);
6968 if (CPL(s) == 0) {
6969 if (dflag != MO_16) {
6970 gen_helper_write_eflags(cpu_env, s->T0,
6971 tcg_const_i32((TF_MASK | AC_MASK |
6972 ID_MASK | NT_MASK |
6973 IF_MASK |
6974 IOPL_MASK)));
6975 } else {
6976 gen_helper_write_eflags(cpu_env, s->T0,
6977 tcg_const_i32((TF_MASK | AC_MASK |
6978 ID_MASK | NT_MASK |
6979 IF_MASK | IOPL_MASK)
6980 & 0xffff));
6982 } else {
6983 if (CPL(s) <= IOPL(s)) {
6984 if (dflag != MO_16) {
6985 gen_helper_write_eflags(cpu_env, s->T0,
6986 tcg_const_i32((TF_MASK |
6987 AC_MASK |
6988 ID_MASK |
6989 NT_MASK |
6990 IF_MASK)));
6991 } else {
6992 gen_helper_write_eflags(cpu_env, s->T0,
6993 tcg_const_i32((TF_MASK |
6994 AC_MASK |
6995 ID_MASK |
6996 NT_MASK |
6997 IF_MASK)
6998 & 0xffff));
7000 } else {
7001 if (dflag != MO_16) {
7002 gen_helper_write_eflags(cpu_env, s->T0,
7003 tcg_const_i32((TF_MASK | AC_MASK |
7004 ID_MASK | NT_MASK)));
7005 } else {
7006 gen_helper_write_eflags(cpu_env, s->T0,
7007 tcg_const_i32((TF_MASK | AC_MASK |
7008 ID_MASK | NT_MASK)
7009 & 0xffff));
7013 gen_pop_update(s, ot);
7014 set_cc_op(s, CC_OP_EFLAGS);
7015 /* abort translation because TF/AC flag may change */
7016 gen_jmp_im(s, s->pc - s->cs_base);
7017 gen_eob(s);
7019 break;
7020 case 0x9e: /* sahf */
7021 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
7022 goto illegal_op;
7023 gen_op_mov_v_reg(s, MO_8, s->T0, R_AH);
7024 gen_compute_eflags(s);
7025 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
7026 tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
7027 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
7028 break;
7029 case 0x9f: /* lahf */
7030 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
7031 goto illegal_op;
7032 gen_compute_eflags(s);
7033 /* Note: gen_compute_eflags() only gives the condition codes */
7034 tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02);
7035 gen_op_mov_reg_v(s, MO_8, R_AH, s->T0);
7036 break;
7037 case 0xf5: /* cmc */
7038 gen_compute_eflags(s);
7039 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
7040 break;
7041 case 0xf8: /* clc */
7042 gen_compute_eflags(s);
7043 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
7044 break;
7045 case 0xf9: /* stc */
7046 gen_compute_eflags(s);
7047 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
7048 break;
7049 case 0xfc: /* cld */
7050 tcg_gen_movi_i32(s->tmp2_i32, 1);
7051 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
7052 break;
7053 case 0xfd: /* std */
7054 tcg_gen_movi_i32(s->tmp2_i32, -1);
7055 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
7056 break;
7058 /************************/
7059 /* bit operations */
7060 case 0x1ba: /* bt/bts/btr/btc Gv, im */
7061 ot = dflag;
7062 modrm = x86_ldub_code(env, s);
7063 op = (modrm >> 3) & 7;
7064 mod = (modrm >> 6) & 3;
7065 rm = (modrm & 7) | REX_B(s);
7066 if (mod != 3) {
7067 s->rip_offset = 1;
7068 gen_lea_modrm(env, s, modrm);
7069 if (!(s->prefix & PREFIX_LOCK)) {
7070 gen_op_ld_v(s, ot, s->T0, s->A0);
7072 } else {
7073 gen_op_mov_v_reg(s, ot, s->T0, rm);
7075 /* load shift */
7076 val = x86_ldub_code(env, s);
7077 tcg_gen_movi_tl(s->T1, val);
7078 if (op < 4)
7079 goto unknown_op;
7080 op -= 4;
7081 goto bt_op;
7082 case 0x1a3: /* bt Gv, Ev */
7083 op = 0;
7084 goto do_btx;
7085 case 0x1ab: /* bts */
7086 op = 1;
7087 goto do_btx;
7088 case 0x1b3: /* btr */
7089 op = 2;
7090 goto do_btx;
7091 case 0x1bb: /* btc */
7092 op = 3;
7093 do_btx:
7094 ot = dflag;
7095 modrm = x86_ldub_code(env, s);
7096 reg = ((modrm >> 3) & 7) | REX_R(s);
7097 mod = (modrm >> 6) & 3;
7098 rm = (modrm & 7) | REX_B(s);
7099 gen_op_mov_v_reg(s, MO_32, s->T1, reg);
7100 if (mod != 3) {
7101 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7102 /* specific case: we need to add a displacement */
7103 gen_exts(ot, s->T1);
7104 tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
7105 tcg_gen_shli_tl(s->tmp0, s->tmp0, ot);
7106 tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a), s->tmp0);
7107 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
7108 if (!(s->prefix & PREFIX_LOCK)) {
7109 gen_op_ld_v(s, ot, s->T0, s->A0);
7111 } else {
7112 gen_op_mov_v_reg(s, ot, s->T0, rm);
7114 bt_op:
7115 tcg_gen_andi_tl(s->T1, s->T1, (1 << (3 + ot)) - 1);
7116 tcg_gen_movi_tl(s->tmp0, 1);
7117 tcg_gen_shl_tl(s->tmp0, s->tmp0, s->T1);
7118 if (s->prefix & PREFIX_LOCK) {
7119 switch (op) {
7120 case 0: /* bt */
7121 /* Needs no atomic ops; we surpressed the normal
7122 memory load for LOCK above so do it now. */
7123 gen_op_ld_v(s, ot, s->T0, s->A0);
7124 break;
7125 case 1: /* bts */
7126 tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, s->tmp0,
7127 s->mem_index, ot | MO_LE);
7128 break;
7129 case 2: /* btr */
7130 tcg_gen_not_tl(s->tmp0, s->tmp0);
7131 tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, s->tmp0,
7132 s->mem_index, ot | MO_LE);
7133 break;
7134 default:
7135 case 3: /* btc */
7136 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0,
7137 s->mem_index, ot | MO_LE);
7138 break;
7140 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
7141 } else {
7142 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
7143 switch (op) {
7144 case 0: /* bt */
7145 /* Data already loaded; nothing to do. */
7146 break;
7147 case 1: /* bts */
7148 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
7149 break;
7150 case 2: /* btr */
7151 tcg_gen_andc_tl(s->T0, s->T0, s->tmp0);
7152 break;
7153 default:
7154 case 3: /* btc */
7155 tcg_gen_xor_tl(s->T0, s->T0, s->tmp0);
7156 break;
7158 if (op != 0) {
7159 if (mod != 3) {
7160 gen_op_st_v(s, ot, s->T0, s->A0);
7161 } else {
7162 gen_op_mov_reg_v(s, ot, rm, s->T0);
7167 /* Delay all CC updates until after the store above. Note that
7168 C is the result of the test, Z is unchanged, and the others
7169 are all undefined. */
7170 switch (s->cc_op) {
7171 case CC_OP_MULB ... CC_OP_MULQ:
7172 case CC_OP_ADDB ... CC_OP_ADDQ:
7173 case CC_OP_ADCB ... CC_OP_ADCQ:
7174 case CC_OP_SUBB ... CC_OP_SUBQ:
7175 case CC_OP_SBBB ... CC_OP_SBBQ:
7176 case CC_OP_LOGICB ... CC_OP_LOGICQ:
7177 case CC_OP_INCB ... CC_OP_INCQ:
7178 case CC_OP_DECB ... CC_OP_DECQ:
7179 case CC_OP_SHLB ... CC_OP_SHLQ:
7180 case CC_OP_SARB ... CC_OP_SARQ:
7181 case CC_OP_BMILGB ... CC_OP_BMILGQ:
7182 /* Z was going to be computed from the non-zero status of CC_DST.
7183 We can get that same Z value (and the new C value) by leaving
7184 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
7185 same width. */
7186 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
7187 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
7188 break;
7189 default:
7190 /* Otherwise, generate EFLAGS and replace the C bit. */
7191 gen_compute_eflags(s);
7192 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, s->tmp4,
7193 ctz32(CC_C), 1);
7194 break;
7196 break;
7197 case 0x1bc: /* bsf / tzcnt */
7198 case 0x1bd: /* bsr / lzcnt */
7199 ot = dflag;
7200 modrm = x86_ldub_code(env, s);
7201 reg = ((modrm >> 3) & 7) | REX_R(s);
7202 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7203 gen_extu(ot, s->T0);
7205 /* Note that lzcnt and tzcnt are in different extensions. */
7206 if ((prefixes & PREFIX_REPZ)
7207 && (b & 1
7208 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
7209 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
7210 int size = 8 << ot;
7211 /* For lzcnt/tzcnt, C bit is defined related to the input. */
7212 tcg_gen_mov_tl(cpu_cc_src, s->T0);
7213 if (b & 1) {
7214 /* For lzcnt, reduce the target_ulong result by the
7215 number of zeros that we expect to find at the top. */
7216 tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
7217 tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
7218 } else {
7219 /* For tzcnt, a zero input must return the operand size. */
7220 tcg_gen_ctzi_tl(s->T0, s->T0, size);
7222 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
7223 gen_op_update1_cc(s);
7224 set_cc_op(s, CC_OP_BMILGB + ot);
7225 } else {
7226 /* For bsr/bsf, only the Z bit is defined and it is related
7227 to the input and not the result. */
7228 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
7229 set_cc_op(s, CC_OP_LOGICB + ot);
7231 /* ??? The manual says that the output is undefined when the
7232 input is zero, but real hardware leaves it unchanged, and
7233 real programs appear to depend on that. Accomplish this
7234 by passing the output as the value to return upon zero. */
7235 if (b & 1) {
7236 /* For bsr, return the bit index of the first 1 bit,
7237 not the count of leading zeros. */
7238 tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
7239 tcg_gen_clz_tl(s->T0, s->T0, s->T1);
7240 tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
7241 } else {
7242 tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
7245 gen_op_mov_reg_v(s, ot, reg, s->T0);
7246 break;
7247 /************************/
7248 /* bcd */
7249 case 0x27: /* daa */
7250 if (CODE64(s))
7251 goto illegal_op;
7252 gen_update_cc_op(s);
7253 gen_helper_daa(cpu_env);
7254 set_cc_op(s, CC_OP_EFLAGS);
7255 break;
7256 case 0x2f: /* das */
7257 if (CODE64(s))
7258 goto illegal_op;
7259 gen_update_cc_op(s);
7260 gen_helper_das(cpu_env);
7261 set_cc_op(s, CC_OP_EFLAGS);
7262 break;
7263 case 0x37: /* aaa */
7264 if (CODE64(s))
7265 goto illegal_op;
7266 gen_update_cc_op(s);
7267 gen_helper_aaa(cpu_env);
7268 set_cc_op(s, CC_OP_EFLAGS);
7269 break;
7270 case 0x3f: /* aas */
7271 if (CODE64(s))
7272 goto illegal_op;
7273 gen_update_cc_op(s);
7274 gen_helper_aas(cpu_env);
7275 set_cc_op(s, CC_OP_EFLAGS);
7276 break;
7277 case 0xd4: /* aam */
7278 if (CODE64(s))
7279 goto illegal_op;
7280 val = x86_ldub_code(env, s);
7281 if (val == 0) {
7282 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7283 } else {
7284 gen_helper_aam(cpu_env, tcg_const_i32(val));
7285 set_cc_op(s, CC_OP_LOGICB);
7287 break;
7288 case 0xd5: /* aad */
7289 if (CODE64(s))
7290 goto illegal_op;
7291 val = x86_ldub_code(env, s);
7292 gen_helper_aad(cpu_env, tcg_const_i32(val));
7293 set_cc_op(s, CC_OP_LOGICB);
7294 break;
7295 /************************/
7296 /* misc */
7297 case 0x90: /* nop */
7298 /* XXX: correct lock test for all insn */
7299 if (prefixes & PREFIX_LOCK) {
7300 goto illegal_op;
7302 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
7303 if (REX_B(s)) {
7304 goto do_xchg_reg_eax;
7306 if (prefixes & PREFIX_REPZ) {
7307 gen_update_cc_op(s);
7308 gen_jmp_im(s, pc_start - s->cs_base);
7309 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
7310 s->base.is_jmp = DISAS_NORETURN;
7312 break;
7313 case 0x9b: /* fwait */
7314 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7315 (HF_MP_MASK | HF_TS_MASK)) {
7316 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7317 } else {
7318 gen_helper_fwait(cpu_env);
7320 break;
7321 case 0xcc: /* int3 */
7322 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7323 break;
7324 case 0xcd: /* int N */
7325 val = x86_ldub_code(env, s);
7326 if (check_vm86_iopl(s)) {
7327 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7329 break;
7330 case 0xce: /* into */
7331 if (CODE64(s))
7332 goto illegal_op;
7333 gen_update_cc_op(s);
7334 gen_jmp_im(s, pc_start - s->cs_base);
7335 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
7336 break;
7337 #ifdef WANT_ICEBP
7338 case 0xf1: /* icebp (undocumented, exits to external debugger) */
7339 gen_svm_check_intercept(s, SVM_EXIT_ICEBP);
7340 gen_debug(s);
7341 break;
7342 #endif
7343 case 0xfa: /* cli */
7344 if (check_iopl(s)) {
7345 gen_helper_cli(cpu_env);
7347 break;
7348 case 0xfb: /* sti */
7349 if (check_iopl(s)) {
7350 gen_helper_sti(cpu_env);
7351 /* interruptions are enabled only the first insn after sti */
7352 gen_jmp_im(s, s->pc - s->cs_base);
7353 gen_eob_inhibit_irq(s, true);
7355 break;
7356 case 0x62: /* bound */
7357 if (CODE64(s))
7358 goto illegal_op;
7359 ot = dflag;
7360 modrm = x86_ldub_code(env, s);
7361 reg = (modrm >> 3) & 7;
7362 mod = (modrm >> 6) & 3;
7363 if (mod == 3)
7364 goto illegal_op;
7365 gen_op_mov_v_reg(s, ot, s->T0, reg);
7366 gen_lea_modrm(env, s, modrm);
7367 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7368 if (ot == MO_16) {
7369 gen_helper_boundw(cpu_env, s->A0, s->tmp2_i32);
7370 } else {
7371 gen_helper_boundl(cpu_env, s->A0, s->tmp2_i32);
7373 break;
7374 case 0x1c8 ... 0x1cf: /* bswap reg */
7375 reg = (b & 7) | REX_B(s);
7376 #ifdef TARGET_X86_64
7377 if (dflag == MO_64) {
7378 tcg_gen_bswap64_i64(cpu_regs[reg], cpu_regs[reg]);
7379 break;
7381 #endif
7382 tcg_gen_bswap32_tl(cpu_regs[reg], cpu_regs[reg], TCG_BSWAP_OZ);
7383 break;
7384 case 0xd6: /* salc */
7385 if (CODE64(s))
7386 goto illegal_op;
7387 gen_compute_eflags_c(s, s->T0);
7388 tcg_gen_neg_tl(s->T0, s->T0);
7389 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
7390 break;
7391 case 0xe0: /* loopnz */
7392 case 0xe1: /* loopz */
7393 case 0xe2: /* loop */
7394 case 0xe3: /* jecxz */
7396 TCGLabel *l1, *l2, *l3;
7398 tval = (int8_t)insn_get(env, s, MO_8);
7399 next_eip = s->pc - s->cs_base;
7400 tval += next_eip;
7401 if (dflag == MO_16) {
7402 tval &= 0xffff;
7405 l1 = gen_new_label();
7406 l2 = gen_new_label();
7407 l3 = gen_new_label();
7408 gen_update_cc_op(s);
7409 b &= 3;
7410 switch(b) {
7411 case 0: /* loopnz */
7412 case 1: /* loopz */
7413 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7414 gen_op_jz_ecx(s, s->aflag, l3);
7415 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7416 break;
7417 case 2: /* loop */
7418 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7419 gen_op_jnz_ecx(s, s->aflag, l1);
7420 break;
7421 default:
7422 case 3: /* jcxz */
7423 gen_op_jz_ecx(s, s->aflag, l1);
7424 break;
7427 gen_set_label(l3);
7428 gen_jmp_im(s, next_eip);
7429 tcg_gen_br(l2);
7431 gen_set_label(l1);
7432 gen_jmp_im(s, tval);
7433 gen_set_label(l2);
7434 gen_eob(s);
7436 break;
7437 case 0x130: /* wrmsr */
7438 case 0x132: /* rdmsr */
7439 if (check_cpl0(s)) {
7440 gen_update_cc_op(s);
7441 gen_jmp_im(s, pc_start - s->cs_base);
7442 if (b & 2) {
7443 gen_helper_rdmsr(cpu_env);
7444 } else {
7445 gen_helper_wrmsr(cpu_env);
7446 gen_jmp_im(s, s->pc - s->cs_base);
7447 gen_eob(s);
7450 break;
7451 case 0x131: /* rdtsc */
7452 gen_update_cc_op(s);
7453 gen_jmp_im(s, pc_start - s->cs_base);
7454 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7455 gen_io_start();
7457 gen_helper_rdtsc(cpu_env);
7458 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7459 gen_jmp(s, s->pc - s->cs_base);
7461 break;
7462 case 0x133: /* rdpmc */
7463 gen_update_cc_op(s);
7464 gen_jmp_im(s, pc_start - s->cs_base);
7465 gen_helper_rdpmc(cpu_env);
7466 s->base.is_jmp = DISAS_NORETURN;
7467 break;
7468 case 0x134: /* sysenter */
7469 /* For Intel SYSENTER is valid on 64-bit */
7470 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7471 goto illegal_op;
7472 if (!PE(s)) {
7473 gen_exception_gpf(s);
7474 } else {
7475 gen_helper_sysenter(cpu_env);
7476 gen_eob(s);
7478 break;
7479 case 0x135: /* sysexit */
7480 /* For Intel SYSEXIT is valid on 64-bit */
7481 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7482 goto illegal_op;
7483 if (!PE(s)) {
7484 gen_exception_gpf(s);
7485 } else {
7486 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7487 gen_eob(s);
7489 break;
7490 #ifdef TARGET_X86_64
7491 case 0x105: /* syscall */
7492 /* XXX: is it usable in real mode ? */
7493 gen_update_cc_op(s);
7494 gen_jmp_im(s, pc_start - s->cs_base);
7495 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7496 /* TF handling for the syscall insn is different. The TF bit is checked
7497 after the syscall insn completes. This allows #DB to not be
7498 generated after one has entered CPL0 if TF is set in FMASK. */
7499 gen_eob_worker(s, false, true);
7500 break;
7501 case 0x107: /* sysret */
7502 if (!PE(s)) {
7503 gen_exception_gpf(s);
7504 } else {
7505 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7506 /* condition codes are modified only in long mode */
7507 if (LMA(s)) {
7508 set_cc_op(s, CC_OP_EFLAGS);
7510 /* TF handling for the sysret insn is different. The TF bit is
7511 checked after the sysret insn completes. This allows #DB to be
7512 generated "as if" the syscall insn in userspace has just
7513 completed. */
7514 gen_eob_worker(s, false, true);
7516 break;
7517 #endif
7518 case 0x1a2: /* cpuid */
7519 gen_update_cc_op(s);
7520 gen_jmp_im(s, pc_start - s->cs_base);
7521 gen_helper_cpuid(cpu_env);
7522 break;
7523 case 0xf4: /* hlt */
7524 if (check_cpl0(s)) {
7525 gen_update_cc_op(s);
7526 gen_jmp_im(s, pc_start - s->cs_base);
7527 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7528 s->base.is_jmp = DISAS_NORETURN;
7530 break;
7531 case 0x100:
7532 modrm = x86_ldub_code(env, s);
7533 mod = (modrm >> 6) & 3;
7534 op = (modrm >> 3) & 7;
7535 switch(op) {
7536 case 0: /* sldt */
7537 if (!PE(s) || VM86(s))
7538 goto illegal_op;
7539 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
7540 break;
7542 gen_svm_check_intercept(s, SVM_EXIT_LDTR_READ);
7543 tcg_gen_ld32u_tl(s->T0, cpu_env,
7544 offsetof(CPUX86State, ldt.selector));
7545 ot = mod == 3 ? dflag : MO_16;
7546 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7547 break;
7548 case 2: /* lldt */
7549 if (!PE(s) || VM86(s))
7550 goto illegal_op;
7551 if (check_cpl0(s)) {
7552 gen_svm_check_intercept(s, SVM_EXIT_LDTR_WRITE);
7553 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7554 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7555 gen_helper_lldt(cpu_env, s->tmp2_i32);
7557 break;
7558 case 1: /* str */
7559 if (!PE(s) || VM86(s))
7560 goto illegal_op;
7561 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
7562 break;
7564 gen_svm_check_intercept(s, SVM_EXIT_TR_READ);
7565 tcg_gen_ld32u_tl(s->T0, cpu_env,
7566 offsetof(CPUX86State, tr.selector));
7567 ot = mod == 3 ? dflag : MO_16;
7568 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7569 break;
7570 case 3: /* ltr */
7571 if (!PE(s) || VM86(s))
7572 goto illegal_op;
7573 if (check_cpl0(s)) {
7574 gen_svm_check_intercept(s, SVM_EXIT_TR_WRITE);
7575 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7576 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7577 gen_helper_ltr(cpu_env, s->tmp2_i32);
7579 break;
7580 case 4: /* verr */
7581 case 5: /* verw */
7582 if (!PE(s) || VM86(s))
7583 goto illegal_op;
7584 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7585 gen_update_cc_op(s);
7586 if (op == 4) {
7587 gen_helper_verr(cpu_env, s->T0);
7588 } else {
7589 gen_helper_verw(cpu_env, s->T0);
7591 set_cc_op(s, CC_OP_EFLAGS);
7592 break;
7593 default:
7594 goto unknown_op;
7596 break;
7598 case 0x101:
7599 modrm = x86_ldub_code(env, s);
7600 switch (modrm) {
7601 CASE_MODRM_MEM_OP(0): /* sgdt */
7602 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
7603 break;
7605 gen_svm_check_intercept(s, SVM_EXIT_GDTR_READ);
7606 gen_lea_modrm(env, s, modrm);
7607 tcg_gen_ld32u_tl(s->T0,
7608 cpu_env, offsetof(CPUX86State, gdt.limit));
7609 gen_op_st_v(s, MO_16, s->T0, s->A0);
7610 gen_add_A0_im(s, 2);
7611 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7612 if (dflag == MO_16) {
7613 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7615 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7616 break;
7618 case 0xc8: /* monitor */
7619 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
7620 goto illegal_op;
7622 gen_update_cc_op(s);
7623 gen_jmp_im(s, pc_start - s->cs_base);
7624 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7625 gen_extu(s->aflag, s->A0);
7626 gen_add_A0_ds_seg(s);
7627 gen_helper_monitor(cpu_env, s->A0);
7628 break;
7630 case 0xc9: /* mwait */
7631 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
7632 goto illegal_op;
7634 gen_update_cc_op(s);
7635 gen_jmp_im(s, pc_start - s->cs_base);
7636 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7637 s->base.is_jmp = DISAS_NORETURN;
7638 break;
7640 case 0xca: /* clac */
7641 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7642 || CPL(s) != 0) {
7643 goto illegal_op;
7645 gen_helper_clac(cpu_env);
7646 gen_jmp_im(s, s->pc - s->cs_base);
7647 gen_eob(s);
7648 break;
7650 case 0xcb: /* stac */
7651 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7652 || CPL(s) != 0) {
7653 goto illegal_op;
7655 gen_helper_stac(cpu_env);
7656 gen_jmp_im(s, s->pc - s->cs_base);
7657 gen_eob(s);
7658 break;
7660 CASE_MODRM_MEM_OP(1): /* sidt */
7661 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
7662 break;
7664 gen_svm_check_intercept(s, SVM_EXIT_IDTR_READ);
7665 gen_lea_modrm(env, s, modrm);
7666 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit));
7667 gen_op_st_v(s, MO_16, s->T0, s->A0);
7668 gen_add_A0_im(s, 2);
7669 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7670 if (dflag == MO_16) {
7671 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7673 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7674 break;
7676 case 0xd0: /* xgetbv */
7677 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7678 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7679 | PREFIX_REPZ | PREFIX_REPNZ))) {
7680 goto illegal_op;
7682 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7683 gen_helper_xgetbv(s->tmp1_i64, cpu_env, s->tmp2_i32);
7684 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7685 break;
7687 case 0xd1: /* xsetbv */
7688 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7689 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7690 | PREFIX_REPZ | PREFIX_REPNZ))) {
7691 goto illegal_op;
7693 if (!check_cpl0(s)) {
7694 break;
7696 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7697 cpu_regs[R_EDX]);
7698 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7699 gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
7700 /* End TB because translation flags may change. */
7701 gen_jmp_im(s, s->pc - s->cs_base);
7702 gen_eob(s);
7703 break;
7705 case 0xd8: /* VMRUN */
7706 if (!SVME(s) || !PE(s)) {
7707 goto illegal_op;
7709 if (!check_cpl0(s)) {
7710 break;
7712 gen_update_cc_op(s);
7713 gen_jmp_im(s, pc_start - s->cs_base);
7714 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7715 tcg_const_i32(s->pc - pc_start));
7716 tcg_gen_exit_tb(NULL, 0);
7717 s->base.is_jmp = DISAS_NORETURN;
7718 break;
7720 case 0xd9: /* VMMCALL */
7721 if (!SVME(s)) {
7722 goto illegal_op;
7724 gen_update_cc_op(s);
7725 gen_jmp_im(s, pc_start - s->cs_base);
7726 gen_helper_vmmcall(cpu_env);
7727 break;
7729 case 0xda: /* VMLOAD */
7730 if (!SVME(s) || !PE(s)) {
7731 goto illegal_op;
7733 if (!check_cpl0(s)) {
7734 break;
7736 gen_update_cc_op(s);
7737 gen_jmp_im(s, pc_start - s->cs_base);
7738 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7739 break;
7741 case 0xdb: /* VMSAVE */
7742 if (!SVME(s) || !PE(s)) {
7743 goto illegal_op;
7745 if (!check_cpl0(s)) {
7746 break;
7748 gen_update_cc_op(s);
7749 gen_jmp_im(s, pc_start - s->cs_base);
7750 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7751 break;
7753 case 0xdc: /* STGI */
7754 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7755 || !PE(s)) {
7756 goto illegal_op;
7758 if (!check_cpl0(s)) {
7759 break;
7761 gen_update_cc_op(s);
7762 gen_helper_stgi(cpu_env);
7763 gen_jmp_im(s, s->pc - s->cs_base);
7764 gen_eob(s);
7765 break;
7767 case 0xdd: /* CLGI */
7768 if (!SVME(s) || !PE(s)) {
7769 goto illegal_op;
7771 if (!check_cpl0(s)) {
7772 break;
7774 gen_update_cc_op(s);
7775 gen_jmp_im(s, pc_start - s->cs_base);
7776 gen_helper_clgi(cpu_env);
7777 break;
7779 case 0xde: /* SKINIT */
7780 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7781 || !PE(s)) {
7782 goto illegal_op;
7784 gen_svm_check_intercept(s, SVM_EXIT_SKINIT);
7785 /* If not intercepted, not implemented -- raise #UD. */
7786 goto illegal_op;
7788 case 0xdf: /* INVLPGA */
7789 if (!SVME(s) || !PE(s)) {
7790 goto illegal_op;
7792 if (!check_cpl0(s)) {
7793 break;
7795 gen_svm_check_intercept(s, SVM_EXIT_INVLPGA);
7796 if (s->aflag == MO_64) {
7797 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7798 } else {
7799 tcg_gen_ext32u_tl(s->A0, cpu_regs[R_EAX]);
7801 gen_helper_flush_page(cpu_env, s->A0);
7802 gen_jmp_im(s, s->pc - s->cs_base);
7803 gen_eob(s);
7804 break;
7806 CASE_MODRM_MEM_OP(2): /* lgdt */
7807 if (!check_cpl0(s)) {
7808 break;
7810 gen_svm_check_intercept(s, SVM_EXIT_GDTR_WRITE);
7811 gen_lea_modrm(env, s, modrm);
7812 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7813 gen_add_A0_im(s, 2);
7814 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7815 if (dflag == MO_16) {
7816 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7818 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7819 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7820 break;
7822 CASE_MODRM_MEM_OP(3): /* lidt */
7823 if (!check_cpl0(s)) {
7824 break;
7826 gen_svm_check_intercept(s, SVM_EXIT_IDTR_WRITE);
7827 gen_lea_modrm(env, s, modrm);
7828 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7829 gen_add_A0_im(s, 2);
7830 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7831 if (dflag == MO_16) {
7832 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7834 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7835 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, idt.limit));
7836 break;
7838 CASE_MODRM_OP(4): /* smsw */
7839 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
7840 break;
7842 gen_svm_check_intercept(s, SVM_EXIT_READ_CR0);
7843 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
7845 * In 32-bit mode, the higher 16 bits of the destination
7846 * register are undefined. In practice CR0[31:0] is stored
7847 * just like in 64-bit mode.
7849 mod = (modrm >> 6) & 3;
7850 ot = (mod != 3 ? MO_16 : s->dflag);
7851 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7852 break;
7853 case 0xee: /* rdpkru */
7854 if (prefixes & PREFIX_LOCK) {
7855 goto illegal_op;
7857 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7858 gen_helper_rdpkru(s->tmp1_i64, cpu_env, s->tmp2_i32);
7859 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7860 break;
7861 case 0xef: /* wrpkru */
7862 if (prefixes & PREFIX_LOCK) {
7863 goto illegal_op;
7865 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7866 cpu_regs[R_EDX]);
7867 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7868 gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64);
7869 break;
7871 CASE_MODRM_OP(6): /* lmsw */
7872 if (!check_cpl0(s)) {
7873 break;
7875 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
7876 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7878 * Only the 4 lower bits of CR0 are modified.
7879 * PE cannot be set to zero if already set to one.
7881 tcg_gen_ld_tl(s->T1, cpu_env, offsetof(CPUX86State, cr[0]));
7882 tcg_gen_andi_tl(s->T0, s->T0, 0xf);
7883 tcg_gen_andi_tl(s->T1, s->T1, ~0xe);
7884 tcg_gen_or_tl(s->T0, s->T0, s->T1);
7885 gen_helper_write_crN(cpu_env, tcg_constant_i32(0), s->T0);
7886 gen_jmp_im(s, s->pc - s->cs_base);
7887 gen_eob(s);
7888 break;
7890 CASE_MODRM_MEM_OP(7): /* invlpg */
7891 if (!check_cpl0(s)) {
7892 break;
7894 gen_svm_check_intercept(s, SVM_EXIT_INVLPG);
7895 gen_lea_modrm(env, s, modrm);
7896 gen_helper_flush_page(cpu_env, s->A0);
7897 gen_jmp_im(s, s->pc - s->cs_base);
7898 gen_eob(s);
7899 break;
7901 case 0xf8: /* swapgs */
7902 #ifdef TARGET_X86_64
7903 if (CODE64(s)) {
7904 if (check_cpl0(s)) {
7905 tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]);
7906 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7907 offsetof(CPUX86State, kernelgsbase));
7908 tcg_gen_st_tl(s->T0, cpu_env,
7909 offsetof(CPUX86State, kernelgsbase));
7911 break;
7913 #endif
7914 goto illegal_op;
7916 case 0xf9: /* rdtscp */
7917 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7918 goto illegal_op;
7920 gen_update_cc_op(s);
7921 gen_jmp_im(s, pc_start - s->cs_base);
7922 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7923 gen_io_start();
7925 gen_helper_rdtscp(cpu_env);
7926 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7927 gen_jmp(s, s->pc - s->cs_base);
7929 break;
7931 default:
7932 goto unknown_op;
7934 break;
7936 case 0x108: /* invd */
7937 case 0x109: /* wbinvd */
7938 if (check_cpl0(s)) {
7939 gen_svm_check_intercept(s, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7940 /* nothing to do */
7942 break;
7943 case 0x63: /* arpl or movslS (x86_64) */
7944 #ifdef TARGET_X86_64
7945 if (CODE64(s)) {
7946 int d_ot;
7947 /* d_ot is the size of destination */
7948 d_ot = dflag;
7950 modrm = x86_ldub_code(env, s);
7951 reg = ((modrm >> 3) & 7) | REX_R(s);
7952 mod = (modrm >> 6) & 3;
7953 rm = (modrm & 7) | REX_B(s);
7955 if (mod == 3) {
7956 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
7957 /* sign extend */
7958 if (d_ot == MO_64) {
7959 tcg_gen_ext32s_tl(s->T0, s->T0);
7961 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7962 } else {
7963 gen_lea_modrm(env, s, modrm);
7964 gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0);
7965 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7967 } else
7968 #endif
7970 TCGLabel *label1;
7971 TCGv t0, t1, t2, a0;
7973 if (!PE(s) || VM86(s))
7974 goto illegal_op;
7975 t0 = tcg_temp_local_new();
7976 t1 = tcg_temp_local_new();
7977 t2 = tcg_temp_local_new();
7978 ot = MO_16;
7979 modrm = x86_ldub_code(env, s);
7980 reg = (modrm >> 3) & 7;
7981 mod = (modrm >> 6) & 3;
7982 rm = modrm & 7;
7983 if (mod != 3) {
7984 gen_lea_modrm(env, s, modrm);
7985 gen_op_ld_v(s, ot, t0, s->A0);
7986 a0 = tcg_temp_local_new();
7987 tcg_gen_mov_tl(a0, s->A0);
7988 } else {
7989 gen_op_mov_v_reg(s, ot, t0, rm);
7990 a0 = NULL;
7992 gen_op_mov_v_reg(s, ot, t1, reg);
7993 tcg_gen_andi_tl(s->tmp0, t0, 3);
7994 tcg_gen_andi_tl(t1, t1, 3);
7995 tcg_gen_movi_tl(t2, 0);
7996 label1 = gen_new_label();
7997 tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1);
7998 tcg_gen_andi_tl(t0, t0, ~3);
7999 tcg_gen_or_tl(t0, t0, t1);
8000 tcg_gen_movi_tl(t2, CC_Z);
8001 gen_set_label(label1);
8002 if (mod != 3) {
8003 gen_op_st_v(s, ot, t0, a0);
8004 tcg_temp_free(a0);
8005 } else {
8006 gen_op_mov_reg_v(s, ot, rm, t0);
8008 gen_compute_eflags(s);
8009 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
8010 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
8011 tcg_temp_free(t0);
8012 tcg_temp_free(t1);
8013 tcg_temp_free(t2);
8015 break;
8016 case 0x102: /* lar */
8017 case 0x103: /* lsl */
8019 TCGLabel *label1;
8020 TCGv t0;
8021 if (!PE(s) || VM86(s))
8022 goto illegal_op;
8023 ot = dflag != MO_16 ? MO_32 : MO_16;
8024 modrm = x86_ldub_code(env, s);
8025 reg = ((modrm >> 3) & 7) | REX_R(s);
8026 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
8027 t0 = tcg_temp_local_new();
8028 gen_update_cc_op(s);
8029 if (b == 0x102) {
8030 gen_helper_lar(t0, cpu_env, s->T0);
8031 } else {
8032 gen_helper_lsl(t0, cpu_env, s->T0);
8034 tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z);
8035 label1 = gen_new_label();
8036 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
8037 gen_op_mov_reg_v(s, ot, reg, t0);
8038 gen_set_label(label1);
8039 set_cc_op(s, CC_OP_EFLAGS);
8040 tcg_temp_free(t0);
8042 break;
8043 case 0x118:
8044 modrm = x86_ldub_code(env, s);
8045 mod = (modrm >> 6) & 3;
8046 op = (modrm >> 3) & 7;
8047 switch(op) {
8048 case 0: /* prefetchnta */
8049 case 1: /* prefetchnt0 */
8050 case 2: /* prefetchnt0 */
8051 case 3: /* prefetchnt0 */
8052 if (mod == 3)
8053 goto illegal_op;
8054 gen_nop_modrm(env, s, modrm);
8055 /* nothing more to do */
8056 break;
8057 default: /* nop (multi byte) */
8058 gen_nop_modrm(env, s, modrm);
8059 break;
8061 break;
8062 case 0x11a:
8063 modrm = x86_ldub_code(env, s);
8064 if (s->flags & HF_MPX_EN_MASK) {
8065 mod = (modrm >> 6) & 3;
8066 reg = ((modrm >> 3) & 7) | REX_R(s);
8067 if (prefixes & PREFIX_REPZ) {
8068 /* bndcl */
8069 if (reg >= 4
8070 || (prefixes & PREFIX_LOCK)
8071 || s->aflag == MO_16) {
8072 goto illegal_op;
8074 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
8075 } else if (prefixes & PREFIX_REPNZ) {
8076 /* bndcu */
8077 if (reg >= 4
8078 || (prefixes & PREFIX_LOCK)
8079 || s->aflag == MO_16) {
8080 goto illegal_op;
8082 TCGv_i64 notu = tcg_temp_new_i64();
8083 tcg_gen_not_i64(notu, cpu_bndu[reg]);
8084 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
8085 tcg_temp_free_i64(notu);
8086 } else if (prefixes & PREFIX_DATA) {
8087 /* bndmov -- from reg/mem */
8088 if (reg >= 4 || s->aflag == MO_16) {
8089 goto illegal_op;
8091 if (mod == 3) {
8092 int reg2 = (modrm & 7) | REX_B(s);
8093 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
8094 goto illegal_op;
8096 if (s->flags & HF_MPX_IU_MASK) {
8097 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
8098 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
8100 } else {
8101 gen_lea_modrm(env, s, modrm);
8102 if (CODE64(s)) {
8103 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
8104 s->mem_index, MO_LEUQ);
8105 tcg_gen_addi_tl(s->A0, s->A0, 8);
8106 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
8107 s->mem_index, MO_LEUQ);
8108 } else {
8109 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
8110 s->mem_index, MO_LEUL);
8111 tcg_gen_addi_tl(s->A0, s->A0, 4);
8112 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
8113 s->mem_index, MO_LEUL);
8115 /* bnd registers are now in-use */
8116 gen_set_hflag(s, HF_MPX_IU_MASK);
8118 } else if (mod != 3) {
8119 /* bndldx */
8120 AddressParts a = gen_lea_modrm_0(env, s, modrm);
8121 if (reg >= 4
8122 || (prefixes & PREFIX_LOCK)
8123 || s->aflag == MO_16
8124 || a.base < -1) {
8125 goto illegal_op;
8127 if (a.base >= 0) {
8128 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
8129 } else {
8130 tcg_gen_movi_tl(s->A0, 0);
8132 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
8133 if (a.index >= 0) {
8134 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
8135 } else {
8136 tcg_gen_movi_tl(s->T0, 0);
8138 if (CODE64(s)) {
8139 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0);
8140 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
8141 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
8142 } else {
8143 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0);
8144 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
8145 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
8147 gen_set_hflag(s, HF_MPX_IU_MASK);
8150 gen_nop_modrm(env, s, modrm);
8151 break;
8152 case 0x11b:
8153 modrm = x86_ldub_code(env, s);
8154 if (s->flags & HF_MPX_EN_MASK) {
8155 mod = (modrm >> 6) & 3;
8156 reg = ((modrm >> 3) & 7) | REX_R(s);
8157 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
8158 /* bndmk */
8159 if (reg >= 4
8160 || (prefixes & PREFIX_LOCK)
8161 || s->aflag == MO_16) {
8162 goto illegal_op;
8164 AddressParts a = gen_lea_modrm_0(env, s, modrm);
8165 if (a.base >= 0) {
8166 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
8167 if (!CODE64(s)) {
8168 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
8170 } else if (a.base == -1) {
8171 /* no base register has lower bound of 0 */
8172 tcg_gen_movi_i64(cpu_bndl[reg], 0);
8173 } else {
8174 /* rip-relative generates #ud */
8175 goto illegal_op;
8177 tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a));
8178 if (!CODE64(s)) {
8179 tcg_gen_ext32u_tl(s->A0, s->A0);
8181 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
8182 /* bnd registers are now in-use */
8183 gen_set_hflag(s, HF_MPX_IU_MASK);
8184 break;
8185 } else if (prefixes & PREFIX_REPNZ) {
8186 /* bndcn */
8187 if (reg >= 4
8188 || (prefixes & PREFIX_LOCK)
8189 || s->aflag == MO_16) {
8190 goto illegal_op;
8192 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
8193 } else if (prefixes & PREFIX_DATA) {
8194 /* bndmov -- to reg/mem */
8195 if (reg >= 4 || s->aflag == MO_16) {
8196 goto illegal_op;
8198 if (mod == 3) {
8199 int reg2 = (modrm & 7) | REX_B(s);
8200 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
8201 goto illegal_op;
8203 if (s->flags & HF_MPX_IU_MASK) {
8204 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
8205 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
8207 } else {
8208 gen_lea_modrm(env, s, modrm);
8209 if (CODE64(s)) {
8210 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
8211 s->mem_index, MO_LEUQ);
8212 tcg_gen_addi_tl(s->A0, s->A0, 8);
8213 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
8214 s->mem_index, MO_LEUQ);
8215 } else {
8216 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
8217 s->mem_index, MO_LEUL);
8218 tcg_gen_addi_tl(s->A0, s->A0, 4);
8219 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
8220 s->mem_index, MO_LEUL);
8223 } else if (mod != 3) {
8224 /* bndstx */
8225 AddressParts a = gen_lea_modrm_0(env, s, modrm);
8226 if (reg >= 4
8227 || (prefixes & PREFIX_LOCK)
8228 || s->aflag == MO_16
8229 || a.base < -1) {
8230 goto illegal_op;
8232 if (a.base >= 0) {
8233 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
8234 } else {
8235 tcg_gen_movi_tl(s->A0, 0);
8237 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
8238 if (a.index >= 0) {
8239 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
8240 } else {
8241 tcg_gen_movi_tl(s->T0, 0);
8243 if (CODE64(s)) {
8244 gen_helper_bndstx64(cpu_env, s->A0, s->T0,
8245 cpu_bndl[reg], cpu_bndu[reg]);
8246 } else {
8247 gen_helper_bndstx32(cpu_env, s->A0, s->T0,
8248 cpu_bndl[reg], cpu_bndu[reg]);
8252 gen_nop_modrm(env, s, modrm);
8253 break;
8254 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
8255 modrm = x86_ldub_code(env, s);
8256 gen_nop_modrm(env, s, modrm);
8257 break;
8259 case 0x120: /* mov reg, crN */
8260 case 0x122: /* mov crN, reg */
8261 if (!check_cpl0(s)) {
8262 break;
8264 modrm = x86_ldub_code(env, s);
8266 * Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8267 * AMD documentation (24594.pdf) and testing of Intel 386 and 486
8268 * processors all show that the mod bits are assumed to be 1's,
8269 * regardless of actual values.
8271 rm = (modrm & 7) | REX_B(s);
8272 reg = ((modrm >> 3) & 7) | REX_R(s);
8273 switch (reg) {
8274 case 0:
8275 if ((prefixes & PREFIX_LOCK) &&
8276 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
8277 reg = 8;
8279 break;
8280 case 2:
8281 case 3:
8282 case 4:
8283 case 8:
8284 break;
8285 default:
8286 goto unknown_op;
8288 ot = (CODE64(s) ? MO_64 : MO_32);
8290 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8291 gen_io_start();
8293 if (b & 2) {
8294 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
8295 gen_op_mov_v_reg(s, ot, s->T0, rm);
8296 gen_helper_write_crN(cpu_env, tcg_constant_i32(reg), s->T0);
8297 gen_jmp_im(s, s->pc - s->cs_base);
8298 gen_eob(s);
8299 } else {
8300 gen_svm_check_intercept(s, SVM_EXIT_READ_CR0 + reg);
8301 gen_helper_read_crN(s->T0, cpu_env, tcg_constant_i32(reg));
8302 gen_op_mov_reg_v(s, ot, rm, s->T0);
8303 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8304 gen_jmp(s, s->pc - s->cs_base);
8307 break;
8309 case 0x121: /* mov reg, drN */
8310 case 0x123: /* mov drN, reg */
8311 if (check_cpl0(s)) {
8312 modrm = x86_ldub_code(env, s);
8313 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8314 * AMD documentation (24594.pdf) and testing of
8315 * intel 386 and 486 processors all show that the mod bits
8316 * are assumed to be 1's, regardless of actual values.
8318 rm = (modrm & 7) | REX_B(s);
8319 reg = ((modrm >> 3) & 7) | REX_R(s);
8320 if (CODE64(s))
8321 ot = MO_64;
8322 else
8323 ot = MO_32;
8324 if (reg >= 8) {
8325 goto illegal_op;
8327 if (b & 2) {
8328 gen_svm_check_intercept(s, SVM_EXIT_WRITE_DR0 + reg);
8329 gen_op_mov_v_reg(s, ot, s->T0, rm);
8330 tcg_gen_movi_i32(s->tmp2_i32, reg);
8331 gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
8332 gen_jmp_im(s, s->pc - s->cs_base);
8333 gen_eob(s);
8334 } else {
8335 gen_svm_check_intercept(s, SVM_EXIT_READ_DR0 + reg);
8336 tcg_gen_movi_i32(s->tmp2_i32, reg);
8337 gen_helper_get_dr(s->T0, cpu_env, s->tmp2_i32);
8338 gen_op_mov_reg_v(s, ot, rm, s->T0);
8341 break;
8342 case 0x106: /* clts */
8343 if (check_cpl0(s)) {
8344 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
8345 gen_helper_clts(cpu_env);
8346 /* abort block because static cpu state changed */
8347 gen_jmp_im(s, s->pc - s->cs_base);
8348 gen_eob(s);
8350 break;
8351 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
8352 case 0x1c3: /* MOVNTI reg, mem */
8353 if (!(s->cpuid_features & CPUID_SSE2))
8354 goto illegal_op;
8355 ot = mo_64_32(dflag);
8356 modrm = x86_ldub_code(env, s);
8357 mod = (modrm >> 6) & 3;
8358 if (mod == 3)
8359 goto illegal_op;
8360 reg = ((modrm >> 3) & 7) | REX_R(s);
8361 /* generate a generic store */
8362 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8363 break;
8364 case 0x1ae:
8365 modrm = x86_ldub_code(env, s);
8366 switch (modrm) {
8367 CASE_MODRM_MEM_OP(0): /* fxsave */
8368 if (!(s->cpuid_features & CPUID_FXSR)
8369 || (prefixes & PREFIX_LOCK)) {
8370 goto illegal_op;
8372 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8373 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8374 break;
8376 gen_lea_modrm(env, s, modrm);
8377 gen_helper_fxsave(cpu_env, s->A0);
8378 break;
8380 CASE_MODRM_MEM_OP(1): /* fxrstor */
8381 if (!(s->cpuid_features & CPUID_FXSR)
8382 || (prefixes & PREFIX_LOCK)) {
8383 goto illegal_op;
8385 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8386 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8387 break;
8389 gen_lea_modrm(env, s, modrm);
8390 gen_helper_fxrstor(cpu_env, s->A0);
8391 break;
8393 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
8394 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8395 goto illegal_op;
8397 if (s->flags & HF_TS_MASK) {
8398 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8399 break;
8401 gen_lea_modrm(env, s, modrm);
8402 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
8403 gen_helper_ldmxcsr(cpu_env, s->tmp2_i32);
8404 break;
8406 CASE_MODRM_MEM_OP(3): /* stmxcsr */
8407 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8408 goto illegal_op;
8410 if (s->flags & HF_TS_MASK) {
8411 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8412 break;
8414 gen_helper_update_mxcsr(cpu_env);
8415 gen_lea_modrm(env, s, modrm);
8416 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr));
8417 gen_op_st_v(s, MO_32, s->T0, s->A0);
8418 break;
8420 CASE_MODRM_MEM_OP(4): /* xsave */
8421 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8422 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8423 | PREFIX_REPZ | PREFIX_REPNZ))) {
8424 goto illegal_op;
8426 gen_lea_modrm(env, s, modrm);
8427 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8428 cpu_regs[R_EDX]);
8429 gen_helper_xsave(cpu_env, s->A0, s->tmp1_i64);
8430 break;
8432 CASE_MODRM_MEM_OP(5): /* xrstor */
8433 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8434 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8435 | PREFIX_REPZ | PREFIX_REPNZ))) {
8436 goto illegal_op;
8438 gen_lea_modrm(env, s, modrm);
8439 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8440 cpu_regs[R_EDX]);
8441 gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64);
8442 /* XRSTOR is how MPX is enabled, which changes how
8443 we translate. Thus we need to end the TB. */
8444 gen_update_cc_op(s);
8445 gen_jmp_im(s, s->pc - s->cs_base);
8446 gen_eob(s);
8447 break;
8449 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
8450 if (prefixes & PREFIX_LOCK) {
8451 goto illegal_op;
8453 if (prefixes & PREFIX_DATA) {
8454 /* clwb */
8455 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8456 goto illegal_op;
8458 gen_nop_modrm(env, s, modrm);
8459 } else {
8460 /* xsaveopt */
8461 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8462 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8463 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8464 goto illegal_op;
8466 gen_lea_modrm(env, s, modrm);
8467 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8468 cpu_regs[R_EDX]);
8469 gen_helper_xsaveopt(cpu_env, s->A0, s->tmp1_i64);
8471 break;
8473 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
8474 if (prefixes & PREFIX_LOCK) {
8475 goto illegal_op;
8477 if (prefixes & PREFIX_DATA) {
8478 /* clflushopt */
8479 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8480 goto illegal_op;
8482 } else {
8483 /* clflush */
8484 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8485 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8486 goto illegal_op;
8489 gen_nop_modrm(env, s, modrm);
8490 break;
8492 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
8493 case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
8494 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
8495 case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
8496 if (CODE64(s)
8497 && (prefixes & PREFIX_REPZ)
8498 && !(prefixes & PREFIX_LOCK)
8499 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8500 TCGv base, treg, src, dst;
8502 /* Preserve hflags bits by testing CR4 at runtime. */
8503 tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
8504 gen_helper_cr4_testbit(cpu_env, s->tmp2_i32);
8506 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8507 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8509 if (modrm & 0x10) {
8510 /* wr*base */
8511 dst = base, src = treg;
8512 } else {
8513 /* rd*base */
8514 dst = treg, src = base;
8517 if (s->dflag == MO_32) {
8518 tcg_gen_ext32u_tl(dst, src);
8519 } else {
8520 tcg_gen_mov_tl(dst, src);
8522 break;
8524 goto unknown_op;
8526 case 0xf8: /* sfence / pcommit */
8527 if (prefixes & PREFIX_DATA) {
8528 /* pcommit */
8529 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8530 || (prefixes & PREFIX_LOCK)) {
8531 goto illegal_op;
8533 break;
8535 /* fallthru */
8536 case 0xf9 ... 0xff: /* sfence */
8537 if (!(s->cpuid_features & CPUID_SSE)
8538 || (prefixes & PREFIX_LOCK)) {
8539 goto illegal_op;
8541 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8542 break;
8543 case 0xe8 ... 0xef: /* lfence */
8544 if (!(s->cpuid_features & CPUID_SSE)
8545 || (prefixes & PREFIX_LOCK)) {
8546 goto illegal_op;
8548 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8549 break;
8550 case 0xf0 ... 0xf7: /* mfence */
8551 if (!(s->cpuid_features & CPUID_SSE2)
8552 || (prefixes & PREFIX_LOCK)) {
8553 goto illegal_op;
8555 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8556 break;
8558 default:
8559 goto unknown_op;
8561 break;
8563 case 0x10d: /* 3DNow! prefetch(w) */
8564 modrm = x86_ldub_code(env, s);
8565 mod = (modrm >> 6) & 3;
8566 if (mod == 3)
8567 goto illegal_op;
8568 gen_nop_modrm(env, s, modrm);
8569 break;
8570 case 0x1aa: /* rsm */
8571 gen_svm_check_intercept(s, SVM_EXIT_RSM);
8572 if (!(s->flags & HF_SMM_MASK))
8573 goto illegal_op;
8574 #ifdef CONFIG_USER_ONLY
8575 /* we should not be in SMM mode */
8576 g_assert_not_reached();
8577 #else
8578 gen_update_cc_op(s);
8579 gen_jmp_im(s, s->pc - s->cs_base);
8580 gen_helper_rsm(cpu_env);
8581 #endif /* CONFIG_USER_ONLY */
8582 gen_eob(s);
8583 break;
8584 case 0x1b8: /* SSE4.2 popcnt */
8585 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8586 PREFIX_REPZ)
8587 goto illegal_op;
8588 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8589 goto illegal_op;
8591 modrm = x86_ldub_code(env, s);
8592 reg = ((modrm >> 3) & 7) | REX_R(s);
8594 if (s->prefix & PREFIX_DATA) {
8595 ot = MO_16;
8596 } else {
8597 ot = mo_64_32(dflag);
8600 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8601 gen_extu(ot, s->T0);
8602 tcg_gen_mov_tl(cpu_cc_src, s->T0);
8603 tcg_gen_ctpop_tl(s->T0, s->T0);
8604 gen_op_mov_reg_v(s, ot, reg, s->T0);
8606 set_cc_op(s, CC_OP_POPCNT);
8607 break;
8608 case 0x10e ... 0x10f:
8609 /* 3DNow! instructions, ignore prefixes */
8610 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8611 /* fall through */
8612 case 0x110 ... 0x117:
8613 case 0x128 ... 0x12f:
8614 case 0x138 ... 0x13a:
8615 case 0x150 ... 0x179:
8616 case 0x17c ... 0x17f:
8617 case 0x1c2:
8618 case 0x1c4 ... 0x1c6:
8619 case 0x1d0 ... 0x1fe:
8620 gen_sse(env, s, b, pc_start);
8621 break;
8622 default:
8623 goto unknown_op;
8625 return s->pc;
8626 illegal_op:
8627 gen_illegal_opcode(s);
8628 return s->pc;
8629 unknown_op:
8630 gen_unknown_opcode(env, s);
8631 return s->pc;
8634 void tcg_x86_init(void)
8636 static const char reg_names[CPU_NB_REGS][4] = {
8637 #ifdef TARGET_X86_64
8638 [R_EAX] = "rax",
8639 [R_EBX] = "rbx",
8640 [R_ECX] = "rcx",
8641 [R_EDX] = "rdx",
8642 [R_ESI] = "rsi",
8643 [R_EDI] = "rdi",
8644 [R_EBP] = "rbp",
8645 [R_ESP] = "rsp",
8646 [8] = "r8",
8647 [9] = "r9",
8648 [10] = "r10",
8649 [11] = "r11",
8650 [12] = "r12",
8651 [13] = "r13",
8652 [14] = "r14",
8653 [15] = "r15",
8654 #else
8655 [R_EAX] = "eax",
8656 [R_EBX] = "ebx",
8657 [R_ECX] = "ecx",
8658 [R_EDX] = "edx",
8659 [R_ESI] = "esi",
8660 [R_EDI] = "edi",
8661 [R_EBP] = "ebp",
8662 [R_ESP] = "esp",
8663 #endif
8665 static const char seg_base_names[6][8] = {
8666 [R_CS] = "cs_base",
8667 [R_DS] = "ds_base",
8668 [R_ES] = "es_base",
8669 [R_FS] = "fs_base",
8670 [R_GS] = "gs_base",
8671 [R_SS] = "ss_base",
8673 static const char bnd_regl_names[4][8] = {
8674 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8676 static const char bnd_regu_names[4][8] = {
8677 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8679 int i;
8681 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8682 offsetof(CPUX86State, cc_op), "cc_op");
8683 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8684 "cc_dst");
8685 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8686 "cc_src");
8687 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8688 "cc_src2");
8690 for (i = 0; i < CPU_NB_REGS; ++i) {
8691 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8692 offsetof(CPUX86State, regs[i]),
8693 reg_names[i]);
8696 for (i = 0; i < 6; ++i) {
8697 cpu_seg_base[i]
8698 = tcg_global_mem_new(cpu_env,
8699 offsetof(CPUX86State, segs[i].base),
8700 seg_base_names[i]);
8703 for (i = 0; i < 4; ++i) {
8704 cpu_bndl[i]
8705 = tcg_global_mem_new_i64(cpu_env,
8706 offsetof(CPUX86State, bnd_regs[i].lb),
8707 bnd_regl_names[i]);
8708 cpu_bndu[i]
8709 = tcg_global_mem_new_i64(cpu_env,
8710 offsetof(CPUX86State, bnd_regs[i].ub),
8711 bnd_regu_names[i]);
8715 static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
8717 DisasContext *dc = container_of(dcbase, DisasContext, base);
8718 CPUX86State *env = cpu->env_ptr;
8719 uint32_t flags = dc->base.tb->flags;
8720 uint32_t cflags = tb_cflags(dc->base.tb);
8721 int cpl = (flags >> HF_CPL_SHIFT) & 3;
8722 int iopl = (flags >> IOPL_SHIFT) & 3;
8724 dc->cs_base = dc->base.tb->cs_base;
8725 dc->flags = flags;
8726 #ifndef CONFIG_USER_ONLY
8727 dc->cpl = cpl;
8728 dc->iopl = iopl;
8729 #endif
8731 /* We make some simplifying assumptions; validate they're correct. */
8732 g_assert(PE(dc) == ((flags & HF_PE_MASK) != 0));
8733 g_assert(CPL(dc) == cpl);
8734 g_assert(IOPL(dc) == iopl);
8735 g_assert(VM86(dc) == ((flags & HF_VM_MASK) != 0));
8736 g_assert(CODE32(dc) == ((flags & HF_CS32_MASK) != 0));
8737 g_assert(CODE64(dc) == ((flags & HF_CS64_MASK) != 0));
8738 g_assert(SS32(dc) == ((flags & HF_SS32_MASK) != 0));
8739 g_assert(LMA(dc) == ((flags & HF_LMA_MASK) != 0));
8740 g_assert(ADDSEG(dc) == ((flags & HF_ADDSEG_MASK) != 0));
8741 g_assert(SVME(dc) == ((flags & HF_SVME_MASK) != 0));
8742 g_assert(GUEST(dc) == ((flags & HF_GUEST_MASK) != 0));
8744 dc->cc_op = CC_OP_DYNAMIC;
8745 dc->cc_op_dirty = false;
8746 dc->popl_esp_hack = 0;
8747 /* select memory access functions */
8748 dc->mem_index = 0;
8749 #ifdef CONFIG_SOFTMMU
8750 dc->mem_index = cpu_mmu_index(env, false);
8751 #endif
8752 dc->cpuid_features = env->features[FEAT_1_EDX];
8753 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8754 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8755 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8756 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8757 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8758 dc->jmp_opt = !((cflags & CF_NO_GOTO_TB) ||
8759 (flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)));
8761 * If jmp_opt, we want to handle each string instruction individually.
8762 * For icount also disable repz optimization so that each iteration
8763 * is accounted separately.
8765 dc->repz_opt = !dc->jmp_opt && !(cflags & CF_USE_ICOUNT);
8767 dc->T0 = tcg_temp_new();
8768 dc->T1 = tcg_temp_new();
8769 dc->A0 = tcg_temp_new();
8771 dc->tmp0 = tcg_temp_new();
8772 dc->tmp1_i64 = tcg_temp_new_i64();
8773 dc->tmp2_i32 = tcg_temp_new_i32();
8774 dc->tmp3_i32 = tcg_temp_new_i32();
8775 dc->tmp4 = tcg_temp_new();
8776 dc->ptr0 = tcg_temp_new_ptr();
8777 dc->ptr1 = tcg_temp_new_ptr();
8778 dc->cc_srcT = tcg_temp_local_new();
8781 static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
8785 static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8787 DisasContext *dc = container_of(dcbase, DisasContext, base);
8789 dc->prev_insn_end = tcg_last_op();
8790 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
8793 static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8795 DisasContext *dc = container_of(dcbase, DisasContext, base);
8796 target_ulong pc_next;
8798 #ifdef TARGET_VSYSCALL_PAGE
8800 * Detect entry into the vsyscall page and invoke the syscall.
8802 if ((dc->base.pc_next & TARGET_PAGE_MASK) == TARGET_VSYSCALL_PAGE) {
8803 gen_exception(dc, EXCP_VSYSCALL, dc->base.pc_next);
8804 dc->base.pc_next = dc->pc + 1;
8805 return;
8807 #endif
8809 pc_next = disas_insn(dc, cpu);
8810 dc->base.pc_next = pc_next;
8812 if (dc->base.is_jmp == DISAS_NEXT) {
8813 if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
8815 * If single step mode, we generate only one instruction and
8816 * generate an exception.
8817 * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8818 * the flag and abort the translation to give the irqs a
8819 * chance to happen.
8821 dc->base.is_jmp = DISAS_TOO_MANY;
8822 } else if (!is_same_page(&dc->base, pc_next)) {
8823 dc->base.is_jmp = DISAS_TOO_MANY;
8828 static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8830 DisasContext *dc = container_of(dcbase, DisasContext, base);
8832 if (dc->base.is_jmp == DISAS_TOO_MANY) {
8833 gen_jmp_im(dc, dc->base.pc_next - dc->cs_base);
8834 gen_eob(dc);
8838 static void i386_tr_disas_log(const DisasContextBase *dcbase,
8839 CPUState *cpu, FILE *logfile)
8841 DisasContext *dc = container_of(dcbase, DisasContext, base);
8843 fprintf(logfile, "IN: %s\n", lookup_symbol(dc->base.pc_first));
8844 target_disas(logfile, cpu, dc->base.pc_first, dc->base.tb->size);
8847 static const TranslatorOps i386_tr_ops = {
8848 .init_disas_context = i386_tr_init_disas_context,
8849 .tb_start = i386_tr_tb_start,
8850 .insn_start = i386_tr_insn_start,
8851 .translate_insn = i386_tr_translate_insn,
8852 .tb_stop = i386_tr_tb_stop,
8853 .disas_log = i386_tr_disas_log,
8856 /* generate intermediate code for basic block 'tb'. */
8857 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
8858 target_ulong pc, void *host_pc)
8860 DisasContext dc;
8862 translator_loop(cpu, tb, max_insns, pc, host_pc, &i386_tr_ops, &dc.base);
8865 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8866 target_ulong *data)
8868 int cc_op = data[1];
8869 env->eip = data[0] - tb->cs_base;
8870 if (cc_op != CC_OP_DYNAMIC) {
8871 env->cc_op = cc_op;