scsi-disk: support reporting of rotation rate
[qemu/ar7.git] / target / i386 / translate.c
blob5d61fa96ad6354aed7ec6d9be95fb7bb70da6819
1 /*
2 * i386 translation
4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include "qemu/host-utils.h"
22 #include "cpu.h"
23 #include "disas/disas.h"
24 #include "exec/exec-all.h"
25 #include "tcg-op.h"
26 #include "exec/cpu_ldst.h"
27 #include "exec/translator.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
32 #include "trace-tcg.h"
33 #include "exec/log.h"
35 #define PREFIX_REPZ 0x01
36 #define PREFIX_REPNZ 0x02
37 #define PREFIX_LOCK 0x04
38 #define PREFIX_DATA 0x08
39 #define PREFIX_ADR 0x10
40 #define PREFIX_VEX 0x20
42 #ifdef TARGET_X86_64
43 #define CODE64(s) ((s)->code64)
44 #define REX_X(s) ((s)->rex_x)
45 #define REX_B(s) ((s)->rex_b)
46 #else
47 #define CODE64(s) 0
48 #define REX_X(s) 0
49 #define REX_B(s) 0
50 #endif
52 #ifdef TARGET_X86_64
53 # define ctztl ctz64
54 # define clztl clz64
55 #else
56 # define ctztl ctz32
57 # define clztl clz32
58 #endif
60 /* For a switch indexed by MODRM, match all memory operands for a given OP. */
61 #define CASE_MODRM_MEM_OP(OP) \
62 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
63 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
64 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
66 #define CASE_MODRM_OP(OP) \
67 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
68 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
69 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
70 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
72 //#define MACRO_TEST 1
74 /* global register indexes */
75 static TCGv_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 DisasContextBase base;
100 /* current insn context */
101 int override; /* -1 if no override */
102 int prefix;
103 TCGMemOp aflag;
104 TCGMemOp dflag;
105 target_ulong pc_start;
106 target_ulong pc; /* pc = eip + cs_base */
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 jmp_opt; /* use direct block chaining for direct jumps */
128 int repz_opt; /* optimize jumps within repz instructions */
129 int mem_index; /* select memory access functions */
130 uint64_t flags; /* all execution flags */
131 int popl_esp_hack; /* for correct popl with esp base handling */
132 int rip_offset; /* only used in x86_64, but left for simplicity */
133 int cpuid_features;
134 int cpuid_ext_features;
135 int cpuid_ext2_features;
136 int cpuid_ext3_features;
137 int cpuid_7_0_ebx_features;
138 int cpuid_xsave_features;
139 } DisasContext;
141 static void gen_eob(DisasContext *s);
142 static void gen_jr(DisasContext *s, TCGv dest);
143 static void gen_jmp(DisasContext *s, target_ulong eip);
144 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
145 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d);
147 /* i386 arith/logic operations */
148 enum {
149 OP_ADDL,
150 OP_ORL,
151 OP_ADCL,
152 OP_SBBL,
153 OP_ANDL,
154 OP_SUBL,
155 OP_XORL,
156 OP_CMPL,
159 /* i386 shift ops */
160 enum {
161 OP_ROL,
162 OP_ROR,
163 OP_RCL,
164 OP_RCR,
165 OP_SHL,
166 OP_SHR,
167 OP_SHL1, /* undocumented */
168 OP_SAR = 7,
171 enum {
172 JCC_O,
173 JCC_B,
174 JCC_Z,
175 JCC_BE,
176 JCC_S,
177 JCC_P,
178 JCC_L,
179 JCC_LE,
182 enum {
183 /* I386 int registers */
184 OR_EAX, /* MUST be even numbered */
185 OR_ECX,
186 OR_EDX,
187 OR_EBX,
188 OR_ESP,
189 OR_EBP,
190 OR_ESI,
191 OR_EDI,
193 OR_TMP0 = 16, /* temporary operand register */
194 OR_TMP1,
195 OR_A0, /* temporary register used when doing address evaluation */
198 enum {
199 USES_CC_DST = 1,
200 USES_CC_SRC = 2,
201 USES_CC_SRC2 = 4,
202 USES_CC_SRCT = 8,
205 /* Bit set if the global variable is live after setting CC_OP to X. */
206 static const uint8_t cc_op_live[CC_OP_NB] = {
207 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
208 [CC_OP_EFLAGS] = USES_CC_SRC,
209 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
210 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
211 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
212 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
213 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
214 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
215 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
216 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
217 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
218 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
219 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
220 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
221 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
222 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
223 [CC_OP_CLR] = 0,
224 [CC_OP_POPCNT] = USES_CC_SRC,
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_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
387 } else {
388 tcg_gen_mov_tl(t0, cpu_regs[reg]);
392 static void gen_add_A0_im(DisasContext *s, int val)
394 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
395 if (!CODE64(s)) {
396 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
400 static inline void gen_op_jmp_v(TCGv dest)
402 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
405 static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
407 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
408 gen_op_mov_reg_v(size, reg, cpu_tmp0);
411 static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
413 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T0);
414 gen_op_mov_reg_v(size, reg, cpu_tmp0);
417 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
419 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
422 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
424 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
427 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
429 if (d == OR_TMP0) {
430 gen_op_st_v(s, idx, cpu_T0, cpu_A0);
431 } else {
432 gen_op_mov_reg_v(idx, d, cpu_T0);
436 static inline void gen_jmp_im(target_ulong pc)
438 tcg_gen_movi_tl(cpu_tmp0, pc);
439 gen_op_jmp_v(cpu_tmp0);
442 /* Compute SEG:REG into A0. SEG is selected from the override segment
443 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
444 indicate no override. */
445 static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
446 int def_seg, int ovr_seg)
448 switch (aflag) {
449 #ifdef TARGET_X86_64
450 case MO_64:
451 if (ovr_seg < 0) {
452 tcg_gen_mov_tl(cpu_A0, a0);
453 return;
455 break;
456 #endif
457 case MO_32:
458 /* 32 bit address */
459 if (ovr_seg < 0 && s->addseg) {
460 ovr_seg = def_seg;
462 if (ovr_seg < 0) {
463 tcg_gen_ext32u_tl(cpu_A0, a0);
464 return;
466 break;
467 case MO_16:
468 /* 16 bit address */
469 tcg_gen_ext16u_tl(cpu_A0, a0);
470 a0 = cpu_A0;
471 if (ovr_seg < 0) {
472 if (s->addseg) {
473 ovr_seg = def_seg;
474 } else {
475 return;
478 break;
479 default:
480 tcg_abort();
483 if (ovr_seg >= 0) {
484 TCGv seg = cpu_seg_base[ovr_seg];
486 if (aflag == MO_64) {
487 tcg_gen_add_tl(cpu_A0, a0, seg);
488 } else if (CODE64(s)) {
489 tcg_gen_ext32u_tl(cpu_A0, a0);
490 tcg_gen_add_tl(cpu_A0, cpu_A0, seg);
491 } else {
492 tcg_gen_add_tl(cpu_A0, a0, seg);
493 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
498 static inline void gen_string_movl_A0_ESI(DisasContext *s)
500 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
503 static inline void gen_string_movl_A0_EDI(DisasContext *s)
505 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
508 static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
510 tcg_gen_ld32s_tl(cpu_T0, cpu_env, offsetof(CPUX86State, df));
511 tcg_gen_shli_tl(cpu_T0, cpu_T0, ot);
514 static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign)
516 switch (size) {
517 case MO_8:
518 if (sign) {
519 tcg_gen_ext8s_tl(dst, src);
520 } else {
521 tcg_gen_ext8u_tl(dst, src);
523 return dst;
524 case MO_16:
525 if (sign) {
526 tcg_gen_ext16s_tl(dst, src);
527 } else {
528 tcg_gen_ext16u_tl(dst, src);
530 return dst;
531 #ifdef TARGET_X86_64
532 case MO_32:
533 if (sign) {
534 tcg_gen_ext32s_tl(dst, src);
535 } else {
536 tcg_gen_ext32u_tl(dst, src);
538 return dst;
539 #endif
540 default:
541 return src;
545 static void gen_extu(TCGMemOp ot, TCGv reg)
547 gen_ext_tl(reg, reg, ot, false);
550 static void gen_exts(TCGMemOp ot, TCGv reg)
552 gen_ext_tl(reg, reg, ot, true);
555 static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1)
557 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
558 gen_extu(size, cpu_tmp0);
559 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
562 static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1)
564 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
565 gen_extu(size, cpu_tmp0);
566 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
569 static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n)
571 switch (ot) {
572 case MO_8:
573 gen_helper_inb(v, cpu_env, n);
574 break;
575 case MO_16:
576 gen_helper_inw(v, cpu_env, n);
577 break;
578 case MO_32:
579 gen_helper_inl(v, cpu_env, n);
580 break;
581 default:
582 tcg_abort();
586 static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n)
588 switch (ot) {
589 case MO_8:
590 gen_helper_outb(cpu_env, v, n);
591 break;
592 case MO_16:
593 gen_helper_outw(cpu_env, v, n);
594 break;
595 case MO_32:
596 gen_helper_outl(cpu_env, v, n);
597 break;
598 default:
599 tcg_abort();
603 static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
604 uint32_t svm_flags)
606 target_ulong next_eip;
608 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
609 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
610 switch (ot) {
611 case MO_8:
612 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
613 break;
614 case MO_16:
615 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
616 break;
617 case MO_32:
618 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
619 break;
620 default:
621 tcg_abort();
624 if(s->flags & HF_SVMI_MASK) {
625 gen_update_cc_op(s);
626 gen_jmp_im(cur_eip);
627 svm_flags |= (1 << (4 + ot));
628 next_eip = s->pc - s->cs_base;
629 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
630 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
631 tcg_const_i32(svm_flags),
632 tcg_const_i32(next_eip - cur_eip));
636 static inline void gen_movs(DisasContext *s, TCGMemOp ot)
638 gen_string_movl_A0_ESI(s);
639 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
640 gen_string_movl_A0_EDI(s);
641 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
642 gen_op_movl_T0_Dshift(ot);
643 gen_op_add_reg_T0(s->aflag, R_ESI);
644 gen_op_add_reg_T0(s->aflag, R_EDI);
647 static void gen_op_update1_cc(void)
649 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
652 static void gen_op_update2_cc(void)
654 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
655 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
658 static void gen_op_update3_cc(TCGv reg)
660 tcg_gen_mov_tl(cpu_cc_src2, reg);
661 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
662 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
665 static inline void gen_op_testl_T0_T1_cc(void)
667 tcg_gen_and_tl(cpu_cc_dst, cpu_T0, cpu_T1);
670 static void gen_op_update_neg_cc(void)
672 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
673 tcg_gen_neg_tl(cpu_cc_src, cpu_T0);
674 tcg_gen_movi_tl(cpu_cc_srcT, 0);
677 /* compute all eflags to cc_src */
678 static void gen_compute_eflags(DisasContext *s)
680 TCGv zero, dst, src1, src2;
681 int live, dead;
683 if (s->cc_op == CC_OP_EFLAGS) {
684 return;
686 if (s->cc_op == CC_OP_CLR) {
687 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
688 set_cc_op(s, CC_OP_EFLAGS);
689 return;
692 TCGV_UNUSED(zero);
693 dst = cpu_cc_dst;
694 src1 = cpu_cc_src;
695 src2 = cpu_cc_src2;
697 /* Take care to not read values that are not live. */
698 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
699 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
700 if (dead) {
701 zero = tcg_const_tl(0);
702 if (dead & USES_CC_DST) {
703 dst = zero;
705 if (dead & USES_CC_SRC) {
706 src1 = zero;
708 if (dead & USES_CC_SRC2) {
709 src2 = zero;
713 gen_update_cc_op(s);
714 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
715 set_cc_op(s, CC_OP_EFLAGS);
717 if (dead) {
718 tcg_temp_free(zero);
722 typedef struct CCPrepare {
723 TCGCond cond;
724 TCGv reg;
725 TCGv reg2;
726 target_ulong imm;
727 target_ulong mask;
728 bool use_reg2;
729 bool no_setcond;
730 } CCPrepare;
732 /* compute eflags.C to reg */
733 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
735 TCGv t0, t1;
736 int size, shift;
738 switch (s->cc_op) {
739 case CC_OP_SUBB ... CC_OP_SUBQ:
740 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
741 size = s->cc_op - CC_OP_SUBB;
742 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
743 /* If no temporary was used, be careful not to alias t1 and t0. */
744 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
745 tcg_gen_mov_tl(t0, cpu_cc_srcT);
746 gen_extu(size, t0);
747 goto add_sub;
749 case CC_OP_ADDB ... CC_OP_ADDQ:
750 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
751 size = s->cc_op - CC_OP_ADDB;
752 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
753 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
754 add_sub:
755 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
756 .reg2 = t1, .mask = -1, .use_reg2 = true };
758 case CC_OP_LOGICB ... CC_OP_LOGICQ:
759 case CC_OP_CLR:
760 case CC_OP_POPCNT:
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 case CC_OP_POPCNT:
829 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
830 default:
832 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
833 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
834 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
839 /* compute eflags.O to reg */
840 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
842 switch (s->cc_op) {
843 case CC_OP_ADOX:
844 case CC_OP_ADCOX:
845 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
846 .mask = -1, .no_setcond = true };
847 case CC_OP_CLR:
848 case CC_OP_POPCNT:
849 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
850 default:
851 gen_compute_eflags(s);
852 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
853 .mask = CC_O };
857 /* compute eflags.Z to reg */
858 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
860 switch (s->cc_op) {
861 case CC_OP_DYNAMIC:
862 gen_compute_eflags(s);
863 /* FALLTHRU */
864 case CC_OP_EFLAGS:
865 case CC_OP_ADCX:
866 case CC_OP_ADOX:
867 case CC_OP_ADCOX:
868 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
869 .mask = CC_Z };
870 case CC_OP_CLR:
871 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
872 case CC_OP_POPCNT:
873 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
874 .mask = -1 };
875 default:
877 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
878 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
879 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
884 /* perform a conditional store into register 'reg' according to jump opcode
885 value 'b'. In the fast case, T0 is guaranted not to be used. */
886 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
888 int inv, jcc_op, cond;
889 TCGMemOp size;
890 CCPrepare cc;
891 TCGv t0;
893 inv = b & 1;
894 jcc_op = (b >> 1) & 7;
896 switch (s->cc_op) {
897 case CC_OP_SUBB ... CC_OP_SUBQ:
898 /* We optimize relational operators for the cmp/jcc case. */
899 size = s->cc_op - CC_OP_SUBB;
900 switch (jcc_op) {
901 case JCC_BE:
902 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
903 gen_extu(size, cpu_tmp4);
904 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
905 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
906 .reg2 = t0, .mask = -1, .use_reg2 = true };
907 break;
909 case JCC_L:
910 cond = TCG_COND_LT;
911 goto fast_jcc_l;
912 case JCC_LE:
913 cond = TCG_COND_LE;
914 fast_jcc_l:
915 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
916 gen_exts(size, cpu_tmp4);
917 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
918 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
919 .reg2 = t0, .mask = -1, .use_reg2 = true };
920 break;
922 default:
923 goto slow_jcc;
925 break;
927 default:
928 slow_jcc:
929 /* This actually generates good code for JC, JZ and JS. */
930 switch (jcc_op) {
931 case JCC_O:
932 cc = gen_prepare_eflags_o(s, reg);
933 break;
934 case JCC_B:
935 cc = gen_prepare_eflags_c(s, reg);
936 break;
937 case JCC_Z:
938 cc = gen_prepare_eflags_z(s, reg);
939 break;
940 case JCC_BE:
941 gen_compute_eflags(s);
942 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
943 .mask = CC_Z | CC_C };
944 break;
945 case JCC_S:
946 cc = gen_prepare_eflags_s(s, reg);
947 break;
948 case JCC_P:
949 cc = gen_prepare_eflags_p(s, reg);
950 break;
951 case JCC_L:
952 gen_compute_eflags(s);
953 if (TCGV_EQUAL(reg, cpu_cc_src)) {
954 reg = cpu_tmp0;
956 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
957 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
958 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
959 .mask = CC_S };
960 break;
961 default:
962 case JCC_LE:
963 gen_compute_eflags(s);
964 if (TCGV_EQUAL(reg, cpu_cc_src)) {
965 reg = cpu_tmp0;
967 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
968 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
969 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
970 .mask = CC_S | CC_Z };
971 break;
973 break;
976 if (inv) {
977 cc.cond = tcg_invert_cond(cc.cond);
979 return cc;
982 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
984 CCPrepare cc = gen_prepare_cc(s, b, reg);
986 if (cc.no_setcond) {
987 if (cc.cond == TCG_COND_EQ) {
988 tcg_gen_xori_tl(reg, cc.reg, 1);
989 } else {
990 tcg_gen_mov_tl(reg, cc.reg);
992 return;
995 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
996 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
997 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
998 tcg_gen_andi_tl(reg, reg, 1);
999 return;
1001 if (cc.mask != -1) {
1002 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1003 cc.reg = reg;
1005 if (cc.use_reg2) {
1006 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1007 } else {
1008 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1012 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1014 gen_setcc1(s, JCC_B << 1, reg);
1017 /* generate a conditional jump to label 'l1' according to jump opcode
1018 value 'b'. In the fast case, T0 is guaranted not to be used. */
1019 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1021 CCPrepare cc = gen_prepare_cc(s, b, cpu_T0);
1023 if (cc.mask != -1) {
1024 tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask);
1025 cc.reg = cpu_T0;
1027 if (cc.use_reg2) {
1028 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1029 } else {
1030 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1034 /* Generate a conditional jump to label 'l1' according to jump opcode
1035 value 'b'. In the fast case, T0 is guaranted not to be used.
1036 A translation block must end soon. */
1037 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1039 CCPrepare cc = gen_prepare_cc(s, b, cpu_T0);
1041 gen_update_cc_op(s);
1042 if (cc.mask != -1) {
1043 tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask);
1044 cc.reg = cpu_T0;
1046 set_cc_op(s, CC_OP_DYNAMIC);
1047 if (cc.use_reg2) {
1048 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1049 } else {
1050 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1054 /* XXX: does not work with gdbstub "ice" single step - not a
1055 serious problem */
1056 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1058 TCGLabel *l1 = gen_new_label();
1059 TCGLabel *l2 = gen_new_label();
1060 gen_op_jnz_ecx(s->aflag, l1);
1061 gen_set_label(l2);
1062 gen_jmp_tb(s, next_eip, 1);
1063 gen_set_label(l1);
1064 return l2;
1067 static inline void gen_stos(DisasContext *s, TCGMemOp ot)
1069 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
1070 gen_string_movl_A0_EDI(s);
1071 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1072 gen_op_movl_T0_Dshift(ot);
1073 gen_op_add_reg_T0(s->aflag, R_EDI);
1076 static inline void gen_lods(DisasContext *s, TCGMemOp ot)
1078 gen_string_movl_A0_ESI(s);
1079 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1080 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
1081 gen_op_movl_T0_Dshift(ot);
1082 gen_op_add_reg_T0(s->aflag, R_ESI);
1085 static inline void gen_scas(DisasContext *s, TCGMemOp ot)
1087 gen_string_movl_A0_EDI(s);
1088 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
1089 gen_op(s, OP_CMPL, ot, R_EAX);
1090 gen_op_movl_T0_Dshift(ot);
1091 gen_op_add_reg_T0(s->aflag, R_EDI);
1094 static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
1096 gen_string_movl_A0_EDI(s);
1097 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
1098 gen_string_movl_A0_ESI(s);
1099 gen_op(s, OP_CMPL, ot, OR_TMP0);
1100 gen_op_movl_T0_Dshift(ot);
1101 gen_op_add_reg_T0(s->aflag, R_ESI);
1102 gen_op_add_reg_T0(s->aflag, R_EDI);
1105 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1107 if (s->flags & HF_IOBPT_MASK) {
1108 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1109 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1111 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1112 tcg_temp_free_i32(t_size);
1113 tcg_temp_free(t_next);
1118 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
1120 if (s->base.tb->cflags & CF_USE_ICOUNT) {
1121 gen_io_start();
1123 gen_string_movl_A0_EDI(s);
1124 /* Note: we must do this dummy write first to be restartable in
1125 case of page fault. */
1126 tcg_gen_movi_tl(cpu_T0, 0);
1127 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1128 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1129 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1130 gen_helper_in_func(ot, cpu_T0, cpu_tmp2_i32);
1131 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1132 gen_op_movl_T0_Dshift(ot);
1133 gen_op_add_reg_T0(s->aflag, R_EDI);
1134 gen_bpt_io(s, cpu_tmp2_i32, ot);
1135 if (s->base.tb->cflags & CF_USE_ICOUNT) {
1136 gen_io_end();
1140 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
1142 if (s->base.tb->cflags & CF_USE_ICOUNT) {
1143 gen_io_start();
1145 gen_string_movl_A0_ESI(s);
1146 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1148 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1149 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1150 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T0);
1151 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1152 gen_op_movl_T0_Dshift(ot);
1153 gen_op_add_reg_T0(s->aflag, R_ESI);
1154 gen_bpt_io(s, cpu_tmp2_i32, ot);
1155 if (s->base.tb->cflags & CF_USE_ICOUNT) {
1156 gen_io_end();
1160 /* same method as Valgrind : we generate jumps to current or next
1161 instruction */
1162 #define GEN_REPZ(op) \
1163 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1164 target_ulong cur_eip, target_ulong next_eip) \
1166 TCGLabel *l2; \
1167 gen_update_cc_op(s); \
1168 l2 = gen_jz_ecx_string(s, next_eip); \
1169 gen_ ## op(s, ot); \
1170 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1171 /* a loop would cause two single step exceptions if ECX = 1 \
1172 before rep string_insn */ \
1173 if (s->repz_opt) \
1174 gen_op_jz_ecx(s->aflag, l2); \
1175 gen_jmp(s, cur_eip); \
1178 #define GEN_REPZ2(op) \
1179 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1180 target_ulong cur_eip, \
1181 target_ulong next_eip, \
1182 int nz) \
1184 TCGLabel *l2; \
1185 gen_update_cc_op(s); \
1186 l2 = gen_jz_ecx_string(s, next_eip); \
1187 gen_ ## op(s, ot); \
1188 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1189 gen_update_cc_op(s); \
1190 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1191 if (s->repz_opt) \
1192 gen_op_jz_ecx(s->aflag, l2); \
1193 gen_jmp(s, cur_eip); \
1196 GEN_REPZ(movs)
1197 GEN_REPZ(stos)
1198 GEN_REPZ(lods)
1199 GEN_REPZ(ins)
1200 GEN_REPZ(outs)
1201 GEN_REPZ2(scas)
1202 GEN_REPZ2(cmps)
1204 static void gen_helper_fp_arith_ST0_FT0(int op)
1206 switch (op) {
1207 case 0:
1208 gen_helper_fadd_ST0_FT0(cpu_env);
1209 break;
1210 case 1:
1211 gen_helper_fmul_ST0_FT0(cpu_env);
1212 break;
1213 case 2:
1214 gen_helper_fcom_ST0_FT0(cpu_env);
1215 break;
1216 case 3:
1217 gen_helper_fcom_ST0_FT0(cpu_env);
1218 break;
1219 case 4:
1220 gen_helper_fsub_ST0_FT0(cpu_env);
1221 break;
1222 case 5:
1223 gen_helper_fsubr_ST0_FT0(cpu_env);
1224 break;
1225 case 6:
1226 gen_helper_fdiv_ST0_FT0(cpu_env);
1227 break;
1228 case 7:
1229 gen_helper_fdivr_ST0_FT0(cpu_env);
1230 break;
1234 /* NOTE the exception in "r" op ordering */
1235 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1237 TCGv_i32 tmp = tcg_const_i32(opreg);
1238 switch (op) {
1239 case 0:
1240 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1241 break;
1242 case 1:
1243 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1244 break;
1245 case 4:
1246 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1247 break;
1248 case 5:
1249 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1250 break;
1251 case 6:
1252 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1253 break;
1254 case 7:
1255 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1256 break;
1260 /* if d == OR_TMP0, it means memory operand (address in A0) */
1261 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
1263 if (d != OR_TMP0) {
1264 gen_op_mov_v_reg(ot, cpu_T0, d);
1265 } else if (!(s1->prefix & PREFIX_LOCK)) {
1266 gen_op_ld_v(s1, ot, cpu_T0, cpu_A0);
1268 switch(op) {
1269 case OP_ADCL:
1270 gen_compute_eflags_c(s1, cpu_tmp4);
1271 if (s1->prefix & PREFIX_LOCK) {
1272 tcg_gen_add_tl(cpu_T0, cpu_tmp4, cpu_T1);
1273 tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
1274 s1->mem_index, ot | MO_LE);
1275 } else {
1276 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
1277 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_tmp4);
1278 gen_op_st_rm_T0_A0(s1, ot, d);
1280 gen_op_update3_cc(cpu_tmp4);
1281 set_cc_op(s1, CC_OP_ADCB + ot);
1282 break;
1283 case OP_SBBL:
1284 gen_compute_eflags_c(s1, cpu_tmp4);
1285 if (s1->prefix & PREFIX_LOCK) {
1286 tcg_gen_add_tl(cpu_T0, cpu_T1, cpu_tmp4);
1287 tcg_gen_neg_tl(cpu_T0, cpu_T0);
1288 tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
1289 s1->mem_index, ot | MO_LE);
1290 } else {
1291 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1);
1292 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_tmp4);
1293 gen_op_st_rm_T0_A0(s1, ot, d);
1295 gen_op_update3_cc(cpu_tmp4);
1296 set_cc_op(s1, CC_OP_SBBB + ot);
1297 break;
1298 case OP_ADDL:
1299 if (s1->prefix & PREFIX_LOCK) {
1300 tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T1,
1301 s1->mem_index, ot | MO_LE);
1302 } else {
1303 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
1304 gen_op_st_rm_T0_A0(s1, ot, d);
1306 gen_op_update2_cc();
1307 set_cc_op(s1, CC_OP_ADDB + ot);
1308 break;
1309 case OP_SUBL:
1310 if (s1->prefix & PREFIX_LOCK) {
1311 tcg_gen_neg_tl(cpu_T0, cpu_T1);
1312 tcg_gen_atomic_fetch_add_tl(cpu_cc_srcT, cpu_A0, cpu_T0,
1313 s1->mem_index, ot | MO_LE);
1314 tcg_gen_sub_tl(cpu_T0, cpu_cc_srcT, cpu_T1);
1315 } else {
1316 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0);
1317 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1);
1318 gen_op_st_rm_T0_A0(s1, ot, d);
1320 gen_op_update2_cc();
1321 set_cc_op(s1, CC_OP_SUBB + ot);
1322 break;
1323 default:
1324 case OP_ANDL:
1325 if (s1->prefix & PREFIX_LOCK) {
1326 tcg_gen_atomic_and_fetch_tl(cpu_T0, cpu_A0, cpu_T1,
1327 s1->mem_index, ot | MO_LE);
1328 } else {
1329 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
1330 gen_op_st_rm_T0_A0(s1, ot, d);
1332 gen_op_update1_cc();
1333 set_cc_op(s1, CC_OP_LOGICB + ot);
1334 break;
1335 case OP_ORL:
1336 if (s1->prefix & PREFIX_LOCK) {
1337 tcg_gen_atomic_or_fetch_tl(cpu_T0, cpu_A0, cpu_T1,
1338 s1->mem_index, ot | MO_LE);
1339 } else {
1340 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1);
1341 gen_op_st_rm_T0_A0(s1, ot, d);
1343 gen_op_update1_cc();
1344 set_cc_op(s1, CC_OP_LOGICB + ot);
1345 break;
1346 case OP_XORL:
1347 if (s1->prefix & PREFIX_LOCK) {
1348 tcg_gen_atomic_xor_fetch_tl(cpu_T0, cpu_A0, cpu_T1,
1349 s1->mem_index, ot | MO_LE);
1350 } else {
1351 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_T1);
1352 gen_op_st_rm_T0_A0(s1, ot, d);
1354 gen_op_update1_cc();
1355 set_cc_op(s1, CC_OP_LOGICB + ot);
1356 break;
1357 case OP_CMPL:
1358 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
1359 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0);
1360 tcg_gen_sub_tl(cpu_cc_dst, cpu_T0, cpu_T1);
1361 set_cc_op(s1, CC_OP_SUBB + ot);
1362 break;
1366 /* if d == OR_TMP0, it means memory operand (address in A0) */
1367 static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
1369 if (s1->prefix & PREFIX_LOCK) {
1370 tcg_gen_movi_tl(cpu_T0, c > 0 ? 1 : -1);
1371 tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
1372 s1->mem_index, ot | MO_LE);
1373 } else {
1374 if (d != OR_TMP0) {
1375 gen_op_mov_v_reg(ot, cpu_T0, d);
1376 } else {
1377 gen_op_ld_v(s1, ot, cpu_T0, cpu_A0);
1379 tcg_gen_addi_tl(cpu_T0, cpu_T0, (c > 0 ? 1 : -1));
1380 gen_op_st_rm_T0_A0(s1, ot, d);
1383 gen_compute_eflags_c(s1, cpu_cc_src);
1384 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
1385 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1388 static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
1389 TCGv shm1, TCGv count, bool is_right)
1391 TCGv_i32 z32, s32, oldop;
1392 TCGv z_tl;
1394 /* Store the results into the CC variables. If we know that the
1395 variable must be dead, store unconditionally. Otherwise we'll
1396 need to not disrupt the current contents. */
1397 z_tl = tcg_const_tl(0);
1398 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1399 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1400 result, cpu_cc_dst);
1401 } else {
1402 tcg_gen_mov_tl(cpu_cc_dst, result);
1404 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1405 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1406 shm1, cpu_cc_src);
1407 } else {
1408 tcg_gen_mov_tl(cpu_cc_src, shm1);
1410 tcg_temp_free(z_tl);
1412 /* Get the two potential CC_OP values into temporaries. */
1413 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1414 if (s->cc_op == CC_OP_DYNAMIC) {
1415 oldop = cpu_cc_op;
1416 } else {
1417 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1418 oldop = cpu_tmp3_i32;
1421 /* Conditionally store the CC_OP value. */
1422 z32 = tcg_const_i32(0);
1423 s32 = tcg_temp_new_i32();
1424 tcg_gen_trunc_tl_i32(s32, count);
1425 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1426 tcg_temp_free_i32(z32);
1427 tcg_temp_free_i32(s32);
1429 /* The CC_OP value is no longer predictable. */
1430 set_cc_op(s, CC_OP_DYNAMIC);
1433 static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1434 int is_right, int is_arith)
1436 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1438 /* load */
1439 if (op1 == OR_TMP0) {
1440 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1441 } else {
1442 gen_op_mov_v_reg(ot, cpu_T0, op1);
1445 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1446 tcg_gen_subi_tl(cpu_tmp0, cpu_T1, 1);
1448 if (is_right) {
1449 if (is_arith) {
1450 gen_exts(ot, cpu_T0);
1451 tcg_gen_sar_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1452 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
1453 } else {
1454 gen_extu(ot, cpu_T0);
1455 tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1456 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
1458 } else {
1459 tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1460 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
1463 /* store */
1464 gen_op_st_rm_T0_A0(s, ot, op1);
1466 gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, cpu_T1, is_right);
1469 static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1470 int is_right, int is_arith)
1472 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1474 /* load */
1475 if (op1 == OR_TMP0)
1476 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1477 else
1478 gen_op_mov_v_reg(ot, cpu_T0, op1);
1480 op2 &= mask;
1481 if (op2 != 0) {
1482 if (is_right) {
1483 if (is_arith) {
1484 gen_exts(ot, cpu_T0);
1485 tcg_gen_sari_tl(cpu_tmp4, cpu_T0, op2 - 1);
1486 tcg_gen_sari_tl(cpu_T0, cpu_T0, op2);
1487 } else {
1488 gen_extu(ot, cpu_T0);
1489 tcg_gen_shri_tl(cpu_tmp4, cpu_T0, op2 - 1);
1490 tcg_gen_shri_tl(cpu_T0, cpu_T0, op2);
1492 } else {
1493 tcg_gen_shli_tl(cpu_tmp4, cpu_T0, op2 - 1);
1494 tcg_gen_shli_tl(cpu_T0, cpu_T0, op2);
1498 /* store */
1499 gen_op_st_rm_T0_A0(s, ot, op1);
1501 /* update eflags if non zero shift */
1502 if (op2 != 0) {
1503 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1504 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
1505 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1509 static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
1511 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1512 TCGv_i32 t0, t1;
1514 /* load */
1515 if (op1 == OR_TMP0) {
1516 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1517 } else {
1518 gen_op_mov_v_reg(ot, cpu_T0, op1);
1521 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1523 switch (ot) {
1524 case MO_8:
1525 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1526 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
1527 tcg_gen_muli_tl(cpu_T0, cpu_T0, 0x01010101);
1528 goto do_long;
1529 case MO_16:
1530 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1531 tcg_gen_deposit_tl(cpu_T0, cpu_T0, cpu_T0, 16, 16);
1532 goto do_long;
1533 do_long:
1534 #ifdef TARGET_X86_64
1535 case MO_32:
1536 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
1537 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
1538 if (is_right) {
1539 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1540 } else {
1541 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1543 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
1544 break;
1545 #endif
1546 default:
1547 if (is_right) {
1548 tcg_gen_rotr_tl(cpu_T0, cpu_T0, cpu_T1);
1549 } else {
1550 tcg_gen_rotl_tl(cpu_T0, cpu_T0, cpu_T1);
1552 break;
1555 /* store */
1556 gen_op_st_rm_T0_A0(s, ot, op1);
1558 /* We'll need the flags computed into CC_SRC. */
1559 gen_compute_eflags(s);
1561 /* The value that was "rotated out" is now present at the other end
1562 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1563 since we've computed the flags into CC_SRC, these variables are
1564 currently dead. */
1565 if (is_right) {
1566 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1);
1567 tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask);
1568 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1569 } else {
1570 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask);
1571 tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1);
1573 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1574 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1576 /* Now conditionally store the new CC_OP value. If the shift count
1577 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1578 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1579 exactly as we computed above. */
1580 t0 = tcg_const_i32(0);
1581 t1 = tcg_temp_new_i32();
1582 tcg_gen_trunc_tl_i32(t1, cpu_T1);
1583 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1584 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1585 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1586 cpu_tmp2_i32, cpu_tmp3_i32);
1587 tcg_temp_free_i32(t0);
1588 tcg_temp_free_i32(t1);
1590 /* The CC_OP value is no longer predictable. */
1591 set_cc_op(s, CC_OP_DYNAMIC);
1594 static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1595 int is_right)
1597 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1598 int shift;
1600 /* load */
1601 if (op1 == OR_TMP0) {
1602 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1603 } else {
1604 gen_op_mov_v_reg(ot, cpu_T0, op1);
1607 op2 &= mask;
1608 if (op2 != 0) {
1609 switch (ot) {
1610 #ifdef TARGET_X86_64
1611 case MO_32:
1612 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
1613 if (is_right) {
1614 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1615 } else {
1616 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1618 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
1619 break;
1620 #endif
1621 default:
1622 if (is_right) {
1623 tcg_gen_rotri_tl(cpu_T0, cpu_T0, op2);
1624 } else {
1625 tcg_gen_rotli_tl(cpu_T0, cpu_T0, op2);
1627 break;
1628 case MO_8:
1629 mask = 7;
1630 goto do_shifts;
1631 case MO_16:
1632 mask = 15;
1633 do_shifts:
1634 shift = op2 & mask;
1635 if (is_right) {
1636 shift = mask + 1 - shift;
1638 gen_extu(ot, cpu_T0);
1639 tcg_gen_shli_tl(cpu_tmp0, cpu_T0, shift);
1640 tcg_gen_shri_tl(cpu_T0, cpu_T0, mask + 1 - shift);
1641 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
1642 break;
1646 /* store */
1647 gen_op_st_rm_T0_A0(s, ot, op1);
1649 if (op2 != 0) {
1650 /* Compute the flags into CC_SRC. */
1651 gen_compute_eflags(s);
1653 /* The value that was "rotated out" is now present at the other end
1654 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1655 since we've computed the flags into CC_SRC, these variables are
1656 currently dead. */
1657 if (is_right) {
1658 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1);
1659 tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask);
1660 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1661 } else {
1662 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask);
1663 tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1);
1665 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1666 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1667 set_cc_op(s, CC_OP_ADCOX);
1671 /* XXX: add faster immediate = 1 case */
1672 static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1673 int is_right)
1675 gen_compute_eflags(s);
1676 assert(s->cc_op == CC_OP_EFLAGS);
1678 /* load */
1679 if (op1 == OR_TMP0)
1680 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1681 else
1682 gen_op_mov_v_reg(ot, cpu_T0, op1);
1684 if (is_right) {
1685 switch (ot) {
1686 case MO_8:
1687 gen_helper_rcrb(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1688 break;
1689 case MO_16:
1690 gen_helper_rcrw(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1691 break;
1692 case MO_32:
1693 gen_helper_rcrl(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1694 break;
1695 #ifdef TARGET_X86_64
1696 case MO_64:
1697 gen_helper_rcrq(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1698 break;
1699 #endif
1700 default:
1701 tcg_abort();
1703 } else {
1704 switch (ot) {
1705 case MO_8:
1706 gen_helper_rclb(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1707 break;
1708 case MO_16:
1709 gen_helper_rclw(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1710 break;
1711 case MO_32:
1712 gen_helper_rcll(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1713 break;
1714 #ifdef TARGET_X86_64
1715 case MO_64:
1716 gen_helper_rclq(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1717 break;
1718 #endif
1719 default:
1720 tcg_abort();
1723 /* store */
1724 gen_op_st_rm_T0_A0(s, ot, op1);
1727 /* XXX: add faster immediate case */
1728 static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1729 bool is_right, TCGv count_in)
1731 target_ulong mask = (ot == MO_64 ? 63 : 31);
1732 TCGv count;
1734 /* load */
1735 if (op1 == OR_TMP0) {
1736 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1737 } else {
1738 gen_op_mov_v_reg(ot, cpu_T0, op1);
1741 count = tcg_temp_new();
1742 tcg_gen_andi_tl(count, count_in, mask);
1744 switch (ot) {
1745 case MO_16:
1746 /* Note: we implement the Intel behaviour for shift count > 16.
1747 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1748 portion by constructing it as a 32-bit value. */
1749 if (is_right) {
1750 tcg_gen_deposit_tl(cpu_tmp0, cpu_T0, cpu_T1, 16, 16);
1751 tcg_gen_mov_tl(cpu_T1, cpu_T0);
1752 tcg_gen_mov_tl(cpu_T0, cpu_tmp0);
1753 } else {
1754 tcg_gen_deposit_tl(cpu_T1, cpu_T0, cpu_T1, 16, 16);
1756 /* FALLTHRU */
1757 #ifdef TARGET_X86_64
1758 case MO_32:
1759 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1760 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1761 if (is_right) {
1762 tcg_gen_concat_tl_i64(cpu_T0, cpu_T0, cpu_T1);
1763 tcg_gen_shr_i64(cpu_tmp0, cpu_T0, cpu_tmp0);
1764 tcg_gen_shr_i64(cpu_T0, cpu_T0, count);
1765 } else {
1766 tcg_gen_concat_tl_i64(cpu_T0, cpu_T1, cpu_T0);
1767 tcg_gen_shl_i64(cpu_tmp0, cpu_T0, cpu_tmp0);
1768 tcg_gen_shl_i64(cpu_T0, cpu_T0, count);
1769 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1770 tcg_gen_shri_i64(cpu_T0, cpu_T0, 32);
1772 break;
1773 #endif
1774 default:
1775 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1776 if (is_right) {
1777 tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1779 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1780 tcg_gen_shr_tl(cpu_T0, cpu_T0, count);
1781 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_tmp4);
1782 } else {
1783 tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1784 if (ot == MO_16) {
1785 /* Only needed if count > 16, for Intel behaviour. */
1786 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1787 tcg_gen_shr_tl(cpu_tmp4, cpu_T1, cpu_tmp4);
1788 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1791 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1792 tcg_gen_shl_tl(cpu_T0, cpu_T0, count);
1793 tcg_gen_shr_tl(cpu_T1, cpu_T1, cpu_tmp4);
1795 tcg_gen_movi_tl(cpu_tmp4, 0);
1796 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T1, count, cpu_tmp4,
1797 cpu_tmp4, cpu_T1);
1798 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1);
1799 break;
1802 /* store */
1803 gen_op_st_rm_T0_A0(s, ot, op1);
1805 gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, count, is_right);
1806 tcg_temp_free(count);
1809 static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
1811 if (s != OR_TMP1)
1812 gen_op_mov_v_reg(ot, cpu_T1, s);
1813 switch(op) {
1814 case OP_ROL:
1815 gen_rot_rm_T1(s1, ot, d, 0);
1816 break;
1817 case OP_ROR:
1818 gen_rot_rm_T1(s1, ot, d, 1);
1819 break;
1820 case OP_SHL:
1821 case OP_SHL1:
1822 gen_shift_rm_T1(s1, ot, d, 0, 0);
1823 break;
1824 case OP_SHR:
1825 gen_shift_rm_T1(s1, ot, d, 1, 0);
1826 break;
1827 case OP_SAR:
1828 gen_shift_rm_T1(s1, ot, d, 1, 1);
1829 break;
1830 case OP_RCL:
1831 gen_rotc_rm_T1(s1, ot, d, 0);
1832 break;
1833 case OP_RCR:
1834 gen_rotc_rm_T1(s1, ot, d, 1);
1835 break;
1839 static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
1841 switch(op) {
1842 case OP_ROL:
1843 gen_rot_rm_im(s1, ot, d, c, 0);
1844 break;
1845 case OP_ROR:
1846 gen_rot_rm_im(s1, ot, d, c, 1);
1847 break;
1848 case OP_SHL:
1849 case OP_SHL1:
1850 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1851 break;
1852 case OP_SHR:
1853 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1854 break;
1855 case OP_SAR:
1856 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1857 break;
1858 default:
1859 /* currently not optimized */
1860 tcg_gen_movi_tl(cpu_T1, c);
1861 gen_shift(s1, op, ot, d, OR_TMP1);
1862 break;
1866 /* Decompose an address. */
1868 typedef struct AddressParts {
1869 int def_seg;
1870 int base;
1871 int index;
1872 int scale;
1873 target_long disp;
1874 } AddressParts;
1876 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
1877 int modrm)
1879 int def_seg, base, index, scale, mod, rm;
1880 target_long disp;
1881 bool havesib;
1883 def_seg = R_DS;
1884 index = -1;
1885 scale = 0;
1886 disp = 0;
1888 mod = (modrm >> 6) & 3;
1889 rm = modrm & 7;
1890 base = rm | REX_B(s);
1892 if (mod == 3) {
1893 /* Normally filtered out earlier, but including this path
1894 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
1895 goto done;
1898 switch (s->aflag) {
1899 case MO_64:
1900 case MO_32:
1901 havesib = 0;
1902 if (rm == 4) {
1903 int code = cpu_ldub_code(env, s->pc++);
1904 scale = (code >> 6) & 3;
1905 index = ((code >> 3) & 7) | REX_X(s);
1906 if (index == 4) {
1907 index = -1; /* no index */
1909 base = (code & 7) | REX_B(s);
1910 havesib = 1;
1913 switch (mod) {
1914 case 0:
1915 if ((base & 7) == 5) {
1916 base = -1;
1917 disp = (int32_t)cpu_ldl_code(env, s->pc);
1918 s->pc += 4;
1919 if (CODE64(s) && !havesib) {
1920 base = -2;
1921 disp += s->pc + s->rip_offset;
1924 break;
1925 case 1:
1926 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1927 break;
1928 default:
1929 case 2:
1930 disp = (int32_t)cpu_ldl_code(env, s->pc);
1931 s->pc += 4;
1932 break;
1935 /* For correct popl handling with esp. */
1936 if (base == R_ESP && s->popl_esp_hack) {
1937 disp += s->popl_esp_hack;
1939 if (base == R_EBP || base == R_ESP) {
1940 def_seg = R_SS;
1942 break;
1944 case MO_16:
1945 if (mod == 0) {
1946 if (rm == 6) {
1947 base = -1;
1948 disp = cpu_lduw_code(env, s->pc);
1949 s->pc += 2;
1950 break;
1952 } else if (mod == 1) {
1953 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1954 } else {
1955 disp = (int16_t)cpu_lduw_code(env, s->pc);
1956 s->pc += 2;
1959 switch (rm) {
1960 case 0:
1961 base = R_EBX;
1962 index = R_ESI;
1963 break;
1964 case 1:
1965 base = R_EBX;
1966 index = R_EDI;
1967 break;
1968 case 2:
1969 base = R_EBP;
1970 index = R_ESI;
1971 def_seg = R_SS;
1972 break;
1973 case 3:
1974 base = R_EBP;
1975 index = R_EDI;
1976 def_seg = R_SS;
1977 break;
1978 case 4:
1979 base = R_ESI;
1980 break;
1981 case 5:
1982 base = R_EDI;
1983 break;
1984 case 6:
1985 base = R_EBP;
1986 def_seg = R_SS;
1987 break;
1988 default:
1989 case 7:
1990 base = R_EBX;
1991 break;
1993 break;
1995 default:
1996 tcg_abort();
1999 done:
2000 return (AddressParts){ def_seg, base, index, scale, disp };
2003 /* Compute the address, with a minimum number of TCG ops. */
2004 static TCGv gen_lea_modrm_1(AddressParts a)
2006 TCGv ea;
2008 TCGV_UNUSED(ea);
2009 if (a.index >= 0) {
2010 if (a.scale == 0) {
2011 ea = cpu_regs[a.index];
2012 } else {
2013 tcg_gen_shli_tl(cpu_A0, cpu_regs[a.index], a.scale);
2014 ea = cpu_A0;
2016 if (a.base >= 0) {
2017 tcg_gen_add_tl(cpu_A0, ea, cpu_regs[a.base]);
2018 ea = cpu_A0;
2020 } else if (a.base >= 0) {
2021 ea = cpu_regs[a.base];
2023 if (TCGV_IS_UNUSED(ea)) {
2024 tcg_gen_movi_tl(cpu_A0, a.disp);
2025 ea = cpu_A0;
2026 } else if (a.disp != 0) {
2027 tcg_gen_addi_tl(cpu_A0, ea, a.disp);
2028 ea = cpu_A0;
2031 return ea;
2034 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2036 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2037 TCGv ea = gen_lea_modrm_1(a);
2038 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2041 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2043 (void)gen_lea_modrm_0(env, s, modrm);
2046 /* Used for BNDCL, BNDCU, BNDCN. */
2047 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2048 TCGCond cond, TCGv_i64 bndv)
2050 TCGv ea = gen_lea_modrm_1(gen_lea_modrm_0(env, s, modrm));
2052 tcg_gen_extu_tl_i64(cpu_tmp1_i64, ea);
2053 if (!CODE64(s)) {
2054 tcg_gen_ext32u_i64(cpu_tmp1_i64, cpu_tmp1_i64);
2056 tcg_gen_setcond_i64(cond, cpu_tmp1_i64, cpu_tmp1_i64, bndv);
2057 tcg_gen_extrl_i64_i32(cpu_tmp2_i32, cpu_tmp1_i64);
2058 gen_helper_bndck(cpu_env, cpu_tmp2_i32);
2061 /* used for LEA and MOV AX, mem */
2062 static void gen_add_A0_ds_seg(DisasContext *s)
2064 gen_lea_v_seg(s, s->aflag, cpu_A0, R_DS, s->override);
2067 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2068 OR_TMP0 */
2069 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2070 TCGMemOp ot, int reg, int is_store)
2072 int mod, rm;
2074 mod = (modrm >> 6) & 3;
2075 rm = (modrm & 7) | REX_B(s);
2076 if (mod == 3) {
2077 if (is_store) {
2078 if (reg != OR_TMP0)
2079 gen_op_mov_v_reg(ot, cpu_T0, reg);
2080 gen_op_mov_reg_v(ot, rm, cpu_T0);
2081 } else {
2082 gen_op_mov_v_reg(ot, cpu_T0, rm);
2083 if (reg != OR_TMP0)
2084 gen_op_mov_reg_v(ot, reg, cpu_T0);
2086 } else {
2087 gen_lea_modrm(env, s, modrm);
2088 if (is_store) {
2089 if (reg != OR_TMP0)
2090 gen_op_mov_v_reg(ot, cpu_T0, reg);
2091 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
2092 } else {
2093 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
2094 if (reg != OR_TMP0)
2095 gen_op_mov_reg_v(ot, reg, cpu_T0);
2100 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
2102 uint32_t ret;
2104 switch (ot) {
2105 case MO_8:
2106 ret = cpu_ldub_code(env, s->pc);
2107 s->pc++;
2108 break;
2109 case MO_16:
2110 ret = cpu_lduw_code(env, s->pc);
2111 s->pc += 2;
2112 break;
2113 case MO_32:
2114 #ifdef TARGET_X86_64
2115 case MO_64:
2116 #endif
2117 ret = cpu_ldl_code(env, s->pc);
2118 s->pc += 4;
2119 break;
2120 default:
2121 tcg_abort();
2123 return ret;
2126 static inline int insn_const_size(TCGMemOp ot)
2128 if (ot <= MO_32) {
2129 return 1 << ot;
2130 } else {
2131 return 4;
2135 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2137 #ifndef CONFIG_USER_ONLY
2138 return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
2139 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2140 #else
2141 return true;
2142 #endif
2145 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2147 target_ulong pc = s->cs_base + eip;
2149 if (use_goto_tb(s, pc)) {
2150 /* jump to same page: we can use a direct jump */
2151 tcg_gen_goto_tb(tb_num);
2152 gen_jmp_im(eip);
2153 tcg_gen_exit_tb((uintptr_t)s->base.tb + tb_num);
2154 s->base.is_jmp = DISAS_NORETURN;
2155 } else {
2156 /* jump to another page */
2157 gen_jmp_im(eip);
2158 gen_jr(s, cpu_tmp0);
2162 static inline void gen_jcc(DisasContext *s, int b,
2163 target_ulong val, target_ulong next_eip)
2165 TCGLabel *l1, *l2;
2167 if (s->jmp_opt) {
2168 l1 = gen_new_label();
2169 gen_jcc1(s, b, l1);
2171 gen_goto_tb(s, 0, next_eip);
2173 gen_set_label(l1);
2174 gen_goto_tb(s, 1, val);
2175 } else {
2176 l1 = gen_new_label();
2177 l2 = gen_new_label();
2178 gen_jcc1(s, b, l1);
2180 gen_jmp_im(next_eip);
2181 tcg_gen_br(l2);
2183 gen_set_label(l1);
2184 gen_jmp_im(val);
2185 gen_set_label(l2);
2186 gen_eob(s);
2190 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
2191 int modrm, int reg)
2193 CCPrepare cc;
2195 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2197 cc = gen_prepare_cc(s, b, cpu_T1);
2198 if (cc.mask != -1) {
2199 TCGv t0 = tcg_temp_new();
2200 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2201 cc.reg = t0;
2203 if (!cc.use_reg2) {
2204 cc.reg2 = tcg_const_tl(cc.imm);
2207 tcg_gen_movcond_tl(cc.cond, cpu_T0, cc.reg, cc.reg2,
2208 cpu_T0, cpu_regs[reg]);
2209 gen_op_mov_reg_v(ot, reg, cpu_T0);
2211 if (cc.mask != -1) {
2212 tcg_temp_free(cc.reg);
2214 if (!cc.use_reg2) {
2215 tcg_temp_free(cc.reg2);
2219 static inline void gen_op_movl_T0_seg(int seg_reg)
2221 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
2222 offsetof(CPUX86State,segs[seg_reg].selector));
2225 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2227 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
2228 tcg_gen_st32_tl(cpu_T0, cpu_env,
2229 offsetof(CPUX86State,segs[seg_reg].selector));
2230 tcg_gen_shli_tl(cpu_seg_base[seg_reg], cpu_T0, 4);
2233 /* move T0 to seg_reg and compute if the CPU state may change. Never
2234 call this function with seg_reg == R_CS */
2235 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
2237 if (s->pe && !s->vm86) {
2238 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
2239 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
2240 /* abort translation because the addseg value may change or
2241 because ss32 may change. For R_SS, translation must always
2242 stop as a special handling must be done to disable hardware
2243 interrupts for the next instruction */
2244 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) {
2245 s->base.is_jmp = DISAS_TOO_MANY;
2247 } else {
2248 gen_op_movl_seg_T0_vm(seg_reg);
2249 if (seg_reg == R_SS) {
2250 s->base.is_jmp = DISAS_TOO_MANY;
2255 static inline int svm_is_rep(int prefixes)
2257 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2260 static inline void
2261 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2262 uint32_t type, uint64_t param)
2264 /* no SVM activated; fast case */
2265 if (likely(!(s->flags & HF_SVMI_MASK)))
2266 return;
2267 gen_update_cc_op(s);
2268 gen_jmp_im(pc_start - s->cs_base);
2269 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2270 tcg_const_i64(param));
2273 static inline void
2274 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2276 gen_svm_check_intercept_param(s, pc_start, type, 0);
2279 static inline void gen_stack_update(DisasContext *s, int addend)
2281 gen_op_add_reg_im(mo_stacksize(s), R_ESP, addend);
2284 /* Generate a push. It depends on ss32, addseg and dflag. */
2285 static void gen_push_v(DisasContext *s, TCGv val)
2287 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2288 TCGMemOp a_ot = mo_stacksize(s);
2289 int size = 1 << d_ot;
2290 TCGv new_esp = cpu_A0;
2292 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
2294 if (!CODE64(s)) {
2295 if (s->addseg) {
2296 new_esp = cpu_tmp4;
2297 tcg_gen_mov_tl(new_esp, cpu_A0);
2299 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2302 gen_op_st_v(s, d_ot, val, cpu_A0);
2303 gen_op_mov_reg_v(a_ot, R_ESP, new_esp);
2306 /* two step pop is necessary for precise exceptions */
2307 static TCGMemOp gen_pop_T0(DisasContext *s)
2309 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2311 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2312 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2314 return d_ot;
2317 static inline void gen_pop_update(DisasContext *s, TCGMemOp ot)
2319 gen_stack_update(s, 1 << ot);
2322 static inline void gen_stack_A0(DisasContext *s)
2324 gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2327 static void gen_pusha(DisasContext *s)
2329 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2330 TCGMemOp d_ot = s->dflag;
2331 int size = 1 << d_ot;
2332 int i;
2334 for (i = 0; i < 8; i++) {
2335 tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], (i - 8) * size);
2336 gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
2337 gen_op_st_v(s, d_ot, cpu_regs[7 - i], cpu_A0);
2340 gen_stack_update(s, -8 * size);
2343 static void gen_popa(DisasContext *s)
2345 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2346 TCGMemOp d_ot = s->dflag;
2347 int size = 1 << d_ot;
2348 int i;
2350 for (i = 0; i < 8; i++) {
2351 /* ESP is not reloaded */
2352 if (7 - i == R_ESP) {
2353 continue;
2355 tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], i * size);
2356 gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
2357 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2358 gen_op_mov_reg_v(d_ot, 7 - i, cpu_T0);
2361 gen_stack_update(s, 8 * size);
2364 static void gen_enter(DisasContext *s, int esp_addend, int level)
2366 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2367 TCGMemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
2368 int size = 1 << d_ot;
2370 /* Push BP; compute FrameTemp into T1. */
2371 tcg_gen_subi_tl(cpu_T1, cpu_regs[R_ESP], size);
2372 gen_lea_v_seg(s, a_ot, cpu_T1, R_SS, -1);
2373 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], cpu_A0);
2375 level &= 31;
2376 if (level != 0) {
2377 int i;
2379 /* Copy level-1 pointers from the previous frame. */
2380 for (i = 1; i < level; ++i) {
2381 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_EBP], size * i);
2382 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2383 gen_op_ld_v(s, d_ot, cpu_tmp0, cpu_A0);
2385 tcg_gen_subi_tl(cpu_A0, cpu_T1, size * i);
2386 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2387 gen_op_st_v(s, d_ot, cpu_tmp0, cpu_A0);
2390 /* Push the current FrameTemp as the last level. */
2391 tcg_gen_subi_tl(cpu_A0, cpu_T1, size * level);
2392 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2393 gen_op_st_v(s, d_ot, cpu_T1, cpu_A0);
2396 /* Copy the FrameTemp value to EBP. */
2397 gen_op_mov_reg_v(a_ot, R_EBP, cpu_T1);
2399 /* Compute the final value of ESP. */
2400 tcg_gen_subi_tl(cpu_T1, cpu_T1, esp_addend + size * level);
2401 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2404 static void gen_leave(DisasContext *s)
2406 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2407 TCGMemOp a_ot = mo_stacksize(s);
2409 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2410 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2412 tcg_gen_addi_tl(cpu_T1, cpu_regs[R_EBP], 1 << d_ot);
2414 gen_op_mov_reg_v(d_ot, R_EBP, cpu_T0);
2415 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2418 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2420 gen_update_cc_op(s);
2421 gen_jmp_im(cur_eip);
2422 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
2423 s->base.is_jmp = DISAS_NORETURN;
2426 /* Generate #UD for the current instruction. The assumption here is that
2427 the instruction is known, but it isn't allowed in the current cpu mode. */
2428 static void gen_illegal_opcode(DisasContext *s)
2430 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
2433 /* Similarly, except that the assumption here is that we don't decode
2434 the instruction at all -- either a missing opcode, an unimplemented
2435 feature, or just a bogus instruction stream. */
2436 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2438 gen_illegal_opcode(s);
2440 if (qemu_loglevel_mask(LOG_UNIMP)) {
2441 target_ulong pc = s->pc_start, end = s->pc;
2442 qemu_log_lock();
2443 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2444 for (; pc < end; ++pc) {
2445 qemu_log(" %02x", cpu_ldub_code(env, pc));
2447 qemu_log("\n");
2448 qemu_log_unlock();
2452 /* an interrupt is different from an exception because of the
2453 privilege checks */
2454 static void gen_interrupt(DisasContext *s, int intno,
2455 target_ulong cur_eip, target_ulong next_eip)
2457 gen_update_cc_op(s);
2458 gen_jmp_im(cur_eip);
2459 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2460 tcg_const_i32(next_eip - cur_eip));
2461 s->base.is_jmp = DISAS_NORETURN;
2464 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2466 gen_update_cc_op(s);
2467 gen_jmp_im(cur_eip);
2468 gen_helper_debug(cpu_env);
2469 s->base.is_jmp = DISAS_NORETURN;
2472 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2474 if ((s->flags & mask) == 0) {
2475 TCGv_i32 t = tcg_temp_new_i32();
2476 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2477 tcg_gen_ori_i32(t, t, mask);
2478 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2479 tcg_temp_free_i32(t);
2480 s->flags |= mask;
2484 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2486 if (s->flags & mask) {
2487 TCGv_i32 t = tcg_temp_new_i32();
2488 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2489 tcg_gen_andi_i32(t, t, ~mask);
2490 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2491 tcg_temp_free_i32(t);
2492 s->flags &= ~mask;
2496 /* Clear BND registers during legacy branches. */
2497 static void gen_bnd_jmp(DisasContext *s)
2499 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2500 and if the BNDREGs are known to be in use (non-zero) already.
2501 The helper itself will check BNDPRESERVE at runtime. */
2502 if ((s->prefix & PREFIX_REPNZ) == 0
2503 && (s->flags & HF_MPX_EN_MASK) != 0
2504 && (s->flags & HF_MPX_IU_MASK) != 0) {
2505 gen_helper_bnd_jmp(cpu_env);
2509 /* Generate an end of block. Trace exception is also generated if needed.
2510 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.
2511 If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
2512 S->TF. This is used by the syscall/sysret insns. */
2513 static void
2514 do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2516 gen_update_cc_op(s);
2518 /* If several instructions disable interrupts, only the first does it. */
2519 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2520 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2521 } else {
2522 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2525 if (s->base.tb->flags & HF_RF_MASK) {
2526 gen_helper_reset_rf(cpu_env);
2528 if (s->base.singlestep_enabled) {
2529 gen_helper_debug(cpu_env);
2530 } else if (recheck_tf) {
2531 gen_helper_rechecking_single_step(cpu_env);
2532 tcg_gen_exit_tb(0);
2533 } else if (s->tf) {
2534 gen_helper_single_step(cpu_env);
2535 } else if (jr) {
2536 tcg_gen_lookup_and_goto_ptr();
2537 } else {
2538 tcg_gen_exit_tb(0);
2540 s->base.is_jmp = DISAS_NORETURN;
2543 static inline void
2544 gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2546 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2549 /* End of block.
2550 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2551 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2553 gen_eob_worker(s, inhibit, false);
2556 /* End of block, resetting the inhibit irq flag. */
2557 static void gen_eob(DisasContext *s)
2559 gen_eob_worker(s, false, false);
2562 /* Jump to register */
2563 static void gen_jr(DisasContext *s, TCGv dest)
2565 do_gen_eob_worker(s, false, false, true);
2568 /* generate a jump to eip. No segment change must happen before as a
2569 direct call to the next block may occur */
2570 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2572 gen_update_cc_op(s);
2573 set_cc_op(s, CC_OP_DYNAMIC);
2574 if (s->jmp_opt) {
2575 gen_goto_tb(s, tb_num, eip);
2576 } else {
2577 gen_jmp_im(eip);
2578 gen_eob(s);
2582 static void gen_jmp(DisasContext *s, target_ulong eip)
2584 gen_jmp_tb(s, eip, 0);
2587 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2589 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2590 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2593 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2595 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2596 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2599 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2601 int mem_index = s->mem_index;
2602 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2603 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2604 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2605 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2606 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2609 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2611 int mem_index = s->mem_index;
2612 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2613 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2614 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2615 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2616 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2619 static inline void gen_op_movo(int d_offset, int s_offset)
2621 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2622 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2623 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2624 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2627 static inline void gen_op_movq(int d_offset, int s_offset)
2629 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2630 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2633 static inline void gen_op_movl(int d_offset, int s_offset)
2635 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2636 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2639 static inline void gen_op_movq_env_0(int d_offset)
2641 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2642 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2645 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2646 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2647 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2648 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2649 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2650 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2651 TCGv_i32 val);
2652 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2653 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2654 TCGv val);
2656 #define SSE_SPECIAL ((void *)1)
2657 #define SSE_DUMMY ((void *)2)
2659 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2660 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2661 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2663 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2664 /* 3DNow! extensions */
2665 [0x0e] = { SSE_DUMMY }, /* femms */
2666 [0x0f] = { SSE_DUMMY }, /* pf... */
2667 /* pure SSE operations */
2668 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2669 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2670 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2671 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2672 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2673 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2674 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2675 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2677 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2678 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2679 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2680 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2681 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2682 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2683 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2684 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2685 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2686 [0x51] = SSE_FOP(sqrt),
2687 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2688 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2689 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2690 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2691 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2692 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2693 [0x58] = SSE_FOP(add),
2694 [0x59] = SSE_FOP(mul),
2695 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2696 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2697 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2698 [0x5c] = SSE_FOP(sub),
2699 [0x5d] = SSE_FOP(min),
2700 [0x5e] = SSE_FOP(div),
2701 [0x5f] = SSE_FOP(max),
2703 [0xc2] = SSE_FOP(cmpeq),
2704 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2705 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2707 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2708 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2709 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2711 /* MMX ops and their SSE extensions */
2712 [0x60] = MMX_OP2(punpcklbw),
2713 [0x61] = MMX_OP2(punpcklwd),
2714 [0x62] = MMX_OP2(punpckldq),
2715 [0x63] = MMX_OP2(packsswb),
2716 [0x64] = MMX_OP2(pcmpgtb),
2717 [0x65] = MMX_OP2(pcmpgtw),
2718 [0x66] = MMX_OP2(pcmpgtl),
2719 [0x67] = MMX_OP2(packuswb),
2720 [0x68] = MMX_OP2(punpckhbw),
2721 [0x69] = MMX_OP2(punpckhwd),
2722 [0x6a] = MMX_OP2(punpckhdq),
2723 [0x6b] = MMX_OP2(packssdw),
2724 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2725 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2726 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2727 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2728 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2729 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2730 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2731 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2732 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2733 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2734 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2735 [0x74] = MMX_OP2(pcmpeqb),
2736 [0x75] = MMX_OP2(pcmpeqw),
2737 [0x76] = MMX_OP2(pcmpeql),
2738 [0x77] = { SSE_DUMMY }, /* emms */
2739 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2740 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2741 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2742 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2743 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2744 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2745 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2746 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2747 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2748 [0xd1] = MMX_OP2(psrlw),
2749 [0xd2] = MMX_OP2(psrld),
2750 [0xd3] = MMX_OP2(psrlq),
2751 [0xd4] = MMX_OP2(paddq),
2752 [0xd5] = MMX_OP2(pmullw),
2753 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2754 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2755 [0xd8] = MMX_OP2(psubusb),
2756 [0xd9] = MMX_OP2(psubusw),
2757 [0xda] = MMX_OP2(pminub),
2758 [0xdb] = MMX_OP2(pand),
2759 [0xdc] = MMX_OP2(paddusb),
2760 [0xdd] = MMX_OP2(paddusw),
2761 [0xde] = MMX_OP2(pmaxub),
2762 [0xdf] = MMX_OP2(pandn),
2763 [0xe0] = MMX_OP2(pavgb),
2764 [0xe1] = MMX_OP2(psraw),
2765 [0xe2] = MMX_OP2(psrad),
2766 [0xe3] = MMX_OP2(pavgw),
2767 [0xe4] = MMX_OP2(pmulhuw),
2768 [0xe5] = MMX_OP2(pmulhw),
2769 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2770 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2771 [0xe8] = MMX_OP2(psubsb),
2772 [0xe9] = MMX_OP2(psubsw),
2773 [0xea] = MMX_OP2(pminsw),
2774 [0xeb] = MMX_OP2(por),
2775 [0xec] = MMX_OP2(paddsb),
2776 [0xed] = MMX_OP2(paddsw),
2777 [0xee] = MMX_OP2(pmaxsw),
2778 [0xef] = MMX_OP2(pxor),
2779 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2780 [0xf1] = MMX_OP2(psllw),
2781 [0xf2] = MMX_OP2(pslld),
2782 [0xf3] = MMX_OP2(psllq),
2783 [0xf4] = MMX_OP2(pmuludq),
2784 [0xf5] = MMX_OP2(pmaddwd),
2785 [0xf6] = MMX_OP2(psadbw),
2786 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2787 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2788 [0xf8] = MMX_OP2(psubb),
2789 [0xf9] = MMX_OP2(psubw),
2790 [0xfa] = MMX_OP2(psubl),
2791 [0xfb] = MMX_OP2(psubq),
2792 [0xfc] = MMX_OP2(paddb),
2793 [0xfd] = MMX_OP2(paddw),
2794 [0xfe] = MMX_OP2(paddl),
2797 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2798 [0 + 2] = MMX_OP2(psrlw),
2799 [0 + 4] = MMX_OP2(psraw),
2800 [0 + 6] = MMX_OP2(psllw),
2801 [8 + 2] = MMX_OP2(psrld),
2802 [8 + 4] = MMX_OP2(psrad),
2803 [8 + 6] = MMX_OP2(pslld),
2804 [16 + 2] = MMX_OP2(psrlq),
2805 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2806 [16 + 6] = MMX_OP2(psllq),
2807 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2810 static const SSEFunc_0_epi sse_op_table3ai[] = {
2811 gen_helper_cvtsi2ss,
2812 gen_helper_cvtsi2sd
2815 #ifdef TARGET_X86_64
2816 static const SSEFunc_0_epl sse_op_table3aq[] = {
2817 gen_helper_cvtsq2ss,
2818 gen_helper_cvtsq2sd
2820 #endif
2822 static const SSEFunc_i_ep sse_op_table3bi[] = {
2823 gen_helper_cvttss2si,
2824 gen_helper_cvtss2si,
2825 gen_helper_cvttsd2si,
2826 gen_helper_cvtsd2si
2829 #ifdef TARGET_X86_64
2830 static const SSEFunc_l_ep sse_op_table3bq[] = {
2831 gen_helper_cvttss2sq,
2832 gen_helper_cvtss2sq,
2833 gen_helper_cvttsd2sq,
2834 gen_helper_cvtsd2sq
2836 #endif
2838 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2839 SSE_FOP(cmpeq),
2840 SSE_FOP(cmplt),
2841 SSE_FOP(cmple),
2842 SSE_FOP(cmpunord),
2843 SSE_FOP(cmpneq),
2844 SSE_FOP(cmpnlt),
2845 SSE_FOP(cmpnle),
2846 SSE_FOP(cmpord),
2849 static const SSEFunc_0_epp sse_op_table5[256] = {
2850 [0x0c] = gen_helper_pi2fw,
2851 [0x0d] = gen_helper_pi2fd,
2852 [0x1c] = gen_helper_pf2iw,
2853 [0x1d] = gen_helper_pf2id,
2854 [0x8a] = gen_helper_pfnacc,
2855 [0x8e] = gen_helper_pfpnacc,
2856 [0x90] = gen_helper_pfcmpge,
2857 [0x94] = gen_helper_pfmin,
2858 [0x96] = gen_helper_pfrcp,
2859 [0x97] = gen_helper_pfrsqrt,
2860 [0x9a] = gen_helper_pfsub,
2861 [0x9e] = gen_helper_pfadd,
2862 [0xa0] = gen_helper_pfcmpgt,
2863 [0xa4] = gen_helper_pfmax,
2864 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2865 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2866 [0xaa] = gen_helper_pfsubr,
2867 [0xae] = gen_helper_pfacc,
2868 [0xb0] = gen_helper_pfcmpeq,
2869 [0xb4] = gen_helper_pfmul,
2870 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2871 [0xb7] = gen_helper_pmulhrw_mmx,
2872 [0xbb] = gen_helper_pswapd,
2873 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
2876 struct SSEOpHelper_epp {
2877 SSEFunc_0_epp op[2];
2878 uint32_t ext_mask;
2881 struct SSEOpHelper_eppi {
2882 SSEFunc_0_eppi op[2];
2883 uint32_t ext_mask;
2886 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2887 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2888 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
2889 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
2890 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2891 CPUID_EXT_PCLMULQDQ }
2892 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
2894 static const struct SSEOpHelper_epp sse_op_table6[256] = {
2895 [0x00] = SSSE3_OP(pshufb),
2896 [0x01] = SSSE3_OP(phaddw),
2897 [0x02] = SSSE3_OP(phaddd),
2898 [0x03] = SSSE3_OP(phaddsw),
2899 [0x04] = SSSE3_OP(pmaddubsw),
2900 [0x05] = SSSE3_OP(phsubw),
2901 [0x06] = SSSE3_OP(phsubd),
2902 [0x07] = SSSE3_OP(phsubsw),
2903 [0x08] = SSSE3_OP(psignb),
2904 [0x09] = SSSE3_OP(psignw),
2905 [0x0a] = SSSE3_OP(psignd),
2906 [0x0b] = SSSE3_OP(pmulhrsw),
2907 [0x10] = SSE41_OP(pblendvb),
2908 [0x14] = SSE41_OP(blendvps),
2909 [0x15] = SSE41_OP(blendvpd),
2910 [0x17] = SSE41_OP(ptest),
2911 [0x1c] = SSSE3_OP(pabsb),
2912 [0x1d] = SSSE3_OP(pabsw),
2913 [0x1e] = SSSE3_OP(pabsd),
2914 [0x20] = SSE41_OP(pmovsxbw),
2915 [0x21] = SSE41_OP(pmovsxbd),
2916 [0x22] = SSE41_OP(pmovsxbq),
2917 [0x23] = SSE41_OP(pmovsxwd),
2918 [0x24] = SSE41_OP(pmovsxwq),
2919 [0x25] = SSE41_OP(pmovsxdq),
2920 [0x28] = SSE41_OP(pmuldq),
2921 [0x29] = SSE41_OP(pcmpeqq),
2922 [0x2a] = SSE41_SPECIAL, /* movntqda */
2923 [0x2b] = SSE41_OP(packusdw),
2924 [0x30] = SSE41_OP(pmovzxbw),
2925 [0x31] = SSE41_OP(pmovzxbd),
2926 [0x32] = SSE41_OP(pmovzxbq),
2927 [0x33] = SSE41_OP(pmovzxwd),
2928 [0x34] = SSE41_OP(pmovzxwq),
2929 [0x35] = SSE41_OP(pmovzxdq),
2930 [0x37] = SSE42_OP(pcmpgtq),
2931 [0x38] = SSE41_OP(pminsb),
2932 [0x39] = SSE41_OP(pminsd),
2933 [0x3a] = SSE41_OP(pminuw),
2934 [0x3b] = SSE41_OP(pminud),
2935 [0x3c] = SSE41_OP(pmaxsb),
2936 [0x3d] = SSE41_OP(pmaxsd),
2937 [0x3e] = SSE41_OP(pmaxuw),
2938 [0x3f] = SSE41_OP(pmaxud),
2939 [0x40] = SSE41_OP(pmulld),
2940 [0x41] = SSE41_OP(phminposuw),
2941 [0xdb] = AESNI_OP(aesimc),
2942 [0xdc] = AESNI_OP(aesenc),
2943 [0xdd] = AESNI_OP(aesenclast),
2944 [0xde] = AESNI_OP(aesdec),
2945 [0xdf] = AESNI_OP(aesdeclast),
2948 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
2949 [0x08] = SSE41_OP(roundps),
2950 [0x09] = SSE41_OP(roundpd),
2951 [0x0a] = SSE41_OP(roundss),
2952 [0x0b] = SSE41_OP(roundsd),
2953 [0x0c] = SSE41_OP(blendps),
2954 [0x0d] = SSE41_OP(blendpd),
2955 [0x0e] = SSE41_OP(pblendw),
2956 [0x0f] = SSSE3_OP(palignr),
2957 [0x14] = SSE41_SPECIAL, /* pextrb */
2958 [0x15] = SSE41_SPECIAL, /* pextrw */
2959 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
2960 [0x17] = SSE41_SPECIAL, /* extractps */
2961 [0x20] = SSE41_SPECIAL, /* pinsrb */
2962 [0x21] = SSE41_SPECIAL, /* insertps */
2963 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
2964 [0x40] = SSE41_OP(dpps),
2965 [0x41] = SSE41_OP(dppd),
2966 [0x42] = SSE41_OP(mpsadbw),
2967 [0x44] = PCLMULQDQ_OP(pclmulqdq),
2968 [0x60] = SSE42_OP(pcmpestrm),
2969 [0x61] = SSE42_OP(pcmpestri),
2970 [0x62] = SSE42_OP(pcmpistrm),
2971 [0x63] = SSE42_OP(pcmpistri),
2972 [0xdf] = AESNI_OP(aeskeygenassist),
2975 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
2976 target_ulong pc_start, int rex_r)
2978 int b1, op1_offset, op2_offset, is_xmm, val;
2979 int modrm, mod, rm, reg;
2980 SSEFunc_0_epp sse_fn_epp;
2981 SSEFunc_0_eppi sse_fn_eppi;
2982 SSEFunc_0_ppi sse_fn_ppi;
2983 SSEFunc_0_eppt sse_fn_eppt;
2984 TCGMemOp ot;
2986 b &= 0xff;
2987 if (s->prefix & PREFIX_DATA)
2988 b1 = 1;
2989 else if (s->prefix & PREFIX_REPZ)
2990 b1 = 2;
2991 else if (s->prefix & PREFIX_REPNZ)
2992 b1 = 3;
2993 else
2994 b1 = 0;
2995 sse_fn_epp = sse_op_table1[b][b1];
2996 if (!sse_fn_epp) {
2997 goto unknown_op;
2999 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3000 is_xmm = 1;
3001 } else {
3002 if (b1 == 0) {
3003 /* MMX case */
3004 is_xmm = 0;
3005 } else {
3006 is_xmm = 1;
3009 /* simple MMX/SSE operation */
3010 if (s->flags & HF_TS_MASK) {
3011 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3012 return;
3014 if (s->flags & HF_EM_MASK) {
3015 illegal_op:
3016 gen_illegal_opcode(s);
3017 return;
3019 if (is_xmm
3020 && !(s->flags & HF_OSFXSR_MASK)
3021 && ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
3022 goto unknown_op;
3024 if (b == 0x0e) {
3025 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3026 /* If we were fully decoding this we might use illegal_op. */
3027 goto unknown_op;
3029 /* femms */
3030 gen_helper_emms(cpu_env);
3031 return;
3033 if (b == 0x77) {
3034 /* emms */
3035 gen_helper_emms(cpu_env);
3036 return;
3038 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3039 the static cpu state) */
3040 if (!is_xmm) {
3041 gen_helper_enter_mmx(cpu_env);
3044 modrm = cpu_ldub_code(env, s->pc++);
3045 reg = ((modrm >> 3) & 7);
3046 if (is_xmm)
3047 reg |= rex_r;
3048 mod = (modrm >> 6) & 3;
3049 if (sse_fn_epp == SSE_SPECIAL) {
3050 b |= (b1 << 8);
3051 switch(b) {
3052 case 0x0e7: /* movntq */
3053 if (mod == 3) {
3054 goto illegal_op;
3056 gen_lea_modrm(env, s, modrm);
3057 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3058 break;
3059 case 0x1e7: /* movntdq */
3060 case 0x02b: /* movntps */
3061 case 0x12b: /* movntps */
3062 if (mod == 3)
3063 goto illegal_op;
3064 gen_lea_modrm(env, s, modrm);
3065 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3066 break;
3067 case 0x3f0: /* lddqu */
3068 if (mod == 3)
3069 goto illegal_op;
3070 gen_lea_modrm(env, s, modrm);
3071 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3072 break;
3073 case 0x22b: /* movntss */
3074 case 0x32b: /* movntsd */
3075 if (mod == 3)
3076 goto illegal_op;
3077 gen_lea_modrm(env, s, modrm);
3078 if (b1 & 1) {
3079 gen_stq_env_A0(s, offsetof(CPUX86State,
3080 xmm_regs[reg].ZMM_Q(0)));
3081 } else {
3082 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
3083 xmm_regs[reg].ZMM_L(0)));
3084 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3086 break;
3087 case 0x6e: /* movd mm, ea */
3088 #ifdef TARGET_X86_64
3089 if (s->dflag == MO_64) {
3090 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3091 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3092 } else
3093 #endif
3095 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3096 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3097 offsetof(CPUX86State,fpregs[reg].mmx));
3098 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3099 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
3101 break;
3102 case 0x16e: /* movd xmm, ea */
3103 #ifdef TARGET_X86_64
3104 if (s->dflag == MO_64) {
3105 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3106 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3107 offsetof(CPUX86State,xmm_regs[reg]));
3108 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T0);
3109 } else
3110 #endif
3112 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3113 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3114 offsetof(CPUX86State,xmm_regs[reg]));
3115 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3116 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
3118 break;
3119 case 0x6f: /* movq mm, ea */
3120 if (mod != 3) {
3121 gen_lea_modrm(env, s, modrm);
3122 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3123 } else {
3124 rm = (modrm & 7);
3125 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3126 offsetof(CPUX86State,fpregs[rm].mmx));
3127 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3128 offsetof(CPUX86State,fpregs[reg].mmx));
3130 break;
3131 case 0x010: /* movups */
3132 case 0x110: /* movupd */
3133 case 0x028: /* movaps */
3134 case 0x128: /* movapd */
3135 case 0x16f: /* movdqa xmm, ea */
3136 case 0x26f: /* movdqu xmm, ea */
3137 if (mod != 3) {
3138 gen_lea_modrm(env, s, modrm);
3139 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3140 } else {
3141 rm = (modrm & 7) | REX_B(s);
3142 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3143 offsetof(CPUX86State,xmm_regs[rm]));
3145 break;
3146 case 0x210: /* movss xmm, ea */
3147 if (mod != 3) {
3148 gen_lea_modrm(env, s, modrm);
3149 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3150 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3151 tcg_gen_movi_tl(cpu_T0, 0);
3152 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3153 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3154 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3155 } else {
3156 rm = (modrm & 7) | REX_B(s);
3157 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3158 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3160 break;
3161 case 0x310: /* movsd xmm, ea */
3162 if (mod != 3) {
3163 gen_lea_modrm(env, s, modrm);
3164 gen_ldq_env_A0(s, offsetof(CPUX86State,
3165 xmm_regs[reg].ZMM_Q(0)));
3166 tcg_gen_movi_tl(cpu_T0, 0);
3167 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3168 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3169 } else {
3170 rm = (modrm & 7) | REX_B(s);
3171 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3172 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3174 break;
3175 case 0x012: /* movlps */
3176 case 0x112: /* movlpd */
3177 if (mod != 3) {
3178 gen_lea_modrm(env, s, modrm);
3179 gen_ldq_env_A0(s, offsetof(CPUX86State,
3180 xmm_regs[reg].ZMM_Q(0)));
3181 } else {
3182 /* movhlps */
3183 rm = (modrm & 7) | REX_B(s);
3184 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3185 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3187 break;
3188 case 0x212: /* movsldup */
3189 if (mod != 3) {
3190 gen_lea_modrm(env, s, modrm);
3191 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3192 } else {
3193 rm = (modrm & 7) | REX_B(s);
3194 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3195 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3196 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3197 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3199 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3200 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3201 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3202 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3203 break;
3204 case 0x312: /* movddup */
3205 if (mod != 3) {
3206 gen_lea_modrm(env, s, modrm);
3207 gen_ldq_env_A0(s, offsetof(CPUX86State,
3208 xmm_regs[reg].ZMM_Q(0)));
3209 } else {
3210 rm = (modrm & 7) | REX_B(s);
3211 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3212 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3214 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3215 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3216 break;
3217 case 0x016: /* movhps */
3218 case 0x116: /* movhpd */
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(1)));
3223 } else {
3224 /* movlhps */
3225 rm = (modrm & 7) | REX_B(s);
3226 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3227 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3229 break;
3230 case 0x216: /* movshdup */
3231 if (mod != 3) {
3232 gen_lea_modrm(env, s, modrm);
3233 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3234 } else {
3235 rm = (modrm & 7) | REX_B(s);
3236 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3237 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3238 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3239 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3241 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3242 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3243 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3244 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3245 break;
3246 case 0x178:
3247 case 0x378:
3249 int bit_index, field_length;
3251 if (b1 == 1 && reg != 0)
3252 goto illegal_op;
3253 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3254 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3255 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3256 offsetof(CPUX86State,xmm_regs[reg]));
3257 if (b1 == 1)
3258 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3259 tcg_const_i32(bit_index),
3260 tcg_const_i32(field_length));
3261 else
3262 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3263 tcg_const_i32(bit_index),
3264 tcg_const_i32(field_length));
3266 break;
3267 case 0x7e: /* movd ea, mm */
3268 #ifdef TARGET_X86_64
3269 if (s->dflag == MO_64) {
3270 tcg_gen_ld_i64(cpu_T0, cpu_env,
3271 offsetof(CPUX86State,fpregs[reg].mmx));
3272 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3273 } else
3274 #endif
3276 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3277 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3278 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3280 break;
3281 case 0x17e: /* movd ea, xmm */
3282 #ifdef TARGET_X86_64
3283 if (s->dflag == MO_64) {
3284 tcg_gen_ld_i64(cpu_T0, cpu_env,
3285 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3286 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3287 } else
3288 #endif
3290 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3291 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3292 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3294 break;
3295 case 0x27e: /* movq xmm, ea */
3296 if (mod != 3) {
3297 gen_lea_modrm(env, s, modrm);
3298 gen_ldq_env_A0(s, offsetof(CPUX86State,
3299 xmm_regs[reg].ZMM_Q(0)));
3300 } else {
3301 rm = (modrm & 7) | REX_B(s);
3302 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3303 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3305 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3306 break;
3307 case 0x7f: /* movq ea, mm */
3308 if (mod != 3) {
3309 gen_lea_modrm(env, s, modrm);
3310 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3311 } else {
3312 rm = (modrm & 7);
3313 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3314 offsetof(CPUX86State,fpregs[reg].mmx));
3316 break;
3317 case 0x011: /* movups */
3318 case 0x111: /* movupd */
3319 case 0x029: /* movaps */
3320 case 0x129: /* movapd */
3321 case 0x17f: /* movdqa ea, xmm */
3322 case 0x27f: /* movdqu ea, xmm */
3323 if (mod != 3) {
3324 gen_lea_modrm(env, s, modrm);
3325 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3326 } else {
3327 rm = (modrm & 7) | REX_B(s);
3328 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3329 offsetof(CPUX86State,xmm_regs[reg]));
3331 break;
3332 case 0x211: /* movss ea, xmm */
3333 if (mod != 3) {
3334 gen_lea_modrm(env, s, modrm);
3335 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3336 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3337 } else {
3338 rm = (modrm & 7) | REX_B(s);
3339 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)),
3340 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3342 break;
3343 case 0x311: /* movsd ea, xmm */
3344 if (mod != 3) {
3345 gen_lea_modrm(env, s, modrm);
3346 gen_stq_env_A0(s, offsetof(CPUX86State,
3347 xmm_regs[reg].ZMM_Q(0)));
3348 } else {
3349 rm = (modrm & 7) | REX_B(s);
3350 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3351 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3353 break;
3354 case 0x013: /* movlps */
3355 case 0x113: /* movlpd */
3356 if (mod != 3) {
3357 gen_lea_modrm(env, s, modrm);
3358 gen_stq_env_A0(s, offsetof(CPUX86State,
3359 xmm_regs[reg].ZMM_Q(0)));
3360 } else {
3361 goto illegal_op;
3363 break;
3364 case 0x017: /* movhps */
3365 case 0x117: /* movhpd */
3366 if (mod != 3) {
3367 gen_lea_modrm(env, s, modrm);
3368 gen_stq_env_A0(s, offsetof(CPUX86State,
3369 xmm_regs[reg].ZMM_Q(1)));
3370 } else {
3371 goto illegal_op;
3373 break;
3374 case 0x71: /* shift mm, im */
3375 case 0x72:
3376 case 0x73:
3377 case 0x171: /* shift xmm, im */
3378 case 0x172:
3379 case 0x173:
3380 if (b1 >= 2) {
3381 goto unknown_op;
3383 val = cpu_ldub_code(env, s->pc++);
3384 if (is_xmm) {
3385 tcg_gen_movi_tl(cpu_T0, val);
3386 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3387 tcg_gen_movi_tl(cpu_T0, 0);
3388 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(1)));
3389 op1_offset = offsetof(CPUX86State,xmm_t0);
3390 } else {
3391 tcg_gen_movi_tl(cpu_T0, val);
3392 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3393 tcg_gen_movi_tl(cpu_T0, 0);
3394 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3395 op1_offset = offsetof(CPUX86State,mmx_t0);
3397 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3398 (((modrm >> 3)) & 7)][b1];
3399 if (!sse_fn_epp) {
3400 goto unknown_op;
3402 if (is_xmm) {
3403 rm = (modrm & 7) | REX_B(s);
3404 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3405 } else {
3406 rm = (modrm & 7);
3407 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3409 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3410 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3411 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3412 break;
3413 case 0x050: /* movmskps */
3414 rm = (modrm & 7) | REX_B(s);
3415 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3416 offsetof(CPUX86State,xmm_regs[rm]));
3417 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3418 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3419 break;
3420 case 0x150: /* movmskpd */
3421 rm = (modrm & 7) | REX_B(s);
3422 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3423 offsetof(CPUX86State,xmm_regs[rm]));
3424 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3425 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3426 break;
3427 case 0x02a: /* cvtpi2ps */
3428 case 0x12a: /* cvtpi2pd */
3429 gen_helper_enter_mmx(cpu_env);
3430 if (mod != 3) {
3431 gen_lea_modrm(env, s, modrm);
3432 op2_offset = offsetof(CPUX86State,mmx_t0);
3433 gen_ldq_env_A0(s, op2_offset);
3434 } else {
3435 rm = (modrm & 7);
3436 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3438 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3439 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3440 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3441 switch(b >> 8) {
3442 case 0x0:
3443 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3444 break;
3445 default:
3446 case 0x1:
3447 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3448 break;
3450 break;
3451 case 0x22a: /* cvtsi2ss */
3452 case 0x32a: /* cvtsi2sd */
3453 ot = mo_64_32(s->dflag);
3454 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3455 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3456 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3457 if (ot == MO_32) {
3458 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3459 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3460 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3461 } else {
3462 #ifdef TARGET_X86_64
3463 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3464 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T0);
3465 #else
3466 goto illegal_op;
3467 #endif
3469 break;
3470 case 0x02c: /* cvttps2pi */
3471 case 0x12c: /* cvttpd2pi */
3472 case 0x02d: /* cvtps2pi */
3473 case 0x12d: /* cvtpd2pi */
3474 gen_helper_enter_mmx(cpu_env);
3475 if (mod != 3) {
3476 gen_lea_modrm(env, s, modrm);
3477 op2_offset = offsetof(CPUX86State,xmm_t0);
3478 gen_ldo_env_A0(s, op2_offset);
3479 } else {
3480 rm = (modrm & 7) | REX_B(s);
3481 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3483 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3484 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3485 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3486 switch(b) {
3487 case 0x02c:
3488 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3489 break;
3490 case 0x12c:
3491 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3492 break;
3493 case 0x02d:
3494 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3495 break;
3496 case 0x12d:
3497 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3498 break;
3500 break;
3501 case 0x22c: /* cvttss2si */
3502 case 0x32c: /* cvttsd2si */
3503 case 0x22d: /* cvtss2si */
3504 case 0x32d: /* cvtsd2si */
3505 ot = mo_64_32(s->dflag);
3506 if (mod != 3) {
3507 gen_lea_modrm(env, s, modrm);
3508 if ((b >> 8) & 1) {
3509 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3510 } else {
3511 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3512 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3514 op2_offset = offsetof(CPUX86State,xmm_t0);
3515 } else {
3516 rm = (modrm & 7) | REX_B(s);
3517 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3519 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3520 if (ot == MO_32) {
3521 SSEFunc_i_ep sse_fn_i_ep =
3522 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3523 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3524 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
3525 } else {
3526 #ifdef TARGET_X86_64
3527 SSEFunc_l_ep sse_fn_l_ep =
3528 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3529 sse_fn_l_ep(cpu_T0, cpu_env, cpu_ptr0);
3530 #else
3531 goto illegal_op;
3532 #endif
3534 gen_op_mov_reg_v(ot, reg, cpu_T0);
3535 break;
3536 case 0xc4: /* pinsrw */
3537 case 0x1c4:
3538 s->rip_offset = 1;
3539 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3540 val = cpu_ldub_code(env, s->pc++);
3541 if (b1) {
3542 val &= 7;
3543 tcg_gen_st16_tl(cpu_T0, cpu_env,
3544 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3545 } else {
3546 val &= 3;
3547 tcg_gen_st16_tl(cpu_T0, cpu_env,
3548 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3550 break;
3551 case 0xc5: /* pextrw */
3552 case 0x1c5:
3553 if (mod != 3)
3554 goto illegal_op;
3555 ot = mo_64_32(s->dflag);
3556 val = cpu_ldub_code(env, s->pc++);
3557 if (b1) {
3558 val &= 7;
3559 rm = (modrm & 7) | REX_B(s);
3560 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3561 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3562 } else {
3563 val &= 3;
3564 rm = (modrm & 7);
3565 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3566 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3568 reg = ((modrm >> 3) & 7) | rex_r;
3569 gen_op_mov_reg_v(ot, reg, cpu_T0);
3570 break;
3571 case 0x1d6: /* movq ea, xmm */
3572 if (mod != 3) {
3573 gen_lea_modrm(env, s, modrm);
3574 gen_stq_env_A0(s, offsetof(CPUX86State,
3575 xmm_regs[reg].ZMM_Q(0)));
3576 } else {
3577 rm = (modrm & 7) | REX_B(s);
3578 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3579 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3580 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3582 break;
3583 case 0x2d6: /* movq2dq */
3584 gen_helper_enter_mmx(cpu_env);
3585 rm = (modrm & 7);
3586 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3587 offsetof(CPUX86State,fpregs[rm].mmx));
3588 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3589 break;
3590 case 0x3d6: /* movdq2q */
3591 gen_helper_enter_mmx(cpu_env);
3592 rm = (modrm & 7) | REX_B(s);
3593 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3594 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3595 break;
3596 case 0xd7: /* pmovmskb */
3597 case 0x1d7:
3598 if (mod != 3)
3599 goto illegal_op;
3600 if (b1) {
3601 rm = (modrm & 7) | REX_B(s);
3602 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3603 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3604 } else {
3605 rm = (modrm & 7);
3606 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3607 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3609 reg = ((modrm >> 3) & 7) | rex_r;
3610 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3611 break;
3613 case 0x138:
3614 case 0x038:
3615 b = modrm;
3616 if ((b & 0xf0) == 0xf0) {
3617 goto do_0f_38_fx;
3619 modrm = cpu_ldub_code(env, s->pc++);
3620 rm = modrm & 7;
3621 reg = ((modrm >> 3) & 7) | rex_r;
3622 mod = (modrm >> 6) & 3;
3623 if (b1 >= 2) {
3624 goto unknown_op;
3627 sse_fn_epp = sse_op_table6[b].op[b1];
3628 if (!sse_fn_epp) {
3629 goto unknown_op;
3631 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3632 goto illegal_op;
3634 if (b1) {
3635 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3636 if (mod == 3) {
3637 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3638 } else {
3639 op2_offset = offsetof(CPUX86State,xmm_t0);
3640 gen_lea_modrm(env, s, modrm);
3641 switch (b) {
3642 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3643 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3644 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3645 gen_ldq_env_A0(s, op2_offset +
3646 offsetof(ZMMReg, ZMM_Q(0)));
3647 break;
3648 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3649 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3650 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3651 s->mem_index, MO_LEUL);
3652 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3653 offsetof(ZMMReg, ZMM_L(0)));
3654 break;
3655 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3656 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3657 s->mem_index, MO_LEUW);
3658 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3659 offsetof(ZMMReg, ZMM_W(0)));
3660 break;
3661 case 0x2a: /* movntqda */
3662 gen_ldo_env_A0(s, op1_offset);
3663 return;
3664 default:
3665 gen_ldo_env_A0(s, op2_offset);
3668 } else {
3669 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3670 if (mod == 3) {
3671 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3672 } else {
3673 op2_offset = offsetof(CPUX86State,mmx_t0);
3674 gen_lea_modrm(env, s, modrm);
3675 gen_ldq_env_A0(s, op2_offset);
3678 if (sse_fn_epp == SSE_SPECIAL) {
3679 goto unknown_op;
3682 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3683 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3684 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3686 if (b == 0x17) {
3687 set_cc_op(s, CC_OP_EFLAGS);
3689 break;
3691 case 0x238:
3692 case 0x338:
3693 do_0f_38_fx:
3694 /* Various integer extensions at 0f 38 f[0-f]. */
3695 b = modrm | (b1 << 8);
3696 modrm = cpu_ldub_code(env, s->pc++);
3697 reg = ((modrm >> 3) & 7) | rex_r;
3699 switch (b) {
3700 case 0x3f0: /* crc32 Gd,Eb */
3701 case 0x3f1: /* crc32 Gd,Ey */
3702 do_crc32:
3703 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3704 goto illegal_op;
3706 if ((b & 0xff) == 0xf0) {
3707 ot = MO_8;
3708 } else if (s->dflag != MO_64) {
3709 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3710 } else {
3711 ot = MO_64;
3714 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
3715 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3716 gen_helper_crc32(cpu_T0, cpu_tmp2_i32,
3717 cpu_T0, tcg_const_i32(8 << ot));
3719 ot = mo_64_32(s->dflag);
3720 gen_op_mov_reg_v(ot, reg, cpu_T0);
3721 break;
3723 case 0x1f0: /* crc32 or movbe */
3724 case 0x1f1:
3725 /* For these insns, the f3 prefix is supposed to have priority
3726 over the 66 prefix, but that's not what we implement above
3727 setting b1. */
3728 if (s->prefix & PREFIX_REPNZ) {
3729 goto do_crc32;
3731 /* FALLTHRU */
3732 case 0x0f0: /* movbe Gy,My */
3733 case 0x0f1: /* movbe My,Gy */
3734 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3735 goto illegal_op;
3737 if (s->dflag != MO_64) {
3738 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3739 } else {
3740 ot = MO_64;
3743 gen_lea_modrm(env, s, modrm);
3744 if ((b & 1) == 0) {
3745 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
3746 s->mem_index, ot | MO_BE);
3747 gen_op_mov_reg_v(ot, reg, cpu_T0);
3748 } else {
3749 tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
3750 s->mem_index, ot | MO_BE);
3752 break;
3754 case 0x0f2: /* andn Gy, By, Ey */
3755 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3756 || !(s->prefix & PREFIX_VEX)
3757 || s->vex_l != 0) {
3758 goto illegal_op;
3760 ot = mo_64_32(s->dflag);
3761 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3762 tcg_gen_andc_tl(cpu_T0, cpu_regs[s->vex_v], cpu_T0);
3763 gen_op_mov_reg_v(ot, reg, cpu_T0);
3764 gen_op_update1_cc();
3765 set_cc_op(s, CC_OP_LOGICB + ot);
3766 break;
3768 case 0x0f7: /* bextr Gy, Ey, By */
3769 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3770 || !(s->prefix & PREFIX_VEX)
3771 || s->vex_l != 0) {
3772 goto illegal_op;
3774 ot = mo_64_32(s->dflag);
3776 TCGv bound, zero;
3778 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3779 /* Extract START, and shift the operand.
3780 Shifts larger than operand size get zeros. */
3781 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
3782 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_A0);
3784 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3785 zero = tcg_const_tl(0);
3786 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T0, cpu_A0, bound,
3787 cpu_T0, zero);
3788 tcg_temp_free(zero);
3790 /* Extract the LEN into a mask. Lengths larger than
3791 operand size get all ones. */
3792 tcg_gen_extract_tl(cpu_A0, cpu_regs[s->vex_v], 8, 8);
3793 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
3794 cpu_A0, bound);
3795 tcg_temp_free(bound);
3796 tcg_gen_movi_tl(cpu_T1, 1);
3797 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_A0);
3798 tcg_gen_subi_tl(cpu_T1, cpu_T1, 1);
3799 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
3801 gen_op_mov_reg_v(ot, reg, cpu_T0);
3802 gen_op_update1_cc();
3803 set_cc_op(s, CC_OP_LOGICB + ot);
3805 break;
3807 case 0x0f5: /* bzhi Gy, Ey, By */
3808 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3809 || !(s->prefix & PREFIX_VEX)
3810 || s->vex_l != 0) {
3811 goto illegal_op;
3813 ot = mo_64_32(s->dflag);
3814 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3815 tcg_gen_ext8u_tl(cpu_T1, cpu_regs[s->vex_v]);
3817 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3818 /* Note that since we're using BMILG (in order to get O
3819 cleared) we need to store the inverse into C. */
3820 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3821 cpu_T1, bound);
3822 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T1, cpu_T1,
3823 bound, bound, cpu_T1);
3824 tcg_temp_free(bound);
3826 tcg_gen_movi_tl(cpu_A0, -1);
3827 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T1);
3828 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_A0);
3829 gen_op_mov_reg_v(ot, reg, cpu_T0);
3830 gen_op_update1_cc();
3831 set_cc_op(s, CC_OP_BMILGB + ot);
3832 break;
3834 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3835 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3836 || !(s->prefix & PREFIX_VEX)
3837 || s->vex_l != 0) {
3838 goto illegal_op;
3840 ot = mo_64_32(s->dflag);
3841 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3842 switch (ot) {
3843 default:
3844 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3845 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3846 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3847 cpu_tmp2_i32, cpu_tmp3_i32);
3848 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3849 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
3850 break;
3851 #ifdef TARGET_X86_64
3852 case MO_64:
3853 tcg_gen_mulu2_i64(cpu_T0, cpu_T1,
3854 cpu_T0, cpu_regs[R_EDX]);
3855 tcg_gen_mov_i64(cpu_regs[s->vex_v], cpu_T0);
3856 tcg_gen_mov_i64(cpu_regs[reg], cpu_T1);
3857 break;
3858 #endif
3860 break;
3862 case 0x3f5: /* pdep Gy, By, Ey */
3863 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3864 || !(s->prefix & PREFIX_VEX)
3865 || s->vex_l != 0) {
3866 goto illegal_op;
3868 ot = mo_64_32(s->dflag);
3869 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3870 /* Note that by zero-extending the mask operand, we
3871 automatically handle zero-extending the result. */
3872 if (ot == MO_64) {
3873 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3874 } else {
3875 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3877 gen_helper_pdep(cpu_regs[reg], cpu_T0, cpu_T1);
3878 break;
3880 case 0x2f5: /* pext Gy, By, Ey */
3881 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3882 || !(s->prefix & PREFIX_VEX)
3883 || s->vex_l != 0) {
3884 goto illegal_op;
3886 ot = mo_64_32(s->dflag);
3887 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3888 /* Note that by zero-extending the mask operand, we
3889 automatically handle zero-extending the result. */
3890 if (ot == MO_64) {
3891 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3892 } else {
3893 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3895 gen_helper_pext(cpu_regs[reg], cpu_T0, cpu_T1);
3896 break;
3898 case 0x1f6: /* adcx Gy, Ey */
3899 case 0x2f6: /* adox Gy, Ey */
3900 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3901 goto illegal_op;
3902 } else {
3903 TCGv carry_in, carry_out, zero;
3904 int end_op;
3906 ot = mo_64_32(s->dflag);
3907 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3909 /* Re-use the carry-out from a previous round. */
3910 TCGV_UNUSED(carry_in);
3911 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3912 switch (s->cc_op) {
3913 case CC_OP_ADCX:
3914 if (b == 0x1f6) {
3915 carry_in = cpu_cc_dst;
3916 end_op = CC_OP_ADCX;
3917 } else {
3918 end_op = CC_OP_ADCOX;
3920 break;
3921 case CC_OP_ADOX:
3922 if (b == 0x1f6) {
3923 end_op = CC_OP_ADCOX;
3924 } else {
3925 carry_in = cpu_cc_src2;
3926 end_op = CC_OP_ADOX;
3928 break;
3929 case CC_OP_ADCOX:
3930 end_op = CC_OP_ADCOX;
3931 carry_in = carry_out;
3932 break;
3933 default:
3934 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
3935 break;
3937 /* If we can't reuse carry-out, get it out of EFLAGS. */
3938 if (TCGV_IS_UNUSED(carry_in)) {
3939 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3940 gen_compute_eflags(s);
3942 carry_in = cpu_tmp0;
3943 tcg_gen_extract_tl(carry_in, cpu_cc_src,
3944 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
3947 switch (ot) {
3948 #ifdef TARGET_X86_64
3949 case MO_32:
3950 /* If we know TL is 64-bit, and we want a 32-bit
3951 result, just do everything in 64-bit arithmetic. */
3952 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3953 tcg_gen_ext32u_i64(cpu_T0, cpu_T0);
3954 tcg_gen_add_i64(cpu_T0, cpu_T0, cpu_regs[reg]);
3955 tcg_gen_add_i64(cpu_T0, cpu_T0, carry_in);
3956 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T0);
3957 tcg_gen_shri_i64(carry_out, cpu_T0, 32);
3958 break;
3959 #endif
3960 default:
3961 /* Otherwise compute the carry-out in two steps. */
3962 zero = tcg_const_tl(0);
3963 tcg_gen_add2_tl(cpu_T0, carry_out,
3964 cpu_T0, zero,
3965 carry_in, zero);
3966 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3967 cpu_regs[reg], carry_out,
3968 cpu_T0, zero);
3969 tcg_temp_free(zero);
3970 break;
3972 set_cc_op(s, end_op);
3974 break;
3976 case 0x1f7: /* shlx Gy, Ey, By */
3977 case 0x2f7: /* sarx Gy, Ey, By */
3978 case 0x3f7: /* shrx Gy, Ey, By */
3979 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3980 || !(s->prefix & PREFIX_VEX)
3981 || s->vex_l != 0) {
3982 goto illegal_op;
3984 ot = mo_64_32(s->dflag);
3985 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3986 if (ot == MO_64) {
3987 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 63);
3988 } else {
3989 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 31);
3991 if (b == 0x1f7) {
3992 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
3993 } else if (b == 0x2f7) {
3994 if (ot != MO_64) {
3995 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
3997 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
3998 } else {
3999 if (ot != MO_64) {
4000 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
4002 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
4004 gen_op_mov_reg_v(ot, reg, cpu_T0);
4005 break;
4007 case 0x0f3:
4008 case 0x1f3:
4009 case 0x2f3:
4010 case 0x3f3: /* Group 17 */
4011 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4012 || !(s->prefix & PREFIX_VEX)
4013 || s->vex_l != 0) {
4014 goto illegal_op;
4016 ot = mo_64_32(s->dflag);
4017 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4019 switch (reg & 7) {
4020 case 1: /* blsr By,Ey */
4021 tcg_gen_neg_tl(cpu_T1, cpu_T0);
4022 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
4023 gen_op_mov_reg_v(ot, s->vex_v, cpu_T0);
4024 gen_op_update2_cc();
4025 set_cc_op(s, CC_OP_BMILGB + ot);
4026 break;
4028 case 2: /* blsmsk By,Ey */
4029 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4030 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
4031 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_cc_src);
4032 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4033 set_cc_op(s, CC_OP_BMILGB + ot);
4034 break;
4036 case 3: /* blsi By, Ey */
4037 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4038 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
4039 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_cc_src);
4040 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4041 set_cc_op(s, CC_OP_BMILGB + ot);
4042 break;
4044 default:
4045 goto unknown_op;
4047 break;
4049 default:
4050 goto unknown_op;
4052 break;
4054 case 0x03a:
4055 case 0x13a:
4056 b = modrm;
4057 modrm = cpu_ldub_code(env, s->pc++);
4058 rm = modrm & 7;
4059 reg = ((modrm >> 3) & 7) | rex_r;
4060 mod = (modrm >> 6) & 3;
4061 if (b1 >= 2) {
4062 goto unknown_op;
4065 sse_fn_eppi = sse_op_table7[b].op[b1];
4066 if (!sse_fn_eppi) {
4067 goto unknown_op;
4069 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4070 goto illegal_op;
4072 s->rip_offset = 1;
4074 if (sse_fn_eppi == SSE_SPECIAL) {
4075 ot = mo_64_32(s->dflag);
4076 rm = (modrm & 7) | REX_B(s);
4077 if (mod != 3)
4078 gen_lea_modrm(env, s, modrm);
4079 reg = ((modrm >> 3) & 7) | rex_r;
4080 val = cpu_ldub_code(env, s->pc++);
4081 switch (b) {
4082 case 0x14: /* pextrb */
4083 tcg_gen_ld8u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4084 xmm_regs[reg].ZMM_B(val & 15)));
4085 if (mod == 3) {
4086 gen_op_mov_reg_v(ot, rm, cpu_T0);
4087 } else {
4088 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4089 s->mem_index, MO_UB);
4091 break;
4092 case 0x15: /* pextrw */
4093 tcg_gen_ld16u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4094 xmm_regs[reg].ZMM_W(val & 7)));
4095 if (mod == 3) {
4096 gen_op_mov_reg_v(ot, rm, cpu_T0);
4097 } else {
4098 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4099 s->mem_index, MO_LEUW);
4101 break;
4102 case 0x16:
4103 if (ot == MO_32) { /* pextrd */
4104 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4105 offsetof(CPUX86State,
4106 xmm_regs[reg].ZMM_L(val & 3)));
4107 if (mod == 3) {
4108 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
4109 } else {
4110 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4111 s->mem_index, MO_LEUL);
4113 } else { /* pextrq */
4114 #ifdef TARGET_X86_64
4115 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4116 offsetof(CPUX86State,
4117 xmm_regs[reg].ZMM_Q(val & 1)));
4118 if (mod == 3) {
4119 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
4120 } else {
4121 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4122 s->mem_index, MO_LEQ);
4124 #else
4125 goto illegal_op;
4126 #endif
4128 break;
4129 case 0x17: /* extractps */
4130 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4131 xmm_regs[reg].ZMM_L(val & 3)));
4132 if (mod == 3) {
4133 gen_op_mov_reg_v(ot, rm, cpu_T0);
4134 } else {
4135 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4136 s->mem_index, MO_LEUL);
4138 break;
4139 case 0x20: /* pinsrb */
4140 if (mod == 3) {
4141 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
4142 } else {
4143 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
4144 s->mem_index, MO_UB);
4146 tcg_gen_st8_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4147 xmm_regs[reg].ZMM_B(val & 15)));
4148 break;
4149 case 0x21: /* insertps */
4150 if (mod == 3) {
4151 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4152 offsetof(CPUX86State,xmm_regs[rm]
4153 .ZMM_L((val >> 6) & 3)));
4154 } else {
4155 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4156 s->mem_index, MO_LEUL);
4158 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4159 offsetof(CPUX86State,xmm_regs[reg]
4160 .ZMM_L((val >> 4) & 3)));
4161 if ((val >> 0) & 1)
4162 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4163 cpu_env, offsetof(CPUX86State,
4164 xmm_regs[reg].ZMM_L(0)));
4165 if ((val >> 1) & 1)
4166 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4167 cpu_env, offsetof(CPUX86State,
4168 xmm_regs[reg].ZMM_L(1)));
4169 if ((val >> 2) & 1)
4170 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4171 cpu_env, offsetof(CPUX86State,
4172 xmm_regs[reg].ZMM_L(2)));
4173 if ((val >> 3) & 1)
4174 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4175 cpu_env, offsetof(CPUX86State,
4176 xmm_regs[reg].ZMM_L(3)));
4177 break;
4178 case 0x22:
4179 if (ot == MO_32) { /* pinsrd */
4180 if (mod == 3) {
4181 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
4182 } else {
4183 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4184 s->mem_index, MO_LEUL);
4186 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4187 offsetof(CPUX86State,
4188 xmm_regs[reg].ZMM_L(val & 3)));
4189 } else { /* pinsrq */
4190 #ifdef TARGET_X86_64
4191 if (mod == 3) {
4192 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4193 } else {
4194 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4195 s->mem_index, MO_LEQ);
4197 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4198 offsetof(CPUX86State,
4199 xmm_regs[reg].ZMM_Q(val & 1)));
4200 #else
4201 goto illegal_op;
4202 #endif
4204 break;
4206 return;
4209 if (b1) {
4210 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4211 if (mod == 3) {
4212 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4213 } else {
4214 op2_offset = offsetof(CPUX86State,xmm_t0);
4215 gen_lea_modrm(env, s, modrm);
4216 gen_ldo_env_A0(s, op2_offset);
4218 } else {
4219 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4220 if (mod == 3) {
4221 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4222 } else {
4223 op2_offset = offsetof(CPUX86State,mmx_t0);
4224 gen_lea_modrm(env, s, modrm);
4225 gen_ldq_env_A0(s, op2_offset);
4228 val = cpu_ldub_code(env, s->pc++);
4230 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4231 set_cc_op(s, CC_OP_EFLAGS);
4233 if (s->dflag == MO_64) {
4234 /* The helper must use entire 64-bit gp registers */
4235 val |= 1 << 8;
4239 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4240 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4241 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4242 break;
4244 case 0x33a:
4245 /* Various integer extensions at 0f 3a f[0-f]. */
4246 b = modrm | (b1 << 8);
4247 modrm = cpu_ldub_code(env, s->pc++);
4248 reg = ((modrm >> 3) & 7) | rex_r;
4250 switch (b) {
4251 case 0x3f0: /* rorx Gy,Ey, Ib */
4252 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4253 || !(s->prefix & PREFIX_VEX)
4254 || s->vex_l != 0) {
4255 goto illegal_op;
4257 ot = mo_64_32(s->dflag);
4258 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4259 b = cpu_ldub_code(env, s->pc++);
4260 if (ot == MO_64) {
4261 tcg_gen_rotri_tl(cpu_T0, cpu_T0, b & 63);
4262 } else {
4263 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4264 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4265 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
4267 gen_op_mov_reg_v(ot, reg, cpu_T0);
4268 break;
4270 default:
4271 goto unknown_op;
4273 break;
4275 default:
4276 unknown_op:
4277 gen_unknown_opcode(env, s);
4278 return;
4280 } else {
4281 /* generic MMX or SSE operation */
4282 switch(b) {
4283 case 0x70: /* pshufx insn */
4284 case 0xc6: /* pshufx insn */
4285 case 0xc2: /* compare insns */
4286 s->rip_offset = 1;
4287 break;
4288 default:
4289 break;
4291 if (is_xmm) {
4292 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4293 if (mod != 3) {
4294 int sz = 4;
4296 gen_lea_modrm(env, s, modrm);
4297 op2_offset = offsetof(CPUX86State,xmm_t0);
4299 switch (b) {
4300 case 0x50 ... 0x5a:
4301 case 0x5c ... 0x5f:
4302 case 0xc2:
4303 /* Most sse scalar operations. */
4304 if (b1 == 2) {
4305 sz = 2;
4306 } else if (b1 == 3) {
4307 sz = 3;
4309 break;
4311 case 0x2e: /* ucomis[sd] */
4312 case 0x2f: /* comis[sd] */
4313 if (b1 == 0) {
4314 sz = 2;
4315 } else {
4316 sz = 3;
4318 break;
4321 switch (sz) {
4322 case 2:
4323 /* 32 bit access */
4324 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
4325 tcg_gen_st32_tl(cpu_T0, cpu_env,
4326 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4327 break;
4328 case 3:
4329 /* 64 bit access */
4330 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4331 break;
4332 default:
4333 /* 128 bit access */
4334 gen_ldo_env_A0(s, op2_offset);
4335 break;
4337 } else {
4338 rm = (modrm & 7) | REX_B(s);
4339 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4341 } else {
4342 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4343 if (mod != 3) {
4344 gen_lea_modrm(env, s, modrm);
4345 op2_offset = offsetof(CPUX86State,mmx_t0);
4346 gen_ldq_env_A0(s, op2_offset);
4347 } else {
4348 rm = (modrm & 7);
4349 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4352 switch(b) {
4353 case 0x0f: /* 3DNow! data insns */
4354 val = cpu_ldub_code(env, s->pc++);
4355 sse_fn_epp = sse_op_table5[val];
4356 if (!sse_fn_epp) {
4357 goto unknown_op;
4359 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4360 goto illegal_op;
4362 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4363 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4364 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4365 break;
4366 case 0x70: /* pshufx insn */
4367 case 0xc6: /* pshufx insn */
4368 val = cpu_ldub_code(env, s->pc++);
4369 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4370 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4371 /* XXX: introduce a new table? */
4372 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4373 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4374 break;
4375 case 0xc2:
4376 /* compare insns */
4377 val = cpu_ldub_code(env, s->pc++);
4378 if (val >= 8)
4379 goto unknown_op;
4380 sse_fn_epp = sse_op_table4[val][b1];
4382 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4383 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4384 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4385 break;
4386 case 0xf7:
4387 /* maskmov : we must prepare A0 */
4388 if (mod != 3)
4389 goto illegal_op;
4390 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4391 gen_extu(s->aflag, cpu_A0);
4392 gen_add_A0_ds_seg(s);
4394 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4395 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4396 /* XXX: introduce a new table? */
4397 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4398 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4399 break;
4400 default:
4401 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4402 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4403 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4404 break;
4406 if (b == 0x2e || b == 0x2f) {
4407 set_cc_op(s, CC_OP_EFLAGS);
4412 /* convert one instruction. s->base.is_jmp is set if the translation must
4413 be stopped. Return the next pc value */
4414 static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
4416 CPUX86State *env = cpu->env_ptr;
4417 int b, prefixes;
4418 int shift;
4419 TCGMemOp ot, aflag, dflag;
4420 int modrm, reg, rm, mod, op, opreg, val;
4421 target_ulong next_eip, tval;
4422 int rex_w, rex_r;
4423 target_ulong pc_start = s->base.pc_next;
4425 s->pc_start = s->pc = pc_start;
4426 prefixes = 0;
4427 s->override = -1;
4428 rex_w = -1;
4429 rex_r = 0;
4430 #ifdef TARGET_X86_64
4431 s->rex_x = 0;
4432 s->rex_b = 0;
4433 x86_64_hregs = 0;
4434 #endif
4435 s->rip_offset = 0; /* for relative ip address */
4436 s->vex_l = 0;
4437 s->vex_v = 0;
4438 next_byte:
4439 /* x86 has an upper limit of 15 bytes for an instruction. Since we
4440 * do not want to decode and generate IR for an illegal
4441 * instruction, the following check limits the instruction size to
4442 * 25 bytes: 14 prefix + 1 opc + 6 (modrm+sib+ofs) + 4 imm */
4443 if (s->pc - pc_start > 14) {
4444 goto illegal_op;
4446 b = cpu_ldub_code(env, s->pc);
4447 s->pc++;
4448 /* Collect prefixes. */
4449 switch (b) {
4450 case 0xf3:
4451 prefixes |= PREFIX_REPZ;
4452 goto next_byte;
4453 case 0xf2:
4454 prefixes |= PREFIX_REPNZ;
4455 goto next_byte;
4456 case 0xf0:
4457 prefixes |= PREFIX_LOCK;
4458 goto next_byte;
4459 case 0x2e:
4460 s->override = R_CS;
4461 goto next_byte;
4462 case 0x36:
4463 s->override = R_SS;
4464 goto next_byte;
4465 case 0x3e:
4466 s->override = R_DS;
4467 goto next_byte;
4468 case 0x26:
4469 s->override = R_ES;
4470 goto next_byte;
4471 case 0x64:
4472 s->override = R_FS;
4473 goto next_byte;
4474 case 0x65:
4475 s->override = R_GS;
4476 goto next_byte;
4477 case 0x66:
4478 prefixes |= PREFIX_DATA;
4479 goto next_byte;
4480 case 0x67:
4481 prefixes |= PREFIX_ADR;
4482 goto next_byte;
4483 #ifdef TARGET_X86_64
4484 case 0x40 ... 0x4f:
4485 if (CODE64(s)) {
4486 /* REX prefix */
4487 rex_w = (b >> 3) & 1;
4488 rex_r = (b & 0x4) << 1;
4489 s->rex_x = (b & 0x2) << 2;
4490 REX_B(s) = (b & 0x1) << 3;
4491 x86_64_hregs = 1; /* select uniform byte register addressing */
4492 goto next_byte;
4494 break;
4495 #endif
4496 case 0xc5: /* 2-byte VEX */
4497 case 0xc4: /* 3-byte VEX */
4498 /* VEX prefixes cannot be used except in 32-bit mode.
4499 Otherwise the instruction is LES or LDS. */
4500 if (s->code32 && !s->vm86) {
4501 static const int pp_prefix[4] = {
4502 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4504 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4506 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4507 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4508 otherwise the instruction is LES or LDS. */
4509 break;
4511 s->pc++;
4513 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4514 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4515 | PREFIX_LOCK | PREFIX_DATA)) {
4516 goto illegal_op;
4518 #ifdef TARGET_X86_64
4519 if (x86_64_hregs) {
4520 goto illegal_op;
4522 #endif
4523 rex_r = (~vex2 >> 4) & 8;
4524 if (b == 0xc5) {
4525 vex3 = vex2;
4526 b = cpu_ldub_code(env, s->pc++);
4527 } else {
4528 #ifdef TARGET_X86_64
4529 s->rex_x = (~vex2 >> 3) & 8;
4530 s->rex_b = (~vex2 >> 2) & 8;
4531 #endif
4532 vex3 = cpu_ldub_code(env, s->pc++);
4533 rex_w = (vex3 >> 7) & 1;
4534 switch (vex2 & 0x1f) {
4535 case 0x01: /* Implied 0f leading opcode bytes. */
4536 b = cpu_ldub_code(env, s->pc++) | 0x100;
4537 break;
4538 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4539 b = 0x138;
4540 break;
4541 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4542 b = 0x13a;
4543 break;
4544 default: /* Reserved for future use. */
4545 goto unknown_op;
4548 s->vex_v = (~vex3 >> 3) & 0xf;
4549 s->vex_l = (vex3 >> 2) & 1;
4550 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4552 break;
4555 /* Post-process prefixes. */
4556 if (CODE64(s)) {
4557 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4558 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4559 over 0x66 if both are present. */
4560 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4561 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4562 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4563 } else {
4564 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4565 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4566 dflag = MO_32;
4567 } else {
4568 dflag = MO_16;
4570 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4571 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4572 aflag = MO_32;
4573 } else {
4574 aflag = MO_16;
4578 s->prefix = prefixes;
4579 s->aflag = aflag;
4580 s->dflag = dflag;
4582 /* now check op code */
4583 reswitch:
4584 switch(b) {
4585 case 0x0f:
4586 /**************************/
4587 /* extended op code */
4588 b = cpu_ldub_code(env, s->pc++) | 0x100;
4589 goto reswitch;
4591 /**************************/
4592 /* arith & logic */
4593 case 0x00 ... 0x05:
4594 case 0x08 ... 0x0d:
4595 case 0x10 ... 0x15:
4596 case 0x18 ... 0x1d:
4597 case 0x20 ... 0x25:
4598 case 0x28 ... 0x2d:
4599 case 0x30 ... 0x35:
4600 case 0x38 ... 0x3d:
4602 int op, f, val;
4603 op = (b >> 3) & 7;
4604 f = (b >> 1) & 3;
4606 ot = mo_b_d(b, dflag);
4608 switch(f) {
4609 case 0: /* OP Ev, Gv */
4610 modrm = cpu_ldub_code(env, s->pc++);
4611 reg = ((modrm >> 3) & 7) | rex_r;
4612 mod = (modrm >> 6) & 3;
4613 rm = (modrm & 7) | REX_B(s);
4614 if (mod != 3) {
4615 gen_lea_modrm(env, s, modrm);
4616 opreg = OR_TMP0;
4617 } else if (op == OP_XORL && rm == reg) {
4618 xor_zero:
4619 /* xor reg, reg optimisation */
4620 set_cc_op(s, CC_OP_CLR);
4621 tcg_gen_movi_tl(cpu_T0, 0);
4622 gen_op_mov_reg_v(ot, reg, cpu_T0);
4623 break;
4624 } else {
4625 opreg = rm;
4627 gen_op_mov_v_reg(ot, cpu_T1, reg);
4628 gen_op(s, op, ot, opreg);
4629 break;
4630 case 1: /* OP Gv, Ev */
4631 modrm = cpu_ldub_code(env, s->pc++);
4632 mod = (modrm >> 6) & 3;
4633 reg = ((modrm >> 3) & 7) | rex_r;
4634 rm = (modrm & 7) | REX_B(s);
4635 if (mod != 3) {
4636 gen_lea_modrm(env, s, modrm);
4637 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4638 } else if (op == OP_XORL && rm == reg) {
4639 goto xor_zero;
4640 } else {
4641 gen_op_mov_v_reg(ot, cpu_T1, rm);
4643 gen_op(s, op, ot, reg);
4644 break;
4645 case 2: /* OP A, Iv */
4646 val = insn_get(env, s, ot);
4647 tcg_gen_movi_tl(cpu_T1, val);
4648 gen_op(s, op, ot, OR_EAX);
4649 break;
4652 break;
4654 case 0x82:
4655 if (CODE64(s))
4656 goto illegal_op;
4657 case 0x80: /* GRP1 */
4658 case 0x81:
4659 case 0x83:
4661 int val;
4663 ot = mo_b_d(b, dflag);
4665 modrm = cpu_ldub_code(env, s->pc++);
4666 mod = (modrm >> 6) & 3;
4667 rm = (modrm & 7) | REX_B(s);
4668 op = (modrm >> 3) & 7;
4670 if (mod != 3) {
4671 if (b == 0x83)
4672 s->rip_offset = 1;
4673 else
4674 s->rip_offset = insn_const_size(ot);
4675 gen_lea_modrm(env, s, modrm);
4676 opreg = OR_TMP0;
4677 } else {
4678 opreg = rm;
4681 switch(b) {
4682 default:
4683 case 0x80:
4684 case 0x81:
4685 case 0x82:
4686 val = insn_get(env, s, ot);
4687 break;
4688 case 0x83:
4689 val = (int8_t)insn_get(env, s, MO_8);
4690 break;
4692 tcg_gen_movi_tl(cpu_T1, val);
4693 gen_op(s, op, ot, opreg);
4695 break;
4697 /**************************/
4698 /* inc, dec, and other misc arith */
4699 case 0x40 ... 0x47: /* inc Gv */
4700 ot = dflag;
4701 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4702 break;
4703 case 0x48 ... 0x4f: /* dec Gv */
4704 ot = dflag;
4705 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4706 break;
4707 case 0xf6: /* GRP3 */
4708 case 0xf7:
4709 ot = mo_b_d(b, dflag);
4711 modrm = cpu_ldub_code(env, s->pc++);
4712 mod = (modrm >> 6) & 3;
4713 rm = (modrm & 7) | REX_B(s);
4714 op = (modrm >> 3) & 7;
4715 if (mod != 3) {
4716 if (op == 0) {
4717 s->rip_offset = insn_const_size(ot);
4719 gen_lea_modrm(env, s, modrm);
4720 /* For those below that handle locked memory, don't load here. */
4721 if (!(s->prefix & PREFIX_LOCK)
4722 || op != 2) {
4723 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4725 } else {
4726 gen_op_mov_v_reg(ot, cpu_T0, rm);
4729 switch(op) {
4730 case 0: /* test */
4731 val = insn_get(env, s, ot);
4732 tcg_gen_movi_tl(cpu_T1, val);
4733 gen_op_testl_T0_T1_cc();
4734 set_cc_op(s, CC_OP_LOGICB + ot);
4735 break;
4736 case 2: /* not */
4737 if (s->prefix & PREFIX_LOCK) {
4738 if (mod == 3) {
4739 goto illegal_op;
4741 tcg_gen_movi_tl(cpu_T0, ~0);
4742 tcg_gen_atomic_xor_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
4743 s->mem_index, ot | MO_LE);
4744 } else {
4745 tcg_gen_not_tl(cpu_T0, cpu_T0);
4746 if (mod != 3) {
4747 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4748 } else {
4749 gen_op_mov_reg_v(ot, rm, cpu_T0);
4752 break;
4753 case 3: /* neg */
4754 if (s->prefix & PREFIX_LOCK) {
4755 TCGLabel *label1;
4756 TCGv a0, t0, t1, t2;
4758 if (mod == 3) {
4759 goto illegal_op;
4761 a0 = tcg_temp_local_new();
4762 t0 = tcg_temp_local_new();
4763 label1 = gen_new_label();
4765 tcg_gen_mov_tl(a0, cpu_A0);
4766 tcg_gen_mov_tl(t0, cpu_T0);
4768 gen_set_label(label1);
4769 t1 = tcg_temp_new();
4770 t2 = tcg_temp_new();
4771 tcg_gen_mov_tl(t2, t0);
4772 tcg_gen_neg_tl(t1, t0);
4773 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4774 s->mem_index, ot | MO_LE);
4775 tcg_temp_free(t1);
4776 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4778 tcg_temp_free(t2);
4779 tcg_temp_free(a0);
4780 tcg_gen_mov_tl(cpu_T0, t0);
4781 tcg_temp_free(t0);
4782 } else {
4783 tcg_gen_neg_tl(cpu_T0, cpu_T0);
4784 if (mod != 3) {
4785 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4786 } else {
4787 gen_op_mov_reg_v(ot, rm, cpu_T0);
4790 gen_op_update_neg_cc();
4791 set_cc_op(s, CC_OP_SUBB + ot);
4792 break;
4793 case 4: /* mul */
4794 switch(ot) {
4795 case MO_8:
4796 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4797 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
4798 tcg_gen_ext8u_tl(cpu_T1, cpu_T1);
4799 /* XXX: use 32 bit mul which could be faster */
4800 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4801 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4802 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4803 tcg_gen_andi_tl(cpu_cc_src, cpu_T0, 0xff00);
4804 set_cc_op(s, CC_OP_MULB);
4805 break;
4806 case MO_16:
4807 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4808 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4809 tcg_gen_ext16u_tl(cpu_T1, cpu_T1);
4810 /* XXX: use 32 bit mul which could be faster */
4811 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4812 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4813 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4814 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4815 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4816 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4817 set_cc_op(s, CC_OP_MULW);
4818 break;
4819 default:
4820 case MO_32:
4821 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4822 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4823 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4824 cpu_tmp2_i32, cpu_tmp3_i32);
4825 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4826 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4827 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4828 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4829 set_cc_op(s, CC_OP_MULL);
4830 break;
4831 #ifdef TARGET_X86_64
4832 case MO_64:
4833 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4834 cpu_T0, cpu_regs[R_EAX]);
4835 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4836 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4837 set_cc_op(s, CC_OP_MULQ);
4838 break;
4839 #endif
4841 break;
4842 case 5: /* imul */
4843 switch(ot) {
4844 case MO_8:
4845 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4846 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
4847 tcg_gen_ext8s_tl(cpu_T1, cpu_T1);
4848 /* XXX: use 32 bit mul which could be faster */
4849 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4850 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4851 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4852 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T0);
4853 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4854 set_cc_op(s, CC_OP_MULB);
4855 break;
4856 case MO_16:
4857 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4858 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4859 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
4860 /* XXX: use 32 bit mul which could be faster */
4861 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4862 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4863 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4864 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
4865 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4866 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4867 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4868 set_cc_op(s, CC_OP_MULW);
4869 break;
4870 default:
4871 case MO_32:
4872 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4873 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4874 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4875 cpu_tmp2_i32, cpu_tmp3_i32);
4876 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4877 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4878 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4879 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4880 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4881 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4882 set_cc_op(s, CC_OP_MULL);
4883 break;
4884 #ifdef TARGET_X86_64
4885 case MO_64:
4886 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4887 cpu_T0, cpu_regs[R_EAX]);
4888 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4889 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4890 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4891 set_cc_op(s, CC_OP_MULQ);
4892 break;
4893 #endif
4895 break;
4896 case 6: /* div */
4897 switch(ot) {
4898 case MO_8:
4899 gen_helper_divb_AL(cpu_env, cpu_T0);
4900 break;
4901 case MO_16:
4902 gen_helper_divw_AX(cpu_env, cpu_T0);
4903 break;
4904 default:
4905 case MO_32:
4906 gen_helper_divl_EAX(cpu_env, cpu_T0);
4907 break;
4908 #ifdef TARGET_X86_64
4909 case MO_64:
4910 gen_helper_divq_EAX(cpu_env, cpu_T0);
4911 break;
4912 #endif
4914 break;
4915 case 7: /* idiv */
4916 switch(ot) {
4917 case MO_8:
4918 gen_helper_idivb_AL(cpu_env, cpu_T0);
4919 break;
4920 case MO_16:
4921 gen_helper_idivw_AX(cpu_env, cpu_T0);
4922 break;
4923 default:
4924 case MO_32:
4925 gen_helper_idivl_EAX(cpu_env, cpu_T0);
4926 break;
4927 #ifdef TARGET_X86_64
4928 case MO_64:
4929 gen_helper_idivq_EAX(cpu_env, cpu_T0);
4930 break;
4931 #endif
4933 break;
4934 default:
4935 goto unknown_op;
4937 break;
4939 case 0xfe: /* GRP4 */
4940 case 0xff: /* GRP5 */
4941 ot = mo_b_d(b, dflag);
4943 modrm = cpu_ldub_code(env, s->pc++);
4944 mod = (modrm >> 6) & 3;
4945 rm = (modrm & 7) | REX_B(s);
4946 op = (modrm >> 3) & 7;
4947 if (op >= 2 && b == 0xfe) {
4948 goto unknown_op;
4950 if (CODE64(s)) {
4951 if (op == 2 || op == 4) {
4952 /* operand size for jumps is 64 bit */
4953 ot = MO_64;
4954 } else if (op == 3 || op == 5) {
4955 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
4956 } else if (op == 6) {
4957 /* default push size is 64 bit */
4958 ot = mo_pushpop(s, dflag);
4961 if (mod != 3) {
4962 gen_lea_modrm(env, s, modrm);
4963 if (op >= 2 && op != 3 && op != 5)
4964 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4965 } else {
4966 gen_op_mov_v_reg(ot, cpu_T0, rm);
4969 switch(op) {
4970 case 0: /* inc Ev */
4971 if (mod != 3)
4972 opreg = OR_TMP0;
4973 else
4974 opreg = rm;
4975 gen_inc(s, ot, opreg, 1);
4976 break;
4977 case 1: /* dec Ev */
4978 if (mod != 3)
4979 opreg = OR_TMP0;
4980 else
4981 opreg = rm;
4982 gen_inc(s, ot, opreg, -1);
4983 break;
4984 case 2: /* call Ev */
4985 /* XXX: optimize if memory (no 'and' is necessary) */
4986 if (dflag == MO_16) {
4987 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4989 next_eip = s->pc - s->cs_base;
4990 tcg_gen_movi_tl(cpu_T1, next_eip);
4991 gen_push_v(s, cpu_T1);
4992 gen_op_jmp_v(cpu_T0);
4993 gen_bnd_jmp(s);
4994 gen_jr(s, cpu_T0);
4995 break;
4996 case 3: /* lcall Ev */
4997 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4998 gen_add_A0_im(s, 1 << ot);
4999 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
5000 do_lcall:
5001 if (s->pe && !s->vm86) {
5002 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
5003 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
5004 tcg_const_i32(dflag - 1),
5005 tcg_const_tl(s->pc - s->cs_base));
5006 } else {
5007 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
5008 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T1,
5009 tcg_const_i32(dflag - 1),
5010 tcg_const_i32(s->pc - s->cs_base));
5012 tcg_gen_ld_tl(cpu_tmp4, cpu_env, offsetof(CPUX86State, eip));
5013 gen_jr(s, cpu_tmp4);
5014 break;
5015 case 4: /* jmp Ev */
5016 if (dflag == MO_16) {
5017 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
5019 gen_op_jmp_v(cpu_T0);
5020 gen_bnd_jmp(s);
5021 gen_jr(s, cpu_T0);
5022 break;
5023 case 5: /* ljmp Ev */
5024 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5025 gen_add_A0_im(s, 1 << ot);
5026 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
5027 do_ljmp:
5028 if (s->pe && !s->vm86) {
5029 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
5030 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
5031 tcg_const_tl(s->pc - s->cs_base));
5032 } else {
5033 gen_op_movl_seg_T0_vm(R_CS);
5034 gen_op_jmp_v(cpu_T1);
5036 tcg_gen_ld_tl(cpu_tmp4, cpu_env, offsetof(CPUX86State, eip));
5037 gen_jr(s, cpu_tmp4);
5038 break;
5039 case 6: /* push Ev */
5040 gen_push_v(s, cpu_T0);
5041 break;
5042 default:
5043 goto unknown_op;
5045 break;
5047 case 0x84: /* test Ev, Gv */
5048 case 0x85:
5049 ot = mo_b_d(b, dflag);
5051 modrm = cpu_ldub_code(env, s->pc++);
5052 reg = ((modrm >> 3) & 7) | rex_r;
5054 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5055 gen_op_mov_v_reg(ot, cpu_T1, reg);
5056 gen_op_testl_T0_T1_cc();
5057 set_cc_op(s, CC_OP_LOGICB + ot);
5058 break;
5060 case 0xa8: /* test eAX, Iv */
5061 case 0xa9:
5062 ot = mo_b_d(b, dflag);
5063 val = insn_get(env, s, ot);
5065 gen_op_mov_v_reg(ot, cpu_T0, OR_EAX);
5066 tcg_gen_movi_tl(cpu_T1, val);
5067 gen_op_testl_T0_T1_cc();
5068 set_cc_op(s, CC_OP_LOGICB + ot);
5069 break;
5071 case 0x98: /* CWDE/CBW */
5072 switch (dflag) {
5073 #ifdef TARGET_X86_64
5074 case MO_64:
5075 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
5076 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
5077 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T0);
5078 break;
5079 #endif
5080 case MO_32:
5081 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
5082 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5083 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T0);
5084 break;
5085 case MO_16:
5086 gen_op_mov_v_reg(MO_8, cpu_T0, R_EAX);
5087 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
5088 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
5089 break;
5090 default:
5091 tcg_abort();
5093 break;
5094 case 0x99: /* CDQ/CWD */
5095 switch (dflag) {
5096 #ifdef TARGET_X86_64
5097 case MO_64:
5098 gen_op_mov_v_reg(MO_64, cpu_T0, R_EAX);
5099 tcg_gen_sari_tl(cpu_T0, cpu_T0, 63);
5100 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T0);
5101 break;
5102 #endif
5103 case MO_32:
5104 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
5105 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
5106 tcg_gen_sari_tl(cpu_T0, cpu_T0, 31);
5107 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T0);
5108 break;
5109 case MO_16:
5110 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
5111 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5112 tcg_gen_sari_tl(cpu_T0, cpu_T0, 15);
5113 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
5114 break;
5115 default:
5116 tcg_abort();
5118 break;
5119 case 0x1af: /* imul Gv, Ev */
5120 case 0x69: /* imul Gv, Ev, I */
5121 case 0x6b:
5122 ot = dflag;
5123 modrm = cpu_ldub_code(env, s->pc++);
5124 reg = ((modrm >> 3) & 7) | rex_r;
5125 if (b == 0x69)
5126 s->rip_offset = insn_const_size(ot);
5127 else if (b == 0x6b)
5128 s->rip_offset = 1;
5129 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5130 if (b == 0x69) {
5131 val = insn_get(env, s, ot);
5132 tcg_gen_movi_tl(cpu_T1, val);
5133 } else if (b == 0x6b) {
5134 val = (int8_t)insn_get(env, s, MO_8);
5135 tcg_gen_movi_tl(cpu_T1, val);
5136 } else {
5137 gen_op_mov_v_reg(ot, cpu_T1, reg);
5139 switch (ot) {
5140 #ifdef TARGET_X86_64
5141 case MO_64:
5142 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T1, cpu_T0, cpu_T1);
5143 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5144 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5145 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T1);
5146 break;
5147 #endif
5148 case MO_32:
5149 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
5150 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
5151 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5152 cpu_tmp2_i32, cpu_tmp3_i32);
5153 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5154 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5155 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5156 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5157 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5158 break;
5159 default:
5160 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5161 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
5162 /* XXX: use 32 bit mul which could be faster */
5163 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
5164 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
5165 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
5166 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
5167 gen_op_mov_reg_v(ot, reg, cpu_T0);
5168 break;
5170 set_cc_op(s, CC_OP_MULB + ot);
5171 break;
5172 case 0x1c0:
5173 case 0x1c1: /* xadd Ev, Gv */
5174 ot = mo_b_d(b, dflag);
5175 modrm = cpu_ldub_code(env, s->pc++);
5176 reg = ((modrm >> 3) & 7) | rex_r;
5177 mod = (modrm >> 6) & 3;
5178 gen_op_mov_v_reg(ot, cpu_T0, reg);
5179 if (mod == 3) {
5180 rm = (modrm & 7) | REX_B(s);
5181 gen_op_mov_v_reg(ot, cpu_T1, rm);
5182 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5183 gen_op_mov_reg_v(ot, reg, cpu_T1);
5184 gen_op_mov_reg_v(ot, rm, cpu_T0);
5185 } else {
5186 gen_lea_modrm(env, s, modrm);
5187 if (s->prefix & PREFIX_LOCK) {
5188 tcg_gen_atomic_fetch_add_tl(cpu_T1, cpu_A0, cpu_T0,
5189 s->mem_index, ot | MO_LE);
5190 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5191 } else {
5192 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5193 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5194 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5196 gen_op_mov_reg_v(ot, reg, cpu_T1);
5198 gen_op_update2_cc();
5199 set_cc_op(s, CC_OP_ADDB + ot);
5200 break;
5201 case 0x1b0:
5202 case 0x1b1: /* cmpxchg Ev, Gv */
5204 TCGv oldv, newv, cmpv;
5206 ot = mo_b_d(b, dflag);
5207 modrm = cpu_ldub_code(env, s->pc++);
5208 reg = ((modrm >> 3) & 7) | rex_r;
5209 mod = (modrm >> 6) & 3;
5210 oldv = tcg_temp_new();
5211 newv = tcg_temp_new();
5212 cmpv = tcg_temp_new();
5213 gen_op_mov_v_reg(ot, newv, reg);
5214 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5216 if (s->prefix & PREFIX_LOCK) {
5217 if (mod == 3) {
5218 goto illegal_op;
5220 gen_lea_modrm(env, s, modrm);
5221 tcg_gen_atomic_cmpxchg_tl(oldv, cpu_A0, cmpv, newv,
5222 s->mem_index, ot | MO_LE);
5223 gen_op_mov_reg_v(ot, R_EAX, oldv);
5224 } else {
5225 if (mod == 3) {
5226 rm = (modrm & 7) | REX_B(s);
5227 gen_op_mov_v_reg(ot, oldv, rm);
5228 } else {
5229 gen_lea_modrm(env, s, modrm);
5230 gen_op_ld_v(s, ot, oldv, cpu_A0);
5231 rm = 0; /* avoid warning */
5233 gen_extu(ot, oldv);
5234 gen_extu(ot, cmpv);
5235 /* store value = (old == cmp ? new : old); */
5236 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5237 if (mod == 3) {
5238 gen_op_mov_reg_v(ot, R_EAX, oldv);
5239 gen_op_mov_reg_v(ot, rm, newv);
5240 } else {
5241 /* Perform an unconditional store cycle like physical cpu;
5242 must be before changing accumulator to ensure
5243 idempotency if the store faults and the instruction
5244 is restarted */
5245 gen_op_st_v(s, ot, newv, cpu_A0);
5246 gen_op_mov_reg_v(ot, R_EAX, oldv);
5249 tcg_gen_mov_tl(cpu_cc_src, oldv);
5250 tcg_gen_mov_tl(cpu_cc_srcT, cmpv);
5251 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5252 set_cc_op(s, CC_OP_SUBB + ot);
5253 tcg_temp_free(oldv);
5254 tcg_temp_free(newv);
5255 tcg_temp_free(cmpv);
5257 break;
5258 case 0x1c7: /* cmpxchg8b */
5259 modrm = cpu_ldub_code(env, s->pc++);
5260 mod = (modrm >> 6) & 3;
5261 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5262 goto illegal_op;
5263 #ifdef TARGET_X86_64
5264 if (dflag == MO_64) {
5265 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5266 goto illegal_op;
5267 gen_lea_modrm(env, s, modrm);
5268 if ((s->prefix & PREFIX_LOCK) && parallel_cpus) {
5269 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5270 } else {
5271 gen_helper_cmpxchg16b_unlocked(cpu_env, cpu_A0);
5273 } else
5274 #endif
5276 if (!(s->cpuid_features & CPUID_CX8))
5277 goto illegal_op;
5278 gen_lea_modrm(env, s, modrm);
5279 if ((s->prefix & PREFIX_LOCK) && parallel_cpus) {
5280 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5281 } else {
5282 gen_helper_cmpxchg8b_unlocked(cpu_env, cpu_A0);
5285 set_cc_op(s, CC_OP_EFLAGS);
5286 break;
5288 /**************************/
5289 /* push/pop */
5290 case 0x50 ... 0x57: /* push */
5291 gen_op_mov_v_reg(MO_32, cpu_T0, (b & 7) | REX_B(s));
5292 gen_push_v(s, cpu_T0);
5293 break;
5294 case 0x58 ... 0x5f: /* pop */
5295 ot = gen_pop_T0(s);
5296 /* NOTE: order is important for pop %sp */
5297 gen_pop_update(s, ot);
5298 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T0);
5299 break;
5300 case 0x60: /* pusha */
5301 if (CODE64(s))
5302 goto illegal_op;
5303 gen_pusha(s);
5304 break;
5305 case 0x61: /* popa */
5306 if (CODE64(s))
5307 goto illegal_op;
5308 gen_popa(s);
5309 break;
5310 case 0x68: /* push Iv */
5311 case 0x6a:
5312 ot = mo_pushpop(s, dflag);
5313 if (b == 0x68)
5314 val = insn_get(env, s, ot);
5315 else
5316 val = (int8_t)insn_get(env, s, MO_8);
5317 tcg_gen_movi_tl(cpu_T0, val);
5318 gen_push_v(s, cpu_T0);
5319 break;
5320 case 0x8f: /* pop Ev */
5321 modrm = cpu_ldub_code(env, s->pc++);
5322 mod = (modrm >> 6) & 3;
5323 ot = gen_pop_T0(s);
5324 if (mod == 3) {
5325 /* NOTE: order is important for pop %sp */
5326 gen_pop_update(s, ot);
5327 rm = (modrm & 7) | REX_B(s);
5328 gen_op_mov_reg_v(ot, rm, cpu_T0);
5329 } else {
5330 /* NOTE: order is important too for MMU exceptions */
5331 s->popl_esp_hack = 1 << ot;
5332 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5333 s->popl_esp_hack = 0;
5334 gen_pop_update(s, ot);
5336 break;
5337 case 0xc8: /* enter */
5339 int level;
5340 val = cpu_lduw_code(env, s->pc);
5341 s->pc += 2;
5342 level = cpu_ldub_code(env, s->pc++);
5343 gen_enter(s, val, level);
5345 break;
5346 case 0xc9: /* leave */
5347 gen_leave(s);
5348 break;
5349 case 0x06: /* push es */
5350 case 0x0e: /* push cs */
5351 case 0x16: /* push ss */
5352 case 0x1e: /* push ds */
5353 if (CODE64(s))
5354 goto illegal_op;
5355 gen_op_movl_T0_seg(b >> 3);
5356 gen_push_v(s, cpu_T0);
5357 break;
5358 case 0x1a0: /* push fs */
5359 case 0x1a8: /* push gs */
5360 gen_op_movl_T0_seg((b >> 3) & 7);
5361 gen_push_v(s, cpu_T0);
5362 break;
5363 case 0x07: /* pop es */
5364 case 0x17: /* pop ss */
5365 case 0x1f: /* pop ds */
5366 if (CODE64(s))
5367 goto illegal_op;
5368 reg = b >> 3;
5369 ot = gen_pop_T0(s);
5370 gen_movl_seg_T0(s, reg);
5371 gen_pop_update(s, ot);
5372 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5373 if (s->base.is_jmp) {
5374 gen_jmp_im(s->pc - s->cs_base);
5375 if (reg == R_SS) {
5376 s->tf = 0;
5377 gen_eob_inhibit_irq(s, true);
5378 } else {
5379 gen_eob(s);
5382 break;
5383 case 0x1a1: /* pop fs */
5384 case 0x1a9: /* pop gs */
5385 ot = gen_pop_T0(s);
5386 gen_movl_seg_T0(s, (b >> 3) & 7);
5387 gen_pop_update(s, ot);
5388 if (s->base.is_jmp) {
5389 gen_jmp_im(s->pc - s->cs_base);
5390 gen_eob(s);
5392 break;
5394 /**************************/
5395 /* mov */
5396 case 0x88:
5397 case 0x89: /* mov Gv, Ev */
5398 ot = mo_b_d(b, dflag);
5399 modrm = cpu_ldub_code(env, s->pc++);
5400 reg = ((modrm >> 3) & 7) | rex_r;
5402 /* generate a generic store */
5403 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5404 break;
5405 case 0xc6:
5406 case 0xc7: /* mov Ev, Iv */
5407 ot = mo_b_d(b, dflag);
5408 modrm = cpu_ldub_code(env, s->pc++);
5409 mod = (modrm >> 6) & 3;
5410 if (mod != 3) {
5411 s->rip_offset = insn_const_size(ot);
5412 gen_lea_modrm(env, s, modrm);
5414 val = insn_get(env, s, ot);
5415 tcg_gen_movi_tl(cpu_T0, val);
5416 if (mod != 3) {
5417 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5418 } else {
5419 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T0);
5421 break;
5422 case 0x8a:
5423 case 0x8b: /* mov Ev, Gv */
5424 ot = mo_b_d(b, dflag);
5425 modrm = cpu_ldub_code(env, s->pc++);
5426 reg = ((modrm >> 3) & 7) | rex_r;
5428 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5429 gen_op_mov_reg_v(ot, reg, cpu_T0);
5430 break;
5431 case 0x8e: /* mov seg, Gv */
5432 modrm = cpu_ldub_code(env, s->pc++);
5433 reg = (modrm >> 3) & 7;
5434 if (reg >= 6 || reg == R_CS)
5435 goto illegal_op;
5436 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5437 gen_movl_seg_T0(s, reg);
5438 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5439 if (s->base.is_jmp) {
5440 gen_jmp_im(s->pc - s->cs_base);
5441 if (reg == R_SS) {
5442 s->tf = 0;
5443 gen_eob_inhibit_irq(s, true);
5444 } else {
5445 gen_eob(s);
5448 break;
5449 case 0x8c: /* mov Gv, seg */
5450 modrm = cpu_ldub_code(env, s->pc++);
5451 reg = (modrm >> 3) & 7;
5452 mod = (modrm >> 6) & 3;
5453 if (reg >= 6)
5454 goto illegal_op;
5455 gen_op_movl_T0_seg(reg);
5456 ot = mod == 3 ? dflag : MO_16;
5457 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5458 break;
5460 case 0x1b6: /* movzbS Gv, Eb */
5461 case 0x1b7: /* movzwS Gv, Eb */
5462 case 0x1be: /* movsbS Gv, Eb */
5463 case 0x1bf: /* movswS Gv, Eb */
5465 TCGMemOp d_ot;
5466 TCGMemOp s_ot;
5468 /* d_ot is the size of destination */
5469 d_ot = dflag;
5470 /* ot is the size of source */
5471 ot = (b & 1) + MO_8;
5472 /* s_ot is the sign+size of source */
5473 s_ot = b & 8 ? MO_SIGN | ot : ot;
5475 modrm = cpu_ldub_code(env, s->pc++);
5476 reg = ((modrm >> 3) & 7) | rex_r;
5477 mod = (modrm >> 6) & 3;
5478 rm = (modrm & 7) | REX_B(s);
5480 if (mod == 3) {
5481 if (s_ot == MO_SB && byte_reg_is_xH(rm)) {
5482 tcg_gen_sextract_tl(cpu_T0, cpu_regs[rm - 4], 8, 8);
5483 } else {
5484 gen_op_mov_v_reg(ot, cpu_T0, rm);
5485 switch (s_ot) {
5486 case MO_UB:
5487 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
5488 break;
5489 case MO_SB:
5490 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
5491 break;
5492 case MO_UW:
5493 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
5494 break;
5495 default:
5496 case MO_SW:
5497 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5498 break;
5501 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5502 } else {
5503 gen_lea_modrm(env, s, modrm);
5504 gen_op_ld_v(s, s_ot, cpu_T0, cpu_A0);
5505 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5508 break;
5510 case 0x8d: /* lea */
5511 modrm = cpu_ldub_code(env, s->pc++);
5512 mod = (modrm >> 6) & 3;
5513 if (mod == 3)
5514 goto illegal_op;
5515 reg = ((modrm >> 3) & 7) | rex_r;
5517 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5518 TCGv ea = gen_lea_modrm_1(a);
5519 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5520 gen_op_mov_reg_v(dflag, reg, cpu_A0);
5522 break;
5524 case 0xa0: /* mov EAX, Ov */
5525 case 0xa1:
5526 case 0xa2: /* mov Ov, EAX */
5527 case 0xa3:
5529 target_ulong offset_addr;
5531 ot = mo_b_d(b, dflag);
5532 switch (s->aflag) {
5533 #ifdef TARGET_X86_64
5534 case MO_64:
5535 offset_addr = cpu_ldq_code(env, s->pc);
5536 s->pc += 8;
5537 break;
5538 #endif
5539 default:
5540 offset_addr = insn_get(env, s, s->aflag);
5541 break;
5543 tcg_gen_movi_tl(cpu_A0, offset_addr);
5544 gen_add_A0_ds_seg(s);
5545 if ((b & 2) == 0) {
5546 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
5547 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
5548 } else {
5549 gen_op_mov_v_reg(ot, cpu_T0, R_EAX);
5550 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5553 break;
5554 case 0xd7: /* xlat */
5555 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5556 tcg_gen_ext8u_tl(cpu_T0, cpu_regs[R_EAX]);
5557 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T0);
5558 gen_extu(s->aflag, cpu_A0);
5559 gen_add_A0_ds_seg(s);
5560 gen_op_ld_v(s, MO_8, cpu_T0, cpu_A0);
5561 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
5562 break;
5563 case 0xb0 ... 0xb7: /* mov R, Ib */
5564 val = insn_get(env, s, MO_8);
5565 tcg_gen_movi_tl(cpu_T0, val);
5566 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T0);
5567 break;
5568 case 0xb8 ... 0xbf: /* mov R, Iv */
5569 #ifdef TARGET_X86_64
5570 if (dflag == MO_64) {
5571 uint64_t tmp;
5572 /* 64 bit case */
5573 tmp = cpu_ldq_code(env, s->pc);
5574 s->pc += 8;
5575 reg = (b & 7) | REX_B(s);
5576 tcg_gen_movi_tl(cpu_T0, tmp);
5577 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
5578 } else
5579 #endif
5581 ot = dflag;
5582 val = insn_get(env, s, ot);
5583 reg = (b & 7) | REX_B(s);
5584 tcg_gen_movi_tl(cpu_T0, val);
5585 gen_op_mov_reg_v(ot, reg, cpu_T0);
5587 break;
5589 case 0x91 ... 0x97: /* xchg R, EAX */
5590 do_xchg_reg_eax:
5591 ot = dflag;
5592 reg = (b & 7) | REX_B(s);
5593 rm = R_EAX;
5594 goto do_xchg_reg;
5595 case 0x86:
5596 case 0x87: /* xchg Ev, Gv */
5597 ot = mo_b_d(b, dflag);
5598 modrm = cpu_ldub_code(env, s->pc++);
5599 reg = ((modrm >> 3) & 7) | rex_r;
5600 mod = (modrm >> 6) & 3;
5601 if (mod == 3) {
5602 rm = (modrm & 7) | REX_B(s);
5603 do_xchg_reg:
5604 gen_op_mov_v_reg(ot, cpu_T0, reg);
5605 gen_op_mov_v_reg(ot, cpu_T1, rm);
5606 gen_op_mov_reg_v(ot, rm, cpu_T0);
5607 gen_op_mov_reg_v(ot, reg, cpu_T1);
5608 } else {
5609 gen_lea_modrm(env, s, modrm);
5610 gen_op_mov_v_reg(ot, cpu_T0, reg);
5611 /* for xchg, lock is implicit */
5612 tcg_gen_atomic_xchg_tl(cpu_T1, cpu_A0, cpu_T0,
5613 s->mem_index, ot | MO_LE);
5614 gen_op_mov_reg_v(ot, reg, cpu_T1);
5616 break;
5617 case 0xc4: /* les Gv */
5618 /* In CODE64 this is VEX3; see above. */
5619 op = R_ES;
5620 goto do_lxx;
5621 case 0xc5: /* lds Gv */
5622 /* In CODE64 this is VEX2; see above. */
5623 op = R_DS;
5624 goto do_lxx;
5625 case 0x1b2: /* lss Gv */
5626 op = R_SS;
5627 goto do_lxx;
5628 case 0x1b4: /* lfs Gv */
5629 op = R_FS;
5630 goto do_lxx;
5631 case 0x1b5: /* lgs Gv */
5632 op = R_GS;
5633 do_lxx:
5634 ot = dflag != MO_16 ? MO_32 : MO_16;
5635 modrm = cpu_ldub_code(env, s->pc++);
5636 reg = ((modrm >> 3) & 7) | rex_r;
5637 mod = (modrm >> 6) & 3;
5638 if (mod == 3)
5639 goto illegal_op;
5640 gen_lea_modrm(env, s, modrm);
5641 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5642 gen_add_A0_im(s, 1 << ot);
5643 /* load the segment first to handle exceptions properly */
5644 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
5645 gen_movl_seg_T0(s, op);
5646 /* then put the data */
5647 gen_op_mov_reg_v(ot, reg, cpu_T1);
5648 if (s->base.is_jmp) {
5649 gen_jmp_im(s->pc - s->cs_base);
5650 gen_eob(s);
5652 break;
5654 /************************/
5655 /* shifts */
5656 case 0xc0:
5657 case 0xc1:
5658 /* shift Ev,Ib */
5659 shift = 2;
5660 grp2:
5662 ot = mo_b_d(b, dflag);
5663 modrm = cpu_ldub_code(env, s->pc++);
5664 mod = (modrm >> 6) & 3;
5665 op = (modrm >> 3) & 7;
5667 if (mod != 3) {
5668 if (shift == 2) {
5669 s->rip_offset = 1;
5671 gen_lea_modrm(env, s, modrm);
5672 opreg = OR_TMP0;
5673 } else {
5674 opreg = (modrm & 7) | REX_B(s);
5677 /* simpler op */
5678 if (shift == 0) {
5679 gen_shift(s, op, ot, opreg, OR_ECX);
5680 } else {
5681 if (shift == 2) {
5682 shift = cpu_ldub_code(env, s->pc++);
5684 gen_shifti(s, op, ot, opreg, shift);
5687 break;
5688 case 0xd0:
5689 case 0xd1:
5690 /* shift Ev,1 */
5691 shift = 1;
5692 goto grp2;
5693 case 0xd2:
5694 case 0xd3:
5695 /* shift Ev,cl */
5696 shift = 0;
5697 goto grp2;
5699 case 0x1a4: /* shld imm */
5700 op = 0;
5701 shift = 1;
5702 goto do_shiftd;
5703 case 0x1a5: /* shld cl */
5704 op = 0;
5705 shift = 0;
5706 goto do_shiftd;
5707 case 0x1ac: /* shrd imm */
5708 op = 1;
5709 shift = 1;
5710 goto do_shiftd;
5711 case 0x1ad: /* shrd cl */
5712 op = 1;
5713 shift = 0;
5714 do_shiftd:
5715 ot = dflag;
5716 modrm = cpu_ldub_code(env, s->pc++);
5717 mod = (modrm >> 6) & 3;
5718 rm = (modrm & 7) | REX_B(s);
5719 reg = ((modrm >> 3) & 7) | rex_r;
5720 if (mod != 3) {
5721 gen_lea_modrm(env, s, modrm);
5722 opreg = OR_TMP0;
5723 } else {
5724 opreg = rm;
5726 gen_op_mov_v_reg(ot, cpu_T1, reg);
5728 if (shift) {
5729 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5730 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5731 tcg_temp_free(imm);
5732 } else {
5733 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5735 break;
5737 /************************/
5738 /* floats */
5739 case 0xd8 ... 0xdf:
5740 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5741 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5742 /* XXX: what to do if illegal op ? */
5743 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5744 break;
5746 modrm = cpu_ldub_code(env, s->pc++);
5747 mod = (modrm >> 6) & 3;
5748 rm = modrm & 7;
5749 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5750 if (mod != 3) {
5751 /* memory op */
5752 gen_lea_modrm(env, s, modrm);
5753 switch(op) {
5754 case 0x00 ... 0x07: /* fxxxs */
5755 case 0x10 ... 0x17: /* fixxxl */
5756 case 0x20 ... 0x27: /* fxxxl */
5757 case 0x30 ... 0x37: /* fixxx */
5759 int op1;
5760 op1 = op & 7;
5762 switch(op >> 4) {
5763 case 0:
5764 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5765 s->mem_index, MO_LEUL);
5766 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5767 break;
5768 case 1:
5769 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5770 s->mem_index, MO_LEUL);
5771 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5772 break;
5773 case 2:
5774 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5775 s->mem_index, MO_LEQ);
5776 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5777 break;
5778 case 3:
5779 default:
5780 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5781 s->mem_index, MO_LESW);
5782 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5783 break;
5786 gen_helper_fp_arith_ST0_FT0(op1);
5787 if (op1 == 3) {
5788 /* fcomp needs pop */
5789 gen_helper_fpop(cpu_env);
5792 break;
5793 case 0x08: /* flds */
5794 case 0x0a: /* fsts */
5795 case 0x0b: /* fstps */
5796 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5797 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5798 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5799 switch(op & 7) {
5800 case 0:
5801 switch(op >> 4) {
5802 case 0:
5803 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5804 s->mem_index, MO_LEUL);
5805 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5806 break;
5807 case 1:
5808 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5809 s->mem_index, MO_LEUL);
5810 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5811 break;
5812 case 2:
5813 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5814 s->mem_index, MO_LEQ);
5815 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5816 break;
5817 case 3:
5818 default:
5819 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5820 s->mem_index, MO_LESW);
5821 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5822 break;
5824 break;
5825 case 1:
5826 /* XXX: the corresponding CPUID bit must be tested ! */
5827 switch(op >> 4) {
5828 case 1:
5829 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5830 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5831 s->mem_index, MO_LEUL);
5832 break;
5833 case 2:
5834 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5835 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5836 s->mem_index, MO_LEQ);
5837 break;
5838 case 3:
5839 default:
5840 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5841 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5842 s->mem_index, MO_LEUW);
5843 break;
5845 gen_helper_fpop(cpu_env);
5846 break;
5847 default:
5848 switch(op >> 4) {
5849 case 0:
5850 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5851 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5852 s->mem_index, MO_LEUL);
5853 break;
5854 case 1:
5855 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5856 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5857 s->mem_index, MO_LEUL);
5858 break;
5859 case 2:
5860 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5861 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5862 s->mem_index, MO_LEQ);
5863 break;
5864 case 3:
5865 default:
5866 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5867 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5868 s->mem_index, MO_LEUW);
5869 break;
5871 if ((op & 7) == 3)
5872 gen_helper_fpop(cpu_env);
5873 break;
5875 break;
5876 case 0x0c: /* fldenv mem */
5877 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5878 break;
5879 case 0x0d: /* fldcw mem */
5880 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5881 s->mem_index, MO_LEUW);
5882 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5883 break;
5884 case 0x0e: /* fnstenv mem */
5885 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5886 break;
5887 case 0x0f: /* fnstcw mem */
5888 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5889 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5890 s->mem_index, MO_LEUW);
5891 break;
5892 case 0x1d: /* fldt mem */
5893 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5894 break;
5895 case 0x1f: /* fstpt mem */
5896 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5897 gen_helper_fpop(cpu_env);
5898 break;
5899 case 0x2c: /* frstor mem */
5900 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5901 break;
5902 case 0x2e: /* fnsave mem */
5903 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5904 break;
5905 case 0x2f: /* fnstsw mem */
5906 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5907 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5908 s->mem_index, MO_LEUW);
5909 break;
5910 case 0x3c: /* fbld */
5911 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5912 break;
5913 case 0x3e: /* fbstp */
5914 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5915 gen_helper_fpop(cpu_env);
5916 break;
5917 case 0x3d: /* fildll */
5918 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5919 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5920 break;
5921 case 0x3f: /* fistpll */
5922 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5923 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5924 gen_helper_fpop(cpu_env);
5925 break;
5926 default:
5927 goto unknown_op;
5929 } else {
5930 /* register float ops */
5931 opreg = rm;
5933 switch(op) {
5934 case 0x08: /* fld sti */
5935 gen_helper_fpush(cpu_env);
5936 gen_helper_fmov_ST0_STN(cpu_env,
5937 tcg_const_i32((opreg + 1) & 7));
5938 break;
5939 case 0x09: /* fxchg sti */
5940 case 0x29: /* fxchg4 sti, undocumented op */
5941 case 0x39: /* fxchg7 sti, undocumented op */
5942 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5943 break;
5944 case 0x0a: /* grp d9/2 */
5945 switch(rm) {
5946 case 0: /* fnop */
5947 /* check exceptions (FreeBSD FPU probe) */
5948 gen_helper_fwait(cpu_env);
5949 break;
5950 default:
5951 goto unknown_op;
5953 break;
5954 case 0x0c: /* grp d9/4 */
5955 switch(rm) {
5956 case 0: /* fchs */
5957 gen_helper_fchs_ST0(cpu_env);
5958 break;
5959 case 1: /* fabs */
5960 gen_helper_fabs_ST0(cpu_env);
5961 break;
5962 case 4: /* ftst */
5963 gen_helper_fldz_FT0(cpu_env);
5964 gen_helper_fcom_ST0_FT0(cpu_env);
5965 break;
5966 case 5: /* fxam */
5967 gen_helper_fxam_ST0(cpu_env);
5968 break;
5969 default:
5970 goto unknown_op;
5972 break;
5973 case 0x0d: /* grp d9/5 */
5975 switch(rm) {
5976 case 0:
5977 gen_helper_fpush(cpu_env);
5978 gen_helper_fld1_ST0(cpu_env);
5979 break;
5980 case 1:
5981 gen_helper_fpush(cpu_env);
5982 gen_helper_fldl2t_ST0(cpu_env);
5983 break;
5984 case 2:
5985 gen_helper_fpush(cpu_env);
5986 gen_helper_fldl2e_ST0(cpu_env);
5987 break;
5988 case 3:
5989 gen_helper_fpush(cpu_env);
5990 gen_helper_fldpi_ST0(cpu_env);
5991 break;
5992 case 4:
5993 gen_helper_fpush(cpu_env);
5994 gen_helper_fldlg2_ST0(cpu_env);
5995 break;
5996 case 5:
5997 gen_helper_fpush(cpu_env);
5998 gen_helper_fldln2_ST0(cpu_env);
5999 break;
6000 case 6:
6001 gen_helper_fpush(cpu_env);
6002 gen_helper_fldz_ST0(cpu_env);
6003 break;
6004 default:
6005 goto unknown_op;
6008 break;
6009 case 0x0e: /* grp d9/6 */
6010 switch(rm) {
6011 case 0: /* f2xm1 */
6012 gen_helper_f2xm1(cpu_env);
6013 break;
6014 case 1: /* fyl2x */
6015 gen_helper_fyl2x(cpu_env);
6016 break;
6017 case 2: /* fptan */
6018 gen_helper_fptan(cpu_env);
6019 break;
6020 case 3: /* fpatan */
6021 gen_helper_fpatan(cpu_env);
6022 break;
6023 case 4: /* fxtract */
6024 gen_helper_fxtract(cpu_env);
6025 break;
6026 case 5: /* fprem1 */
6027 gen_helper_fprem1(cpu_env);
6028 break;
6029 case 6: /* fdecstp */
6030 gen_helper_fdecstp(cpu_env);
6031 break;
6032 default:
6033 case 7: /* fincstp */
6034 gen_helper_fincstp(cpu_env);
6035 break;
6037 break;
6038 case 0x0f: /* grp d9/7 */
6039 switch(rm) {
6040 case 0: /* fprem */
6041 gen_helper_fprem(cpu_env);
6042 break;
6043 case 1: /* fyl2xp1 */
6044 gen_helper_fyl2xp1(cpu_env);
6045 break;
6046 case 2: /* fsqrt */
6047 gen_helper_fsqrt(cpu_env);
6048 break;
6049 case 3: /* fsincos */
6050 gen_helper_fsincos(cpu_env);
6051 break;
6052 case 5: /* fscale */
6053 gen_helper_fscale(cpu_env);
6054 break;
6055 case 4: /* frndint */
6056 gen_helper_frndint(cpu_env);
6057 break;
6058 case 6: /* fsin */
6059 gen_helper_fsin(cpu_env);
6060 break;
6061 default:
6062 case 7: /* fcos */
6063 gen_helper_fcos(cpu_env);
6064 break;
6066 break;
6067 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6068 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6069 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6071 int op1;
6073 op1 = op & 7;
6074 if (op >= 0x20) {
6075 gen_helper_fp_arith_STN_ST0(op1, opreg);
6076 if (op >= 0x30)
6077 gen_helper_fpop(cpu_env);
6078 } else {
6079 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6080 gen_helper_fp_arith_ST0_FT0(op1);
6083 break;
6084 case 0x02: /* fcom */
6085 case 0x22: /* fcom2, undocumented op */
6086 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6087 gen_helper_fcom_ST0_FT0(cpu_env);
6088 break;
6089 case 0x03: /* fcomp */
6090 case 0x23: /* fcomp3, undocumented op */
6091 case 0x32: /* fcomp5, undocumented op */
6092 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6093 gen_helper_fcom_ST0_FT0(cpu_env);
6094 gen_helper_fpop(cpu_env);
6095 break;
6096 case 0x15: /* da/5 */
6097 switch(rm) {
6098 case 1: /* fucompp */
6099 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6100 gen_helper_fucom_ST0_FT0(cpu_env);
6101 gen_helper_fpop(cpu_env);
6102 gen_helper_fpop(cpu_env);
6103 break;
6104 default:
6105 goto unknown_op;
6107 break;
6108 case 0x1c:
6109 switch(rm) {
6110 case 0: /* feni (287 only, just do nop here) */
6111 break;
6112 case 1: /* fdisi (287 only, just do nop here) */
6113 break;
6114 case 2: /* fclex */
6115 gen_helper_fclex(cpu_env);
6116 break;
6117 case 3: /* fninit */
6118 gen_helper_fninit(cpu_env);
6119 break;
6120 case 4: /* fsetpm (287 only, just do nop here) */
6121 break;
6122 default:
6123 goto unknown_op;
6125 break;
6126 case 0x1d: /* fucomi */
6127 if (!(s->cpuid_features & CPUID_CMOV)) {
6128 goto illegal_op;
6130 gen_update_cc_op(s);
6131 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6132 gen_helper_fucomi_ST0_FT0(cpu_env);
6133 set_cc_op(s, CC_OP_EFLAGS);
6134 break;
6135 case 0x1e: /* fcomi */
6136 if (!(s->cpuid_features & CPUID_CMOV)) {
6137 goto illegal_op;
6139 gen_update_cc_op(s);
6140 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6141 gen_helper_fcomi_ST0_FT0(cpu_env);
6142 set_cc_op(s, CC_OP_EFLAGS);
6143 break;
6144 case 0x28: /* ffree sti */
6145 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6146 break;
6147 case 0x2a: /* fst sti */
6148 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6149 break;
6150 case 0x2b: /* fstp sti */
6151 case 0x0b: /* fstp1 sti, undocumented op */
6152 case 0x3a: /* fstp8 sti, undocumented op */
6153 case 0x3b: /* fstp9 sti, undocumented op */
6154 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6155 gen_helper_fpop(cpu_env);
6156 break;
6157 case 0x2c: /* fucom st(i) */
6158 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6159 gen_helper_fucom_ST0_FT0(cpu_env);
6160 break;
6161 case 0x2d: /* fucomp st(i) */
6162 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6163 gen_helper_fucom_ST0_FT0(cpu_env);
6164 gen_helper_fpop(cpu_env);
6165 break;
6166 case 0x33: /* de/3 */
6167 switch(rm) {
6168 case 1: /* fcompp */
6169 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6170 gen_helper_fcom_ST0_FT0(cpu_env);
6171 gen_helper_fpop(cpu_env);
6172 gen_helper_fpop(cpu_env);
6173 break;
6174 default:
6175 goto unknown_op;
6177 break;
6178 case 0x38: /* ffreep sti, undocumented op */
6179 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6180 gen_helper_fpop(cpu_env);
6181 break;
6182 case 0x3c: /* df/4 */
6183 switch(rm) {
6184 case 0:
6185 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6186 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
6187 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
6188 break;
6189 default:
6190 goto unknown_op;
6192 break;
6193 case 0x3d: /* fucomip */
6194 if (!(s->cpuid_features & CPUID_CMOV)) {
6195 goto illegal_op;
6197 gen_update_cc_op(s);
6198 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6199 gen_helper_fucomi_ST0_FT0(cpu_env);
6200 gen_helper_fpop(cpu_env);
6201 set_cc_op(s, CC_OP_EFLAGS);
6202 break;
6203 case 0x3e: /* fcomip */
6204 if (!(s->cpuid_features & CPUID_CMOV)) {
6205 goto illegal_op;
6207 gen_update_cc_op(s);
6208 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6209 gen_helper_fcomi_ST0_FT0(cpu_env);
6210 gen_helper_fpop(cpu_env);
6211 set_cc_op(s, CC_OP_EFLAGS);
6212 break;
6213 case 0x10 ... 0x13: /* fcmovxx */
6214 case 0x18 ... 0x1b:
6216 int op1;
6217 TCGLabel *l1;
6218 static const uint8_t fcmov_cc[8] = {
6219 (JCC_B << 1),
6220 (JCC_Z << 1),
6221 (JCC_BE << 1),
6222 (JCC_P << 1),
6225 if (!(s->cpuid_features & CPUID_CMOV)) {
6226 goto illegal_op;
6228 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6229 l1 = gen_new_label();
6230 gen_jcc1_noeob(s, op1, l1);
6231 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6232 gen_set_label(l1);
6234 break;
6235 default:
6236 goto unknown_op;
6239 break;
6240 /************************/
6241 /* string ops */
6243 case 0xa4: /* movsS */
6244 case 0xa5:
6245 ot = mo_b_d(b, dflag);
6246 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6247 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6248 } else {
6249 gen_movs(s, ot);
6251 break;
6253 case 0xaa: /* stosS */
6254 case 0xab:
6255 ot = mo_b_d(b, dflag);
6256 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6257 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6258 } else {
6259 gen_stos(s, ot);
6261 break;
6262 case 0xac: /* lodsS */
6263 case 0xad:
6264 ot = mo_b_d(b, dflag);
6265 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6266 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6267 } else {
6268 gen_lods(s, ot);
6270 break;
6271 case 0xae: /* scasS */
6272 case 0xaf:
6273 ot = mo_b_d(b, dflag);
6274 if (prefixes & PREFIX_REPNZ) {
6275 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6276 } else if (prefixes & PREFIX_REPZ) {
6277 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6278 } else {
6279 gen_scas(s, ot);
6281 break;
6283 case 0xa6: /* cmpsS */
6284 case 0xa7:
6285 ot = mo_b_d(b, dflag);
6286 if (prefixes & PREFIX_REPNZ) {
6287 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6288 } else if (prefixes & PREFIX_REPZ) {
6289 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6290 } else {
6291 gen_cmps(s, ot);
6293 break;
6294 case 0x6c: /* insS */
6295 case 0x6d:
6296 ot = mo_b_d32(b, dflag);
6297 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6298 gen_check_io(s, ot, pc_start - s->cs_base,
6299 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6300 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6301 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6302 } else {
6303 gen_ins(s, ot);
6304 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6305 gen_jmp(s, s->pc - s->cs_base);
6308 break;
6309 case 0x6e: /* outsS */
6310 case 0x6f:
6311 ot = mo_b_d32(b, dflag);
6312 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6313 gen_check_io(s, ot, pc_start - s->cs_base,
6314 svm_is_rep(prefixes) | 4);
6315 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6316 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6317 } else {
6318 gen_outs(s, ot);
6319 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6320 gen_jmp(s, s->pc - s->cs_base);
6323 break;
6325 /************************/
6326 /* port I/O */
6328 case 0xe4:
6329 case 0xe5:
6330 ot = mo_b_d32(b, dflag);
6331 val = cpu_ldub_code(env, s->pc++);
6332 tcg_gen_movi_tl(cpu_T0, val);
6333 gen_check_io(s, ot, pc_start - s->cs_base,
6334 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6335 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6336 gen_io_start();
6338 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6339 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6340 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6341 gen_bpt_io(s, cpu_tmp2_i32, ot);
6342 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6343 gen_io_end();
6344 gen_jmp(s, s->pc - s->cs_base);
6346 break;
6347 case 0xe6:
6348 case 0xe7:
6349 ot = mo_b_d32(b, dflag);
6350 val = cpu_ldub_code(env, s->pc++);
6351 tcg_gen_movi_tl(cpu_T0, val);
6352 gen_check_io(s, ot, pc_start - s->cs_base,
6353 svm_is_rep(prefixes));
6354 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6356 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6357 gen_io_start();
6359 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6360 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6361 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6362 gen_bpt_io(s, cpu_tmp2_i32, ot);
6363 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6364 gen_io_end();
6365 gen_jmp(s, s->pc - s->cs_base);
6367 break;
6368 case 0xec:
6369 case 0xed:
6370 ot = mo_b_d32(b, dflag);
6371 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6372 gen_check_io(s, ot, pc_start - s->cs_base,
6373 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6374 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6375 gen_io_start();
6377 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6378 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6379 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6380 gen_bpt_io(s, cpu_tmp2_i32, ot);
6381 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6382 gen_io_end();
6383 gen_jmp(s, s->pc - s->cs_base);
6385 break;
6386 case 0xee:
6387 case 0xef:
6388 ot = mo_b_d32(b, dflag);
6389 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6390 gen_check_io(s, ot, pc_start - s->cs_base,
6391 svm_is_rep(prefixes));
6392 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6394 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6395 gen_io_start();
6397 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6398 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6399 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6400 gen_bpt_io(s, cpu_tmp2_i32, ot);
6401 if (s->base.tb->cflags & CF_USE_ICOUNT) {
6402 gen_io_end();
6403 gen_jmp(s, s->pc - s->cs_base);
6405 break;
6407 /************************/
6408 /* control */
6409 case 0xc2: /* ret im */
6410 val = cpu_ldsw_code(env, s->pc);
6411 s->pc += 2;
6412 ot = gen_pop_T0(s);
6413 gen_stack_update(s, val + (1 << ot));
6414 /* Note that gen_pop_T0 uses a zero-extending load. */
6415 gen_op_jmp_v(cpu_T0);
6416 gen_bnd_jmp(s);
6417 gen_jr(s, cpu_T0);
6418 break;
6419 case 0xc3: /* ret */
6420 ot = gen_pop_T0(s);
6421 gen_pop_update(s, ot);
6422 /* Note that gen_pop_T0 uses a zero-extending load. */
6423 gen_op_jmp_v(cpu_T0);
6424 gen_bnd_jmp(s);
6425 gen_jr(s, cpu_T0);
6426 break;
6427 case 0xca: /* lret im */
6428 val = cpu_ldsw_code(env, s->pc);
6429 s->pc += 2;
6430 do_lret:
6431 if (s->pe && !s->vm86) {
6432 gen_update_cc_op(s);
6433 gen_jmp_im(pc_start - s->cs_base);
6434 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6435 tcg_const_i32(val));
6436 } else {
6437 gen_stack_A0(s);
6438 /* pop offset */
6439 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6440 /* NOTE: keeping EIP updated is not a problem in case of
6441 exception */
6442 gen_op_jmp_v(cpu_T0);
6443 /* pop selector */
6444 gen_add_A0_im(s, 1 << dflag);
6445 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6446 gen_op_movl_seg_T0_vm(R_CS);
6447 /* add stack offset */
6448 gen_stack_update(s, val + (2 << dflag));
6450 gen_eob(s);
6451 break;
6452 case 0xcb: /* lret */
6453 val = 0;
6454 goto do_lret;
6455 case 0xcf: /* iret */
6456 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6457 if (!s->pe) {
6458 /* real mode */
6459 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6460 set_cc_op(s, CC_OP_EFLAGS);
6461 } else if (s->vm86) {
6462 if (s->iopl != 3) {
6463 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6464 } else {
6465 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6466 set_cc_op(s, CC_OP_EFLAGS);
6468 } else {
6469 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6470 tcg_const_i32(s->pc - s->cs_base));
6471 set_cc_op(s, CC_OP_EFLAGS);
6473 gen_eob(s);
6474 break;
6475 case 0xe8: /* call im */
6477 if (dflag != MO_16) {
6478 tval = (int32_t)insn_get(env, s, MO_32);
6479 } else {
6480 tval = (int16_t)insn_get(env, s, MO_16);
6482 next_eip = s->pc - s->cs_base;
6483 tval += next_eip;
6484 if (dflag == MO_16) {
6485 tval &= 0xffff;
6486 } else if (!CODE64(s)) {
6487 tval &= 0xffffffff;
6489 tcg_gen_movi_tl(cpu_T0, next_eip);
6490 gen_push_v(s, cpu_T0);
6491 gen_bnd_jmp(s);
6492 gen_jmp(s, tval);
6494 break;
6495 case 0x9a: /* lcall im */
6497 unsigned int selector, offset;
6499 if (CODE64(s))
6500 goto illegal_op;
6501 ot = dflag;
6502 offset = insn_get(env, s, ot);
6503 selector = insn_get(env, s, MO_16);
6505 tcg_gen_movi_tl(cpu_T0, selector);
6506 tcg_gen_movi_tl(cpu_T1, offset);
6508 goto do_lcall;
6509 case 0xe9: /* jmp im */
6510 if (dflag != MO_16) {
6511 tval = (int32_t)insn_get(env, s, MO_32);
6512 } else {
6513 tval = (int16_t)insn_get(env, s, MO_16);
6515 tval += s->pc - s->cs_base;
6516 if (dflag == MO_16) {
6517 tval &= 0xffff;
6518 } else if (!CODE64(s)) {
6519 tval &= 0xffffffff;
6521 gen_bnd_jmp(s);
6522 gen_jmp(s, tval);
6523 break;
6524 case 0xea: /* ljmp im */
6526 unsigned int selector, offset;
6528 if (CODE64(s))
6529 goto illegal_op;
6530 ot = dflag;
6531 offset = insn_get(env, s, ot);
6532 selector = insn_get(env, s, MO_16);
6534 tcg_gen_movi_tl(cpu_T0, selector);
6535 tcg_gen_movi_tl(cpu_T1, offset);
6537 goto do_ljmp;
6538 case 0xeb: /* jmp Jb */
6539 tval = (int8_t)insn_get(env, s, MO_8);
6540 tval += s->pc - s->cs_base;
6541 if (dflag == MO_16) {
6542 tval &= 0xffff;
6544 gen_jmp(s, tval);
6545 break;
6546 case 0x70 ... 0x7f: /* jcc Jb */
6547 tval = (int8_t)insn_get(env, s, MO_8);
6548 goto do_jcc;
6549 case 0x180 ... 0x18f: /* jcc Jv */
6550 if (dflag != MO_16) {
6551 tval = (int32_t)insn_get(env, s, MO_32);
6552 } else {
6553 tval = (int16_t)insn_get(env, s, MO_16);
6555 do_jcc:
6556 next_eip = s->pc - s->cs_base;
6557 tval += next_eip;
6558 if (dflag == MO_16) {
6559 tval &= 0xffff;
6561 gen_bnd_jmp(s);
6562 gen_jcc(s, b, tval, next_eip);
6563 break;
6565 case 0x190 ... 0x19f: /* setcc Gv */
6566 modrm = cpu_ldub_code(env, s->pc++);
6567 gen_setcc1(s, b, cpu_T0);
6568 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6569 break;
6570 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6571 if (!(s->cpuid_features & CPUID_CMOV)) {
6572 goto illegal_op;
6574 ot = dflag;
6575 modrm = cpu_ldub_code(env, s->pc++);
6576 reg = ((modrm >> 3) & 7) | rex_r;
6577 gen_cmovcc1(env, s, ot, b, modrm, reg);
6578 break;
6580 /************************/
6581 /* flags */
6582 case 0x9c: /* pushf */
6583 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6584 if (s->vm86 && s->iopl != 3) {
6585 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6586 } else {
6587 gen_update_cc_op(s);
6588 gen_helper_read_eflags(cpu_T0, cpu_env);
6589 gen_push_v(s, cpu_T0);
6591 break;
6592 case 0x9d: /* popf */
6593 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6594 if (s->vm86 && s->iopl != 3) {
6595 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6596 } else {
6597 ot = gen_pop_T0(s);
6598 if (s->cpl == 0) {
6599 if (dflag != MO_16) {
6600 gen_helper_write_eflags(cpu_env, cpu_T0,
6601 tcg_const_i32((TF_MASK | AC_MASK |
6602 ID_MASK | NT_MASK |
6603 IF_MASK |
6604 IOPL_MASK)));
6605 } else {
6606 gen_helper_write_eflags(cpu_env, cpu_T0,
6607 tcg_const_i32((TF_MASK | AC_MASK |
6608 ID_MASK | NT_MASK |
6609 IF_MASK | IOPL_MASK)
6610 & 0xffff));
6612 } else {
6613 if (s->cpl <= s->iopl) {
6614 if (dflag != MO_16) {
6615 gen_helper_write_eflags(cpu_env, cpu_T0,
6616 tcg_const_i32((TF_MASK |
6617 AC_MASK |
6618 ID_MASK |
6619 NT_MASK |
6620 IF_MASK)));
6621 } else {
6622 gen_helper_write_eflags(cpu_env, cpu_T0,
6623 tcg_const_i32((TF_MASK |
6624 AC_MASK |
6625 ID_MASK |
6626 NT_MASK |
6627 IF_MASK)
6628 & 0xffff));
6630 } else {
6631 if (dflag != MO_16) {
6632 gen_helper_write_eflags(cpu_env, cpu_T0,
6633 tcg_const_i32((TF_MASK | AC_MASK |
6634 ID_MASK | NT_MASK)));
6635 } else {
6636 gen_helper_write_eflags(cpu_env, cpu_T0,
6637 tcg_const_i32((TF_MASK | AC_MASK |
6638 ID_MASK | NT_MASK)
6639 & 0xffff));
6643 gen_pop_update(s, ot);
6644 set_cc_op(s, CC_OP_EFLAGS);
6645 /* abort translation because TF/AC flag may change */
6646 gen_jmp_im(s->pc - s->cs_base);
6647 gen_eob(s);
6649 break;
6650 case 0x9e: /* sahf */
6651 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6652 goto illegal_op;
6653 gen_op_mov_v_reg(MO_8, cpu_T0, R_AH);
6654 gen_compute_eflags(s);
6655 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6656 tcg_gen_andi_tl(cpu_T0, cpu_T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6657 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T0);
6658 break;
6659 case 0x9f: /* lahf */
6660 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6661 goto illegal_op;
6662 gen_compute_eflags(s);
6663 /* Note: gen_compute_eflags() only gives the condition codes */
6664 tcg_gen_ori_tl(cpu_T0, cpu_cc_src, 0x02);
6665 gen_op_mov_reg_v(MO_8, R_AH, cpu_T0);
6666 break;
6667 case 0xf5: /* cmc */
6668 gen_compute_eflags(s);
6669 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6670 break;
6671 case 0xf8: /* clc */
6672 gen_compute_eflags(s);
6673 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6674 break;
6675 case 0xf9: /* stc */
6676 gen_compute_eflags(s);
6677 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6678 break;
6679 case 0xfc: /* cld */
6680 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6681 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6682 break;
6683 case 0xfd: /* std */
6684 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6685 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6686 break;
6688 /************************/
6689 /* bit operations */
6690 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6691 ot = dflag;
6692 modrm = cpu_ldub_code(env, s->pc++);
6693 op = (modrm >> 3) & 7;
6694 mod = (modrm >> 6) & 3;
6695 rm = (modrm & 7) | REX_B(s);
6696 if (mod != 3) {
6697 s->rip_offset = 1;
6698 gen_lea_modrm(env, s, modrm);
6699 if (!(s->prefix & PREFIX_LOCK)) {
6700 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6702 } else {
6703 gen_op_mov_v_reg(ot, cpu_T0, rm);
6705 /* load shift */
6706 val = cpu_ldub_code(env, s->pc++);
6707 tcg_gen_movi_tl(cpu_T1, val);
6708 if (op < 4)
6709 goto unknown_op;
6710 op -= 4;
6711 goto bt_op;
6712 case 0x1a3: /* bt Gv, Ev */
6713 op = 0;
6714 goto do_btx;
6715 case 0x1ab: /* bts */
6716 op = 1;
6717 goto do_btx;
6718 case 0x1b3: /* btr */
6719 op = 2;
6720 goto do_btx;
6721 case 0x1bb: /* btc */
6722 op = 3;
6723 do_btx:
6724 ot = dflag;
6725 modrm = cpu_ldub_code(env, s->pc++);
6726 reg = ((modrm >> 3) & 7) | rex_r;
6727 mod = (modrm >> 6) & 3;
6728 rm = (modrm & 7) | REX_B(s);
6729 gen_op_mov_v_reg(MO_32, cpu_T1, reg);
6730 if (mod != 3) {
6731 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6732 /* specific case: we need to add a displacement */
6733 gen_exts(ot, cpu_T1);
6734 tcg_gen_sari_tl(cpu_tmp0, cpu_T1, 3 + ot);
6735 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6736 tcg_gen_add_tl(cpu_A0, gen_lea_modrm_1(a), cpu_tmp0);
6737 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
6738 if (!(s->prefix & PREFIX_LOCK)) {
6739 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6741 } else {
6742 gen_op_mov_v_reg(ot, cpu_T0, rm);
6744 bt_op:
6745 tcg_gen_andi_tl(cpu_T1, cpu_T1, (1 << (3 + ot)) - 1);
6746 tcg_gen_movi_tl(cpu_tmp0, 1);
6747 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6748 if (s->prefix & PREFIX_LOCK) {
6749 switch (op) {
6750 case 0: /* bt */
6751 /* Needs no atomic ops; we surpressed the normal
6752 memory load for LOCK above so do it now. */
6753 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6754 break;
6755 case 1: /* bts */
6756 tcg_gen_atomic_fetch_or_tl(cpu_T0, cpu_A0, cpu_tmp0,
6757 s->mem_index, ot | MO_LE);
6758 break;
6759 case 2: /* btr */
6760 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
6761 tcg_gen_atomic_fetch_and_tl(cpu_T0, cpu_A0, cpu_tmp0,
6762 s->mem_index, ot | MO_LE);
6763 break;
6764 default:
6765 case 3: /* btc */
6766 tcg_gen_atomic_fetch_xor_tl(cpu_T0, cpu_A0, cpu_tmp0,
6767 s->mem_index, ot | MO_LE);
6768 break;
6770 tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1);
6771 } else {
6772 tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1);
6773 switch (op) {
6774 case 0: /* bt */
6775 /* Data already loaded; nothing to do. */
6776 break;
6777 case 1: /* bts */
6778 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
6779 break;
6780 case 2: /* btr */
6781 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_tmp0);
6782 break;
6783 default:
6784 case 3: /* btc */
6785 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_tmp0);
6786 break;
6788 if (op != 0) {
6789 if (mod != 3) {
6790 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
6791 } else {
6792 gen_op_mov_reg_v(ot, rm, cpu_T0);
6797 /* Delay all CC updates until after the store above. Note that
6798 C is the result of the test, Z is unchanged, and the others
6799 are all undefined. */
6800 switch (s->cc_op) {
6801 case CC_OP_MULB ... CC_OP_MULQ:
6802 case CC_OP_ADDB ... CC_OP_ADDQ:
6803 case CC_OP_ADCB ... CC_OP_ADCQ:
6804 case CC_OP_SUBB ... CC_OP_SUBQ:
6805 case CC_OP_SBBB ... CC_OP_SBBQ:
6806 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6807 case CC_OP_INCB ... CC_OP_INCQ:
6808 case CC_OP_DECB ... CC_OP_DECQ:
6809 case CC_OP_SHLB ... CC_OP_SHLQ:
6810 case CC_OP_SARB ... CC_OP_SARQ:
6811 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6812 /* Z was going to be computed from the non-zero status of CC_DST.
6813 We can get that same Z value (and the new C value) by leaving
6814 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6815 same width. */
6816 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6817 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6818 break;
6819 default:
6820 /* Otherwise, generate EFLAGS and replace the C bit. */
6821 gen_compute_eflags(s);
6822 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6823 ctz32(CC_C), 1);
6824 break;
6826 break;
6827 case 0x1bc: /* bsf / tzcnt */
6828 case 0x1bd: /* bsr / lzcnt */
6829 ot = dflag;
6830 modrm = cpu_ldub_code(env, s->pc++);
6831 reg = ((modrm >> 3) & 7) | rex_r;
6832 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6833 gen_extu(ot, cpu_T0);
6835 /* Note that lzcnt and tzcnt are in different extensions. */
6836 if ((prefixes & PREFIX_REPZ)
6837 && (b & 1
6838 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6839 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6840 int size = 8 << ot;
6841 /* For lzcnt/tzcnt, C bit is defined related to the input. */
6842 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
6843 if (b & 1) {
6844 /* For lzcnt, reduce the target_ulong result by the
6845 number of zeros that we expect to find at the top. */
6846 tcg_gen_clzi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS);
6847 tcg_gen_subi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - size);
6848 } else {
6849 /* For tzcnt, a zero input must return the operand size. */
6850 tcg_gen_ctzi_tl(cpu_T0, cpu_T0, size);
6852 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
6853 gen_op_update1_cc();
6854 set_cc_op(s, CC_OP_BMILGB + ot);
6855 } else {
6856 /* For bsr/bsf, only the Z bit is defined and it is related
6857 to the input and not the result. */
6858 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
6859 set_cc_op(s, CC_OP_LOGICB + ot);
6861 /* ??? The manual says that the output is undefined when the
6862 input is zero, but real hardware leaves it unchanged, and
6863 real programs appear to depend on that. Accomplish this
6864 by passing the output as the value to return upon zero. */
6865 if (b & 1) {
6866 /* For bsr, return the bit index of the first 1 bit,
6867 not the count of leading zeros. */
6868 tcg_gen_xori_tl(cpu_T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
6869 tcg_gen_clz_tl(cpu_T0, cpu_T0, cpu_T1);
6870 tcg_gen_xori_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - 1);
6871 } else {
6872 tcg_gen_ctz_tl(cpu_T0, cpu_T0, cpu_regs[reg]);
6875 gen_op_mov_reg_v(ot, reg, cpu_T0);
6876 break;
6877 /************************/
6878 /* bcd */
6879 case 0x27: /* daa */
6880 if (CODE64(s))
6881 goto illegal_op;
6882 gen_update_cc_op(s);
6883 gen_helper_daa(cpu_env);
6884 set_cc_op(s, CC_OP_EFLAGS);
6885 break;
6886 case 0x2f: /* das */
6887 if (CODE64(s))
6888 goto illegal_op;
6889 gen_update_cc_op(s);
6890 gen_helper_das(cpu_env);
6891 set_cc_op(s, CC_OP_EFLAGS);
6892 break;
6893 case 0x37: /* aaa */
6894 if (CODE64(s))
6895 goto illegal_op;
6896 gen_update_cc_op(s);
6897 gen_helper_aaa(cpu_env);
6898 set_cc_op(s, CC_OP_EFLAGS);
6899 break;
6900 case 0x3f: /* aas */
6901 if (CODE64(s))
6902 goto illegal_op;
6903 gen_update_cc_op(s);
6904 gen_helper_aas(cpu_env);
6905 set_cc_op(s, CC_OP_EFLAGS);
6906 break;
6907 case 0xd4: /* aam */
6908 if (CODE64(s))
6909 goto illegal_op;
6910 val = cpu_ldub_code(env, s->pc++);
6911 if (val == 0) {
6912 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6913 } else {
6914 gen_helper_aam(cpu_env, tcg_const_i32(val));
6915 set_cc_op(s, CC_OP_LOGICB);
6917 break;
6918 case 0xd5: /* aad */
6919 if (CODE64(s))
6920 goto illegal_op;
6921 val = cpu_ldub_code(env, s->pc++);
6922 gen_helper_aad(cpu_env, tcg_const_i32(val));
6923 set_cc_op(s, CC_OP_LOGICB);
6924 break;
6925 /************************/
6926 /* misc */
6927 case 0x90: /* nop */
6928 /* XXX: correct lock test for all insn */
6929 if (prefixes & PREFIX_LOCK) {
6930 goto illegal_op;
6932 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6933 if (REX_B(s)) {
6934 goto do_xchg_reg_eax;
6936 if (prefixes & PREFIX_REPZ) {
6937 gen_update_cc_op(s);
6938 gen_jmp_im(pc_start - s->cs_base);
6939 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6940 s->base.is_jmp = DISAS_NORETURN;
6942 break;
6943 case 0x9b: /* fwait */
6944 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6945 (HF_MP_MASK | HF_TS_MASK)) {
6946 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6947 } else {
6948 gen_helper_fwait(cpu_env);
6950 break;
6951 case 0xcc: /* int3 */
6952 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6953 break;
6954 case 0xcd: /* int N */
6955 val = cpu_ldub_code(env, s->pc++);
6956 if (s->vm86 && s->iopl != 3) {
6957 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6958 } else {
6959 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6961 break;
6962 case 0xce: /* into */
6963 if (CODE64(s))
6964 goto illegal_op;
6965 gen_update_cc_op(s);
6966 gen_jmp_im(pc_start - s->cs_base);
6967 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6968 break;
6969 #ifdef WANT_ICEBP
6970 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6971 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6972 #if 1
6973 gen_debug(s, pc_start - s->cs_base);
6974 #else
6975 /* start debug */
6976 tb_flush(CPU(x86_env_get_cpu(env)));
6977 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6978 #endif
6979 break;
6980 #endif
6981 case 0xfa: /* cli */
6982 if (!s->vm86) {
6983 if (s->cpl <= s->iopl) {
6984 gen_helper_cli(cpu_env);
6985 } else {
6986 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6988 } else {
6989 if (s->iopl == 3) {
6990 gen_helper_cli(cpu_env);
6991 } else {
6992 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6995 break;
6996 case 0xfb: /* sti */
6997 if (s->vm86 ? s->iopl == 3 : s->cpl <= s->iopl) {
6998 gen_helper_sti(cpu_env);
6999 /* interruptions are enabled only the first insn after sti */
7000 gen_jmp_im(s->pc - s->cs_base);
7001 gen_eob_inhibit_irq(s, true);
7002 } else {
7003 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7005 break;
7006 case 0x62: /* bound */
7007 if (CODE64(s))
7008 goto illegal_op;
7009 ot = dflag;
7010 modrm = cpu_ldub_code(env, s->pc++);
7011 reg = (modrm >> 3) & 7;
7012 mod = (modrm >> 6) & 3;
7013 if (mod == 3)
7014 goto illegal_op;
7015 gen_op_mov_v_reg(ot, cpu_T0, reg);
7016 gen_lea_modrm(env, s, modrm);
7017 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
7018 if (ot == MO_16) {
7019 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
7020 } else {
7021 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
7023 break;
7024 case 0x1c8 ... 0x1cf: /* bswap reg */
7025 reg = (b & 7) | REX_B(s);
7026 #ifdef TARGET_X86_64
7027 if (dflag == MO_64) {
7028 gen_op_mov_v_reg(MO_64, cpu_T0, reg);
7029 tcg_gen_bswap64_i64(cpu_T0, cpu_T0);
7030 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
7031 } else
7032 #endif
7034 gen_op_mov_v_reg(MO_32, cpu_T0, reg);
7035 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
7036 tcg_gen_bswap32_tl(cpu_T0, cpu_T0);
7037 gen_op_mov_reg_v(MO_32, reg, cpu_T0);
7039 break;
7040 case 0xd6: /* salc */
7041 if (CODE64(s))
7042 goto illegal_op;
7043 gen_compute_eflags_c(s, cpu_T0);
7044 tcg_gen_neg_tl(cpu_T0, cpu_T0);
7045 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
7046 break;
7047 case 0xe0: /* loopnz */
7048 case 0xe1: /* loopz */
7049 case 0xe2: /* loop */
7050 case 0xe3: /* jecxz */
7052 TCGLabel *l1, *l2, *l3;
7054 tval = (int8_t)insn_get(env, s, MO_8);
7055 next_eip = s->pc - s->cs_base;
7056 tval += next_eip;
7057 if (dflag == MO_16) {
7058 tval &= 0xffff;
7061 l1 = gen_new_label();
7062 l2 = gen_new_label();
7063 l3 = gen_new_label();
7064 b &= 3;
7065 switch(b) {
7066 case 0: /* loopnz */
7067 case 1: /* loopz */
7068 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7069 gen_op_jz_ecx(s->aflag, l3);
7070 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7071 break;
7072 case 2: /* loop */
7073 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7074 gen_op_jnz_ecx(s->aflag, l1);
7075 break;
7076 default:
7077 case 3: /* jcxz */
7078 gen_op_jz_ecx(s->aflag, l1);
7079 break;
7082 gen_set_label(l3);
7083 gen_jmp_im(next_eip);
7084 tcg_gen_br(l2);
7086 gen_set_label(l1);
7087 gen_jmp_im(tval);
7088 gen_set_label(l2);
7089 gen_eob(s);
7091 break;
7092 case 0x130: /* wrmsr */
7093 case 0x132: /* rdmsr */
7094 if (s->cpl != 0) {
7095 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7096 } else {
7097 gen_update_cc_op(s);
7098 gen_jmp_im(pc_start - s->cs_base);
7099 if (b & 2) {
7100 gen_helper_rdmsr(cpu_env);
7101 } else {
7102 gen_helper_wrmsr(cpu_env);
7105 break;
7106 case 0x131: /* rdtsc */
7107 gen_update_cc_op(s);
7108 gen_jmp_im(pc_start - s->cs_base);
7109 if (s->base.tb->cflags & CF_USE_ICOUNT) {
7110 gen_io_start();
7112 gen_helper_rdtsc(cpu_env);
7113 if (s->base.tb->cflags & CF_USE_ICOUNT) {
7114 gen_io_end();
7115 gen_jmp(s, s->pc - s->cs_base);
7117 break;
7118 case 0x133: /* rdpmc */
7119 gen_update_cc_op(s);
7120 gen_jmp_im(pc_start - s->cs_base);
7121 gen_helper_rdpmc(cpu_env);
7122 break;
7123 case 0x134: /* sysenter */
7124 /* For Intel SYSENTER is valid on 64-bit */
7125 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7126 goto illegal_op;
7127 if (!s->pe) {
7128 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7129 } else {
7130 gen_helper_sysenter(cpu_env);
7131 gen_eob(s);
7133 break;
7134 case 0x135: /* sysexit */
7135 /* For Intel SYSEXIT is valid on 64-bit */
7136 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7137 goto illegal_op;
7138 if (!s->pe) {
7139 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7140 } else {
7141 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7142 gen_eob(s);
7144 break;
7145 #ifdef TARGET_X86_64
7146 case 0x105: /* syscall */
7147 /* XXX: is it usable in real mode ? */
7148 gen_update_cc_op(s);
7149 gen_jmp_im(pc_start - s->cs_base);
7150 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7151 /* TF handling for the syscall insn is different. The TF bit is checked
7152 after the syscall insn completes. This allows #DB to not be
7153 generated after one has entered CPL0 if TF is set in FMASK. */
7154 gen_eob_worker(s, false, true);
7155 break;
7156 case 0x107: /* sysret */
7157 if (!s->pe) {
7158 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7159 } else {
7160 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7161 /* condition codes are modified only in long mode */
7162 if (s->lma) {
7163 set_cc_op(s, CC_OP_EFLAGS);
7165 /* TF handling for the sysret insn is different. The TF bit is
7166 checked after the sysret insn completes. This allows #DB to be
7167 generated "as if" the syscall insn in userspace has just
7168 completed. */
7169 gen_eob_worker(s, false, true);
7171 break;
7172 #endif
7173 case 0x1a2: /* cpuid */
7174 gen_update_cc_op(s);
7175 gen_jmp_im(pc_start - s->cs_base);
7176 gen_helper_cpuid(cpu_env);
7177 break;
7178 case 0xf4: /* hlt */
7179 if (s->cpl != 0) {
7180 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7181 } else {
7182 gen_update_cc_op(s);
7183 gen_jmp_im(pc_start - s->cs_base);
7184 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7185 s->base.is_jmp = DISAS_NORETURN;
7187 break;
7188 case 0x100:
7189 modrm = cpu_ldub_code(env, s->pc++);
7190 mod = (modrm >> 6) & 3;
7191 op = (modrm >> 3) & 7;
7192 switch(op) {
7193 case 0: /* sldt */
7194 if (!s->pe || s->vm86)
7195 goto illegal_op;
7196 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7197 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
7198 offsetof(CPUX86State, ldt.selector));
7199 ot = mod == 3 ? dflag : MO_16;
7200 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7201 break;
7202 case 2: /* lldt */
7203 if (!s->pe || s->vm86)
7204 goto illegal_op;
7205 if (s->cpl != 0) {
7206 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7207 } else {
7208 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7209 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7210 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
7211 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7213 break;
7214 case 1: /* str */
7215 if (!s->pe || s->vm86)
7216 goto illegal_op;
7217 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7218 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
7219 offsetof(CPUX86State, tr.selector));
7220 ot = mod == 3 ? dflag : MO_16;
7221 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7222 break;
7223 case 3: /* ltr */
7224 if (!s->pe || s->vm86)
7225 goto illegal_op;
7226 if (s->cpl != 0) {
7227 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7228 } else {
7229 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7230 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7231 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
7232 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7234 break;
7235 case 4: /* verr */
7236 case 5: /* verw */
7237 if (!s->pe || s->vm86)
7238 goto illegal_op;
7239 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7240 gen_update_cc_op(s);
7241 if (op == 4) {
7242 gen_helper_verr(cpu_env, cpu_T0);
7243 } else {
7244 gen_helper_verw(cpu_env, cpu_T0);
7246 set_cc_op(s, CC_OP_EFLAGS);
7247 break;
7248 default:
7249 goto unknown_op;
7251 break;
7253 case 0x101:
7254 modrm = cpu_ldub_code(env, s->pc++);
7255 switch (modrm) {
7256 CASE_MODRM_MEM_OP(0): /* sgdt */
7257 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7258 gen_lea_modrm(env, s, modrm);
7259 tcg_gen_ld32u_tl(cpu_T0,
7260 cpu_env, offsetof(CPUX86State, gdt.limit));
7261 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7262 gen_add_A0_im(s, 2);
7263 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7264 if (dflag == MO_16) {
7265 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7267 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7268 break;
7270 case 0xc8: /* monitor */
7271 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7272 goto illegal_op;
7274 gen_update_cc_op(s);
7275 gen_jmp_im(pc_start - s->cs_base);
7276 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7277 gen_extu(s->aflag, cpu_A0);
7278 gen_add_A0_ds_seg(s);
7279 gen_helper_monitor(cpu_env, cpu_A0);
7280 break;
7282 case 0xc9: /* mwait */
7283 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7284 goto illegal_op;
7286 gen_update_cc_op(s);
7287 gen_jmp_im(pc_start - s->cs_base);
7288 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7289 gen_eob(s);
7290 break;
7292 case 0xca: /* clac */
7293 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7294 || s->cpl != 0) {
7295 goto illegal_op;
7297 gen_helper_clac(cpu_env);
7298 gen_jmp_im(s->pc - s->cs_base);
7299 gen_eob(s);
7300 break;
7302 case 0xcb: /* stac */
7303 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7304 || s->cpl != 0) {
7305 goto illegal_op;
7307 gen_helper_stac(cpu_env);
7308 gen_jmp_im(s->pc - s->cs_base);
7309 gen_eob(s);
7310 break;
7312 CASE_MODRM_MEM_OP(1): /* sidt */
7313 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7314 gen_lea_modrm(env, s, modrm);
7315 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.limit));
7316 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7317 gen_add_A0_im(s, 2);
7318 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base));
7319 if (dflag == MO_16) {
7320 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7322 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7323 break;
7325 case 0xd0: /* xgetbv */
7326 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7327 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7328 | PREFIX_REPZ | PREFIX_REPNZ))) {
7329 goto illegal_op;
7331 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7332 gen_helper_xgetbv(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7333 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7334 break;
7336 case 0xd1: /* xsetbv */
7337 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7338 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7339 | PREFIX_REPZ | PREFIX_REPNZ))) {
7340 goto illegal_op;
7342 if (s->cpl != 0) {
7343 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7344 break;
7346 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7347 cpu_regs[R_EDX]);
7348 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7349 gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7350 /* End TB because translation flags may change. */
7351 gen_jmp_im(s->pc - s->cs_base);
7352 gen_eob(s);
7353 break;
7355 case 0xd8: /* VMRUN */
7356 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7357 goto illegal_op;
7359 if (s->cpl != 0) {
7360 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7361 break;
7363 gen_update_cc_op(s);
7364 gen_jmp_im(pc_start - s->cs_base);
7365 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7366 tcg_const_i32(s->pc - pc_start));
7367 tcg_gen_exit_tb(0);
7368 s->base.is_jmp = DISAS_NORETURN;
7369 break;
7371 case 0xd9: /* VMMCALL */
7372 if (!(s->flags & HF_SVME_MASK)) {
7373 goto illegal_op;
7375 gen_update_cc_op(s);
7376 gen_jmp_im(pc_start - s->cs_base);
7377 gen_helper_vmmcall(cpu_env);
7378 break;
7380 case 0xda: /* VMLOAD */
7381 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7382 goto illegal_op;
7384 if (s->cpl != 0) {
7385 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7386 break;
7388 gen_update_cc_op(s);
7389 gen_jmp_im(pc_start - s->cs_base);
7390 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7391 break;
7393 case 0xdb: /* VMSAVE */
7394 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7395 goto illegal_op;
7397 if (s->cpl != 0) {
7398 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7399 break;
7401 gen_update_cc_op(s);
7402 gen_jmp_im(pc_start - s->cs_base);
7403 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7404 break;
7406 case 0xdc: /* STGI */
7407 if ((!(s->flags & HF_SVME_MASK)
7408 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7409 || !s->pe) {
7410 goto illegal_op;
7412 if (s->cpl != 0) {
7413 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7414 break;
7416 gen_update_cc_op(s);
7417 gen_jmp_im(pc_start - s->cs_base);
7418 gen_helper_stgi(cpu_env);
7419 break;
7421 case 0xdd: /* CLGI */
7422 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7423 goto illegal_op;
7425 if (s->cpl != 0) {
7426 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7427 break;
7429 gen_update_cc_op(s);
7430 gen_jmp_im(pc_start - s->cs_base);
7431 gen_helper_clgi(cpu_env);
7432 break;
7434 case 0xde: /* SKINIT */
7435 if ((!(s->flags & HF_SVME_MASK)
7436 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7437 || !s->pe) {
7438 goto illegal_op;
7440 gen_update_cc_op(s);
7441 gen_jmp_im(pc_start - s->cs_base);
7442 gen_helper_skinit(cpu_env);
7443 break;
7445 case 0xdf: /* INVLPGA */
7446 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7447 goto illegal_op;
7449 if (s->cpl != 0) {
7450 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7451 break;
7453 gen_update_cc_op(s);
7454 gen_jmp_im(pc_start - s->cs_base);
7455 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7456 break;
7458 CASE_MODRM_MEM_OP(2): /* lgdt */
7459 if (s->cpl != 0) {
7460 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7461 break;
7463 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE);
7464 gen_lea_modrm(env, s, modrm);
7465 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7466 gen_add_A0_im(s, 2);
7467 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7468 if (dflag == MO_16) {
7469 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7471 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7472 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7473 break;
7475 CASE_MODRM_MEM_OP(3): /* lidt */
7476 if (s->cpl != 0) {
7477 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7478 break;
7480 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7481 gen_lea_modrm(env, s, modrm);
7482 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7483 gen_add_A0_im(s, 2);
7484 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7485 if (dflag == MO_16) {
7486 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7488 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base));
7489 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, idt.limit));
7490 break;
7492 CASE_MODRM_OP(4): /* smsw */
7493 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7494 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, cr[0]));
7495 if (CODE64(s)) {
7496 mod = (modrm >> 6) & 3;
7497 ot = (mod != 3 ? MO_16 : s->dflag);
7498 } else {
7499 ot = MO_16;
7501 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7502 break;
7503 case 0xee: /* rdpkru */
7504 if (prefixes & PREFIX_LOCK) {
7505 goto illegal_op;
7507 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7508 gen_helper_rdpkru(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7509 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7510 break;
7511 case 0xef: /* wrpkru */
7512 if (prefixes & PREFIX_LOCK) {
7513 goto illegal_op;
7515 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7516 cpu_regs[R_EDX]);
7517 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7518 gen_helper_wrpkru(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7519 break;
7520 CASE_MODRM_OP(6): /* lmsw */
7521 if (s->cpl != 0) {
7522 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7523 break;
7525 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7526 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7527 gen_helper_lmsw(cpu_env, cpu_T0);
7528 gen_jmp_im(s->pc - s->cs_base);
7529 gen_eob(s);
7530 break;
7532 CASE_MODRM_MEM_OP(7): /* invlpg */
7533 if (s->cpl != 0) {
7534 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7535 break;
7537 gen_update_cc_op(s);
7538 gen_jmp_im(pc_start - s->cs_base);
7539 gen_lea_modrm(env, s, modrm);
7540 gen_helper_invlpg(cpu_env, cpu_A0);
7541 gen_jmp_im(s->pc - s->cs_base);
7542 gen_eob(s);
7543 break;
7545 case 0xf8: /* swapgs */
7546 #ifdef TARGET_X86_64
7547 if (CODE64(s)) {
7548 if (s->cpl != 0) {
7549 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7550 } else {
7551 tcg_gen_mov_tl(cpu_T0, cpu_seg_base[R_GS]);
7552 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7553 offsetof(CPUX86State, kernelgsbase));
7554 tcg_gen_st_tl(cpu_T0, cpu_env,
7555 offsetof(CPUX86State, kernelgsbase));
7557 break;
7559 #endif
7560 goto illegal_op;
7562 case 0xf9: /* rdtscp */
7563 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7564 goto illegal_op;
7566 gen_update_cc_op(s);
7567 gen_jmp_im(pc_start - s->cs_base);
7568 if (s->base.tb->cflags & CF_USE_ICOUNT) {
7569 gen_io_start();
7571 gen_helper_rdtscp(cpu_env);
7572 if (s->base.tb->cflags & CF_USE_ICOUNT) {
7573 gen_io_end();
7574 gen_jmp(s, s->pc - s->cs_base);
7576 break;
7578 default:
7579 goto unknown_op;
7581 break;
7583 case 0x108: /* invd */
7584 case 0x109: /* wbinvd */
7585 if (s->cpl != 0) {
7586 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7587 } else {
7588 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7589 /* nothing to do */
7591 break;
7592 case 0x63: /* arpl or movslS (x86_64) */
7593 #ifdef TARGET_X86_64
7594 if (CODE64(s)) {
7595 int d_ot;
7596 /* d_ot is the size of destination */
7597 d_ot = dflag;
7599 modrm = cpu_ldub_code(env, s->pc++);
7600 reg = ((modrm >> 3) & 7) | rex_r;
7601 mod = (modrm >> 6) & 3;
7602 rm = (modrm & 7) | REX_B(s);
7604 if (mod == 3) {
7605 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
7606 /* sign extend */
7607 if (d_ot == MO_64) {
7608 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
7610 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7611 } else {
7612 gen_lea_modrm(env, s, modrm);
7613 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T0, cpu_A0);
7614 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7616 } else
7617 #endif
7619 TCGLabel *label1;
7620 TCGv t0, t1, t2, a0;
7622 if (!s->pe || s->vm86)
7623 goto illegal_op;
7624 t0 = tcg_temp_local_new();
7625 t1 = tcg_temp_local_new();
7626 t2 = tcg_temp_local_new();
7627 ot = MO_16;
7628 modrm = cpu_ldub_code(env, s->pc++);
7629 reg = (modrm >> 3) & 7;
7630 mod = (modrm >> 6) & 3;
7631 rm = modrm & 7;
7632 if (mod != 3) {
7633 gen_lea_modrm(env, s, modrm);
7634 gen_op_ld_v(s, ot, t0, cpu_A0);
7635 a0 = tcg_temp_local_new();
7636 tcg_gen_mov_tl(a0, cpu_A0);
7637 } else {
7638 gen_op_mov_v_reg(ot, t0, rm);
7639 TCGV_UNUSED(a0);
7641 gen_op_mov_v_reg(ot, t1, reg);
7642 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7643 tcg_gen_andi_tl(t1, t1, 3);
7644 tcg_gen_movi_tl(t2, 0);
7645 label1 = gen_new_label();
7646 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7647 tcg_gen_andi_tl(t0, t0, ~3);
7648 tcg_gen_or_tl(t0, t0, t1);
7649 tcg_gen_movi_tl(t2, CC_Z);
7650 gen_set_label(label1);
7651 if (mod != 3) {
7652 gen_op_st_v(s, ot, t0, a0);
7653 tcg_temp_free(a0);
7654 } else {
7655 gen_op_mov_reg_v(ot, rm, t0);
7657 gen_compute_eflags(s);
7658 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7659 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7660 tcg_temp_free(t0);
7661 tcg_temp_free(t1);
7662 tcg_temp_free(t2);
7664 break;
7665 case 0x102: /* lar */
7666 case 0x103: /* lsl */
7668 TCGLabel *label1;
7669 TCGv t0;
7670 if (!s->pe || s->vm86)
7671 goto illegal_op;
7672 ot = dflag != MO_16 ? MO_32 : MO_16;
7673 modrm = cpu_ldub_code(env, s->pc++);
7674 reg = ((modrm >> 3) & 7) | rex_r;
7675 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7676 t0 = tcg_temp_local_new();
7677 gen_update_cc_op(s);
7678 if (b == 0x102) {
7679 gen_helper_lar(t0, cpu_env, cpu_T0);
7680 } else {
7681 gen_helper_lsl(t0, cpu_env, cpu_T0);
7683 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7684 label1 = gen_new_label();
7685 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7686 gen_op_mov_reg_v(ot, reg, t0);
7687 gen_set_label(label1);
7688 set_cc_op(s, CC_OP_EFLAGS);
7689 tcg_temp_free(t0);
7691 break;
7692 case 0x118:
7693 modrm = cpu_ldub_code(env, s->pc++);
7694 mod = (modrm >> 6) & 3;
7695 op = (modrm >> 3) & 7;
7696 switch(op) {
7697 case 0: /* prefetchnta */
7698 case 1: /* prefetchnt0 */
7699 case 2: /* prefetchnt0 */
7700 case 3: /* prefetchnt0 */
7701 if (mod == 3)
7702 goto illegal_op;
7703 gen_nop_modrm(env, s, modrm);
7704 /* nothing more to do */
7705 break;
7706 default: /* nop (multi byte) */
7707 gen_nop_modrm(env, s, modrm);
7708 break;
7710 break;
7711 case 0x11a:
7712 modrm = cpu_ldub_code(env, s->pc++);
7713 if (s->flags & HF_MPX_EN_MASK) {
7714 mod = (modrm >> 6) & 3;
7715 reg = ((modrm >> 3) & 7) | rex_r;
7716 if (prefixes & PREFIX_REPZ) {
7717 /* bndcl */
7718 if (reg >= 4
7719 || (prefixes & PREFIX_LOCK)
7720 || s->aflag == MO_16) {
7721 goto illegal_op;
7723 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7724 } else if (prefixes & PREFIX_REPNZ) {
7725 /* bndcu */
7726 if (reg >= 4
7727 || (prefixes & PREFIX_LOCK)
7728 || s->aflag == MO_16) {
7729 goto illegal_op;
7731 TCGv_i64 notu = tcg_temp_new_i64();
7732 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7733 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7734 tcg_temp_free_i64(notu);
7735 } else if (prefixes & PREFIX_DATA) {
7736 /* bndmov -- from reg/mem */
7737 if (reg >= 4 || s->aflag == MO_16) {
7738 goto illegal_op;
7740 if (mod == 3) {
7741 int reg2 = (modrm & 7) | REX_B(s);
7742 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7743 goto illegal_op;
7745 if (s->flags & HF_MPX_IU_MASK) {
7746 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7747 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7749 } else {
7750 gen_lea_modrm(env, s, modrm);
7751 if (CODE64(s)) {
7752 tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0,
7753 s->mem_index, MO_LEQ);
7754 tcg_gen_addi_tl(cpu_A0, cpu_A0, 8);
7755 tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0,
7756 s->mem_index, MO_LEQ);
7757 } else {
7758 tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0,
7759 s->mem_index, MO_LEUL);
7760 tcg_gen_addi_tl(cpu_A0, cpu_A0, 4);
7761 tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0,
7762 s->mem_index, MO_LEUL);
7764 /* bnd registers are now in-use */
7765 gen_set_hflag(s, HF_MPX_IU_MASK);
7767 } else if (mod != 3) {
7768 /* bndldx */
7769 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7770 if (reg >= 4
7771 || (prefixes & PREFIX_LOCK)
7772 || s->aflag == MO_16
7773 || a.base < -1) {
7774 goto illegal_op;
7776 if (a.base >= 0) {
7777 tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp);
7778 } else {
7779 tcg_gen_movi_tl(cpu_A0, 0);
7781 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
7782 if (a.index >= 0) {
7783 tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]);
7784 } else {
7785 tcg_gen_movi_tl(cpu_T0, 0);
7787 if (CODE64(s)) {
7788 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, cpu_A0, cpu_T0);
7789 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7790 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7791 } else {
7792 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, cpu_A0, cpu_T0);
7793 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7794 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7796 gen_set_hflag(s, HF_MPX_IU_MASK);
7799 gen_nop_modrm(env, s, modrm);
7800 break;
7801 case 0x11b:
7802 modrm = cpu_ldub_code(env, s->pc++);
7803 if (s->flags & HF_MPX_EN_MASK) {
7804 mod = (modrm >> 6) & 3;
7805 reg = ((modrm >> 3) & 7) | rex_r;
7806 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7807 /* bndmk */
7808 if (reg >= 4
7809 || (prefixes & PREFIX_LOCK)
7810 || s->aflag == MO_16) {
7811 goto illegal_op;
7813 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7814 if (a.base >= 0) {
7815 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7816 if (!CODE64(s)) {
7817 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7819 } else if (a.base == -1) {
7820 /* no base register has lower bound of 0 */
7821 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7822 } else {
7823 /* rip-relative generates #ud */
7824 goto illegal_op;
7826 tcg_gen_not_tl(cpu_A0, gen_lea_modrm_1(a));
7827 if (!CODE64(s)) {
7828 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
7830 tcg_gen_extu_tl_i64(cpu_bndu[reg], cpu_A0);
7831 /* bnd registers are now in-use */
7832 gen_set_hflag(s, HF_MPX_IU_MASK);
7833 break;
7834 } else if (prefixes & PREFIX_REPNZ) {
7835 /* bndcn */
7836 if (reg >= 4
7837 || (prefixes & PREFIX_LOCK)
7838 || s->aflag == MO_16) {
7839 goto illegal_op;
7841 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
7842 } else if (prefixes & PREFIX_DATA) {
7843 /* bndmov -- to reg/mem */
7844 if (reg >= 4 || s->aflag == MO_16) {
7845 goto illegal_op;
7847 if (mod == 3) {
7848 int reg2 = (modrm & 7) | REX_B(s);
7849 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7850 goto illegal_op;
7852 if (s->flags & HF_MPX_IU_MASK) {
7853 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7854 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7856 } else {
7857 gen_lea_modrm(env, s, modrm);
7858 if (CODE64(s)) {
7859 tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0,
7860 s->mem_index, MO_LEQ);
7861 tcg_gen_addi_tl(cpu_A0, cpu_A0, 8);
7862 tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0,
7863 s->mem_index, MO_LEQ);
7864 } else {
7865 tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0,
7866 s->mem_index, MO_LEUL);
7867 tcg_gen_addi_tl(cpu_A0, cpu_A0, 4);
7868 tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0,
7869 s->mem_index, MO_LEUL);
7872 } else if (mod != 3) {
7873 /* bndstx */
7874 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7875 if (reg >= 4
7876 || (prefixes & PREFIX_LOCK)
7877 || s->aflag == MO_16
7878 || a.base < -1) {
7879 goto illegal_op;
7881 if (a.base >= 0) {
7882 tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp);
7883 } else {
7884 tcg_gen_movi_tl(cpu_A0, 0);
7886 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
7887 if (a.index >= 0) {
7888 tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]);
7889 } else {
7890 tcg_gen_movi_tl(cpu_T0, 0);
7892 if (CODE64(s)) {
7893 gen_helper_bndstx64(cpu_env, cpu_A0, cpu_T0,
7894 cpu_bndl[reg], cpu_bndu[reg]);
7895 } else {
7896 gen_helper_bndstx32(cpu_env, cpu_A0, cpu_T0,
7897 cpu_bndl[reg], cpu_bndu[reg]);
7901 gen_nop_modrm(env, s, modrm);
7902 break;
7903 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
7904 modrm = cpu_ldub_code(env, s->pc++);
7905 gen_nop_modrm(env, s, modrm);
7906 break;
7907 case 0x120: /* mov reg, crN */
7908 case 0x122: /* mov crN, reg */
7909 if (s->cpl != 0) {
7910 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7911 } else {
7912 modrm = cpu_ldub_code(env, s->pc++);
7913 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7914 * AMD documentation (24594.pdf) and testing of
7915 * intel 386 and 486 processors all show that the mod bits
7916 * are assumed to be 1's, regardless of actual values.
7918 rm = (modrm & 7) | REX_B(s);
7919 reg = ((modrm >> 3) & 7) | rex_r;
7920 if (CODE64(s))
7921 ot = MO_64;
7922 else
7923 ot = MO_32;
7924 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7925 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7926 reg = 8;
7928 switch(reg) {
7929 case 0:
7930 case 2:
7931 case 3:
7932 case 4:
7933 case 8:
7934 gen_update_cc_op(s);
7935 gen_jmp_im(pc_start - s->cs_base);
7936 if (b & 2) {
7937 if (s->base.tb->cflags & CF_USE_ICOUNT) {
7938 gen_io_start();
7940 gen_op_mov_v_reg(ot, cpu_T0, rm);
7941 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7942 cpu_T0);
7943 if (s->base.tb->cflags & CF_USE_ICOUNT) {
7944 gen_io_end();
7946 gen_jmp_im(s->pc - s->cs_base);
7947 gen_eob(s);
7948 } else {
7949 if (s->base.tb->cflags & CF_USE_ICOUNT) {
7950 gen_io_start();
7952 gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg));
7953 gen_op_mov_reg_v(ot, rm, cpu_T0);
7954 if (s->base.tb->cflags & CF_USE_ICOUNT) {
7955 gen_io_end();
7958 break;
7959 default:
7960 goto unknown_op;
7963 break;
7964 case 0x121: /* mov reg, drN */
7965 case 0x123: /* mov drN, reg */
7966 if (s->cpl != 0) {
7967 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7968 } else {
7969 modrm = cpu_ldub_code(env, s->pc++);
7970 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7971 * AMD documentation (24594.pdf) and testing of
7972 * intel 386 and 486 processors all show that the mod bits
7973 * are assumed to be 1's, regardless of actual values.
7975 rm = (modrm & 7) | REX_B(s);
7976 reg = ((modrm >> 3) & 7) | rex_r;
7977 if (CODE64(s))
7978 ot = MO_64;
7979 else
7980 ot = MO_32;
7981 if (reg >= 8) {
7982 goto illegal_op;
7984 if (b & 2) {
7985 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7986 gen_op_mov_v_reg(ot, cpu_T0, rm);
7987 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7988 gen_helper_set_dr(cpu_env, cpu_tmp2_i32, cpu_T0);
7989 gen_jmp_im(s->pc - s->cs_base);
7990 gen_eob(s);
7991 } else {
7992 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7993 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7994 gen_helper_get_dr(cpu_T0, cpu_env, cpu_tmp2_i32);
7995 gen_op_mov_reg_v(ot, rm, cpu_T0);
7998 break;
7999 case 0x106: /* clts */
8000 if (s->cpl != 0) {
8001 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8002 } else {
8003 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
8004 gen_helper_clts(cpu_env);
8005 /* abort block because static cpu state changed */
8006 gen_jmp_im(s->pc - s->cs_base);
8007 gen_eob(s);
8009 break;
8010 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
8011 case 0x1c3: /* MOVNTI reg, mem */
8012 if (!(s->cpuid_features & CPUID_SSE2))
8013 goto illegal_op;
8014 ot = mo_64_32(dflag);
8015 modrm = cpu_ldub_code(env, s->pc++);
8016 mod = (modrm >> 6) & 3;
8017 if (mod == 3)
8018 goto illegal_op;
8019 reg = ((modrm >> 3) & 7) | rex_r;
8020 /* generate a generic store */
8021 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8022 break;
8023 case 0x1ae:
8024 modrm = cpu_ldub_code(env, s->pc++);
8025 switch (modrm) {
8026 CASE_MODRM_MEM_OP(0): /* fxsave */
8027 if (!(s->cpuid_features & CPUID_FXSR)
8028 || (prefixes & PREFIX_LOCK)) {
8029 goto illegal_op;
8031 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8032 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8033 break;
8035 gen_lea_modrm(env, s, modrm);
8036 gen_helper_fxsave(cpu_env, cpu_A0);
8037 break;
8039 CASE_MODRM_MEM_OP(1): /* fxrstor */
8040 if (!(s->cpuid_features & CPUID_FXSR)
8041 || (prefixes & PREFIX_LOCK)) {
8042 goto illegal_op;
8044 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8045 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8046 break;
8048 gen_lea_modrm(env, s, modrm);
8049 gen_helper_fxrstor(cpu_env, cpu_A0);
8050 break;
8052 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
8053 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8054 goto illegal_op;
8056 if (s->flags & HF_TS_MASK) {
8057 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8058 break;
8060 gen_lea_modrm(env, s, modrm);
8061 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, s->mem_index, MO_LEUL);
8062 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
8063 break;
8065 CASE_MODRM_MEM_OP(3): /* stmxcsr */
8066 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8067 goto illegal_op;
8069 if (s->flags & HF_TS_MASK) {
8070 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8071 break;
8073 gen_lea_modrm(env, s, modrm);
8074 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, mxcsr));
8075 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
8076 break;
8078 CASE_MODRM_MEM_OP(4): /* xsave */
8079 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8080 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8081 | PREFIX_REPZ | PREFIX_REPNZ))) {
8082 goto illegal_op;
8084 gen_lea_modrm(env, s, modrm);
8085 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8086 cpu_regs[R_EDX]);
8087 gen_helper_xsave(cpu_env, cpu_A0, cpu_tmp1_i64);
8088 break;
8090 CASE_MODRM_MEM_OP(5): /* xrstor */
8091 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8092 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8093 | PREFIX_REPZ | PREFIX_REPNZ))) {
8094 goto illegal_op;
8096 gen_lea_modrm(env, s, modrm);
8097 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8098 cpu_regs[R_EDX]);
8099 gen_helper_xrstor(cpu_env, cpu_A0, cpu_tmp1_i64);
8100 /* XRSTOR is how MPX is enabled, which changes how
8101 we translate. Thus we need to end the TB. */
8102 gen_update_cc_op(s);
8103 gen_jmp_im(s->pc - s->cs_base);
8104 gen_eob(s);
8105 break;
8107 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
8108 if (prefixes & PREFIX_LOCK) {
8109 goto illegal_op;
8111 if (prefixes & PREFIX_DATA) {
8112 /* clwb */
8113 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8114 goto illegal_op;
8116 gen_nop_modrm(env, s, modrm);
8117 } else {
8118 /* xsaveopt */
8119 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8120 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8121 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8122 goto illegal_op;
8124 gen_lea_modrm(env, s, modrm);
8125 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8126 cpu_regs[R_EDX]);
8127 gen_helper_xsaveopt(cpu_env, cpu_A0, cpu_tmp1_i64);
8129 break;
8131 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
8132 if (prefixes & PREFIX_LOCK) {
8133 goto illegal_op;
8135 if (prefixes & PREFIX_DATA) {
8136 /* clflushopt */
8137 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8138 goto illegal_op;
8140 } else {
8141 /* clflush */
8142 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8143 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8144 goto illegal_op;
8147 gen_nop_modrm(env, s, modrm);
8148 break;
8150 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
8151 case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
8152 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
8153 case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
8154 if (CODE64(s)
8155 && (prefixes & PREFIX_REPZ)
8156 && !(prefixes & PREFIX_LOCK)
8157 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8158 TCGv base, treg, src, dst;
8160 /* Preserve hflags bits by testing CR4 at runtime. */
8161 tcg_gen_movi_i32(cpu_tmp2_i32, CR4_FSGSBASE_MASK);
8162 gen_helper_cr4_testbit(cpu_env, cpu_tmp2_i32);
8164 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8165 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8167 if (modrm & 0x10) {
8168 /* wr*base */
8169 dst = base, src = treg;
8170 } else {
8171 /* rd*base */
8172 dst = treg, src = base;
8175 if (s->dflag == MO_32) {
8176 tcg_gen_ext32u_tl(dst, src);
8177 } else {
8178 tcg_gen_mov_tl(dst, src);
8180 break;
8182 goto unknown_op;
8184 case 0xf8: /* sfence / pcommit */
8185 if (prefixes & PREFIX_DATA) {
8186 /* pcommit */
8187 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8188 || (prefixes & PREFIX_LOCK)) {
8189 goto illegal_op;
8191 break;
8193 /* fallthru */
8194 case 0xf9 ... 0xff: /* sfence */
8195 if (!(s->cpuid_features & CPUID_SSE)
8196 || (prefixes & PREFIX_LOCK)) {
8197 goto illegal_op;
8199 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8200 break;
8201 case 0xe8 ... 0xef: /* lfence */
8202 if (!(s->cpuid_features & CPUID_SSE)
8203 || (prefixes & PREFIX_LOCK)) {
8204 goto illegal_op;
8206 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8207 break;
8208 case 0xf0 ... 0xf7: /* mfence */
8209 if (!(s->cpuid_features & CPUID_SSE2)
8210 || (prefixes & PREFIX_LOCK)) {
8211 goto illegal_op;
8213 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8214 break;
8216 default:
8217 goto unknown_op;
8219 break;
8221 case 0x10d: /* 3DNow! prefetch(w) */
8222 modrm = cpu_ldub_code(env, s->pc++);
8223 mod = (modrm >> 6) & 3;
8224 if (mod == 3)
8225 goto illegal_op;
8226 gen_nop_modrm(env, s, modrm);
8227 break;
8228 case 0x1aa: /* rsm */
8229 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8230 if (!(s->flags & HF_SMM_MASK))
8231 goto illegal_op;
8232 gen_update_cc_op(s);
8233 gen_jmp_im(s->pc - s->cs_base);
8234 gen_helper_rsm(cpu_env);
8235 gen_eob(s);
8236 break;
8237 case 0x1b8: /* SSE4.2 popcnt */
8238 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8239 PREFIX_REPZ)
8240 goto illegal_op;
8241 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8242 goto illegal_op;
8244 modrm = cpu_ldub_code(env, s->pc++);
8245 reg = ((modrm >> 3) & 7) | rex_r;
8247 if (s->prefix & PREFIX_DATA) {
8248 ot = MO_16;
8249 } else {
8250 ot = mo_64_32(dflag);
8253 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8254 gen_extu(ot, cpu_T0);
8255 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
8256 tcg_gen_ctpop_tl(cpu_T0, cpu_T0);
8257 gen_op_mov_reg_v(ot, reg, cpu_T0);
8259 set_cc_op(s, CC_OP_POPCNT);
8260 break;
8261 case 0x10e ... 0x10f:
8262 /* 3DNow! instructions, ignore prefixes */
8263 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8264 case 0x110 ... 0x117:
8265 case 0x128 ... 0x12f:
8266 case 0x138 ... 0x13a:
8267 case 0x150 ... 0x179:
8268 case 0x17c ... 0x17f:
8269 case 0x1c2:
8270 case 0x1c4 ... 0x1c6:
8271 case 0x1d0 ... 0x1fe:
8272 gen_sse(env, s, b, pc_start, rex_r);
8273 break;
8274 default:
8275 goto unknown_op;
8277 return s->pc;
8278 illegal_op:
8279 gen_illegal_opcode(s);
8280 return s->pc;
8281 unknown_op:
8282 gen_unknown_opcode(env, s);
8283 return s->pc;
8286 void tcg_x86_init(void)
8288 static const char reg_names[CPU_NB_REGS][4] = {
8289 #ifdef TARGET_X86_64
8290 [R_EAX] = "rax",
8291 [R_EBX] = "rbx",
8292 [R_ECX] = "rcx",
8293 [R_EDX] = "rdx",
8294 [R_ESI] = "rsi",
8295 [R_EDI] = "rdi",
8296 [R_EBP] = "rbp",
8297 [R_ESP] = "rsp",
8298 [8] = "r8",
8299 [9] = "r9",
8300 [10] = "r10",
8301 [11] = "r11",
8302 [12] = "r12",
8303 [13] = "r13",
8304 [14] = "r14",
8305 [15] = "r15",
8306 #else
8307 [R_EAX] = "eax",
8308 [R_EBX] = "ebx",
8309 [R_ECX] = "ecx",
8310 [R_EDX] = "edx",
8311 [R_ESI] = "esi",
8312 [R_EDI] = "edi",
8313 [R_EBP] = "ebp",
8314 [R_ESP] = "esp",
8315 #endif
8317 static const char seg_base_names[6][8] = {
8318 [R_CS] = "cs_base",
8319 [R_DS] = "ds_base",
8320 [R_ES] = "es_base",
8321 [R_FS] = "fs_base",
8322 [R_GS] = "gs_base",
8323 [R_SS] = "ss_base",
8325 static const char bnd_regl_names[4][8] = {
8326 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8328 static const char bnd_regu_names[4][8] = {
8329 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8331 int i;
8332 static bool initialized;
8334 if (initialized) {
8335 return;
8337 initialized = true;
8339 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8340 tcg_ctx.tcg_env = cpu_env;
8341 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8342 offsetof(CPUX86State, cc_op), "cc_op");
8343 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8344 "cc_dst");
8345 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8346 "cc_src");
8347 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8348 "cc_src2");
8350 for (i = 0; i < CPU_NB_REGS; ++i) {
8351 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8352 offsetof(CPUX86State, regs[i]),
8353 reg_names[i]);
8356 for (i = 0; i < 6; ++i) {
8357 cpu_seg_base[i]
8358 = tcg_global_mem_new(cpu_env,
8359 offsetof(CPUX86State, segs[i].base),
8360 seg_base_names[i]);
8363 for (i = 0; i < 4; ++i) {
8364 cpu_bndl[i]
8365 = tcg_global_mem_new_i64(cpu_env,
8366 offsetof(CPUX86State, bnd_regs[i].lb),
8367 bnd_regl_names[i]);
8368 cpu_bndu[i]
8369 = tcg_global_mem_new_i64(cpu_env,
8370 offsetof(CPUX86State, bnd_regs[i].ub),
8371 bnd_regu_names[i]);
8375 static int i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu,
8376 int max_insns)
8378 DisasContext *dc = container_of(dcbase, DisasContext, base);
8379 CPUX86State *env = cpu->env_ptr;
8380 uint32_t flags = dc->base.tb->flags;
8381 target_ulong cs_base = dc->base.tb->cs_base;
8383 dc->pe = (flags >> HF_PE_SHIFT) & 1;
8384 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8385 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8386 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8387 dc->f_st = 0;
8388 dc->vm86 = (flags >> VM_SHIFT) & 1;
8389 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8390 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8391 dc->tf = (flags >> TF_SHIFT) & 1;
8392 dc->cc_op = CC_OP_DYNAMIC;
8393 dc->cc_op_dirty = false;
8394 dc->cs_base = cs_base;
8395 dc->popl_esp_hack = 0;
8396 /* select memory access functions */
8397 dc->mem_index = 0;
8398 #ifdef CONFIG_SOFTMMU
8399 dc->mem_index = cpu_mmu_index(env, false);
8400 #endif
8401 dc->cpuid_features = env->features[FEAT_1_EDX];
8402 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8403 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8404 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8405 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8406 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8407 #ifdef TARGET_X86_64
8408 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8409 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8410 #endif
8411 dc->flags = flags;
8412 dc->jmp_opt = !(dc->tf || dc->base.singlestep_enabled ||
8413 (flags & HF_INHIBIT_IRQ_MASK));
8414 /* Do not optimize repz jumps at all in icount mode, because
8415 rep movsS instructions are execured with different paths
8416 in !repz_opt and repz_opt modes. The first one was used
8417 always except single step mode. And this setting
8418 disables jumps optimization and control paths become
8419 equivalent in run and single step modes.
8420 Now there will be no jump optimization for repz in
8421 record/replay modes and there will always be an
8422 additional step for ecx=0 when icount is enabled.
8424 dc->repz_opt = !dc->jmp_opt && !(dc->base.tb->cflags & CF_USE_ICOUNT);
8425 #if 0
8426 /* check addseg logic */
8427 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8428 printf("ERROR addseg\n");
8429 #endif
8431 cpu_T0 = tcg_temp_new();
8432 cpu_T1 = tcg_temp_new();
8433 cpu_A0 = tcg_temp_new();
8435 cpu_tmp0 = tcg_temp_new();
8436 cpu_tmp1_i64 = tcg_temp_new_i64();
8437 cpu_tmp2_i32 = tcg_temp_new_i32();
8438 cpu_tmp3_i32 = tcg_temp_new_i32();
8439 cpu_tmp4 = tcg_temp_new();
8440 cpu_ptr0 = tcg_temp_new_ptr();
8441 cpu_ptr1 = tcg_temp_new_ptr();
8442 cpu_cc_srcT = tcg_temp_local_new();
8444 return max_insns;
8447 static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
8451 static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8453 DisasContext *dc = container_of(dcbase, DisasContext, base);
8455 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
8458 static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8459 const CPUBreakpoint *bp)
8461 DisasContext *dc = container_of(dcbase, DisasContext, base);
8462 /* If RF is set, suppress an internally generated breakpoint. */
8463 int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
8464 if (bp->flags & flags) {
8465 gen_debug(dc, dc->base.pc_next - dc->cs_base);
8466 dc->base.is_jmp = DISAS_NORETURN;
8467 /* The address covered by the breakpoint must be included in
8468 [tb->pc, tb->pc + tb->size) in order to for it to be
8469 properly cleared -- thus we increment the PC here so that
8470 the generic logic setting tb->size later does the right thing. */
8471 dc->base.pc_next += 1;
8472 return true;
8473 } else {
8474 return false;
8478 static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8480 DisasContext *dc = container_of(dcbase, DisasContext, base);
8481 target_ulong pc_next = disas_insn(dc, cpu);
8483 if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
8484 /* if single step mode, we generate only one instruction and
8485 generate an exception */
8486 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8487 the flag and abort the translation to give the irqs a
8488 chance to happen */
8489 dc->base.is_jmp = DISAS_TOO_MANY;
8490 } else if ((dc->base.tb->cflags & CF_USE_ICOUNT)
8491 && ((dc->base.pc_next & TARGET_PAGE_MASK)
8492 != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1)
8493 & TARGET_PAGE_MASK)
8494 || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
8495 /* Do not cross the boundary of the pages in icount mode,
8496 it can cause an exception. Do it only when boundary is
8497 crossed by the first instruction in the block.
8498 If current instruction already crossed the bound - it's ok,
8499 because an exception hasn't stopped this code.
8501 dc->base.is_jmp = DISAS_TOO_MANY;
8502 } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
8503 dc->base.is_jmp = DISAS_TOO_MANY;
8506 dc->base.pc_next = pc_next;
8509 static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8511 DisasContext *dc = container_of(dcbase, DisasContext, base);
8513 if (dc->base.is_jmp == DISAS_TOO_MANY) {
8514 gen_jmp_im(dc->base.pc_next - dc->cs_base);
8515 gen_eob(dc);
8519 static void i386_tr_disas_log(const DisasContextBase *dcbase,
8520 CPUState *cpu)
8522 DisasContext *dc = container_of(dcbase, DisasContext, base);
8523 int disas_flags = !dc->code32;
8525 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
8526 #ifdef TARGET_X86_64
8527 if (dc->code64) {
8528 disas_flags = 2;
8530 #endif
8531 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size, disas_flags);
8534 static const TranslatorOps i386_tr_ops = {
8535 .init_disas_context = i386_tr_init_disas_context,
8536 .tb_start = i386_tr_tb_start,
8537 .insn_start = i386_tr_insn_start,
8538 .breakpoint_check = i386_tr_breakpoint_check,
8539 .translate_insn = i386_tr_translate_insn,
8540 .tb_stop = i386_tr_tb_stop,
8541 .disas_log = i386_tr_disas_log,
8544 /* generate intermediate code for basic block 'tb'. */
8545 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
8547 DisasContext dc;
8549 translator_loop(&i386_tr_ops, &dc.base, cpu, tb);
8552 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8553 target_ulong *data)
8555 int cc_op = data[1];
8556 env->eip = data[0] - tb->cs_base;
8557 if (cc_op != CC_OP_DYNAMIC) {
8558 env->cc_op = cc_op;