block: improve error handling in raw_open
[qemu/ar7.git] / target-i386 / translate.c
blob23fde58547ab26d29a577d903fda3568b4045d08
1 /*
2 * i386 translation
4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include "qemu/host-utils.h"
22 #include "cpu.h"
23 #include "disas/disas.h"
24 #include "exec/exec-all.h"
25 #include "tcg-op.h"
26 #include "exec/cpu_ldst.h"
28 #include "exec/helper-proto.h"
29 #include "exec/helper-gen.h"
31 #include "trace-tcg.h"
32 #include "exec/log.h"
35 #define PREFIX_REPZ 0x01
36 #define PREFIX_REPNZ 0x02
37 #define PREFIX_LOCK 0x04
38 #define PREFIX_DATA 0x08
39 #define PREFIX_ADR 0x10
40 #define PREFIX_VEX 0x20
42 #ifdef TARGET_X86_64
43 #define CODE64(s) ((s)->code64)
44 #define REX_X(s) ((s)->rex_x)
45 #define REX_B(s) ((s)->rex_b)
46 #else
47 #define CODE64(s) 0
48 #define REX_X(s) 0
49 #define REX_B(s) 0
50 #endif
52 #ifdef TARGET_X86_64
53 # define ctztl ctz64
54 # define clztl clz64
55 #else
56 # define ctztl ctz32
57 # define clztl clz32
58 #endif
60 /* For a switch indexed by MODRM, match all memory operands for a given OP. */
61 #define CASE_MODRM_MEM_OP(OP) \
62 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
63 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
64 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
66 #define CASE_MODRM_OP(OP) \
67 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
68 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
69 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
70 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
72 //#define MACRO_TEST 1
74 /* global register indexes */
75 static TCGv_env cpu_env;
76 static TCGv cpu_A0;
77 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
78 static TCGv_i32 cpu_cc_op;
79 static TCGv cpu_regs[CPU_NB_REGS];
80 static TCGv cpu_seg_base[6];
81 static TCGv_i64 cpu_bndl[4];
82 static TCGv_i64 cpu_bndu[4];
83 /* local temps */
84 static TCGv cpu_T0, cpu_T1;
85 /* local register indexes (only used inside old micro ops) */
86 static TCGv cpu_tmp0, cpu_tmp4;
87 static TCGv_ptr cpu_ptr0, cpu_ptr1;
88 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
89 static TCGv_i64 cpu_tmp1_i64;
91 #include "exec/gen-icount.h"
93 #ifdef TARGET_X86_64
94 static int x86_64_hregs;
95 #endif
97 typedef struct DisasContext {
98 /* current insn context */
99 int override; /* -1 if no override */
100 int prefix;
101 TCGMemOp aflag;
102 TCGMemOp dflag;
103 target_ulong pc_start;
104 target_ulong pc; /* pc = eip + cs_base */
105 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
106 static state change (stop translation) */
107 /* current block context */
108 target_ulong cs_base; /* base of CS segment */
109 int pe; /* protected mode */
110 int code32; /* 32 bit code segment */
111 #ifdef TARGET_X86_64
112 int lma; /* long mode active */
113 int code64; /* 64 bit code segment */
114 int rex_x, rex_b;
115 #endif
116 int vex_l; /* vex vector length */
117 int vex_v; /* vex vvvv register, without 1's compliment. */
118 int ss32; /* 32 bit stack segment */
119 CCOp cc_op; /* current CC operation */
120 bool cc_op_dirty;
121 int addseg; /* non zero if either DS/ES/SS have a non zero base */
122 int f_st; /* currently unused */
123 int vm86; /* vm86 mode */
124 int cpl;
125 int iopl;
126 int tf; /* TF cpu flag */
127 int singlestep_enabled; /* "hardware" single step enabled */
128 int jmp_opt; /* use direct block chaining for direct jumps */
129 int repz_opt; /* optimize jumps within repz instructions */
130 int mem_index; /* select memory access functions */
131 uint64_t flags; /* all execution flags */
132 struct TranslationBlock *tb;
133 int popl_esp_hack; /* for correct popl with esp base handling */
134 int rip_offset; /* only used in x86_64, but left for simplicity */
135 int cpuid_features;
136 int cpuid_ext_features;
137 int cpuid_ext2_features;
138 int cpuid_ext3_features;
139 int cpuid_7_0_ebx_features;
140 int cpuid_xsave_features;
141 } DisasContext;
143 static void gen_eob(DisasContext *s);
144 static void gen_jmp(DisasContext *s, target_ulong eip);
145 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
146 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d);
148 /* i386 arith/logic operations */
149 enum {
150 OP_ADDL,
151 OP_ORL,
152 OP_ADCL,
153 OP_SBBL,
154 OP_ANDL,
155 OP_SUBL,
156 OP_XORL,
157 OP_CMPL,
160 /* i386 shift ops */
161 enum {
162 OP_ROL,
163 OP_ROR,
164 OP_RCL,
165 OP_RCR,
166 OP_SHL,
167 OP_SHR,
168 OP_SHL1, /* undocumented */
169 OP_SAR = 7,
172 enum {
173 JCC_O,
174 JCC_B,
175 JCC_Z,
176 JCC_BE,
177 JCC_S,
178 JCC_P,
179 JCC_L,
180 JCC_LE,
183 enum {
184 /* I386 int registers */
185 OR_EAX, /* MUST be even numbered */
186 OR_ECX,
187 OR_EDX,
188 OR_EBX,
189 OR_ESP,
190 OR_EBP,
191 OR_ESI,
192 OR_EDI,
194 OR_TMP0 = 16, /* temporary operand register */
195 OR_TMP1,
196 OR_A0, /* temporary register used when doing address evaluation */
199 enum {
200 USES_CC_DST = 1,
201 USES_CC_SRC = 2,
202 USES_CC_SRC2 = 4,
203 USES_CC_SRCT = 8,
206 /* Bit set if the global variable is live after setting CC_OP to X. */
207 static const uint8_t cc_op_live[CC_OP_NB] = {
208 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
209 [CC_OP_EFLAGS] = USES_CC_SRC,
210 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
211 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
212 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
213 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
214 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
215 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
216 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
217 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
218 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
219 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
220 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
221 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
222 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
223 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
224 [CC_OP_CLR] = 0,
227 static void set_cc_op(DisasContext *s, CCOp op)
229 int dead;
231 if (s->cc_op == op) {
232 return;
235 /* Discard CC computation that will no longer be used. */
236 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
237 if (dead & USES_CC_DST) {
238 tcg_gen_discard_tl(cpu_cc_dst);
240 if (dead & USES_CC_SRC) {
241 tcg_gen_discard_tl(cpu_cc_src);
243 if (dead & USES_CC_SRC2) {
244 tcg_gen_discard_tl(cpu_cc_src2);
246 if (dead & USES_CC_SRCT) {
247 tcg_gen_discard_tl(cpu_cc_srcT);
250 if (op == CC_OP_DYNAMIC) {
251 /* The DYNAMIC setting is translator only, and should never be
252 stored. Thus we always consider it clean. */
253 s->cc_op_dirty = false;
254 } else {
255 /* Discard any computed CC_OP value (see shifts). */
256 if (s->cc_op == CC_OP_DYNAMIC) {
257 tcg_gen_discard_i32(cpu_cc_op);
259 s->cc_op_dirty = true;
261 s->cc_op = op;
264 static void gen_update_cc_op(DisasContext *s)
266 if (s->cc_op_dirty) {
267 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
268 s->cc_op_dirty = false;
272 #ifdef TARGET_X86_64
274 #define NB_OP_SIZES 4
276 #else /* !TARGET_X86_64 */
278 #define NB_OP_SIZES 3
280 #endif /* !TARGET_X86_64 */
282 #if defined(HOST_WORDS_BIGENDIAN)
283 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
284 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
285 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
286 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
287 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
288 #else
289 #define REG_B_OFFSET 0
290 #define REG_H_OFFSET 1
291 #define REG_W_OFFSET 0
292 #define REG_L_OFFSET 0
293 #define REG_LH_OFFSET 4
294 #endif
296 /* In instruction encodings for byte register accesses the
297 * register number usually indicates "low 8 bits of register N";
298 * however there are some special cases where N 4..7 indicates
299 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
300 * true for this special case, false otherwise.
302 static inline bool byte_reg_is_xH(int reg)
304 if (reg < 4) {
305 return false;
307 #ifdef TARGET_X86_64
308 if (reg >= 8 || x86_64_hregs) {
309 return false;
311 #endif
312 return true;
315 /* Select the size of a push/pop operation. */
316 static inline TCGMemOp mo_pushpop(DisasContext *s, TCGMemOp ot)
318 if (CODE64(s)) {
319 return ot == MO_16 ? MO_16 : MO_64;
320 } else {
321 return ot;
325 /* Select the size of the stack pointer. */
326 static inline TCGMemOp mo_stacksize(DisasContext *s)
328 return CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
331 /* Select only size 64 else 32. Used for SSE operand sizes. */
332 static inline TCGMemOp mo_64_32(TCGMemOp ot)
334 #ifdef TARGET_X86_64
335 return ot == MO_64 ? MO_64 : MO_32;
336 #else
337 return MO_32;
338 #endif
341 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
342 byte vs word opcodes. */
343 static inline TCGMemOp mo_b_d(int b, TCGMemOp ot)
345 return b & 1 ? ot : MO_8;
348 /* Select size 8 if lsb of B is clear, else OT capped at 32.
349 Used for decoding operand size of port opcodes. */
350 static inline TCGMemOp mo_b_d32(int b, TCGMemOp ot)
352 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
355 static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
357 switch(ot) {
358 case MO_8:
359 if (!byte_reg_is_xH(reg)) {
360 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
361 } else {
362 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
364 break;
365 case MO_16:
366 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
367 break;
368 case MO_32:
369 /* For x86_64, this sets the higher half of register to zero.
370 For i386, this is equivalent to a mov. */
371 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
372 break;
373 #ifdef TARGET_X86_64
374 case MO_64:
375 tcg_gen_mov_tl(cpu_regs[reg], t0);
376 break;
377 #endif
378 default:
379 tcg_abort();
383 static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
385 if (ot == MO_8 && byte_reg_is_xH(reg)) {
386 tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
387 tcg_gen_ext8u_tl(t0, t0);
388 } else {
389 tcg_gen_mov_tl(t0, cpu_regs[reg]);
393 static void gen_add_A0_im(DisasContext *s, int val)
395 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
396 if (!CODE64(s)) {
397 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
401 static inline void gen_op_jmp_v(TCGv dest)
403 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
406 static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
408 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
409 gen_op_mov_reg_v(size, reg, cpu_tmp0);
412 static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
414 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T0);
415 gen_op_mov_reg_v(size, reg, cpu_tmp0);
418 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
420 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
423 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
425 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
428 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
430 if (d == OR_TMP0) {
431 gen_op_st_v(s, idx, cpu_T0, cpu_A0);
432 } else {
433 gen_op_mov_reg_v(idx, d, cpu_T0);
437 static inline void gen_jmp_im(target_ulong pc)
439 tcg_gen_movi_tl(cpu_tmp0, pc);
440 gen_op_jmp_v(cpu_tmp0);
443 /* Compute SEG:REG into A0. SEG is selected from the override segment
444 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
445 indicate no override. */
446 static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
447 int def_seg, int ovr_seg)
449 switch (aflag) {
450 #ifdef TARGET_X86_64
451 case MO_64:
452 if (ovr_seg < 0) {
453 tcg_gen_mov_tl(cpu_A0, a0);
454 return;
456 break;
457 #endif
458 case MO_32:
459 /* 32 bit address */
460 if (ovr_seg < 0 && s->addseg) {
461 ovr_seg = def_seg;
463 if (ovr_seg < 0) {
464 tcg_gen_ext32u_tl(cpu_A0, a0);
465 return;
467 break;
468 case MO_16:
469 /* 16 bit address */
470 tcg_gen_ext16u_tl(cpu_A0, a0);
471 a0 = cpu_A0;
472 if (ovr_seg < 0) {
473 if (s->addseg) {
474 ovr_seg = def_seg;
475 } else {
476 return;
479 break;
480 default:
481 tcg_abort();
484 if (ovr_seg >= 0) {
485 TCGv seg = cpu_seg_base[ovr_seg];
487 if (aflag == MO_64) {
488 tcg_gen_add_tl(cpu_A0, a0, seg);
489 } else if (CODE64(s)) {
490 tcg_gen_ext32u_tl(cpu_A0, a0);
491 tcg_gen_add_tl(cpu_A0, cpu_A0, seg);
492 } else {
493 tcg_gen_add_tl(cpu_A0, a0, seg);
494 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
499 static inline void gen_string_movl_A0_ESI(DisasContext *s)
501 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
504 static inline void gen_string_movl_A0_EDI(DisasContext *s)
506 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
509 static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
511 tcg_gen_ld32s_tl(cpu_T0, cpu_env, offsetof(CPUX86State, df));
512 tcg_gen_shli_tl(cpu_T0, cpu_T0, ot);
515 static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign)
517 switch (size) {
518 case MO_8:
519 if (sign) {
520 tcg_gen_ext8s_tl(dst, src);
521 } else {
522 tcg_gen_ext8u_tl(dst, src);
524 return dst;
525 case MO_16:
526 if (sign) {
527 tcg_gen_ext16s_tl(dst, src);
528 } else {
529 tcg_gen_ext16u_tl(dst, src);
531 return dst;
532 #ifdef TARGET_X86_64
533 case MO_32:
534 if (sign) {
535 tcg_gen_ext32s_tl(dst, src);
536 } else {
537 tcg_gen_ext32u_tl(dst, src);
539 return dst;
540 #endif
541 default:
542 return src;
546 static void gen_extu(TCGMemOp ot, TCGv reg)
548 gen_ext_tl(reg, reg, ot, false);
551 static void gen_exts(TCGMemOp ot, TCGv reg)
553 gen_ext_tl(reg, reg, ot, true);
556 static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1)
558 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
559 gen_extu(size, cpu_tmp0);
560 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
563 static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1)
565 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
566 gen_extu(size, cpu_tmp0);
567 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
570 static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n)
572 switch (ot) {
573 case MO_8:
574 gen_helper_inb(v, cpu_env, n);
575 break;
576 case MO_16:
577 gen_helper_inw(v, cpu_env, n);
578 break;
579 case MO_32:
580 gen_helper_inl(v, cpu_env, n);
581 break;
582 default:
583 tcg_abort();
587 static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n)
589 switch (ot) {
590 case MO_8:
591 gen_helper_outb(cpu_env, v, n);
592 break;
593 case MO_16:
594 gen_helper_outw(cpu_env, v, n);
595 break;
596 case MO_32:
597 gen_helper_outl(cpu_env, v, n);
598 break;
599 default:
600 tcg_abort();
604 static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
605 uint32_t svm_flags)
607 target_ulong next_eip;
609 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
610 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
611 switch (ot) {
612 case MO_8:
613 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
614 break;
615 case MO_16:
616 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
617 break;
618 case MO_32:
619 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
620 break;
621 default:
622 tcg_abort();
625 if(s->flags & HF_SVMI_MASK) {
626 gen_update_cc_op(s);
627 gen_jmp_im(cur_eip);
628 svm_flags |= (1 << (4 + ot));
629 next_eip = s->pc - s->cs_base;
630 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
631 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
632 tcg_const_i32(svm_flags),
633 tcg_const_i32(next_eip - cur_eip));
637 static inline void gen_movs(DisasContext *s, TCGMemOp ot)
639 gen_string_movl_A0_ESI(s);
640 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
641 gen_string_movl_A0_EDI(s);
642 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
643 gen_op_movl_T0_Dshift(ot);
644 gen_op_add_reg_T0(s->aflag, R_ESI);
645 gen_op_add_reg_T0(s->aflag, R_EDI);
648 static void gen_op_update1_cc(void)
650 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
653 static void gen_op_update2_cc(void)
655 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
656 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
659 static void gen_op_update3_cc(TCGv reg)
661 tcg_gen_mov_tl(cpu_cc_src2, reg);
662 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
663 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
666 static inline void gen_op_testl_T0_T1_cc(void)
668 tcg_gen_and_tl(cpu_cc_dst, cpu_T0, cpu_T1);
671 static void gen_op_update_neg_cc(void)
673 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
674 tcg_gen_neg_tl(cpu_cc_src, cpu_T0);
675 tcg_gen_movi_tl(cpu_cc_srcT, 0);
678 /* compute all eflags to cc_src */
679 static void gen_compute_eflags(DisasContext *s)
681 TCGv zero, dst, src1, src2;
682 int live, dead;
684 if (s->cc_op == CC_OP_EFLAGS) {
685 return;
687 if (s->cc_op == CC_OP_CLR) {
688 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
689 set_cc_op(s, CC_OP_EFLAGS);
690 return;
693 TCGV_UNUSED(zero);
694 dst = cpu_cc_dst;
695 src1 = cpu_cc_src;
696 src2 = cpu_cc_src2;
698 /* Take care to not read values that are not live. */
699 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
700 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
701 if (dead) {
702 zero = tcg_const_tl(0);
703 if (dead & USES_CC_DST) {
704 dst = zero;
706 if (dead & USES_CC_SRC) {
707 src1 = zero;
709 if (dead & USES_CC_SRC2) {
710 src2 = zero;
714 gen_update_cc_op(s);
715 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
716 set_cc_op(s, CC_OP_EFLAGS);
718 if (dead) {
719 tcg_temp_free(zero);
723 typedef struct CCPrepare {
724 TCGCond cond;
725 TCGv reg;
726 TCGv reg2;
727 target_ulong imm;
728 target_ulong mask;
729 bool use_reg2;
730 bool no_setcond;
731 } CCPrepare;
733 /* compute eflags.C to reg */
734 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
736 TCGv t0, t1;
737 int size, shift;
739 switch (s->cc_op) {
740 case CC_OP_SUBB ... CC_OP_SUBQ:
741 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
742 size = s->cc_op - CC_OP_SUBB;
743 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
744 /* If no temporary was used, be careful not to alias t1 and t0. */
745 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
746 tcg_gen_mov_tl(t0, cpu_cc_srcT);
747 gen_extu(size, t0);
748 goto add_sub;
750 case CC_OP_ADDB ... CC_OP_ADDQ:
751 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
752 size = s->cc_op - CC_OP_ADDB;
753 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
754 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
755 add_sub:
756 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
757 .reg2 = t1, .mask = -1, .use_reg2 = true };
759 case CC_OP_LOGICB ... CC_OP_LOGICQ:
760 case CC_OP_CLR:
761 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
763 case CC_OP_INCB ... CC_OP_INCQ:
764 case CC_OP_DECB ... CC_OP_DECQ:
765 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
766 .mask = -1, .no_setcond = true };
768 case CC_OP_SHLB ... CC_OP_SHLQ:
769 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
770 size = s->cc_op - CC_OP_SHLB;
771 shift = (8 << size) - 1;
772 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
773 .mask = (target_ulong)1 << shift };
775 case CC_OP_MULB ... CC_OP_MULQ:
776 return (CCPrepare) { .cond = TCG_COND_NE,
777 .reg = cpu_cc_src, .mask = -1 };
779 case CC_OP_BMILGB ... CC_OP_BMILGQ:
780 size = s->cc_op - CC_OP_BMILGB;
781 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
782 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
784 case CC_OP_ADCX:
785 case CC_OP_ADCOX:
786 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
787 .mask = -1, .no_setcond = true };
789 case CC_OP_EFLAGS:
790 case CC_OP_SARB ... CC_OP_SARQ:
791 /* CC_SRC & 1 */
792 return (CCPrepare) { .cond = TCG_COND_NE,
793 .reg = cpu_cc_src, .mask = CC_C };
795 default:
796 /* The need to compute only C from CC_OP_DYNAMIC is important
797 in efficiently implementing e.g. INC at the start of a TB. */
798 gen_update_cc_op(s);
799 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
800 cpu_cc_src2, cpu_cc_op);
801 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
802 .mask = -1, .no_setcond = true };
806 /* compute eflags.P to reg */
807 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
809 gen_compute_eflags(s);
810 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
811 .mask = CC_P };
814 /* compute eflags.S to reg */
815 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
817 switch (s->cc_op) {
818 case CC_OP_DYNAMIC:
819 gen_compute_eflags(s);
820 /* FALLTHRU */
821 case CC_OP_EFLAGS:
822 case CC_OP_ADCX:
823 case CC_OP_ADOX:
824 case CC_OP_ADCOX:
825 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
826 .mask = CC_S };
827 case CC_OP_CLR:
828 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
829 default:
831 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
832 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
833 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
838 /* compute eflags.O to reg */
839 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
841 switch (s->cc_op) {
842 case CC_OP_ADOX:
843 case CC_OP_ADCOX:
844 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
845 .mask = -1, .no_setcond = true };
846 case CC_OP_CLR:
847 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
848 default:
849 gen_compute_eflags(s);
850 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
851 .mask = CC_O };
855 /* compute eflags.Z to reg */
856 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
858 switch (s->cc_op) {
859 case CC_OP_DYNAMIC:
860 gen_compute_eflags(s);
861 /* FALLTHRU */
862 case CC_OP_EFLAGS:
863 case CC_OP_ADCX:
864 case CC_OP_ADOX:
865 case CC_OP_ADCOX:
866 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
867 .mask = CC_Z };
868 case CC_OP_CLR:
869 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
870 default:
872 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
873 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
874 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
879 /* perform a conditional store into register 'reg' according to jump opcode
880 value 'b'. In the fast case, T0 is guaranted not to be used. */
881 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
883 int inv, jcc_op, cond;
884 TCGMemOp size;
885 CCPrepare cc;
886 TCGv t0;
888 inv = b & 1;
889 jcc_op = (b >> 1) & 7;
891 switch (s->cc_op) {
892 case CC_OP_SUBB ... CC_OP_SUBQ:
893 /* We optimize relational operators for the cmp/jcc case. */
894 size = s->cc_op - CC_OP_SUBB;
895 switch (jcc_op) {
896 case JCC_BE:
897 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
898 gen_extu(size, cpu_tmp4);
899 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
900 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
901 .reg2 = t0, .mask = -1, .use_reg2 = true };
902 break;
904 case JCC_L:
905 cond = TCG_COND_LT;
906 goto fast_jcc_l;
907 case JCC_LE:
908 cond = TCG_COND_LE;
909 fast_jcc_l:
910 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
911 gen_exts(size, cpu_tmp4);
912 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
913 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
914 .reg2 = t0, .mask = -1, .use_reg2 = true };
915 break;
917 default:
918 goto slow_jcc;
920 break;
922 default:
923 slow_jcc:
924 /* This actually generates good code for JC, JZ and JS. */
925 switch (jcc_op) {
926 case JCC_O:
927 cc = gen_prepare_eflags_o(s, reg);
928 break;
929 case JCC_B:
930 cc = gen_prepare_eflags_c(s, reg);
931 break;
932 case JCC_Z:
933 cc = gen_prepare_eflags_z(s, reg);
934 break;
935 case JCC_BE:
936 gen_compute_eflags(s);
937 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
938 .mask = CC_Z | CC_C };
939 break;
940 case JCC_S:
941 cc = gen_prepare_eflags_s(s, reg);
942 break;
943 case JCC_P:
944 cc = gen_prepare_eflags_p(s, reg);
945 break;
946 case JCC_L:
947 gen_compute_eflags(s);
948 if (TCGV_EQUAL(reg, cpu_cc_src)) {
949 reg = cpu_tmp0;
951 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
952 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
953 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
954 .mask = CC_S };
955 break;
956 default:
957 case JCC_LE:
958 gen_compute_eflags(s);
959 if (TCGV_EQUAL(reg, cpu_cc_src)) {
960 reg = cpu_tmp0;
962 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
963 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
964 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
965 .mask = CC_S | CC_Z };
966 break;
968 break;
971 if (inv) {
972 cc.cond = tcg_invert_cond(cc.cond);
974 return cc;
977 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
979 CCPrepare cc = gen_prepare_cc(s, b, reg);
981 if (cc.no_setcond) {
982 if (cc.cond == TCG_COND_EQ) {
983 tcg_gen_xori_tl(reg, cc.reg, 1);
984 } else {
985 tcg_gen_mov_tl(reg, cc.reg);
987 return;
990 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
991 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
992 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
993 tcg_gen_andi_tl(reg, reg, 1);
994 return;
996 if (cc.mask != -1) {
997 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
998 cc.reg = reg;
1000 if (cc.use_reg2) {
1001 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1002 } else {
1003 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1007 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1009 gen_setcc1(s, JCC_B << 1, reg);
1012 /* generate a conditional jump to label 'l1' according to jump opcode
1013 value 'b'. In the fast case, T0 is guaranted not to be used. */
1014 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1016 CCPrepare cc = gen_prepare_cc(s, b, cpu_T0);
1018 if (cc.mask != -1) {
1019 tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask);
1020 cc.reg = cpu_T0;
1022 if (cc.use_reg2) {
1023 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1024 } else {
1025 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1029 /* Generate a conditional jump to label 'l1' according to jump opcode
1030 value 'b'. In the fast case, T0 is guaranted not to be used.
1031 A translation block must end soon. */
1032 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1034 CCPrepare cc = gen_prepare_cc(s, b, cpu_T0);
1036 gen_update_cc_op(s);
1037 if (cc.mask != -1) {
1038 tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask);
1039 cc.reg = cpu_T0;
1041 set_cc_op(s, CC_OP_DYNAMIC);
1042 if (cc.use_reg2) {
1043 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1044 } else {
1045 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1049 /* XXX: does not work with gdbstub "ice" single step - not a
1050 serious problem */
1051 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1053 TCGLabel *l1 = gen_new_label();
1054 TCGLabel *l2 = gen_new_label();
1055 gen_op_jnz_ecx(s->aflag, l1);
1056 gen_set_label(l2);
1057 gen_jmp_tb(s, next_eip, 1);
1058 gen_set_label(l1);
1059 return l2;
1062 static inline void gen_stos(DisasContext *s, TCGMemOp ot)
1064 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
1065 gen_string_movl_A0_EDI(s);
1066 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1067 gen_op_movl_T0_Dshift(ot);
1068 gen_op_add_reg_T0(s->aflag, R_EDI);
1071 static inline void gen_lods(DisasContext *s, TCGMemOp ot)
1073 gen_string_movl_A0_ESI(s);
1074 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1075 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
1076 gen_op_movl_T0_Dshift(ot);
1077 gen_op_add_reg_T0(s->aflag, R_ESI);
1080 static inline void gen_scas(DisasContext *s, TCGMemOp ot)
1082 gen_string_movl_A0_EDI(s);
1083 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
1084 gen_op(s, OP_CMPL, ot, R_EAX);
1085 gen_op_movl_T0_Dshift(ot);
1086 gen_op_add_reg_T0(s->aflag, R_EDI);
1089 static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
1091 gen_string_movl_A0_EDI(s);
1092 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
1093 gen_string_movl_A0_ESI(s);
1094 gen_op(s, OP_CMPL, ot, OR_TMP0);
1095 gen_op_movl_T0_Dshift(ot);
1096 gen_op_add_reg_T0(s->aflag, R_ESI);
1097 gen_op_add_reg_T0(s->aflag, R_EDI);
1100 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1102 if (s->flags & HF_IOBPT_MASK) {
1103 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1104 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1106 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1107 tcg_temp_free_i32(t_size);
1108 tcg_temp_free(t_next);
1113 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
1115 if (s->tb->cflags & CF_USE_ICOUNT) {
1116 gen_io_start();
1118 gen_string_movl_A0_EDI(s);
1119 /* Note: we must do this dummy write first to be restartable in
1120 case of page fault. */
1121 tcg_gen_movi_tl(cpu_T0, 0);
1122 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1123 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1124 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1125 gen_helper_in_func(ot, cpu_T0, cpu_tmp2_i32);
1126 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1127 gen_op_movl_T0_Dshift(ot);
1128 gen_op_add_reg_T0(s->aflag, R_EDI);
1129 gen_bpt_io(s, cpu_tmp2_i32, ot);
1130 if (s->tb->cflags & CF_USE_ICOUNT) {
1131 gen_io_end();
1135 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
1137 if (s->tb->cflags & CF_USE_ICOUNT) {
1138 gen_io_start();
1140 gen_string_movl_A0_ESI(s);
1141 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1143 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1144 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1145 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T0);
1146 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1147 gen_op_movl_T0_Dshift(ot);
1148 gen_op_add_reg_T0(s->aflag, R_ESI);
1149 gen_bpt_io(s, cpu_tmp2_i32, ot);
1150 if (s->tb->cflags & CF_USE_ICOUNT) {
1151 gen_io_end();
1155 /* same method as Valgrind : we generate jumps to current or next
1156 instruction */
1157 #define GEN_REPZ(op) \
1158 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1159 target_ulong cur_eip, target_ulong next_eip) \
1161 TCGLabel *l2; \
1162 gen_update_cc_op(s); \
1163 l2 = gen_jz_ecx_string(s, next_eip); \
1164 gen_ ## op(s, ot); \
1165 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1166 /* a loop would cause two single step exceptions if ECX = 1 \
1167 before rep string_insn */ \
1168 if (s->repz_opt) \
1169 gen_op_jz_ecx(s->aflag, l2); \
1170 gen_jmp(s, cur_eip); \
1173 #define GEN_REPZ2(op) \
1174 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1175 target_ulong cur_eip, \
1176 target_ulong next_eip, \
1177 int nz) \
1179 TCGLabel *l2; \
1180 gen_update_cc_op(s); \
1181 l2 = gen_jz_ecx_string(s, next_eip); \
1182 gen_ ## op(s, ot); \
1183 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1184 gen_update_cc_op(s); \
1185 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1186 if (s->repz_opt) \
1187 gen_op_jz_ecx(s->aflag, l2); \
1188 gen_jmp(s, cur_eip); \
1191 GEN_REPZ(movs)
1192 GEN_REPZ(stos)
1193 GEN_REPZ(lods)
1194 GEN_REPZ(ins)
1195 GEN_REPZ(outs)
1196 GEN_REPZ2(scas)
1197 GEN_REPZ2(cmps)
1199 static void gen_helper_fp_arith_ST0_FT0(int op)
1201 switch (op) {
1202 case 0:
1203 gen_helper_fadd_ST0_FT0(cpu_env);
1204 break;
1205 case 1:
1206 gen_helper_fmul_ST0_FT0(cpu_env);
1207 break;
1208 case 2:
1209 gen_helper_fcom_ST0_FT0(cpu_env);
1210 break;
1211 case 3:
1212 gen_helper_fcom_ST0_FT0(cpu_env);
1213 break;
1214 case 4:
1215 gen_helper_fsub_ST0_FT0(cpu_env);
1216 break;
1217 case 5:
1218 gen_helper_fsubr_ST0_FT0(cpu_env);
1219 break;
1220 case 6:
1221 gen_helper_fdiv_ST0_FT0(cpu_env);
1222 break;
1223 case 7:
1224 gen_helper_fdivr_ST0_FT0(cpu_env);
1225 break;
1229 /* NOTE the exception in "r" op ordering */
1230 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1232 TCGv_i32 tmp = tcg_const_i32(opreg);
1233 switch (op) {
1234 case 0:
1235 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1236 break;
1237 case 1:
1238 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1239 break;
1240 case 4:
1241 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1242 break;
1243 case 5:
1244 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1245 break;
1246 case 6:
1247 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1248 break;
1249 case 7:
1250 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1251 break;
1255 /* if d == OR_TMP0, it means memory operand (address in A0) */
1256 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
1258 if (d != OR_TMP0) {
1259 gen_op_mov_v_reg(ot, cpu_T0, d);
1260 } else {
1261 gen_op_ld_v(s1, ot, cpu_T0, cpu_A0);
1263 switch(op) {
1264 case OP_ADCL:
1265 gen_compute_eflags_c(s1, cpu_tmp4);
1266 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
1267 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_tmp4);
1268 gen_op_st_rm_T0_A0(s1, ot, d);
1269 gen_op_update3_cc(cpu_tmp4);
1270 set_cc_op(s1, CC_OP_ADCB + ot);
1271 break;
1272 case OP_SBBL:
1273 gen_compute_eflags_c(s1, cpu_tmp4);
1274 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1);
1275 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_tmp4);
1276 gen_op_st_rm_T0_A0(s1, ot, d);
1277 gen_op_update3_cc(cpu_tmp4);
1278 set_cc_op(s1, CC_OP_SBBB + ot);
1279 break;
1280 case OP_ADDL:
1281 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
1282 gen_op_st_rm_T0_A0(s1, ot, d);
1283 gen_op_update2_cc();
1284 set_cc_op(s1, CC_OP_ADDB + ot);
1285 break;
1286 case OP_SUBL:
1287 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0);
1288 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1);
1289 gen_op_st_rm_T0_A0(s1, ot, d);
1290 gen_op_update2_cc();
1291 set_cc_op(s1, CC_OP_SUBB + ot);
1292 break;
1293 default:
1294 case OP_ANDL:
1295 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
1296 gen_op_st_rm_T0_A0(s1, ot, d);
1297 gen_op_update1_cc();
1298 set_cc_op(s1, CC_OP_LOGICB + ot);
1299 break;
1300 case OP_ORL:
1301 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1);
1302 gen_op_st_rm_T0_A0(s1, ot, d);
1303 gen_op_update1_cc();
1304 set_cc_op(s1, CC_OP_LOGICB + ot);
1305 break;
1306 case OP_XORL:
1307 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_T1);
1308 gen_op_st_rm_T0_A0(s1, ot, d);
1309 gen_op_update1_cc();
1310 set_cc_op(s1, CC_OP_LOGICB + ot);
1311 break;
1312 case OP_CMPL:
1313 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
1314 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0);
1315 tcg_gen_sub_tl(cpu_cc_dst, cpu_T0, cpu_T1);
1316 set_cc_op(s1, CC_OP_SUBB + ot);
1317 break;
1321 /* if d == OR_TMP0, it means memory operand (address in A0) */
1322 static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
1324 if (d != OR_TMP0) {
1325 gen_op_mov_v_reg(ot, cpu_T0, d);
1326 } else {
1327 gen_op_ld_v(s1, ot, cpu_T0, cpu_A0);
1329 gen_compute_eflags_c(s1, cpu_cc_src);
1330 if (c > 0) {
1331 tcg_gen_addi_tl(cpu_T0, cpu_T0, 1);
1332 set_cc_op(s1, CC_OP_INCB + ot);
1333 } else {
1334 tcg_gen_addi_tl(cpu_T0, cpu_T0, -1);
1335 set_cc_op(s1, CC_OP_DECB + ot);
1337 gen_op_st_rm_T0_A0(s1, ot, d);
1338 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
1341 static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
1342 TCGv shm1, TCGv count, bool is_right)
1344 TCGv_i32 z32, s32, oldop;
1345 TCGv z_tl;
1347 /* Store the results into the CC variables. If we know that the
1348 variable must be dead, store unconditionally. Otherwise we'll
1349 need to not disrupt the current contents. */
1350 z_tl = tcg_const_tl(0);
1351 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1352 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1353 result, cpu_cc_dst);
1354 } else {
1355 tcg_gen_mov_tl(cpu_cc_dst, result);
1357 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1358 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1359 shm1, cpu_cc_src);
1360 } else {
1361 tcg_gen_mov_tl(cpu_cc_src, shm1);
1363 tcg_temp_free(z_tl);
1365 /* Get the two potential CC_OP values into temporaries. */
1366 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1367 if (s->cc_op == CC_OP_DYNAMIC) {
1368 oldop = cpu_cc_op;
1369 } else {
1370 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1371 oldop = cpu_tmp3_i32;
1374 /* Conditionally store the CC_OP value. */
1375 z32 = tcg_const_i32(0);
1376 s32 = tcg_temp_new_i32();
1377 tcg_gen_trunc_tl_i32(s32, count);
1378 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1379 tcg_temp_free_i32(z32);
1380 tcg_temp_free_i32(s32);
1382 /* The CC_OP value is no longer predictable. */
1383 set_cc_op(s, CC_OP_DYNAMIC);
1386 static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1387 int is_right, int is_arith)
1389 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1391 /* load */
1392 if (op1 == OR_TMP0) {
1393 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1394 } else {
1395 gen_op_mov_v_reg(ot, cpu_T0, op1);
1398 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1399 tcg_gen_subi_tl(cpu_tmp0, cpu_T1, 1);
1401 if (is_right) {
1402 if (is_arith) {
1403 gen_exts(ot, cpu_T0);
1404 tcg_gen_sar_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1405 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
1406 } else {
1407 gen_extu(ot, cpu_T0);
1408 tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1409 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
1411 } else {
1412 tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1413 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
1416 /* store */
1417 gen_op_st_rm_T0_A0(s, ot, op1);
1419 gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, cpu_T1, is_right);
1422 static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1423 int is_right, int is_arith)
1425 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1427 /* load */
1428 if (op1 == OR_TMP0)
1429 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1430 else
1431 gen_op_mov_v_reg(ot, cpu_T0, op1);
1433 op2 &= mask;
1434 if (op2 != 0) {
1435 if (is_right) {
1436 if (is_arith) {
1437 gen_exts(ot, cpu_T0);
1438 tcg_gen_sari_tl(cpu_tmp4, cpu_T0, op2 - 1);
1439 tcg_gen_sari_tl(cpu_T0, cpu_T0, op2);
1440 } else {
1441 gen_extu(ot, cpu_T0);
1442 tcg_gen_shri_tl(cpu_tmp4, cpu_T0, op2 - 1);
1443 tcg_gen_shri_tl(cpu_T0, cpu_T0, op2);
1445 } else {
1446 tcg_gen_shli_tl(cpu_tmp4, cpu_T0, op2 - 1);
1447 tcg_gen_shli_tl(cpu_T0, cpu_T0, op2);
1451 /* store */
1452 gen_op_st_rm_T0_A0(s, ot, op1);
1454 /* update eflags if non zero shift */
1455 if (op2 != 0) {
1456 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1457 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
1458 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1462 static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
1464 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1465 TCGv_i32 t0, t1;
1467 /* load */
1468 if (op1 == OR_TMP0) {
1469 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1470 } else {
1471 gen_op_mov_v_reg(ot, cpu_T0, op1);
1474 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1476 switch (ot) {
1477 case MO_8:
1478 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1479 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
1480 tcg_gen_muli_tl(cpu_T0, cpu_T0, 0x01010101);
1481 goto do_long;
1482 case MO_16:
1483 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1484 tcg_gen_deposit_tl(cpu_T0, cpu_T0, cpu_T0, 16, 16);
1485 goto do_long;
1486 do_long:
1487 #ifdef TARGET_X86_64
1488 case MO_32:
1489 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
1490 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
1491 if (is_right) {
1492 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1493 } else {
1494 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1496 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
1497 break;
1498 #endif
1499 default:
1500 if (is_right) {
1501 tcg_gen_rotr_tl(cpu_T0, cpu_T0, cpu_T1);
1502 } else {
1503 tcg_gen_rotl_tl(cpu_T0, cpu_T0, cpu_T1);
1505 break;
1508 /* store */
1509 gen_op_st_rm_T0_A0(s, ot, op1);
1511 /* We'll need the flags computed into CC_SRC. */
1512 gen_compute_eflags(s);
1514 /* The value that was "rotated out" is now present at the other end
1515 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1516 since we've computed the flags into CC_SRC, these variables are
1517 currently dead. */
1518 if (is_right) {
1519 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1);
1520 tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask);
1521 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1522 } else {
1523 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask);
1524 tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1);
1526 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1527 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1529 /* Now conditionally store the new CC_OP value. If the shift count
1530 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1531 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1532 exactly as we computed above. */
1533 t0 = tcg_const_i32(0);
1534 t1 = tcg_temp_new_i32();
1535 tcg_gen_trunc_tl_i32(t1, cpu_T1);
1536 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1537 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1538 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1539 cpu_tmp2_i32, cpu_tmp3_i32);
1540 tcg_temp_free_i32(t0);
1541 tcg_temp_free_i32(t1);
1543 /* The CC_OP value is no longer predictable. */
1544 set_cc_op(s, CC_OP_DYNAMIC);
1547 static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1548 int is_right)
1550 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1551 int shift;
1553 /* load */
1554 if (op1 == OR_TMP0) {
1555 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1556 } else {
1557 gen_op_mov_v_reg(ot, cpu_T0, op1);
1560 op2 &= mask;
1561 if (op2 != 0) {
1562 switch (ot) {
1563 #ifdef TARGET_X86_64
1564 case MO_32:
1565 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
1566 if (is_right) {
1567 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1568 } else {
1569 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1571 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
1572 break;
1573 #endif
1574 default:
1575 if (is_right) {
1576 tcg_gen_rotri_tl(cpu_T0, cpu_T0, op2);
1577 } else {
1578 tcg_gen_rotli_tl(cpu_T0, cpu_T0, op2);
1580 break;
1581 case MO_8:
1582 mask = 7;
1583 goto do_shifts;
1584 case MO_16:
1585 mask = 15;
1586 do_shifts:
1587 shift = op2 & mask;
1588 if (is_right) {
1589 shift = mask + 1 - shift;
1591 gen_extu(ot, cpu_T0);
1592 tcg_gen_shli_tl(cpu_tmp0, cpu_T0, shift);
1593 tcg_gen_shri_tl(cpu_T0, cpu_T0, mask + 1 - shift);
1594 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
1595 break;
1599 /* store */
1600 gen_op_st_rm_T0_A0(s, ot, op1);
1602 if (op2 != 0) {
1603 /* Compute the flags into CC_SRC. */
1604 gen_compute_eflags(s);
1606 /* The value that was "rotated out" is now present at the other end
1607 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1608 since we've computed the flags into CC_SRC, these variables are
1609 currently dead. */
1610 if (is_right) {
1611 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1);
1612 tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask);
1613 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1614 } else {
1615 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask);
1616 tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1);
1618 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1619 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1620 set_cc_op(s, CC_OP_ADCOX);
1624 /* XXX: add faster immediate = 1 case */
1625 static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1626 int is_right)
1628 gen_compute_eflags(s);
1629 assert(s->cc_op == CC_OP_EFLAGS);
1631 /* load */
1632 if (op1 == OR_TMP0)
1633 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1634 else
1635 gen_op_mov_v_reg(ot, cpu_T0, op1);
1637 if (is_right) {
1638 switch (ot) {
1639 case MO_8:
1640 gen_helper_rcrb(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1641 break;
1642 case MO_16:
1643 gen_helper_rcrw(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1644 break;
1645 case MO_32:
1646 gen_helper_rcrl(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1647 break;
1648 #ifdef TARGET_X86_64
1649 case MO_64:
1650 gen_helper_rcrq(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1651 break;
1652 #endif
1653 default:
1654 tcg_abort();
1656 } else {
1657 switch (ot) {
1658 case MO_8:
1659 gen_helper_rclb(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1660 break;
1661 case MO_16:
1662 gen_helper_rclw(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1663 break;
1664 case MO_32:
1665 gen_helper_rcll(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1666 break;
1667 #ifdef TARGET_X86_64
1668 case MO_64:
1669 gen_helper_rclq(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1670 break;
1671 #endif
1672 default:
1673 tcg_abort();
1676 /* store */
1677 gen_op_st_rm_T0_A0(s, ot, op1);
1680 /* XXX: add faster immediate case */
1681 static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1682 bool is_right, TCGv count_in)
1684 target_ulong mask = (ot == MO_64 ? 63 : 31);
1685 TCGv count;
1687 /* load */
1688 if (op1 == OR_TMP0) {
1689 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1690 } else {
1691 gen_op_mov_v_reg(ot, cpu_T0, op1);
1694 count = tcg_temp_new();
1695 tcg_gen_andi_tl(count, count_in, mask);
1697 switch (ot) {
1698 case MO_16:
1699 /* Note: we implement the Intel behaviour for shift count > 16.
1700 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1701 portion by constructing it as a 32-bit value. */
1702 if (is_right) {
1703 tcg_gen_deposit_tl(cpu_tmp0, cpu_T0, cpu_T1, 16, 16);
1704 tcg_gen_mov_tl(cpu_T1, cpu_T0);
1705 tcg_gen_mov_tl(cpu_T0, cpu_tmp0);
1706 } else {
1707 tcg_gen_deposit_tl(cpu_T1, cpu_T0, cpu_T1, 16, 16);
1709 /* FALLTHRU */
1710 #ifdef TARGET_X86_64
1711 case MO_32:
1712 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1713 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1714 if (is_right) {
1715 tcg_gen_concat_tl_i64(cpu_T0, cpu_T0, cpu_T1);
1716 tcg_gen_shr_i64(cpu_tmp0, cpu_T0, cpu_tmp0);
1717 tcg_gen_shr_i64(cpu_T0, cpu_T0, count);
1718 } else {
1719 tcg_gen_concat_tl_i64(cpu_T0, cpu_T1, cpu_T0);
1720 tcg_gen_shl_i64(cpu_tmp0, cpu_T0, cpu_tmp0);
1721 tcg_gen_shl_i64(cpu_T0, cpu_T0, count);
1722 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1723 tcg_gen_shri_i64(cpu_T0, cpu_T0, 32);
1725 break;
1726 #endif
1727 default:
1728 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1729 if (is_right) {
1730 tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1732 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1733 tcg_gen_shr_tl(cpu_T0, cpu_T0, count);
1734 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_tmp4);
1735 } else {
1736 tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1737 if (ot == MO_16) {
1738 /* Only needed if count > 16, for Intel behaviour. */
1739 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1740 tcg_gen_shr_tl(cpu_tmp4, cpu_T1, cpu_tmp4);
1741 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1744 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1745 tcg_gen_shl_tl(cpu_T0, cpu_T0, count);
1746 tcg_gen_shr_tl(cpu_T1, cpu_T1, cpu_tmp4);
1748 tcg_gen_movi_tl(cpu_tmp4, 0);
1749 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T1, count, cpu_tmp4,
1750 cpu_tmp4, cpu_T1);
1751 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1);
1752 break;
1755 /* store */
1756 gen_op_st_rm_T0_A0(s, ot, op1);
1758 gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, count, is_right);
1759 tcg_temp_free(count);
1762 static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
1764 if (s != OR_TMP1)
1765 gen_op_mov_v_reg(ot, cpu_T1, s);
1766 switch(op) {
1767 case OP_ROL:
1768 gen_rot_rm_T1(s1, ot, d, 0);
1769 break;
1770 case OP_ROR:
1771 gen_rot_rm_T1(s1, ot, d, 1);
1772 break;
1773 case OP_SHL:
1774 case OP_SHL1:
1775 gen_shift_rm_T1(s1, ot, d, 0, 0);
1776 break;
1777 case OP_SHR:
1778 gen_shift_rm_T1(s1, ot, d, 1, 0);
1779 break;
1780 case OP_SAR:
1781 gen_shift_rm_T1(s1, ot, d, 1, 1);
1782 break;
1783 case OP_RCL:
1784 gen_rotc_rm_T1(s1, ot, d, 0);
1785 break;
1786 case OP_RCR:
1787 gen_rotc_rm_T1(s1, ot, d, 1);
1788 break;
1792 static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
1794 switch(op) {
1795 case OP_ROL:
1796 gen_rot_rm_im(s1, ot, d, c, 0);
1797 break;
1798 case OP_ROR:
1799 gen_rot_rm_im(s1, ot, d, c, 1);
1800 break;
1801 case OP_SHL:
1802 case OP_SHL1:
1803 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1804 break;
1805 case OP_SHR:
1806 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1807 break;
1808 case OP_SAR:
1809 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1810 break;
1811 default:
1812 /* currently not optimized */
1813 tcg_gen_movi_tl(cpu_T1, c);
1814 gen_shift(s1, op, ot, d, OR_TMP1);
1815 break;
1819 /* Decompose an address. */
1821 typedef struct AddressParts {
1822 int def_seg;
1823 int base;
1824 int index;
1825 int scale;
1826 target_long disp;
1827 } AddressParts;
1829 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
1830 int modrm)
1832 int def_seg, base, index, scale, mod, rm;
1833 target_long disp;
1834 bool havesib;
1836 def_seg = R_DS;
1837 index = -1;
1838 scale = 0;
1839 disp = 0;
1841 mod = (modrm >> 6) & 3;
1842 rm = modrm & 7;
1843 base = rm | REX_B(s);
1845 if (mod == 3) {
1846 /* Normally filtered out earlier, but including this path
1847 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
1848 goto done;
1851 switch (s->aflag) {
1852 case MO_64:
1853 case MO_32:
1854 havesib = 0;
1855 if (rm == 4) {
1856 int code = cpu_ldub_code(env, s->pc++);
1857 scale = (code >> 6) & 3;
1858 index = ((code >> 3) & 7) | REX_X(s);
1859 if (index == 4) {
1860 index = -1; /* no index */
1862 base = (code & 7) | REX_B(s);
1863 havesib = 1;
1866 switch (mod) {
1867 case 0:
1868 if ((base & 7) == 5) {
1869 base = -1;
1870 disp = (int32_t)cpu_ldl_code(env, s->pc);
1871 s->pc += 4;
1872 if (CODE64(s) && !havesib) {
1873 base = -2;
1874 disp += s->pc + s->rip_offset;
1877 break;
1878 case 1:
1879 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1880 break;
1881 default:
1882 case 2:
1883 disp = (int32_t)cpu_ldl_code(env, s->pc);
1884 s->pc += 4;
1885 break;
1888 /* For correct popl handling with esp. */
1889 if (base == R_ESP && s->popl_esp_hack) {
1890 disp += s->popl_esp_hack;
1892 if (base == R_EBP || base == R_ESP) {
1893 def_seg = R_SS;
1895 break;
1897 case MO_16:
1898 if (mod == 0) {
1899 if (rm == 6) {
1900 base = -1;
1901 disp = cpu_lduw_code(env, s->pc);
1902 s->pc += 2;
1903 break;
1905 } else if (mod == 1) {
1906 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1907 } else {
1908 disp = (int16_t)cpu_lduw_code(env, s->pc);
1909 s->pc += 2;
1912 switch (rm) {
1913 case 0:
1914 base = R_EBX;
1915 index = R_ESI;
1916 break;
1917 case 1:
1918 base = R_EBX;
1919 index = R_EDI;
1920 break;
1921 case 2:
1922 base = R_EBP;
1923 index = R_ESI;
1924 def_seg = R_SS;
1925 break;
1926 case 3:
1927 base = R_EBP;
1928 index = R_EDI;
1929 def_seg = R_SS;
1930 break;
1931 case 4:
1932 base = R_ESI;
1933 break;
1934 case 5:
1935 base = R_EDI;
1936 break;
1937 case 6:
1938 base = R_EBP;
1939 def_seg = R_SS;
1940 break;
1941 default:
1942 case 7:
1943 base = R_EBX;
1944 break;
1946 break;
1948 default:
1949 tcg_abort();
1952 done:
1953 return (AddressParts){ def_seg, base, index, scale, disp };
1956 /* Compute the address, with a minimum number of TCG ops. */
1957 static TCGv gen_lea_modrm_1(AddressParts a)
1959 TCGv ea;
1961 TCGV_UNUSED(ea);
1962 if (a.index >= 0) {
1963 if (a.scale == 0) {
1964 ea = cpu_regs[a.index];
1965 } else {
1966 tcg_gen_shli_tl(cpu_A0, cpu_regs[a.index], a.scale);
1967 ea = cpu_A0;
1969 if (a.base >= 0) {
1970 tcg_gen_add_tl(cpu_A0, ea, cpu_regs[a.base]);
1971 ea = cpu_A0;
1973 } else if (a.base >= 0) {
1974 ea = cpu_regs[a.base];
1976 if (TCGV_IS_UNUSED(ea)) {
1977 tcg_gen_movi_tl(cpu_A0, a.disp);
1978 ea = cpu_A0;
1979 } else if (a.disp != 0) {
1980 tcg_gen_addi_tl(cpu_A0, ea, a.disp);
1981 ea = cpu_A0;
1984 return ea;
1987 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
1989 AddressParts a = gen_lea_modrm_0(env, s, modrm);
1990 TCGv ea = gen_lea_modrm_1(a);
1991 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
1994 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
1996 (void)gen_lea_modrm_0(env, s, modrm);
1999 /* Used for BNDCL, BNDCU, BNDCN. */
2000 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2001 TCGCond cond, TCGv_i64 bndv)
2003 TCGv ea = gen_lea_modrm_1(gen_lea_modrm_0(env, s, modrm));
2005 tcg_gen_extu_tl_i64(cpu_tmp1_i64, ea);
2006 if (!CODE64(s)) {
2007 tcg_gen_ext32u_i64(cpu_tmp1_i64, cpu_tmp1_i64);
2009 tcg_gen_setcond_i64(cond, cpu_tmp1_i64, cpu_tmp1_i64, bndv);
2010 tcg_gen_extrl_i64_i32(cpu_tmp2_i32, cpu_tmp1_i64);
2011 gen_helper_bndck(cpu_env, cpu_tmp2_i32);
2014 /* used for LEA and MOV AX, mem */
2015 static void gen_add_A0_ds_seg(DisasContext *s)
2017 gen_lea_v_seg(s, s->aflag, cpu_A0, R_DS, s->override);
2020 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2021 OR_TMP0 */
2022 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2023 TCGMemOp ot, int reg, int is_store)
2025 int mod, rm;
2027 mod = (modrm >> 6) & 3;
2028 rm = (modrm & 7) | REX_B(s);
2029 if (mod == 3) {
2030 if (is_store) {
2031 if (reg != OR_TMP0)
2032 gen_op_mov_v_reg(ot, cpu_T0, reg);
2033 gen_op_mov_reg_v(ot, rm, cpu_T0);
2034 } else {
2035 gen_op_mov_v_reg(ot, cpu_T0, rm);
2036 if (reg != OR_TMP0)
2037 gen_op_mov_reg_v(ot, reg, cpu_T0);
2039 } else {
2040 gen_lea_modrm(env, s, modrm);
2041 if (is_store) {
2042 if (reg != OR_TMP0)
2043 gen_op_mov_v_reg(ot, cpu_T0, reg);
2044 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
2045 } else {
2046 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
2047 if (reg != OR_TMP0)
2048 gen_op_mov_reg_v(ot, reg, cpu_T0);
2053 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
2055 uint32_t ret;
2057 switch (ot) {
2058 case MO_8:
2059 ret = cpu_ldub_code(env, s->pc);
2060 s->pc++;
2061 break;
2062 case MO_16:
2063 ret = cpu_lduw_code(env, s->pc);
2064 s->pc += 2;
2065 break;
2066 case MO_32:
2067 #ifdef TARGET_X86_64
2068 case MO_64:
2069 #endif
2070 ret = cpu_ldl_code(env, s->pc);
2071 s->pc += 4;
2072 break;
2073 default:
2074 tcg_abort();
2076 return ret;
2079 static inline int insn_const_size(TCGMemOp ot)
2081 if (ot <= MO_32) {
2082 return 1 << ot;
2083 } else {
2084 return 4;
2088 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2090 #ifndef CONFIG_USER_ONLY
2091 return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) ||
2092 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2093 #else
2094 return true;
2095 #endif
2098 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2100 target_ulong pc = s->cs_base + eip;
2102 if (use_goto_tb(s, pc)) {
2103 /* jump to same page: we can use a direct jump */
2104 tcg_gen_goto_tb(tb_num);
2105 gen_jmp_im(eip);
2106 tcg_gen_exit_tb((uintptr_t)s->tb + tb_num);
2107 } else {
2108 /* jump to another page: currently not optimized */
2109 gen_jmp_im(eip);
2110 gen_eob(s);
2114 static inline void gen_jcc(DisasContext *s, int b,
2115 target_ulong val, target_ulong next_eip)
2117 TCGLabel *l1, *l2;
2119 if (s->jmp_opt) {
2120 l1 = gen_new_label();
2121 gen_jcc1(s, b, l1);
2123 gen_goto_tb(s, 0, next_eip);
2125 gen_set_label(l1);
2126 gen_goto_tb(s, 1, val);
2127 s->is_jmp = DISAS_TB_JUMP;
2128 } else {
2129 l1 = gen_new_label();
2130 l2 = gen_new_label();
2131 gen_jcc1(s, b, l1);
2133 gen_jmp_im(next_eip);
2134 tcg_gen_br(l2);
2136 gen_set_label(l1);
2137 gen_jmp_im(val);
2138 gen_set_label(l2);
2139 gen_eob(s);
2143 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
2144 int modrm, int reg)
2146 CCPrepare cc;
2148 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2150 cc = gen_prepare_cc(s, b, cpu_T1);
2151 if (cc.mask != -1) {
2152 TCGv t0 = tcg_temp_new();
2153 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2154 cc.reg = t0;
2156 if (!cc.use_reg2) {
2157 cc.reg2 = tcg_const_tl(cc.imm);
2160 tcg_gen_movcond_tl(cc.cond, cpu_T0, cc.reg, cc.reg2,
2161 cpu_T0, cpu_regs[reg]);
2162 gen_op_mov_reg_v(ot, reg, cpu_T0);
2164 if (cc.mask != -1) {
2165 tcg_temp_free(cc.reg);
2167 if (!cc.use_reg2) {
2168 tcg_temp_free(cc.reg2);
2172 static inline void gen_op_movl_T0_seg(int seg_reg)
2174 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
2175 offsetof(CPUX86State,segs[seg_reg].selector));
2178 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2180 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
2181 tcg_gen_st32_tl(cpu_T0, cpu_env,
2182 offsetof(CPUX86State,segs[seg_reg].selector));
2183 tcg_gen_shli_tl(cpu_seg_base[seg_reg], cpu_T0, 4);
2186 /* move T0 to seg_reg and compute if the CPU state may change. Never
2187 call this function with seg_reg == R_CS */
2188 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
2190 if (s->pe && !s->vm86) {
2191 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
2192 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
2193 /* abort translation because the addseg value may change or
2194 because ss32 may change. For R_SS, translation must always
2195 stop as a special handling must be done to disable hardware
2196 interrupts for the next instruction */
2197 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
2198 s->is_jmp = DISAS_TB_JUMP;
2199 } else {
2200 gen_op_movl_seg_T0_vm(seg_reg);
2201 if (seg_reg == R_SS)
2202 s->is_jmp = DISAS_TB_JUMP;
2206 static inline int svm_is_rep(int prefixes)
2208 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2211 static inline void
2212 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2213 uint32_t type, uint64_t param)
2215 /* no SVM activated; fast case */
2216 if (likely(!(s->flags & HF_SVMI_MASK)))
2217 return;
2218 gen_update_cc_op(s);
2219 gen_jmp_im(pc_start - s->cs_base);
2220 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2221 tcg_const_i64(param));
2224 static inline void
2225 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2227 gen_svm_check_intercept_param(s, pc_start, type, 0);
2230 static inline void gen_stack_update(DisasContext *s, int addend)
2232 gen_op_add_reg_im(mo_stacksize(s), R_ESP, addend);
2235 /* Generate a push. It depends on ss32, addseg and dflag. */
2236 static void gen_push_v(DisasContext *s, TCGv val)
2238 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2239 TCGMemOp a_ot = mo_stacksize(s);
2240 int size = 1 << d_ot;
2241 TCGv new_esp = cpu_A0;
2243 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
2245 if (!CODE64(s)) {
2246 if (s->addseg) {
2247 new_esp = cpu_tmp4;
2248 tcg_gen_mov_tl(new_esp, cpu_A0);
2250 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2253 gen_op_st_v(s, d_ot, val, cpu_A0);
2254 gen_op_mov_reg_v(a_ot, R_ESP, new_esp);
2257 /* two step pop is necessary for precise exceptions */
2258 static TCGMemOp gen_pop_T0(DisasContext *s)
2260 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2262 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2263 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2265 return d_ot;
2268 static inline void gen_pop_update(DisasContext *s, TCGMemOp ot)
2270 gen_stack_update(s, 1 << ot);
2273 static inline void gen_stack_A0(DisasContext *s)
2275 gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2278 static void gen_pusha(DisasContext *s)
2280 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2281 TCGMemOp d_ot = s->dflag;
2282 int size = 1 << d_ot;
2283 int i;
2285 for (i = 0; i < 8; i++) {
2286 tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], (i - 8) * size);
2287 gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
2288 gen_op_st_v(s, d_ot, cpu_regs[7 - i], cpu_A0);
2291 gen_stack_update(s, -8 * size);
2294 static void gen_popa(DisasContext *s)
2296 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2297 TCGMemOp d_ot = s->dflag;
2298 int size = 1 << d_ot;
2299 int i;
2301 for (i = 0; i < 8; i++) {
2302 /* ESP is not reloaded */
2303 if (7 - i == R_ESP) {
2304 continue;
2306 tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], i * size);
2307 gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
2308 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2309 gen_op_mov_reg_v(d_ot, 7 - i, cpu_T0);
2312 gen_stack_update(s, 8 * size);
2315 static void gen_enter(DisasContext *s, int esp_addend, int level)
2317 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2318 TCGMemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
2319 int size = 1 << d_ot;
2321 /* Push BP; compute FrameTemp into T1. */
2322 tcg_gen_subi_tl(cpu_T1, cpu_regs[R_ESP], size);
2323 gen_lea_v_seg(s, a_ot, cpu_T1, R_SS, -1);
2324 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], cpu_A0);
2326 level &= 31;
2327 if (level != 0) {
2328 int i;
2330 /* Copy level-1 pointers from the previous frame. */
2331 for (i = 1; i < level; ++i) {
2332 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_EBP], size * i);
2333 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2334 gen_op_ld_v(s, d_ot, cpu_tmp0, cpu_A0);
2336 tcg_gen_subi_tl(cpu_A0, cpu_T1, size * i);
2337 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2338 gen_op_st_v(s, d_ot, cpu_tmp0, cpu_A0);
2341 /* Push the current FrameTemp as the last level. */
2342 tcg_gen_subi_tl(cpu_A0, cpu_T1, size * level);
2343 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2344 gen_op_st_v(s, d_ot, cpu_T1, cpu_A0);
2347 /* Copy the FrameTemp value to EBP. */
2348 gen_op_mov_reg_v(a_ot, R_EBP, cpu_T1);
2350 /* Compute the final value of ESP. */
2351 tcg_gen_subi_tl(cpu_T1, cpu_T1, esp_addend + size * level);
2352 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2355 static void gen_leave(DisasContext *s)
2357 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2358 TCGMemOp a_ot = mo_stacksize(s);
2360 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2361 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2363 tcg_gen_addi_tl(cpu_T1, cpu_regs[R_EBP], 1 << d_ot);
2365 gen_op_mov_reg_v(d_ot, R_EBP, cpu_T0);
2366 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2369 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2371 gen_update_cc_op(s);
2372 gen_jmp_im(cur_eip);
2373 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
2374 s->is_jmp = DISAS_TB_JUMP;
2377 /* Generate #UD for the current instruction. The assumption here is that
2378 the instruction is known, but it isn't allowed in the current cpu mode. */
2379 static void gen_illegal_opcode(DisasContext *s)
2381 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
2384 /* Similarly, except that the assumption here is that we don't decode
2385 the instruction at all -- either a missing opcode, an unimplemented
2386 feature, or just a bogus instruction stream. */
2387 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2389 gen_illegal_opcode(s);
2391 if (qemu_loglevel_mask(LOG_UNIMP)) {
2392 target_ulong pc = s->pc_start, end = s->pc;
2393 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2394 for (; pc < end; ++pc) {
2395 qemu_log(" %02x", cpu_ldub_code(env, pc));
2397 qemu_log("\n");
2401 /* an interrupt is different from an exception because of the
2402 privilege checks */
2403 static void gen_interrupt(DisasContext *s, int intno,
2404 target_ulong cur_eip, target_ulong next_eip)
2406 gen_update_cc_op(s);
2407 gen_jmp_im(cur_eip);
2408 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2409 tcg_const_i32(next_eip - cur_eip));
2410 s->is_jmp = DISAS_TB_JUMP;
2413 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2415 gen_update_cc_op(s);
2416 gen_jmp_im(cur_eip);
2417 gen_helper_debug(cpu_env);
2418 s->is_jmp = DISAS_TB_JUMP;
2421 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2423 if ((s->flags & mask) == 0) {
2424 TCGv_i32 t = tcg_temp_new_i32();
2425 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2426 tcg_gen_ori_i32(t, t, mask);
2427 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2428 tcg_temp_free_i32(t);
2429 s->flags |= mask;
2433 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2435 if (s->flags & mask) {
2436 TCGv_i32 t = tcg_temp_new_i32();
2437 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2438 tcg_gen_andi_i32(t, t, ~mask);
2439 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2440 tcg_temp_free_i32(t);
2441 s->flags &= ~mask;
2445 /* Clear BND registers during legacy branches. */
2446 static void gen_bnd_jmp(DisasContext *s)
2448 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2449 and if the BNDREGs are known to be in use (non-zero) already.
2450 The helper itself will check BNDPRESERVE at runtime. */
2451 if ((s->prefix & PREFIX_REPNZ) == 0
2452 && (s->flags & HF_MPX_EN_MASK) != 0
2453 && (s->flags & HF_MPX_IU_MASK) != 0) {
2454 gen_helper_bnd_jmp(cpu_env);
2458 /* Generate an end of block. Trace exception is also generated if needed.
2459 If IIM, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2460 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2462 gen_update_cc_op(s);
2464 /* If several instructions disable interrupts, only the first does it. */
2465 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2466 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2467 } else {
2468 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2471 if (s->tb->flags & HF_RF_MASK) {
2472 gen_helper_reset_rf(cpu_env);
2474 if (s->singlestep_enabled) {
2475 gen_helper_debug(cpu_env);
2476 } else if (s->tf) {
2477 gen_helper_single_step(cpu_env);
2478 } else {
2479 tcg_gen_exit_tb(0);
2481 s->is_jmp = DISAS_TB_JUMP;
2484 /* End of block, resetting the inhibit irq flag. */
2485 static void gen_eob(DisasContext *s)
2487 gen_eob_inhibit_irq(s, false);
2490 /* generate a jump to eip. No segment change must happen before as a
2491 direct call to the next block may occur */
2492 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2494 gen_update_cc_op(s);
2495 set_cc_op(s, CC_OP_DYNAMIC);
2496 if (s->jmp_opt) {
2497 gen_goto_tb(s, tb_num, eip);
2498 s->is_jmp = DISAS_TB_JUMP;
2499 } else {
2500 gen_jmp_im(eip);
2501 gen_eob(s);
2505 static void gen_jmp(DisasContext *s, target_ulong eip)
2507 gen_jmp_tb(s, eip, 0);
2510 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2512 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2513 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2516 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2518 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2519 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2522 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2524 int mem_index = s->mem_index;
2525 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2526 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2527 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2528 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2529 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2532 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2534 int mem_index = s->mem_index;
2535 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2536 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2537 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2538 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2539 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2542 static inline void gen_op_movo(int d_offset, int s_offset)
2544 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2545 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2546 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2547 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2550 static inline void gen_op_movq(int d_offset, int s_offset)
2552 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2553 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2556 static inline void gen_op_movl(int d_offset, int s_offset)
2558 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2559 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2562 static inline void gen_op_movq_env_0(int d_offset)
2564 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2565 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2568 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2569 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2570 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2571 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2572 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2573 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2574 TCGv_i32 val);
2575 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2576 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2577 TCGv val);
2579 #define SSE_SPECIAL ((void *)1)
2580 #define SSE_DUMMY ((void *)2)
2582 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2583 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2584 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2586 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2587 /* 3DNow! extensions */
2588 [0x0e] = { SSE_DUMMY }, /* femms */
2589 [0x0f] = { SSE_DUMMY }, /* pf... */
2590 /* pure SSE operations */
2591 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2592 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2593 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2594 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2595 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2596 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2597 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2598 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2600 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2601 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2602 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2603 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2604 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2605 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2606 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2607 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2608 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2609 [0x51] = SSE_FOP(sqrt),
2610 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2611 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2612 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2613 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2614 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2615 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2616 [0x58] = SSE_FOP(add),
2617 [0x59] = SSE_FOP(mul),
2618 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2619 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2620 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2621 [0x5c] = SSE_FOP(sub),
2622 [0x5d] = SSE_FOP(min),
2623 [0x5e] = SSE_FOP(div),
2624 [0x5f] = SSE_FOP(max),
2626 [0xc2] = SSE_FOP(cmpeq),
2627 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2628 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2630 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2631 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2632 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2634 /* MMX ops and their SSE extensions */
2635 [0x60] = MMX_OP2(punpcklbw),
2636 [0x61] = MMX_OP2(punpcklwd),
2637 [0x62] = MMX_OP2(punpckldq),
2638 [0x63] = MMX_OP2(packsswb),
2639 [0x64] = MMX_OP2(pcmpgtb),
2640 [0x65] = MMX_OP2(pcmpgtw),
2641 [0x66] = MMX_OP2(pcmpgtl),
2642 [0x67] = MMX_OP2(packuswb),
2643 [0x68] = MMX_OP2(punpckhbw),
2644 [0x69] = MMX_OP2(punpckhwd),
2645 [0x6a] = MMX_OP2(punpckhdq),
2646 [0x6b] = MMX_OP2(packssdw),
2647 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2648 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2649 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2650 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2651 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2652 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2653 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2654 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2655 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2656 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2657 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2658 [0x74] = MMX_OP2(pcmpeqb),
2659 [0x75] = MMX_OP2(pcmpeqw),
2660 [0x76] = MMX_OP2(pcmpeql),
2661 [0x77] = { SSE_DUMMY }, /* emms */
2662 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2663 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2664 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2665 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2666 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2667 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2668 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2669 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2670 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2671 [0xd1] = MMX_OP2(psrlw),
2672 [0xd2] = MMX_OP2(psrld),
2673 [0xd3] = MMX_OP2(psrlq),
2674 [0xd4] = MMX_OP2(paddq),
2675 [0xd5] = MMX_OP2(pmullw),
2676 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2677 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2678 [0xd8] = MMX_OP2(psubusb),
2679 [0xd9] = MMX_OP2(psubusw),
2680 [0xda] = MMX_OP2(pminub),
2681 [0xdb] = MMX_OP2(pand),
2682 [0xdc] = MMX_OP2(paddusb),
2683 [0xdd] = MMX_OP2(paddusw),
2684 [0xde] = MMX_OP2(pmaxub),
2685 [0xdf] = MMX_OP2(pandn),
2686 [0xe0] = MMX_OP2(pavgb),
2687 [0xe1] = MMX_OP2(psraw),
2688 [0xe2] = MMX_OP2(psrad),
2689 [0xe3] = MMX_OP2(pavgw),
2690 [0xe4] = MMX_OP2(pmulhuw),
2691 [0xe5] = MMX_OP2(pmulhw),
2692 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2693 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2694 [0xe8] = MMX_OP2(psubsb),
2695 [0xe9] = MMX_OP2(psubsw),
2696 [0xea] = MMX_OP2(pminsw),
2697 [0xeb] = MMX_OP2(por),
2698 [0xec] = MMX_OP2(paddsb),
2699 [0xed] = MMX_OP2(paddsw),
2700 [0xee] = MMX_OP2(pmaxsw),
2701 [0xef] = MMX_OP2(pxor),
2702 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2703 [0xf1] = MMX_OP2(psllw),
2704 [0xf2] = MMX_OP2(pslld),
2705 [0xf3] = MMX_OP2(psllq),
2706 [0xf4] = MMX_OP2(pmuludq),
2707 [0xf5] = MMX_OP2(pmaddwd),
2708 [0xf6] = MMX_OP2(psadbw),
2709 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2710 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2711 [0xf8] = MMX_OP2(psubb),
2712 [0xf9] = MMX_OP2(psubw),
2713 [0xfa] = MMX_OP2(psubl),
2714 [0xfb] = MMX_OP2(psubq),
2715 [0xfc] = MMX_OP2(paddb),
2716 [0xfd] = MMX_OP2(paddw),
2717 [0xfe] = MMX_OP2(paddl),
2720 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2721 [0 + 2] = MMX_OP2(psrlw),
2722 [0 + 4] = MMX_OP2(psraw),
2723 [0 + 6] = MMX_OP2(psllw),
2724 [8 + 2] = MMX_OP2(psrld),
2725 [8 + 4] = MMX_OP2(psrad),
2726 [8 + 6] = MMX_OP2(pslld),
2727 [16 + 2] = MMX_OP2(psrlq),
2728 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2729 [16 + 6] = MMX_OP2(psllq),
2730 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2733 static const SSEFunc_0_epi sse_op_table3ai[] = {
2734 gen_helper_cvtsi2ss,
2735 gen_helper_cvtsi2sd
2738 #ifdef TARGET_X86_64
2739 static const SSEFunc_0_epl sse_op_table3aq[] = {
2740 gen_helper_cvtsq2ss,
2741 gen_helper_cvtsq2sd
2743 #endif
2745 static const SSEFunc_i_ep sse_op_table3bi[] = {
2746 gen_helper_cvttss2si,
2747 gen_helper_cvtss2si,
2748 gen_helper_cvttsd2si,
2749 gen_helper_cvtsd2si
2752 #ifdef TARGET_X86_64
2753 static const SSEFunc_l_ep sse_op_table3bq[] = {
2754 gen_helper_cvttss2sq,
2755 gen_helper_cvtss2sq,
2756 gen_helper_cvttsd2sq,
2757 gen_helper_cvtsd2sq
2759 #endif
2761 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2762 SSE_FOP(cmpeq),
2763 SSE_FOP(cmplt),
2764 SSE_FOP(cmple),
2765 SSE_FOP(cmpunord),
2766 SSE_FOP(cmpneq),
2767 SSE_FOP(cmpnlt),
2768 SSE_FOP(cmpnle),
2769 SSE_FOP(cmpord),
2772 static const SSEFunc_0_epp sse_op_table5[256] = {
2773 [0x0c] = gen_helper_pi2fw,
2774 [0x0d] = gen_helper_pi2fd,
2775 [0x1c] = gen_helper_pf2iw,
2776 [0x1d] = gen_helper_pf2id,
2777 [0x8a] = gen_helper_pfnacc,
2778 [0x8e] = gen_helper_pfpnacc,
2779 [0x90] = gen_helper_pfcmpge,
2780 [0x94] = gen_helper_pfmin,
2781 [0x96] = gen_helper_pfrcp,
2782 [0x97] = gen_helper_pfrsqrt,
2783 [0x9a] = gen_helper_pfsub,
2784 [0x9e] = gen_helper_pfadd,
2785 [0xa0] = gen_helper_pfcmpgt,
2786 [0xa4] = gen_helper_pfmax,
2787 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2788 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2789 [0xaa] = gen_helper_pfsubr,
2790 [0xae] = gen_helper_pfacc,
2791 [0xb0] = gen_helper_pfcmpeq,
2792 [0xb4] = gen_helper_pfmul,
2793 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2794 [0xb7] = gen_helper_pmulhrw_mmx,
2795 [0xbb] = gen_helper_pswapd,
2796 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
2799 struct SSEOpHelper_epp {
2800 SSEFunc_0_epp op[2];
2801 uint32_t ext_mask;
2804 struct SSEOpHelper_eppi {
2805 SSEFunc_0_eppi op[2];
2806 uint32_t ext_mask;
2809 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2810 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2811 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
2812 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
2813 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2814 CPUID_EXT_PCLMULQDQ }
2815 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
2817 static const struct SSEOpHelper_epp sse_op_table6[256] = {
2818 [0x00] = SSSE3_OP(pshufb),
2819 [0x01] = SSSE3_OP(phaddw),
2820 [0x02] = SSSE3_OP(phaddd),
2821 [0x03] = SSSE3_OP(phaddsw),
2822 [0x04] = SSSE3_OP(pmaddubsw),
2823 [0x05] = SSSE3_OP(phsubw),
2824 [0x06] = SSSE3_OP(phsubd),
2825 [0x07] = SSSE3_OP(phsubsw),
2826 [0x08] = SSSE3_OP(psignb),
2827 [0x09] = SSSE3_OP(psignw),
2828 [0x0a] = SSSE3_OP(psignd),
2829 [0x0b] = SSSE3_OP(pmulhrsw),
2830 [0x10] = SSE41_OP(pblendvb),
2831 [0x14] = SSE41_OP(blendvps),
2832 [0x15] = SSE41_OP(blendvpd),
2833 [0x17] = SSE41_OP(ptest),
2834 [0x1c] = SSSE3_OP(pabsb),
2835 [0x1d] = SSSE3_OP(pabsw),
2836 [0x1e] = SSSE3_OP(pabsd),
2837 [0x20] = SSE41_OP(pmovsxbw),
2838 [0x21] = SSE41_OP(pmovsxbd),
2839 [0x22] = SSE41_OP(pmovsxbq),
2840 [0x23] = SSE41_OP(pmovsxwd),
2841 [0x24] = SSE41_OP(pmovsxwq),
2842 [0x25] = SSE41_OP(pmovsxdq),
2843 [0x28] = SSE41_OP(pmuldq),
2844 [0x29] = SSE41_OP(pcmpeqq),
2845 [0x2a] = SSE41_SPECIAL, /* movntqda */
2846 [0x2b] = SSE41_OP(packusdw),
2847 [0x30] = SSE41_OP(pmovzxbw),
2848 [0x31] = SSE41_OP(pmovzxbd),
2849 [0x32] = SSE41_OP(pmovzxbq),
2850 [0x33] = SSE41_OP(pmovzxwd),
2851 [0x34] = SSE41_OP(pmovzxwq),
2852 [0x35] = SSE41_OP(pmovzxdq),
2853 [0x37] = SSE42_OP(pcmpgtq),
2854 [0x38] = SSE41_OP(pminsb),
2855 [0x39] = SSE41_OP(pminsd),
2856 [0x3a] = SSE41_OP(pminuw),
2857 [0x3b] = SSE41_OP(pminud),
2858 [0x3c] = SSE41_OP(pmaxsb),
2859 [0x3d] = SSE41_OP(pmaxsd),
2860 [0x3e] = SSE41_OP(pmaxuw),
2861 [0x3f] = SSE41_OP(pmaxud),
2862 [0x40] = SSE41_OP(pmulld),
2863 [0x41] = SSE41_OP(phminposuw),
2864 [0xdb] = AESNI_OP(aesimc),
2865 [0xdc] = AESNI_OP(aesenc),
2866 [0xdd] = AESNI_OP(aesenclast),
2867 [0xde] = AESNI_OP(aesdec),
2868 [0xdf] = AESNI_OP(aesdeclast),
2871 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
2872 [0x08] = SSE41_OP(roundps),
2873 [0x09] = SSE41_OP(roundpd),
2874 [0x0a] = SSE41_OP(roundss),
2875 [0x0b] = SSE41_OP(roundsd),
2876 [0x0c] = SSE41_OP(blendps),
2877 [0x0d] = SSE41_OP(blendpd),
2878 [0x0e] = SSE41_OP(pblendw),
2879 [0x0f] = SSSE3_OP(palignr),
2880 [0x14] = SSE41_SPECIAL, /* pextrb */
2881 [0x15] = SSE41_SPECIAL, /* pextrw */
2882 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
2883 [0x17] = SSE41_SPECIAL, /* extractps */
2884 [0x20] = SSE41_SPECIAL, /* pinsrb */
2885 [0x21] = SSE41_SPECIAL, /* insertps */
2886 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
2887 [0x40] = SSE41_OP(dpps),
2888 [0x41] = SSE41_OP(dppd),
2889 [0x42] = SSE41_OP(mpsadbw),
2890 [0x44] = PCLMULQDQ_OP(pclmulqdq),
2891 [0x60] = SSE42_OP(pcmpestrm),
2892 [0x61] = SSE42_OP(pcmpestri),
2893 [0x62] = SSE42_OP(pcmpistrm),
2894 [0x63] = SSE42_OP(pcmpistri),
2895 [0xdf] = AESNI_OP(aeskeygenassist),
2898 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
2899 target_ulong pc_start, int rex_r)
2901 int b1, op1_offset, op2_offset, is_xmm, val;
2902 int modrm, mod, rm, reg;
2903 SSEFunc_0_epp sse_fn_epp;
2904 SSEFunc_0_eppi sse_fn_eppi;
2905 SSEFunc_0_ppi sse_fn_ppi;
2906 SSEFunc_0_eppt sse_fn_eppt;
2907 TCGMemOp ot;
2909 b &= 0xff;
2910 if (s->prefix & PREFIX_DATA)
2911 b1 = 1;
2912 else if (s->prefix & PREFIX_REPZ)
2913 b1 = 2;
2914 else if (s->prefix & PREFIX_REPNZ)
2915 b1 = 3;
2916 else
2917 b1 = 0;
2918 sse_fn_epp = sse_op_table1[b][b1];
2919 if (!sse_fn_epp) {
2920 goto unknown_op;
2922 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
2923 is_xmm = 1;
2924 } else {
2925 if (b1 == 0) {
2926 /* MMX case */
2927 is_xmm = 0;
2928 } else {
2929 is_xmm = 1;
2932 /* simple MMX/SSE operation */
2933 if (s->flags & HF_TS_MASK) {
2934 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2935 return;
2937 if (s->flags & HF_EM_MASK) {
2938 illegal_op:
2939 gen_illegal_opcode(s);
2940 return;
2942 if (is_xmm
2943 && !(s->flags & HF_OSFXSR_MASK)
2944 && ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
2945 goto unknown_op;
2947 if (b == 0x0e) {
2948 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
2949 /* If we were fully decoding this we might use illegal_op. */
2950 goto unknown_op;
2952 /* femms */
2953 gen_helper_emms(cpu_env);
2954 return;
2956 if (b == 0x77) {
2957 /* emms */
2958 gen_helper_emms(cpu_env);
2959 return;
2961 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2962 the static cpu state) */
2963 if (!is_xmm) {
2964 gen_helper_enter_mmx(cpu_env);
2967 modrm = cpu_ldub_code(env, s->pc++);
2968 reg = ((modrm >> 3) & 7);
2969 if (is_xmm)
2970 reg |= rex_r;
2971 mod = (modrm >> 6) & 3;
2972 if (sse_fn_epp == SSE_SPECIAL) {
2973 b |= (b1 << 8);
2974 switch(b) {
2975 case 0x0e7: /* movntq */
2976 if (mod == 3) {
2977 goto illegal_op;
2979 gen_lea_modrm(env, s, modrm);
2980 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
2981 break;
2982 case 0x1e7: /* movntdq */
2983 case 0x02b: /* movntps */
2984 case 0x12b: /* movntps */
2985 if (mod == 3)
2986 goto illegal_op;
2987 gen_lea_modrm(env, s, modrm);
2988 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
2989 break;
2990 case 0x3f0: /* lddqu */
2991 if (mod == 3)
2992 goto illegal_op;
2993 gen_lea_modrm(env, s, modrm);
2994 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
2995 break;
2996 case 0x22b: /* movntss */
2997 case 0x32b: /* movntsd */
2998 if (mod == 3)
2999 goto illegal_op;
3000 gen_lea_modrm(env, s, modrm);
3001 if (b1 & 1) {
3002 gen_stq_env_A0(s, offsetof(CPUX86State,
3003 xmm_regs[reg].ZMM_Q(0)));
3004 } else {
3005 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
3006 xmm_regs[reg].ZMM_L(0)));
3007 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3009 break;
3010 case 0x6e: /* movd mm, ea */
3011 #ifdef TARGET_X86_64
3012 if (s->dflag == MO_64) {
3013 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3014 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3015 } else
3016 #endif
3018 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3019 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3020 offsetof(CPUX86State,fpregs[reg].mmx));
3021 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3022 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
3024 break;
3025 case 0x16e: /* movd xmm, ea */
3026 #ifdef TARGET_X86_64
3027 if (s->dflag == MO_64) {
3028 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3029 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3030 offsetof(CPUX86State,xmm_regs[reg]));
3031 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T0);
3032 } else
3033 #endif
3035 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3036 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3037 offsetof(CPUX86State,xmm_regs[reg]));
3038 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3039 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
3041 break;
3042 case 0x6f: /* movq mm, ea */
3043 if (mod != 3) {
3044 gen_lea_modrm(env, s, modrm);
3045 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3046 } else {
3047 rm = (modrm & 7);
3048 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3049 offsetof(CPUX86State,fpregs[rm].mmx));
3050 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3051 offsetof(CPUX86State,fpregs[reg].mmx));
3053 break;
3054 case 0x010: /* movups */
3055 case 0x110: /* movupd */
3056 case 0x028: /* movaps */
3057 case 0x128: /* movapd */
3058 case 0x16f: /* movdqa xmm, ea */
3059 case 0x26f: /* movdqu xmm, ea */
3060 if (mod != 3) {
3061 gen_lea_modrm(env, s, modrm);
3062 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3063 } else {
3064 rm = (modrm & 7) | REX_B(s);
3065 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3066 offsetof(CPUX86State,xmm_regs[rm]));
3068 break;
3069 case 0x210: /* movss xmm, ea */
3070 if (mod != 3) {
3071 gen_lea_modrm(env, s, modrm);
3072 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3073 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3074 tcg_gen_movi_tl(cpu_T0, 0);
3075 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3076 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3077 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3078 } else {
3079 rm = (modrm & 7) | REX_B(s);
3080 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3081 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3083 break;
3084 case 0x310: /* movsd xmm, ea */
3085 if (mod != 3) {
3086 gen_lea_modrm(env, s, modrm);
3087 gen_ldq_env_A0(s, offsetof(CPUX86State,
3088 xmm_regs[reg].ZMM_Q(0)));
3089 tcg_gen_movi_tl(cpu_T0, 0);
3090 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3091 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3092 } else {
3093 rm = (modrm & 7) | REX_B(s);
3094 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3095 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3097 break;
3098 case 0x012: /* movlps */
3099 case 0x112: /* movlpd */
3100 if (mod != 3) {
3101 gen_lea_modrm(env, s, modrm);
3102 gen_ldq_env_A0(s, offsetof(CPUX86State,
3103 xmm_regs[reg].ZMM_Q(0)));
3104 } else {
3105 /* movhlps */
3106 rm = (modrm & 7) | REX_B(s);
3107 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3108 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3110 break;
3111 case 0x212: /* movsldup */
3112 if (mod != 3) {
3113 gen_lea_modrm(env, s, modrm);
3114 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3115 } else {
3116 rm = (modrm & 7) | REX_B(s);
3117 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3118 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3119 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3120 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3122 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3123 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3124 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3125 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3126 break;
3127 case 0x312: /* movddup */
3128 if (mod != 3) {
3129 gen_lea_modrm(env, s, modrm);
3130 gen_ldq_env_A0(s, offsetof(CPUX86State,
3131 xmm_regs[reg].ZMM_Q(0)));
3132 } else {
3133 rm = (modrm & 7) | REX_B(s);
3134 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3135 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3137 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3138 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3139 break;
3140 case 0x016: /* movhps */
3141 case 0x116: /* movhpd */
3142 if (mod != 3) {
3143 gen_lea_modrm(env, s, modrm);
3144 gen_ldq_env_A0(s, offsetof(CPUX86State,
3145 xmm_regs[reg].ZMM_Q(1)));
3146 } else {
3147 /* movlhps */
3148 rm = (modrm & 7) | REX_B(s);
3149 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3150 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3152 break;
3153 case 0x216: /* movshdup */
3154 if (mod != 3) {
3155 gen_lea_modrm(env, s, modrm);
3156 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3157 } else {
3158 rm = (modrm & 7) | REX_B(s);
3159 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3160 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3161 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3162 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3164 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3165 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3166 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3167 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3168 break;
3169 case 0x178:
3170 case 0x378:
3172 int bit_index, field_length;
3174 if (b1 == 1 && reg != 0)
3175 goto illegal_op;
3176 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3177 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3178 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3179 offsetof(CPUX86State,xmm_regs[reg]));
3180 if (b1 == 1)
3181 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3182 tcg_const_i32(bit_index),
3183 tcg_const_i32(field_length));
3184 else
3185 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3186 tcg_const_i32(bit_index),
3187 tcg_const_i32(field_length));
3189 break;
3190 case 0x7e: /* movd ea, mm */
3191 #ifdef TARGET_X86_64
3192 if (s->dflag == MO_64) {
3193 tcg_gen_ld_i64(cpu_T0, cpu_env,
3194 offsetof(CPUX86State,fpregs[reg].mmx));
3195 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3196 } else
3197 #endif
3199 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3200 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3201 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3203 break;
3204 case 0x17e: /* movd ea, xmm */
3205 #ifdef TARGET_X86_64
3206 if (s->dflag == MO_64) {
3207 tcg_gen_ld_i64(cpu_T0, cpu_env,
3208 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3209 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3210 } else
3211 #endif
3213 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3214 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3215 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3217 break;
3218 case 0x27e: /* movq xmm, ea */
3219 if (mod != 3) {
3220 gen_lea_modrm(env, s, modrm);
3221 gen_ldq_env_A0(s, offsetof(CPUX86State,
3222 xmm_regs[reg].ZMM_Q(0)));
3223 } else {
3224 rm = (modrm & 7) | REX_B(s);
3225 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3226 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3228 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3229 break;
3230 case 0x7f: /* movq ea, mm */
3231 if (mod != 3) {
3232 gen_lea_modrm(env, s, modrm);
3233 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3234 } else {
3235 rm = (modrm & 7);
3236 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3237 offsetof(CPUX86State,fpregs[reg].mmx));
3239 break;
3240 case 0x011: /* movups */
3241 case 0x111: /* movupd */
3242 case 0x029: /* movaps */
3243 case 0x129: /* movapd */
3244 case 0x17f: /* movdqa ea, xmm */
3245 case 0x27f: /* movdqu ea, xmm */
3246 if (mod != 3) {
3247 gen_lea_modrm(env, s, modrm);
3248 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3249 } else {
3250 rm = (modrm & 7) | REX_B(s);
3251 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3252 offsetof(CPUX86State,xmm_regs[reg]));
3254 break;
3255 case 0x211: /* movss ea, xmm */
3256 if (mod != 3) {
3257 gen_lea_modrm(env, s, modrm);
3258 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3259 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3260 } else {
3261 rm = (modrm & 7) | REX_B(s);
3262 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)),
3263 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3265 break;
3266 case 0x311: /* movsd ea, xmm */
3267 if (mod != 3) {
3268 gen_lea_modrm(env, s, modrm);
3269 gen_stq_env_A0(s, offsetof(CPUX86State,
3270 xmm_regs[reg].ZMM_Q(0)));
3271 } else {
3272 rm = (modrm & 7) | REX_B(s);
3273 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3274 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3276 break;
3277 case 0x013: /* movlps */
3278 case 0x113: /* movlpd */
3279 if (mod != 3) {
3280 gen_lea_modrm(env, s, modrm);
3281 gen_stq_env_A0(s, offsetof(CPUX86State,
3282 xmm_regs[reg].ZMM_Q(0)));
3283 } else {
3284 goto illegal_op;
3286 break;
3287 case 0x017: /* movhps */
3288 case 0x117: /* movhpd */
3289 if (mod != 3) {
3290 gen_lea_modrm(env, s, modrm);
3291 gen_stq_env_A0(s, offsetof(CPUX86State,
3292 xmm_regs[reg].ZMM_Q(1)));
3293 } else {
3294 goto illegal_op;
3296 break;
3297 case 0x71: /* shift mm, im */
3298 case 0x72:
3299 case 0x73:
3300 case 0x171: /* shift xmm, im */
3301 case 0x172:
3302 case 0x173:
3303 if (b1 >= 2) {
3304 goto unknown_op;
3306 val = cpu_ldub_code(env, s->pc++);
3307 if (is_xmm) {
3308 tcg_gen_movi_tl(cpu_T0, val);
3309 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3310 tcg_gen_movi_tl(cpu_T0, 0);
3311 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(1)));
3312 op1_offset = offsetof(CPUX86State,xmm_t0);
3313 } else {
3314 tcg_gen_movi_tl(cpu_T0, val);
3315 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3316 tcg_gen_movi_tl(cpu_T0, 0);
3317 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3318 op1_offset = offsetof(CPUX86State,mmx_t0);
3320 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3321 (((modrm >> 3)) & 7)][b1];
3322 if (!sse_fn_epp) {
3323 goto unknown_op;
3325 if (is_xmm) {
3326 rm = (modrm & 7) | REX_B(s);
3327 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3328 } else {
3329 rm = (modrm & 7);
3330 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3332 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3333 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3334 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3335 break;
3336 case 0x050: /* movmskps */
3337 rm = (modrm & 7) | REX_B(s);
3338 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3339 offsetof(CPUX86State,xmm_regs[rm]));
3340 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3341 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3342 break;
3343 case 0x150: /* movmskpd */
3344 rm = (modrm & 7) | REX_B(s);
3345 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3346 offsetof(CPUX86State,xmm_regs[rm]));
3347 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3348 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3349 break;
3350 case 0x02a: /* cvtpi2ps */
3351 case 0x12a: /* cvtpi2pd */
3352 gen_helper_enter_mmx(cpu_env);
3353 if (mod != 3) {
3354 gen_lea_modrm(env, s, modrm);
3355 op2_offset = offsetof(CPUX86State,mmx_t0);
3356 gen_ldq_env_A0(s, op2_offset);
3357 } else {
3358 rm = (modrm & 7);
3359 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3361 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3362 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3363 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3364 switch(b >> 8) {
3365 case 0x0:
3366 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3367 break;
3368 default:
3369 case 0x1:
3370 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3371 break;
3373 break;
3374 case 0x22a: /* cvtsi2ss */
3375 case 0x32a: /* cvtsi2sd */
3376 ot = mo_64_32(s->dflag);
3377 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3378 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3379 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3380 if (ot == MO_32) {
3381 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3382 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3383 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3384 } else {
3385 #ifdef TARGET_X86_64
3386 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3387 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T0);
3388 #else
3389 goto illegal_op;
3390 #endif
3392 break;
3393 case 0x02c: /* cvttps2pi */
3394 case 0x12c: /* cvttpd2pi */
3395 case 0x02d: /* cvtps2pi */
3396 case 0x12d: /* cvtpd2pi */
3397 gen_helper_enter_mmx(cpu_env);
3398 if (mod != 3) {
3399 gen_lea_modrm(env, s, modrm);
3400 op2_offset = offsetof(CPUX86State,xmm_t0);
3401 gen_ldo_env_A0(s, op2_offset);
3402 } else {
3403 rm = (modrm & 7) | REX_B(s);
3404 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3406 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3407 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3408 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3409 switch(b) {
3410 case 0x02c:
3411 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3412 break;
3413 case 0x12c:
3414 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3415 break;
3416 case 0x02d:
3417 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3418 break;
3419 case 0x12d:
3420 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3421 break;
3423 break;
3424 case 0x22c: /* cvttss2si */
3425 case 0x32c: /* cvttsd2si */
3426 case 0x22d: /* cvtss2si */
3427 case 0x32d: /* cvtsd2si */
3428 ot = mo_64_32(s->dflag);
3429 if (mod != 3) {
3430 gen_lea_modrm(env, s, modrm);
3431 if ((b >> 8) & 1) {
3432 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3433 } else {
3434 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3435 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3437 op2_offset = offsetof(CPUX86State,xmm_t0);
3438 } else {
3439 rm = (modrm & 7) | REX_B(s);
3440 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3442 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3443 if (ot == MO_32) {
3444 SSEFunc_i_ep sse_fn_i_ep =
3445 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3446 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3447 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
3448 } else {
3449 #ifdef TARGET_X86_64
3450 SSEFunc_l_ep sse_fn_l_ep =
3451 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3452 sse_fn_l_ep(cpu_T0, cpu_env, cpu_ptr0);
3453 #else
3454 goto illegal_op;
3455 #endif
3457 gen_op_mov_reg_v(ot, reg, cpu_T0);
3458 break;
3459 case 0xc4: /* pinsrw */
3460 case 0x1c4:
3461 s->rip_offset = 1;
3462 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3463 val = cpu_ldub_code(env, s->pc++);
3464 if (b1) {
3465 val &= 7;
3466 tcg_gen_st16_tl(cpu_T0, cpu_env,
3467 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3468 } else {
3469 val &= 3;
3470 tcg_gen_st16_tl(cpu_T0, cpu_env,
3471 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3473 break;
3474 case 0xc5: /* pextrw */
3475 case 0x1c5:
3476 if (mod != 3)
3477 goto illegal_op;
3478 ot = mo_64_32(s->dflag);
3479 val = cpu_ldub_code(env, s->pc++);
3480 if (b1) {
3481 val &= 7;
3482 rm = (modrm & 7) | REX_B(s);
3483 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3484 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3485 } else {
3486 val &= 3;
3487 rm = (modrm & 7);
3488 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3489 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3491 reg = ((modrm >> 3) & 7) | rex_r;
3492 gen_op_mov_reg_v(ot, reg, cpu_T0);
3493 break;
3494 case 0x1d6: /* movq ea, xmm */
3495 if (mod != 3) {
3496 gen_lea_modrm(env, s, modrm);
3497 gen_stq_env_A0(s, offsetof(CPUX86State,
3498 xmm_regs[reg].ZMM_Q(0)));
3499 } else {
3500 rm = (modrm & 7) | REX_B(s);
3501 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3502 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3503 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3505 break;
3506 case 0x2d6: /* movq2dq */
3507 gen_helper_enter_mmx(cpu_env);
3508 rm = (modrm & 7);
3509 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3510 offsetof(CPUX86State,fpregs[rm].mmx));
3511 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3512 break;
3513 case 0x3d6: /* movdq2q */
3514 gen_helper_enter_mmx(cpu_env);
3515 rm = (modrm & 7) | REX_B(s);
3516 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3517 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3518 break;
3519 case 0xd7: /* pmovmskb */
3520 case 0x1d7:
3521 if (mod != 3)
3522 goto illegal_op;
3523 if (b1) {
3524 rm = (modrm & 7) | REX_B(s);
3525 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3526 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3527 } else {
3528 rm = (modrm & 7);
3529 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3530 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3532 reg = ((modrm >> 3) & 7) | rex_r;
3533 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3534 break;
3536 case 0x138:
3537 case 0x038:
3538 b = modrm;
3539 if ((b & 0xf0) == 0xf0) {
3540 goto do_0f_38_fx;
3542 modrm = cpu_ldub_code(env, s->pc++);
3543 rm = modrm & 7;
3544 reg = ((modrm >> 3) & 7) | rex_r;
3545 mod = (modrm >> 6) & 3;
3546 if (b1 >= 2) {
3547 goto unknown_op;
3550 sse_fn_epp = sse_op_table6[b].op[b1];
3551 if (!sse_fn_epp) {
3552 goto unknown_op;
3554 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3555 goto illegal_op;
3557 if (b1) {
3558 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3559 if (mod == 3) {
3560 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3561 } else {
3562 op2_offset = offsetof(CPUX86State,xmm_t0);
3563 gen_lea_modrm(env, s, modrm);
3564 switch (b) {
3565 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3566 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3567 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3568 gen_ldq_env_A0(s, op2_offset +
3569 offsetof(ZMMReg, ZMM_Q(0)));
3570 break;
3571 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3572 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3573 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3574 s->mem_index, MO_LEUL);
3575 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3576 offsetof(ZMMReg, ZMM_L(0)));
3577 break;
3578 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3579 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3580 s->mem_index, MO_LEUW);
3581 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3582 offsetof(ZMMReg, ZMM_W(0)));
3583 break;
3584 case 0x2a: /* movntqda */
3585 gen_ldo_env_A0(s, op1_offset);
3586 return;
3587 default:
3588 gen_ldo_env_A0(s, op2_offset);
3591 } else {
3592 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3593 if (mod == 3) {
3594 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3595 } else {
3596 op2_offset = offsetof(CPUX86State,mmx_t0);
3597 gen_lea_modrm(env, s, modrm);
3598 gen_ldq_env_A0(s, op2_offset);
3601 if (sse_fn_epp == SSE_SPECIAL) {
3602 goto unknown_op;
3605 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3606 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3607 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3609 if (b == 0x17) {
3610 set_cc_op(s, CC_OP_EFLAGS);
3612 break;
3614 case 0x238:
3615 case 0x338:
3616 do_0f_38_fx:
3617 /* Various integer extensions at 0f 38 f[0-f]. */
3618 b = modrm | (b1 << 8);
3619 modrm = cpu_ldub_code(env, s->pc++);
3620 reg = ((modrm >> 3) & 7) | rex_r;
3622 switch (b) {
3623 case 0x3f0: /* crc32 Gd,Eb */
3624 case 0x3f1: /* crc32 Gd,Ey */
3625 do_crc32:
3626 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3627 goto illegal_op;
3629 if ((b & 0xff) == 0xf0) {
3630 ot = MO_8;
3631 } else if (s->dflag != MO_64) {
3632 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3633 } else {
3634 ot = MO_64;
3637 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
3638 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3639 gen_helper_crc32(cpu_T0, cpu_tmp2_i32,
3640 cpu_T0, tcg_const_i32(8 << ot));
3642 ot = mo_64_32(s->dflag);
3643 gen_op_mov_reg_v(ot, reg, cpu_T0);
3644 break;
3646 case 0x1f0: /* crc32 or movbe */
3647 case 0x1f1:
3648 /* For these insns, the f3 prefix is supposed to have priority
3649 over the 66 prefix, but that's not what we implement above
3650 setting b1. */
3651 if (s->prefix & PREFIX_REPNZ) {
3652 goto do_crc32;
3654 /* FALLTHRU */
3655 case 0x0f0: /* movbe Gy,My */
3656 case 0x0f1: /* movbe My,Gy */
3657 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3658 goto illegal_op;
3660 if (s->dflag != MO_64) {
3661 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3662 } else {
3663 ot = MO_64;
3666 gen_lea_modrm(env, s, modrm);
3667 if ((b & 1) == 0) {
3668 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
3669 s->mem_index, ot | MO_BE);
3670 gen_op_mov_reg_v(ot, reg, cpu_T0);
3671 } else {
3672 tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
3673 s->mem_index, ot | MO_BE);
3675 break;
3677 case 0x0f2: /* andn Gy, By, Ey */
3678 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3679 || !(s->prefix & PREFIX_VEX)
3680 || s->vex_l != 0) {
3681 goto illegal_op;
3683 ot = mo_64_32(s->dflag);
3684 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3685 tcg_gen_andc_tl(cpu_T0, cpu_regs[s->vex_v], cpu_T0);
3686 gen_op_mov_reg_v(ot, reg, cpu_T0);
3687 gen_op_update1_cc();
3688 set_cc_op(s, CC_OP_LOGICB + ot);
3689 break;
3691 case 0x0f7: /* bextr Gy, Ey, By */
3692 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3693 || !(s->prefix & PREFIX_VEX)
3694 || s->vex_l != 0) {
3695 goto illegal_op;
3697 ot = mo_64_32(s->dflag);
3699 TCGv bound, zero;
3701 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3702 /* Extract START, and shift the operand.
3703 Shifts larger than operand size get zeros. */
3704 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
3705 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_A0);
3707 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3708 zero = tcg_const_tl(0);
3709 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T0, cpu_A0, bound,
3710 cpu_T0, zero);
3711 tcg_temp_free(zero);
3713 /* Extract the LEN into a mask. Lengths larger than
3714 operand size get all ones. */
3715 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
3716 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
3717 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
3718 cpu_A0, bound);
3719 tcg_temp_free(bound);
3720 tcg_gen_movi_tl(cpu_T1, 1);
3721 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_A0);
3722 tcg_gen_subi_tl(cpu_T1, cpu_T1, 1);
3723 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
3725 gen_op_mov_reg_v(ot, reg, cpu_T0);
3726 gen_op_update1_cc();
3727 set_cc_op(s, CC_OP_LOGICB + ot);
3729 break;
3731 case 0x0f5: /* bzhi Gy, Ey, By */
3732 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3733 || !(s->prefix & PREFIX_VEX)
3734 || s->vex_l != 0) {
3735 goto illegal_op;
3737 ot = mo_64_32(s->dflag);
3738 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3739 tcg_gen_ext8u_tl(cpu_T1, cpu_regs[s->vex_v]);
3741 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3742 /* Note that since we're using BMILG (in order to get O
3743 cleared) we need to store the inverse into C. */
3744 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3745 cpu_T1, bound);
3746 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T1, cpu_T1,
3747 bound, bound, cpu_T1);
3748 tcg_temp_free(bound);
3750 tcg_gen_movi_tl(cpu_A0, -1);
3751 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T1);
3752 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_A0);
3753 gen_op_mov_reg_v(ot, reg, cpu_T0);
3754 gen_op_update1_cc();
3755 set_cc_op(s, CC_OP_BMILGB + ot);
3756 break;
3758 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3759 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3760 || !(s->prefix & PREFIX_VEX)
3761 || s->vex_l != 0) {
3762 goto illegal_op;
3764 ot = mo_64_32(s->dflag);
3765 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3766 switch (ot) {
3767 default:
3768 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3769 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3770 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3771 cpu_tmp2_i32, cpu_tmp3_i32);
3772 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3773 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
3774 break;
3775 #ifdef TARGET_X86_64
3776 case MO_64:
3777 tcg_gen_mulu2_i64(cpu_T0, cpu_T1,
3778 cpu_T0, cpu_regs[R_EDX]);
3779 tcg_gen_mov_i64(cpu_regs[s->vex_v], cpu_T0);
3780 tcg_gen_mov_i64(cpu_regs[reg], cpu_T1);
3781 break;
3782 #endif
3784 break;
3786 case 0x3f5: /* pdep Gy, By, Ey */
3787 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3788 || !(s->prefix & PREFIX_VEX)
3789 || s->vex_l != 0) {
3790 goto illegal_op;
3792 ot = mo_64_32(s->dflag);
3793 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3794 /* Note that by zero-extending the mask operand, we
3795 automatically handle zero-extending the result. */
3796 if (ot == MO_64) {
3797 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3798 } else {
3799 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3801 gen_helper_pdep(cpu_regs[reg], cpu_T0, cpu_T1);
3802 break;
3804 case 0x2f5: /* pext Gy, By, Ey */
3805 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3806 || !(s->prefix & PREFIX_VEX)
3807 || s->vex_l != 0) {
3808 goto illegal_op;
3810 ot = mo_64_32(s->dflag);
3811 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3812 /* Note that by zero-extending the mask operand, we
3813 automatically handle zero-extending the result. */
3814 if (ot == MO_64) {
3815 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3816 } else {
3817 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3819 gen_helper_pext(cpu_regs[reg], cpu_T0, cpu_T1);
3820 break;
3822 case 0x1f6: /* adcx Gy, Ey */
3823 case 0x2f6: /* adox Gy, Ey */
3824 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3825 goto illegal_op;
3826 } else {
3827 TCGv carry_in, carry_out, zero;
3828 int end_op;
3830 ot = mo_64_32(s->dflag);
3831 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3833 /* Re-use the carry-out from a previous round. */
3834 TCGV_UNUSED(carry_in);
3835 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3836 switch (s->cc_op) {
3837 case CC_OP_ADCX:
3838 if (b == 0x1f6) {
3839 carry_in = cpu_cc_dst;
3840 end_op = CC_OP_ADCX;
3841 } else {
3842 end_op = CC_OP_ADCOX;
3844 break;
3845 case CC_OP_ADOX:
3846 if (b == 0x1f6) {
3847 end_op = CC_OP_ADCOX;
3848 } else {
3849 carry_in = cpu_cc_src2;
3850 end_op = CC_OP_ADOX;
3852 break;
3853 case CC_OP_ADCOX:
3854 end_op = CC_OP_ADCOX;
3855 carry_in = carry_out;
3856 break;
3857 default:
3858 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
3859 break;
3861 /* If we can't reuse carry-out, get it out of EFLAGS. */
3862 if (TCGV_IS_UNUSED(carry_in)) {
3863 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3864 gen_compute_eflags(s);
3866 carry_in = cpu_tmp0;
3867 tcg_gen_shri_tl(carry_in, cpu_cc_src,
3868 ctz32(b == 0x1f6 ? CC_C : CC_O));
3869 tcg_gen_andi_tl(carry_in, carry_in, 1);
3872 switch (ot) {
3873 #ifdef TARGET_X86_64
3874 case MO_32:
3875 /* If we know TL is 64-bit, and we want a 32-bit
3876 result, just do everything in 64-bit arithmetic. */
3877 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3878 tcg_gen_ext32u_i64(cpu_T0, cpu_T0);
3879 tcg_gen_add_i64(cpu_T0, cpu_T0, cpu_regs[reg]);
3880 tcg_gen_add_i64(cpu_T0, cpu_T0, carry_in);
3881 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T0);
3882 tcg_gen_shri_i64(carry_out, cpu_T0, 32);
3883 break;
3884 #endif
3885 default:
3886 /* Otherwise compute the carry-out in two steps. */
3887 zero = tcg_const_tl(0);
3888 tcg_gen_add2_tl(cpu_T0, carry_out,
3889 cpu_T0, zero,
3890 carry_in, zero);
3891 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3892 cpu_regs[reg], carry_out,
3893 cpu_T0, zero);
3894 tcg_temp_free(zero);
3895 break;
3897 set_cc_op(s, end_op);
3899 break;
3901 case 0x1f7: /* shlx Gy, Ey, By */
3902 case 0x2f7: /* sarx Gy, Ey, By */
3903 case 0x3f7: /* shrx Gy, Ey, By */
3904 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3905 || !(s->prefix & PREFIX_VEX)
3906 || s->vex_l != 0) {
3907 goto illegal_op;
3909 ot = mo_64_32(s->dflag);
3910 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3911 if (ot == MO_64) {
3912 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 63);
3913 } else {
3914 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 31);
3916 if (b == 0x1f7) {
3917 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
3918 } else if (b == 0x2f7) {
3919 if (ot != MO_64) {
3920 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
3922 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
3923 } else {
3924 if (ot != MO_64) {
3925 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
3927 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
3929 gen_op_mov_reg_v(ot, reg, cpu_T0);
3930 break;
3932 case 0x0f3:
3933 case 0x1f3:
3934 case 0x2f3:
3935 case 0x3f3: /* Group 17 */
3936 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3937 || !(s->prefix & PREFIX_VEX)
3938 || s->vex_l != 0) {
3939 goto illegal_op;
3941 ot = mo_64_32(s->dflag);
3942 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3944 switch (reg & 7) {
3945 case 1: /* blsr By,Ey */
3946 tcg_gen_neg_tl(cpu_T1, cpu_T0);
3947 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
3948 gen_op_mov_reg_v(ot, s->vex_v, cpu_T0);
3949 gen_op_update2_cc();
3950 set_cc_op(s, CC_OP_BMILGB + ot);
3951 break;
3953 case 2: /* blsmsk By,Ey */
3954 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
3955 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
3956 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_cc_src);
3957 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
3958 set_cc_op(s, CC_OP_BMILGB + ot);
3959 break;
3961 case 3: /* blsi By, Ey */
3962 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
3963 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
3964 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_cc_src);
3965 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
3966 set_cc_op(s, CC_OP_BMILGB + ot);
3967 break;
3969 default:
3970 goto unknown_op;
3972 break;
3974 default:
3975 goto unknown_op;
3977 break;
3979 case 0x03a:
3980 case 0x13a:
3981 b = modrm;
3982 modrm = cpu_ldub_code(env, s->pc++);
3983 rm = modrm & 7;
3984 reg = ((modrm >> 3) & 7) | rex_r;
3985 mod = (modrm >> 6) & 3;
3986 if (b1 >= 2) {
3987 goto unknown_op;
3990 sse_fn_eppi = sse_op_table7[b].op[b1];
3991 if (!sse_fn_eppi) {
3992 goto unknown_op;
3994 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
3995 goto illegal_op;
3997 if (sse_fn_eppi == SSE_SPECIAL) {
3998 ot = mo_64_32(s->dflag);
3999 rm = (modrm & 7) | REX_B(s);
4000 if (mod != 3)
4001 gen_lea_modrm(env, s, modrm);
4002 reg = ((modrm >> 3) & 7) | rex_r;
4003 val = cpu_ldub_code(env, s->pc++);
4004 switch (b) {
4005 case 0x14: /* pextrb */
4006 tcg_gen_ld8u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4007 xmm_regs[reg].ZMM_B(val & 15)));
4008 if (mod == 3) {
4009 gen_op_mov_reg_v(ot, rm, cpu_T0);
4010 } else {
4011 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4012 s->mem_index, MO_UB);
4014 break;
4015 case 0x15: /* pextrw */
4016 tcg_gen_ld16u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4017 xmm_regs[reg].ZMM_W(val & 7)));
4018 if (mod == 3) {
4019 gen_op_mov_reg_v(ot, rm, cpu_T0);
4020 } else {
4021 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4022 s->mem_index, MO_LEUW);
4024 break;
4025 case 0x16:
4026 if (ot == MO_32) { /* pextrd */
4027 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4028 offsetof(CPUX86State,
4029 xmm_regs[reg].ZMM_L(val & 3)));
4030 if (mod == 3) {
4031 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
4032 } else {
4033 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4034 s->mem_index, MO_LEUL);
4036 } else { /* pextrq */
4037 #ifdef TARGET_X86_64
4038 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4039 offsetof(CPUX86State,
4040 xmm_regs[reg].ZMM_Q(val & 1)));
4041 if (mod == 3) {
4042 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
4043 } else {
4044 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4045 s->mem_index, MO_LEQ);
4047 #else
4048 goto illegal_op;
4049 #endif
4051 break;
4052 case 0x17: /* extractps */
4053 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4054 xmm_regs[reg].ZMM_L(val & 3)));
4055 if (mod == 3) {
4056 gen_op_mov_reg_v(ot, rm, cpu_T0);
4057 } else {
4058 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4059 s->mem_index, MO_LEUL);
4061 break;
4062 case 0x20: /* pinsrb */
4063 if (mod == 3) {
4064 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
4065 } else {
4066 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
4067 s->mem_index, MO_UB);
4069 tcg_gen_st8_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4070 xmm_regs[reg].ZMM_B(val & 15)));
4071 break;
4072 case 0x21: /* insertps */
4073 if (mod == 3) {
4074 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4075 offsetof(CPUX86State,xmm_regs[rm]
4076 .ZMM_L((val >> 6) & 3)));
4077 } else {
4078 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4079 s->mem_index, MO_LEUL);
4081 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4082 offsetof(CPUX86State,xmm_regs[reg]
4083 .ZMM_L((val >> 4) & 3)));
4084 if ((val >> 0) & 1)
4085 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4086 cpu_env, offsetof(CPUX86State,
4087 xmm_regs[reg].ZMM_L(0)));
4088 if ((val >> 1) & 1)
4089 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4090 cpu_env, offsetof(CPUX86State,
4091 xmm_regs[reg].ZMM_L(1)));
4092 if ((val >> 2) & 1)
4093 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4094 cpu_env, offsetof(CPUX86State,
4095 xmm_regs[reg].ZMM_L(2)));
4096 if ((val >> 3) & 1)
4097 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4098 cpu_env, offsetof(CPUX86State,
4099 xmm_regs[reg].ZMM_L(3)));
4100 break;
4101 case 0x22:
4102 if (ot == MO_32) { /* pinsrd */
4103 if (mod == 3) {
4104 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
4105 } else {
4106 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4107 s->mem_index, MO_LEUL);
4109 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4110 offsetof(CPUX86State,
4111 xmm_regs[reg].ZMM_L(val & 3)));
4112 } else { /* pinsrq */
4113 #ifdef TARGET_X86_64
4114 if (mod == 3) {
4115 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4116 } else {
4117 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4118 s->mem_index, MO_LEQ);
4120 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4121 offsetof(CPUX86State,
4122 xmm_regs[reg].ZMM_Q(val & 1)));
4123 #else
4124 goto illegal_op;
4125 #endif
4127 break;
4129 return;
4132 if (b1) {
4133 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4134 if (mod == 3) {
4135 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4136 } else {
4137 op2_offset = offsetof(CPUX86State,xmm_t0);
4138 gen_lea_modrm(env, s, modrm);
4139 gen_ldo_env_A0(s, op2_offset);
4141 } else {
4142 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4143 if (mod == 3) {
4144 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4145 } else {
4146 op2_offset = offsetof(CPUX86State,mmx_t0);
4147 gen_lea_modrm(env, s, modrm);
4148 gen_ldq_env_A0(s, op2_offset);
4151 val = cpu_ldub_code(env, s->pc++);
4153 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4154 set_cc_op(s, CC_OP_EFLAGS);
4156 if (s->dflag == MO_64) {
4157 /* The helper must use entire 64-bit gp registers */
4158 val |= 1 << 8;
4162 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4163 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4164 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4165 break;
4167 case 0x33a:
4168 /* Various integer extensions at 0f 3a f[0-f]. */
4169 b = modrm | (b1 << 8);
4170 modrm = cpu_ldub_code(env, s->pc++);
4171 reg = ((modrm >> 3) & 7) | rex_r;
4173 switch (b) {
4174 case 0x3f0: /* rorx Gy,Ey, Ib */
4175 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4176 || !(s->prefix & PREFIX_VEX)
4177 || s->vex_l != 0) {
4178 goto illegal_op;
4180 ot = mo_64_32(s->dflag);
4181 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4182 b = cpu_ldub_code(env, s->pc++);
4183 if (ot == MO_64) {
4184 tcg_gen_rotri_tl(cpu_T0, cpu_T0, b & 63);
4185 } else {
4186 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4187 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4188 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
4190 gen_op_mov_reg_v(ot, reg, cpu_T0);
4191 break;
4193 default:
4194 goto unknown_op;
4196 break;
4198 default:
4199 unknown_op:
4200 gen_unknown_opcode(env, s);
4201 return;
4203 } else {
4204 /* generic MMX or SSE operation */
4205 switch(b) {
4206 case 0x70: /* pshufx insn */
4207 case 0xc6: /* pshufx insn */
4208 case 0xc2: /* compare insns */
4209 s->rip_offset = 1;
4210 break;
4211 default:
4212 break;
4214 if (is_xmm) {
4215 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4216 if (mod != 3) {
4217 int sz = 4;
4219 gen_lea_modrm(env, s, modrm);
4220 op2_offset = offsetof(CPUX86State,xmm_t0);
4222 switch (b) {
4223 case 0x50 ... 0x5a:
4224 case 0x5c ... 0x5f:
4225 case 0xc2:
4226 /* Most sse scalar operations. */
4227 if (b1 == 2) {
4228 sz = 2;
4229 } else if (b1 == 3) {
4230 sz = 3;
4232 break;
4234 case 0x2e: /* ucomis[sd] */
4235 case 0x2f: /* comis[sd] */
4236 if (b1 == 0) {
4237 sz = 2;
4238 } else {
4239 sz = 3;
4241 break;
4244 switch (sz) {
4245 case 2:
4246 /* 32 bit access */
4247 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
4248 tcg_gen_st32_tl(cpu_T0, cpu_env,
4249 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4250 break;
4251 case 3:
4252 /* 64 bit access */
4253 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4254 break;
4255 default:
4256 /* 128 bit access */
4257 gen_ldo_env_A0(s, op2_offset);
4258 break;
4260 } else {
4261 rm = (modrm & 7) | REX_B(s);
4262 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4264 } else {
4265 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4266 if (mod != 3) {
4267 gen_lea_modrm(env, s, modrm);
4268 op2_offset = offsetof(CPUX86State,mmx_t0);
4269 gen_ldq_env_A0(s, op2_offset);
4270 } else {
4271 rm = (modrm & 7);
4272 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4275 switch(b) {
4276 case 0x0f: /* 3DNow! data insns */
4277 val = cpu_ldub_code(env, s->pc++);
4278 sse_fn_epp = sse_op_table5[val];
4279 if (!sse_fn_epp) {
4280 goto unknown_op;
4282 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4283 goto illegal_op;
4285 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4286 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4287 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4288 break;
4289 case 0x70: /* pshufx insn */
4290 case 0xc6: /* pshufx insn */
4291 val = cpu_ldub_code(env, s->pc++);
4292 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4293 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4294 /* XXX: introduce a new table? */
4295 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4296 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4297 break;
4298 case 0xc2:
4299 /* compare insns */
4300 val = cpu_ldub_code(env, s->pc++);
4301 if (val >= 8)
4302 goto unknown_op;
4303 sse_fn_epp = sse_op_table4[val][b1];
4305 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4306 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4307 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4308 break;
4309 case 0xf7:
4310 /* maskmov : we must prepare A0 */
4311 if (mod != 3)
4312 goto illegal_op;
4313 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4314 gen_extu(s->aflag, cpu_A0);
4315 gen_add_A0_ds_seg(s);
4317 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4318 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4319 /* XXX: introduce a new table? */
4320 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4321 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4322 break;
4323 default:
4324 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4325 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4326 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4327 break;
4329 if (b == 0x2e || b == 0x2f) {
4330 set_cc_op(s, CC_OP_EFLAGS);
4335 /* convert one instruction. s->is_jmp is set if the translation must
4336 be stopped. Return the next pc value */
4337 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4338 target_ulong pc_start)
4340 int b, prefixes;
4341 int shift;
4342 TCGMemOp ot, aflag, dflag;
4343 int modrm, reg, rm, mod, op, opreg, val;
4344 target_ulong next_eip, tval;
4345 int rex_w, rex_r;
4347 s->pc_start = s->pc = pc_start;
4348 prefixes = 0;
4349 s->override = -1;
4350 rex_w = -1;
4351 rex_r = 0;
4352 #ifdef TARGET_X86_64
4353 s->rex_x = 0;
4354 s->rex_b = 0;
4355 x86_64_hregs = 0;
4356 #endif
4357 s->rip_offset = 0; /* for relative ip address */
4358 s->vex_l = 0;
4359 s->vex_v = 0;
4360 next_byte:
4361 b = cpu_ldub_code(env, s->pc);
4362 s->pc++;
4363 /* Collect prefixes. */
4364 switch (b) {
4365 case 0xf3:
4366 prefixes |= PREFIX_REPZ;
4367 goto next_byte;
4368 case 0xf2:
4369 prefixes |= PREFIX_REPNZ;
4370 goto next_byte;
4371 case 0xf0:
4372 prefixes |= PREFIX_LOCK;
4373 goto next_byte;
4374 case 0x2e:
4375 s->override = R_CS;
4376 goto next_byte;
4377 case 0x36:
4378 s->override = R_SS;
4379 goto next_byte;
4380 case 0x3e:
4381 s->override = R_DS;
4382 goto next_byte;
4383 case 0x26:
4384 s->override = R_ES;
4385 goto next_byte;
4386 case 0x64:
4387 s->override = R_FS;
4388 goto next_byte;
4389 case 0x65:
4390 s->override = R_GS;
4391 goto next_byte;
4392 case 0x66:
4393 prefixes |= PREFIX_DATA;
4394 goto next_byte;
4395 case 0x67:
4396 prefixes |= PREFIX_ADR;
4397 goto next_byte;
4398 #ifdef TARGET_X86_64
4399 case 0x40 ... 0x4f:
4400 if (CODE64(s)) {
4401 /* REX prefix */
4402 rex_w = (b >> 3) & 1;
4403 rex_r = (b & 0x4) << 1;
4404 s->rex_x = (b & 0x2) << 2;
4405 REX_B(s) = (b & 0x1) << 3;
4406 x86_64_hregs = 1; /* select uniform byte register addressing */
4407 goto next_byte;
4409 break;
4410 #endif
4411 case 0xc5: /* 2-byte VEX */
4412 case 0xc4: /* 3-byte VEX */
4413 /* VEX prefixes cannot be used except in 32-bit mode.
4414 Otherwise the instruction is LES or LDS. */
4415 if (s->code32 && !s->vm86) {
4416 static const int pp_prefix[4] = {
4417 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4419 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4421 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4422 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4423 otherwise the instruction is LES or LDS. */
4424 break;
4426 s->pc++;
4428 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4429 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4430 | PREFIX_LOCK | PREFIX_DATA)) {
4431 goto illegal_op;
4433 #ifdef TARGET_X86_64
4434 if (x86_64_hregs) {
4435 goto illegal_op;
4437 #endif
4438 rex_r = (~vex2 >> 4) & 8;
4439 if (b == 0xc5) {
4440 vex3 = vex2;
4441 b = cpu_ldub_code(env, s->pc++);
4442 } else {
4443 #ifdef TARGET_X86_64
4444 s->rex_x = (~vex2 >> 3) & 8;
4445 s->rex_b = (~vex2 >> 2) & 8;
4446 #endif
4447 vex3 = cpu_ldub_code(env, s->pc++);
4448 rex_w = (vex3 >> 7) & 1;
4449 switch (vex2 & 0x1f) {
4450 case 0x01: /* Implied 0f leading opcode bytes. */
4451 b = cpu_ldub_code(env, s->pc++) | 0x100;
4452 break;
4453 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4454 b = 0x138;
4455 break;
4456 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4457 b = 0x13a;
4458 break;
4459 default: /* Reserved for future use. */
4460 goto unknown_op;
4463 s->vex_v = (~vex3 >> 3) & 0xf;
4464 s->vex_l = (vex3 >> 2) & 1;
4465 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4467 break;
4470 /* Post-process prefixes. */
4471 if (CODE64(s)) {
4472 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4473 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4474 over 0x66 if both are present. */
4475 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4476 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4477 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4478 } else {
4479 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4480 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4481 dflag = MO_32;
4482 } else {
4483 dflag = MO_16;
4485 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4486 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4487 aflag = MO_32;
4488 } else {
4489 aflag = MO_16;
4493 s->prefix = prefixes;
4494 s->aflag = aflag;
4495 s->dflag = dflag;
4497 /* lock generation */
4498 if (prefixes & PREFIX_LOCK)
4499 gen_helper_lock();
4501 /* now check op code */
4502 reswitch:
4503 switch(b) {
4504 case 0x0f:
4505 /**************************/
4506 /* extended op code */
4507 b = cpu_ldub_code(env, s->pc++) | 0x100;
4508 goto reswitch;
4510 /**************************/
4511 /* arith & logic */
4512 case 0x00 ... 0x05:
4513 case 0x08 ... 0x0d:
4514 case 0x10 ... 0x15:
4515 case 0x18 ... 0x1d:
4516 case 0x20 ... 0x25:
4517 case 0x28 ... 0x2d:
4518 case 0x30 ... 0x35:
4519 case 0x38 ... 0x3d:
4521 int op, f, val;
4522 op = (b >> 3) & 7;
4523 f = (b >> 1) & 3;
4525 ot = mo_b_d(b, dflag);
4527 switch(f) {
4528 case 0: /* OP Ev, Gv */
4529 modrm = cpu_ldub_code(env, s->pc++);
4530 reg = ((modrm >> 3) & 7) | rex_r;
4531 mod = (modrm >> 6) & 3;
4532 rm = (modrm & 7) | REX_B(s);
4533 if (mod != 3) {
4534 gen_lea_modrm(env, s, modrm);
4535 opreg = OR_TMP0;
4536 } else if (op == OP_XORL && rm == reg) {
4537 xor_zero:
4538 /* xor reg, reg optimisation */
4539 set_cc_op(s, CC_OP_CLR);
4540 tcg_gen_movi_tl(cpu_T0, 0);
4541 gen_op_mov_reg_v(ot, reg, cpu_T0);
4542 break;
4543 } else {
4544 opreg = rm;
4546 gen_op_mov_v_reg(ot, cpu_T1, reg);
4547 gen_op(s, op, ot, opreg);
4548 break;
4549 case 1: /* OP Gv, Ev */
4550 modrm = cpu_ldub_code(env, s->pc++);
4551 mod = (modrm >> 6) & 3;
4552 reg = ((modrm >> 3) & 7) | rex_r;
4553 rm = (modrm & 7) | REX_B(s);
4554 if (mod != 3) {
4555 gen_lea_modrm(env, s, modrm);
4556 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4557 } else if (op == OP_XORL && rm == reg) {
4558 goto xor_zero;
4559 } else {
4560 gen_op_mov_v_reg(ot, cpu_T1, rm);
4562 gen_op(s, op, ot, reg);
4563 break;
4564 case 2: /* OP A, Iv */
4565 val = insn_get(env, s, ot);
4566 tcg_gen_movi_tl(cpu_T1, val);
4567 gen_op(s, op, ot, OR_EAX);
4568 break;
4571 break;
4573 case 0x82:
4574 if (CODE64(s))
4575 goto illegal_op;
4576 case 0x80: /* GRP1 */
4577 case 0x81:
4578 case 0x83:
4580 int val;
4582 ot = mo_b_d(b, dflag);
4584 modrm = cpu_ldub_code(env, s->pc++);
4585 mod = (modrm >> 6) & 3;
4586 rm = (modrm & 7) | REX_B(s);
4587 op = (modrm >> 3) & 7;
4589 if (mod != 3) {
4590 if (b == 0x83)
4591 s->rip_offset = 1;
4592 else
4593 s->rip_offset = insn_const_size(ot);
4594 gen_lea_modrm(env, s, modrm);
4595 opreg = OR_TMP0;
4596 } else {
4597 opreg = rm;
4600 switch(b) {
4601 default:
4602 case 0x80:
4603 case 0x81:
4604 case 0x82:
4605 val = insn_get(env, s, ot);
4606 break;
4607 case 0x83:
4608 val = (int8_t)insn_get(env, s, MO_8);
4609 break;
4611 tcg_gen_movi_tl(cpu_T1, val);
4612 gen_op(s, op, ot, opreg);
4614 break;
4616 /**************************/
4617 /* inc, dec, and other misc arith */
4618 case 0x40 ... 0x47: /* inc Gv */
4619 ot = dflag;
4620 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4621 break;
4622 case 0x48 ... 0x4f: /* dec Gv */
4623 ot = dflag;
4624 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4625 break;
4626 case 0xf6: /* GRP3 */
4627 case 0xf7:
4628 ot = mo_b_d(b, dflag);
4630 modrm = cpu_ldub_code(env, s->pc++);
4631 mod = (modrm >> 6) & 3;
4632 rm = (modrm & 7) | REX_B(s);
4633 op = (modrm >> 3) & 7;
4634 if (mod != 3) {
4635 if (op == 0)
4636 s->rip_offset = insn_const_size(ot);
4637 gen_lea_modrm(env, s, modrm);
4638 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4639 } else {
4640 gen_op_mov_v_reg(ot, cpu_T0, rm);
4643 switch(op) {
4644 case 0: /* test */
4645 val = insn_get(env, s, ot);
4646 tcg_gen_movi_tl(cpu_T1, val);
4647 gen_op_testl_T0_T1_cc();
4648 set_cc_op(s, CC_OP_LOGICB + ot);
4649 break;
4650 case 2: /* not */
4651 tcg_gen_not_tl(cpu_T0, cpu_T0);
4652 if (mod != 3) {
4653 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4654 } else {
4655 gen_op_mov_reg_v(ot, rm, cpu_T0);
4657 break;
4658 case 3: /* neg */
4659 tcg_gen_neg_tl(cpu_T0, cpu_T0);
4660 if (mod != 3) {
4661 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4662 } else {
4663 gen_op_mov_reg_v(ot, rm, cpu_T0);
4665 gen_op_update_neg_cc();
4666 set_cc_op(s, CC_OP_SUBB + ot);
4667 break;
4668 case 4: /* mul */
4669 switch(ot) {
4670 case MO_8:
4671 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4672 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
4673 tcg_gen_ext8u_tl(cpu_T1, cpu_T1);
4674 /* XXX: use 32 bit mul which could be faster */
4675 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4676 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4677 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4678 tcg_gen_andi_tl(cpu_cc_src, cpu_T0, 0xff00);
4679 set_cc_op(s, CC_OP_MULB);
4680 break;
4681 case MO_16:
4682 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4683 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4684 tcg_gen_ext16u_tl(cpu_T1, cpu_T1);
4685 /* XXX: use 32 bit mul which could be faster */
4686 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4687 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4688 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4689 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4690 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4691 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4692 set_cc_op(s, CC_OP_MULW);
4693 break;
4694 default:
4695 case MO_32:
4696 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4697 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4698 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4699 cpu_tmp2_i32, cpu_tmp3_i32);
4700 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4701 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4702 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4703 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4704 set_cc_op(s, CC_OP_MULL);
4705 break;
4706 #ifdef TARGET_X86_64
4707 case MO_64:
4708 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4709 cpu_T0, cpu_regs[R_EAX]);
4710 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4711 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4712 set_cc_op(s, CC_OP_MULQ);
4713 break;
4714 #endif
4716 break;
4717 case 5: /* imul */
4718 switch(ot) {
4719 case MO_8:
4720 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4721 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
4722 tcg_gen_ext8s_tl(cpu_T1, cpu_T1);
4723 /* XXX: use 32 bit mul which could be faster */
4724 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4725 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4726 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4727 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T0);
4728 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4729 set_cc_op(s, CC_OP_MULB);
4730 break;
4731 case MO_16:
4732 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4733 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4734 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
4735 /* XXX: use 32 bit mul which could be faster */
4736 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4737 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4738 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4739 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
4740 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4741 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4742 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4743 set_cc_op(s, CC_OP_MULW);
4744 break;
4745 default:
4746 case MO_32:
4747 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4748 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4749 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4750 cpu_tmp2_i32, cpu_tmp3_i32);
4751 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4752 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4753 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4754 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4755 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4756 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4757 set_cc_op(s, CC_OP_MULL);
4758 break;
4759 #ifdef TARGET_X86_64
4760 case MO_64:
4761 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4762 cpu_T0, cpu_regs[R_EAX]);
4763 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4764 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4765 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4766 set_cc_op(s, CC_OP_MULQ);
4767 break;
4768 #endif
4770 break;
4771 case 6: /* div */
4772 switch(ot) {
4773 case MO_8:
4774 gen_helper_divb_AL(cpu_env, cpu_T0);
4775 break;
4776 case MO_16:
4777 gen_helper_divw_AX(cpu_env, cpu_T0);
4778 break;
4779 default:
4780 case MO_32:
4781 gen_helper_divl_EAX(cpu_env, cpu_T0);
4782 break;
4783 #ifdef TARGET_X86_64
4784 case MO_64:
4785 gen_helper_divq_EAX(cpu_env, cpu_T0);
4786 break;
4787 #endif
4789 break;
4790 case 7: /* idiv */
4791 switch(ot) {
4792 case MO_8:
4793 gen_helper_idivb_AL(cpu_env, cpu_T0);
4794 break;
4795 case MO_16:
4796 gen_helper_idivw_AX(cpu_env, cpu_T0);
4797 break;
4798 default:
4799 case MO_32:
4800 gen_helper_idivl_EAX(cpu_env, cpu_T0);
4801 break;
4802 #ifdef TARGET_X86_64
4803 case MO_64:
4804 gen_helper_idivq_EAX(cpu_env, cpu_T0);
4805 break;
4806 #endif
4808 break;
4809 default:
4810 goto unknown_op;
4812 break;
4814 case 0xfe: /* GRP4 */
4815 case 0xff: /* GRP5 */
4816 ot = mo_b_d(b, dflag);
4818 modrm = cpu_ldub_code(env, s->pc++);
4819 mod = (modrm >> 6) & 3;
4820 rm = (modrm & 7) | REX_B(s);
4821 op = (modrm >> 3) & 7;
4822 if (op >= 2 && b == 0xfe) {
4823 goto unknown_op;
4825 if (CODE64(s)) {
4826 if (op == 2 || op == 4) {
4827 /* operand size for jumps is 64 bit */
4828 ot = MO_64;
4829 } else if (op == 3 || op == 5) {
4830 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
4831 } else if (op == 6) {
4832 /* default push size is 64 bit */
4833 ot = mo_pushpop(s, dflag);
4836 if (mod != 3) {
4837 gen_lea_modrm(env, s, modrm);
4838 if (op >= 2 && op != 3 && op != 5)
4839 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4840 } else {
4841 gen_op_mov_v_reg(ot, cpu_T0, rm);
4844 switch(op) {
4845 case 0: /* inc Ev */
4846 if (mod != 3)
4847 opreg = OR_TMP0;
4848 else
4849 opreg = rm;
4850 gen_inc(s, ot, opreg, 1);
4851 break;
4852 case 1: /* dec Ev */
4853 if (mod != 3)
4854 opreg = OR_TMP0;
4855 else
4856 opreg = rm;
4857 gen_inc(s, ot, opreg, -1);
4858 break;
4859 case 2: /* call Ev */
4860 /* XXX: optimize if memory (no 'and' is necessary) */
4861 if (dflag == MO_16) {
4862 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4864 next_eip = s->pc - s->cs_base;
4865 tcg_gen_movi_tl(cpu_T1, next_eip);
4866 gen_push_v(s, cpu_T1);
4867 gen_op_jmp_v(cpu_T0);
4868 gen_bnd_jmp(s);
4869 gen_eob(s);
4870 break;
4871 case 3: /* lcall Ev */
4872 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4873 gen_add_A0_im(s, 1 << ot);
4874 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
4875 do_lcall:
4876 if (s->pe && !s->vm86) {
4877 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4878 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
4879 tcg_const_i32(dflag - 1),
4880 tcg_const_tl(s->pc - s->cs_base));
4881 } else {
4882 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4883 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T1,
4884 tcg_const_i32(dflag - 1),
4885 tcg_const_i32(s->pc - s->cs_base));
4887 gen_eob(s);
4888 break;
4889 case 4: /* jmp Ev */
4890 if (dflag == MO_16) {
4891 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4893 gen_op_jmp_v(cpu_T0);
4894 gen_bnd_jmp(s);
4895 gen_eob(s);
4896 break;
4897 case 5: /* ljmp Ev */
4898 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4899 gen_add_A0_im(s, 1 << ot);
4900 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
4901 do_ljmp:
4902 if (s->pe && !s->vm86) {
4903 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4904 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
4905 tcg_const_tl(s->pc - s->cs_base));
4906 } else {
4907 gen_op_movl_seg_T0_vm(R_CS);
4908 gen_op_jmp_v(cpu_T1);
4910 gen_eob(s);
4911 break;
4912 case 6: /* push Ev */
4913 gen_push_v(s, cpu_T0);
4914 break;
4915 default:
4916 goto unknown_op;
4918 break;
4920 case 0x84: /* test Ev, Gv */
4921 case 0x85:
4922 ot = mo_b_d(b, dflag);
4924 modrm = cpu_ldub_code(env, s->pc++);
4925 reg = ((modrm >> 3) & 7) | rex_r;
4927 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4928 gen_op_mov_v_reg(ot, cpu_T1, reg);
4929 gen_op_testl_T0_T1_cc();
4930 set_cc_op(s, CC_OP_LOGICB + ot);
4931 break;
4933 case 0xa8: /* test eAX, Iv */
4934 case 0xa9:
4935 ot = mo_b_d(b, dflag);
4936 val = insn_get(env, s, ot);
4938 gen_op_mov_v_reg(ot, cpu_T0, OR_EAX);
4939 tcg_gen_movi_tl(cpu_T1, val);
4940 gen_op_testl_T0_T1_cc();
4941 set_cc_op(s, CC_OP_LOGICB + ot);
4942 break;
4944 case 0x98: /* CWDE/CBW */
4945 switch (dflag) {
4946 #ifdef TARGET_X86_64
4947 case MO_64:
4948 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
4949 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
4950 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T0);
4951 break;
4952 #endif
4953 case MO_32:
4954 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
4955 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4956 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T0);
4957 break;
4958 case MO_16:
4959 gen_op_mov_v_reg(MO_8, cpu_T0, R_EAX);
4960 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
4961 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4962 break;
4963 default:
4964 tcg_abort();
4966 break;
4967 case 0x99: /* CDQ/CWD */
4968 switch (dflag) {
4969 #ifdef TARGET_X86_64
4970 case MO_64:
4971 gen_op_mov_v_reg(MO_64, cpu_T0, R_EAX);
4972 tcg_gen_sari_tl(cpu_T0, cpu_T0, 63);
4973 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T0);
4974 break;
4975 #endif
4976 case MO_32:
4977 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
4978 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
4979 tcg_gen_sari_tl(cpu_T0, cpu_T0, 31);
4980 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T0);
4981 break;
4982 case MO_16:
4983 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
4984 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4985 tcg_gen_sari_tl(cpu_T0, cpu_T0, 15);
4986 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4987 break;
4988 default:
4989 tcg_abort();
4991 break;
4992 case 0x1af: /* imul Gv, Ev */
4993 case 0x69: /* imul Gv, Ev, I */
4994 case 0x6b:
4995 ot = dflag;
4996 modrm = cpu_ldub_code(env, s->pc++);
4997 reg = ((modrm >> 3) & 7) | rex_r;
4998 if (b == 0x69)
4999 s->rip_offset = insn_const_size(ot);
5000 else if (b == 0x6b)
5001 s->rip_offset = 1;
5002 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5003 if (b == 0x69) {
5004 val = insn_get(env, s, ot);
5005 tcg_gen_movi_tl(cpu_T1, val);
5006 } else if (b == 0x6b) {
5007 val = (int8_t)insn_get(env, s, MO_8);
5008 tcg_gen_movi_tl(cpu_T1, val);
5009 } else {
5010 gen_op_mov_v_reg(ot, cpu_T1, reg);
5012 switch (ot) {
5013 #ifdef TARGET_X86_64
5014 case MO_64:
5015 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T1, cpu_T0, cpu_T1);
5016 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5017 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5018 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T1);
5019 break;
5020 #endif
5021 case MO_32:
5022 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
5023 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
5024 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5025 cpu_tmp2_i32, cpu_tmp3_i32);
5026 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5027 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5028 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5029 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5030 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5031 break;
5032 default:
5033 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5034 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
5035 /* XXX: use 32 bit mul which could be faster */
5036 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
5037 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
5038 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
5039 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
5040 gen_op_mov_reg_v(ot, reg, cpu_T0);
5041 break;
5043 set_cc_op(s, CC_OP_MULB + ot);
5044 break;
5045 case 0x1c0:
5046 case 0x1c1: /* xadd Ev, Gv */
5047 ot = mo_b_d(b, dflag);
5048 modrm = cpu_ldub_code(env, s->pc++);
5049 reg = ((modrm >> 3) & 7) | rex_r;
5050 mod = (modrm >> 6) & 3;
5051 if (mod == 3) {
5052 rm = (modrm & 7) | REX_B(s);
5053 gen_op_mov_v_reg(ot, cpu_T0, reg);
5054 gen_op_mov_v_reg(ot, cpu_T1, rm);
5055 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5056 gen_op_mov_reg_v(ot, reg, cpu_T1);
5057 gen_op_mov_reg_v(ot, rm, cpu_T0);
5058 } else {
5059 gen_lea_modrm(env, s, modrm);
5060 gen_op_mov_v_reg(ot, cpu_T0, reg);
5061 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5062 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5063 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5064 gen_op_mov_reg_v(ot, reg, cpu_T1);
5066 gen_op_update2_cc();
5067 set_cc_op(s, CC_OP_ADDB + ot);
5068 break;
5069 case 0x1b0:
5070 case 0x1b1: /* cmpxchg Ev, Gv */
5072 TCGLabel *label1, *label2;
5073 TCGv t0, t1, t2, a0;
5075 ot = mo_b_d(b, dflag);
5076 modrm = cpu_ldub_code(env, s->pc++);
5077 reg = ((modrm >> 3) & 7) | rex_r;
5078 mod = (modrm >> 6) & 3;
5079 t0 = tcg_temp_local_new();
5080 t1 = tcg_temp_local_new();
5081 t2 = tcg_temp_local_new();
5082 a0 = tcg_temp_local_new();
5083 gen_op_mov_v_reg(ot, t1, reg);
5084 if (mod == 3) {
5085 rm = (modrm & 7) | REX_B(s);
5086 gen_op_mov_v_reg(ot, t0, rm);
5087 } else {
5088 gen_lea_modrm(env, s, modrm);
5089 tcg_gen_mov_tl(a0, cpu_A0);
5090 gen_op_ld_v(s, ot, t0, a0);
5091 rm = 0; /* avoid warning */
5093 label1 = gen_new_label();
5094 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5095 gen_extu(ot, t0);
5096 gen_extu(ot, t2);
5097 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
5098 label2 = gen_new_label();
5099 if (mod == 3) {
5100 gen_op_mov_reg_v(ot, R_EAX, t0);
5101 tcg_gen_br(label2);
5102 gen_set_label(label1);
5103 gen_op_mov_reg_v(ot, rm, t1);
5104 } else {
5105 /* perform no-op store cycle like physical cpu; must be
5106 before changing accumulator to ensure idempotency if
5107 the store faults and the instruction is restarted */
5108 gen_op_st_v(s, ot, t0, a0);
5109 gen_op_mov_reg_v(ot, R_EAX, t0);
5110 tcg_gen_br(label2);
5111 gen_set_label(label1);
5112 gen_op_st_v(s, ot, t1, a0);
5114 gen_set_label(label2);
5115 tcg_gen_mov_tl(cpu_cc_src, t0);
5116 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5117 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
5118 set_cc_op(s, CC_OP_SUBB + ot);
5119 tcg_temp_free(t0);
5120 tcg_temp_free(t1);
5121 tcg_temp_free(t2);
5122 tcg_temp_free(a0);
5124 break;
5125 case 0x1c7: /* cmpxchg8b */
5126 modrm = cpu_ldub_code(env, s->pc++);
5127 mod = (modrm >> 6) & 3;
5128 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5129 goto illegal_op;
5130 #ifdef TARGET_X86_64
5131 if (dflag == MO_64) {
5132 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5133 goto illegal_op;
5134 gen_lea_modrm(env, s, modrm);
5135 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5136 } else
5137 #endif
5139 if (!(s->cpuid_features & CPUID_CX8))
5140 goto illegal_op;
5141 gen_lea_modrm(env, s, modrm);
5142 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5144 set_cc_op(s, CC_OP_EFLAGS);
5145 break;
5147 /**************************/
5148 /* push/pop */
5149 case 0x50 ... 0x57: /* push */
5150 gen_op_mov_v_reg(MO_32, cpu_T0, (b & 7) | REX_B(s));
5151 gen_push_v(s, cpu_T0);
5152 break;
5153 case 0x58 ... 0x5f: /* pop */
5154 ot = gen_pop_T0(s);
5155 /* NOTE: order is important for pop %sp */
5156 gen_pop_update(s, ot);
5157 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T0);
5158 break;
5159 case 0x60: /* pusha */
5160 if (CODE64(s))
5161 goto illegal_op;
5162 gen_pusha(s);
5163 break;
5164 case 0x61: /* popa */
5165 if (CODE64(s))
5166 goto illegal_op;
5167 gen_popa(s);
5168 break;
5169 case 0x68: /* push Iv */
5170 case 0x6a:
5171 ot = mo_pushpop(s, dflag);
5172 if (b == 0x68)
5173 val = insn_get(env, s, ot);
5174 else
5175 val = (int8_t)insn_get(env, s, MO_8);
5176 tcg_gen_movi_tl(cpu_T0, val);
5177 gen_push_v(s, cpu_T0);
5178 break;
5179 case 0x8f: /* pop Ev */
5180 modrm = cpu_ldub_code(env, s->pc++);
5181 mod = (modrm >> 6) & 3;
5182 ot = gen_pop_T0(s);
5183 if (mod == 3) {
5184 /* NOTE: order is important for pop %sp */
5185 gen_pop_update(s, ot);
5186 rm = (modrm & 7) | REX_B(s);
5187 gen_op_mov_reg_v(ot, rm, cpu_T0);
5188 } else {
5189 /* NOTE: order is important too for MMU exceptions */
5190 s->popl_esp_hack = 1 << ot;
5191 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5192 s->popl_esp_hack = 0;
5193 gen_pop_update(s, ot);
5195 break;
5196 case 0xc8: /* enter */
5198 int level;
5199 val = cpu_lduw_code(env, s->pc);
5200 s->pc += 2;
5201 level = cpu_ldub_code(env, s->pc++);
5202 gen_enter(s, val, level);
5204 break;
5205 case 0xc9: /* leave */
5206 gen_leave(s);
5207 break;
5208 case 0x06: /* push es */
5209 case 0x0e: /* push cs */
5210 case 0x16: /* push ss */
5211 case 0x1e: /* push ds */
5212 if (CODE64(s))
5213 goto illegal_op;
5214 gen_op_movl_T0_seg(b >> 3);
5215 gen_push_v(s, cpu_T0);
5216 break;
5217 case 0x1a0: /* push fs */
5218 case 0x1a8: /* push gs */
5219 gen_op_movl_T0_seg((b >> 3) & 7);
5220 gen_push_v(s, cpu_T0);
5221 break;
5222 case 0x07: /* pop es */
5223 case 0x17: /* pop ss */
5224 case 0x1f: /* pop ds */
5225 if (CODE64(s))
5226 goto illegal_op;
5227 reg = b >> 3;
5228 ot = gen_pop_T0(s);
5229 gen_movl_seg_T0(s, reg);
5230 gen_pop_update(s, ot);
5231 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5232 if (s->is_jmp) {
5233 gen_jmp_im(s->pc - s->cs_base);
5234 if (reg == R_SS) {
5235 s->tf = 0;
5236 gen_eob_inhibit_irq(s, true);
5237 } else {
5238 gen_eob(s);
5241 break;
5242 case 0x1a1: /* pop fs */
5243 case 0x1a9: /* pop gs */
5244 ot = gen_pop_T0(s);
5245 gen_movl_seg_T0(s, (b >> 3) & 7);
5246 gen_pop_update(s, ot);
5247 if (s->is_jmp) {
5248 gen_jmp_im(s->pc - s->cs_base);
5249 gen_eob(s);
5251 break;
5253 /**************************/
5254 /* mov */
5255 case 0x88:
5256 case 0x89: /* mov Gv, Ev */
5257 ot = mo_b_d(b, dflag);
5258 modrm = cpu_ldub_code(env, s->pc++);
5259 reg = ((modrm >> 3) & 7) | rex_r;
5261 /* generate a generic store */
5262 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5263 break;
5264 case 0xc6:
5265 case 0xc7: /* mov Ev, Iv */
5266 ot = mo_b_d(b, dflag);
5267 modrm = cpu_ldub_code(env, s->pc++);
5268 mod = (modrm >> 6) & 3;
5269 if (mod != 3) {
5270 s->rip_offset = insn_const_size(ot);
5271 gen_lea_modrm(env, s, modrm);
5273 val = insn_get(env, s, ot);
5274 tcg_gen_movi_tl(cpu_T0, val);
5275 if (mod != 3) {
5276 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5277 } else {
5278 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T0);
5280 break;
5281 case 0x8a:
5282 case 0x8b: /* mov Ev, Gv */
5283 ot = mo_b_d(b, dflag);
5284 modrm = cpu_ldub_code(env, s->pc++);
5285 reg = ((modrm >> 3) & 7) | rex_r;
5287 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5288 gen_op_mov_reg_v(ot, reg, cpu_T0);
5289 break;
5290 case 0x8e: /* mov seg, Gv */
5291 modrm = cpu_ldub_code(env, s->pc++);
5292 reg = (modrm >> 3) & 7;
5293 if (reg >= 6 || reg == R_CS)
5294 goto illegal_op;
5295 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5296 gen_movl_seg_T0(s, reg);
5297 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5298 if (s->is_jmp) {
5299 gen_jmp_im(s->pc - s->cs_base);
5300 if (reg == R_SS) {
5301 s->tf = 0;
5302 gen_eob_inhibit_irq(s, true);
5303 } else {
5304 gen_eob(s);
5307 break;
5308 case 0x8c: /* mov Gv, seg */
5309 modrm = cpu_ldub_code(env, s->pc++);
5310 reg = (modrm >> 3) & 7;
5311 mod = (modrm >> 6) & 3;
5312 if (reg >= 6)
5313 goto illegal_op;
5314 gen_op_movl_T0_seg(reg);
5315 ot = mod == 3 ? dflag : MO_16;
5316 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5317 break;
5319 case 0x1b6: /* movzbS Gv, Eb */
5320 case 0x1b7: /* movzwS Gv, Eb */
5321 case 0x1be: /* movsbS Gv, Eb */
5322 case 0x1bf: /* movswS Gv, Eb */
5324 TCGMemOp d_ot;
5325 TCGMemOp s_ot;
5327 /* d_ot is the size of destination */
5328 d_ot = dflag;
5329 /* ot is the size of source */
5330 ot = (b & 1) + MO_8;
5331 /* s_ot is the sign+size of source */
5332 s_ot = b & 8 ? MO_SIGN | ot : ot;
5334 modrm = cpu_ldub_code(env, s->pc++);
5335 reg = ((modrm >> 3) & 7) | rex_r;
5336 mod = (modrm >> 6) & 3;
5337 rm = (modrm & 7) | REX_B(s);
5339 if (mod == 3) {
5340 gen_op_mov_v_reg(ot, cpu_T0, rm);
5341 switch (s_ot) {
5342 case MO_UB:
5343 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
5344 break;
5345 case MO_SB:
5346 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
5347 break;
5348 case MO_UW:
5349 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
5350 break;
5351 default:
5352 case MO_SW:
5353 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5354 break;
5356 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5357 } else {
5358 gen_lea_modrm(env, s, modrm);
5359 gen_op_ld_v(s, s_ot, cpu_T0, cpu_A0);
5360 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5363 break;
5365 case 0x8d: /* lea */
5366 modrm = cpu_ldub_code(env, s->pc++);
5367 mod = (modrm >> 6) & 3;
5368 if (mod == 3)
5369 goto illegal_op;
5370 reg = ((modrm >> 3) & 7) | rex_r;
5372 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5373 TCGv ea = gen_lea_modrm_1(a);
5374 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5375 gen_op_mov_reg_v(dflag, reg, cpu_A0);
5377 break;
5379 case 0xa0: /* mov EAX, Ov */
5380 case 0xa1:
5381 case 0xa2: /* mov Ov, EAX */
5382 case 0xa3:
5384 target_ulong offset_addr;
5386 ot = mo_b_d(b, dflag);
5387 switch (s->aflag) {
5388 #ifdef TARGET_X86_64
5389 case MO_64:
5390 offset_addr = cpu_ldq_code(env, s->pc);
5391 s->pc += 8;
5392 break;
5393 #endif
5394 default:
5395 offset_addr = insn_get(env, s, s->aflag);
5396 break;
5398 tcg_gen_movi_tl(cpu_A0, offset_addr);
5399 gen_add_A0_ds_seg(s);
5400 if ((b & 2) == 0) {
5401 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
5402 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
5403 } else {
5404 gen_op_mov_v_reg(ot, cpu_T0, R_EAX);
5405 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5408 break;
5409 case 0xd7: /* xlat */
5410 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5411 tcg_gen_ext8u_tl(cpu_T0, cpu_regs[R_EAX]);
5412 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T0);
5413 gen_extu(s->aflag, cpu_A0);
5414 gen_add_A0_ds_seg(s);
5415 gen_op_ld_v(s, MO_8, cpu_T0, cpu_A0);
5416 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
5417 break;
5418 case 0xb0 ... 0xb7: /* mov R, Ib */
5419 val = insn_get(env, s, MO_8);
5420 tcg_gen_movi_tl(cpu_T0, val);
5421 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T0);
5422 break;
5423 case 0xb8 ... 0xbf: /* mov R, Iv */
5424 #ifdef TARGET_X86_64
5425 if (dflag == MO_64) {
5426 uint64_t tmp;
5427 /* 64 bit case */
5428 tmp = cpu_ldq_code(env, s->pc);
5429 s->pc += 8;
5430 reg = (b & 7) | REX_B(s);
5431 tcg_gen_movi_tl(cpu_T0, tmp);
5432 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
5433 } else
5434 #endif
5436 ot = dflag;
5437 val = insn_get(env, s, ot);
5438 reg = (b & 7) | REX_B(s);
5439 tcg_gen_movi_tl(cpu_T0, val);
5440 gen_op_mov_reg_v(ot, reg, cpu_T0);
5442 break;
5444 case 0x91 ... 0x97: /* xchg R, EAX */
5445 do_xchg_reg_eax:
5446 ot = dflag;
5447 reg = (b & 7) | REX_B(s);
5448 rm = R_EAX;
5449 goto do_xchg_reg;
5450 case 0x86:
5451 case 0x87: /* xchg Ev, Gv */
5452 ot = mo_b_d(b, dflag);
5453 modrm = cpu_ldub_code(env, s->pc++);
5454 reg = ((modrm >> 3) & 7) | rex_r;
5455 mod = (modrm >> 6) & 3;
5456 if (mod == 3) {
5457 rm = (modrm & 7) | REX_B(s);
5458 do_xchg_reg:
5459 gen_op_mov_v_reg(ot, cpu_T0, reg);
5460 gen_op_mov_v_reg(ot, cpu_T1, rm);
5461 gen_op_mov_reg_v(ot, rm, cpu_T0);
5462 gen_op_mov_reg_v(ot, reg, cpu_T1);
5463 } else {
5464 gen_lea_modrm(env, s, modrm);
5465 gen_op_mov_v_reg(ot, cpu_T0, reg);
5466 /* for xchg, lock is implicit */
5467 if (!(prefixes & PREFIX_LOCK))
5468 gen_helper_lock();
5469 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5470 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5471 if (!(prefixes & PREFIX_LOCK))
5472 gen_helper_unlock();
5473 gen_op_mov_reg_v(ot, reg, cpu_T1);
5475 break;
5476 case 0xc4: /* les Gv */
5477 /* In CODE64 this is VEX3; see above. */
5478 op = R_ES;
5479 goto do_lxx;
5480 case 0xc5: /* lds Gv */
5481 /* In CODE64 this is VEX2; see above. */
5482 op = R_DS;
5483 goto do_lxx;
5484 case 0x1b2: /* lss Gv */
5485 op = R_SS;
5486 goto do_lxx;
5487 case 0x1b4: /* lfs Gv */
5488 op = R_FS;
5489 goto do_lxx;
5490 case 0x1b5: /* lgs Gv */
5491 op = R_GS;
5492 do_lxx:
5493 ot = dflag != MO_16 ? MO_32 : MO_16;
5494 modrm = cpu_ldub_code(env, s->pc++);
5495 reg = ((modrm >> 3) & 7) | rex_r;
5496 mod = (modrm >> 6) & 3;
5497 if (mod == 3)
5498 goto illegal_op;
5499 gen_lea_modrm(env, s, modrm);
5500 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5501 gen_add_A0_im(s, 1 << ot);
5502 /* load the segment first to handle exceptions properly */
5503 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
5504 gen_movl_seg_T0(s, op);
5505 /* then put the data */
5506 gen_op_mov_reg_v(ot, reg, cpu_T1);
5507 if (s->is_jmp) {
5508 gen_jmp_im(s->pc - s->cs_base);
5509 gen_eob(s);
5511 break;
5513 /************************/
5514 /* shifts */
5515 case 0xc0:
5516 case 0xc1:
5517 /* shift Ev,Ib */
5518 shift = 2;
5519 grp2:
5521 ot = mo_b_d(b, dflag);
5522 modrm = cpu_ldub_code(env, s->pc++);
5523 mod = (modrm >> 6) & 3;
5524 op = (modrm >> 3) & 7;
5526 if (mod != 3) {
5527 if (shift == 2) {
5528 s->rip_offset = 1;
5530 gen_lea_modrm(env, s, modrm);
5531 opreg = OR_TMP0;
5532 } else {
5533 opreg = (modrm & 7) | REX_B(s);
5536 /* simpler op */
5537 if (shift == 0) {
5538 gen_shift(s, op, ot, opreg, OR_ECX);
5539 } else {
5540 if (shift == 2) {
5541 shift = cpu_ldub_code(env, s->pc++);
5543 gen_shifti(s, op, ot, opreg, shift);
5546 break;
5547 case 0xd0:
5548 case 0xd1:
5549 /* shift Ev,1 */
5550 shift = 1;
5551 goto grp2;
5552 case 0xd2:
5553 case 0xd3:
5554 /* shift Ev,cl */
5555 shift = 0;
5556 goto grp2;
5558 case 0x1a4: /* shld imm */
5559 op = 0;
5560 shift = 1;
5561 goto do_shiftd;
5562 case 0x1a5: /* shld cl */
5563 op = 0;
5564 shift = 0;
5565 goto do_shiftd;
5566 case 0x1ac: /* shrd imm */
5567 op = 1;
5568 shift = 1;
5569 goto do_shiftd;
5570 case 0x1ad: /* shrd cl */
5571 op = 1;
5572 shift = 0;
5573 do_shiftd:
5574 ot = dflag;
5575 modrm = cpu_ldub_code(env, s->pc++);
5576 mod = (modrm >> 6) & 3;
5577 rm = (modrm & 7) | REX_B(s);
5578 reg = ((modrm >> 3) & 7) | rex_r;
5579 if (mod != 3) {
5580 gen_lea_modrm(env, s, modrm);
5581 opreg = OR_TMP0;
5582 } else {
5583 opreg = rm;
5585 gen_op_mov_v_reg(ot, cpu_T1, reg);
5587 if (shift) {
5588 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5589 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5590 tcg_temp_free(imm);
5591 } else {
5592 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5594 break;
5596 /************************/
5597 /* floats */
5598 case 0xd8 ... 0xdf:
5599 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5600 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5601 /* XXX: what to do if illegal op ? */
5602 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5603 break;
5605 modrm = cpu_ldub_code(env, s->pc++);
5606 mod = (modrm >> 6) & 3;
5607 rm = modrm & 7;
5608 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5609 if (mod != 3) {
5610 /* memory op */
5611 gen_lea_modrm(env, s, modrm);
5612 switch(op) {
5613 case 0x00 ... 0x07: /* fxxxs */
5614 case 0x10 ... 0x17: /* fixxxl */
5615 case 0x20 ... 0x27: /* fxxxl */
5616 case 0x30 ... 0x37: /* fixxx */
5618 int op1;
5619 op1 = op & 7;
5621 switch(op >> 4) {
5622 case 0:
5623 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5624 s->mem_index, MO_LEUL);
5625 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5626 break;
5627 case 1:
5628 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5629 s->mem_index, MO_LEUL);
5630 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5631 break;
5632 case 2:
5633 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5634 s->mem_index, MO_LEQ);
5635 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5636 break;
5637 case 3:
5638 default:
5639 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5640 s->mem_index, MO_LESW);
5641 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5642 break;
5645 gen_helper_fp_arith_ST0_FT0(op1);
5646 if (op1 == 3) {
5647 /* fcomp needs pop */
5648 gen_helper_fpop(cpu_env);
5651 break;
5652 case 0x08: /* flds */
5653 case 0x0a: /* fsts */
5654 case 0x0b: /* fstps */
5655 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5656 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5657 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5658 switch(op & 7) {
5659 case 0:
5660 switch(op >> 4) {
5661 case 0:
5662 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5663 s->mem_index, MO_LEUL);
5664 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5665 break;
5666 case 1:
5667 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5668 s->mem_index, MO_LEUL);
5669 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5670 break;
5671 case 2:
5672 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5673 s->mem_index, MO_LEQ);
5674 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5675 break;
5676 case 3:
5677 default:
5678 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5679 s->mem_index, MO_LESW);
5680 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5681 break;
5683 break;
5684 case 1:
5685 /* XXX: the corresponding CPUID bit must be tested ! */
5686 switch(op >> 4) {
5687 case 1:
5688 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5689 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5690 s->mem_index, MO_LEUL);
5691 break;
5692 case 2:
5693 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5694 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5695 s->mem_index, MO_LEQ);
5696 break;
5697 case 3:
5698 default:
5699 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5700 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5701 s->mem_index, MO_LEUW);
5702 break;
5704 gen_helper_fpop(cpu_env);
5705 break;
5706 default:
5707 switch(op >> 4) {
5708 case 0:
5709 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5710 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5711 s->mem_index, MO_LEUL);
5712 break;
5713 case 1:
5714 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5715 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5716 s->mem_index, MO_LEUL);
5717 break;
5718 case 2:
5719 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5720 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5721 s->mem_index, MO_LEQ);
5722 break;
5723 case 3:
5724 default:
5725 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5726 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5727 s->mem_index, MO_LEUW);
5728 break;
5730 if ((op & 7) == 3)
5731 gen_helper_fpop(cpu_env);
5732 break;
5734 break;
5735 case 0x0c: /* fldenv mem */
5736 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5737 break;
5738 case 0x0d: /* fldcw mem */
5739 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5740 s->mem_index, MO_LEUW);
5741 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5742 break;
5743 case 0x0e: /* fnstenv mem */
5744 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5745 break;
5746 case 0x0f: /* fnstcw mem */
5747 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5748 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5749 s->mem_index, MO_LEUW);
5750 break;
5751 case 0x1d: /* fldt mem */
5752 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5753 break;
5754 case 0x1f: /* fstpt mem */
5755 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5756 gen_helper_fpop(cpu_env);
5757 break;
5758 case 0x2c: /* frstor mem */
5759 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5760 break;
5761 case 0x2e: /* fnsave mem */
5762 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5763 break;
5764 case 0x2f: /* fnstsw mem */
5765 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5766 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5767 s->mem_index, MO_LEUW);
5768 break;
5769 case 0x3c: /* fbld */
5770 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5771 break;
5772 case 0x3e: /* fbstp */
5773 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5774 gen_helper_fpop(cpu_env);
5775 break;
5776 case 0x3d: /* fildll */
5777 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5778 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5779 break;
5780 case 0x3f: /* fistpll */
5781 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5782 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5783 gen_helper_fpop(cpu_env);
5784 break;
5785 default:
5786 goto unknown_op;
5788 } else {
5789 /* register float ops */
5790 opreg = rm;
5792 switch(op) {
5793 case 0x08: /* fld sti */
5794 gen_helper_fpush(cpu_env);
5795 gen_helper_fmov_ST0_STN(cpu_env,
5796 tcg_const_i32((opreg + 1) & 7));
5797 break;
5798 case 0x09: /* fxchg sti */
5799 case 0x29: /* fxchg4 sti, undocumented op */
5800 case 0x39: /* fxchg7 sti, undocumented op */
5801 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5802 break;
5803 case 0x0a: /* grp d9/2 */
5804 switch(rm) {
5805 case 0: /* fnop */
5806 /* check exceptions (FreeBSD FPU probe) */
5807 gen_helper_fwait(cpu_env);
5808 break;
5809 default:
5810 goto unknown_op;
5812 break;
5813 case 0x0c: /* grp d9/4 */
5814 switch(rm) {
5815 case 0: /* fchs */
5816 gen_helper_fchs_ST0(cpu_env);
5817 break;
5818 case 1: /* fabs */
5819 gen_helper_fabs_ST0(cpu_env);
5820 break;
5821 case 4: /* ftst */
5822 gen_helper_fldz_FT0(cpu_env);
5823 gen_helper_fcom_ST0_FT0(cpu_env);
5824 break;
5825 case 5: /* fxam */
5826 gen_helper_fxam_ST0(cpu_env);
5827 break;
5828 default:
5829 goto unknown_op;
5831 break;
5832 case 0x0d: /* grp d9/5 */
5834 switch(rm) {
5835 case 0:
5836 gen_helper_fpush(cpu_env);
5837 gen_helper_fld1_ST0(cpu_env);
5838 break;
5839 case 1:
5840 gen_helper_fpush(cpu_env);
5841 gen_helper_fldl2t_ST0(cpu_env);
5842 break;
5843 case 2:
5844 gen_helper_fpush(cpu_env);
5845 gen_helper_fldl2e_ST0(cpu_env);
5846 break;
5847 case 3:
5848 gen_helper_fpush(cpu_env);
5849 gen_helper_fldpi_ST0(cpu_env);
5850 break;
5851 case 4:
5852 gen_helper_fpush(cpu_env);
5853 gen_helper_fldlg2_ST0(cpu_env);
5854 break;
5855 case 5:
5856 gen_helper_fpush(cpu_env);
5857 gen_helper_fldln2_ST0(cpu_env);
5858 break;
5859 case 6:
5860 gen_helper_fpush(cpu_env);
5861 gen_helper_fldz_ST0(cpu_env);
5862 break;
5863 default:
5864 goto unknown_op;
5867 break;
5868 case 0x0e: /* grp d9/6 */
5869 switch(rm) {
5870 case 0: /* f2xm1 */
5871 gen_helper_f2xm1(cpu_env);
5872 break;
5873 case 1: /* fyl2x */
5874 gen_helper_fyl2x(cpu_env);
5875 break;
5876 case 2: /* fptan */
5877 gen_helper_fptan(cpu_env);
5878 break;
5879 case 3: /* fpatan */
5880 gen_helper_fpatan(cpu_env);
5881 break;
5882 case 4: /* fxtract */
5883 gen_helper_fxtract(cpu_env);
5884 break;
5885 case 5: /* fprem1 */
5886 gen_helper_fprem1(cpu_env);
5887 break;
5888 case 6: /* fdecstp */
5889 gen_helper_fdecstp(cpu_env);
5890 break;
5891 default:
5892 case 7: /* fincstp */
5893 gen_helper_fincstp(cpu_env);
5894 break;
5896 break;
5897 case 0x0f: /* grp d9/7 */
5898 switch(rm) {
5899 case 0: /* fprem */
5900 gen_helper_fprem(cpu_env);
5901 break;
5902 case 1: /* fyl2xp1 */
5903 gen_helper_fyl2xp1(cpu_env);
5904 break;
5905 case 2: /* fsqrt */
5906 gen_helper_fsqrt(cpu_env);
5907 break;
5908 case 3: /* fsincos */
5909 gen_helper_fsincos(cpu_env);
5910 break;
5911 case 5: /* fscale */
5912 gen_helper_fscale(cpu_env);
5913 break;
5914 case 4: /* frndint */
5915 gen_helper_frndint(cpu_env);
5916 break;
5917 case 6: /* fsin */
5918 gen_helper_fsin(cpu_env);
5919 break;
5920 default:
5921 case 7: /* fcos */
5922 gen_helper_fcos(cpu_env);
5923 break;
5925 break;
5926 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
5927 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
5928 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
5930 int op1;
5932 op1 = op & 7;
5933 if (op >= 0x20) {
5934 gen_helper_fp_arith_STN_ST0(op1, opreg);
5935 if (op >= 0x30)
5936 gen_helper_fpop(cpu_env);
5937 } else {
5938 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5939 gen_helper_fp_arith_ST0_FT0(op1);
5942 break;
5943 case 0x02: /* fcom */
5944 case 0x22: /* fcom2, undocumented op */
5945 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5946 gen_helper_fcom_ST0_FT0(cpu_env);
5947 break;
5948 case 0x03: /* fcomp */
5949 case 0x23: /* fcomp3, undocumented op */
5950 case 0x32: /* fcomp5, undocumented op */
5951 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5952 gen_helper_fcom_ST0_FT0(cpu_env);
5953 gen_helper_fpop(cpu_env);
5954 break;
5955 case 0x15: /* da/5 */
5956 switch(rm) {
5957 case 1: /* fucompp */
5958 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
5959 gen_helper_fucom_ST0_FT0(cpu_env);
5960 gen_helper_fpop(cpu_env);
5961 gen_helper_fpop(cpu_env);
5962 break;
5963 default:
5964 goto unknown_op;
5966 break;
5967 case 0x1c:
5968 switch(rm) {
5969 case 0: /* feni (287 only, just do nop here) */
5970 break;
5971 case 1: /* fdisi (287 only, just do nop here) */
5972 break;
5973 case 2: /* fclex */
5974 gen_helper_fclex(cpu_env);
5975 break;
5976 case 3: /* fninit */
5977 gen_helper_fninit(cpu_env);
5978 break;
5979 case 4: /* fsetpm (287 only, just do nop here) */
5980 break;
5981 default:
5982 goto unknown_op;
5984 break;
5985 case 0x1d: /* fucomi */
5986 if (!(s->cpuid_features & CPUID_CMOV)) {
5987 goto illegal_op;
5989 gen_update_cc_op(s);
5990 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
5991 gen_helper_fucomi_ST0_FT0(cpu_env);
5992 set_cc_op(s, CC_OP_EFLAGS);
5993 break;
5994 case 0x1e: /* fcomi */
5995 if (!(s->cpuid_features & CPUID_CMOV)) {
5996 goto illegal_op;
5998 gen_update_cc_op(s);
5999 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6000 gen_helper_fcomi_ST0_FT0(cpu_env);
6001 set_cc_op(s, CC_OP_EFLAGS);
6002 break;
6003 case 0x28: /* ffree sti */
6004 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6005 break;
6006 case 0x2a: /* fst sti */
6007 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6008 break;
6009 case 0x2b: /* fstp sti */
6010 case 0x0b: /* fstp1 sti, undocumented op */
6011 case 0x3a: /* fstp8 sti, undocumented op */
6012 case 0x3b: /* fstp9 sti, undocumented op */
6013 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6014 gen_helper_fpop(cpu_env);
6015 break;
6016 case 0x2c: /* fucom st(i) */
6017 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6018 gen_helper_fucom_ST0_FT0(cpu_env);
6019 break;
6020 case 0x2d: /* fucomp st(i) */
6021 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6022 gen_helper_fucom_ST0_FT0(cpu_env);
6023 gen_helper_fpop(cpu_env);
6024 break;
6025 case 0x33: /* de/3 */
6026 switch(rm) {
6027 case 1: /* fcompp */
6028 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6029 gen_helper_fcom_ST0_FT0(cpu_env);
6030 gen_helper_fpop(cpu_env);
6031 gen_helper_fpop(cpu_env);
6032 break;
6033 default:
6034 goto unknown_op;
6036 break;
6037 case 0x38: /* ffreep sti, undocumented op */
6038 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6039 gen_helper_fpop(cpu_env);
6040 break;
6041 case 0x3c: /* df/4 */
6042 switch(rm) {
6043 case 0:
6044 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6045 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
6046 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
6047 break;
6048 default:
6049 goto unknown_op;
6051 break;
6052 case 0x3d: /* fucomip */
6053 if (!(s->cpuid_features & CPUID_CMOV)) {
6054 goto illegal_op;
6056 gen_update_cc_op(s);
6057 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6058 gen_helper_fucomi_ST0_FT0(cpu_env);
6059 gen_helper_fpop(cpu_env);
6060 set_cc_op(s, CC_OP_EFLAGS);
6061 break;
6062 case 0x3e: /* fcomip */
6063 if (!(s->cpuid_features & CPUID_CMOV)) {
6064 goto illegal_op;
6066 gen_update_cc_op(s);
6067 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6068 gen_helper_fcomi_ST0_FT0(cpu_env);
6069 gen_helper_fpop(cpu_env);
6070 set_cc_op(s, CC_OP_EFLAGS);
6071 break;
6072 case 0x10 ... 0x13: /* fcmovxx */
6073 case 0x18 ... 0x1b:
6075 int op1;
6076 TCGLabel *l1;
6077 static const uint8_t fcmov_cc[8] = {
6078 (JCC_B << 1),
6079 (JCC_Z << 1),
6080 (JCC_BE << 1),
6081 (JCC_P << 1),
6084 if (!(s->cpuid_features & CPUID_CMOV)) {
6085 goto illegal_op;
6087 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6088 l1 = gen_new_label();
6089 gen_jcc1_noeob(s, op1, l1);
6090 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6091 gen_set_label(l1);
6093 break;
6094 default:
6095 goto unknown_op;
6098 break;
6099 /************************/
6100 /* string ops */
6102 case 0xa4: /* movsS */
6103 case 0xa5:
6104 ot = mo_b_d(b, dflag);
6105 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6106 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6107 } else {
6108 gen_movs(s, ot);
6110 break;
6112 case 0xaa: /* stosS */
6113 case 0xab:
6114 ot = mo_b_d(b, dflag);
6115 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6116 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6117 } else {
6118 gen_stos(s, ot);
6120 break;
6121 case 0xac: /* lodsS */
6122 case 0xad:
6123 ot = mo_b_d(b, dflag);
6124 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6125 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6126 } else {
6127 gen_lods(s, ot);
6129 break;
6130 case 0xae: /* scasS */
6131 case 0xaf:
6132 ot = mo_b_d(b, dflag);
6133 if (prefixes & PREFIX_REPNZ) {
6134 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6135 } else if (prefixes & PREFIX_REPZ) {
6136 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6137 } else {
6138 gen_scas(s, ot);
6140 break;
6142 case 0xa6: /* cmpsS */
6143 case 0xa7:
6144 ot = mo_b_d(b, dflag);
6145 if (prefixes & PREFIX_REPNZ) {
6146 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6147 } else if (prefixes & PREFIX_REPZ) {
6148 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6149 } else {
6150 gen_cmps(s, ot);
6152 break;
6153 case 0x6c: /* insS */
6154 case 0x6d:
6155 ot = mo_b_d32(b, dflag);
6156 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6157 gen_check_io(s, ot, pc_start - s->cs_base,
6158 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6159 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6160 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6161 } else {
6162 gen_ins(s, ot);
6163 if (s->tb->cflags & CF_USE_ICOUNT) {
6164 gen_jmp(s, s->pc - s->cs_base);
6167 break;
6168 case 0x6e: /* outsS */
6169 case 0x6f:
6170 ot = mo_b_d32(b, dflag);
6171 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6172 gen_check_io(s, ot, pc_start - s->cs_base,
6173 svm_is_rep(prefixes) | 4);
6174 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6175 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6176 } else {
6177 gen_outs(s, ot);
6178 if (s->tb->cflags & CF_USE_ICOUNT) {
6179 gen_jmp(s, s->pc - s->cs_base);
6182 break;
6184 /************************/
6185 /* port I/O */
6187 case 0xe4:
6188 case 0xe5:
6189 ot = mo_b_d32(b, dflag);
6190 val = cpu_ldub_code(env, s->pc++);
6191 tcg_gen_movi_tl(cpu_T0, val);
6192 gen_check_io(s, ot, pc_start - s->cs_base,
6193 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6194 if (s->tb->cflags & CF_USE_ICOUNT) {
6195 gen_io_start();
6197 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6198 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6199 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6200 gen_bpt_io(s, cpu_tmp2_i32, ot);
6201 if (s->tb->cflags & CF_USE_ICOUNT) {
6202 gen_io_end();
6203 gen_jmp(s, s->pc - s->cs_base);
6205 break;
6206 case 0xe6:
6207 case 0xe7:
6208 ot = mo_b_d32(b, dflag);
6209 val = cpu_ldub_code(env, s->pc++);
6210 tcg_gen_movi_tl(cpu_T0, val);
6211 gen_check_io(s, ot, pc_start - s->cs_base,
6212 svm_is_rep(prefixes));
6213 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6215 if (s->tb->cflags & CF_USE_ICOUNT) {
6216 gen_io_start();
6218 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6219 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6220 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6221 gen_bpt_io(s, cpu_tmp2_i32, ot);
6222 if (s->tb->cflags & CF_USE_ICOUNT) {
6223 gen_io_end();
6224 gen_jmp(s, s->pc - s->cs_base);
6226 break;
6227 case 0xec:
6228 case 0xed:
6229 ot = mo_b_d32(b, dflag);
6230 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6231 gen_check_io(s, ot, pc_start - s->cs_base,
6232 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6233 if (s->tb->cflags & CF_USE_ICOUNT) {
6234 gen_io_start();
6236 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6237 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6238 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6239 gen_bpt_io(s, cpu_tmp2_i32, ot);
6240 if (s->tb->cflags & CF_USE_ICOUNT) {
6241 gen_io_end();
6242 gen_jmp(s, s->pc - s->cs_base);
6244 break;
6245 case 0xee:
6246 case 0xef:
6247 ot = mo_b_d32(b, dflag);
6248 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6249 gen_check_io(s, ot, pc_start - s->cs_base,
6250 svm_is_rep(prefixes));
6251 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6253 if (s->tb->cflags & CF_USE_ICOUNT) {
6254 gen_io_start();
6256 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6257 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6258 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6259 gen_bpt_io(s, cpu_tmp2_i32, ot);
6260 if (s->tb->cflags & CF_USE_ICOUNT) {
6261 gen_io_end();
6262 gen_jmp(s, s->pc - s->cs_base);
6264 break;
6266 /************************/
6267 /* control */
6268 case 0xc2: /* ret im */
6269 val = cpu_ldsw_code(env, s->pc);
6270 s->pc += 2;
6271 ot = gen_pop_T0(s);
6272 gen_stack_update(s, val + (1 << ot));
6273 /* Note that gen_pop_T0 uses a zero-extending load. */
6274 gen_op_jmp_v(cpu_T0);
6275 gen_bnd_jmp(s);
6276 gen_eob(s);
6277 break;
6278 case 0xc3: /* ret */
6279 ot = gen_pop_T0(s);
6280 gen_pop_update(s, ot);
6281 /* Note that gen_pop_T0 uses a zero-extending load. */
6282 gen_op_jmp_v(cpu_T0);
6283 gen_bnd_jmp(s);
6284 gen_eob(s);
6285 break;
6286 case 0xca: /* lret im */
6287 val = cpu_ldsw_code(env, s->pc);
6288 s->pc += 2;
6289 do_lret:
6290 if (s->pe && !s->vm86) {
6291 gen_update_cc_op(s);
6292 gen_jmp_im(pc_start - s->cs_base);
6293 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6294 tcg_const_i32(val));
6295 } else {
6296 gen_stack_A0(s);
6297 /* pop offset */
6298 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6299 /* NOTE: keeping EIP updated is not a problem in case of
6300 exception */
6301 gen_op_jmp_v(cpu_T0);
6302 /* pop selector */
6303 gen_add_A0_im(s, 1 << dflag);
6304 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6305 gen_op_movl_seg_T0_vm(R_CS);
6306 /* add stack offset */
6307 gen_stack_update(s, val + (2 << dflag));
6309 gen_eob(s);
6310 break;
6311 case 0xcb: /* lret */
6312 val = 0;
6313 goto do_lret;
6314 case 0xcf: /* iret */
6315 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6316 if (!s->pe) {
6317 /* real mode */
6318 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6319 set_cc_op(s, CC_OP_EFLAGS);
6320 } else if (s->vm86) {
6321 if (s->iopl != 3) {
6322 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6323 } else {
6324 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6325 set_cc_op(s, CC_OP_EFLAGS);
6327 } else {
6328 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6329 tcg_const_i32(s->pc - s->cs_base));
6330 set_cc_op(s, CC_OP_EFLAGS);
6332 gen_eob(s);
6333 break;
6334 case 0xe8: /* call im */
6336 if (dflag != MO_16) {
6337 tval = (int32_t)insn_get(env, s, MO_32);
6338 } else {
6339 tval = (int16_t)insn_get(env, s, MO_16);
6341 next_eip = s->pc - s->cs_base;
6342 tval += next_eip;
6343 if (dflag == MO_16) {
6344 tval &= 0xffff;
6345 } else if (!CODE64(s)) {
6346 tval &= 0xffffffff;
6348 tcg_gen_movi_tl(cpu_T0, next_eip);
6349 gen_push_v(s, cpu_T0);
6350 gen_bnd_jmp(s);
6351 gen_jmp(s, tval);
6353 break;
6354 case 0x9a: /* lcall im */
6356 unsigned int selector, offset;
6358 if (CODE64(s))
6359 goto illegal_op;
6360 ot = dflag;
6361 offset = insn_get(env, s, ot);
6362 selector = insn_get(env, s, MO_16);
6364 tcg_gen_movi_tl(cpu_T0, selector);
6365 tcg_gen_movi_tl(cpu_T1, offset);
6367 goto do_lcall;
6368 case 0xe9: /* jmp im */
6369 if (dflag != MO_16) {
6370 tval = (int32_t)insn_get(env, s, MO_32);
6371 } else {
6372 tval = (int16_t)insn_get(env, s, MO_16);
6374 tval += s->pc - s->cs_base;
6375 if (dflag == MO_16) {
6376 tval &= 0xffff;
6377 } else if (!CODE64(s)) {
6378 tval &= 0xffffffff;
6380 gen_bnd_jmp(s);
6381 gen_jmp(s, tval);
6382 break;
6383 case 0xea: /* ljmp im */
6385 unsigned int selector, offset;
6387 if (CODE64(s))
6388 goto illegal_op;
6389 ot = dflag;
6390 offset = insn_get(env, s, ot);
6391 selector = insn_get(env, s, MO_16);
6393 tcg_gen_movi_tl(cpu_T0, selector);
6394 tcg_gen_movi_tl(cpu_T1, offset);
6396 goto do_ljmp;
6397 case 0xeb: /* jmp Jb */
6398 tval = (int8_t)insn_get(env, s, MO_8);
6399 tval += s->pc - s->cs_base;
6400 if (dflag == MO_16) {
6401 tval &= 0xffff;
6403 gen_jmp(s, tval);
6404 break;
6405 case 0x70 ... 0x7f: /* jcc Jb */
6406 tval = (int8_t)insn_get(env, s, MO_8);
6407 goto do_jcc;
6408 case 0x180 ... 0x18f: /* jcc Jv */
6409 if (dflag != MO_16) {
6410 tval = (int32_t)insn_get(env, s, MO_32);
6411 } else {
6412 tval = (int16_t)insn_get(env, s, MO_16);
6414 do_jcc:
6415 next_eip = s->pc - s->cs_base;
6416 tval += next_eip;
6417 if (dflag == MO_16) {
6418 tval &= 0xffff;
6420 gen_bnd_jmp(s);
6421 gen_jcc(s, b, tval, next_eip);
6422 break;
6424 case 0x190 ... 0x19f: /* setcc Gv */
6425 modrm = cpu_ldub_code(env, s->pc++);
6426 gen_setcc1(s, b, cpu_T0);
6427 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6428 break;
6429 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6430 if (!(s->cpuid_features & CPUID_CMOV)) {
6431 goto illegal_op;
6433 ot = dflag;
6434 modrm = cpu_ldub_code(env, s->pc++);
6435 reg = ((modrm >> 3) & 7) | rex_r;
6436 gen_cmovcc1(env, s, ot, b, modrm, reg);
6437 break;
6439 /************************/
6440 /* flags */
6441 case 0x9c: /* pushf */
6442 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6443 if (s->vm86 && s->iopl != 3) {
6444 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6445 } else {
6446 gen_update_cc_op(s);
6447 gen_helper_read_eflags(cpu_T0, cpu_env);
6448 gen_push_v(s, cpu_T0);
6450 break;
6451 case 0x9d: /* popf */
6452 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6453 if (s->vm86 && s->iopl != 3) {
6454 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6455 } else {
6456 ot = gen_pop_T0(s);
6457 if (s->cpl == 0) {
6458 if (dflag != MO_16) {
6459 gen_helper_write_eflags(cpu_env, cpu_T0,
6460 tcg_const_i32((TF_MASK | AC_MASK |
6461 ID_MASK | NT_MASK |
6462 IF_MASK |
6463 IOPL_MASK)));
6464 } else {
6465 gen_helper_write_eflags(cpu_env, cpu_T0,
6466 tcg_const_i32((TF_MASK | AC_MASK |
6467 ID_MASK | NT_MASK |
6468 IF_MASK | IOPL_MASK)
6469 & 0xffff));
6471 } else {
6472 if (s->cpl <= s->iopl) {
6473 if (dflag != MO_16) {
6474 gen_helper_write_eflags(cpu_env, cpu_T0,
6475 tcg_const_i32((TF_MASK |
6476 AC_MASK |
6477 ID_MASK |
6478 NT_MASK |
6479 IF_MASK)));
6480 } else {
6481 gen_helper_write_eflags(cpu_env, cpu_T0,
6482 tcg_const_i32((TF_MASK |
6483 AC_MASK |
6484 ID_MASK |
6485 NT_MASK |
6486 IF_MASK)
6487 & 0xffff));
6489 } else {
6490 if (dflag != MO_16) {
6491 gen_helper_write_eflags(cpu_env, cpu_T0,
6492 tcg_const_i32((TF_MASK | AC_MASK |
6493 ID_MASK | NT_MASK)));
6494 } else {
6495 gen_helper_write_eflags(cpu_env, cpu_T0,
6496 tcg_const_i32((TF_MASK | AC_MASK |
6497 ID_MASK | NT_MASK)
6498 & 0xffff));
6502 gen_pop_update(s, ot);
6503 set_cc_op(s, CC_OP_EFLAGS);
6504 /* abort translation because TF/AC flag may change */
6505 gen_jmp_im(s->pc - s->cs_base);
6506 gen_eob(s);
6508 break;
6509 case 0x9e: /* sahf */
6510 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6511 goto illegal_op;
6512 gen_op_mov_v_reg(MO_8, cpu_T0, R_AH);
6513 gen_compute_eflags(s);
6514 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6515 tcg_gen_andi_tl(cpu_T0, cpu_T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6516 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T0);
6517 break;
6518 case 0x9f: /* lahf */
6519 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6520 goto illegal_op;
6521 gen_compute_eflags(s);
6522 /* Note: gen_compute_eflags() only gives the condition codes */
6523 tcg_gen_ori_tl(cpu_T0, cpu_cc_src, 0x02);
6524 gen_op_mov_reg_v(MO_8, R_AH, cpu_T0);
6525 break;
6526 case 0xf5: /* cmc */
6527 gen_compute_eflags(s);
6528 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6529 break;
6530 case 0xf8: /* clc */
6531 gen_compute_eflags(s);
6532 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6533 break;
6534 case 0xf9: /* stc */
6535 gen_compute_eflags(s);
6536 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6537 break;
6538 case 0xfc: /* cld */
6539 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6540 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6541 break;
6542 case 0xfd: /* std */
6543 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6544 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6545 break;
6547 /************************/
6548 /* bit operations */
6549 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6550 ot = dflag;
6551 modrm = cpu_ldub_code(env, s->pc++);
6552 op = (modrm >> 3) & 7;
6553 mod = (modrm >> 6) & 3;
6554 rm = (modrm & 7) | REX_B(s);
6555 if (mod != 3) {
6556 s->rip_offset = 1;
6557 gen_lea_modrm(env, s, modrm);
6558 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6559 } else {
6560 gen_op_mov_v_reg(ot, cpu_T0, rm);
6562 /* load shift */
6563 val = cpu_ldub_code(env, s->pc++);
6564 tcg_gen_movi_tl(cpu_T1, val);
6565 if (op < 4)
6566 goto unknown_op;
6567 op -= 4;
6568 goto bt_op;
6569 case 0x1a3: /* bt Gv, Ev */
6570 op = 0;
6571 goto do_btx;
6572 case 0x1ab: /* bts */
6573 op = 1;
6574 goto do_btx;
6575 case 0x1b3: /* btr */
6576 op = 2;
6577 goto do_btx;
6578 case 0x1bb: /* btc */
6579 op = 3;
6580 do_btx:
6581 ot = dflag;
6582 modrm = cpu_ldub_code(env, s->pc++);
6583 reg = ((modrm >> 3) & 7) | rex_r;
6584 mod = (modrm >> 6) & 3;
6585 rm = (modrm & 7) | REX_B(s);
6586 gen_op_mov_v_reg(MO_32, cpu_T1, reg);
6587 if (mod != 3) {
6588 gen_lea_modrm(env, s, modrm);
6589 /* specific case: we need to add a displacement */
6590 gen_exts(ot, cpu_T1);
6591 tcg_gen_sari_tl(cpu_tmp0, cpu_T1, 3 + ot);
6592 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6593 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
6594 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6595 } else {
6596 gen_op_mov_v_reg(ot, cpu_T0, rm);
6598 bt_op:
6599 tcg_gen_andi_tl(cpu_T1, cpu_T1, (1 << (3 + ot)) - 1);
6600 tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1);
6601 switch(op) {
6602 case 0:
6603 break;
6604 case 1:
6605 tcg_gen_movi_tl(cpu_tmp0, 1);
6606 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6607 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
6608 break;
6609 case 2:
6610 tcg_gen_movi_tl(cpu_tmp0, 1);
6611 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6612 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_tmp0);
6613 break;
6614 default:
6615 case 3:
6616 tcg_gen_movi_tl(cpu_tmp0, 1);
6617 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6618 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_tmp0);
6619 break;
6621 if (op != 0) {
6622 if (mod != 3) {
6623 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
6624 } else {
6625 gen_op_mov_reg_v(ot, rm, cpu_T0);
6629 /* Delay all CC updates until after the store above. Note that
6630 C is the result of the test, Z is unchanged, and the others
6631 are all undefined. */
6632 switch (s->cc_op) {
6633 case CC_OP_MULB ... CC_OP_MULQ:
6634 case CC_OP_ADDB ... CC_OP_ADDQ:
6635 case CC_OP_ADCB ... CC_OP_ADCQ:
6636 case CC_OP_SUBB ... CC_OP_SUBQ:
6637 case CC_OP_SBBB ... CC_OP_SBBQ:
6638 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6639 case CC_OP_INCB ... CC_OP_INCQ:
6640 case CC_OP_DECB ... CC_OP_DECQ:
6641 case CC_OP_SHLB ... CC_OP_SHLQ:
6642 case CC_OP_SARB ... CC_OP_SARQ:
6643 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6644 /* Z was going to be computed from the non-zero status of CC_DST.
6645 We can get that same Z value (and the new C value) by leaving
6646 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6647 same width. */
6648 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6649 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6650 break;
6651 default:
6652 /* Otherwise, generate EFLAGS and replace the C bit. */
6653 gen_compute_eflags(s);
6654 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6655 ctz32(CC_C), 1);
6656 break;
6658 break;
6659 case 0x1bc: /* bsf / tzcnt */
6660 case 0x1bd: /* bsr / lzcnt */
6661 ot = dflag;
6662 modrm = cpu_ldub_code(env, s->pc++);
6663 reg = ((modrm >> 3) & 7) | rex_r;
6664 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6665 gen_extu(ot, cpu_T0);
6667 /* Note that lzcnt and tzcnt are in different extensions. */
6668 if ((prefixes & PREFIX_REPZ)
6669 && (b & 1
6670 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6671 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6672 int size = 8 << ot;
6673 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
6674 if (b & 1) {
6675 /* For lzcnt, reduce the target_ulong result by the
6676 number of zeros that we expect to find at the top. */
6677 gen_helper_clz(cpu_T0, cpu_T0);
6678 tcg_gen_subi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - size);
6679 } else {
6680 /* For tzcnt, a zero input must return the operand size:
6681 force all bits outside the operand size to 1. */
6682 target_ulong mask = (target_ulong)-2 << (size - 1);
6683 tcg_gen_ori_tl(cpu_T0, cpu_T0, mask);
6684 gen_helper_ctz(cpu_T0, cpu_T0);
6686 /* For lzcnt/tzcnt, C and Z bits are defined and are
6687 related to the result. */
6688 gen_op_update1_cc();
6689 set_cc_op(s, CC_OP_BMILGB + ot);
6690 } else {
6691 /* For bsr/bsf, only the Z bit is defined and it is related
6692 to the input and not the result. */
6693 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
6694 set_cc_op(s, CC_OP_LOGICB + ot);
6695 if (b & 1) {
6696 /* For bsr, return the bit index of the first 1 bit,
6697 not the count of leading zeros. */
6698 gen_helper_clz(cpu_T0, cpu_T0);
6699 tcg_gen_xori_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - 1);
6700 } else {
6701 gen_helper_ctz(cpu_T0, cpu_T0);
6703 /* ??? The manual says that the output is undefined when the
6704 input is zero, but real hardware leaves it unchanged, and
6705 real programs appear to depend on that. */
6706 tcg_gen_movi_tl(cpu_tmp0, 0);
6707 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T0, cpu_cc_dst, cpu_tmp0,
6708 cpu_regs[reg], cpu_T0);
6710 gen_op_mov_reg_v(ot, reg, cpu_T0);
6711 break;
6712 /************************/
6713 /* bcd */
6714 case 0x27: /* daa */
6715 if (CODE64(s))
6716 goto illegal_op;
6717 gen_update_cc_op(s);
6718 gen_helper_daa(cpu_env);
6719 set_cc_op(s, CC_OP_EFLAGS);
6720 break;
6721 case 0x2f: /* das */
6722 if (CODE64(s))
6723 goto illegal_op;
6724 gen_update_cc_op(s);
6725 gen_helper_das(cpu_env);
6726 set_cc_op(s, CC_OP_EFLAGS);
6727 break;
6728 case 0x37: /* aaa */
6729 if (CODE64(s))
6730 goto illegal_op;
6731 gen_update_cc_op(s);
6732 gen_helper_aaa(cpu_env);
6733 set_cc_op(s, CC_OP_EFLAGS);
6734 break;
6735 case 0x3f: /* aas */
6736 if (CODE64(s))
6737 goto illegal_op;
6738 gen_update_cc_op(s);
6739 gen_helper_aas(cpu_env);
6740 set_cc_op(s, CC_OP_EFLAGS);
6741 break;
6742 case 0xd4: /* aam */
6743 if (CODE64(s))
6744 goto illegal_op;
6745 val = cpu_ldub_code(env, s->pc++);
6746 if (val == 0) {
6747 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6748 } else {
6749 gen_helper_aam(cpu_env, tcg_const_i32(val));
6750 set_cc_op(s, CC_OP_LOGICB);
6752 break;
6753 case 0xd5: /* aad */
6754 if (CODE64(s))
6755 goto illegal_op;
6756 val = cpu_ldub_code(env, s->pc++);
6757 gen_helper_aad(cpu_env, tcg_const_i32(val));
6758 set_cc_op(s, CC_OP_LOGICB);
6759 break;
6760 /************************/
6761 /* misc */
6762 case 0x90: /* nop */
6763 /* XXX: correct lock test for all insn */
6764 if (prefixes & PREFIX_LOCK) {
6765 goto illegal_op;
6767 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6768 if (REX_B(s)) {
6769 goto do_xchg_reg_eax;
6771 if (prefixes & PREFIX_REPZ) {
6772 gen_update_cc_op(s);
6773 gen_jmp_im(pc_start - s->cs_base);
6774 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6775 s->is_jmp = DISAS_TB_JUMP;
6777 break;
6778 case 0x9b: /* fwait */
6779 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6780 (HF_MP_MASK | HF_TS_MASK)) {
6781 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6782 } else {
6783 gen_helper_fwait(cpu_env);
6785 break;
6786 case 0xcc: /* int3 */
6787 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6788 break;
6789 case 0xcd: /* int N */
6790 val = cpu_ldub_code(env, s->pc++);
6791 if (s->vm86 && s->iopl != 3) {
6792 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6793 } else {
6794 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6796 break;
6797 case 0xce: /* into */
6798 if (CODE64(s))
6799 goto illegal_op;
6800 gen_update_cc_op(s);
6801 gen_jmp_im(pc_start - s->cs_base);
6802 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6803 break;
6804 #ifdef WANT_ICEBP
6805 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6806 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6807 #if 1
6808 gen_debug(s, pc_start - s->cs_base);
6809 #else
6810 /* start debug */
6811 tb_flush(CPU(x86_env_get_cpu(env)));
6812 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6813 #endif
6814 break;
6815 #endif
6816 case 0xfa: /* cli */
6817 if (!s->vm86) {
6818 if (s->cpl <= s->iopl) {
6819 gen_helper_cli(cpu_env);
6820 } else {
6821 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6823 } else {
6824 if (s->iopl == 3) {
6825 gen_helper_cli(cpu_env);
6826 } else {
6827 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6830 break;
6831 case 0xfb: /* sti */
6832 if (s->vm86 ? s->iopl == 3 : s->cpl <= s->iopl) {
6833 gen_helper_sti(cpu_env);
6834 /* interruptions are enabled only the first insn after sti */
6835 gen_jmp_im(s->pc - s->cs_base);
6836 gen_eob_inhibit_irq(s, true);
6837 } else {
6838 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6840 break;
6841 case 0x62: /* bound */
6842 if (CODE64(s))
6843 goto illegal_op;
6844 ot = dflag;
6845 modrm = cpu_ldub_code(env, s->pc++);
6846 reg = (modrm >> 3) & 7;
6847 mod = (modrm >> 6) & 3;
6848 if (mod == 3)
6849 goto illegal_op;
6850 gen_op_mov_v_reg(ot, cpu_T0, reg);
6851 gen_lea_modrm(env, s, modrm);
6852 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6853 if (ot == MO_16) {
6854 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
6855 } else {
6856 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
6858 break;
6859 case 0x1c8 ... 0x1cf: /* bswap reg */
6860 reg = (b & 7) | REX_B(s);
6861 #ifdef TARGET_X86_64
6862 if (dflag == MO_64) {
6863 gen_op_mov_v_reg(MO_64, cpu_T0, reg);
6864 tcg_gen_bswap64_i64(cpu_T0, cpu_T0);
6865 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
6866 } else
6867 #endif
6869 gen_op_mov_v_reg(MO_32, cpu_T0, reg);
6870 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
6871 tcg_gen_bswap32_tl(cpu_T0, cpu_T0);
6872 gen_op_mov_reg_v(MO_32, reg, cpu_T0);
6874 break;
6875 case 0xd6: /* salc */
6876 if (CODE64(s))
6877 goto illegal_op;
6878 gen_compute_eflags_c(s, cpu_T0);
6879 tcg_gen_neg_tl(cpu_T0, cpu_T0);
6880 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
6881 break;
6882 case 0xe0: /* loopnz */
6883 case 0xe1: /* loopz */
6884 case 0xe2: /* loop */
6885 case 0xe3: /* jecxz */
6887 TCGLabel *l1, *l2, *l3;
6889 tval = (int8_t)insn_get(env, s, MO_8);
6890 next_eip = s->pc - s->cs_base;
6891 tval += next_eip;
6892 if (dflag == MO_16) {
6893 tval &= 0xffff;
6896 l1 = gen_new_label();
6897 l2 = gen_new_label();
6898 l3 = gen_new_label();
6899 b &= 3;
6900 switch(b) {
6901 case 0: /* loopnz */
6902 case 1: /* loopz */
6903 gen_op_add_reg_im(s->aflag, R_ECX, -1);
6904 gen_op_jz_ecx(s->aflag, l3);
6905 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
6906 break;
6907 case 2: /* loop */
6908 gen_op_add_reg_im(s->aflag, R_ECX, -1);
6909 gen_op_jnz_ecx(s->aflag, l1);
6910 break;
6911 default:
6912 case 3: /* jcxz */
6913 gen_op_jz_ecx(s->aflag, l1);
6914 break;
6917 gen_set_label(l3);
6918 gen_jmp_im(next_eip);
6919 tcg_gen_br(l2);
6921 gen_set_label(l1);
6922 gen_jmp_im(tval);
6923 gen_set_label(l2);
6924 gen_eob(s);
6926 break;
6927 case 0x130: /* wrmsr */
6928 case 0x132: /* rdmsr */
6929 if (s->cpl != 0) {
6930 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6931 } else {
6932 gen_update_cc_op(s);
6933 gen_jmp_im(pc_start - s->cs_base);
6934 if (b & 2) {
6935 gen_helper_rdmsr(cpu_env);
6936 } else {
6937 gen_helper_wrmsr(cpu_env);
6940 break;
6941 case 0x131: /* rdtsc */
6942 gen_update_cc_op(s);
6943 gen_jmp_im(pc_start - s->cs_base);
6944 if (s->tb->cflags & CF_USE_ICOUNT) {
6945 gen_io_start();
6947 gen_helper_rdtsc(cpu_env);
6948 if (s->tb->cflags & CF_USE_ICOUNT) {
6949 gen_io_end();
6950 gen_jmp(s, s->pc - s->cs_base);
6952 break;
6953 case 0x133: /* rdpmc */
6954 gen_update_cc_op(s);
6955 gen_jmp_im(pc_start - s->cs_base);
6956 gen_helper_rdpmc(cpu_env);
6957 break;
6958 case 0x134: /* sysenter */
6959 /* For Intel SYSENTER is valid on 64-bit */
6960 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
6961 goto illegal_op;
6962 if (!s->pe) {
6963 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6964 } else {
6965 gen_helper_sysenter(cpu_env);
6966 gen_eob(s);
6968 break;
6969 case 0x135: /* sysexit */
6970 /* For Intel SYSEXIT is valid on 64-bit */
6971 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
6972 goto illegal_op;
6973 if (!s->pe) {
6974 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6975 } else {
6976 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
6977 gen_eob(s);
6979 break;
6980 #ifdef TARGET_X86_64
6981 case 0x105: /* syscall */
6982 /* XXX: is it usable in real mode ? */
6983 gen_update_cc_op(s);
6984 gen_jmp_im(pc_start - s->cs_base);
6985 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
6986 gen_eob(s);
6987 break;
6988 case 0x107: /* sysret */
6989 if (!s->pe) {
6990 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6991 } else {
6992 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
6993 /* condition codes are modified only in long mode */
6994 if (s->lma) {
6995 set_cc_op(s, CC_OP_EFLAGS);
6997 gen_eob(s);
6999 break;
7000 #endif
7001 case 0x1a2: /* cpuid */
7002 gen_update_cc_op(s);
7003 gen_jmp_im(pc_start - s->cs_base);
7004 gen_helper_cpuid(cpu_env);
7005 break;
7006 case 0xf4: /* hlt */
7007 if (s->cpl != 0) {
7008 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7009 } else {
7010 gen_update_cc_op(s);
7011 gen_jmp_im(pc_start - s->cs_base);
7012 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7013 s->is_jmp = DISAS_TB_JUMP;
7015 break;
7016 case 0x100:
7017 modrm = cpu_ldub_code(env, s->pc++);
7018 mod = (modrm >> 6) & 3;
7019 op = (modrm >> 3) & 7;
7020 switch(op) {
7021 case 0: /* sldt */
7022 if (!s->pe || s->vm86)
7023 goto illegal_op;
7024 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7025 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
7026 offsetof(CPUX86State, ldt.selector));
7027 ot = mod == 3 ? dflag : MO_16;
7028 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7029 break;
7030 case 2: /* lldt */
7031 if (!s->pe || s->vm86)
7032 goto illegal_op;
7033 if (s->cpl != 0) {
7034 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7035 } else {
7036 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7037 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7038 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
7039 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7041 break;
7042 case 1: /* str */
7043 if (!s->pe || s->vm86)
7044 goto illegal_op;
7045 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7046 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
7047 offsetof(CPUX86State, tr.selector));
7048 ot = mod == 3 ? dflag : MO_16;
7049 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7050 break;
7051 case 3: /* ltr */
7052 if (!s->pe || s->vm86)
7053 goto illegal_op;
7054 if (s->cpl != 0) {
7055 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7056 } else {
7057 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7058 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7059 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
7060 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7062 break;
7063 case 4: /* verr */
7064 case 5: /* verw */
7065 if (!s->pe || s->vm86)
7066 goto illegal_op;
7067 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7068 gen_update_cc_op(s);
7069 if (op == 4) {
7070 gen_helper_verr(cpu_env, cpu_T0);
7071 } else {
7072 gen_helper_verw(cpu_env, cpu_T0);
7074 set_cc_op(s, CC_OP_EFLAGS);
7075 break;
7076 default:
7077 goto unknown_op;
7079 break;
7081 case 0x101:
7082 modrm = cpu_ldub_code(env, s->pc++);
7083 switch (modrm) {
7084 CASE_MODRM_MEM_OP(0): /* sgdt */
7085 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7086 gen_lea_modrm(env, s, modrm);
7087 tcg_gen_ld32u_tl(cpu_T0,
7088 cpu_env, offsetof(CPUX86State, gdt.limit));
7089 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7090 gen_add_A0_im(s, 2);
7091 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7092 if (dflag == MO_16) {
7093 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7095 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7096 break;
7098 case 0xc8: /* monitor */
7099 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7100 goto illegal_op;
7102 gen_update_cc_op(s);
7103 gen_jmp_im(pc_start - s->cs_base);
7104 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7105 gen_extu(s->aflag, cpu_A0);
7106 gen_add_A0_ds_seg(s);
7107 gen_helper_monitor(cpu_env, cpu_A0);
7108 break;
7110 case 0xc9: /* mwait */
7111 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7112 goto illegal_op;
7114 gen_update_cc_op(s);
7115 gen_jmp_im(pc_start - s->cs_base);
7116 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7117 gen_eob(s);
7118 break;
7120 case 0xca: /* clac */
7121 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7122 || s->cpl != 0) {
7123 goto illegal_op;
7125 gen_helper_clac(cpu_env);
7126 gen_jmp_im(s->pc - s->cs_base);
7127 gen_eob(s);
7128 break;
7130 case 0xcb: /* stac */
7131 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7132 || s->cpl != 0) {
7133 goto illegal_op;
7135 gen_helper_stac(cpu_env);
7136 gen_jmp_im(s->pc - s->cs_base);
7137 gen_eob(s);
7138 break;
7140 CASE_MODRM_MEM_OP(1): /* sidt */
7141 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7142 gen_lea_modrm(env, s, modrm);
7143 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.limit));
7144 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7145 gen_add_A0_im(s, 2);
7146 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base));
7147 if (dflag == MO_16) {
7148 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7150 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7151 break;
7153 case 0xd0: /* xgetbv */
7154 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7155 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7156 | PREFIX_REPZ | PREFIX_REPNZ))) {
7157 goto illegal_op;
7159 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7160 gen_helper_xgetbv(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7161 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7162 break;
7164 case 0xd1: /* xsetbv */
7165 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7166 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7167 | PREFIX_REPZ | PREFIX_REPNZ))) {
7168 goto illegal_op;
7170 if (s->cpl != 0) {
7171 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7172 break;
7174 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7175 cpu_regs[R_EDX]);
7176 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7177 gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7178 /* End TB because translation flags may change. */
7179 gen_jmp_im(s->pc - s->cs_base);
7180 gen_eob(s);
7181 break;
7183 case 0xd8: /* VMRUN */
7184 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7185 goto illegal_op;
7187 if (s->cpl != 0) {
7188 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7189 break;
7191 gen_update_cc_op(s);
7192 gen_jmp_im(pc_start - s->cs_base);
7193 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7194 tcg_const_i32(s->pc - pc_start));
7195 tcg_gen_exit_tb(0);
7196 s->is_jmp = DISAS_TB_JUMP;
7197 break;
7199 case 0xd9: /* VMMCALL */
7200 if (!(s->flags & HF_SVME_MASK)) {
7201 goto illegal_op;
7203 gen_update_cc_op(s);
7204 gen_jmp_im(pc_start - s->cs_base);
7205 gen_helper_vmmcall(cpu_env);
7206 break;
7208 case 0xda: /* VMLOAD */
7209 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7210 goto illegal_op;
7212 if (s->cpl != 0) {
7213 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7214 break;
7216 gen_update_cc_op(s);
7217 gen_jmp_im(pc_start - s->cs_base);
7218 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7219 break;
7221 case 0xdb: /* VMSAVE */
7222 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7223 goto illegal_op;
7225 if (s->cpl != 0) {
7226 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7227 break;
7229 gen_update_cc_op(s);
7230 gen_jmp_im(pc_start - s->cs_base);
7231 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7232 break;
7234 case 0xdc: /* STGI */
7235 if ((!(s->flags & HF_SVME_MASK)
7236 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7237 || !s->pe) {
7238 goto illegal_op;
7240 if (s->cpl != 0) {
7241 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7242 break;
7244 gen_update_cc_op(s);
7245 gen_jmp_im(pc_start - s->cs_base);
7246 gen_helper_stgi(cpu_env);
7247 break;
7249 case 0xdd: /* CLGI */
7250 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7251 goto illegal_op;
7253 if (s->cpl != 0) {
7254 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7255 break;
7257 gen_update_cc_op(s);
7258 gen_jmp_im(pc_start - s->cs_base);
7259 gen_helper_clgi(cpu_env);
7260 break;
7262 case 0xde: /* SKINIT */
7263 if ((!(s->flags & HF_SVME_MASK)
7264 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7265 || !s->pe) {
7266 goto illegal_op;
7268 gen_update_cc_op(s);
7269 gen_jmp_im(pc_start - s->cs_base);
7270 gen_helper_skinit(cpu_env);
7271 break;
7273 case 0xdf: /* INVLPGA */
7274 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7275 goto illegal_op;
7277 if (s->cpl != 0) {
7278 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7279 break;
7281 gen_update_cc_op(s);
7282 gen_jmp_im(pc_start - s->cs_base);
7283 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7284 break;
7286 CASE_MODRM_MEM_OP(2): /* lgdt */
7287 if (s->cpl != 0) {
7288 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7289 break;
7291 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE);
7292 gen_lea_modrm(env, s, modrm);
7293 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7294 gen_add_A0_im(s, 2);
7295 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7296 if (dflag == MO_16) {
7297 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7299 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7300 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7301 break;
7303 CASE_MODRM_MEM_OP(3): /* lidt */
7304 if (s->cpl != 0) {
7305 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7306 break;
7308 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7309 gen_lea_modrm(env, s, modrm);
7310 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7311 gen_add_A0_im(s, 2);
7312 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7313 if (dflag == MO_16) {
7314 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7316 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base));
7317 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, idt.limit));
7318 break;
7320 CASE_MODRM_OP(4): /* smsw */
7321 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7322 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, cr[0]));
7323 if (CODE64(s)) {
7324 mod = (modrm >> 6) & 3;
7325 ot = (mod != 3 ? MO_16 : s->dflag);
7326 } else {
7327 ot = MO_16;
7329 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7330 break;
7331 case 0xee: /* rdpkru */
7332 if (prefixes & PREFIX_LOCK) {
7333 goto illegal_op;
7335 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7336 gen_helper_rdpkru(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7337 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7338 break;
7339 case 0xef: /* wrpkru */
7340 if (prefixes & PREFIX_LOCK) {
7341 goto illegal_op;
7343 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7344 cpu_regs[R_EDX]);
7345 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7346 gen_helper_wrpkru(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7347 break;
7348 CASE_MODRM_OP(6): /* lmsw */
7349 if (s->cpl != 0) {
7350 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7351 break;
7353 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7354 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7355 gen_helper_lmsw(cpu_env, cpu_T0);
7356 gen_jmp_im(s->pc - s->cs_base);
7357 gen_eob(s);
7358 break;
7360 CASE_MODRM_MEM_OP(7): /* invlpg */
7361 if (s->cpl != 0) {
7362 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7363 break;
7365 gen_update_cc_op(s);
7366 gen_jmp_im(pc_start - s->cs_base);
7367 gen_lea_modrm(env, s, modrm);
7368 gen_helper_invlpg(cpu_env, cpu_A0);
7369 gen_jmp_im(s->pc - s->cs_base);
7370 gen_eob(s);
7371 break;
7373 case 0xf8: /* swapgs */
7374 #ifdef TARGET_X86_64
7375 if (CODE64(s)) {
7376 if (s->cpl != 0) {
7377 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7378 } else {
7379 tcg_gen_mov_tl(cpu_T0, cpu_seg_base[R_GS]);
7380 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7381 offsetof(CPUX86State, kernelgsbase));
7382 tcg_gen_st_tl(cpu_T0, cpu_env,
7383 offsetof(CPUX86State, kernelgsbase));
7385 break;
7387 #endif
7388 goto illegal_op;
7390 case 0xf9: /* rdtscp */
7391 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7392 goto illegal_op;
7394 gen_update_cc_op(s);
7395 gen_jmp_im(pc_start - s->cs_base);
7396 if (s->tb->cflags & CF_USE_ICOUNT) {
7397 gen_io_start();
7399 gen_helper_rdtscp(cpu_env);
7400 if (s->tb->cflags & CF_USE_ICOUNT) {
7401 gen_io_end();
7402 gen_jmp(s, s->pc - s->cs_base);
7404 break;
7406 default:
7407 goto unknown_op;
7409 break;
7411 case 0x108: /* invd */
7412 case 0x109: /* wbinvd */
7413 if (s->cpl != 0) {
7414 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7415 } else {
7416 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7417 /* nothing to do */
7419 break;
7420 case 0x63: /* arpl or movslS (x86_64) */
7421 #ifdef TARGET_X86_64
7422 if (CODE64(s)) {
7423 int d_ot;
7424 /* d_ot is the size of destination */
7425 d_ot = dflag;
7427 modrm = cpu_ldub_code(env, s->pc++);
7428 reg = ((modrm >> 3) & 7) | rex_r;
7429 mod = (modrm >> 6) & 3;
7430 rm = (modrm & 7) | REX_B(s);
7432 if (mod == 3) {
7433 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
7434 /* sign extend */
7435 if (d_ot == MO_64) {
7436 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
7438 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7439 } else {
7440 gen_lea_modrm(env, s, modrm);
7441 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T0, cpu_A0);
7442 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7444 } else
7445 #endif
7447 TCGLabel *label1;
7448 TCGv t0, t1, t2, a0;
7450 if (!s->pe || s->vm86)
7451 goto illegal_op;
7452 t0 = tcg_temp_local_new();
7453 t1 = tcg_temp_local_new();
7454 t2 = tcg_temp_local_new();
7455 ot = MO_16;
7456 modrm = cpu_ldub_code(env, s->pc++);
7457 reg = (modrm >> 3) & 7;
7458 mod = (modrm >> 6) & 3;
7459 rm = modrm & 7;
7460 if (mod != 3) {
7461 gen_lea_modrm(env, s, modrm);
7462 gen_op_ld_v(s, ot, t0, cpu_A0);
7463 a0 = tcg_temp_local_new();
7464 tcg_gen_mov_tl(a0, cpu_A0);
7465 } else {
7466 gen_op_mov_v_reg(ot, t0, rm);
7467 TCGV_UNUSED(a0);
7469 gen_op_mov_v_reg(ot, t1, reg);
7470 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7471 tcg_gen_andi_tl(t1, t1, 3);
7472 tcg_gen_movi_tl(t2, 0);
7473 label1 = gen_new_label();
7474 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7475 tcg_gen_andi_tl(t0, t0, ~3);
7476 tcg_gen_or_tl(t0, t0, t1);
7477 tcg_gen_movi_tl(t2, CC_Z);
7478 gen_set_label(label1);
7479 if (mod != 3) {
7480 gen_op_st_v(s, ot, t0, a0);
7481 tcg_temp_free(a0);
7482 } else {
7483 gen_op_mov_reg_v(ot, rm, t0);
7485 gen_compute_eflags(s);
7486 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7487 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7488 tcg_temp_free(t0);
7489 tcg_temp_free(t1);
7490 tcg_temp_free(t2);
7492 break;
7493 case 0x102: /* lar */
7494 case 0x103: /* lsl */
7496 TCGLabel *label1;
7497 TCGv t0;
7498 if (!s->pe || s->vm86)
7499 goto illegal_op;
7500 ot = dflag != MO_16 ? MO_32 : MO_16;
7501 modrm = cpu_ldub_code(env, s->pc++);
7502 reg = ((modrm >> 3) & 7) | rex_r;
7503 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7504 t0 = tcg_temp_local_new();
7505 gen_update_cc_op(s);
7506 if (b == 0x102) {
7507 gen_helper_lar(t0, cpu_env, cpu_T0);
7508 } else {
7509 gen_helper_lsl(t0, cpu_env, cpu_T0);
7511 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7512 label1 = gen_new_label();
7513 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7514 gen_op_mov_reg_v(ot, reg, t0);
7515 gen_set_label(label1);
7516 set_cc_op(s, CC_OP_EFLAGS);
7517 tcg_temp_free(t0);
7519 break;
7520 case 0x118:
7521 modrm = cpu_ldub_code(env, s->pc++);
7522 mod = (modrm >> 6) & 3;
7523 op = (modrm >> 3) & 7;
7524 switch(op) {
7525 case 0: /* prefetchnta */
7526 case 1: /* prefetchnt0 */
7527 case 2: /* prefetchnt0 */
7528 case 3: /* prefetchnt0 */
7529 if (mod == 3)
7530 goto illegal_op;
7531 gen_nop_modrm(env, s, modrm);
7532 /* nothing more to do */
7533 break;
7534 default: /* nop (multi byte) */
7535 gen_nop_modrm(env, s, modrm);
7536 break;
7538 break;
7539 case 0x11a:
7540 modrm = cpu_ldub_code(env, s->pc++);
7541 if (s->flags & HF_MPX_EN_MASK) {
7542 mod = (modrm >> 6) & 3;
7543 reg = ((modrm >> 3) & 7) | rex_r;
7544 if (prefixes & PREFIX_REPZ) {
7545 /* bndcl */
7546 if (reg >= 4
7547 || (prefixes & PREFIX_LOCK)
7548 || s->aflag == MO_16) {
7549 goto illegal_op;
7551 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7552 } else if (prefixes & PREFIX_REPNZ) {
7553 /* bndcu */
7554 if (reg >= 4
7555 || (prefixes & PREFIX_LOCK)
7556 || s->aflag == MO_16) {
7557 goto illegal_op;
7559 TCGv_i64 notu = tcg_temp_new_i64();
7560 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7561 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7562 tcg_temp_free_i64(notu);
7563 } else if (prefixes & PREFIX_DATA) {
7564 /* bndmov -- from reg/mem */
7565 if (reg >= 4 || s->aflag == MO_16) {
7566 goto illegal_op;
7568 if (mod == 3) {
7569 int reg2 = (modrm & 7) | REX_B(s);
7570 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7571 goto illegal_op;
7573 if (s->flags & HF_MPX_IU_MASK) {
7574 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7575 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7577 } else {
7578 gen_lea_modrm(env, s, modrm);
7579 if (CODE64(s)) {
7580 tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0,
7581 s->mem_index, MO_LEQ);
7582 tcg_gen_addi_tl(cpu_A0, cpu_A0, 8);
7583 tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0,
7584 s->mem_index, MO_LEQ);
7585 } else {
7586 tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0,
7587 s->mem_index, MO_LEUL);
7588 tcg_gen_addi_tl(cpu_A0, cpu_A0, 4);
7589 tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0,
7590 s->mem_index, MO_LEUL);
7592 /* bnd registers are now in-use */
7593 gen_set_hflag(s, HF_MPX_IU_MASK);
7595 } else if (mod != 3) {
7596 /* bndldx */
7597 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7598 if (reg >= 4
7599 || (prefixes & PREFIX_LOCK)
7600 || s->aflag == MO_16
7601 || a.base < -1) {
7602 goto illegal_op;
7604 if (a.base >= 0) {
7605 tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp);
7606 } else {
7607 tcg_gen_movi_tl(cpu_A0, 0);
7609 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
7610 if (a.index >= 0) {
7611 tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]);
7612 } else {
7613 tcg_gen_movi_tl(cpu_T0, 0);
7615 if (CODE64(s)) {
7616 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, cpu_A0, cpu_T0);
7617 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7618 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7619 } else {
7620 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, cpu_A0, cpu_T0);
7621 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7622 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7624 gen_set_hflag(s, HF_MPX_IU_MASK);
7627 gen_nop_modrm(env, s, modrm);
7628 break;
7629 case 0x11b:
7630 modrm = cpu_ldub_code(env, s->pc++);
7631 if (s->flags & HF_MPX_EN_MASK) {
7632 mod = (modrm >> 6) & 3;
7633 reg = ((modrm >> 3) & 7) | rex_r;
7634 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7635 /* bndmk */
7636 if (reg >= 4
7637 || (prefixes & PREFIX_LOCK)
7638 || s->aflag == MO_16) {
7639 goto illegal_op;
7641 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7642 if (a.base >= 0) {
7643 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7644 if (!CODE64(s)) {
7645 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7647 } else if (a.base == -1) {
7648 /* no base register has lower bound of 0 */
7649 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7650 } else {
7651 /* rip-relative generates #ud */
7652 goto illegal_op;
7654 tcg_gen_not_tl(cpu_A0, gen_lea_modrm_1(a));
7655 if (!CODE64(s)) {
7656 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
7658 tcg_gen_extu_tl_i64(cpu_bndu[reg], cpu_A0);
7659 /* bnd registers are now in-use */
7660 gen_set_hflag(s, HF_MPX_IU_MASK);
7661 break;
7662 } else if (prefixes & PREFIX_REPNZ) {
7663 /* bndcn */
7664 if (reg >= 4
7665 || (prefixes & PREFIX_LOCK)
7666 || s->aflag == MO_16) {
7667 goto illegal_op;
7669 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
7670 } else if (prefixes & PREFIX_DATA) {
7671 /* bndmov -- to reg/mem */
7672 if (reg >= 4 || s->aflag == MO_16) {
7673 goto illegal_op;
7675 if (mod == 3) {
7676 int reg2 = (modrm & 7) | REX_B(s);
7677 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7678 goto illegal_op;
7680 if (s->flags & HF_MPX_IU_MASK) {
7681 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7682 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7684 } else {
7685 gen_lea_modrm(env, s, modrm);
7686 if (CODE64(s)) {
7687 tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0,
7688 s->mem_index, MO_LEQ);
7689 tcg_gen_addi_tl(cpu_A0, cpu_A0, 8);
7690 tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0,
7691 s->mem_index, MO_LEQ);
7692 } else {
7693 tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0,
7694 s->mem_index, MO_LEUL);
7695 tcg_gen_addi_tl(cpu_A0, cpu_A0, 4);
7696 tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0,
7697 s->mem_index, MO_LEUL);
7700 } else if (mod != 3) {
7701 /* bndstx */
7702 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7703 if (reg >= 4
7704 || (prefixes & PREFIX_LOCK)
7705 || s->aflag == MO_16
7706 || a.base < -1) {
7707 goto illegal_op;
7709 if (a.base >= 0) {
7710 tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp);
7711 } else {
7712 tcg_gen_movi_tl(cpu_A0, 0);
7714 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
7715 if (a.index >= 0) {
7716 tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]);
7717 } else {
7718 tcg_gen_movi_tl(cpu_T0, 0);
7720 if (CODE64(s)) {
7721 gen_helper_bndstx64(cpu_env, cpu_A0, cpu_T0,
7722 cpu_bndl[reg], cpu_bndu[reg]);
7723 } else {
7724 gen_helper_bndstx32(cpu_env, cpu_A0, cpu_T0,
7725 cpu_bndl[reg], cpu_bndu[reg]);
7729 gen_nop_modrm(env, s, modrm);
7730 break;
7731 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
7732 modrm = cpu_ldub_code(env, s->pc++);
7733 gen_nop_modrm(env, s, modrm);
7734 break;
7735 case 0x120: /* mov reg, crN */
7736 case 0x122: /* mov crN, reg */
7737 if (s->cpl != 0) {
7738 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7739 } else {
7740 modrm = cpu_ldub_code(env, s->pc++);
7741 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7742 * AMD documentation (24594.pdf) and testing of
7743 * intel 386 and 486 processors all show that the mod bits
7744 * are assumed to be 1's, regardless of actual values.
7746 rm = (modrm & 7) | REX_B(s);
7747 reg = ((modrm >> 3) & 7) | rex_r;
7748 if (CODE64(s))
7749 ot = MO_64;
7750 else
7751 ot = MO_32;
7752 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7753 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7754 reg = 8;
7756 switch(reg) {
7757 case 0:
7758 case 2:
7759 case 3:
7760 case 4:
7761 case 8:
7762 gen_update_cc_op(s);
7763 gen_jmp_im(pc_start - s->cs_base);
7764 if (b & 2) {
7765 gen_op_mov_v_reg(ot, cpu_T0, rm);
7766 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7767 cpu_T0);
7768 gen_jmp_im(s->pc - s->cs_base);
7769 gen_eob(s);
7770 } else {
7771 gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg));
7772 gen_op_mov_reg_v(ot, rm, cpu_T0);
7774 break;
7775 default:
7776 goto unknown_op;
7779 break;
7780 case 0x121: /* mov reg, drN */
7781 case 0x123: /* mov drN, reg */
7782 if (s->cpl != 0) {
7783 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7784 } else {
7785 modrm = cpu_ldub_code(env, s->pc++);
7786 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7787 * AMD documentation (24594.pdf) and testing of
7788 * intel 386 and 486 processors all show that the mod bits
7789 * are assumed to be 1's, regardless of actual values.
7791 rm = (modrm & 7) | REX_B(s);
7792 reg = ((modrm >> 3) & 7) | rex_r;
7793 if (CODE64(s))
7794 ot = MO_64;
7795 else
7796 ot = MO_32;
7797 if (reg >= 8) {
7798 goto illegal_op;
7800 if (b & 2) {
7801 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7802 gen_op_mov_v_reg(ot, cpu_T0, rm);
7803 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7804 gen_helper_set_dr(cpu_env, cpu_tmp2_i32, cpu_T0);
7805 gen_jmp_im(s->pc - s->cs_base);
7806 gen_eob(s);
7807 } else {
7808 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7809 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7810 gen_helper_get_dr(cpu_T0, cpu_env, cpu_tmp2_i32);
7811 gen_op_mov_reg_v(ot, rm, cpu_T0);
7814 break;
7815 case 0x106: /* clts */
7816 if (s->cpl != 0) {
7817 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7818 } else {
7819 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7820 gen_helper_clts(cpu_env);
7821 /* abort block because static cpu state changed */
7822 gen_jmp_im(s->pc - s->cs_base);
7823 gen_eob(s);
7825 break;
7826 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
7827 case 0x1c3: /* MOVNTI reg, mem */
7828 if (!(s->cpuid_features & CPUID_SSE2))
7829 goto illegal_op;
7830 ot = mo_64_32(dflag);
7831 modrm = cpu_ldub_code(env, s->pc++);
7832 mod = (modrm >> 6) & 3;
7833 if (mod == 3)
7834 goto illegal_op;
7835 reg = ((modrm >> 3) & 7) | rex_r;
7836 /* generate a generic store */
7837 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
7838 break;
7839 case 0x1ae:
7840 modrm = cpu_ldub_code(env, s->pc++);
7841 switch (modrm) {
7842 CASE_MODRM_MEM_OP(0): /* fxsave */
7843 if (!(s->cpuid_features & CPUID_FXSR)
7844 || (prefixes & PREFIX_LOCK)) {
7845 goto illegal_op;
7847 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7848 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7849 break;
7851 gen_lea_modrm(env, s, modrm);
7852 gen_helper_fxsave(cpu_env, cpu_A0);
7853 break;
7855 CASE_MODRM_MEM_OP(1): /* fxrstor */
7856 if (!(s->cpuid_features & CPUID_FXSR)
7857 || (prefixes & PREFIX_LOCK)) {
7858 goto illegal_op;
7860 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7861 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7862 break;
7864 gen_lea_modrm(env, s, modrm);
7865 gen_helper_fxrstor(cpu_env, cpu_A0);
7866 break;
7868 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
7869 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
7870 goto illegal_op;
7872 if (s->flags & HF_TS_MASK) {
7873 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7874 break;
7876 gen_lea_modrm(env, s, modrm);
7877 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, s->mem_index, MO_LEUL);
7878 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
7879 break;
7881 CASE_MODRM_MEM_OP(3): /* stmxcsr */
7882 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
7883 goto illegal_op;
7885 if (s->flags & HF_TS_MASK) {
7886 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7887 break;
7889 gen_lea_modrm(env, s, modrm);
7890 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, mxcsr));
7891 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
7892 break;
7894 CASE_MODRM_MEM_OP(4): /* xsave */
7895 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7896 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
7897 | PREFIX_REPZ | PREFIX_REPNZ))) {
7898 goto illegal_op;
7900 gen_lea_modrm(env, s, modrm);
7901 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7902 cpu_regs[R_EDX]);
7903 gen_helper_xsave(cpu_env, cpu_A0, cpu_tmp1_i64);
7904 break;
7906 CASE_MODRM_MEM_OP(5): /* xrstor */
7907 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7908 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
7909 | PREFIX_REPZ | PREFIX_REPNZ))) {
7910 goto illegal_op;
7912 gen_lea_modrm(env, s, modrm);
7913 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7914 cpu_regs[R_EDX]);
7915 gen_helper_xrstor(cpu_env, cpu_A0, cpu_tmp1_i64);
7916 /* XRSTOR is how MPX is enabled, which changes how
7917 we translate. Thus we need to end the TB. */
7918 gen_update_cc_op(s);
7919 gen_jmp_im(s->pc - s->cs_base);
7920 gen_eob(s);
7921 break;
7923 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
7924 if (prefixes & PREFIX_LOCK) {
7925 goto illegal_op;
7927 if (prefixes & PREFIX_DATA) {
7928 /* clwb */
7929 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
7930 goto illegal_op;
7932 gen_nop_modrm(env, s, modrm);
7933 } else {
7934 /* xsaveopt */
7935 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7936 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
7937 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
7938 goto illegal_op;
7940 gen_lea_modrm(env, s, modrm);
7941 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7942 cpu_regs[R_EDX]);
7943 gen_helper_xsaveopt(cpu_env, cpu_A0, cpu_tmp1_i64);
7945 break;
7947 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
7948 if (prefixes & PREFIX_LOCK) {
7949 goto illegal_op;
7951 if (prefixes & PREFIX_DATA) {
7952 /* clflushopt */
7953 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
7954 goto illegal_op;
7956 } else {
7957 /* clflush */
7958 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
7959 || !(s->cpuid_features & CPUID_CLFLUSH)) {
7960 goto illegal_op;
7963 gen_nop_modrm(env, s, modrm);
7964 break;
7966 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
7967 case 0xc8 ... 0xc8: /* rdgsbase (f3 0f ae /1) */
7968 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
7969 case 0xd8 ... 0xd8: /* wrgsbase (f3 0f ae /3) */
7970 if (CODE64(s)
7971 && (prefixes & PREFIX_REPZ)
7972 && !(prefixes & PREFIX_LOCK)
7973 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
7974 TCGv base, treg, src, dst;
7976 /* Preserve hflags bits by testing CR4 at runtime. */
7977 tcg_gen_movi_i32(cpu_tmp2_i32, CR4_FSGSBASE_MASK);
7978 gen_helper_cr4_testbit(cpu_env, cpu_tmp2_i32);
7980 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
7981 treg = cpu_regs[(modrm & 7) | REX_B(s)];
7983 if (modrm & 0x10) {
7984 /* wr*base */
7985 dst = base, src = treg;
7986 } else {
7987 /* rd*base */
7988 dst = treg, src = base;
7991 if (s->dflag == MO_32) {
7992 tcg_gen_ext32u_tl(dst, src);
7993 } else {
7994 tcg_gen_mov_tl(dst, src);
7996 break;
7998 goto unknown_op;
8000 case 0xf8: /* sfence / pcommit */
8001 if (prefixes & PREFIX_DATA) {
8002 /* pcommit */
8003 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8004 || (prefixes & PREFIX_LOCK)) {
8005 goto illegal_op;
8007 break;
8009 /* fallthru */
8010 case 0xf9 ... 0xff: /* sfence */
8011 if (!(s->cpuid_features & CPUID_SSE)
8012 || (prefixes & PREFIX_LOCK)) {
8013 goto illegal_op;
8015 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8016 break;
8017 case 0xe8 ... 0xef: /* lfence */
8018 if (!(s->cpuid_features & CPUID_SSE)
8019 || (prefixes & PREFIX_LOCK)) {
8020 goto illegal_op;
8022 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8023 break;
8024 case 0xf0 ... 0xf7: /* mfence */
8025 if (!(s->cpuid_features & CPUID_SSE2)
8026 || (prefixes & PREFIX_LOCK)) {
8027 goto illegal_op;
8029 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8030 break;
8032 default:
8033 goto unknown_op;
8035 break;
8037 case 0x10d: /* 3DNow! prefetch(w) */
8038 modrm = cpu_ldub_code(env, s->pc++);
8039 mod = (modrm >> 6) & 3;
8040 if (mod == 3)
8041 goto illegal_op;
8042 gen_nop_modrm(env, s, modrm);
8043 break;
8044 case 0x1aa: /* rsm */
8045 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8046 if (!(s->flags & HF_SMM_MASK))
8047 goto illegal_op;
8048 gen_update_cc_op(s);
8049 gen_jmp_im(s->pc - s->cs_base);
8050 gen_helper_rsm(cpu_env);
8051 gen_eob(s);
8052 break;
8053 case 0x1b8: /* SSE4.2 popcnt */
8054 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8055 PREFIX_REPZ)
8056 goto illegal_op;
8057 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8058 goto illegal_op;
8060 modrm = cpu_ldub_code(env, s->pc++);
8061 reg = ((modrm >> 3) & 7) | rex_r;
8063 if (s->prefix & PREFIX_DATA) {
8064 ot = MO_16;
8065 } else {
8066 ot = mo_64_32(dflag);
8069 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8070 gen_helper_popcnt(cpu_T0, cpu_env, cpu_T0, tcg_const_i32(ot));
8071 gen_op_mov_reg_v(ot, reg, cpu_T0);
8073 set_cc_op(s, CC_OP_EFLAGS);
8074 break;
8075 case 0x10e ... 0x10f:
8076 /* 3DNow! instructions, ignore prefixes */
8077 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8078 case 0x110 ... 0x117:
8079 case 0x128 ... 0x12f:
8080 case 0x138 ... 0x13a:
8081 case 0x150 ... 0x179:
8082 case 0x17c ... 0x17f:
8083 case 0x1c2:
8084 case 0x1c4 ... 0x1c6:
8085 case 0x1d0 ... 0x1fe:
8086 gen_sse(env, s, b, pc_start, rex_r);
8087 break;
8088 default:
8089 goto unknown_op;
8091 /* lock generation */
8092 if (s->prefix & PREFIX_LOCK)
8093 gen_helper_unlock();
8094 return s->pc;
8095 illegal_op:
8096 if (s->prefix & PREFIX_LOCK)
8097 gen_helper_unlock();
8098 /* XXX: ensure that no lock was generated */
8099 gen_illegal_opcode(s);
8100 return s->pc;
8101 unknown_op:
8102 if (s->prefix & PREFIX_LOCK)
8103 gen_helper_unlock();
8104 /* XXX: ensure that no lock was generated */
8105 gen_unknown_opcode(env, s);
8106 return s->pc;
8109 void tcg_x86_init(void)
8111 static const char reg_names[CPU_NB_REGS][4] = {
8112 #ifdef TARGET_X86_64
8113 [R_EAX] = "rax",
8114 [R_EBX] = "rbx",
8115 [R_ECX] = "rcx",
8116 [R_EDX] = "rdx",
8117 [R_ESI] = "rsi",
8118 [R_EDI] = "rdi",
8119 [R_EBP] = "rbp",
8120 [R_ESP] = "rsp",
8121 [8] = "r8",
8122 [9] = "r9",
8123 [10] = "r10",
8124 [11] = "r11",
8125 [12] = "r12",
8126 [13] = "r13",
8127 [14] = "r14",
8128 [15] = "r15",
8129 #else
8130 [R_EAX] = "eax",
8131 [R_EBX] = "ebx",
8132 [R_ECX] = "ecx",
8133 [R_EDX] = "edx",
8134 [R_ESI] = "esi",
8135 [R_EDI] = "edi",
8136 [R_EBP] = "ebp",
8137 [R_ESP] = "esp",
8138 #endif
8140 static const char seg_base_names[6][8] = {
8141 [R_CS] = "cs_base",
8142 [R_DS] = "ds_base",
8143 [R_ES] = "es_base",
8144 [R_FS] = "fs_base",
8145 [R_GS] = "gs_base",
8146 [R_SS] = "ss_base",
8148 static const char bnd_regl_names[4][8] = {
8149 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8151 static const char bnd_regu_names[4][8] = {
8152 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8154 int i;
8155 static bool initialized;
8157 if (initialized) {
8158 return;
8160 initialized = true;
8162 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8163 tcg_ctx.tcg_env = cpu_env;
8164 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8165 offsetof(CPUX86State, cc_op), "cc_op");
8166 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8167 "cc_dst");
8168 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8169 "cc_src");
8170 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8171 "cc_src2");
8173 for (i = 0; i < CPU_NB_REGS; ++i) {
8174 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8175 offsetof(CPUX86State, regs[i]),
8176 reg_names[i]);
8179 for (i = 0; i < 6; ++i) {
8180 cpu_seg_base[i]
8181 = tcg_global_mem_new(cpu_env,
8182 offsetof(CPUX86State, segs[i].base),
8183 seg_base_names[i]);
8186 for (i = 0; i < 4; ++i) {
8187 cpu_bndl[i]
8188 = tcg_global_mem_new_i64(cpu_env,
8189 offsetof(CPUX86State, bnd_regs[i].lb),
8190 bnd_regl_names[i]);
8191 cpu_bndu[i]
8192 = tcg_global_mem_new_i64(cpu_env,
8193 offsetof(CPUX86State, bnd_regs[i].ub),
8194 bnd_regu_names[i]);
8197 helper_lock_init();
8200 /* generate intermediate code for basic block 'tb'. */
8201 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
8203 X86CPU *cpu = x86_env_get_cpu(env);
8204 CPUState *cs = CPU(cpu);
8205 DisasContext dc1, *dc = &dc1;
8206 target_ulong pc_ptr;
8207 uint32_t flags;
8208 target_ulong pc_start;
8209 target_ulong cs_base;
8210 int num_insns;
8211 int max_insns;
8213 /* generate intermediate code */
8214 pc_start = tb->pc;
8215 cs_base = tb->cs_base;
8216 flags = tb->flags;
8218 dc->pe = (flags >> HF_PE_SHIFT) & 1;
8219 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8220 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8221 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8222 dc->f_st = 0;
8223 dc->vm86 = (flags >> VM_SHIFT) & 1;
8224 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8225 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8226 dc->tf = (flags >> TF_SHIFT) & 1;
8227 dc->singlestep_enabled = cs->singlestep_enabled;
8228 dc->cc_op = CC_OP_DYNAMIC;
8229 dc->cc_op_dirty = false;
8230 dc->cs_base = cs_base;
8231 dc->tb = tb;
8232 dc->popl_esp_hack = 0;
8233 /* select memory access functions */
8234 dc->mem_index = 0;
8235 #ifdef CONFIG_SOFTMMU
8236 dc->mem_index = cpu_mmu_index(env, false);
8237 #endif
8238 dc->cpuid_features = env->features[FEAT_1_EDX];
8239 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8240 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8241 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8242 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8243 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8244 #ifdef TARGET_X86_64
8245 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8246 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8247 #endif
8248 dc->flags = flags;
8249 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
8250 (flags & HF_INHIBIT_IRQ_MASK));
8251 /* Do not optimize repz jumps at all in icount mode, because
8252 rep movsS instructions are execured with different paths
8253 in !repz_opt and repz_opt modes. The first one was used
8254 always except single step mode. And this setting
8255 disables jumps optimization and control paths become
8256 equivalent in run and single step modes.
8257 Now there will be no jump optimization for repz in
8258 record/replay modes and there will always be an
8259 additional step for ecx=0 when icount is enabled.
8261 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
8262 #if 0
8263 /* check addseg logic */
8264 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8265 printf("ERROR addseg\n");
8266 #endif
8268 cpu_T0 = tcg_temp_new();
8269 cpu_T1 = tcg_temp_new();
8270 cpu_A0 = tcg_temp_new();
8272 cpu_tmp0 = tcg_temp_new();
8273 cpu_tmp1_i64 = tcg_temp_new_i64();
8274 cpu_tmp2_i32 = tcg_temp_new_i32();
8275 cpu_tmp3_i32 = tcg_temp_new_i32();
8276 cpu_tmp4 = tcg_temp_new();
8277 cpu_ptr0 = tcg_temp_new_ptr();
8278 cpu_ptr1 = tcg_temp_new_ptr();
8279 cpu_cc_srcT = tcg_temp_local_new();
8281 dc->is_jmp = DISAS_NEXT;
8282 pc_ptr = pc_start;
8283 num_insns = 0;
8284 max_insns = tb->cflags & CF_COUNT_MASK;
8285 if (max_insns == 0) {
8286 max_insns = CF_COUNT_MASK;
8288 if (max_insns > TCG_MAX_INSNS) {
8289 max_insns = TCG_MAX_INSNS;
8292 gen_tb_start(tb);
8293 for(;;) {
8294 tcg_gen_insn_start(pc_ptr, dc->cc_op);
8295 num_insns++;
8297 /* If RF is set, suppress an internally generated breakpoint. */
8298 if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
8299 tb->flags & HF_RF_MASK
8300 ? BP_GDB : BP_ANY))) {
8301 gen_debug(dc, pc_ptr - dc->cs_base);
8302 /* The address covered by the breakpoint must be included in
8303 [tb->pc, tb->pc + tb->size) in order to for it to be
8304 properly cleared -- thus we increment the PC here so that
8305 the logic setting tb->size below does the right thing. */
8306 pc_ptr += 1;
8307 goto done_generating;
8309 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
8310 gen_io_start();
8313 pc_ptr = disas_insn(env, dc, pc_ptr);
8314 /* stop translation if indicated */
8315 if (dc->is_jmp)
8316 break;
8317 /* if single step mode, we generate only one instruction and
8318 generate an exception */
8319 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8320 the flag and abort the translation to give the irqs a
8321 change to be happen */
8322 if (dc->tf || dc->singlestep_enabled ||
8323 (flags & HF_INHIBIT_IRQ_MASK)) {
8324 gen_jmp_im(pc_ptr - dc->cs_base);
8325 gen_eob(dc);
8326 break;
8328 /* Do not cross the boundary of the pages in icount mode,
8329 it can cause an exception. Do it only when boundary is
8330 crossed by the first instruction in the block.
8331 If current instruction already crossed the bound - it's ok,
8332 because an exception hasn't stopped this code.
8334 if ((tb->cflags & CF_USE_ICOUNT)
8335 && ((pc_ptr & TARGET_PAGE_MASK)
8336 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
8337 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
8338 gen_jmp_im(pc_ptr - dc->cs_base);
8339 gen_eob(dc);
8340 break;
8342 /* if too long translation, stop generation too */
8343 if (tcg_op_buf_full() ||
8344 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8345 num_insns >= max_insns) {
8346 gen_jmp_im(pc_ptr - dc->cs_base);
8347 gen_eob(dc);
8348 break;
8350 if (singlestep) {
8351 gen_jmp_im(pc_ptr - dc->cs_base);
8352 gen_eob(dc);
8353 break;
8356 if (tb->cflags & CF_LAST_IO)
8357 gen_io_end();
8358 done_generating:
8359 gen_tb_end(tb, num_insns);
8361 #ifdef DEBUG_DISAS
8362 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
8363 && qemu_log_in_addr_range(pc_start)) {
8364 int disas_flags;
8365 qemu_log("----------------\n");
8366 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8367 #ifdef TARGET_X86_64
8368 if (dc->code64)
8369 disas_flags = 2;
8370 else
8371 #endif
8372 disas_flags = !dc->code32;
8373 log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
8374 qemu_log("\n");
8376 #endif
8378 tb->size = pc_ptr - pc_start;
8379 tb->icount = num_insns;
8382 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8383 target_ulong *data)
8385 int cc_op = data[1];
8386 env->eip = data[0] - tb->cs_base;
8387 if (cc_op != CC_OP_DYNAMIC) {
8388 env->cc_op = cc_op;