Merge remote-tracking branch 'qemu/master'
[qemu/ar7.git] / target / i386 / translate.c
blob7942e7994e5b3a65445a0abd00d5213821dd8252
1 /*
2 * i386 translation
4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include "qemu/host-utils.h"
22 #include "cpu.h"
23 #include "disas/disas.h"
24 #include "exec/exec-all.h"
25 #include "tcg-op.h"
26 #include "exec/cpu_ldst.h"
28 #include "exec/helper-proto.h"
29 #include "exec/helper-gen.h"
31 #if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
32 #include "vsyscall.h"
33 #endif
35 #include "trace-tcg.h"
36 #include "exec/log.h"
39 #define PREFIX_REPZ 0x01
40 #define PREFIX_REPNZ 0x02
41 #define PREFIX_LOCK 0x04
42 #define PREFIX_DATA 0x08
43 #define PREFIX_ADR 0x10
44 #define PREFIX_VEX 0x20
46 #ifdef TARGET_X86_64
47 #define CODE64(s) ((s)->code64)
48 #define REX_X(s) ((s)->rex_x)
49 #define REX_B(s) ((s)->rex_b)
50 #else
51 #define CODE64(s) 0
52 #define REX_X(s) 0
53 #define REX_B(s) 0
54 #endif
56 #ifdef TARGET_X86_64
57 # define ctztl ctz64
58 # define clztl clz64
59 #else
60 # define ctztl ctz32
61 # define clztl clz32
62 #endif
64 /* For a switch indexed by MODRM, match all memory operands for a given OP. */
65 #define CASE_MODRM_MEM_OP(OP) \
66 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
67 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
68 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
70 #define CASE_MODRM_OP(OP) \
71 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
72 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
73 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
74 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
76 //#define MACRO_TEST 1
78 /* global register indexes */
79 static TCGv_env cpu_env;
80 static TCGv cpu_A0;
81 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
82 static TCGv_i32 cpu_cc_op;
83 static TCGv cpu_regs[CPU_NB_REGS];
84 static TCGv cpu_seg_base[6];
85 static TCGv_i64 cpu_bndl[4];
86 static TCGv_i64 cpu_bndu[4];
87 /* local temps */
88 static TCGv cpu_T0, cpu_T1;
89 /* local register indexes (only used inside old micro ops) */
90 static TCGv cpu_tmp0, cpu_tmp4;
91 static TCGv_ptr cpu_ptr0, cpu_ptr1;
92 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
93 static TCGv_i64 cpu_tmp1_i64;
95 #include "exec/gen-icount.h"
97 #ifdef TARGET_X86_64
98 static int x86_64_hregs;
99 #endif
101 typedef struct DisasContext {
102 /* current insn context */
103 int override; /* -1 if no override */
104 int prefix;
105 TCGMemOp aflag;
106 TCGMemOp dflag;
107 target_ulong pc_start;
108 target_ulong pc; /* pc = eip + cs_base */
109 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
110 static state change (stop translation) */
111 /* current block context */
112 target_ulong cs_base; /* base of CS segment */
113 int pe; /* protected mode */
114 int code32; /* 32 bit code segment */
115 #ifdef TARGET_X86_64
116 int lma; /* long mode active */
117 int code64; /* 64 bit code segment */
118 int rex_x, rex_b;
119 #endif
120 int vex_l; /* vex vector length */
121 int vex_v; /* vex vvvv register, without 1's compliment. */
122 int ss32; /* 32 bit stack segment */
123 CCOp cc_op; /* current CC operation */
124 bool cc_op_dirty;
125 int addseg; /* non zero if either DS/ES/SS have a non zero base */
126 int f_st; /* currently unused */
127 int vm86; /* vm86 mode */
128 int cpl;
129 int iopl;
130 int tf; /* TF cpu flag */
131 int singlestep_enabled; /* "hardware" single step enabled */
132 int jmp_opt; /* use direct block chaining for direct jumps */
133 int repz_opt; /* optimize jumps within repz instructions */
134 int mem_index; /* select memory access functions */
135 uint64_t flags; /* all execution flags */
136 struct TranslationBlock *tb;
137 int popl_esp_hack; /* for correct popl with esp base handling */
138 int rip_offset; /* only used in x86_64, but left for simplicity */
139 int cpuid_features;
140 int cpuid_ext_features;
141 int cpuid_ext2_features;
142 int cpuid_ext3_features;
143 int cpuid_7_0_ebx_features;
144 int cpuid_xsave_features;
145 } DisasContext;
147 static void gen_eob(DisasContext *s);
148 static void gen_jmp(DisasContext *s, target_ulong eip);
149 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
150 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d);
152 /* i386 arith/logic operations */
153 enum {
154 OP_ADDL,
155 OP_ORL,
156 OP_ADCL,
157 OP_SBBL,
158 OP_ANDL,
159 OP_SUBL,
160 OP_XORL,
161 OP_CMPL,
164 /* i386 shift ops */
165 enum {
166 OP_ROL,
167 OP_ROR,
168 OP_RCL,
169 OP_RCR,
170 OP_SHL,
171 OP_SHR,
172 OP_SHL1, /* undocumented */
173 OP_SAR = 7,
176 enum {
177 JCC_O,
178 JCC_B,
179 JCC_Z,
180 JCC_BE,
181 JCC_S,
182 JCC_P,
183 JCC_L,
184 JCC_LE,
187 enum {
188 /* I386 int registers */
189 OR_EAX, /* MUST be even numbered */
190 OR_ECX,
191 OR_EDX,
192 OR_EBX,
193 OR_ESP,
194 OR_EBP,
195 OR_ESI,
196 OR_EDI,
198 OR_TMP0 = 16, /* temporary operand register */
199 OR_TMP1,
200 OR_A0, /* temporary register used when doing address evaluation */
203 enum {
204 USES_CC_DST = 1,
205 USES_CC_SRC = 2,
206 USES_CC_SRC2 = 4,
207 USES_CC_SRCT = 8,
210 /* Bit set if the global variable is live after setting CC_OP to X. */
211 static const uint8_t cc_op_live[CC_OP_NB] = {
212 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
213 [CC_OP_EFLAGS] = USES_CC_SRC,
214 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
215 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
216 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
217 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
218 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
219 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
220 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
221 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
222 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
223 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
224 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
225 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
226 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
227 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
228 [CC_OP_CLR] = 0,
229 [CC_OP_POPCNT] = USES_CC_SRC,
232 static void set_cc_op(DisasContext *s, CCOp op)
234 int dead;
236 if (s->cc_op == op) {
237 return;
240 /* Discard CC computation that will no longer be used. */
241 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
242 if (dead & USES_CC_DST) {
243 tcg_gen_discard_tl(cpu_cc_dst);
245 if (dead & USES_CC_SRC) {
246 tcg_gen_discard_tl(cpu_cc_src);
248 if (dead & USES_CC_SRC2) {
249 tcg_gen_discard_tl(cpu_cc_src2);
251 if (dead & USES_CC_SRCT) {
252 tcg_gen_discard_tl(cpu_cc_srcT);
255 if (op == CC_OP_DYNAMIC) {
256 /* The DYNAMIC setting is translator only, and should never be
257 stored. Thus we always consider it clean. */
258 s->cc_op_dirty = false;
259 } else {
260 /* Discard any computed CC_OP value (see shifts). */
261 if (s->cc_op == CC_OP_DYNAMIC) {
262 tcg_gen_discard_i32(cpu_cc_op);
264 s->cc_op_dirty = true;
266 s->cc_op = op;
269 static void gen_update_cc_op(DisasContext *s)
271 if (s->cc_op_dirty) {
272 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
273 s->cc_op_dirty = false;
277 #ifdef TARGET_X86_64
279 #define NB_OP_SIZES 4
281 #else /* !TARGET_X86_64 */
283 #define NB_OP_SIZES 3
285 #endif /* !TARGET_X86_64 */
287 #if defined(HOST_WORDS_BIGENDIAN)
288 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
289 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
290 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
291 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
292 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
293 #else
294 #define REG_B_OFFSET 0
295 #define REG_H_OFFSET 1
296 #define REG_W_OFFSET 0
297 #define REG_L_OFFSET 0
298 #define REG_LH_OFFSET 4
299 #endif
301 /* In instruction encodings for byte register accesses the
302 * register number usually indicates "low 8 bits of register N";
303 * however there are some special cases where N 4..7 indicates
304 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
305 * true for this special case, false otherwise.
307 static inline bool byte_reg_is_xH(int reg)
309 if (reg < 4) {
310 return false;
312 #ifdef TARGET_X86_64
313 if (reg >= 8 || x86_64_hregs) {
314 return false;
316 #endif
317 return true;
320 /* Select the size of a push/pop operation. */
321 static inline TCGMemOp mo_pushpop(DisasContext *s, TCGMemOp ot)
323 if (CODE64(s)) {
324 return ot == MO_16 ? MO_16 : MO_64;
325 } else {
326 return ot;
330 /* Select the size of the stack pointer. */
331 static inline TCGMemOp mo_stacksize(DisasContext *s)
333 return CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
336 /* Select only size 64 else 32. Used for SSE operand sizes. */
337 static inline TCGMemOp mo_64_32(TCGMemOp ot)
339 #ifdef TARGET_X86_64
340 return ot == MO_64 ? MO_64 : MO_32;
341 #else
342 return MO_32;
343 #endif
346 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
347 byte vs word opcodes. */
348 static inline TCGMemOp mo_b_d(int b, TCGMemOp ot)
350 return b & 1 ? ot : MO_8;
353 /* Select size 8 if lsb of B is clear, else OT capped at 32.
354 Used for decoding operand size of port opcodes. */
355 static inline TCGMemOp mo_b_d32(int b, TCGMemOp ot)
357 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
360 static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
362 switch(ot) {
363 case MO_8:
364 if (!byte_reg_is_xH(reg)) {
365 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
366 } else {
367 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
369 break;
370 case MO_16:
371 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
372 break;
373 case MO_32:
374 /* For x86_64, this sets the higher half of register to zero.
375 For i386, this is equivalent to a mov. */
376 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
377 break;
378 #ifdef TARGET_X86_64
379 case MO_64:
380 tcg_gen_mov_tl(cpu_regs[reg], t0);
381 break;
382 #endif
383 default:
384 tcg_abort();
388 static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
390 if (ot == MO_8 && byte_reg_is_xH(reg)) {
391 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
392 } else {
393 tcg_gen_mov_tl(t0, cpu_regs[reg]);
397 static void gen_add_A0_im(DisasContext *s, int val)
399 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
400 if (!CODE64(s)) {
401 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
405 static inline void gen_op_jmp_v(TCGv dest)
407 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
410 static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
412 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
413 gen_op_mov_reg_v(size, reg, cpu_tmp0);
416 static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
418 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T0);
419 gen_op_mov_reg_v(size, reg, cpu_tmp0);
422 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
424 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
427 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
429 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
432 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
434 if (d == OR_TMP0) {
435 gen_op_st_v(s, idx, cpu_T0, cpu_A0);
436 } else {
437 gen_op_mov_reg_v(idx, d, cpu_T0);
441 static inline void gen_jmp_im(target_ulong pc)
443 tcg_gen_movi_tl(cpu_tmp0, pc);
444 gen_op_jmp_v(cpu_tmp0);
447 /* Compute SEG:REG into A0. SEG is selected from the override segment
448 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
449 indicate no override. */
450 static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
451 int def_seg, int ovr_seg)
453 switch (aflag) {
454 #ifdef TARGET_X86_64
455 case MO_64:
456 if (ovr_seg < 0) {
457 tcg_gen_mov_tl(cpu_A0, a0);
458 return;
460 break;
461 #endif
462 case MO_32:
463 /* 32 bit address */
464 if (ovr_seg < 0 && s->addseg) {
465 ovr_seg = def_seg;
467 if (ovr_seg < 0) {
468 tcg_gen_ext32u_tl(cpu_A0, a0);
469 return;
471 break;
472 case MO_16:
473 /* 16 bit address */
474 tcg_gen_ext16u_tl(cpu_A0, a0);
475 a0 = cpu_A0;
476 if (ovr_seg < 0) {
477 if (s->addseg) {
478 ovr_seg = def_seg;
479 } else {
480 return;
483 break;
484 default:
485 tcg_abort();
488 if (ovr_seg >= 0) {
489 TCGv seg = cpu_seg_base[ovr_seg];
491 if (aflag == MO_64) {
492 tcg_gen_add_tl(cpu_A0, a0, seg);
493 } else if (CODE64(s)) {
494 tcg_gen_ext32u_tl(cpu_A0, a0);
495 tcg_gen_add_tl(cpu_A0, cpu_A0, seg);
496 } else {
497 tcg_gen_add_tl(cpu_A0, a0, seg);
498 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
503 static inline void gen_string_movl_A0_ESI(DisasContext *s)
505 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
508 static inline void gen_string_movl_A0_EDI(DisasContext *s)
510 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
513 static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
515 tcg_gen_ld32s_tl(cpu_T0, cpu_env, offsetof(CPUX86State, df));
516 tcg_gen_shli_tl(cpu_T0, cpu_T0, ot);
519 static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign)
521 switch (size) {
522 case MO_8:
523 if (sign) {
524 tcg_gen_ext8s_tl(dst, src);
525 } else {
526 tcg_gen_ext8u_tl(dst, src);
528 return dst;
529 case MO_16:
530 if (sign) {
531 tcg_gen_ext16s_tl(dst, src);
532 } else {
533 tcg_gen_ext16u_tl(dst, src);
535 return dst;
536 #ifdef TARGET_X86_64
537 case MO_32:
538 if (sign) {
539 tcg_gen_ext32s_tl(dst, src);
540 } else {
541 tcg_gen_ext32u_tl(dst, src);
543 return dst;
544 #endif
545 default:
546 return src;
550 static void gen_extu(TCGMemOp ot, TCGv reg)
552 gen_ext_tl(reg, reg, ot, false);
555 static void gen_exts(TCGMemOp ot, TCGv reg)
557 gen_ext_tl(reg, reg, ot, true);
560 static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1)
562 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
563 gen_extu(size, cpu_tmp0);
564 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
567 static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1)
569 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
570 gen_extu(size, cpu_tmp0);
571 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
574 static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n)
576 switch (ot) {
577 case MO_8:
578 gen_helper_inb(v, cpu_env, n);
579 break;
580 case MO_16:
581 gen_helper_inw(v, cpu_env, n);
582 break;
583 case MO_32:
584 gen_helper_inl(v, cpu_env, n);
585 break;
586 default:
587 tcg_abort();
591 static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n)
593 switch (ot) {
594 case MO_8:
595 gen_helper_outb(cpu_env, v, n);
596 break;
597 case MO_16:
598 gen_helper_outw(cpu_env, v, n);
599 break;
600 case MO_32:
601 gen_helper_outl(cpu_env, v, n);
602 break;
603 default:
604 tcg_abort();
608 static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
609 uint32_t svm_flags)
611 target_ulong next_eip;
613 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
614 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
615 switch (ot) {
616 case MO_8:
617 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
618 break;
619 case MO_16:
620 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
621 break;
622 case MO_32:
623 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
624 break;
625 default:
626 tcg_abort();
629 if(s->flags & HF_SVMI_MASK) {
630 gen_update_cc_op(s);
631 gen_jmp_im(cur_eip);
632 svm_flags |= (1 << (4 + ot));
633 next_eip = s->pc - s->cs_base;
634 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
635 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
636 tcg_const_i32(svm_flags),
637 tcg_const_i32(next_eip - cur_eip));
641 static inline void gen_movs(DisasContext *s, TCGMemOp ot)
643 gen_string_movl_A0_ESI(s);
644 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
645 gen_string_movl_A0_EDI(s);
646 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
647 gen_op_movl_T0_Dshift(ot);
648 gen_op_add_reg_T0(s->aflag, R_ESI);
649 gen_op_add_reg_T0(s->aflag, R_EDI);
652 static void gen_op_update1_cc(void)
654 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
657 static void gen_op_update2_cc(void)
659 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
660 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
663 static void gen_op_update3_cc(TCGv reg)
665 tcg_gen_mov_tl(cpu_cc_src2, reg);
666 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
667 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
670 static inline void gen_op_testl_T0_T1_cc(void)
672 tcg_gen_and_tl(cpu_cc_dst, cpu_T0, cpu_T1);
675 static void gen_op_update_neg_cc(void)
677 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
678 tcg_gen_neg_tl(cpu_cc_src, cpu_T0);
679 tcg_gen_movi_tl(cpu_cc_srcT, 0);
682 /* compute all eflags to cc_src */
683 static void gen_compute_eflags(DisasContext *s)
685 TCGv zero, dst, src1, src2;
686 int live, dead;
688 if (s->cc_op == CC_OP_EFLAGS) {
689 return;
691 if (s->cc_op == CC_OP_CLR) {
692 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
693 set_cc_op(s, CC_OP_EFLAGS);
694 return;
697 TCGV_UNUSED(zero);
698 dst = cpu_cc_dst;
699 src1 = cpu_cc_src;
700 src2 = cpu_cc_src2;
702 /* Take care to not read values that are not live. */
703 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
704 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
705 if (dead) {
706 zero = tcg_const_tl(0);
707 if (dead & USES_CC_DST) {
708 dst = zero;
710 if (dead & USES_CC_SRC) {
711 src1 = zero;
713 if (dead & USES_CC_SRC2) {
714 src2 = zero;
718 gen_update_cc_op(s);
719 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
720 set_cc_op(s, CC_OP_EFLAGS);
722 if (dead) {
723 tcg_temp_free(zero);
727 typedef struct CCPrepare {
728 TCGCond cond;
729 TCGv reg;
730 TCGv reg2;
731 target_ulong imm;
732 target_ulong mask;
733 bool use_reg2;
734 bool no_setcond;
735 } CCPrepare;
737 /* compute eflags.C to reg */
738 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
740 TCGv t0, t1;
741 int size, shift;
743 switch (s->cc_op) {
744 case CC_OP_SUBB ... CC_OP_SUBQ:
745 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
746 size = s->cc_op - CC_OP_SUBB;
747 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
748 /* If no temporary was used, be careful not to alias t1 and t0. */
749 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
750 tcg_gen_mov_tl(t0, cpu_cc_srcT);
751 gen_extu(size, t0);
752 goto add_sub;
754 case CC_OP_ADDB ... CC_OP_ADDQ:
755 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
756 size = s->cc_op - CC_OP_ADDB;
757 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
758 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
759 add_sub:
760 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
761 .reg2 = t1, .mask = -1, .use_reg2 = true };
763 case CC_OP_LOGICB ... CC_OP_LOGICQ:
764 case CC_OP_CLR:
765 case CC_OP_POPCNT:
766 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
768 case CC_OP_INCB ... CC_OP_INCQ:
769 case CC_OP_DECB ... CC_OP_DECQ:
770 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
771 .mask = -1, .no_setcond = true };
773 case CC_OP_SHLB ... CC_OP_SHLQ:
774 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
775 size = s->cc_op - CC_OP_SHLB;
776 shift = (8 << size) - 1;
777 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
778 .mask = (target_ulong)1 << shift };
780 case CC_OP_MULB ... CC_OP_MULQ:
781 return (CCPrepare) { .cond = TCG_COND_NE,
782 .reg = cpu_cc_src, .mask = -1 };
784 case CC_OP_BMILGB ... CC_OP_BMILGQ:
785 size = s->cc_op - CC_OP_BMILGB;
786 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
787 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
789 case CC_OP_ADCX:
790 case CC_OP_ADCOX:
791 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
792 .mask = -1, .no_setcond = true };
794 case CC_OP_EFLAGS:
795 case CC_OP_SARB ... CC_OP_SARQ:
796 /* CC_SRC & 1 */
797 return (CCPrepare) { .cond = TCG_COND_NE,
798 .reg = cpu_cc_src, .mask = CC_C };
800 default:
801 /* The need to compute only C from CC_OP_DYNAMIC is important
802 in efficiently implementing e.g. INC at the start of a TB. */
803 gen_update_cc_op(s);
804 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
805 cpu_cc_src2, cpu_cc_op);
806 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
807 .mask = -1, .no_setcond = true };
811 /* compute eflags.P to reg */
812 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
814 gen_compute_eflags(s);
815 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
816 .mask = CC_P };
819 /* compute eflags.S to reg */
820 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
822 switch (s->cc_op) {
823 case CC_OP_DYNAMIC:
824 gen_compute_eflags(s);
825 /* FALLTHRU */
826 case CC_OP_EFLAGS:
827 case CC_OP_ADCX:
828 case CC_OP_ADOX:
829 case CC_OP_ADCOX:
830 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
831 .mask = CC_S };
832 case CC_OP_CLR:
833 case CC_OP_POPCNT:
834 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
835 default:
837 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
838 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
839 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
844 /* compute eflags.O to reg */
845 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
847 switch (s->cc_op) {
848 case CC_OP_ADOX:
849 case CC_OP_ADCOX:
850 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
851 .mask = -1, .no_setcond = true };
852 case CC_OP_CLR:
853 case CC_OP_POPCNT:
854 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
855 default:
856 gen_compute_eflags(s);
857 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
858 .mask = CC_O };
862 /* compute eflags.Z to reg */
863 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
865 switch (s->cc_op) {
866 case CC_OP_DYNAMIC:
867 gen_compute_eflags(s);
868 /* FALLTHRU */
869 case CC_OP_EFLAGS:
870 case CC_OP_ADCX:
871 case CC_OP_ADOX:
872 case CC_OP_ADCOX:
873 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
874 .mask = CC_Z };
875 case CC_OP_CLR:
876 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
877 case CC_OP_POPCNT:
878 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
879 .mask = -1 };
880 default:
882 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
883 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
884 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
889 /* perform a conditional store into register 'reg' according to jump opcode
890 value 'b'. In the fast case, T0 is guaranted not to be used. */
891 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
893 int inv, jcc_op, cond;
894 TCGMemOp size;
895 CCPrepare cc;
896 TCGv t0;
898 inv = b & 1;
899 jcc_op = (b >> 1) & 7;
901 switch (s->cc_op) {
902 case CC_OP_SUBB ... CC_OP_SUBQ:
903 /* We optimize relational operators for the cmp/jcc case. */
904 size = s->cc_op - CC_OP_SUBB;
905 switch (jcc_op) {
906 case JCC_BE:
907 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
908 gen_extu(size, cpu_tmp4);
909 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
910 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
911 .reg2 = t0, .mask = -1, .use_reg2 = true };
912 break;
914 case JCC_L:
915 cond = TCG_COND_LT;
916 goto fast_jcc_l;
917 case JCC_LE:
918 cond = TCG_COND_LE;
919 fast_jcc_l:
920 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
921 gen_exts(size, cpu_tmp4);
922 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
923 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
924 .reg2 = t0, .mask = -1, .use_reg2 = true };
925 break;
927 default:
928 goto slow_jcc;
930 break;
932 default:
933 slow_jcc:
934 /* This actually generates good code for JC, JZ and JS. */
935 switch (jcc_op) {
936 case JCC_O:
937 cc = gen_prepare_eflags_o(s, reg);
938 break;
939 case JCC_B:
940 cc = gen_prepare_eflags_c(s, reg);
941 break;
942 case JCC_Z:
943 cc = gen_prepare_eflags_z(s, reg);
944 break;
945 case JCC_BE:
946 gen_compute_eflags(s);
947 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
948 .mask = CC_Z | CC_C };
949 break;
950 case JCC_S:
951 cc = gen_prepare_eflags_s(s, reg);
952 break;
953 case JCC_P:
954 cc = gen_prepare_eflags_p(s, reg);
955 break;
956 case JCC_L:
957 gen_compute_eflags(s);
958 if (TCGV_EQUAL(reg, cpu_cc_src)) {
959 reg = cpu_tmp0;
961 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
962 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
963 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
964 .mask = CC_S };
965 break;
966 default:
967 case JCC_LE:
968 gen_compute_eflags(s);
969 if (TCGV_EQUAL(reg, cpu_cc_src)) {
970 reg = cpu_tmp0;
972 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
973 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
974 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
975 .mask = CC_S | CC_Z };
976 break;
978 break;
981 if (inv) {
982 cc.cond = tcg_invert_cond(cc.cond);
984 return cc;
987 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
989 CCPrepare cc = gen_prepare_cc(s, b, reg);
991 if (cc.no_setcond) {
992 if (cc.cond == TCG_COND_EQ) {
993 tcg_gen_xori_tl(reg, cc.reg, 1);
994 } else {
995 tcg_gen_mov_tl(reg, cc.reg);
997 return;
1000 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1001 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1002 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1003 tcg_gen_andi_tl(reg, reg, 1);
1004 return;
1006 if (cc.mask != -1) {
1007 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1008 cc.reg = reg;
1010 if (cc.use_reg2) {
1011 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1012 } else {
1013 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1017 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1019 gen_setcc1(s, JCC_B << 1, reg);
1022 /* generate a conditional jump to label 'l1' according to jump opcode
1023 value 'b'. In the fast case, T0 is guaranted not to be used. */
1024 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1026 CCPrepare cc = gen_prepare_cc(s, b, cpu_T0);
1028 if (cc.mask != -1) {
1029 tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask);
1030 cc.reg = cpu_T0;
1032 if (cc.use_reg2) {
1033 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1034 } else {
1035 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1039 /* Generate a conditional jump to label 'l1' according to jump opcode
1040 value 'b'. In the fast case, T0 is guaranted not to be used.
1041 A translation block must end soon. */
1042 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1044 CCPrepare cc = gen_prepare_cc(s, b, cpu_T0);
1046 gen_update_cc_op(s);
1047 if (cc.mask != -1) {
1048 tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask);
1049 cc.reg = cpu_T0;
1051 set_cc_op(s, CC_OP_DYNAMIC);
1052 if (cc.use_reg2) {
1053 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1054 } else {
1055 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1059 /* XXX: does not work with gdbstub "ice" single step - not a
1060 serious problem */
1061 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1063 TCGLabel *l1 = gen_new_label();
1064 TCGLabel *l2 = gen_new_label();
1065 gen_op_jnz_ecx(s->aflag, l1);
1066 gen_set_label(l2);
1067 gen_jmp_tb(s, next_eip, 1);
1068 gen_set_label(l1);
1069 return l2;
1072 static inline void gen_stos(DisasContext *s, TCGMemOp ot)
1074 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
1075 gen_string_movl_A0_EDI(s);
1076 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1077 gen_op_movl_T0_Dshift(ot);
1078 gen_op_add_reg_T0(s->aflag, R_EDI);
1081 static inline void gen_lods(DisasContext *s, TCGMemOp ot)
1083 gen_string_movl_A0_ESI(s);
1084 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1085 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
1086 gen_op_movl_T0_Dshift(ot);
1087 gen_op_add_reg_T0(s->aflag, R_ESI);
1090 static inline void gen_scas(DisasContext *s, TCGMemOp ot)
1092 gen_string_movl_A0_EDI(s);
1093 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
1094 gen_op(s, OP_CMPL, ot, R_EAX);
1095 gen_op_movl_T0_Dshift(ot);
1096 gen_op_add_reg_T0(s->aflag, R_EDI);
1099 static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
1101 gen_string_movl_A0_EDI(s);
1102 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
1103 gen_string_movl_A0_ESI(s);
1104 gen_op(s, OP_CMPL, ot, OR_TMP0);
1105 gen_op_movl_T0_Dshift(ot);
1106 gen_op_add_reg_T0(s->aflag, R_ESI);
1107 gen_op_add_reg_T0(s->aflag, R_EDI);
1110 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1112 if (s->flags & HF_IOBPT_MASK) {
1113 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1114 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1116 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1117 tcg_temp_free_i32(t_size);
1118 tcg_temp_free(t_next);
1123 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
1125 if (s->tb->cflags & CF_USE_ICOUNT) {
1126 gen_io_start();
1128 gen_string_movl_A0_EDI(s);
1129 /* Note: we must do this dummy write first to be restartable in
1130 case of page fault. */
1131 tcg_gen_movi_tl(cpu_T0, 0);
1132 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1133 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1134 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1135 gen_helper_in_func(ot, cpu_T0, cpu_tmp2_i32);
1136 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
1137 gen_op_movl_T0_Dshift(ot);
1138 gen_op_add_reg_T0(s->aflag, R_EDI);
1139 gen_bpt_io(s, cpu_tmp2_i32, ot);
1140 if (s->tb->cflags & CF_USE_ICOUNT) {
1141 gen_io_end();
1145 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
1147 if (s->tb->cflags & CF_USE_ICOUNT) {
1148 gen_io_start();
1150 gen_string_movl_A0_ESI(s);
1151 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1153 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1154 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1155 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T0);
1156 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1157 gen_op_movl_T0_Dshift(ot);
1158 gen_op_add_reg_T0(s->aflag, R_ESI);
1159 gen_bpt_io(s, cpu_tmp2_i32, ot);
1160 if (s->tb->cflags & CF_USE_ICOUNT) {
1161 gen_io_end();
1165 /* same method as Valgrind : we generate jumps to current or next
1166 instruction */
1167 #define GEN_REPZ(op) \
1168 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1169 target_ulong cur_eip, target_ulong next_eip) \
1171 TCGLabel *l2; \
1172 gen_update_cc_op(s); \
1173 l2 = gen_jz_ecx_string(s, next_eip); \
1174 gen_ ## op(s, ot); \
1175 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1176 /* a loop would cause two single step exceptions if ECX = 1 \
1177 before rep string_insn */ \
1178 if (s->repz_opt) \
1179 gen_op_jz_ecx(s->aflag, l2); \
1180 gen_jmp(s, cur_eip); \
1183 #define GEN_REPZ2(op) \
1184 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1185 target_ulong cur_eip, \
1186 target_ulong next_eip, \
1187 int nz) \
1189 TCGLabel *l2; \
1190 gen_update_cc_op(s); \
1191 l2 = gen_jz_ecx_string(s, next_eip); \
1192 gen_ ## op(s, ot); \
1193 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1194 gen_update_cc_op(s); \
1195 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1196 if (s->repz_opt) \
1197 gen_op_jz_ecx(s->aflag, l2); \
1198 gen_jmp(s, cur_eip); \
1201 GEN_REPZ(movs)
1202 GEN_REPZ(stos)
1203 GEN_REPZ(lods)
1204 GEN_REPZ(ins)
1205 GEN_REPZ(outs)
1206 GEN_REPZ2(scas)
1207 GEN_REPZ2(cmps)
1209 static void gen_helper_fp_arith_ST0_FT0(int op)
1211 switch (op) {
1212 case 0:
1213 gen_helper_fadd_ST0_FT0(cpu_env);
1214 break;
1215 case 1:
1216 gen_helper_fmul_ST0_FT0(cpu_env);
1217 break;
1218 case 2:
1219 gen_helper_fcom_ST0_FT0(cpu_env);
1220 break;
1221 case 3:
1222 gen_helper_fcom_ST0_FT0(cpu_env);
1223 break;
1224 case 4:
1225 gen_helper_fsub_ST0_FT0(cpu_env);
1226 break;
1227 case 5:
1228 gen_helper_fsubr_ST0_FT0(cpu_env);
1229 break;
1230 case 6:
1231 gen_helper_fdiv_ST0_FT0(cpu_env);
1232 break;
1233 case 7:
1234 gen_helper_fdivr_ST0_FT0(cpu_env);
1235 break;
1239 /* NOTE the exception in "r" op ordering */
1240 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1242 TCGv_i32 tmp = tcg_const_i32(opreg);
1243 switch (op) {
1244 case 0:
1245 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1246 break;
1247 case 1:
1248 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1249 break;
1250 case 4:
1251 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1252 break;
1253 case 5:
1254 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1255 break;
1256 case 6:
1257 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1258 break;
1259 case 7:
1260 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1261 break;
1265 /* if d == OR_TMP0, it means memory operand (address in A0) */
1266 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
1268 if (d != OR_TMP0) {
1269 gen_op_mov_v_reg(ot, cpu_T0, d);
1270 } else if (!(s1->prefix & PREFIX_LOCK)) {
1271 gen_op_ld_v(s1, ot, cpu_T0, cpu_A0);
1273 switch(op) {
1274 case OP_ADCL:
1275 gen_compute_eflags_c(s1, cpu_tmp4);
1276 if (s1->prefix & PREFIX_LOCK) {
1277 tcg_gen_add_tl(cpu_T0, cpu_tmp4, cpu_T1);
1278 tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
1279 s1->mem_index, ot | MO_LE);
1280 } else {
1281 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
1282 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_tmp4);
1283 gen_op_st_rm_T0_A0(s1, ot, d);
1285 gen_op_update3_cc(cpu_tmp4);
1286 set_cc_op(s1, CC_OP_ADCB + ot);
1287 break;
1288 case OP_SBBL:
1289 gen_compute_eflags_c(s1, cpu_tmp4);
1290 if (s1->prefix & PREFIX_LOCK) {
1291 tcg_gen_add_tl(cpu_T0, cpu_T1, cpu_tmp4);
1292 tcg_gen_neg_tl(cpu_T0, cpu_T0);
1293 tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
1294 s1->mem_index, ot | MO_LE);
1295 } else {
1296 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1);
1297 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_tmp4);
1298 gen_op_st_rm_T0_A0(s1, ot, d);
1300 gen_op_update3_cc(cpu_tmp4);
1301 set_cc_op(s1, CC_OP_SBBB + ot);
1302 break;
1303 case OP_ADDL:
1304 if (s1->prefix & PREFIX_LOCK) {
1305 tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T1,
1306 s1->mem_index, ot | MO_LE);
1307 } else {
1308 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
1309 gen_op_st_rm_T0_A0(s1, ot, d);
1311 gen_op_update2_cc();
1312 set_cc_op(s1, CC_OP_ADDB + ot);
1313 break;
1314 case OP_SUBL:
1315 if (s1->prefix & PREFIX_LOCK) {
1316 tcg_gen_neg_tl(cpu_T0, cpu_T1);
1317 tcg_gen_atomic_fetch_add_tl(cpu_cc_srcT, cpu_A0, cpu_T0,
1318 s1->mem_index, ot | MO_LE);
1319 tcg_gen_sub_tl(cpu_T0, cpu_cc_srcT, cpu_T1);
1320 } else {
1321 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0);
1322 tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1);
1323 gen_op_st_rm_T0_A0(s1, ot, d);
1325 gen_op_update2_cc();
1326 set_cc_op(s1, CC_OP_SUBB + ot);
1327 break;
1328 default:
1329 case OP_ANDL:
1330 if (s1->prefix & PREFIX_LOCK) {
1331 tcg_gen_atomic_and_fetch_tl(cpu_T0, cpu_A0, cpu_T1,
1332 s1->mem_index, ot | MO_LE);
1333 } else {
1334 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
1335 gen_op_st_rm_T0_A0(s1, ot, d);
1337 gen_op_update1_cc();
1338 set_cc_op(s1, CC_OP_LOGICB + ot);
1339 break;
1340 case OP_ORL:
1341 if (s1->prefix & PREFIX_LOCK) {
1342 tcg_gen_atomic_or_fetch_tl(cpu_T0, cpu_A0, cpu_T1,
1343 s1->mem_index, ot | MO_LE);
1344 } else {
1345 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1);
1346 gen_op_st_rm_T0_A0(s1, ot, d);
1348 gen_op_update1_cc();
1349 set_cc_op(s1, CC_OP_LOGICB + ot);
1350 break;
1351 case OP_XORL:
1352 if (s1->prefix & PREFIX_LOCK) {
1353 tcg_gen_atomic_xor_fetch_tl(cpu_T0, cpu_A0, cpu_T1,
1354 s1->mem_index, ot | MO_LE);
1355 } else {
1356 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_T1);
1357 gen_op_st_rm_T0_A0(s1, ot, d);
1359 gen_op_update1_cc();
1360 set_cc_op(s1, CC_OP_LOGICB + ot);
1361 break;
1362 case OP_CMPL:
1363 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
1364 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0);
1365 tcg_gen_sub_tl(cpu_cc_dst, cpu_T0, cpu_T1);
1366 set_cc_op(s1, CC_OP_SUBB + ot);
1367 break;
1371 /* if d == OR_TMP0, it means memory operand (address in A0) */
1372 static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
1374 if (s1->prefix & PREFIX_LOCK) {
1375 tcg_gen_movi_tl(cpu_T0, c > 0 ? 1 : -1);
1376 tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
1377 s1->mem_index, ot | MO_LE);
1378 } else {
1379 if (d != OR_TMP0) {
1380 gen_op_mov_v_reg(ot, cpu_T0, d);
1381 } else {
1382 gen_op_ld_v(s1, ot, cpu_T0, cpu_A0);
1384 tcg_gen_addi_tl(cpu_T0, cpu_T0, (c > 0 ? 1 : -1));
1385 gen_op_st_rm_T0_A0(s1, ot, d);
1388 gen_compute_eflags_c(s1, cpu_cc_src);
1389 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
1390 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1393 static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
1394 TCGv shm1, TCGv count, bool is_right)
1396 TCGv_i32 z32, s32, oldop;
1397 TCGv z_tl;
1399 /* Store the results into the CC variables. If we know that the
1400 variable must be dead, store unconditionally. Otherwise we'll
1401 need to not disrupt the current contents. */
1402 z_tl = tcg_const_tl(0);
1403 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1404 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1405 result, cpu_cc_dst);
1406 } else {
1407 tcg_gen_mov_tl(cpu_cc_dst, result);
1409 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1410 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1411 shm1, cpu_cc_src);
1412 } else {
1413 tcg_gen_mov_tl(cpu_cc_src, shm1);
1415 tcg_temp_free(z_tl);
1417 /* Get the two potential CC_OP values into temporaries. */
1418 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1419 if (s->cc_op == CC_OP_DYNAMIC) {
1420 oldop = cpu_cc_op;
1421 } else {
1422 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1423 oldop = cpu_tmp3_i32;
1426 /* Conditionally store the CC_OP value. */
1427 z32 = tcg_const_i32(0);
1428 s32 = tcg_temp_new_i32();
1429 tcg_gen_trunc_tl_i32(s32, count);
1430 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1431 tcg_temp_free_i32(z32);
1432 tcg_temp_free_i32(s32);
1434 /* The CC_OP value is no longer predictable. */
1435 set_cc_op(s, CC_OP_DYNAMIC);
1438 static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1439 int is_right, int is_arith)
1441 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1443 /* load */
1444 if (op1 == OR_TMP0) {
1445 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1446 } else {
1447 gen_op_mov_v_reg(ot, cpu_T0, op1);
1450 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1451 tcg_gen_subi_tl(cpu_tmp0, cpu_T1, 1);
1453 if (is_right) {
1454 if (is_arith) {
1455 gen_exts(ot, cpu_T0);
1456 tcg_gen_sar_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1457 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
1458 } else {
1459 gen_extu(ot, cpu_T0);
1460 tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1461 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
1463 } else {
1464 tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1465 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
1468 /* store */
1469 gen_op_st_rm_T0_A0(s, ot, op1);
1471 gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, cpu_T1, is_right);
1474 static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1475 int is_right, int is_arith)
1477 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1479 /* load */
1480 if (op1 == OR_TMP0)
1481 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1482 else
1483 gen_op_mov_v_reg(ot, cpu_T0, op1);
1485 op2 &= mask;
1486 if (op2 != 0) {
1487 if (is_right) {
1488 if (is_arith) {
1489 gen_exts(ot, cpu_T0);
1490 tcg_gen_sari_tl(cpu_tmp4, cpu_T0, op2 - 1);
1491 tcg_gen_sari_tl(cpu_T0, cpu_T0, op2);
1492 } else {
1493 gen_extu(ot, cpu_T0);
1494 tcg_gen_shri_tl(cpu_tmp4, cpu_T0, op2 - 1);
1495 tcg_gen_shri_tl(cpu_T0, cpu_T0, op2);
1497 } else {
1498 tcg_gen_shli_tl(cpu_tmp4, cpu_T0, op2 - 1);
1499 tcg_gen_shli_tl(cpu_T0, cpu_T0, op2);
1503 /* store */
1504 gen_op_st_rm_T0_A0(s, ot, op1);
1506 /* update eflags if non zero shift */
1507 if (op2 != 0) {
1508 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1509 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
1510 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1514 static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
1516 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1517 TCGv_i32 t0, t1;
1519 /* load */
1520 if (op1 == OR_TMP0) {
1521 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1522 } else {
1523 gen_op_mov_v_reg(ot, cpu_T0, op1);
1526 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1528 switch (ot) {
1529 case MO_8:
1530 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1531 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
1532 tcg_gen_muli_tl(cpu_T0, cpu_T0, 0x01010101);
1533 goto do_long;
1534 case MO_16:
1535 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1536 tcg_gen_deposit_tl(cpu_T0, cpu_T0, cpu_T0, 16, 16);
1537 goto do_long;
1538 do_long:
1539 #ifdef TARGET_X86_64
1540 case MO_32:
1541 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
1542 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
1543 if (is_right) {
1544 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1545 } else {
1546 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1548 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
1549 break;
1550 #endif
1551 default:
1552 if (is_right) {
1553 tcg_gen_rotr_tl(cpu_T0, cpu_T0, cpu_T1);
1554 } else {
1555 tcg_gen_rotl_tl(cpu_T0, cpu_T0, cpu_T1);
1557 break;
1560 /* store */
1561 gen_op_st_rm_T0_A0(s, ot, op1);
1563 /* We'll need the flags computed into CC_SRC. */
1564 gen_compute_eflags(s);
1566 /* The value that was "rotated out" is now present at the other end
1567 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1568 since we've computed the flags into CC_SRC, these variables are
1569 currently dead. */
1570 if (is_right) {
1571 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1);
1572 tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask);
1573 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1574 } else {
1575 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask);
1576 tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1);
1578 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1579 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1581 /* Now conditionally store the new CC_OP value. If the shift count
1582 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1583 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1584 exactly as we computed above. */
1585 t0 = tcg_const_i32(0);
1586 t1 = tcg_temp_new_i32();
1587 tcg_gen_trunc_tl_i32(t1, cpu_T1);
1588 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1589 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1590 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1591 cpu_tmp2_i32, cpu_tmp3_i32);
1592 tcg_temp_free_i32(t0);
1593 tcg_temp_free_i32(t1);
1595 /* The CC_OP value is no longer predictable. */
1596 set_cc_op(s, CC_OP_DYNAMIC);
1599 static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1600 int is_right)
1602 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1603 int shift;
1605 /* load */
1606 if (op1 == OR_TMP0) {
1607 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1608 } else {
1609 gen_op_mov_v_reg(ot, cpu_T0, op1);
1612 op2 &= mask;
1613 if (op2 != 0) {
1614 switch (ot) {
1615 #ifdef TARGET_X86_64
1616 case MO_32:
1617 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
1618 if (is_right) {
1619 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1620 } else {
1621 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1623 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
1624 break;
1625 #endif
1626 default:
1627 if (is_right) {
1628 tcg_gen_rotri_tl(cpu_T0, cpu_T0, op2);
1629 } else {
1630 tcg_gen_rotli_tl(cpu_T0, cpu_T0, op2);
1632 break;
1633 case MO_8:
1634 mask = 7;
1635 goto do_shifts;
1636 case MO_16:
1637 mask = 15;
1638 do_shifts:
1639 shift = op2 & mask;
1640 if (is_right) {
1641 shift = mask + 1 - shift;
1643 gen_extu(ot, cpu_T0);
1644 tcg_gen_shli_tl(cpu_tmp0, cpu_T0, shift);
1645 tcg_gen_shri_tl(cpu_T0, cpu_T0, mask + 1 - shift);
1646 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
1647 break;
1651 /* store */
1652 gen_op_st_rm_T0_A0(s, ot, op1);
1654 if (op2 != 0) {
1655 /* Compute the flags into CC_SRC. */
1656 gen_compute_eflags(s);
1658 /* The value that was "rotated out" is now present at the other end
1659 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1660 since we've computed the flags into CC_SRC, these variables are
1661 currently dead. */
1662 if (is_right) {
1663 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1);
1664 tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask);
1665 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1666 } else {
1667 tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask);
1668 tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1);
1670 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1671 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1672 set_cc_op(s, CC_OP_ADCOX);
1676 /* XXX: add faster immediate = 1 case */
1677 static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1678 int is_right)
1680 gen_compute_eflags(s);
1681 assert(s->cc_op == CC_OP_EFLAGS);
1683 /* load */
1684 if (op1 == OR_TMP0)
1685 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1686 else
1687 gen_op_mov_v_reg(ot, cpu_T0, op1);
1689 if (is_right) {
1690 switch (ot) {
1691 case MO_8:
1692 gen_helper_rcrb(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1693 break;
1694 case MO_16:
1695 gen_helper_rcrw(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1696 break;
1697 case MO_32:
1698 gen_helper_rcrl(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1699 break;
1700 #ifdef TARGET_X86_64
1701 case MO_64:
1702 gen_helper_rcrq(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1703 break;
1704 #endif
1705 default:
1706 tcg_abort();
1708 } else {
1709 switch (ot) {
1710 case MO_8:
1711 gen_helper_rclb(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1712 break;
1713 case MO_16:
1714 gen_helper_rclw(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1715 break;
1716 case MO_32:
1717 gen_helper_rcll(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1718 break;
1719 #ifdef TARGET_X86_64
1720 case MO_64:
1721 gen_helper_rclq(cpu_T0, cpu_env, cpu_T0, cpu_T1);
1722 break;
1723 #endif
1724 default:
1725 tcg_abort();
1728 /* store */
1729 gen_op_st_rm_T0_A0(s, ot, op1);
1732 /* XXX: add faster immediate case */
1733 static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1734 bool is_right, TCGv count_in)
1736 target_ulong mask = (ot == MO_64 ? 63 : 31);
1737 TCGv count;
1739 /* load */
1740 if (op1 == OR_TMP0) {
1741 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
1742 } else {
1743 gen_op_mov_v_reg(ot, cpu_T0, op1);
1746 count = tcg_temp_new();
1747 tcg_gen_andi_tl(count, count_in, mask);
1749 switch (ot) {
1750 case MO_16:
1751 /* Note: we implement the Intel behaviour for shift count > 16.
1752 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1753 portion by constructing it as a 32-bit value. */
1754 if (is_right) {
1755 tcg_gen_deposit_tl(cpu_tmp0, cpu_T0, cpu_T1, 16, 16);
1756 tcg_gen_mov_tl(cpu_T1, cpu_T0);
1757 tcg_gen_mov_tl(cpu_T0, cpu_tmp0);
1758 } else {
1759 tcg_gen_deposit_tl(cpu_T1, cpu_T0, cpu_T1, 16, 16);
1761 /* FALLTHRU */
1762 #ifdef TARGET_X86_64
1763 case MO_32:
1764 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1765 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1766 if (is_right) {
1767 tcg_gen_concat_tl_i64(cpu_T0, cpu_T0, cpu_T1);
1768 tcg_gen_shr_i64(cpu_tmp0, cpu_T0, cpu_tmp0);
1769 tcg_gen_shr_i64(cpu_T0, cpu_T0, count);
1770 } else {
1771 tcg_gen_concat_tl_i64(cpu_T0, cpu_T1, cpu_T0);
1772 tcg_gen_shl_i64(cpu_tmp0, cpu_T0, cpu_tmp0);
1773 tcg_gen_shl_i64(cpu_T0, cpu_T0, count);
1774 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1775 tcg_gen_shri_i64(cpu_T0, cpu_T0, 32);
1777 break;
1778 #endif
1779 default:
1780 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1781 if (is_right) {
1782 tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1784 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1785 tcg_gen_shr_tl(cpu_T0, cpu_T0, count);
1786 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_tmp4);
1787 } else {
1788 tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0);
1789 if (ot == MO_16) {
1790 /* Only needed if count > 16, for Intel behaviour. */
1791 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1792 tcg_gen_shr_tl(cpu_tmp4, cpu_T1, cpu_tmp4);
1793 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1796 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1797 tcg_gen_shl_tl(cpu_T0, cpu_T0, count);
1798 tcg_gen_shr_tl(cpu_T1, cpu_T1, cpu_tmp4);
1800 tcg_gen_movi_tl(cpu_tmp4, 0);
1801 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T1, count, cpu_tmp4,
1802 cpu_tmp4, cpu_T1);
1803 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1);
1804 break;
1807 /* store */
1808 gen_op_st_rm_T0_A0(s, ot, op1);
1810 gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, count, is_right);
1811 tcg_temp_free(count);
1814 static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
1816 if (s != OR_TMP1)
1817 gen_op_mov_v_reg(ot, cpu_T1, s);
1818 switch(op) {
1819 case OP_ROL:
1820 gen_rot_rm_T1(s1, ot, d, 0);
1821 break;
1822 case OP_ROR:
1823 gen_rot_rm_T1(s1, ot, d, 1);
1824 break;
1825 case OP_SHL:
1826 case OP_SHL1:
1827 gen_shift_rm_T1(s1, ot, d, 0, 0);
1828 break;
1829 case OP_SHR:
1830 gen_shift_rm_T1(s1, ot, d, 1, 0);
1831 break;
1832 case OP_SAR:
1833 gen_shift_rm_T1(s1, ot, d, 1, 1);
1834 break;
1835 case OP_RCL:
1836 gen_rotc_rm_T1(s1, ot, d, 0);
1837 break;
1838 case OP_RCR:
1839 gen_rotc_rm_T1(s1, ot, d, 1);
1840 break;
1844 static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
1846 switch(op) {
1847 case OP_ROL:
1848 gen_rot_rm_im(s1, ot, d, c, 0);
1849 break;
1850 case OP_ROR:
1851 gen_rot_rm_im(s1, ot, d, c, 1);
1852 break;
1853 case OP_SHL:
1854 case OP_SHL1:
1855 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1856 break;
1857 case OP_SHR:
1858 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1859 break;
1860 case OP_SAR:
1861 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1862 break;
1863 default:
1864 /* currently not optimized */
1865 tcg_gen_movi_tl(cpu_T1, c);
1866 gen_shift(s1, op, ot, d, OR_TMP1);
1867 break;
1871 /* Decompose an address. */
1873 typedef struct AddressParts {
1874 int def_seg;
1875 int base;
1876 int index;
1877 int scale;
1878 target_long disp;
1879 } AddressParts;
1881 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
1882 int modrm)
1884 int def_seg, base, index, scale, mod, rm;
1885 target_long disp;
1886 bool havesib;
1888 def_seg = R_DS;
1889 index = -1;
1890 scale = 0;
1891 disp = 0;
1893 mod = (modrm >> 6) & 3;
1894 rm = modrm & 7;
1895 base = rm | REX_B(s);
1897 if (mod == 3) {
1898 /* Normally filtered out earlier, but including this path
1899 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
1900 goto done;
1903 switch (s->aflag) {
1904 case MO_64:
1905 case MO_32:
1906 havesib = 0;
1907 if (rm == 4) {
1908 int code = cpu_ldub_code(env, s->pc++);
1909 scale = (code >> 6) & 3;
1910 index = ((code >> 3) & 7) | REX_X(s);
1911 if (index == 4) {
1912 index = -1; /* no index */
1914 base = (code & 7) | REX_B(s);
1915 havesib = 1;
1918 switch (mod) {
1919 case 0:
1920 if ((base & 7) == 5) {
1921 base = -1;
1922 disp = (int32_t)cpu_ldl_code(env, s->pc);
1923 s->pc += 4;
1924 if (CODE64(s) && !havesib) {
1925 base = -2;
1926 disp += s->pc + s->rip_offset;
1929 break;
1930 case 1:
1931 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1932 break;
1933 default:
1934 case 2:
1935 disp = (int32_t)cpu_ldl_code(env, s->pc);
1936 s->pc += 4;
1937 break;
1940 /* For correct popl handling with esp. */
1941 if (base == R_ESP && s->popl_esp_hack) {
1942 disp += s->popl_esp_hack;
1944 if (base == R_EBP || base == R_ESP) {
1945 def_seg = R_SS;
1947 break;
1949 case MO_16:
1950 if (mod == 0) {
1951 if (rm == 6) {
1952 base = -1;
1953 disp = cpu_lduw_code(env, s->pc);
1954 s->pc += 2;
1955 break;
1957 } else if (mod == 1) {
1958 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1959 } else {
1960 disp = (int16_t)cpu_lduw_code(env, s->pc);
1961 s->pc += 2;
1964 switch (rm) {
1965 case 0:
1966 base = R_EBX;
1967 index = R_ESI;
1968 break;
1969 case 1:
1970 base = R_EBX;
1971 index = R_EDI;
1972 break;
1973 case 2:
1974 base = R_EBP;
1975 index = R_ESI;
1976 def_seg = R_SS;
1977 break;
1978 case 3:
1979 base = R_EBP;
1980 index = R_EDI;
1981 def_seg = R_SS;
1982 break;
1983 case 4:
1984 base = R_ESI;
1985 break;
1986 case 5:
1987 base = R_EDI;
1988 break;
1989 case 6:
1990 base = R_EBP;
1991 def_seg = R_SS;
1992 break;
1993 default:
1994 case 7:
1995 base = R_EBX;
1996 break;
1998 break;
2000 default:
2001 tcg_abort();
2004 done:
2005 return (AddressParts){ def_seg, base, index, scale, disp };
2008 /* Compute the address, with a minimum number of TCG ops. */
2009 static TCGv gen_lea_modrm_1(AddressParts a)
2011 TCGv ea;
2013 TCGV_UNUSED(ea);
2014 if (a.index >= 0) {
2015 if (a.scale == 0) {
2016 ea = cpu_regs[a.index];
2017 } else {
2018 tcg_gen_shli_tl(cpu_A0, cpu_regs[a.index], a.scale);
2019 ea = cpu_A0;
2021 if (a.base >= 0) {
2022 tcg_gen_add_tl(cpu_A0, ea, cpu_regs[a.base]);
2023 ea = cpu_A0;
2025 } else if (a.base >= 0) {
2026 ea = cpu_regs[a.base];
2028 if (TCGV_IS_UNUSED(ea)) {
2029 tcg_gen_movi_tl(cpu_A0, a.disp);
2030 ea = cpu_A0;
2031 } else if (a.disp != 0) {
2032 tcg_gen_addi_tl(cpu_A0, ea, a.disp);
2033 ea = cpu_A0;
2036 return ea;
2039 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2041 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2042 TCGv ea = gen_lea_modrm_1(a);
2043 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2046 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2048 (void)gen_lea_modrm_0(env, s, modrm);
2051 /* Used for BNDCL, BNDCU, BNDCN. */
2052 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2053 TCGCond cond, TCGv_i64 bndv)
2055 TCGv ea = gen_lea_modrm_1(gen_lea_modrm_0(env, s, modrm));
2057 tcg_gen_extu_tl_i64(cpu_tmp1_i64, ea);
2058 if (!CODE64(s)) {
2059 tcg_gen_ext32u_i64(cpu_tmp1_i64, cpu_tmp1_i64);
2061 tcg_gen_setcond_i64(cond, cpu_tmp1_i64, cpu_tmp1_i64, bndv);
2062 tcg_gen_extrl_i64_i32(cpu_tmp2_i32, cpu_tmp1_i64);
2063 gen_helper_bndck(cpu_env, cpu_tmp2_i32);
2066 /* used for LEA and MOV AX, mem */
2067 static void gen_add_A0_ds_seg(DisasContext *s)
2069 gen_lea_v_seg(s, s->aflag, cpu_A0, R_DS, s->override);
2072 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2073 OR_TMP0 */
2074 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2075 TCGMemOp ot, int reg, int is_store)
2077 int mod, rm;
2079 mod = (modrm >> 6) & 3;
2080 rm = (modrm & 7) | REX_B(s);
2081 if (mod == 3) {
2082 if (is_store) {
2083 if (reg != OR_TMP0)
2084 gen_op_mov_v_reg(ot, cpu_T0, reg);
2085 gen_op_mov_reg_v(ot, rm, cpu_T0);
2086 } else {
2087 gen_op_mov_v_reg(ot, cpu_T0, rm);
2088 if (reg != OR_TMP0)
2089 gen_op_mov_reg_v(ot, reg, cpu_T0);
2091 } else {
2092 gen_lea_modrm(env, s, modrm);
2093 if (is_store) {
2094 if (reg != OR_TMP0)
2095 gen_op_mov_v_reg(ot, cpu_T0, reg);
2096 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
2097 } else {
2098 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
2099 if (reg != OR_TMP0)
2100 gen_op_mov_reg_v(ot, reg, cpu_T0);
2105 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
2107 uint32_t ret;
2109 switch (ot) {
2110 case MO_8:
2111 ret = cpu_ldub_code(env, s->pc);
2112 s->pc++;
2113 break;
2114 case MO_16:
2115 ret = cpu_lduw_code(env, s->pc);
2116 s->pc += 2;
2117 break;
2118 case MO_32:
2119 #ifdef TARGET_X86_64
2120 case MO_64:
2121 #endif
2122 ret = cpu_ldl_code(env, s->pc);
2123 s->pc += 4;
2124 break;
2125 default:
2126 tcg_abort();
2128 return ret;
2131 static inline int insn_const_size(TCGMemOp ot)
2133 if (ot <= MO_32) {
2134 return 1 << ot;
2135 } else {
2136 return 4;
2140 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2142 #ifndef CONFIG_USER_ONLY
2143 return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) ||
2144 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2145 #else
2146 return true;
2147 #endif
2150 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2152 target_ulong pc = s->cs_base + eip;
2154 if (use_goto_tb(s, pc)) {
2155 /* jump to same page: we can use a direct jump */
2156 tcg_gen_goto_tb(tb_num);
2157 gen_jmp_im(eip);
2158 tcg_gen_exit_tb((uintptr_t)s->tb + tb_num);
2159 } else {
2160 /* jump to another page: currently not optimized */
2161 gen_jmp_im(eip);
2162 gen_eob(s);
2166 static inline void gen_jcc(DisasContext *s, int b,
2167 target_ulong val, target_ulong next_eip)
2169 TCGLabel *l1, *l2;
2171 if (s->jmp_opt) {
2172 l1 = gen_new_label();
2173 gen_jcc1(s, b, l1);
2175 gen_goto_tb(s, 0, next_eip);
2177 gen_set_label(l1);
2178 gen_goto_tb(s, 1, val);
2179 s->is_jmp = DISAS_TB_JUMP;
2180 } else {
2181 l1 = gen_new_label();
2182 l2 = gen_new_label();
2183 gen_jcc1(s, b, l1);
2185 gen_jmp_im(next_eip);
2186 tcg_gen_br(l2);
2188 gen_set_label(l1);
2189 gen_jmp_im(val);
2190 gen_set_label(l2);
2191 gen_eob(s);
2195 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
2196 int modrm, int reg)
2198 CCPrepare cc;
2200 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2202 cc = gen_prepare_cc(s, b, cpu_T1);
2203 if (cc.mask != -1) {
2204 TCGv t0 = tcg_temp_new();
2205 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2206 cc.reg = t0;
2208 if (!cc.use_reg2) {
2209 cc.reg2 = tcg_const_tl(cc.imm);
2212 tcg_gen_movcond_tl(cc.cond, cpu_T0, cc.reg, cc.reg2,
2213 cpu_T0, cpu_regs[reg]);
2214 gen_op_mov_reg_v(ot, reg, cpu_T0);
2216 if (cc.mask != -1) {
2217 tcg_temp_free(cc.reg);
2219 if (!cc.use_reg2) {
2220 tcg_temp_free(cc.reg2);
2224 static inline void gen_op_movl_T0_seg(int seg_reg)
2226 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
2227 offsetof(CPUX86State,segs[seg_reg].selector));
2230 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2232 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
2233 tcg_gen_st32_tl(cpu_T0, cpu_env,
2234 offsetof(CPUX86State,segs[seg_reg].selector));
2235 tcg_gen_shli_tl(cpu_seg_base[seg_reg], cpu_T0, 4);
2238 /* move T0 to seg_reg and compute if the CPU state may change. Never
2239 call this function with seg_reg == R_CS */
2240 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
2242 if (s->pe && !s->vm86) {
2243 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
2244 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
2245 /* abort translation because the addseg value may change or
2246 because ss32 may change. For R_SS, translation must always
2247 stop as a special handling must be done to disable hardware
2248 interrupts for the next instruction */
2249 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
2250 s->is_jmp = DISAS_TB_JUMP;
2251 } else {
2252 gen_op_movl_seg_T0_vm(seg_reg);
2253 if (seg_reg == R_SS)
2254 s->is_jmp = DISAS_TB_JUMP;
2258 static inline int svm_is_rep(int prefixes)
2260 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2263 static inline void
2264 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2265 uint32_t type, uint64_t param)
2267 /* no SVM activated; fast case */
2268 if (likely(!(s->flags & HF_SVMI_MASK)))
2269 return;
2270 gen_update_cc_op(s);
2271 gen_jmp_im(pc_start - s->cs_base);
2272 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2273 tcg_const_i64(param));
2276 static inline void
2277 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2279 gen_svm_check_intercept_param(s, pc_start, type, 0);
2282 static inline void gen_stack_update(DisasContext *s, int addend)
2284 gen_op_add_reg_im(mo_stacksize(s), R_ESP, addend);
2287 /* Generate a push. It depends on ss32, addseg and dflag. */
2288 static void gen_push_v(DisasContext *s, TCGv val)
2290 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2291 TCGMemOp a_ot = mo_stacksize(s);
2292 int size = 1 << d_ot;
2293 TCGv new_esp = cpu_A0;
2295 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
2297 if (!CODE64(s)) {
2298 if (s->addseg) {
2299 new_esp = cpu_tmp4;
2300 tcg_gen_mov_tl(new_esp, cpu_A0);
2302 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2305 gen_op_st_v(s, d_ot, val, cpu_A0);
2306 gen_op_mov_reg_v(a_ot, R_ESP, new_esp);
2309 /* two step pop is necessary for precise exceptions */
2310 static TCGMemOp gen_pop_T0(DisasContext *s)
2312 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2314 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2315 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2317 return d_ot;
2320 static inline void gen_pop_update(DisasContext *s, TCGMemOp ot)
2322 gen_stack_update(s, 1 << ot);
2325 static inline void gen_stack_A0(DisasContext *s)
2327 gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2330 static void gen_pusha(DisasContext *s)
2332 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2333 TCGMemOp d_ot = s->dflag;
2334 int size = 1 << d_ot;
2335 int i;
2337 for (i = 0; i < 8; i++) {
2338 tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], (i - 8) * size);
2339 gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
2340 gen_op_st_v(s, d_ot, cpu_regs[7 - i], cpu_A0);
2343 gen_stack_update(s, -8 * size);
2346 static void gen_popa(DisasContext *s)
2348 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2349 TCGMemOp d_ot = s->dflag;
2350 int size = 1 << d_ot;
2351 int i;
2353 for (i = 0; i < 8; i++) {
2354 /* ESP is not reloaded */
2355 if (7 - i == R_ESP) {
2356 continue;
2358 tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], i * size);
2359 gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1);
2360 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2361 gen_op_mov_reg_v(d_ot, 7 - i, cpu_T0);
2364 gen_stack_update(s, 8 * size);
2367 static void gen_enter(DisasContext *s, int esp_addend, int level)
2369 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2370 TCGMemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
2371 int size = 1 << d_ot;
2373 /* Push BP; compute FrameTemp into T1. */
2374 tcg_gen_subi_tl(cpu_T1, cpu_regs[R_ESP], size);
2375 gen_lea_v_seg(s, a_ot, cpu_T1, R_SS, -1);
2376 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], cpu_A0);
2378 level &= 31;
2379 if (level != 0) {
2380 int i;
2382 /* Copy level-1 pointers from the previous frame. */
2383 for (i = 1; i < level; ++i) {
2384 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_EBP], size * i);
2385 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2386 gen_op_ld_v(s, d_ot, cpu_tmp0, cpu_A0);
2388 tcg_gen_subi_tl(cpu_A0, cpu_T1, size * i);
2389 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2390 gen_op_st_v(s, d_ot, cpu_tmp0, cpu_A0);
2393 /* Push the current FrameTemp as the last level. */
2394 tcg_gen_subi_tl(cpu_A0, cpu_T1, size * level);
2395 gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1);
2396 gen_op_st_v(s, d_ot, cpu_T1, cpu_A0);
2399 /* Copy the FrameTemp value to EBP. */
2400 gen_op_mov_reg_v(a_ot, R_EBP, cpu_T1);
2402 /* Compute the final value of ESP. */
2403 tcg_gen_subi_tl(cpu_T1, cpu_T1, esp_addend + size * level);
2404 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2407 static void gen_leave(DisasContext *s)
2409 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2410 TCGMemOp a_ot = mo_stacksize(s);
2412 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2413 gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
2415 tcg_gen_addi_tl(cpu_T1, cpu_regs[R_EBP], 1 << d_ot);
2417 gen_op_mov_reg_v(d_ot, R_EBP, cpu_T0);
2418 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2421 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2423 gen_update_cc_op(s);
2424 gen_jmp_im(cur_eip);
2425 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
2426 s->is_jmp = DISAS_TB_JUMP;
2429 /* Generate #UD for the current instruction. The assumption here is that
2430 the instruction is known, but it isn't allowed in the current cpu mode. */
2431 static void gen_illegal_opcode(DisasContext *s)
2433 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
2436 /* Similarly, except that the assumption here is that we don't decode
2437 the instruction at all -- either a missing opcode, an unimplemented
2438 feature, or just a bogus instruction stream. */
2439 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2441 gen_illegal_opcode(s);
2443 if (qemu_loglevel_mask(LOG_UNIMP)) {
2444 target_ulong pc = s->pc_start, end = s->pc;
2445 qemu_log_lock();
2446 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2447 for (; pc < end; ++pc) {
2448 qemu_log(" %02x", cpu_ldub_code(env, pc));
2450 qemu_log("\n");
2451 qemu_log_unlock();
2455 /* an interrupt is different from an exception because of the
2456 privilege checks */
2457 static void gen_interrupt(DisasContext *s, int intno,
2458 target_ulong cur_eip, target_ulong next_eip)
2460 gen_update_cc_op(s);
2461 gen_jmp_im(cur_eip);
2462 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2463 tcg_const_i32(next_eip - cur_eip));
2464 s->is_jmp = DISAS_TB_JUMP;
2467 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2469 gen_update_cc_op(s);
2470 gen_jmp_im(cur_eip);
2471 gen_helper_debug(cpu_env);
2472 s->is_jmp = DISAS_TB_JUMP;
2475 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2477 if ((s->flags & mask) == 0) {
2478 TCGv_i32 t = tcg_temp_new_i32();
2479 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2480 tcg_gen_ori_i32(t, t, mask);
2481 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2482 tcg_temp_free_i32(t);
2483 s->flags |= mask;
2487 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2489 if (s->flags & mask) {
2490 TCGv_i32 t = tcg_temp_new_i32();
2491 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2492 tcg_gen_andi_i32(t, t, ~mask);
2493 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2494 tcg_temp_free_i32(t);
2495 s->flags &= ~mask;
2499 /* Clear BND registers during legacy branches. */
2500 static void gen_bnd_jmp(DisasContext *s)
2502 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2503 and if the BNDREGs are known to be in use (non-zero) already.
2504 The helper itself will check BNDPRESERVE at runtime. */
2505 if ((s->prefix & PREFIX_REPNZ) == 0
2506 && (s->flags & HF_MPX_EN_MASK) != 0
2507 && (s->flags & HF_MPX_IU_MASK) != 0) {
2508 gen_helper_bnd_jmp(cpu_env);
2512 /* Generate an end of block. Trace exception is also generated if needed.
2513 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.
2514 If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
2515 S->TF. This is used by the syscall/sysret insns. */
2516 static void gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2518 gen_update_cc_op(s);
2520 /* If several instructions disable interrupts, only the first does it. */
2521 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2522 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2523 } else {
2524 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2527 if (s->tb->flags & HF_RF_MASK) {
2528 gen_helper_reset_rf(cpu_env);
2530 if (s->singlestep_enabled) {
2531 gen_helper_debug(cpu_env);
2532 } else if (recheck_tf) {
2533 gen_helper_rechecking_single_step(cpu_env);
2534 tcg_gen_exit_tb(0);
2535 } else if (s->tf) {
2536 gen_helper_single_step(cpu_env);
2537 } else {
2538 tcg_gen_exit_tb(0);
2540 s->is_jmp = DISAS_TB_JUMP;
2543 /* End of block.
2544 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2545 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2547 gen_eob_worker(s, inhibit, false);
2550 /* End of block, resetting the inhibit irq flag. */
2551 static void gen_eob(DisasContext *s)
2553 gen_eob_worker(s, false, false);
2556 /* generate a jump to eip. No segment change must happen before as a
2557 direct call to the next block may occur */
2558 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2560 gen_update_cc_op(s);
2561 set_cc_op(s, CC_OP_DYNAMIC);
2562 if (s->jmp_opt) {
2563 gen_goto_tb(s, tb_num, eip);
2564 s->is_jmp = DISAS_TB_JUMP;
2565 } else {
2566 gen_jmp_im(eip);
2567 gen_eob(s);
2571 static void gen_jmp(DisasContext *s, target_ulong eip)
2573 gen_jmp_tb(s, eip, 0);
2576 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2578 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2579 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2582 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2584 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2585 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2588 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2590 int mem_index = s->mem_index;
2591 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2592 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2593 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2594 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2595 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2598 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2600 int mem_index = s->mem_index;
2601 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2602 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2603 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2604 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2605 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2608 static inline void gen_op_movo(int d_offset, int s_offset)
2610 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2611 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2612 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2613 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2616 static inline void gen_op_movq(int d_offset, int s_offset)
2618 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2619 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2622 static inline void gen_op_movl(int d_offset, int s_offset)
2624 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2625 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2628 static inline void gen_op_movq_env_0(int d_offset)
2630 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2631 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2634 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2635 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2636 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2637 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2638 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2639 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2640 TCGv_i32 val);
2641 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2642 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2643 TCGv val);
2645 #define SSE_SPECIAL ((void *)1)
2646 #define SSE_DUMMY ((void *)2)
2648 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2649 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2650 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2652 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2653 /* 3DNow! extensions */
2654 [0x0e] = { SSE_DUMMY }, /* femms */
2655 [0x0f] = { SSE_DUMMY }, /* pf... */
2656 /* pure SSE operations */
2657 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2658 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2659 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2660 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2661 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2662 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2663 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2664 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2666 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2667 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2668 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2669 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2670 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2671 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2672 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2673 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2674 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2675 [0x51] = SSE_FOP(sqrt),
2676 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2677 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2678 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2679 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2680 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2681 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2682 [0x58] = SSE_FOP(add),
2683 [0x59] = SSE_FOP(mul),
2684 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2685 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2686 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2687 [0x5c] = SSE_FOP(sub),
2688 [0x5d] = SSE_FOP(min),
2689 [0x5e] = SSE_FOP(div),
2690 [0x5f] = SSE_FOP(max),
2692 [0xc2] = SSE_FOP(cmpeq),
2693 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2694 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2696 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2697 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2698 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2700 /* MMX ops and their SSE extensions */
2701 [0x60] = MMX_OP2(punpcklbw),
2702 [0x61] = MMX_OP2(punpcklwd),
2703 [0x62] = MMX_OP2(punpckldq),
2704 [0x63] = MMX_OP2(packsswb),
2705 [0x64] = MMX_OP2(pcmpgtb),
2706 [0x65] = MMX_OP2(pcmpgtw),
2707 [0x66] = MMX_OP2(pcmpgtl),
2708 [0x67] = MMX_OP2(packuswb),
2709 [0x68] = MMX_OP2(punpckhbw),
2710 [0x69] = MMX_OP2(punpckhwd),
2711 [0x6a] = MMX_OP2(punpckhdq),
2712 [0x6b] = MMX_OP2(packssdw),
2713 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2714 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2715 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2716 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2717 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2718 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2719 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2720 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2721 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2722 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2723 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2724 [0x74] = MMX_OP2(pcmpeqb),
2725 [0x75] = MMX_OP2(pcmpeqw),
2726 [0x76] = MMX_OP2(pcmpeql),
2727 [0x77] = { SSE_DUMMY }, /* emms */
2728 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2729 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2730 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2731 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2732 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2733 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2734 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2735 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2736 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2737 [0xd1] = MMX_OP2(psrlw),
2738 [0xd2] = MMX_OP2(psrld),
2739 [0xd3] = MMX_OP2(psrlq),
2740 [0xd4] = MMX_OP2(paddq),
2741 [0xd5] = MMX_OP2(pmullw),
2742 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2743 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2744 [0xd8] = MMX_OP2(psubusb),
2745 [0xd9] = MMX_OP2(psubusw),
2746 [0xda] = MMX_OP2(pminub),
2747 [0xdb] = MMX_OP2(pand),
2748 [0xdc] = MMX_OP2(paddusb),
2749 [0xdd] = MMX_OP2(paddusw),
2750 [0xde] = MMX_OP2(pmaxub),
2751 [0xdf] = MMX_OP2(pandn),
2752 [0xe0] = MMX_OP2(pavgb),
2753 [0xe1] = MMX_OP2(psraw),
2754 [0xe2] = MMX_OP2(psrad),
2755 [0xe3] = MMX_OP2(pavgw),
2756 [0xe4] = MMX_OP2(pmulhuw),
2757 [0xe5] = MMX_OP2(pmulhw),
2758 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2759 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2760 [0xe8] = MMX_OP2(psubsb),
2761 [0xe9] = MMX_OP2(psubsw),
2762 [0xea] = MMX_OP2(pminsw),
2763 [0xeb] = MMX_OP2(por),
2764 [0xec] = MMX_OP2(paddsb),
2765 [0xed] = MMX_OP2(paddsw),
2766 [0xee] = MMX_OP2(pmaxsw),
2767 [0xef] = MMX_OP2(pxor),
2768 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2769 [0xf1] = MMX_OP2(psllw),
2770 [0xf2] = MMX_OP2(pslld),
2771 [0xf3] = MMX_OP2(psllq),
2772 [0xf4] = MMX_OP2(pmuludq),
2773 [0xf5] = MMX_OP2(pmaddwd),
2774 [0xf6] = MMX_OP2(psadbw),
2775 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2776 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2777 [0xf8] = MMX_OP2(psubb),
2778 [0xf9] = MMX_OP2(psubw),
2779 [0xfa] = MMX_OP2(psubl),
2780 [0xfb] = MMX_OP2(psubq),
2781 [0xfc] = MMX_OP2(paddb),
2782 [0xfd] = MMX_OP2(paddw),
2783 [0xfe] = MMX_OP2(paddl),
2786 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2787 [0 + 2] = MMX_OP2(psrlw),
2788 [0 + 4] = MMX_OP2(psraw),
2789 [0 + 6] = MMX_OP2(psllw),
2790 [8 + 2] = MMX_OP2(psrld),
2791 [8 + 4] = MMX_OP2(psrad),
2792 [8 + 6] = MMX_OP2(pslld),
2793 [16 + 2] = MMX_OP2(psrlq),
2794 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2795 [16 + 6] = MMX_OP2(psllq),
2796 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2799 static const SSEFunc_0_epi sse_op_table3ai[] = {
2800 gen_helper_cvtsi2ss,
2801 gen_helper_cvtsi2sd
2804 #ifdef TARGET_X86_64
2805 static const SSEFunc_0_epl sse_op_table3aq[] = {
2806 gen_helper_cvtsq2ss,
2807 gen_helper_cvtsq2sd
2809 #endif
2811 static const SSEFunc_i_ep sse_op_table3bi[] = {
2812 gen_helper_cvttss2si,
2813 gen_helper_cvtss2si,
2814 gen_helper_cvttsd2si,
2815 gen_helper_cvtsd2si
2818 #ifdef TARGET_X86_64
2819 static const SSEFunc_l_ep sse_op_table3bq[] = {
2820 gen_helper_cvttss2sq,
2821 gen_helper_cvtss2sq,
2822 gen_helper_cvttsd2sq,
2823 gen_helper_cvtsd2sq
2825 #endif
2827 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2828 SSE_FOP(cmpeq),
2829 SSE_FOP(cmplt),
2830 SSE_FOP(cmple),
2831 SSE_FOP(cmpunord),
2832 SSE_FOP(cmpneq),
2833 SSE_FOP(cmpnlt),
2834 SSE_FOP(cmpnle),
2835 SSE_FOP(cmpord),
2838 static const SSEFunc_0_epp sse_op_table5[256] = {
2839 [0x0c] = gen_helper_pi2fw,
2840 [0x0d] = gen_helper_pi2fd,
2841 [0x1c] = gen_helper_pf2iw,
2842 [0x1d] = gen_helper_pf2id,
2843 [0x8a] = gen_helper_pfnacc,
2844 [0x8e] = gen_helper_pfpnacc,
2845 [0x90] = gen_helper_pfcmpge,
2846 [0x94] = gen_helper_pfmin,
2847 [0x96] = gen_helper_pfrcp,
2848 [0x97] = gen_helper_pfrsqrt,
2849 [0x9a] = gen_helper_pfsub,
2850 [0x9e] = gen_helper_pfadd,
2851 [0xa0] = gen_helper_pfcmpgt,
2852 [0xa4] = gen_helper_pfmax,
2853 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2854 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2855 [0xaa] = gen_helper_pfsubr,
2856 [0xae] = gen_helper_pfacc,
2857 [0xb0] = gen_helper_pfcmpeq,
2858 [0xb4] = gen_helper_pfmul,
2859 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2860 [0xb7] = gen_helper_pmulhrw_mmx,
2861 [0xbb] = gen_helper_pswapd,
2862 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
2865 struct SSEOpHelper_epp {
2866 SSEFunc_0_epp op[2];
2867 uint32_t ext_mask;
2870 struct SSEOpHelper_eppi {
2871 SSEFunc_0_eppi op[2];
2872 uint32_t ext_mask;
2875 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2876 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2877 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
2878 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
2879 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2880 CPUID_EXT_PCLMULQDQ }
2881 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
2883 static const struct SSEOpHelper_epp sse_op_table6[256] = {
2884 [0x00] = SSSE3_OP(pshufb),
2885 [0x01] = SSSE3_OP(phaddw),
2886 [0x02] = SSSE3_OP(phaddd),
2887 [0x03] = SSSE3_OP(phaddsw),
2888 [0x04] = SSSE3_OP(pmaddubsw),
2889 [0x05] = SSSE3_OP(phsubw),
2890 [0x06] = SSSE3_OP(phsubd),
2891 [0x07] = SSSE3_OP(phsubsw),
2892 [0x08] = SSSE3_OP(psignb),
2893 [0x09] = SSSE3_OP(psignw),
2894 [0x0a] = SSSE3_OP(psignd),
2895 [0x0b] = SSSE3_OP(pmulhrsw),
2896 [0x10] = SSE41_OP(pblendvb),
2897 [0x14] = SSE41_OP(blendvps),
2898 [0x15] = SSE41_OP(blendvpd),
2899 [0x17] = SSE41_OP(ptest),
2900 [0x1c] = SSSE3_OP(pabsb),
2901 [0x1d] = SSSE3_OP(pabsw),
2902 [0x1e] = SSSE3_OP(pabsd),
2903 [0x20] = SSE41_OP(pmovsxbw),
2904 [0x21] = SSE41_OP(pmovsxbd),
2905 [0x22] = SSE41_OP(pmovsxbq),
2906 [0x23] = SSE41_OP(pmovsxwd),
2907 [0x24] = SSE41_OP(pmovsxwq),
2908 [0x25] = SSE41_OP(pmovsxdq),
2909 [0x28] = SSE41_OP(pmuldq),
2910 [0x29] = SSE41_OP(pcmpeqq),
2911 [0x2a] = SSE41_SPECIAL, /* movntqda */
2912 [0x2b] = SSE41_OP(packusdw),
2913 [0x30] = SSE41_OP(pmovzxbw),
2914 [0x31] = SSE41_OP(pmovzxbd),
2915 [0x32] = SSE41_OP(pmovzxbq),
2916 [0x33] = SSE41_OP(pmovzxwd),
2917 [0x34] = SSE41_OP(pmovzxwq),
2918 [0x35] = SSE41_OP(pmovzxdq),
2919 [0x37] = SSE42_OP(pcmpgtq),
2920 [0x38] = SSE41_OP(pminsb),
2921 [0x39] = SSE41_OP(pminsd),
2922 [0x3a] = SSE41_OP(pminuw),
2923 [0x3b] = SSE41_OP(pminud),
2924 [0x3c] = SSE41_OP(pmaxsb),
2925 [0x3d] = SSE41_OP(pmaxsd),
2926 [0x3e] = SSE41_OP(pmaxuw),
2927 [0x3f] = SSE41_OP(pmaxud),
2928 [0x40] = SSE41_OP(pmulld),
2929 [0x41] = SSE41_OP(phminposuw),
2930 [0xdb] = AESNI_OP(aesimc),
2931 [0xdc] = AESNI_OP(aesenc),
2932 [0xdd] = AESNI_OP(aesenclast),
2933 [0xde] = AESNI_OP(aesdec),
2934 [0xdf] = AESNI_OP(aesdeclast),
2937 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
2938 [0x08] = SSE41_OP(roundps),
2939 [0x09] = SSE41_OP(roundpd),
2940 [0x0a] = SSE41_OP(roundss),
2941 [0x0b] = SSE41_OP(roundsd),
2942 [0x0c] = SSE41_OP(blendps),
2943 [0x0d] = SSE41_OP(blendpd),
2944 [0x0e] = SSE41_OP(pblendw),
2945 [0x0f] = SSSE3_OP(palignr),
2946 [0x14] = SSE41_SPECIAL, /* pextrb */
2947 [0x15] = SSE41_SPECIAL, /* pextrw */
2948 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
2949 [0x17] = SSE41_SPECIAL, /* extractps */
2950 [0x20] = SSE41_SPECIAL, /* pinsrb */
2951 [0x21] = SSE41_SPECIAL, /* insertps */
2952 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
2953 [0x40] = SSE41_OP(dpps),
2954 [0x41] = SSE41_OP(dppd),
2955 [0x42] = SSE41_OP(mpsadbw),
2956 [0x44] = PCLMULQDQ_OP(pclmulqdq),
2957 [0x60] = SSE42_OP(pcmpestrm),
2958 [0x61] = SSE42_OP(pcmpestri),
2959 [0x62] = SSE42_OP(pcmpistrm),
2960 [0x63] = SSE42_OP(pcmpistri),
2961 [0xdf] = AESNI_OP(aeskeygenassist),
2964 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
2965 target_ulong pc_start, int rex_r)
2967 int b1, op1_offset, op2_offset, is_xmm, val;
2968 int modrm, mod, rm, reg;
2969 SSEFunc_0_epp sse_fn_epp;
2970 SSEFunc_0_eppi sse_fn_eppi;
2971 SSEFunc_0_ppi sse_fn_ppi;
2972 SSEFunc_0_eppt sse_fn_eppt;
2973 TCGMemOp ot;
2975 b &= 0xff;
2976 if (s->prefix & PREFIX_DATA)
2977 b1 = 1;
2978 else if (s->prefix & PREFIX_REPZ)
2979 b1 = 2;
2980 else if (s->prefix & PREFIX_REPNZ)
2981 b1 = 3;
2982 else
2983 b1 = 0;
2984 sse_fn_epp = sse_op_table1[b][b1];
2985 if (!sse_fn_epp) {
2986 goto unknown_op;
2988 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
2989 is_xmm = 1;
2990 } else {
2991 if (b1 == 0) {
2992 /* MMX case */
2993 is_xmm = 0;
2994 } else {
2995 is_xmm = 1;
2998 /* simple MMX/SSE operation */
2999 if (s->flags & HF_TS_MASK) {
3000 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3001 return;
3003 if (s->flags & HF_EM_MASK) {
3004 illegal_op:
3005 gen_illegal_opcode(s);
3006 return;
3008 if (is_xmm
3009 && !(s->flags & HF_OSFXSR_MASK)
3010 && ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
3011 goto unknown_op;
3013 if (b == 0x0e) {
3014 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3015 /* If we were fully decoding this we might use illegal_op. */
3016 goto unknown_op;
3018 /* femms */
3019 gen_helper_emms(cpu_env);
3020 return;
3022 if (b == 0x77) {
3023 /* emms */
3024 gen_helper_emms(cpu_env);
3025 return;
3027 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3028 the static cpu state) */
3029 if (!is_xmm) {
3030 gen_helper_enter_mmx(cpu_env);
3033 modrm = cpu_ldub_code(env, s->pc++);
3034 reg = ((modrm >> 3) & 7);
3035 if (is_xmm)
3036 reg |= rex_r;
3037 mod = (modrm >> 6) & 3;
3038 if (sse_fn_epp == SSE_SPECIAL) {
3039 b |= (b1 << 8);
3040 switch(b) {
3041 case 0x0e7: /* movntq */
3042 if (mod == 3) {
3043 goto illegal_op;
3045 gen_lea_modrm(env, s, modrm);
3046 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3047 break;
3048 case 0x1e7: /* movntdq */
3049 case 0x02b: /* movntps */
3050 case 0x12b: /* movntps */
3051 if (mod == 3)
3052 goto illegal_op;
3053 gen_lea_modrm(env, s, modrm);
3054 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3055 break;
3056 case 0x3f0: /* lddqu */
3057 if (mod == 3)
3058 goto illegal_op;
3059 gen_lea_modrm(env, s, modrm);
3060 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3061 break;
3062 case 0x22b: /* movntss */
3063 case 0x32b: /* movntsd */
3064 if (mod == 3)
3065 goto illegal_op;
3066 gen_lea_modrm(env, s, modrm);
3067 if (b1 & 1) {
3068 gen_stq_env_A0(s, offsetof(CPUX86State,
3069 xmm_regs[reg].ZMM_Q(0)));
3070 } else {
3071 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
3072 xmm_regs[reg].ZMM_L(0)));
3073 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3075 break;
3076 case 0x6e: /* movd mm, ea */
3077 #ifdef TARGET_X86_64
3078 if (s->dflag == MO_64) {
3079 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3080 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3081 } else
3082 #endif
3084 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3085 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3086 offsetof(CPUX86State,fpregs[reg].mmx));
3087 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3088 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
3090 break;
3091 case 0x16e: /* movd xmm, ea */
3092 #ifdef TARGET_X86_64
3093 if (s->dflag == MO_64) {
3094 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3095 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3096 offsetof(CPUX86State,xmm_regs[reg]));
3097 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T0);
3098 } else
3099 #endif
3101 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3102 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3103 offsetof(CPUX86State,xmm_regs[reg]));
3104 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3105 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
3107 break;
3108 case 0x6f: /* movq mm, ea */
3109 if (mod != 3) {
3110 gen_lea_modrm(env, s, modrm);
3111 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3112 } else {
3113 rm = (modrm & 7);
3114 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3115 offsetof(CPUX86State,fpregs[rm].mmx));
3116 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3117 offsetof(CPUX86State,fpregs[reg].mmx));
3119 break;
3120 case 0x010: /* movups */
3121 case 0x110: /* movupd */
3122 case 0x028: /* movaps */
3123 case 0x128: /* movapd */
3124 case 0x16f: /* movdqa xmm, ea */
3125 case 0x26f: /* movdqu xmm, ea */
3126 if (mod != 3) {
3127 gen_lea_modrm(env, s, modrm);
3128 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3129 } else {
3130 rm = (modrm & 7) | REX_B(s);
3131 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3132 offsetof(CPUX86State,xmm_regs[rm]));
3134 break;
3135 case 0x210: /* movss xmm, ea */
3136 if (mod != 3) {
3137 gen_lea_modrm(env, s, modrm);
3138 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3139 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3140 tcg_gen_movi_tl(cpu_T0, 0);
3141 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3142 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3143 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3144 } else {
3145 rm = (modrm & 7) | REX_B(s);
3146 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3147 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3149 break;
3150 case 0x310: /* movsd xmm, ea */
3151 if (mod != 3) {
3152 gen_lea_modrm(env, s, modrm);
3153 gen_ldq_env_A0(s, offsetof(CPUX86State,
3154 xmm_regs[reg].ZMM_Q(0)));
3155 tcg_gen_movi_tl(cpu_T0, 0);
3156 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3157 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3158 } else {
3159 rm = (modrm & 7) | REX_B(s);
3160 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3161 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3163 break;
3164 case 0x012: /* movlps */
3165 case 0x112: /* movlpd */
3166 if (mod != 3) {
3167 gen_lea_modrm(env, s, modrm);
3168 gen_ldq_env_A0(s, offsetof(CPUX86State,
3169 xmm_regs[reg].ZMM_Q(0)));
3170 } else {
3171 /* movhlps */
3172 rm = (modrm & 7) | REX_B(s);
3173 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3174 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3176 break;
3177 case 0x212: /* movsldup */
3178 if (mod != 3) {
3179 gen_lea_modrm(env, s, modrm);
3180 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3181 } else {
3182 rm = (modrm & 7) | REX_B(s);
3183 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3184 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3185 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3186 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3188 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3189 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3190 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3191 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3192 break;
3193 case 0x312: /* movddup */
3194 if (mod != 3) {
3195 gen_lea_modrm(env, s, modrm);
3196 gen_ldq_env_A0(s, offsetof(CPUX86State,
3197 xmm_regs[reg].ZMM_Q(0)));
3198 } else {
3199 rm = (modrm & 7) | REX_B(s);
3200 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3201 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3203 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3204 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3205 break;
3206 case 0x016: /* movhps */
3207 case 0x116: /* movhpd */
3208 if (mod != 3) {
3209 gen_lea_modrm(env, s, modrm);
3210 gen_ldq_env_A0(s, offsetof(CPUX86State,
3211 xmm_regs[reg].ZMM_Q(1)));
3212 } else {
3213 /* movlhps */
3214 rm = (modrm & 7) | REX_B(s);
3215 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3216 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3218 break;
3219 case 0x216: /* movshdup */
3220 if (mod != 3) {
3221 gen_lea_modrm(env, s, modrm);
3222 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3223 } else {
3224 rm = (modrm & 7) | REX_B(s);
3225 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3226 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3227 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3228 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3230 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3231 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3232 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3233 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3234 break;
3235 case 0x178:
3236 case 0x378:
3238 int bit_index, field_length;
3240 if (b1 == 1 && reg != 0)
3241 goto illegal_op;
3242 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3243 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3244 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3245 offsetof(CPUX86State,xmm_regs[reg]));
3246 if (b1 == 1)
3247 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3248 tcg_const_i32(bit_index),
3249 tcg_const_i32(field_length));
3250 else
3251 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3252 tcg_const_i32(bit_index),
3253 tcg_const_i32(field_length));
3255 break;
3256 case 0x7e: /* movd ea, mm */
3257 #ifdef TARGET_X86_64
3258 if (s->dflag == MO_64) {
3259 tcg_gen_ld_i64(cpu_T0, cpu_env,
3260 offsetof(CPUX86State,fpregs[reg].mmx));
3261 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3262 } else
3263 #endif
3265 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3266 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3267 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3269 break;
3270 case 0x17e: /* movd ea, xmm */
3271 #ifdef TARGET_X86_64
3272 if (s->dflag == MO_64) {
3273 tcg_gen_ld_i64(cpu_T0, cpu_env,
3274 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3275 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3276 } else
3277 #endif
3279 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
3280 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3281 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3283 break;
3284 case 0x27e: /* movq xmm, ea */
3285 if (mod != 3) {
3286 gen_lea_modrm(env, s, modrm);
3287 gen_ldq_env_A0(s, offsetof(CPUX86State,
3288 xmm_regs[reg].ZMM_Q(0)));
3289 } else {
3290 rm = (modrm & 7) | REX_B(s);
3291 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3292 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3294 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3295 break;
3296 case 0x7f: /* movq ea, mm */
3297 if (mod != 3) {
3298 gen_lea_modrm(env, s, modrm);
3299 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3300 } else {
3301 rm = (modrm & 7);
3302 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3303 offsetof(CPUX86State,fpregs[reg].mmx));
3305 break;
3306 case 0x011: /* movups */
3307 case 0x111: /* movupd */
3308 case 0x029: /* movaps */
3309 case 0x129: /* movapd */
3310 case 0x17f: /* movdqa ea, xmm */
3311 case 0x27f: /* movdqu ea, xmm */
3312 if (mod != 3) {
3313 gen_lea_modrm(env, s, modrm);
3314 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3315 } else {
3316 rm = (modrm & 7) | REX_B(s);
3317 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3318 offsetof(CPUX86State,xmm_regs[reg]));
3320 break;
3321 case 0x211: /* movss ea, xmm */
3322 if (mod != 3) {
3323 gen_lea_modrm(env, s, modrm);
3324 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3325 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
3326 } else {
3327 rm = (modrm & 7) | REX_B(s);
3328 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)),
3329 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3331 break;
3332 case 0x311: /* movsd ea, xmm */
3333 if (mod != 3) {
3334 gen_lea_modrm(env, s, modrm);
3335 gen_stq_env_A0(s, offsetof(CPUX86State,
3336 xmm_regs[reg].ZMM_Q(0)));
3337 } else {
3338 rm = (modrm & 7) | REX_B(s);
3339 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3340 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3342 break;
3343 case 0x013: /* movlps */
3344 case 0x113: /* movlpd */
3345 if (mod != 3) {
3346 gen_lea_modrm(env, s, modrm);
3347 gen_stq_env_A0(s, offsetof(CPUX86State,
3348 xmm_regs[reg].ZMM_Q(0)));
3349 } else {
3350 goto illegal_op;
3352 break;
3353 case 0x017: /* movhps */
3354 case 0x117: /* movhpd */
3355 if (mod != 3) {
3356 gen_lea_modrm(env, s, modrm);
3357 gen_stq_env_A0(s, offsetof(CPUX86State,
3358 xmm_regs[reg].ZMM_Q(1)));
3359 } else {
3360 goto illegal_op;
3362 break;
3363 case 0x71: /* shift mm, im */
3364 case 0x72:
3365 case 0x73:
3366 case 0x171: /* shift xmm, im */
3367 case 0x172:
3368 case 0x173:
3369 if (b1 >= 2) {
3370 goto unknown_op;
3372 val = cpu_ldub_code(env, s->pc++);
3373 if (is_xmm) {
3374 tcg_gen_movi_tl(cpu_T0, val);
3375 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3376 tcg_gen_movi_tl(cpu_T0, 0);
3377 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(1)));
3378 op1_offset = offsetof(CPUX86State,xmm_t0);
3379 } else {
3380 tcg_gen_movi_tl(cpu_T0, val);
3381 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3382 tcg_gen_movi_tl(cpu_T0, 0);
3383 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3384 op1_offset = offsetof(CPUX86State,mmx_t0);
3386 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3387 (((modrm >> 3)) & 7)][b1];
3388 if (!sse_fn_epp) {
3389 goto unknown_op;
3391 if (is_xmm) {
3392 rm = (modrm & 7) | REX_B(s);
3393 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3394 } else {
3395 rm = (modrm & 7);
3396 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3398 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3399 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3400 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3401 break;
3402 case 0x050: /* movmskps */
3403 rm = (modrm & 7) | REX_B(s);
3404 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3405 offsetof(CPUX86State,xmm_regs[rm]));
3406 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3407 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3408 break;
3409 case 0x150: /* movmskpd */
3410 rm = (modrm & 7) | REX_B(s);
3411 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3412 offsetof(CPUX86State,xmm_regs[rm]));
3413 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3414 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3415 break;
3416 case 0x02a: /* cvtpi2ps */
3417 case 0x12a: /* cvtpi2pd */
3418 gen_helper_enter_mmx(cpu_env);
3419 if (mod != 3) {
3420 gen_lea_modrm(env, s, modrm);
3421 op2_offset = offsetof(CPUX86State,mmx_t0);
3422 gen_ldq_env_A0(s, op2_offset);
3423 } else {
3424 rm = (modrm & 7);
3425 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3427 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3428 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3429 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3430 switch(b >> 8) {
3431 case 0x0:
3432 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3433 break;
3434 default:
3435 case 0x1:
3436 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3437 break;
3439 break;
3440 case 0x22a: /* cvtsi2ss */
3441 case 0x32a: /* cvtsi2sd */
3442 ot = mo_64_32(s->dflag);
3443 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3444 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3445 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3446 if (ot == MO_32) {
3447 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3448 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3449 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3450 } else {
3451 #ifdef TARGET_X86_64
3452 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3453 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T0);
3454 #else
3455 goto illegal_op;
3456 #endif
3458 break;
3459 case 0x02c: /* cvttps2pi */
3460 case 0x12c: /* cvttpd2pi */
3461 case 0x02d: /* cvtps2pi */
3462 case 0x12d: /* cvtpd2pi */
3463 gen_helper_enter_mmx(cpu_env);
3464 if (mod != 3) {
3465 gen_lea_modrm(env, s, modrm);
3466 op2_offset = offsetof(CPUX86State,xmm_t0);
3467 gen_ldo_env_A0(s, op2_offset);
3468 } else {
3469 rm = (modrm & 7) | REX_B(s);
3470 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3472 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3473 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3474 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3475 switch(b) {
3476 case 0x02c:
3477 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3478 break;
3479 case 0x12c:
3480 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3481 break;
3482 case 0x02d:
3483 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3484 break;
3485 case 0x12d:
3486 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3487 break;
3489 break;
3490 case 0x22c: /* cvttss2si */
3491 case 0x22d: /* cvtss2si */
3492 case 0x32c: /* cvttsd2si */
3493 case 0x32d: /* cvtsd2si */
3494 ot = mo_64_32(s->dflag);
3495 if (mod != 3) {
3496 gen_lea_modrm(env, s, modrm);
3497 if ((b >> 8) & 1) {
3498 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3499 } else {
3500 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
3501 tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
3503 op2_offset = offsetof(CPUX86State,xmm_t0);
3504 } else {
3505 rm = (modrm & 7) | REX_B(s);
3506 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3508 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3509 if (ot == MO_32) {
3510 SSEFunc_i_ep sse_fn_i_ep =
3511 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3512 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3513 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
3514 } else {
3515 #ifdef TARGET_X86_64
3516 SSEFunc_l_ep sse_fn_l_ep =
3517 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3518 sse_fn_l_ep(cpu_T0, cpu_env, cpu_ptr0);
3519 #else
3520 goto illegal_op;
3521 #endif
3523 gen_op_mov_reg_v(ot, reg, cpu_T0);
3524 break;
3525 case 0xc4: /* pinsrw */
3526 case 0x1c4:
3527 s->rip_offset = 1;
3528 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3529 val = cpu_ldub_code(env, s->pc++);
3530 if (b1) {
3531 val &= 7;
3532 tcg_gen_st16_tl(cpu_T0, cpu_env,
3533 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3534 } else {
3535 val &= 3;
3536 tcg_gen_st16_tl(cpu_T0, cpu_env,
3537 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3539 break;
3540 case 0xc5: /* pextrw */
3541 case 0x1c5:
3542 if (mod != 3)
3543 goto illegal_op;
3544 ot = mo_64_32(s->dflag);
3545 val = cpu_ldub_code(env, s->pc++);
3546 if (b1) {
3547 val &= 7;
3548 rm = (modrm & 7) | REX_B(s);
3549 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3550 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3551 } else {
3552 val &= 3;
3553 rm = (modrm & 7);
3554 tcg_gen_ld16u_tl(cpu_T0, cpu_env,
3555 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3557 reg = ((modrm >> 3) & 7) | rex_r;
3558 gen_op_mov_reg_v(ot, reg, cpu_T0);
3559 break;
3560 case 0x1d6: /* movq ea, xmm */
3561 if (mod != 3) {
3562 gen_lea_modrm(env, s, modrm);
3563 gen_stq_env_A0(s, offsetof(CPUX86State,
3564 xmm_regs[reg].ZMM_Q(0)));
3565 } else {
3566 rm = (modrm & 7) | REX_B(s);
3567 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3568 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3569 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3571 break;
3572 case 0x2d6: /* movq2dq */
3573 gen_helper_enter_mmx(cpu_env);
3574 rm = (modrm & 7);
3575 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3576 offsetof(CPUX86State,fpregs[rm].mmx));
3577 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
3578 break;
3579 case 0x3d6: /* movdq2q */
3580 gen_helper_enter_mmx(cpu_env);
3581 rm = (modrm & 7) | REX_B(s);
3582 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3583 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3584 break;
3585 case 0xd7: /* pmovmskb */
3586 case 0x1d7:
3587 if (mod != 3)
3588 goto illegal_op;
3589 if (b1) {
3590 rm = (modrm & 7) | REX_B(s);
3591 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3592 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3593 } else {
3594 rm = (modrm & 7);
3595 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3596 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3598 reg = ((modrm >> 3) & 7) | rex_r;
3599 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3600 break;
3602 case 0x138:
3603 case 0x038:
3604 b = modrm;
3605 if ((b & 0xf0) == 0xf0) {
3606 goto do_0f_38_fx;
3608 modrm = cpu_ldub_code(env, s->pc++);
3609 rm = modrm & 7;
3610 reg = ((modrm >> 3) & 7) | rex_r;
3611 mod = (modrm >> 6) & 3;
3612 if (b1 >= 2) {
3613 goto unknown_op;
3616 sse_fn_epp = sse_op_table6[b].op[b1];
3617 if (!sse_fn_epp) {
3618 goto unknown_op;
3620 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3621 goto illegal_op;
3623 if (b1) {
3624 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3625 if (mod == 3) {
3626 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3627 } else {
3628 op2_offset = offsetof(CPUX86State,xmm_t0);
3629 gen_lea_modrm(env, s, modrm);
3630 switch (b) {
3631 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3632 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3633 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3634 gen_ldq_env_A0(s, op2_offset +
3635 offsetof(ZMMReg, ZMM_Q(0)));
3636 break;
3637 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3638 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3639 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3640 s->mem_index, MO_LEUL);
3641 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3642 offsetof(ZMMReg, ZMM_L(0)));
3643 break;
3644 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3645 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3646 s->mem_index, MO_LEUW);
3647 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3648 offsetof(ZMMReg, ZMM_W(0)));
3649 break;
3650 case 0x2a: /* movntqda */
3651 gen_ldo_env_A0(s, op1_offset);
3652 return;
3653 default:
3654 gen_ldo_env_A0(s, op2_offset);
3657 } else {
3658 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3659 if (mod == 3) {
3660 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3661 } else {
3662 op2_offset = offsetof(CPUX86State,mmx_t0);
3663 gen_lea_modrm(env, s, modrm);
3664 gen_ldq_env_A0(s, op2_offset);
3667 if (sse_fn_epp == SSE_SPECIAL) {
3668 goto unknown_op;
3671 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3672 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3673 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3675 if (b == 0x17) {
3676 set_cc_op(s, CC_OP_EFLAGS);
3678 break;
3680 case 0x238:
3681 case 0x338:
3682 do_0f_38_fx:
3683 /* Various integer extensions at 0f 38 f[0-f]. */
3684 b = modrm | (b1 << 8);
3685 modrm = cpu_ldub_code(env, s->pc++);
3686 reg = ((modrm >> 3) & 7) | rex_r;
3688 switch (b) {
3689 case 0x3f0: /* crc32 Gd,Eb */
3690 case 0x3f1: /* crc32 Gd,Ey */
3691 do_crc32:
3692 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3693 goto illegal_op;
3695 if ((b & 0xff) == 0xf0) {
3696 ot = MO_8;
3697 } else if (s->dflag != MO_64) {
3698 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3699 } else {
3700 ot = MO_64;
3703 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
3704 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3705 gen_helper_crc32(cpu_T0, cpu_tmp2_i32,
3706 cpu_T0, tcg_const_i32(8 << ot));
3708 ot = mo_64_32(s->dflag);
3709 gen_op_mov_reg_v(ot, reg, cpu_T0);
3710 break;
3712 case 0x1f0: /* crc32 or movbe */
3713 case 0x1f1:
3714 /* For these insns, the f3 prefix is supposed to have priority
3715 over the 66 prefix, but that's not what we implement above
3716 setting b1. */
3717 if (s->prefix & PREFIX_REPNZ) {
3718 goto do_crc32;
3720 /* FALLTHRU */
3721 case 0x0f0: /* movbe Gy,My */
3722 case 0x0f1: /* movbe My,Gy */
3723 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3724 goto illegal_op;
3726 if (s->dflag != MO_64) {
3727 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3728 } else {
3729 ot = MO_64;
3732 gen_lea_modrm(env, s, modrm);
3733 if ((b & 1) == 0) {
3734 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
3735 s->mem_index, ot | MO_BE);
3736 gen_op_mov_reg_v(ot, reg, cpu_T0);
3737 } else {
3738 tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
3739 s->mem_index, ot | MO_BE);
3741 break;
3743 case 0x0f2: /* andn Gy, By, Ey */
3744 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3745 || !(s->prefix & PREFIX_VEX)
3746 || s->vex_l != 0) {
3747 goto illegal_op;
3749 ot = mo_64_32(s->dflag);
3750 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3751 tcg_gen_andc_tl(cpu_T0, cpu_regs[s->vex_v], cpu_T0);
3752 gen_op_mov_reg_v(ot, reg, cpu_T0);
3753 gen_op_update1_cc();
3754 set_cc_op(s, CC_OP_LOGICB + ot);
3755 break;
3757 case 0x0f7: /* bextr Gy, Ey, By */
3758 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3759 || !(s->prefix & PREFIX_VEX)
3760 || s->vex_l != 0) {
3761 goto illegal_op;
3763 ot = mo_64_32(s->dflag);
3765 TCGv bound, zero;
3767 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3768 /* Extract START, and shift the operand.
3769 Shifts larger than operand size get zeros. */
3770 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
3771 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_A0);
3773 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3774 zero = tcg_const_tl(0);
3775 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T0, cpu_A0, bound,
3776 cpu_T0, zero);
3777 tcg_temp_free(zero);
3779 /* Extract the LEN into a mask. Lengths larger than
3780 operand size get all ones. */
3781 tcg_gen_extract_tl(cpu_A0, cpu_regs[s->vex_v], 8, 8);
3782 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
3783 cpu_A0, bound);
3784 tcg_temp_free(bound);
3785 tcg_gen_movi_tl(cpu_T1, 1);
3786 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_A0);
3787 tcg_gen_subi_tl(cpu_T1, cpu_T1, 1);
3788 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
3790 gen_op_mov_reg_v(ot, reg, cpu_T0);
3791 gen_op_update1_cc();
3792 set_cc_op(s, CC_OP_LOGICB + ot);
3794 break;
3796 case 0x0f5: /* bzhi Gy, Ey, By */
3797 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3798 || !(s->prefix & PREFIX_VEX)
3799 || s->vex_l != 0) {
3800 goto illegal_op;
3802 ot = mo_64_32(s->dflag);
3803 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3804 tcg_gen_ext8u_tl(cpu_T1, cpu_regs[s->vex_v]);
3806 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3807 /* Note that since we're using BMILG (in order to get O
3808 cleared) we need to store the inverse into C. */
3809 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3810 cpu_T1, bound);
3811 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T1, cpu_T1,
3812 bound, bound, cpu_T1);
3813 tcg_temp_free(bound);
3815 tcg_gen_movi_tl(cpu_A0, -1);
3816 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T1);
3817 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_A0);
3818 gen_op_mov_reg_v(ot, reg, cpu_T0);
3819 gen_op_update1_cc();
3820 set_cc_op(s, CC_OP_BMILGB + ot);
3821 break;
3823 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3824 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3825 || !(s->prefix & PREFIX_VEX)
3826 || s->vex_l != 0) {
3827 goto illegal_op;
3829 ot = mo_64_32(s->dflag);
3830 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3831 switch (ot) {
3832 default:
3833 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
3834 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3835 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3836 cpu_tmp2_i32, cpu_tmp3_i32);
3837 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3838 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
3839 break;
3840 #ifdef TARGET_X86_64
3841 case MO_64:
3842 tcg_gen_mulu2_i64(cpu_T0, cpu_T1,
3843 cpu_T0, cpu_regs[R_EDX]);
3844 tcg_gen_mov_i64(cpu_regs[s->vex_v], cpu_T0);
3845 tcg_gen_mov_i64(cpu_regs[reg], cpu_T1);
3846 break;
3847 #endif
3849 break;
3851 case 0x3f5: /* pdep Gy, By, Ey */
3852 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3853 || !(s->prefix & PREFIX_VEX)
3854 || s->vex_l != 0) {
3855 goto illegal_op;
3857 ot = mo_64_32(s->dflag);
3858 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3859 /* Note that by zero-extending the mask operand, we
3860 automatically handle zero-extending the result. */
3861 if (ot == MO_64) {
3862 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3863 } else {
3864 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3866 gen_helper_pdep(cpu_regs[reg], cpu_T0, cpu_T1);
3867 break;
3869 case 0x2f5: /* pext Gy, By, Ey */
3870 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3871 || !(s->prefix & PREFIX_VEX)
3872 || s->vex_l != 0) {
3873 goto illegal_op;
3875 ot = mo_64_32(s->dflag);
3876 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3877 /* Note that by zero-extending the mask operand, we
3878 automatically handle zero-extending the result. */
3879 if (ot == MO_64) {
3880 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
3881 } else {
3882 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
3884 gen_helper_pext(cpu_regs[reg], cpu_T0, cpu_T1);
3885 break;
3887 case 0x1f6: /* adcx Gy, Ey */
3888 case 0x2f6: /* adox Gy, Ey */
3889 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3890 goto illegal_op;
3891 } else {
3892 TCGv carry_in, carry_out, zero;
3893 int end_op;
3895 ot = mo_64_32(s->dflag);
3896 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3898 /* Re-use the carry-out from a previous round. */
3899 TCGV_UNUSED(carry_in);
3900 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3901 switch (s->cc_op) {
3902 case CC_OP_ADCX:
3903 if (b == 0x1f6) {
3904 carry_in = cpu_cc_dst;
3905 end_op = CC_OP_ADCX;
3906 } else {
3907 end_op = CC_OP_ADCOX;
3909 break;
3910 case CC_OP_ADOX:
3911 if (b == 0x1f6) {
3912 end_op = CC_OP_ADCOX;
3913 } else {
3914 carry_in = cpu_cc_src2;
3915 end_op = CC_OP_ADOX;
3917 break;
3918 case CC_OP_ADCOX:
3919 end_op = CC_OP_ADCOX;
3920 carry_in = carry_out;
3921 break;
3922 default:
3923 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
3924 break;
3926 /* If we can't reuse carry-out, get it out of EFLAGS. */
3927 if (TCGV_IS_UNUSED(carry_in)) {
3928 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3929 gen_compute_eflags(s);
3931 carry_in = cpu_tmp0;
3932 tcg_gen_extract_tl(carry_in, cpu_cc_src,
3933 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
3936 switch (ot) {
3937 #ifdef TARGET_X86_64
3938 case MO_32:
3939 /* If we know TL is 64-bit, and we want a 32-bit
3940 result, just do everything in 64-bit arithmetic. */
3941 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3942 tcg_gen_ext32u_i64(cpu_T0, cpu_T0);
3943 tcg_gen_add_i64(cpu_T0, cpu_T0, cpu_regs[reg]);
3944 tcg_gen_add_i64(cpu_T0, cpu_T0, carry_in);
3945 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T0);
3946 tcg_gen_shri_i64(carry_out, cpu_T0, 32);
3947 break;
3948 #endif
3949 default:
3950 /* Otherwise compute the carry-out in two steps. */
3951 zero = tcg_const_tl(0);
3952 tcg_gen_add2_tl(cpu_T0, carry_out,
3953 cpu_T0, zero,
3954 carry_in, zero);
3955 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3956 cpu_regs[reg], carry_out,
3957 cpu_T0, zero);
3958 tcg_temp_free(zero);
3959 break;
3961 set_cc_op(s, end_op);
3963 break;
3965 case 0x1f7: /* shlx Gy, Ey, By */
3966 case 0x2f7: /* sarx Gy, Ey, By */
3967 case 0x3f7: /* shrx Gy, Ey, By */
3968 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3969 || !(s->prefix & PREFIX_VEX)
3970 || s->vex_l != 0) {
3971 goto illegal_op;
3973 ot = mo_64_32(s->dflag);
3974 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3975 if (ot == MO_64) {
3976 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 63);
3977 } else {
3978 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 31);
3980 if (b == 0x1f7) {
3981 tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1);
3982 } else if (b == 0x2f7) {
3983 if (ot != MO_64) {
3984 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
3986 tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1);
3987 } else {
3988 if (ot != MO_64) {
3989 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
3991 tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1);
3993 gen_op_mov_reg_v(ot, reg, cpu_T0);
3994 break;
3996 case 0x0f3:
3997 case 0x1f3:
3998 case 0x2f3:
3999 case 0x3f3: /* Group 17 */
4000 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4001 || !(s->prefix & PREFIX_VEX)
4002 || s->vex_l != 0) {
4003 goto illegal_op;
4005 ot = mo_64_32(s->dflag);
4006 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4008 switch (reg & 7) {
4009 case 1: /* blsr By,Ey */
4010 tcg_gen_neg_tl(cpu_T1, cpu_T0);
4011 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1);
4012 gen_op_mov_reg_v(ot, s->vex_v, cpu_T0);
4013 gen_op_update2_cc();
4014 set_cc_op(s, CC_OP_BMILGB + ot);
4015 break;
4017 case 2: /* blsmsk By,Ey */
4018 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4019 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
4020 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_cc_src);
4021 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4022 set_cc_op(s, CC_OP_BMILGB + ot);
4023 break;
4025 case 3: /* blsi By, Ey */
4026 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4027 tcg_gen_subi_tl(cpu_T0, cpu_T0, 1);
4028 tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_cc_src);
4029 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4030 set_cc_op(s, CC_OP_BMILGB + ot);
4031 break;
4033 default:
4034 goto unknown_op;
4036 break;
4038 default:
4039 goto unknown_op;
4041 break;
4043 case 0x03a:
4044 case 0x13a:
4045 b = modrm;
4046 modrm = cpu_ldub_code(env, s->pc++);
4047 rm = modrm & 7;
4048 reg = ((modrm >> 3) & 7) | rex_r;
4049 mod = (modrm >> 6) & 3;
4050 if (b1 >= 2) {
4051 goto unknown_op;
4054 sse_fn_eppi = sse_op_table7[b].op[b1];
4055 if (!sse_fn_eppi) {
4056 goto unknown_op;
4058 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4059 goto illegal_op;
4061 if (sse_fn_eppi == SSE_SPECIAL) {
4062 ot = mo_64_32(s->dflag);
4063 rm = (modrm & 7) | REX_B(s);
4064 if (mod != 3)
4065 gen_lea_modrm(env, s, modrm);
4066 reg = ((modrm >> 3) & 7) | rex_r;
4067 val = cpu_ldub_code(env, s->pc++);
4068 switch (b) {
4069 case 0x14: /* pextrb */
4070 tcg_gen_ld8u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4071 xmm_regs[reg].ZMM_B(val & 15)));
4072 if (mod == 3) {
4073 gen_op_mov_reg_v(ot, rm, cpu_T0);
4074 } else {
4075 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4076 s->mem_index, MO_UB);
4078 break;
4079 case 0x15: /* pextrw */
4080 tcg_gen_ld16u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4081 xmm_regs[reg].ZMM_W(val & 7)));
4082 if (mod == 3) {
4083 gen_op_mov_reg_v(ot, rm, cpu_T0);
4084 } else {
4085 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4086 s->mem_index, MO_LEUW);
4088 break;
4089 case 0x16:
4090 if (ot == MO_32) { /* pextrd */
4091 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4092 offsetof(CPUX86State,
4093 xmm_regs[reg].ZMM_L(val & 3)));
4094 if (mod == 3) {
4095 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
4096 } else {
4097 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4098 s->mem_index, MO_LEUL);
4100 } else { /* pextrq */
4101 #ifdef TARGET_X86_64
4102 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4103 offsetof(CPUX86State,
4104 xmm_regs[reg].ZMM_Q(val & 1)));
4105 if (mod == 3) {
4106 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
4107 } else {
4108 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4109 s->mem_index, MO_LEQ);
4111 #else
4112 goto illegal_op;
4113 #endif
4115 break;
4116 case 0x17: /* extractps */
4117 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4118 xmm_regs[reg].ZMM_L(val & 3)));
4119 if (mod == 3) {
4120 gen_op_mov_reg_v(ot, rm, cpu_T0);
4121 } else {
4122 tcg_gen_qemu_st_tl(cpu_T0, cpu_A0,
4123 s->mem_index, MO_LEUL);
4125 break;
4126 case 0x20: /* pinsrb */
4127 if (mod == 3) {
4128 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
4129 } else {
4130 tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0,
4131 s->mem_index, MO_UB);
4133 tcg_gen_st8_tl(cpu_T0, cpu_env, offsetof(CPUX86State,
4134 xmm_regs[reg].ZMM_B(val & 15)));
4135 break;
4136 case 0x21: /* insertps */
4137 if (mod == 3) {
4138 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4139 offsetof(CPUX86State,xmm_regs[rm]
4140 .ZMM_L((val >> 6) & 3)));
4141 } else {
4142 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4143 s->mem_index, MO_LEUL);
4145 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4146 offsetof(CPUX86State,xmm_regs[reg]
4147 .ZMM_L((val >> 4) & 3)));
4148 if ((val >> 0) & 1)
4149 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4150 cpu_env, offsetof(CPUX86State,
4151 xmm_regs[reg].ZMM_L(0)));
4152 if ((val >> 1) & 1)
4153 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4154 cpu_env, offsetof(CPUX86State,
4155 xmm_regs[reg].ZMM_L(1)));
4156 if ((val >> 2) & 1)
4157 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4158 cpu_env, offsetof(CPUX86State,
4159 xmm_regs[reg].ZMM_L(2)));
4160 if ((val >> 3) & 1)
4161 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4162 cpu_env, offsetof(CPUX86State,
4163 xmm_regs[reg].ZMM_L(3)));
4164 break;
4165 case 0x22:
4166 if (ot == MO_32) { /* pinsrd */
4167 if (mod == 3) {
4168 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
4169 } else {
4170 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4171 s->mem_index, MO_LEUL);
4173 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4174 offsetof(CPUX86State,
4175 xmm_regs[reg].ZMM_L(val & 3)));
4176 } else { /* pinsrq */
4177 #ifdef TARGET_X86_64
4178 if (mod == 3) {
4179 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4180 } else {
4181 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4182 s->mem_index, MO_LEQ);
4184 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4185 offsetof(CPUX86State,
4186 xmm_regs[reg].ZMM_Q(val & 1)));
4187 #else
4188 goto illegal_op;
4189 #endif
4191 break;
4193 return;
4196 if (b1) {
4197 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4198 if (mod == 3) {
4199 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4200 } else {
4201 op2_offset = offsetof(CPUX86State,xmm_t0);
4202 gen_lea_modrm(env, s, modrm);
4203 gen_ldo_env_A0(s, op2_offset);
4205 } else {
4206 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4207 if (mod == 3) {
4208 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4209 } else {
4210 op2_offset = offsetof(CPUX86State,mmx_t0);
4211 gen_lea_modrm(env, s, modrm);
4212 gen_ldq_env_A0(s, op2_offset);
4215 val = cpu_ldub_code(env, s->pc++);
4217 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4218 set_cc_op(s, CC_OP_EFLAGS);
4220 if (s->dflag == MO_64) {
4221 /* The helper must use entire 64-bit gp registers */
4222 val |= 1 << 8;
4226 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4227 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4228 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4229 break;
4231 case 0x33a:
4232 /* Various integer extensions at 0f 3a f[0-f]. */
4233 b = modrm | (b1 << 8);
4234 modrm = cpu_ldub_code(env, s->pc++);
4235 reg = ((modrm >> 3) & 7) | rex_r;
4237 switch (b) {
4238 case 0x3f0: /* rorx Gy,Ey, Ib */
4239 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4240 || !(s->prefix & PREFIX_VEX)
4241 || s->vex_l != 0) {
4242 goto illegal_op;
4244 ot = mo_64_32(s->dflag);
4245 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4246 b = cpu_ldub_code(env, s->pc++);
4247 if (ot == MO_64) {
4248 tcg_gen_rotri_tl(cpu_T0, cpu_T0, b & 63);
4249 } else {
4250 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4251 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4252 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
4254 gen_op_mov_reg_v(ot, reg, cpu_T0);
4255 break;
4257 default:
4258 goto unknown_op;
4260 break;
4262 default:
4263 unknown_op:
4264 gen_unknown_opcode(env, s);
4265 return;
4267 } else {
4268 /* generic MMX or SSE operation */
4269 switch(b) {
4270 case 0x70: /* pshufx insn */
4271 case 0xc6: /* pshufx insn */
4272 case 0xc2: /* compare insns */
4273 s->rip_offset = 1;
4274 break;
4275 default:
4276 break;
4278 if (is_xmm) {
4279 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4280 if (mod != 3) {
4281 int sz = 4;
4283 gen_lea_modrm(env, s, modrm);
4284 op2_offset = offsetof(CPUX86State,xmm_t0);
4286 switch (b) {
4287 case 0x50 ... 0x5a:
4288 case 0x5c ... 0x5f:
4289 case 0xc2:
4290 /* Most sse scalar operations. */
4291 if (b1 == 2) {
4292 sz = 2;
4293 } else if (b1 == 3) {
4294 sz = 3;
4296 break;
4298 case 0x2e: /* ucomis[sd] */
4299 case 0x2f: /* comis[sd] */
4300 if (b1 == 0) {
4301 sz = 2;
4302 } else {
4303 sz = 3;
4305 break;
4308 switch (sz) {
4309 case 2:
4310 /* 32 bit access */
4311 gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0);
4312 tcg_gen_st32_tl(cpu_T0, cpu_env,
4313 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4314 break;
4315 case 3:
4316 /* 64 bit access */
4317 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4318 break;
4319 default:
4320 /* 128 bit access */
4321 gen_ldo_env_A0(s, op2_offset);
4322 break;
4324 } else {
4325 rm = (modrm & 7) | REX_B(s);
4326 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4328 } else {
4329 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4330 if (mod != 3) {
4331 gen_lea_modrm(env, s, modrm);
4332 op2_offset = offsetof(CPUX86State,mmx_t0);
4333 gen_ldq_env_A0(s, op2_offset);
4334 } else {
4335 rm = (modrm & 7);
4336 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4339 switch(b) {
4340 case 0x0f: /* 3DNow! data insns */
4341 val = cpu_ldub_code(env, s->pc++);
4342 sse_fn_epp = sse_op_table5[val];
4343 if (!sse_fn_epp) {
4344 goto unknown_op;
4346 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4347 goto illegal_op;
4349 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4350 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4351 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4352 break;
4353 case 0x70: /* pshufx insn */
4354 case 0xc6: /* pshufx insn */
4355 val = cpu_ldub_code(env, s->pc++);
4356 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4357 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4358 /* XXX: introduce a new table? */
4359 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4360 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4361 break;
4362 case 0xc2:
4363 /* compare insns */
4364 val = cpu_ldub_code(env, s->pc++);
4365 if (val >= 8)
4366 goto unknown_op;
4367 sse_fn_epp = sse_op_table4[val][b1];
4369 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4370 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4371 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4372 break;
4373 case 0xf7:
4374 /* maskmov : we must prepare A0 */
4375 if (mod != 3)
4376 goto illegal_op;
4377 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4378 gen_extu(s->aflag, cpu_A0);
4379 gen_add_A0_ds_seg(s);
4381 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4382 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4383 /* XXX: introduce a new table? */
4384 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4385 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4386 break;
4387 default:
4388 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4389 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4390 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4391 break;
4393 if (b == 0x2e || b == 0x2f) {
4394 set_cc_op(s, CC_OP_EFLAGS);
4399 /* convert one instruction. s->is_jmp is set if the translation must
4400 be stopped. Return the next pc value */
4401 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4402 target_ulong pc_start)
4404 int b, prefixes;
4405 int shift;
4406 TCGMemOp ot, aflag, dflag;
4407 int modrm, reg, rm, mod, op, opreg, val;
4408 target_ulong next_eip, tval;
4409 int rex_w, rex_r;
4411 s->pc_start = s->pc = pc_start;
4412 prefixes = 0;
4413 s->override = -1;
4414 rex_w = -1;
4415 rex_r = 0;
4416 #ifdef TARGET_X86_64
4417 s->rex_x = 0;
4418 s->rex_b = 0;
4419 x86_64_hregs = 0;
4420 #endif
4421 s->rip_offset = 0; /* for relative ip address */
4422 s->vex_l = 0;
4423 s->vex_v = 0;
4424 next_byte:
4425 b = cpu_ldub_code(env, s->pc);
4426 s->pc++;
4427 /* Collect prefixes. */
4428 switch (b) {
4429 case 0xf3:
4430 prefixes |= PREFIX_REPZ;
4431 goto next_byte;
4432 case 0xf2:
4433 prefixes |= PREFIX_REPNZ;
4434 goto next_byte;
4435 case 0xf0:
4436 prefixes |= PREFIX_LOCK;
4437 goto next_byte;
4438 case 0x2e:
4439 s->override = R_CS;
4440 goto next_byte;
4441 case 0x36:
4442 s->override = R_SS;
4443 goto next_byte;
4444 case 0x3e:
4445 s->override = R_DS;
4446 goto next_byte;
4447 case 0x26:
4448 s->override = R_ES;
4449 goto next_byte;
4450 case 0x64:
4451 s->override = R_FS;
4452 goto next_byte;
4453 case 0x65:
4454 s->override = R_GS;
4455 goto next_byte;
4456 case 0x66:
4457 prefixes |= PREFIX_DATA;
4458 goto next_byte;
4459 case 0x67:
4460 prefixes |= PREFIX_ADR;
4461 goto next_byte;
4462 #ifdef TARGET_X86_64
4463 case 0x40 ... 0x4f:
4464 if (CODE64(s)) {
4465 /* REX prefix */
4466 rex_w = (b >> 3) & 1;
4467 rex_r = (b & 0x4) << 1;
4468 s->rex_x = (b & 0x2) << 2;
4469 REX_B(s) = (b & 0x1) << 3;
4470 x86_64_hregs = 1; /* select uniform byte register addressing */
4471 goto next_byte;
4473 break;
4474 #endif
4475 case 0xc5: /* 2-byte VEX */
4476 case 0xc4: /* 3-byte VEX */
4477 /* VEX prefixes cannot be used except in 32-bit mode.
4478 Otherwise the instruction is LES or LDS. */
4479 if (s->code32 && !s->vm86) {
4480 static const int pp_prefix[4] = {
4481 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4483 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4485 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4486 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4487 otherwise the instruction is LES or LDS. */
4488 break;
4490 s->pc++;
4492 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4493 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4494 | PREFIX_LOCK | PREFIX_DATA)) {
4495 goto illegal_op;
4497 #ifdef TARGET_X86_64
4498 if (x86_64_hregs) {
4499 goto illegal_op;
4501 #endif
4502 rex_r = (~vex2 >> 4) & 8;
4503 if (b == 0xc5) {
4504 vex3 = vex2;
4505 b = cpu_ldub_code(env, s->pc++);
4506 } else {
4507 #ifdef TARGET_X86_64
4508 s->rex_x = (~vex2 >> 3) & 8;
4509 s->rex_b = (~vex2 >> 2) & 8;
4510 #endif
4511 vex3 = cpu_ldub_code(env, s->pc++);
4512 rex_w = (vex3 >> 7) & 1;
4513 switch (vex2 & 0x1f) {
4514 case 0x01: /* Implied 0f leading opcode bytes. */
4515 b = cpu_ldub_code(env, s->pc++) | 0x100;
4516 break;
4517 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4518 b = 0x138;
4519 break;
4520 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4521 b = 0x13a;
4522 break;
4523 default: /* Reserved for future use. */
4524 goto unknown_op;
4527 s->vex_v = (~vex3 >> 3) & 0xf;
4528 s->vex_l = (vex3 >> 2) & 1;
4529 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4531 break;
4534 /* Post-process prefixes. */
4535 if (CODE64(s)) {
4536 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4537 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4538 over 0x66 if both are present. */
4539 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4540 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4541 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4542 } else {
4543 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4544 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4545 dflag = MO_32;
4546 } else {
4547 dflag = MO_16;
4549 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4550 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4551 aflag = MO_32;
4552 } else {
4553 aflag = MO_16;
4557 s->prefix = prefixes;
4558 s->aflag = aflag;
4559 s->dflag = dflag;
4561 /* now check op code */
4562 reswitch:
4563 switch(b) {
4564 case 0x0f:
4565 /**************************/
4566 /* extended op code */
4567 b = cpu_ldub_code(env, s->pc++) | 0x100;
4568 goto reswitch;
4570 /**************************/
4571 /* arith & logic */
4572 case 0x00 ... 0x05:
4573 case 0x08 ... 0x0d:
4574 case 0x10 ... 0x15:
4575 case 0x18 ... 0x1d:
4576 case 0x20 ... 0x25:
4577 case 0x28 ... 0x2d:
4578 case 0x30 ... 0x35:
4579 case 0x38 ... 0x3d:
4581 int op, f, val;
4582 op = (b >> 3) & 7;
4583 f = (b >> 1) & 3;
4585 ot = mo_b_d(b, dflag);
4587 switch(f) {
4588 case 0: /* OP Ev, Gv */
4589 modrm = cpu_ldub_code(env, s->pc++);
4590 reg = ((modrm >> 3) & 7) | rex_r;
4591 mod = (modrm >> 6) & 3;
4592 rm = (modrm & 7) | REX_B(s);
4593 if (mod != 3) {
4594 gen_lea_modrm(env, s, modrm);
4595 opreg = OR_TMP0;
4596 } else if (op == OP_XORL && rm == reg) {
4597 xor_zero:
4598 /* xor reg, reg optimisation */
4599 set_cc_op(s, CC_OP_CLR);
4600 tcg_gen_movi_tl(cpu_T0, 0);
4601 gen_op_mov_reg_v(ot, reg, cpu_T0);
4602 break;
4603 } else {
4604 opreg = rm;
4606 gen_op_mov_v_reg(ot, cpu_T1, reg);
4607 gen_op(s, op, ot, opreg);
4608 break;
4609 case 1: /* OP Gv, Ev */
4610 modrm = cpu_ldub_code(env, s->pc++);
4611 mod = (modrm >> 6) & 3;
4612 reg = ((modrm >> 3) & 7) | rex_r;
4613 rm = (modrm & 7) | REX_B(s);
4614 if (mod != 3) {
4615 gen_lea_modrm(env, s, modrm);
4616 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4617 } else if (op == OP_XORL && rm == reg) {
4618 goto xor_zero;
4619 } else {
4620 gen_op_mov_v_reg(ot, cpu_T1, rm);
4622 gen_op(s, op, ot, reg);
4623 break;
4624 case 2: /* OP A, Iv */
4625 val = insn_get(env, s, ot);
4626 tcg_gen_movi_tl(cpu_T1, val);
4627 gen_op(s, op, ot, OR_EAX);
4628 break;
4631 break;
4633 case 0x82:
4634 if (CODE64(s))
4635 goto illegal_op;
4636 case 0x80: /* GRP1 */
4637 case 0x81:
4638 case 0x83:
4640 int val;
4642 ot = mo_b_d(b, dflag);
4644 modrm = cpu_ldub_code(env, s->pc++);
4645 mod = (modrm >> 6) & 3;
4646 rm = (modrm & 7) | REX_B(s);
4647 op = (modrm >> 3) & 7;
4649 if (mod != 3) {
4650 if (b == 0x83)
4651 s->rip_offset = 1;
4652 else
4653 s->rip_offset = insn_const_size(ot);
4654 gen_lea_modrm(env, s, modrm);
4655 opreg = OR_TMP0;
4656 } else {
4657 opreg = rm;
4660 switch(b) {
4661 default:
4662 case 0x80:
4663 case 0x81:
4664 case 0x82:
4665 val = insn_get(env, s, ot);
4666 break;
4667 case 0x83:
4668 val = (int8_t)insn_get(env, s, MO_8);
4669 break;
4671 tcg_gen_movi_tl(cpu_T1, val);
4672 gen_op(s, op, ot, opreg);
4674 break;
4676 /**************************/
4677 /* inc, dec, and other misc arith */
4678 case 0x40 ... 0x47: /* inc Gv */
4679 ot = dflag;
4680 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4681 break;
4682 case 0x48 ... 0x4f: /* dec Gv */
4683 ot = dflag;
4684 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4685 break;
4686 case 0xf6: /* GRP3 */
4687 case 0xf7:
4688 ot = mo_b_d(b, dflag);
4690 modrm = cpu_ldub_code(env, s->pc++);
4691 mod = (modrm >> 6) & 3;
4692 rm = (modrm & 7) | REX_B(s);
4693 op = (modrm >> 3) & 7;
4694 if (mod != 3) {
4695 if (op == 0) {
4696 s->rip_offset = insn_const_size(ot);
4698 gen_lea_modrm(env, s, modrm);
4699 /* For those below that handle locked memory, don't load here. */
4700 if (!(s->prefix & PREFIX_LOCK)
4701 || op != 2) {
4702 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4704 } else {
4705 gen_op_mov_v_reg(ot, cpu_T0, rm);
4708 switch(op) {
4709 case 0: /* test */
4710 val = insn_get(env, s, ot);
4711 tcg_gen_movi_tl(cpu_T1, val);
4712 gen_op_testl_T0_T1_cc();
4713 set_cc_op(s, CC_OP_LOGICB + ot);
4714 break;
4715 case 2: /* not */
4716 if (s->prefix & PREFIX_LOCK) {
4717 if (mod == 3) {
4718 goto illegal_op;
4720 tcg_gen_movi_tl(cpu_T0, ~0);
4721 tcg_gen_atomic_xor_fetch_tl(cpu_T0, cpu_A0, cpu_T0,
4722 s->mem_index, ot | MO_LE);
4723 } else {
4724 tcg_gen_not_tl(cpu_T0, cpu_T0);
4725 if (mod != 3) {
4726 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4727 } else {
4728 gen_op_mov_reg_v(ot, rm, cpu_T0);
4731 break;
4732 case 3: /* neg */
4733 if (s->prefix & PREFIX_LOCK) {
4734 TCGLabel *label1;
4735 TCGv a0, t0, t1, t2;
4737 if (mod == 3) {
4738 goto illegal_op;
4740 a0 = tcg_temp_local_new();
4741 t0 = tcg_temp_local_new();
4742 label1 = gen_new_label();
4744 tcg_gen_mov_tl(a0, cpu_A0);
4745 tcg_gen_mov_tl(t0, cpu_T0);
4747 gen_set_label(label1);
4748 t1 = tcg_temp_new();
4749 t2 = tcg_temp_new();
4750 tcg_gen_mov_tl(t2, t0);
4751 tcg_gen_neg_tl(t1, t0);
4752 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4753 s->mem_index, ot | MO_LE);
4754 tcg_temp_free(t1);
4755 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4757 tcg_temp_free(t2);
4758 tcg_temp_free(a0);
4759 tcg_gen_mov_tl(cpu_T0, t0);
4760 tcg_temp_free(t0);
4761 } else {
4762 tcg_gen_neg_tl(cpu_T0, cpu_T0);
4763 if (mod != 3) {
4764 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
4765 } else {
4766 gen_op_mov_reg_v(ot, rm, cpu_T0);
4769 gen_op_update_neg_cc();
4770 set_cc_op(s, CC_OP_SUBB + ot);
4771 break;
4772 case 4: /* mul */
4773 switch(ot) {
4774 case MO_8:
4775 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4776 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
4777 tcg_gen_ext8u_tl(cpu_T1, cpu_T1);
4778 /* XXX: use 32 bit mul which could be faster */
4779 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4780 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4781 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4782 tcg_gen_andi_tl(cpu_cc_src, cpu_T0, 0xff00);
4783 set_cc_op(s, CC_OP_MULB);
4784 break;
4785 case MO_16:
4786 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4787 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4788 tcg_gen_ext16u_tl(cpu_T1, cpu_T1);
4789 /* XXX: use 32 bit mul which could be faster */
4790 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4791 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4792 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4793 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4794 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4795 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
4796 set_cc_op(s, CC_OP_MULW);
4797 break;
4798 default:
4799 case MO_32:
4800 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4801 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4802 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4803 cpu_tmp2_i32, cpu_tmp3_i32);
4804 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4805 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4806 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4807 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4808 set_cc_op(s, CC_OP_MULL);
4809 break;
4810 #ifdef TARGET_X86_64
4811 case MO_64:
4812 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4813 cpu_T0, cpu_regs[R_EAX]);
4814 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4815 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4816 set_cc_op(s, CC_OP_MULQ);
4817 break;
4818 #endif
4820 break;
4821 case 5: /* imul */
4822 switch(ot) {
4823 case MO_8:
4824 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
4825 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
4826 tcg_gen_ext8s_tl(cpu_T1, cpu_T1);
4827 /* XXX: use 32 bit mul which could be faster */
4828 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4829 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4830 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4831 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T0);
4832 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4833 set_cc_op(s, CC_OP_MULB);
4834 break;
4835 case MO_16:
4836 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
4837 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
4838 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
4839 /* XXX: use 32 bit mul which could be faster */
4840 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
4841 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
4842 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
4843 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
4844 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
4845 tcg_gen_shri_tl(cpu_T0, cpu_T0, 16);
4846 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
4847 set_cc_op(s, CC_OP_MULW);
4848 break;
4849 default:
4850 case MO_32:
4851 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4852 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4853 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4854 cpu_tmp2_i32, cpu_tmp3_i32);
4855 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4856 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4857 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4858 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4859 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4860 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4861 set_cc_op(s, CC_OP_MULL);
4862 break;
4863 #ifdef TARGET_X86_64
4864 case MO_64:
4865 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4866 cpu_T0, cpu_regs[R_EAX]);
4867 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4868 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4869 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4870 set_cc_op(s, CC_OP_MULQ);
4871 break;
4872 #endif
4874 break;
4875 case 6: /* div */
4876 switch(ot) {
4877 case MO_8:
4878 gen_helper_divb_AL(cpu_env, cpu_T0);
4879 break;
4880 case MO_16:
4881 gen_helper_divw_AX(cpu_env, cpu_T0);
4882 break;
4883 default:
4884 case MO_32:
4885 gen_helper_divl_EAX(cpu_env, cpu_T0);
4886 break;
4887 #ifdef TARGET_X86_64
4888 case MO_64:
4889 gen_helper_divq_EAX(cpu_env, cpu_T0);
4890 break;
4891 #endif
4893 break;
4894 case 7: /* idiv */
4895 switch(ot) {
4896 case MO_8:
4897 gen_helper_idivb_AL(cpu_env, cpu_T0);
4898 break;
4899 case MO_16:
4900 gen_helper_idivw_AX(cpu_env, cpu_T0);
4901 break;
4902 default:
4903 case MO_32:
4904 gen_helper_idivl_EAX(cpu_env, cpu_T0);
4905 break;
4906 #ifdef TARGET_X86_64
4907 case MO_64:
4908 gen_helper_idivq_EAX(cpu_env, cpu_T0);
4909 break;
4910 #endif
4912 break;
4913 default:
4914 goto unknown_op;
4916 break;
4918 case 0xfe: /* GRP4 */
4919 case 0xff: /* GRP5 */
4920 ot = mo_b_d(b, dflag);
4922 modrm = cpu_ldub_code(env, s->pc++);
4923 mod = (modrm >> 6) & 3;
4924 rm = (modrm & 7) | REX_B(s);
4925 op = (modrm >> 3) & 7;
4926 if (op >= 2 && b == 0xfe) {
4927 goto unknown_op;
4929 if (CODE64(s)) {
4930 if (op == 2 || op == 4) {
4931 /* operand size for jumps is 64 bit */
4932 ot = MO_64;
4933 } else if (op == 3 || op == 5) {
4934 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
4935 } else if (op == 6) {
4936 /* default push size is 64 bit */
4937 ot = mo_pushpop(s, dflag);
4940 if (mod != 3) {
4941 gen_lea_modrm(env, s, modrm);
4942 if (op >= 2 && op != 3 && op != 5)
4943 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
4944 } else {
4945 gen_op_mov_v_reg(ot, cpu_T0, rm);
4948 switch(op) {
4949 case 0: /* inc Ev */
4950 if (mod != 3)
4951 opreg = OR_TMP0;
4952 else
4953 opreg = rm;
4954 gen_inc(s, ot, opreg, 1);
4955 break;
4956 case 1: /* dec Ev */
4957 if (mod != 3)
4958 opreg = OR_TMP0;
4959 else
4960 opreg = rm;
4961 gen_inc(s, ot, opreg, -1);
4962 break;
4963 case 2: /* call Ev */
4964 /* XXX: optimize if memory (no 'and' is necessary) */
4965 if (dflag == MO_16) {
4966 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4968 next_eip = s->pc - s->cs_base;
4969 tcg_gen_movi_tl(cpu_T1, next_eip);
4970 gen_push_v(s, cpu_T1);
4971 gen_op_jmp_v(cpu_T0);
4972 gen_bnd_jmp(s);
4973 gen_eob(s);
4974 break;
4975 case 3: /* lcall Ev */
4976 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
4977 gen_add_A0_im(s, 1 << ot);
4978 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
4979 do_lcall:
4980 if (s->pe && !s->vm86) {
4981 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4982 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
4983 tcg_const_i32(dflag - 1),
4984 tcg_const_tl(s->pc - s->cs_base));
4985 } else {
4986 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
4987 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T1,
4988 tcg_const_i32(dflag - 1),
4989 tcg_const_i32(s->pc - s->cs_base));
4991 gen_eob(s);
4992 break;
4993 case 4: /* jmp Ev */
4994 if (dflag == MO_16) {
4995 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
4997 gen_op_jmp_v(cpu_T0);
4998 gen_bnd_jmp(s);
4999 gen_eob(s);
5000 break;
5001 case 5: /* ljmp Ev */
5002 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5003 gen_add_A0_im(s, 1 << ot);
5004 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
5005 do_ljmp:
5006 if (s->pe && !s->vm86) {
5007 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
5008 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
5009 tcg_const_tl(s->pc - s->cs_base));
5010 } else {
5011 gen_op_movl_seg_T0_vm(R_CS);
5012 gen_op_jmp_v(cpu_T1);
5014 gen_eob(s);
5015 break;
5016 case 6: /* push Ev */
5017 gen_push_v(s, cpu_T0);
5018 break;
5019 default:
5020 goto unknown_op;
5022 break;
5024 case 0x84: /* test Ev, Gv */
5025 case 0x85:
5026 ot = mo_b_d(b, dflag);
5028 modrm = cpu_ldub_code(env, s->pc++);
5029 reg = ((modrm >> 3) & 7) | rex_r;
5031 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5032 gen_op_mov_v_reg(ot, cpu_T1, reg);
5033 gen_op_testl_T0_T1_cc();
5034 set_cc_op(s, CC_OP_LOGICB + ot);
5035 break;
5037 case 0xa8: /* test eAX, Iv */
5038 case 0xa9:
5039 ot = mo_b_d(b, dflag);
5040 val = insn_get(env, s, ot);
5042 gen_op_mov_v_reg(ot, cpu_T0, OR_EAX);
5043 tcg_gen_movi_tl(cpu_T1, val);
5044 gen_op_testl_T0_T1_cc();
5045 set_cc_op(s, CC_OP_LOGICB + ot);
5046 break;
5048 case 0x98: /* CWDE/CBW */
5049 switch (dflag) {
5050 #ifdef TARGET_X86_64
5051 case MO_64:
5052 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
5053 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
5054 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T0);
5055 break;
5056 #endif
5057 case MO_32:
5058 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
5059 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5060 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T0);
5061 break;
5062 case MO_16:
5063 gen_op_mov_v_reg(MO_8, cpu_T0, R_EAX);
5064 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
5065 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
5066 break;
5067 default:
5068 tcg_abort();
5070 break;
5071 case 0x99: /* CDQ/CWD */
5072 switch (dflag) {
5073 #ifdef TARGET_X86_64
5074 case MO_64:
5075 gen_op_mov_v_reg(MO_64, cpu_T0, R_EAX);
5076 tcg_gen_sari_tl(cpu_T0, cpu_T0, 63);
5077 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T0);
5078 break;
5079 #endif
5080 case MO_32:
5081 gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX);
5082 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
5083 tcg_gen_sari_tl(cpu_T0, cpu_T0, 31);
5084 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T0);
5085 break;
5086 case MO_16:
5087 gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX);
5088 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5089 tcg_gen_sari_tl(cpu_T0, cpu_T0, 15);
5090 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0);
5091 break;
5092 default:
5093 tcg_abort();
5095 break;
5096 case 0x1af: /* imul Gv, Ev */
5097 case 0x69: /* imul Gv, Ev, I */
5098 case 0x6b:
5099 ot = dflag;
5100 modrm = cpu_ldub_code(env, s->pc++);
5101 reg = ((modrm >> 3) & 7) | rex_r;
5102 if (b == 0x69)
5103 s->rip_offset = insn_const_size(ot);
5104 else if (b == 0x6b)
5105 s->rip_offset = 1;
5106 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5107 if (b == 0x69) {
5108 val = insn_get(env, s, ot);
5109 tcg_gen_movi_tl(cpu_T1, val);
5110 } else if (b == 0x6b) {
5111 val = (int8_t)insn_get(env, s, MO_8);
5112 tcg_gen_movi_tl(cpu_T1, val);
5113 } else {
5114 gen_op_mov_v_reg(ot, cpu_T1, reg);
5116 switch (ot) {
5117 #ifdef TARGET_X86_64
5118 case MO_64:
5119 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T1, cpu_T0, cpu_T1);
5120 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5121 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5122 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T1);
5123 break;
5124 #endif
5125 case MO_32:
5126 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
5127 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
5128 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5129 cpu_tmp2_i32, cpu_tmp3_i32);
5130 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5131 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5132 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5133 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5134 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5135 break;
5136 default:
5137 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5138 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
5139 /* XXX: use 32 bit mul which could be faster */
5140 tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1);
5141 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
5142 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0);
5143 tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0);
5144 gen_op_mov_reg_v(ot, reg, cpu_T0);
5145 break;
5147 set_cc_op(s, CC_OP_MULB + ot);
5148 break;
5149 case 0x1c0:
5150 case 0x1c1: /* xadd Ev, Gv */
5151 ot = mo_b_d(b, dflag);
5152 modrm = cpu_ldub_code(env, s->pc++);
5153 reg = ((modrm >> 3) & 7) | rex_r;
5154 mod = (modrm >> 6) & 3;
5155 gen_op_mov_v_reg(ot, cpu_T0, reg);
5156 if (mod == 3) {
5157 rm = (modrm & 7) | REX_B(s);
5158 gen_op_mov_v_reg(ot, cpu_T1, rm);
5159 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5160 gen_op_mov_reg_v(ot, reg, cpu_T1);
5161 gen_op_mov_reg_v(ot, rm, cpu_T0);
5162 } else {
5163 gen_lea_modrm(env, s, modrm);
5164 if (s->prefix & PREFIX_LOCK) {
5165 tcg_gen_atomic_fetch_add_tl(cpu_T1, cpu_A0, cpu_T0,
5166 s->mem_index, ot | MO_LE);
5167 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5168 } else {
5169 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5170 tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1);
5171 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5173 gen_op_mov_reg_v(ot, reg, cpu_T1);
5175 gen_op_update2_cc();
5176 set_cc_op(s, CC_OP_ADDB + ot);
5177 break;
5178 case 0x1b0:
5179 case 0x1b1: /* cmpxchg Ev, Gv */
5181 TCGv oldv, newv, cmpv;
5183 ot = mo_b_d(b, dflag);
5184 modrm = cpu_ldub_code(env, s->pc++);
5185 reg = ((modrm >> 3) & 7) | rex_r;
5186 mod = (modrm >> 6) & 3;
5187 oldv = tcg_temp_new();
5188 newv = tcg_temp_new();
5189 cmpv = tcg_temp_new();
5190 gen_op_mov_v_reg(ot, newv, reg);
5191 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5193 if (s->prefix & PREFIX_LOCK) {
5194 if (mod == 3) {
5195 goto illegal_op;
5197 gen_lea_modrm(env, s, modrm);
5198 tcg_gen_atomic_cmpxchg_tl(oldv, cpu_A0, cmpv, newv,
5199 s->mem_index, ot | MO_LE);
5200 gen_op_mov_reg_v(ot, R_EAX, oldv);
5201 } else {
5202 if (mod == 3) {
5203 rm = (modrm & 7) | REX_B(s);
5204 gen_op_mov_v_reg(ot, oldv, rm);
5205 } else {
5206 gen_lea_modrm(env, s, modrm);
5207 gen_op_ld_v(s, ot, oldv, cpu_A0);
5208 rm = 0; /* avoid warning */
5210 gen_extu(ot, oldv);
5211 gen_extu(ot, cmpv);
5212 /* store value = (old == cmp ? new : old); */
5213 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5214 if (mod == 3) {
5215 gen_op_mov_reg_v(ot, R_EAX, oldv);
5216 gen_op_mov_reg_v(ot, rm, newv);
5217 } else {
5218 /* Perform an unconditional store cycle like physical cpu;
5219 must be before changing accumulator to ensure
5220 idempotency if the store faults and the instruction
5221 is restarted */
5222 gen_op_st_v(s, ot, newv, cpu_A0);
5223 gen_op_mov_reg_v(ot, R_EAX, oldv);
5226 tcg_gen_mov_tl(cpu_cc_src, oldv);
5227 tcg_gen_mov_tl(cpu_cc_srcT, cmpv);
5228 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5229 set_cc_op(s, CC_OP_SUBB + ot);
5230 tcg_temp_free(oldv);
5231 tcg_temp_free(newv);
5232 tcg_temp_free(cmpv);
5234 break;
5235 case 0x1c7: /* cmpxchg8b */
5236 modrm = cpu_ldub_code(env, s->pc++);
5237 mod = (modrm >> 6) & 3;
5238 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5239 goto illegal_op;
5240 #ifdef TARGET_X86_64
5241 if (dflag == MO_64) {
5242 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5243 goto illegal_op;
5244 gen_lea_modrm(env, s, modrm);
5245 if ((s->prefix & PREFIX_LOCK) && parallel_cpus) {
5246 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5247 } else {
5248 gen_helper_cmpxchg16b_unlocked(cpu_env, cpu_A0);
5250 } else
5251 #endif
5253 if (!(s->cpuid_features & CPUID_CX8))
5254 goto illegal_op;
5255 gen_lea_modrm(env, s, modrm);
5256 if ((s->prefix & PREFIX_LOCK) && parallel_cpus) {
5257 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5258 } else {
5259 gen_helper_cmpxchg8b_unlocked(cpu_env, cpu_A0);
5262 set_cc_op(s, CC_OP_EFLAGS);
5263 break;
5265 /**************************/
5266 /* push/pop */
5267 case 0x50 ... 0x57: /* push */
5268 gen_op_mov_v_reg(MO_32, cpu_T0, (b & 7) | REX_B(s));
5269 gen_push_v(s, cpu_T0);
5270 break;
5271 case 0x58 ... 0x5f: /* pop */
5272 ot = gen_pop_T0(s);
5273 /* NOTE: order is important for pop %sp */
5274 gen_pop_update(s, ot);
5275 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T0);
5276 break;
5277 case 0x60: /* pusha */
5278 if (CODE64(s))
5279 goto illegal_op;
5280 gen_pusha(s);
5281 break;
5282 case 0x61: /* popa */
5283 if (CODE64(s))
5284 goto illegal_op;
5285 gen_popa(s);
5286 break;
5287 case 0x68: /* push Iv */
5288 case 0x6a:
5289 ot = mo_pushpop(s, dflag);
5290 if (b == 0x68)
5291 val = insn_get(env, s, ot);
5292 else
5293 val = (int8_t)insn_get(env, s, MO_8);
5294 tcg_gen_movi_tl(cpu_T0, val);
5295 gen_push_v(s, cpu_T0);
5296 break;
5297 case 0x8f: /* pop Ev */
5298 modrm = cpu_ldub_code(env, s->pc++);
5299 mod = (modrm >> 6) & 3;
5300 ot = gen_pop_T0(s);
5301 if (mod == 3) {
5302 /* NOTE: order is important for pop %sp */
5303 gen_pop_update(s, ot);
5304 rm = (modrm & 7) | REX_B(s);
5305 gen_op_mov_reg_v(ot, rm, cpu_T0);
5306 } else {
5307 /* NOTE: order is important too for MMU exceptions */
5308 s->popl_esp_hack = 1 << ot;
5309 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5310 s->popl_esp_hack = 0;
5311 gen_pop_update(s, ot);
5313 break;
5314 case 0xc8: /* enter */
5316 int level;
5317 val = cpu_lduw_code(env, s->pc);
5318 s->pc += 2;
5319 level = cpu_ldub_code(env, s->pc++);
5320 gen_enter(s, val, level);
5322 break;
5323 case 0xc9: /* leave */
5324 gen_leave(s);
5325 break;
5326 case 0x06: /* push es */
5327 case 0x0e: /* push cs */
5328 case 0x16: /* push ss */
5329 case 0x1e: /* push ds */
5330 if (CODE64(s))
5331 goto illegal_op;
5332 gen_op_movl_T0_seg(b >> 3);
5333 gen_push_v(s, cpu_T0);
5334 break;
5335 case 0x1a0: /* push fs */
5336 case 0x1a8: /* push gs */
5337 gen_op_movl_T0_seg((b >> 3) & 7);
5338 gen_push_v(s, cpu_T0);
5339 break;
5340 case 0x07: /* pop es */
5341 case 0x17: /* pop ss */
5342 case 0x1f: /* pop ds */
5343 if (CODE64(s))
5344 goto illegal_op;
5345 reg = b >> 3;
5346 ot = gen_pop_T0(s);
5347 gen_movl_seg_T0(s, reg);
5348 gen_pop_update(s, ot);
5349 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5350 if (s->is_jmp) {
5351 gen_jmp_im(s->pc - s->cs_base);
5352 if (reg == R_SS) {
5353 s->tf = 0;
5354 gen_eob_inhibit_irq(s, true);
5355 } else {
5356 gen_eob(s);
5359 break;
5360 case 0x1a1: /* pop fs */
5361 case 0x1a9: /* pop gs */
5362 ot = gen_pop_T0(s);
5363 gen_movl_seg_T0(s, (b >> 3) & 7);
5364 gen_pop_update(s, ot);
5365 if (s->is_jmp) {
5366 gen_jmp_im(s->pc - s->cs_base);
5367 gen_eob(s);
5369 break;
5371 /**************************/
5372 /* mov */
5373 case 0x88:
5374 case 0x89: /* mov Gv, Ev */
5375 ot = mo_b_d(b, dflag);
5376 modrm = cpu_ldub_code(env, s->pc++);
5377 reg = ((modrm >> 3) & 7) | rex_r;
5379 /* generate a generic store */
5380 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5381 break;
5382 case 0xc6:
5383 case 0xc7: /* mov Ev, Iv */
5384 ot = mo_b_d(b, dflag);
5385 modrm = cpu_ldub_code(env, s->pc++);
5386 mod = (modrm >> 6) & 3;
5387 if (mod != 3) {
5388 s->rip_offset = insn_const_size(ot);
5389 gen_lea_modrm(env, s, modrm);
5391 val = insn_get(env, s, ot);
5392 tcg_gen_movi_tl(cpu_T0, val);
5393 if (mod != 3) {
5394 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5395 } else {
5396 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T0);
5398 break;
5399 case 0x8a:
5400 case 0x8b: /* mov Ev, Gv */
5401 ot = mo_b_d(b, dflag);
5402 modrm = cpu_ldub_code(env, s->pc++);
5403 reg = ((modrm >> 3) & 7) | rex_r;
5405 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5406 gen_op_mov_reg_v(ot, reg, cpu_T0);
5407 break;
5408 case 0x8e: /* mov seg, Gv */
5409 modrm = cpu_ldub_code(env, s->pc++);
5410 reg = (modrm >> 3) & 7;
5411 if (reg >= 6 || reg == R_CS)
5412 goto illegal_op;
5413 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5414 gen_movl_seg_T0(s, reg);
5415 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5416 if (s->is_jmp) {
5417 gen_jmp_im(s->pc - s->cs_base);
5418 if (reg == R_SS) {
5419 s->tf = 0;
5420 gen_eob_inhibit_irq(s, true);
5421 } else {
5422 gen_eob(s);
5425 break;
5426 case 0x8c: /* mov Gv, seg */
5427 modrm = cpu_ldub_code(env, s->pc++);
5428 reg = (modrm >> 3) & 7;
5429 mod = (modrm >> 6) & 3;
5430 if (reg >= 6)
5431 goto illegal_op;
5432 gen_op_movl_T0_seg(reg);
5433 ot = mod == 3 ? dflag : MO_16;
5434 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5435 break;
5437 case 0x1b6: /* movzbS Gv, Eb */
5438 case 0x1b7: /* movzwS Gv, Eb */
5439 case 0x1be: /* movsbS Gv, Eb */
5440 case 0x1bf: /* movswS Gv, Eb */
5442 TCGMemOp d_ot;
5443 TCGMemOp s_ot;
5445 /* d_ot is the size of destination */
5446 d_ot = dflag;
5447 /* ot is the size of source */
5448 ot = (b & 1) + MO_8;
5449 /* s_ot is the sign+size of source */
5450 s_ot = b & 8 ? MO_SIGN | ot : ot;
5452 modrm = cpu_ldub_code(env, s->pc++);
5453 reg = ((modrm >> 3) & 7) | rex_r;
5454 mod = (modrm >> 6) & 3;
5455 rm = (modrm & 7) | REX_B(s);
5457 if (mod == 3) {
5458 if (s_ot == MO_SB && byte_reg_is_xH(rm)) {
5459 tcg_gen_sextract_tl(cpu_T0, cpu_regs[rm - 4], 8, 8);
5460 } else {
5461 gen_op_mov_v_reg(ot, cpu_T0, rm);
5462 switch (s_ot) {
5463 case MO_UB:
5464 tcg_gen_ext8u_tl(cpu_T0, cpu_T0);
5465 break;
5466 case MO_SB:
5467 tcg_gen_ext8s_tl(cpu_T0, cpu_T0);
5468 break;
5469 case MO_UW:
5470 tcg_gen_ext16u_tl(cpu_T0, cpu_T0);
5471 break;
5472 default:
5473 case MO_SW:
5474 tcg_gen_ext16s_tl(cpu_T0, cpu_T0);
5475 break;
5478 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5479 } else {
5480 gen_lea_modrm(env, s, modrm);
5481 gen_op_ld_v(s, s_ot, cpu_T0, cpu_A0);
5482 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
5485 break;
5487 case 0x8d: /* lea */
5488 modrm = cpu_ldub_code(env, s->pc++);
5489 mod = (modrm >> 6) & 3;
5490 if (mod == 3)
5491 goto illegal_op;
5492 reg = ((modrm >> 3) & 7) | rex_r;
5494 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5495 TCGv ea = gen_lea_modrm_1(a);
5496 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5497 gen_op_mov_reg_v(dflag, reg, cpu_A0);
5499 break;
5501 case 0xa0: /* mov EAX, Ov */
5502 case 0xa1:
5503 case 0xa2: /* mov Ov, EAX */
5504 case 0xa3:
5506 target_ulong offset_addr;
5508 ot = mo_b_d(b, dflag);
5509 switch (s->aflag) {
5510 #ifdef TARGET_X86_64
5511 case MO_64:
5512 offset_addr = cpu_ldq_code(env, s->pc);
5513 s->pc += 8;
5514 break;
5515 #endif
5516 default:
5517 offset_addr = insn_get(env, s, s->aflag);
5518 break;
5520 tcg_gen_movi_tl(cpu_A0, offset_addr);
5521 gen_add_A0_ds_seg(s);
5522 if ((b & 2) == 0) {
5523 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
5524 gen_op_mov_reg_v(ot, R_EAX, cpu_T0);
5525 } else {
5526 gen_op_mov_v_reg(ot, cpu_T0, R_EAX);
5527 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
5530 break;
5531 case 0xd7: /* xlat */
5532 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5533 tcg_gen_ext8u_tl(cpu_T0, cpu_regs[R_EAX]);
5534 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T0);
5535 gen_extu(s->aflag, cpu_A0);
5536 gen_add_A0_ds_seg(s);
5537 gen_op_ld_v(s, MO_8, cpu_T0, cpu_A0);
5538 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
5539 break;
5540 case 0xb0 ... 0xb7: /* mov R, Ib */
5541 val = insn_get(env, s, MO_8);
5542 tcg_gen_movi_tl(cpu_T0, val);
5543 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T0);
5544 break;
5545 case 0xb8 ... 0xbf: /* mov R, Iv */
5546 #ifdef TARGET_X86_64
5547 if (dflag == MO_64) {
5548 uint64_t tmp;
5549 /* 64 bit case */
5550 tmp = cpu_ldq_code(env, s->pc);
5551 s->pc += 8;
5552 reg = (b & 7) | REX_B(s);
5553 tcg_gen_movi_tl(cpu_T0, tmp);
5554 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
5555 } else
5556 #endif
5558 ot = dflag;
5559 val = insn_get(env, s, ot);
5560 reg = (b & 7) | REX_B(s);
5561 tcg_gen_movi_tl(cpu_T0, val);
5562 gen_op_mov_reg_v(ot, reg, cpu_T0);
5564 break;
5566 case 0x91 ... 0x97: /* xchg R, EAX */
5567 do_xchg_reg_eax:
5568 ot = dflag;
5569 reg = (b & 7) | REX_B(s);
5570 rm = R_EAX;
5571 goto do_xchg_reg;
5572 case 0x86:
5573 case 0x87: /* xchg Ev, Gv */
5574 ot = mo_b_d(b, dflag);
5575 modrm = cpu_ldub_code(env, s->pc++);
5576 reg = ((modrm >> 3) & 7) | rex_r;
5577 mod = (modrm >> 6) & 3;
5578 if (mod == 3) {
5579 rm = (modrm & 7) | REX_B(s);
5580 do_xchg_reg:
5581 gen_op_mov_v_reg(ot, cpu_T0, reg);
5582 gen_op_mov_v_reg(ot, cpu_T1, rm);
5583 gen_op_mov_reg_v(ot, rm, cpu_T0);
5584 gen_op_mov_reg_v(ot, reg, cpu_T1);
5585 } else {
5586 gen_lea_modrm(env, s, modrm);
5587 gen_op_mov_v_reg(ot, cpu_T0, reg);
5588 /* for xchg, lock is implicit */
5589 tcg_gen_atomic_xchg_tl(cpu_T1, cpu_A0, cpu_T0,
5590 s->mem_index, ot | MO_LE);
5591 gen_op_mov_reg_v(ot, reg, cpu_T1);
5593 break;
5594 case 0xc4: /* les Gv */
5595 /* In CODE64 this is VEX3; see above. */
5596 op = R_ES;
5597 goto do_lxx;
5598 case 0xc5: /* lds Gv */
5599 /* In CODE64 this is VEX2; see above. */
5600 op = R_DS;
5601 goto do_lxx;
5602 case 0x1b2: /* lss Gv */
5603 op = R_SS;
5604 goto do_lxx;
5605 case 0x1b4: /* lfs Gv */
5606 op = R_FS;
5607 goto do_lxx;
5608 case 0x1b5: /* lgs Gv */
5609 op = R_GS;
5610 do_lxx:
5611 ot = dflag != MO_16 ? MO_32 : MO_16;
5612 modrm = cpu_ldub_code(env, s->pc++);
5613 reg = ((modrm >> 3) & 7) | rex_r;
5614 mod = (modrm >> 6) & 3;
5615 if (mod == 3)
5616 goto illegal_op;
5617 gen_lea_modrm(env, s, modrm);
5618 gen_op_ld_v(s, ot, cpu_T1, cpu_A0);
5619 gen_add_A0_im(s, 1 << ot);
5620 /* load the segment first to handle exceptions properly */
5621 gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0);
5622 gen_movl_seg_T0(s, op);
5623 /* then put the data */
5624 gen_op_mov_reg_v(ot, reg, cpu_T1);
5625 if (s->is_jmp) {
5626 gen_jmp_im(s->pc - s->cs_base);
5627 gen_eob(s);
5629 break;
5631 /************************/
5632 /* shifts */
5633 case 0xc0:
5634 case 0xc1:
5635 /* shift Ev,Ib */
5636 shift = 2;
5637 grp2:
5639 ot = mo_b_d(b, dflag);
5640 modrm = cpu_ldub_code(env, s->pc++);
5641 mod = (modrm >> 6) & 3;
5642 op = (modrm >> 3) & 7;
5644 if (mod != 3) {
5645 if (shift == 2) {
5646 s->rip_offset = 1;
5648 gen_lea_modrm(env, s, modrm);
5649 opreg = OR_TMP0;
5650 } else {
5651 opreg = (modrm & 7) | REX_B(s);
5654 /* simpler op */
5655 if (shift == 0) {
5656 gen_shift(s, op, ot, opreg, OR_ECX);
5657 } else {
5658 if (shift == 2) {
5659 shift = cpu_ldub_code(env, s->pc++);
5661 gen_shifti(s, op, ot, opreg, shift);
5664 break;
5665 case 0xd0:
5666 case 0xd1:
5667 /* shift Ev,1 */
5668 shift = 1;
5669 goto grp2;
5670 case 0xd2:
5671 case 0xd3:
5672 /* shift Ev,cl */
5673 shift = 0;
5674 goto grp2;
5676 case 0x1a4: /* shld imm */
5677 op = 0;
5678 shift = 1;
5679 goto do_shiftd;
5680 case 0x1a5: /* shld cl */
5681 op = 0;
5682 shift = 0;
5683 goto do_shiftd;
5684 case 0x1ac: /* shrd imm */
5685 op = 1;
5686 shift = 1;
5687 goto do_shiftd;
5688 case 0x1ad: /* shrd cl */
5689 op = 1;
5690 shift = 0;
5691 do_shiftd:
5692 ot = dflag;
5693 modrm = cpu_ldub_code(env, s->pc++);
5694 mod = (modrm >> 6) & 3;
5695 rm = (modrm & 7) | REX_B(s);
5696 reg = ((modrm >> 3) & 7) | rex_r;
5697 if (mod != 3) {
5698 gen_lea_modrm(env, s, modrm);
5699 opreg = OR_TMP0;
5700 } else {
5701 opreg = rm;
5703 gen_op_mov_v_reg(ot, cpu_T1, reg);
5705 if (shift) {
5706 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5707 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5708 tcg_temp_free(imm);
5709 } else {
5710 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5712 break;
5714 /************************/
5715 /* floats */
5716 case 0xd8 ... 0xdf:
5717 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5718 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5719 /* XXX: what to do if illegal op ? */
5720 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5721 break;
5723 modrm = cpu_ldub_code(env, s->pc++);
5724 mod = (modrm >> 6) & 3;
5725 rm = modrm & 7;
5726 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5727 if (mod != 3) {
5728 /* memory op */
5729 gen_lea_modrm(env, s, modrm);
5730 switch(op) {
5731 case 0x00 ... 0x07: /* fxxxs */
5732 case 0x10 ... 0x17: /* fixxxl */
5733 case 0x20 ... 0x27: /* fxxxl */
5734 case 0x30 ... 0x37: /* fixxx */
5736 int op1;
5737 op1 = op & 7;
5739 switch(op >> 4) {
5740 case 0:
5741 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5742 s->mem_index, MO_LEUL);
5743 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5744 break;
5745 case 1:
5746 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5747 s->mem_index, MO_LEUL);
5748 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5749 break;
5750 case 2:
5751 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5752 s->mem_index, MO_LEQ);
5753 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5754 break;
5755 case 3:
5756 default:
5757 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5758 s->mem_index, MO_LESW);
5759 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5760 break;
5763 gen_helper_fp_arith_ST0_FT0(op1);
5764 if (op1 == 3) {
5765 /* fcomp needs pop */
5766 gen_helper_fpop(cpu_env);
5769 break;
5770 case 0x08: /* flds */
5771 case 0x0a: /* fsts */
5772 case 0x0b: /* fstps */
5773 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5774 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5775 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5776 switch(op & 7) {
5777 case 0:
5778 switch(op >> 4) {
5779 case 0:
5780 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5781 s->mem_index, MO_LEUL);
5782 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5783 break;
5784 case 1:
5785 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5786 s->mem_index, MO_LEUL);
5787 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5788 break;
5789 case 2:
5790 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5791 s->mem_index, MO_LEQ);
5792 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5793 break;
5794 case 3:
5795 default:
5796 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5797 s->mem_index, MO_LESW);
5798 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5799 break;
5801 break;
5802 case 1:
5803 /* XXX: the corresponding CPUID bit must be tested ! */
5804 switch(op >> 4) {
5805 case 1:
5806 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5807 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5808 s->mem_index, MO_LEUL);
5809 break;
5810 case 2:
5811 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5812 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5813 s->mem_index, MO_LEQ);
5814 break;
5815 case 3:
5816 default:
5817 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5818 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5819 s->mem_index, MO_LEUW);
5820 break;
5822 gen_helper_fpop(cpu_env);
5823 break;
5824 default:
5825 switch(op >> 4) {
5826 case 0:
5827 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5828 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5829 s->mem_index, MO_LEUL);
5830 break;
5831 case 1:
5832 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5833 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5834 s->mem_index, MO_LEUL);
5835 break;
5836 case 2:
5837 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5838 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5839 s->mem_index, MO_LEQ);
5840 break;
5841 case 3:
5842 default:
5843 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5844 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5845 s->mem_index, MO_LEUW);
5846 break;
5848 if ((op & 7) == 3)
5849 gen_helper_fpop(cpu_env);
5850 break;
5852 break;
5853 case 0x0c: /* fldenv mem */
5854 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5855 break;
5856 case 0x0d: /* fldcw mem */
5857 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5858 s->mem_index, MO_LEUW);
5859 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5860 break;
5861 case 0x0e: /* fnstenv mem */
5862 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5863 break;
5864 case 0x0f: /* fnstcw mem */
5865 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5866 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5867 s->mem_index, MO_LEUW);
5868 break;
5869 case 0x1d: /* fldt mem */
5870 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5871 break;
5872 case 0x1f: /* fstpt mem */
5873 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5874 gen_helper_fpop(cpu_env);
5875 break;
5876 case 0x2c: /* frstor mem */
5877 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5878 break;
5879 case 0x2e: /* fnsave mem */
5880 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5881 break;
5882 case 0x2f: /* fnstsw mem */
5883 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5884 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5885 s->mem_index, MO_LEUW);
5886 break;
5887 case 0x3c: /* fbld */
5888 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5889 break;
5890 case 0x3e: /* fbstp */
5891 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5892 gen_helper_fpop(cpu_env);
5893 break;
5894 case 0x3d: /* fildll */
5895 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5896 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5897 break;
5898 case 0x3f: /* fistpll */
5899 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5900 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5901 gen_helper_fpop(cpu_env);
5902 break;
5903 default:
5904 goto unknown_op;
5906 } else {
5907 /* register float ops */
5908 opreg = rm;
5910 switch(op) {
5911 case 0x08: /* fld sti */
5912 gen_helper_fpush(cpu_env);
5913 gen_helper_fmov_ST0_STN(cpu_env,
5914 tcg_const_i32((opreg + 1) & 7));
5915 break;
5916 case 0x09: /* fxchg sti */
5917 case 0x29: /* fxchg4 sti, undocumented op */
5918 case 0x39: /* fxchg7 sti, undocumented op */
5919 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5920 break;
5921 case 0x0a: /* grp d9/2 */
5922 switch(rm) {
5923 case 0: /* fnop */
5924 /* check exceptions (FreeBSD FPU probe) */
5925 gen_helper_fwait(cpu_env);
5926 break;
5927 default:
5928 goto unknown_op;
5930 break;
5931 case 0x0c: /* grp d9/4 */
5932 switch(rm) {
5933 case 0: /* fchs */
5934 gen_helper_fchs_ST0(cpu_env);
5935 break;
5936 case 1: /* fabs */
5937 gen_helper_fabs_ST0(cpu_env);
5938 break;
5939 case 4: /* ftst */
5940 gen_helper_fldz_FT0(cpu_env);
5941 gen_helper_fcom_ST0_FT0(cpu_env);
5942 break;
5943 case 5: /* fxam */
5944 gen_helper_fxam_ST0(cpu_env);
5945 break;
5946 default:
5947 goto unknown_op;
5949 break;
5950 case 0x0d: /* grp d9/5 */
5952 switch(rm) {
5953 case 0:
5954 gen_helper_fpush(cpu_env);
5955 gen_helper_fld1_ST0(cpu_env);
5956 break;
5957 case 1:
5958 gen_helper_fpush(cpu_env);
5959 gen_helper_fldl2t_ST0(cpu_env);
5960 break;
5961 case 2:
5962 gen_helper_fpush(cpu_env);
5963 gen_helper_fldl2e_ST0(cpu_env);
5964 break;
5965 case 3:
5966 gen_helper_fpush(cpu_env);
5967 gen_helper_fldpi_ST0(cpu_env);
5968 break;
5969 case 4:
5970 gen_helper_fpush(cpu_env);
5971 gen_helper_fldlg2_ST0(cpu_env);
5972 break;
5973 case 5:
5974 gen_helper_fpush(cpu_env);
5975 gen_helper_fldln2_ST0(cpu_env);
5976 break;
5977 case 6:
5978 gen_helper_fpush(cpu_env);
5979 gen_helper_fldz_ST0(cpu_env);
5980 break;
5981 default:
5982 goto unknown_op;
5985 break;
5986 case 0x0e: /* grp d9/6 */
5987 switch(rm) {
5988 case 0: /* f2xm1 */
5989 gen_helper_f2xm1(cpu_env);
5990 break;
5991 case 1: /* fyl2x */
5992 gen_helper_fyl2x(cpu_env);
5993 break;
5994 case 2: /* fptan */
5995 gen_helper_fptan(cpu_env);
5996 break;
5997 case 3: /* fpatan */
5998 gen_helper_fpatan(cpu_env);
5999 break;
6000 case 4: /* fxtract */
6001 gen_helper_fxtract(cpu_env);
6002 break;
6003 case 5: /* fprem1 */
6004 gen_helper_fprem1(cpu_env);
6005 break;
6006 case 6: /* fdecstp */
6007 gen_helper_fdecstp(cpu_env);
6008 break;
6009 default:
6010 case 7: /* fincstp */
6011 gen_helper_fincstp(cpu_env);
6012 break;
6014 break;
6015 case 0x0f: /* grp d9/7 */
6016 switch(rm) {
6017 case 0: /* fprem */
6018 gen_helper_fprem(cpu_env);
6019 break;
6020 case 1: /* fyl2xp1 */
6021 gen_helper_fyl2xp1(cpu_env);
6022 break;
6023 case 2: /* fsqrt */
6024 gen_helper_fsqrt(cpu_env);
6025 break;
6026 case 3: /* fsincos */
6027 gen_helper_fsincos(cpu_env);
6028 break;
6029 case 5: /* fscale */
6030 gen_helper_fscale(cpu_env);
6031 break;
6032 case 4: /* frndint */
6033 gen_helper_frndint(cpu_env);
6034 break;
6035 case 6: /* fsin */
6036 gen_helper_fsin(cpu_env);
6037 break;
6038 default:
6039 case 7: /* fcos */
6040 gen_helper_fcos(cpu_env);
6041 break;
6043 break;
6044 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6045 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6046 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6048 int op1;
6050 op1 = op & 7;
6051 if (op >= 0x20) {
6052 gen_helper_fp_arith_STN_ST0(op1, opreg);
6053 if (op >= 0x30)
6054 gen_helper_fpop(cpu_env);
6055 } else {
6056 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6057 gen_helper_fp_arith_ST0_FT0(op1);
6060 break;
6061 case 0x02: /* fcom */
6062 case 0x22: /* fcom2, undocumented op */
6063 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6064 gen_helper_fcom_ST0_FT0(cpu_env);
6065 break;
6066 case 0x03: /* fcomp */
6067 case 0x23: /* fcomp3, undocumented op */
6068 case 0x32: /* fcomp5, undocumented op */
6069 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6070 gen_helper_fcom_ST0_FT0(cpu_env);
6071 gen_helper_fpop(cpu_env);
6072 break;
6073 case 0x15: /* da/5 */
6074 switch(rm) {
6075 case 1: /* fucompp */
6076 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6077 gen_helper_fucom_ST0_FT0(cpu_env);
6078 gen_helper_fpop(cpu_env);
6079 gen_helper_fpop(cpu_env);
6080 break;
6081 default:
6082 goto unknown_op;
6084 break;
6085 case 0x1c:
6086 switch(rm) {
6087 case 0: /* feni (287 only, just do nop here) */
6088 break;
6089 case 1: /* fdisi (287 only, just do nop here) */
6090 break;
6091 case 2: /* fclex */
6092 gen_helper_fclex(cpu_env);
6093 break;
6094 case 3: /* fninit */
6095 gen_helper_fninit(cpu_env);
6096 break;
6097 case 4: /* fsetpm (287 only, just do nop here) */
6098 break;
6099 default:
6100 goto unknown_op;
6102 break;
6103 case 0x1d: /* fucomi */
6104 if (!(s->cpuid_features & CPUID_CMOV)) {
6105 goto illegal_op;
6107 gen_update_cc_op(s);
6108 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6109 gen_helper_fucomi_ST0_FT0(cpu_env);
6110 set_cc_op(s, CC_OP_EFLAGS);
6111 break;
6112 case 0x1e: /* fcomi */
6113 if (!(s->cpuid_features & CPUID_CMOV)) {
6114 goto illegal_op;
6116 gen_update_cc_op(s);
6117 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6118 gen_helper_fcomi_ST0_FT0(cpu_env);
6119 set_cc_op(s, CC_OP_EFLAGS);
6120 break;
6121 case 0x28: /* ffree sti */
6122 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6123 break;
6124 case 0x2a: /* fst sti */
6125 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6126 break;
6127 case 0x2b: /* fstp sti */
6128 case 0x0b: /* fstp1 sti, undocumented op */
6129 case 0x3a: /* fstp8 sti, undocumented op */
6130 case 0x3b: /* fstp9 sti, undocumented op */
6131 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6132 gen_helper_fpop(cpu_env);
6133 break;
6134 case 0x2c: /* fucom st(i) */
6135 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6136 gen_helper_fucom_ST0_FT0(cpu_env);
6137 break;
6138 case 0x2d: /* fucomp st(i) */
6139 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6140 gen_helper_fucom_ST0_FT0(cpu_env);
6141 gen_helper_fpop(cpu_env);
6142 break;
6143 case 0x33: /* de/3 */
6144 switch(rm) {
6145 case 1: /* fcompp */
6146 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6147 gen_helper_fcom_ST0_FT0(cpu_env);
6148 gen_helper_fpop(cpu_env);
6149 gen_helper_fpop(cpu_env);
6150 break;
6151 default:
6152 goto unknown_op;
6154 break;
6155 case 0x38: /* ffreep sti, undocumented op */
6156 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6157 gen_helper_fpop(cpu_env);
6158 break;
6159 case 0x3c: /* df/4 */
6160 switch(rm) {
6161 case 0:
6162 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6163 tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32);
6164 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0);
6165 break;
6166 default:
6167 goto unknown_op;
6169 break;
6170 case 0x3d: /* fucomip */
6171 if (!(s->cpuid_features & CPUID_CMOV)) {
6172 goto illegal_op;
6174 gen_update_cc_op(s);
6175 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6176 gen_helper_fucomi_ST0_FT0(cpu_env);
6177 gen_helper_fpop(cpu_env);
6178 set_cc_op(s, CC_OP_EFLAGS);
6179 break;
6180 case 0x3e: /* fcomip */
6181 if (!(s->cpuid_features & CPUID_CMOV)) {
6182 goto illegal_op;
6184 gen_update_cc_op(s);
6185 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6186 gen_helper_fcomi_ST0_FT0(cpu_env);
6187 gen_helper_fpop(cpu_env);
6188 set_cc_op(s, CC_OP_EFLAGS);
6189 break;
6190 case 0x10 ... 0x13: /* fcmovxx */
6191 case 0x18 ... 0x1b:
6193 int op1;
6194 TCGLabel *l1;
6195 static const uint8_t fcmov_cc[8] = {
6196 (JCC_B << 1),
6197 (JCC_Z << 1),
6198 (JCC_BE << 1),
6199 (JCC_P << 1),
6202 if (!(s->cpuid_features & CPUID_CMOV)) {
6203 goto illegal_op;
6205 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6206 l1 = gen_new_label();
6207 gen_jcc1_noeob(s, op1, l1);
6208 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6209 gen_set_label(l1);
6211 break;
6212 default:
6213 goto unknown_op;
6216 break;
6217 /************************/
6218 /* string ops */
6220 case 0xa4: /* movsS */
6221 case 0xa5:
6222 ot = mo_b_d(b, dflag);
6223 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6224 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6225 } else {
6226 gen_movs(s, ot);
6228 break;
6230 case 0xaa: /* stosS */
6231 case 0xab:
6232 ot = mo_b_d(b, dflag);
6233 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6234 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6235 } else {
6236 gen_stos(s, ot);
6238 break;
6239 case 0xac: /* lodsS */
6240 case 0xad:
6241 ot = mo_b_d(b, dflag);
6242 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6243 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6244 } else {
6245 gen_lods(s, ot);
6247 break;
6248 case 0xae: /* scasS */
6249 case 0xaf:
6250 ot = mo_b_d(b, dflag);
6251 if (prefixes & PREFIX_REPNZ) {
6252 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6253 } else if (prefixes & PREFIX_REPZ) {
6254 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6255 } else {
6256 gen_scas(s, ot);
6258 break;
6260 case 0xa6: /* cmpsS */
6261 case 0xa7:
6262 ot = mo_b_d(b, dflag);
6263 if (prefixes & PREFIX_REPNZ) {
6264 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6265 } else if (prefixes & PREFIX_REPZ) {
6266 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6267 } else {
6268 gen_cmps(s, ot);
6270 break;
6271 case 0x6c: /* insS */
6272 case 0x6d:
6273 ot = mo_b_d32(b, dflag);
6274 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6275 gen_check_io(s, ot, pc_start - s->cs_base,
6276 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6277 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6278 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6279 } else {
6280 gen_ins(s, ot);
6281 if (s->tb->cflags & CF_USE_ICOUNT) {
6282 gen_jmp(s, s->pc - s->cs_base);
6285 break;
6286 case 0x6e: /* outsS */
6287 case 0x6f:
6288 ot = mo_b_d32(b, dflag);
6289 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6290 gen_check_io(s, ot, pc_start - s->cs_base,
6291 svm_is_rep(prefixes) | 4);
6292 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6293 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6294 } else {
6295 gen_outs(s, ot);
6296 if (s->tb->cflags & CF_USE_ICOUNT) {
6297 gen_jmp(s, s->pc - s->cs_base);
6300 break;
6302 /************************/
6303 /* port I/O */
6305 case 0xe4:
6306 case 0xe5:
6307 ot = mo_b_d32(b, dflag);
6308 val = cpu_ldub_code(env, s->pc++);
6309 tcg_gen_movi_tl(cpu_T0, val);
6310 gen_check_io(s, ot, pc_start - s->cs_base,
6311 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6312 if (s->tb->cflags & CF_USE_ICOUNT) {
6313 gen_io_start();
6315 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6316 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6317 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6318 gen_bpt_io(s, cpu_tmp2_i32, ot);
6319 if (s->tb->cflags & CF_USE_ICOUNT) {
6320 gen_io_end();
6321 gen_jmp(s, s->pc - s->cs_base);
6323 break;
6324 case 0xe6:
6325 case 0xe7:
6326 ot = mo_b_d32(b, dflag);
6327 val = cpu_ldub_code(env, s->pc++);
6328 tcg_gen_movi_tl(cpu_T0, val);
6329 gen_check_io(s, ot, pc_start - s->cs_base,
6330 svm_is_rep(prefixes));
6331 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6333 if (s->tb->cflags & CF_USE_ICOUNT) {
6334 gen_io_start();
6336 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6337 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6338 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6339 gen_bpt_io(s, cpu_tmp2_i32, ot);
6340 if (s->tb->cflags & CF_USE_ICOUNT) {
6341 gen_io_end();
6342 gen_jmp(s, s->pc - s->cs_base);
6344 break;
6345 case 0xec:
6346 case 0xed:
6347 ot = mo_b_d32(b, dflag);
6348 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6349 gen_check_io(s, ot, pc_start - s->cs_base,
6350 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6351 if (s->tb->cflags & CF_USE_ICOUNT) {
6352 gen_io_start();
6354 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6355 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6356 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
6357 gen_bpt_io(s, cpu_tmp2_i32, ot);
6358 if (s->tb->cflags & CF_USE_ICOUNT) {
6359 gen_io_end();
6360 gen_jmp(s, s->pc - s->cs_base);
6362 break;
6363 case 0xee:
6364 case 0xef:
6365 ot = mo_b_d32(b, dflag);
6366 tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
6367 gen_check_io(s, ot, pc_start - s->cs_base,
6368 svm_is_rep(prefixes));
6369 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
6371 if (s->tb->cflags & CF_USE_ICOUNT) {
6372 gen_io_start();
6374 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6375 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
6376 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6377 gen_bpt_io(s, cpu_tmp2_i32, ot);
6378 if (s->tb->cflags & CF_USE_ICOUNT) {
6379 gen_io_end();
6380 gen_jmp(s, s->pc - s->cs_base);
6382 break;
6384 /************************/
6385 /* control */
6386 case 0xc2: /* ret im */
6387 val = cpu_ldsw_code(env, s->pc);
6388 s->pc += 2;
6389 ot = gen_pop_T0(s);
6390 gen_stack_update(s, val + (1 << ot));
6391 /* Note that gen_pop_T0 uses a zero-extending load. */
6392 gen_op_jmp_v(cpu_T0);
6393 gen_bnd_jmp(s);
6394 gen_eob(s);
6395 break;
6396 case 0xc3: /* ret */
6397 ot = gen_pop_T0(s);
6398 gen_pop_update(s, ot);
6399 /* Note that gen_pop_T0 uses a zero-extending load. */
6400 gen_op_jmp_v(cpu_T0);
6401 gen_bnd_jmp(s);
6402 gen_eob(s);
6403 break;
6404 case 0xca: /* lret im */
6405 val = cpu_ldsw_code(env, s->pc);
6406 s->pc += 2;
6407 do_lret:
6408 if (s->pe && !s->vm86) {
6409 gen_update_cc_op(s);
6410 gen_jmp_im(pc_start - s->cs_base);
6411 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6412 tcg_const_i32(val));
6413 } else {
6414 gen_stack_A0(s);
6415 /* pop offset */
6416 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6417 /* NOTE: keeping EIP updated is not a problem in case of
6418 exception */
6419 gen_op_jmp_v(cpu_T0);
6420 /* pop selector */
6421 gen_add_A0_im(s, 1 << dflag);
6422 gen_op_ld_v(s, dflag, cpu_T0, cpu_A0);
6423 gen_op_movl_seg_T0_vm(R_CS);
6424 /* add stack offset */
6425 gen_stack_update(s, val + (2 << dflag));
6427 gen_eob(s);
6428 break;
6429 case 0xcb: /* lret */
6430 val = 0;
6431 goto do_lret;
6432 case 0xcf: /* iret */
6433 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6434 if (!s->pe) {
6435 /* real mode */
6436 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6437 set_cc_op(s, CC_OP_EFLAGS);
6438 } else if (s->vm86) {
6439 if (s->iopl != 3) {
6440 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6441 } else {
6442 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6443 set_cc_op(s, CC_OP_EFLAGS);
6445 } else {
6446 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6447 tcg_const_i32(s->pc - s->cs_base));
6448 set_cc_op(s, CC_OP_EFLAGS);
6450 gen_eob(s);
6451 break;
6452 case 0xe8: /* call im */
6454 if (dflag != MO_16) {
6455 tval = (int32_t)insn_get(env, s, MO_32);
6456 } else {
6457 tval = (int16_t)insn_get(env, s, MO_16);
6459 next_eip = s->pc - s->cs_base;
6460 tval += next_eip;
6461 if (dflag == MO_16) {
6462 tval &= 0xffff;
6463 } else if (!CODE64(s)) {
6464 tval &= 0xffffffff;
6466 tcg_gen_movi_tl(cpu_T0, next_eip);
6467 gen_push_v(s, cpu_T0);
6468 gen_bnd_jmp(s);
6469 gen_jmp(s, tval);
6471 break;
6472 case 0x9a: /* lcall im */
6474 unsigned int selector, offset;
6476 if (CODE64(s))
6477 goto illegal_op;
6478 ot = dflag;
6479 offset = insn_get(env, s, ot);
6480 selector = insn_get(env, s, MO_16);
6482 tcg_gen_movi_tl(cpu_T0, selector);
6483 tcg_gen_movi_tl(cpu_T1, offset);
6485 goto do_lcall;
6486 case 0xe9: /* jmp im */
6487 if (dflag != MO_16) {
6488 tval = (int32_t)insn_get(env, s, MO_32);
6489 } else {
6490 tval = (int16_t)insn_get(env, s, MO_16);
6492 tval += s->pc - s->cs_base;
6493 if (dflag == MO_16) {
6494 tval &= 0xffff;
6495 } else if (!CODE64(s)) {
6496 tval &= 0xffffffff;
6498 gen_bnd_jmp(s);
6499 gen_jmp(s, tval);
6500 break;
6501 case 0xea: /* ljmp im */
6503 unsigned int selector, offset;
6505 if (CODE64(s))
6506 goto illegal_op;
6507 ot = dflag;
6508 offset = insn_get(env, s, ot);
6509 selector = insn_get(env, s, MO_16);
6511 tcg_gen_movi_tl(cpu_T0, selector);
6512 tcg_gen_movi_tl(cpu_T1, offset);
6514 goto do_ljmp;
6515 case 0xeb: /* jmp Jb */
6516 tval = (int8_t)insn_get(env, s, MO_8);
6517 tval += s->pc - s->cs_base;
6518 if (dflag == MO_16) {
6519 tval &= 0xffff;
6521 gen_jmp(s, tval);
6522 break;
6523 case 0x70 ... 0x7f: /* jcc Jb */
6524 tval = (int8_t)insn_get(env, s, MO_8);
6525 goto do_jcc;
6526 case 0x180 ... 0x18f: /* jcc Jv */
6527 if (dflag != MO_16) {
6528 tval = (int32_t)insn_get(env, s, MO_32);
6529 } else {
6530 tval = (int16_t)insn_get(env, s, MO_16);
6532 do_jcc:
6533 next_eip = s->pc - s->cs_base;
6534 tval += next_eip;
6535 if (dflag == MO_16) {
6536 tval &= 0xffff;
6538 gen_bnd_jmp(s);
6539 gen_jcc(s, b, tval, next_eip);
6540 break;
6542 case 0x190 ... 0x19f: /* setcc Gv */
6543 modrm = cpu_ldub_code(env, s->pc++);
6544 gen_setcc1(s, b, cpu_T0);
6545 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6546 break;
6547 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6548 if (!(s->cpuid_features & CPUID_CMOV)) {
6549 goto illegal_op;
6551 ot = dflag;
6552 modrm = cpu_ldub_code(env, s->pc++);
6553 reg = ((modrm >> 3) & 7) | rex_r;
6554 gen_cmovcc1(env, s, ot, b, modrm, reg);
6555 break;
6557 /************************/
6558 /* flags */
6559 case 0x9c: /* pushf */
6560 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6561 if (s->vm86 && s->iopl != 3) {
6562 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6563 } else {
6564 gen_update_cc_op(s);
6565 gen_helper_read_eflags(cpu_T0, cpu_env);
6566 gen_push_v(s, cpu_T0);
6568 break;
6569 case 0x9d: /* popf */
6570 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6571 if (s->vm86 && s->iopl != 3) {
6572 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6573 } else {
6574 ot = gen_pop_T0(s);
6575 if (s->cpl == 0) {
6576 if (dflag != MO_16) {
6577 gen_helper_write_eflags(cpu_env, cpu_T0,
6578 tcg_const_i32((TF_MASK | AC_MASK |
6579 ID_MASK | NT_MASK |
6580 IF_MASK |
6581 IOPL_MASK)));
6582 } else {
6583 gen_helper_write_eflags(cpu_env, cpu_T0,
6584 tcg_const_i32((TF_MASK | AC_MASK |
6585 ID_MASK | NT_MASK |
6586 IF_MASK | IOPL_MASK)
6587 & 0xffff));
6589 } else {
6590 if (s->cpl <= s->iopl) {
6591 if (dflag != MO_16) {
6592 gen_helper_write_eflags(cpu_env, cpu_T0,
6593 tcg_const_i32((TF_MASK |
6594 AC_MASK |
6595 ID_MASK |
6596 NT_MASK |
6597 IF_MASK)));
6598 } else {
6599 gen_helper_write_eflags(cpu_env, cpu_T0,
6600 tcg_const_i32((TF_MASK |
6601 AC_MASK |
6602 ID_MASK |
6603 NT_MASK |
6604 IF_MASK)
6605 & 0xffff));
6607 } else {
6608 if (dflag != MO_16) {
6609 gen_helper_write_eflags(cpu_env, cpu_T0,
6610 tcg_const_i32((TF_MASK | AC_MASK |
6611 ID_MASK | NT_MASK)));
6612 } else {
6613 gen_helper_write_eflags(cpu_env, cpu_T0,
6614 tcg_const_i32((TF_MASK | AC_MASK |
6615 ID_MASK | NT_MASK)
6616 & 0xffff));
6620 gen_pop_update(s, ot);
6621 set_cc_op(s, CC_OP_EFLAGS);
6622 /* abort translation because TF/AC flag may change */
6623 gen_jmp_im(s->pc - s->cs_base);
6624 gen_eob(s);
6626 break;
6627 case 0x9e: /* sahf */
6628 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6629 goto illegal_op;
6630 gen_op_mov_v_reg(MO_8, cpu_T0, R_AH);
6631 gen_compute_eflags(s);
6632 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6633 tcg_gen_andi_tl(cpu_T0, cpu_T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6634 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T0);
6635 break;
6636 case 0x9f: /* lahf */
6637 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6638 goto illegal_op;
6639 gen_compute_eflags(s);
6640 /* Note: gen_compute_eflags() only gives the condition codes */
6641 tcg_gen_ori_tl(cpu_T0, cpu_cc_src, 0x02);
6642 gen_op_mov_reg_v(MO_8, R_AH, cpu_T0);
6643 break;
6644 case 0xf5: /* cmc */
6645 gen_compute_eflags(s);
6646 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6647 break;
6648 case 0xf8: /* clc */
6649 gen_compute_eflags(s);
6650 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6651 break;
6652 case 0xf9: /* stc */
6653 gen_compute_eflags(s);
6654 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6655 break;
6656 case 0xfc: /* cld */
6657 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6658 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6659 break;
6660 case 0xfd: /* std */
6661 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6662 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6663 break;
6665 /************************/
6666 /* bit operations */
6667 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6668 ot = dflag;
6669 modrm = cpu_ldub_code(env, s->pc++);
6670 op = (modrm >> 3) & 7;
6671 mod = (modrm >> 6) & 3;
6672 rm = (modrm & 7) | REX_B(s);
6673 if (mod != 3) {
6674 s->rip_offset = 1;
6675 gen_lea_modrm(env, s, modrm);
6676 if (!(s->prefix & PREFIX_LOCK)) {
6677 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6679 } else {
6680 gen_op_mov_v_reg(ot, cpu_T0, rm);
6682 /* load shift */
6683 val = cpu_ldub_code(env, s->pc++);
6684 tcg_gen_movi_tl(cpu_T1, val);
6685 if (op < 4)
6686 goto unknown_op;
6687 op -= 4;
6688 goto bt_op;
6689 case 0x1a3: /* bt Gv, Ev */
6690 op = 0;
6691 goto do_btx;
6692 case 0x1ab: /* bts */
6693 op = 1;
6694 goto do_btx;
6695 case 0x1b3: /* btr */
6696 op = 2;
6697 goto do_btx;
6698 case 0x1bb: /* btc */
6699 op = 3;
6700 do_btx:
6701 ot = dflag;
6702 modrm = cpu_ldub_code(env, s->pc++);
6703 reg = ((modrm >> 3) & 7) | rex_r;
6704 mod = (modrm >> 6) & 3;
6705 rm = (modrm & 7) | REX_B(s);
6706 gen_op_mov_v_reg(MO_32, cpu_T1, reg);
6707 if (mod != 3) {
6708 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6709 /* specific case: we need to add a displacement */
6710 gen_exts(ot, cpu_T1);
6711 tcg_gen_sari_tl(cpu_tmp0, cpu_T1, 3 + ot);
6712 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6713 tcg_gen_add_tl(cpu_A0, gen_lea_modrm_1(a), cpu_tmp0);
6714 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
6715 if (!(s->prefix & PREFIX_LOCK)) {
6716 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6718 } else {
6719 gen_op_mov_v_reg(ot, cpu_T0, rm);
6721 bt_op:
6722 tcg_gen_andi_tl(cpu_T1, cpu_T1, (1 << (3 + ot)) - 1);
6723 tcg_gen_movi_tl(cpu_tmp0, 1);
6724 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6725 if (s->prefix & PREFIX_LOCK) {
6726 switch (op) {
6727 case 0: /* bt */
6728 /* Needs no atomic ops; we surpressed the normal
6729 memory load for LOCK above so do it now. */
6730 gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
6731 break;
6732 case 1: /* bts */
6733 tcg_gen_atomic_fetch_or_tl(cpu_T0, cpu_A0, cpu_tmp0,
6734 s->mem_index, ot | MO_LE);
6735 break;
6736 case 2: /* btr */
6737 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
6738 tcg_gen_atomic_fetch_and_tl(cpu_T0, cpu_A0, cpu_tmp0,
6739 s->mem_index, ot | MO_LE);
6740 break;
6741 default:
6742 case 3: /* btc */
6743 tcg_gen_atomic_fetch_xor_tl(cpu_T0, cpu_A0, cpu_tmp0,
6744 s->mem_index, ot | MO_LE);
6745 break;
6747 tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1);
6748 } else {
6749 tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1);
6750 switch (op) {
6751 case 0: /* bt */
6752 /* Data already loaded; nothing to do. */
6753 break;
6754 case 1: /* bts */
6755 tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0);
6756 break;
6757 case 2: /* btr */
6758 tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_tmp0);
6759 break;
6760 default:
6761 case 3: /* btc */
6762 tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_tmp0);
6763 break;
6765 if (op != 0) {
6766 if (mod != 3) {
6767 gen_op_st_v(s, ot, cpu_T0, cpu_A0);
6768 } else {
6769 gen_op_mov_reg_v(ot, rm, cpu_T0);
6774 /* Delay all CC updates until after the store above. Note that
6775 C is the result of the test, Z is unchanged, and the others
6776 are all undefined. */
6777 switch (s->cc_op) {
6778 case CC_OP_MULB ... CC_OP_MULQ:
6779 case CC_OP_ADDB ... CC_OP_ADDQ:
6780 case CC_OP_ADCB ... CC_OP_ADCQ:
6781 case CC_OP_SUBB ... CC_OP_SUBQ:
6782 case CC_OP_SBBB ... CC_OP_SBBQ:
6783 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6784 case CC_OP_INCB ... CC_OP_INCQ:
6785 case CC_OP_DECB ... CC_OP_DECQ:
6786 case CC_OP_SHLB ... CC_OP_SHLQ:
6787 case CC_OP_SARB ... CC_OP_SARQ:
6788 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6789 /* Z was going to be computed from the non-zero status of CC_DST.
6790 We can get that same Z value (and the new C value) by leaving
6791 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6792 same width. */
6793 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6794 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6795 break;
6796 default:
6797 /* Otherwise, generate EFLAGS and replace the C bit. */
6798 gen_compute_eflags(s);
6799 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6800 ctz32(CC_C), 1);
6801 break;
6803 break;
6804 case 0x1bc: /* bsf / tzcnt */
6805 case 0x1bd: /* bsr / lzcnt */
6806 ot = dflag;
6807 modrm = cpu_ldub_code(env, s->pc++);
6808 reg = ((modrm >> 3) & 7) | rex_r;
6809 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6810 gen_extu(ot, cpu_T0);
6812 /* Note that lzcnt and tzcnt are in different extensions. */
6813 if ((prefixes & PREFIX_REPZ)
6814 && (b & 1
6815 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6816 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6817 int size = 8 << ot;
6818 /* For lzcnt/tzcnt, C bit is defined related to the input. */
6819 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
6820 if (b & 1) {
6821 /* For lzcnt, reduce the target_ulong result by the
6822 number of zeros that we expect to find at the top. */
6823 tcg_gen_clzi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS);
6824 tcg_gen_subi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - size);
6825 } else {
6826 /* For tzcnt, a zero input must return the operand size. */
6827 tcg_gen_ctzi_tl(cpu_T0, cpu_T0, size);
6829 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
6830 gen_op_update1_cc();
6831 set_cc_op(s, CC_OP_BMILGB + ot);
6832 } else {
6833 /* For bsr/bsf, only the Z bit is defined and it is related
6834 to the input and not the result. */
6835 tcg_gen_mov_tl(cpu_cc_dst, cpu_T0);
6836 set_cc_op(s, CC_OP_LOGICB + ot);
6838 /* ??? The manual says that the output is undefined when the
6839 input is zero, but real hardware leaves it unchanged, and
6840 real programs appear to depend on that. Accomplish this
6841 by passing the output as the value to return upon zero. */
6842 if (b & 1) {
6843 /* For bsr, return the bit index of the first 1 bit,
6844 not the count of leading zeros. */
6845 tcg_gen_xori_tl(cpu_T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
6846 tcg_gen_clz_tl(cpu_T0, cpu_T0, cpu_T1);
6847 tcg_gen_xori_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - 1);
6848 } else {
6849 tcg_gen_ctz_tl(cpu_T0, cpu_T0, cpu_regs[reg]);
6852 gen_op_mov_reg_v(ot, reg, cpu_T0);
6853 break;
6854 /************************/
6855 /* bcd */
6856 case 0x27: /* daa */
6857 if (CODE64(s))
6858 goto illegal_op;
6859 gen_update_cc_op(s);
6860 gen_helper_daa(cpu_env);
6861 set_cc_op(s, CC_OP_EFLAGS);
6862 break;
6863 case 0x2f: /* das */
6864 if (CODE64(s))
6865 goto illegal_op;
6866 gen_update_cc_op(s);
6867 gen_helper_das(cpu_env);
6868 set_cc_op(s, CC_OP_EFLAGS);
6869 break;
6870 case 0x37: /* aaa */
6871 if (CODE64(s))
6872 goto illegal_op;
6873 gen_update_cc_op(s);
6874 gen_helper_aaa(cpu_env);
6875 set_cc_op(s, CC_OP_EFLAGS);
6876 break;
6877 case 0x3f: /* aas */
6878 if (CODE64(s))
6879 goto illegal_op;
6880 gen_update_cc_op(s);
6881 gen_helper_aas(cpu_env);
6882 set_cc_op(s, CC_OP_EFLAGS);
6883 break;
6884 case 0xd4: /* aam */
6885 if (CODE64(s))
6886 goto illegal_op;
6887 val = cpu_ldub_code(env, s->pc++);
6888 if (val == 0) {
6889 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6890 } else {
6891 gen_helper_aam(cpu_env, tcg_const_i32(val));
6892 set_cc_op(s, CC_OP_LOGICB);
6894 break;
6895 case 0xd5: /* aad */
6896 if (CODE64(s))
6897 goto illegal_op;
6898 val = cpu_ldub_code(env, s->pc++);
6899 gen_helper_aad(cpu_env, tcg_const_i32(val));
6900 set_cc_op(s, CC_OP_LOGICB);
6901 break;
6902 /************************/
6903 /* misc */
6904 case 0x90: /* nop */
6905 /* XXX: correct lock test for all insn */
6906 if (prefixes & PREFIX_LOCK) {
6907 goto illegal_op;
6909 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6910 if (REX_B(s)) {
6911 goto do_xchg_reg_eax;
6913 if (prefixes & PREFIX_REPZ) {
6914 gen_update_cc_op(s);
6915 gen_jmp_im(pc_start - s->cs_base);
6916 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6917 s->is_jmp = DISAS_TB_JUMP;
6919 break;
6920 case 0x9b: /* fwait */
6921 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6922 (HF_MP_MASK | HF_TS_MASK)) {
6923 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6924 } else {
6925 gen_helper_fwait(cpu_env);
6927 break;
6928 case 0xcc: /* int3 */
6929 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6930 break;
6931 case 0xcd: /* int N */
6932 val = cpu_ldub_code(env, s->pc++);
6933 if (s->vm86 && s->iopl != 3) {
6934 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6935 } else {
6936 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6938 break;
6939 case 0xce: /* into */
6940 if (CODE64(s))
6941 goto illegal_op;
6942 gen_update_cc_op(s);
6943 gen_jmp_im(pc_start - s->cs_base);
6944 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6945 break;
6946 #ifdef WANT_ICEBP
6947 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6948 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6949 #if 1
6950 gen_debug(s, pc_start - s->cs_base);
6951 #else
6952 /* start debug */
6953 tb_flush(CPU(x86_env_get_cpu(env)));
6954 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6955 #endif
6956 break;
6957 #endif
6958 case 0xfa: /* cli */
6959 if (!s->vm86) {
6960 if (s->cpl <= s->iopl) {
6961 gen_helper_cli(cpu_env);
6962 } else {
6963 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6965 } else {
6966 if (s->iopl == 3) {
6967 gen_helper_cli(cpu_env);
6968 } else {
6969 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6972 break;
6973 case 0xfb: /* sti */
6974 if (s->vm86 ? s->iopl == 3 : s->cpl <= s->iopl) {
6975 gen_helper_sti(cpu_env);
6976 /* interruptions are enabled only the first insn after sti */
6977 gen_jmp_im(s->pc - s->cs_base);
6978 gen_eob_inhibit_irq(s, true);
6979 } else {
6980 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6982 break;
6983 case 0x62: /* bound */
6984 if (CODE64(s))
6985 goto illegal_op;
6986 ot = dflag;
6987 modrm = cpu_ldub_code(env, s->pc++);
6988 reg = (modrm >> 3) & 7;
6989 mod = (modrm >> 6) & 3;
6990 if (mod == 3)
6991 goto illegal_op;
6992 gen_op_mov_v_reg(ot, cpu_T0, reg);
6993 gen_lea_modrm(env, s, modrm);
6994 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
6995 if (ot == MO_16) {
6996 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
6997 } else {
6998 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
7000 break;
7001 case 0x1c8 ... 0x1cf: /* bswap reg */
7002 reg = (b & 7) | REX_B(s);
7003 #ifdef TARGET_X86_64
7004 if (dflag == MO_64) {
7005 gen_op_mov_v_reg(MO_64, cpu_T0, reg);
7006 tcg_gen_bswap64_i64(cpu_T0, cpu_T0);
7007 gen_op_mov_reg_v(MO_64, reg, cpu_T0);
7008 } else
7009 #endif
7011 gen_op_mov_v_reg(MO_32, cpu_T0, reg);
7012 tcg_gen_ext32u_tl(cpu_T0, cpu_T0);
7013 tcg_gen_bswap32_tl(cpu_T0, cpu_T0);
7014 gen_op_mov_reg_v(MO_32, reg, cpu_T0);
7016 break;
7017 case 0xd6: /* salc */
7018 if (CODE64(s))
7019 goto illegal_op;
7020 gen_compute_eflags_c(s, cpu_T0);
7021 tcg_gen_neg_tl(cpu_T0, cpu_T0);
7022 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0);
7023 break;
7024 case 0xe0: /* loopnz */
7025 case 0xe1: /* loopz */
7026 case 0xe2: /* loop */
7027 case 0xe3: /* jecxz */
7029 TCGLabel *l1, *l2, *l3;
7031 tval = (int8_t)insn_get(env, s, MO_8);
7032 next_eip = s->pc - s->cs_base;
7033 tval += next_eip;
7034 if (dflag == MO_16) {
7035 tval &= 0xffff;
7038 l1 = gen_new_label();
7039 l2 = gen_new_label();
7040 l3 = gen_new_label();
7041 b &= 3;
7042 switch(b) {
7043 case 0: /* loopnz */
7044 case 1: /* loopz */
7045 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7046 gen_op_jz_ecx(s->aflag, l3);
7047 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7048 break;
7049 case 2: /* loop */
7050 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7051 gen_op_jnz_ecx(s->aflag, l1);
7052 break;
7053 default:
7054 case 3: /* jcxz */
7055 gen_op_jz_ecx(s->aflag, l1);
7056 break;
7059 gen_set_label(l3);
7060 gen_jmp_im(next_eip);
7061 tcg_gen_br(l2);
7063 gen_set_label(l1);
7064 gen_jmp_im(tval);
7065 gen_set_label(l2);
7066 gen_eob(s);
7068 break;
7069 case 0x130: /* wrmsr */
7070 case 0x132: /* rdmsr */
7071 if (s->cpl != 0) {
7072 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7073 } else {
7074 gen_update_cc_op(s);
7075 gen_jmp_im(pc_start - s->cs_base);
7076 if (b & 2) {
7077 gen_helper_rdmsr(cpu_env);
7078 } else {
7079 gen_helper_wrmsr(cpu_env);
7082 break;
7083 case 0x131: /* rdtsc */
7084 gen_update_cc_op(s);
7085 gen_jmp_im(pc_start - s->cs_base);
7086 if (s->tb->cflags & CF_USE_ICOUNT) {
7087 gen_io_start();
7089 gen_helper_rdtsc(cpu_env);
7090 if (s->tb->cflags & CF_USE_ICOUNT) {
7091 gen_io_end();
7092 gen_jmp(s, s->pc - s->cs_base);
7094 break;
7095 case 0x133: /* rdpmc */
7096 gen_update_cc_op(s);
7097 gen_jmp_im(pc_start - s->cs_base);
7098 gen_helper_rdpmc(cpu_env);
7099 break;
7100 case 0x134: /* sysenter */
7101 /* For Intel SYSENTER is valid on 64-bit */
7102 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7103 goto illegal_op;
7104 if (!s->pe) {
7105 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7106 } else {
7107 gen_helper_sysenter(cpu_env);
7108 gen_eob(s);
7110 break;
7111 case 0x135: /* sysexit */
7112 /* For Intel SYSEXIT is valid on 64-bit */
7113 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7114 goto illegal_op;
7115 if (!s->pe) {
7116 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7117 } else {
7118 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7119 gen_eob(s);
7121 break;
7122 #ifdef TARGET_X86_64
7123 case 0x105: /* syscall */
7124 /* XXX: is it usable in real mode ? */
7125 gen_update_cc_op(s);
7126 gen_jmp_im(pc_start - s->cs_base);
7127 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7128 /* TF handling for the syscall insn is different. The TF bit is checked
7129 after the syscall insn completes. This allows #DB to not be
7130 generated after one has entered CPL0 if TF is set in FMASK. */
7131 gen_eob_worker(s, false, true);
7132 break;
7133 case 0x107: /* sysret */
7134 if (!s->pe) {
7135 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7136 } else {
7137 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7138 /* condition codes are modified only in long mode */
7139 if (s->lma) {
7140 set_cc_op(s, CC_OP_EFLAGS);
7142 /* TF handling for the sysret insn is different. The TF bit is
7143 checked after the sysret insn completes. This allows #DB to be
7144 generated "as if" the syscall insn in userspace has just
7145 completed. */
7146 gen_eob_worker(s, false, true);
7148 break;
7149 #endif
7150 case 0x1a2: /* cpuid */
7151 gen_update_cc_op(s);
7152 gen_jmp_im(pc_start - s->cs_base);
7153 gen_helper_cpuid(cpu_env);
7154 break;
7155 case 0xf4: /* hlt */
7156 if (s->cpl != 0) {
7157 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7158 } else {
7159 gen_update_cc_op(s);
7160 gen_jmp_im(pc_start - s->cs_base);
7161 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7162 s->is_jmp = DISAS_TB_JUMP;
7164 break;
7165 case 0x100:
7166 modrm = cpu_ldub_code(env, s->pc++);
7167 mod = (modrm >> 6) & 3;
7168 op = (modrm >> 3) & 7;
7169 switch(op) {
7170 case 0: /* sldt */
7171 if (!s->pe || s->vm86)
7172 goto illegal_op;
7173 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7174 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
7175 offsetof(CPUX86State, ldt.selector));
7176 ot = mod == 3 ? dflag : MO_16;
7177 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7178 break;
7179 case 2: /* lldt */
7180 if (!s->pe || s->vm86)
7181 goto illegal_op;
7182 if (s->cpl != 0) {
7183 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7184 } else {
7185 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7186 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7187 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
7188 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7190 break;
7191 case 1: /* str */
7192 if (!s->pe || s->vm86)
7193 goto illegal_op;
7194 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7195 tcg_gen_ld32u_tl(cpu_T0, cpu_env,
7196 offsetof(CPUX86State, tr.selector));
7197 ot = mod == 3 ? dflag : MO_16;
7198 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7199 break;
7200 case 3: /* ltr */
7201 if (!s->pe || s->vm86)
7202 goto illegal_op;
7203 if (s->cpl != 0) {
7204 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7205 } else {
7206 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7207 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7208 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
7209 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7211 break;
7212 case 4: /* verr */
7213 case 5: /* verw */
7214 if (!s->pe || s->vm86)
7215 goto illegal_op;
7216 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7217 gen_update_cc_op(s);
7218 if (op == 4) {
7219 gen_helper_verr(cpu_env, cpu_T0);
7220 } else {
7221 gen_helper_verw(cpu_env, cpu_T0);
7223 set_cc_op(s, CC_OP_EFLAGS);
7224 break;
7225 default:
7226 goto unknown_op;
7228 break;
7230 case 0x101:
7231 modrm = cpu_ldub_code(env, s->pc++);
7232 switch (modrm) {
7233 CASE_MODRM_MEM_OP(0): /* sgdt */
7234 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7235 gen_lea_modrm(env, s, modrm);
7236 tcg_gen_ld32u_tl(cpu_T0,
7237 cpu_env, offsetof(CPUX86State, gdt.limit));
7238 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7239 gen_add_A0_im(s, 2);
7240 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7241 if (dflag == MO_16) {
7242 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7244 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7245 break;
7247 case 0xc8: /* monitor */
7248 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7249 goto illegal_op;
7251 gen_update_cc_op(s);
7252 gen_jmp_im(pc_start - s->cs_base);
7253 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7254 gen_extu(s->aflag, cpu_A0);
7255 gen_add_A0_ds_seg(s);
7256 gen_helper_monitor(cpu_env, cpu_A0);
7257 break;
7259 case 0xc9: /* mwait */
7260 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7261 goto illegal_op;
7263 gen_update_cc_op(s);
7264 gen_jmp_im(pc_start - s->cs_base);
7265 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7266 gen_eob(s);
7267 break;
7269 case 0xca: /* clac */
7270 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7271 || s->cpl != 0) {
7272 goto illegal_op;
7274 gen_helper_clac(cpu_env);
7275 gen_jmp_im(s->pc - s->cs_base);
7276 gen_eob(s);
7277 break;
7279 case 0xcb: /* stac */
7280 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7281 || s->cpl != 0) {
7282 goto illegal_op;
7284 gen_helper_stac(cpu_env);
7285 gen_jmp_im(s->pc - s->cs_base);
7286 gen_eob(s);
7287 break;
7289 CASE_MODRM_MEM_OP(1): /* sidt */
7290 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7291 gen_lea_modrm(env, s, modrm);
7292 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.limit));
7293 gen_op_st_v(s, MO_16, cpu_T0, cpu_A0);
7294 gen_add_A0_im(s, 2);
7295 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base));
7296 if (dflag == MO_16) {
7297 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7299 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7300 break;
7302 case 0xd0: /* xgetbv */
7303 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7304 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7305 | PREFIX_REPZ | PREFIX_REPNZ))) {
7306 goto illegal_op;
7308 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7309 gen_helper_xgetbv(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7310 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7311 break;
7313 case 0xd1: /* xsetbv */
7314 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7315 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7316 | PREFIX_REPZ | PREFIX_REPNZ))) {
7317 goto illegal_op;
7319 if (s->cpl != 0) {
7320 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7321 break;
7323 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7324 cpu_regs[R_EDX]);
7325 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7326 gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7327 /* End TB because translation flags may change. */
7328 gen_jmp_im(s->pc - s->cs_base);
7329 gen_eob(s);
7330 break;
7332 case 0xd8: /* VMRUN */
7333 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7334 goto illegal_op;
7336 if (s->cpl != 0) {
7337 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7338 break;
7340 gen_update_cc_op(s);
7341 gen_jmp_im(pc_start - s->cs_base);
7342 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7343 tcg_const_i32(s->pc - pc_start));
7344 tcg_gen_exit_tb(0);
7345 s->is_jmp = DISAS_TB_JUMP;
7346 break;
7348 case 0xd9: /* VMMCALL */
7349 if (!(s->flags & HF_SVME_MASK)) {
7350 goto illegal_op;
7352 gen_update_cc_op(s);
7353 gen_jmp_im(pc_start - s->cs_base);
7354 gen_helper_vmmcall(cpu_env);
7355 break;
7357 case 0xda: /* VMLOAD */
7358 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7359 goto illegal_op;
7361 if (s->cpl != 0) {
7362 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7363 break;
7365 gen_update_cc_op(s);
7366 gen_jmp_im(pc_start - s->cs_base);
7367 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7368 break;
7370 case 0xdb: /* VMSAVE */
7371 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7372 goto illegal_op;
7374 if (s->cpl != 0) {
7375 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7376 break;
7378 gen_update_cc_op(s);
7379 gen_jmp_im(pc_start - s->cs_base);
7380 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7381 break;
7383 case 0xdc: /* STGI */
7384 if ((!(s->flags & HF_SVME_MASK)
7385 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7386 || !s->pe) {
7387 goto illegal_op;
7389 if (s->cpl != 0) {
7390 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7391 break;
7393 gen_update_cc_op(s);
7394 gen_jmp_im(pc_start - s->cs_base);
7395 gen_helper_stgi(cpu_env);
7396 break;
7398 case 0xdd: /* CLGI */
7399 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7400 goto illegal_op;
7402 if (s->cpl != 0) {
7403 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7404 break;
7406 gen_update_cc_op(s);
7407 gen_jmp_im(pc_start - s->cs_base);
7408 gen_helper_clgi(cpu_env);
7409 break;
7411 case 0xde: /* SKINIT */
7412 if ((!(s->flags & HF_SVME_MASK)
7413 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7414 || !s->pe) {
7415 goto illegal_op;
7417 gen_update_cc_op(s);
7418 gen_jmp_im(pc_start - s->cs_base);
7419 gen_helper_skinit(cpu_env);
7420 break;
7422 case 0xdf: /* INVLPGA */
7423 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7424 goto illegal_op;
7426 if (s->cpl != 0) {
7427 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7428 break;
7430 gen_update_cc_op(s);
7431 gen_jmp_im(pc_start - s->cs_base);
7432 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7433 break;
7435 CASE_MODRM_MEM_OP(2): /* lgdt */
7436 if (s->cpl != 0) {
7437 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7438 break;
7440 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE);
7441 gen_lea_modrm(env, s, modrm);
7442 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7443 gen_add_A0_im(s, 2);
7444 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7445 if (dflag == MO_16) {
7446 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7448 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base));
7449 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7450 break;
7452 CASE_MODRM_MEM_OP(3): /* lidt */
7453 if (s->cpl != 0) {
7454 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7455 break;
7457 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7458 gen_lea_modrm(env, s, modrm);
7459 gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0);
7460 gen_add_A0_im(s, 2);
7461 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0);
7462 if (dflag == MO_16) {
7463 tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff);
7465 tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base));
7466 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, idt.limit));
7467 break;
7469 CASE_MODRM_OP(4): /* smsw */
7470 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7471 tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, cr[0]));
7472 if (CODE64(s)) {
7473 mod = (modrm >> 6) & 3;
7474 ot = (mod != 3 ? MO_16 : s->dflag);
7475 } else {
7476 ot = MO_16;
7478 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7479 break;
7480 case 0xee: /* rdpkru */
7481 if (prefixes & PREFIX_LOCK) {
7482 goto illegal_op;
7484 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7485 gen_helper_rdpkru(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7486 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7487 break;
7488 case 0xef: /* wrpkru */
7489 if (prefixes & PREFIX_LOCK) {
7490 goto illegal_op;
7492 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7493 cpu_regs[R_EDX]);
7494 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7495 gen_helper_wrpkru(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7496 break;
7497 CASE_MODRM_OP(6): /* lmsw */
7498 if (s->cpl != 0) {
7499 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7500 break;
7502 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7503 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7504 gen_helper_lmsw(cpu_env, cpu_T0);
7505 gen_jmp_im(s->pc - s->cs_base);
7506 gen_eob(s);
7507 break;
7509 CASE_MODRM_MEM_OP(7): /* invlpg */
7510 if (s->cpl != 0) {
7511 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7512 break;
7514 gen_update_cc_op(s);
7515 gen_jmp_im(pc_start - s->cs_base);
7516 gen_lea_modrm(env, s, modrm);
7517 gen_helper_invlpg(cpu_env, cpu_A0);
7518 gen_jmp_im(s->pc - s->cs_base);
7519 gen_eob(s);
7520 break;
7522 case 0xf8: /* swapgs */
7523 #ifdef TARGET_X86_64
7524 if (CODE64(s)) {
7525 if (s->cpl != 0) {
7526 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7527 } else {
7528 tcg_gen_mov_tl(cpu_T0, cpu_seg_base[R_GS]);
7529 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7530 offsetof(CPUX86State, kernelgsbase));
7531 tcg_gen_st_tl(cpu_T0, cpu_env,
7532 offsetof(CPUX86State, kernelgsbase));
7534 break;
7536 #endif
7537 goto illegal_op;
7539 case 0xf9: /* rdtscp */
7540 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7541 goto illegal_op;
7543 gen_update_cc_op(s);
7544 gen_jmp_im(pc_start - s->cs_base);
7545 if (s->tb->cflags & CF_USE_ICOUNT) {
7546 gen_io_start();
7548 gen_helper_rdtscp(cpu_env);
7549 if (s->tb->cflags & CF_USE_ICOUNT) {
7550 gen_io_end();
7551 gen_jmp(s, s->pc - s->cs_base);
7553 break;
7555 default:
7556 goto unknown_op;
7558 break;
7560 case 0x108: /* invd */
7561 case 0x109: /* wbinvd */
7562 if (s->cpl != 0) {
7563 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7564 } else {
7565 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7566 /* nothing to do */
7568 break;
7569 case 0x63: /* arpl or movslS (x86_64) */
7570 #ifdef TARGET_X86_64
7571 if (CODE64(s)) {
7572 int d_ot;
7573 /* d_ot is the size of destination */
7574 d_ot = dflag;
7576 modrm = cpu_ldub_code(env, s->pc++);
7577 reg = ((modrm >> 3) & 7) | rex_r;
7578 mod = (modrm >> 6) & 3;
7579 rm = (modrm & 7) | REX_B(s);
7581 if (mod == 3) {
7582 gen_op_mov_v_reg(MO_32, cpu_T0, rm);
7583 /* sign extend */
7584 if (d_ot == MO_64) {
7585 tcg_gen_ext32s_tl(cpu_T0, cpu_T0);
7587 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7588 } else {
7589 gen_lea_modrm(env, s, modrm);
7590 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T0, cpu_A0);
7591 gen_op_mov_reg_v(d_ot, reg, cpu_T0);
7593 } else
7594 #endif
7596 TCGLabel *label1;
7597 TCGv t0, t1, t2, a0;
7599 if (!s->pe || s->vm86)
7600 goto illegal_op;
7601 t0 = tcg_temp_local_new();
7602 t1 = tcg_temp_local_new();
7603 t2 = tcg_temp_local_new();
7604 ot = MO_16;
7605 modrm = cpu_ldub_code(env, s->pc++);
7606 reg = (modrm >> 3) & 7;
7607 mod = (modrm >> 6) & 3;
7608 rm = modrm & 7;
7609 if (mod != 3) {
7610 gen_lea_modrm(env, s, modrm);
7611 gen_op_ld_v(s, ot, t0, cpu_A0);
7612 a0 = tcg_temp_local_new();
7613 tcg_gen_mov_tl(a0, cpu_A0);
7614 } else {
7615 gen_op_mov_v_reg(ot, t0, rm);
7616 TCGV_UNUSED(a0);
7618 gen_op_mov_v_reg(ot, t1, reg);
7619 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7620 tcg_gen_andi_tl(t1, t1, 3);
7621 tcg_gen_movi_tl(t2, 0);
7622 label1 = gen_new_label();
7623 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7624 tcg_gen_andi_tl(t0, t0, ~3);
7625 tcg_gen_or_tl(t0, t0, t1);
7626 tcg_gen_movi_tl(t2, CC_Z);
7627 gen_set_label(label1);
7628 if (mod != 3) {
7629 gen_op_st_v(s, ot, t0, a0);
7630 tcg_temp_free(a0);
7631 } else {
7632 gen_op_mov_reg_v(ot, rm, t0);
7634 gen_compute_eflags(s);
7635 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7636 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7637 tcg_temp_free(t0);
7638 tcg_temp_free(t1);
7639 tcg_temp_free(t2);
7641 break;
7642 case 0x102: /* lar */
7643 case 0x103: /* lsl */
7645 TCGLabel *label1;
7646 TCGv t0;
7647 if (!s->pe || s->vm86)
7648 goto illegal_op;
7649 ot = dflag != MO_16 ? MO_32 : MO_16;
7650 modrm = cpu_ldub_code(env, s->pc++);
7651 reg = ((modrm >> 3) & 7) | rex_r;
7652 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7653 t0 = tcg_temp_local_new();
7654 gen_update_cc_op(s);
7655 if (b == 0x102) {
7656 gen_helper_lar(t0, cpu_env, cpu_T0);
7657 } else {
7658 gen_helper_lsl(t0, cpu_env, cpu_T0);
7660 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7661 label1 = gen_new_label();
7662 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7663 gen_op_mov_reg_v(ot, reg, t0);
7664 gen_set_label(label1);
7665 set_cc_op(s, CC_OP_EFLAGS);
7666 tcg_temp_free(t0);
7668 break;
7669 case 0x118:
7670 modrm = cpu_ldub_code(env, s->pc++);
7671 mod = (modrm >> 6) & 3;
7672 op = (modrm >> 3) & 7;
7673 switch(op) {
7674 case 0: /* prefetchnta */
7675 case 1: /* prefetchnt0 */
7676 case 2: /* prefetchnt0 */
7677 case 3: /* prefetchnt0 */
7678 if (mod == 3)
7679 goto illegal_op;
7680 gen_nop_modrm(env, s, modrm);
7681 /* nothing more to do */
7682 break;
7683 default: /* nop (multi byte) */
7684 gen_nop_modrm(env, s, modrm);
7685 break;
7687 break;
7688 case 0x11a:
7689 modrm = cpu_ldub_code(env, s->pc++);
7690 if (s->flags & HF_MPX_EN_MASK) {
7691 mod = (modrm >> 6) & 3;
7692 reg = ((modrm >> 3) & 7) | rex_r;
7693 if (prefixes & PREFIX_REPZ) {
7694 /* bndcl */
7695 if (reg >= 4
7696 || (prefixes & PREFIX_LOCK)
7697 || s->aflag == MO_16) {
7698 goto illegal_op;
7700 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7701 } else if (prefixes & PREFIX_REPNZ) {
7702 /* bndcu */
7703 if (reg >= 4
7704 || (prefixes & PREFIX_LOCK)
7705 || s->aflag == MO_16) {
7706 goto illegal_op;
7708 TCGv_i64 notu = tcg_temp_new_i64();
7709 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7710 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7711 tcg_temp_free_i64(notu);
7712 } else if (prefixes & PREFIX_DATA) {
7713 /* bndmov -- from reg/mem */
7714 if (reg >= 4 || s->aflag == MO_16) {
7715 goto illegal_op;
7717 if (mod == 3) {
7718 int reg2 = (modrm & 7) | REX_B(s);
7719 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7720 goto illegal_op;
7722 if (s->flags & HF_MPX_IU_MASK) {
7723 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7724 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7726 } else {
7727 gen_lea_modrm(env, s, modrm);
7728 if (CODE64(s)) {
7729 tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0,
7730 s->mem_index, MO_LEQ);
7731 tcg_gen_addi_tl(cpu_A0, cpu_A0, 8);
7732 tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0,
7733 s->mem_index, MO_LEQ);
7734 } else {
7735 tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0,
7736 s->mem_index, MO_LEUL);
7737 tcg_gen_addi_tl(cpu_A0, cpu_A0, 4);
7738 tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0,
7739 s->mem_index, MO_LEUL);
7741 /* bnd registers are now in-use */
7742 gen_set_hflag(s, HF_MPX_IU_MASK);
7744 } else if (mod != 3) {
7745 /* bndldx */
7746 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7747 if (reg >= 4
7748 || (prefixes & PREFIX_LOCK)
7749 || s->aflag == MO_16
7750 || a.base < -1) {
7751 goto illegal_op;
7753 if (a.base >= 0) {
7754 tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp);
7755 } else {
7756 tcg_gen_movi_tl(cpu_A0, 0);
7758 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
7759 if (a.index >= 0) {
7760 tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]);
7761 } else {
7762 tcg_gen_movi_tl(cpu_T0, 0);
7764 if (CODE64(s)) {
7765 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, cpu_A0, cpu_T0);
7766 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7767 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7768 } else {
7769 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, cpu_A0, cpu_T0);
7770 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7771 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7773 gen_set_hflag(s, HF_MPX_IU_MASK);
7776 gen_nop_modrm(env, s, modrm);
7777 break;
7778 case 0x11b:
7779 modrm = cpu_ldub_code(env, s->pc++);
7780 if (s->flags & HF_MPX_EN_MASK) {
7781 mod = (modrm >> 6) & 3;
7782 reg = ((modrm >> 3) & 7) | rex_r;
7783 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7784 /* bndmk */
7785 if (reg >= 4
7786 || (prefixes & PREFIX_LOCK)
7787 || s->aflag == MO_16) {
7788 goto illegal_op;
7790 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7791 if (a.base >= 0) {
7792 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7793 if (!CODE64(s)) {
7794 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7796 } else if (a.base == -1) {
7797 /* no base register has lower bound of 0 */
7798 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7799 } else {
7800 /* rip-relative generates #ud */
7801 goto illegal_op;
7803 tcg_gen_not_tl(cpu_A0, gen_lea_modrm_1(a));
7804 if (!CODE64(s)) {
7805 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
7807 tcg_gen_extu_tl_i64(cpu_bndu[reg], cpu_A0);
7808 /* bnd registers are now in-use */
7809 gen_set_hflag(s, HF_MPX_IU_MASK);
7810 break;
7811 } else if (prefixes & PREFIX_REPNZ) {
7812 /* bndcn */
7813 if (reg >= 4
7814 || (prefixes & PREFIX_LOCK)
7815 || s->aflag == MO_16) {
7816 goto illegal_op;
7818 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
7819 } else if (prefixes & PREFIX_DATA) {
7820 /* bndmov -- to reg/mem */
7821 if (reg >= 4 || s->aflag == MO_16) {
7822 goto illegal_op;
7824 if (mod == 3) {
7825 int reg2 = (modrm & 7) | REX_B(s);
7826 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7827 goto illegal_op;
7829 if (s->flags & HF_MPX_IU_MASK) {
7830 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7831 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7833 } else {
7834 gen_lea_modrm(env, s, modrm);
7835 if (CODE64(s)) {
7836 tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0,
7837 s->mem_index, MO_LEQ);
7838 tcg_gen_addi_tl(cpu_A0, cpu_A0, 8);
7839 tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0,
7840 s->mem_index, MO_LEQ);
7841 } else {
7842 tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0,
7843 s->mem_index, MO_LEUL);
7844 tcg_gen_addi_tl(cpu_A0, cpu_A0, 4);
7845 tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0,
7846 s->mem_index, MO_LEUL);
7849 } else if (mod != 3) {
7850 /* bndstx */
7851 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7852 if (reg >= 4
7853 || (prefixes & PREFIX_LOCK)
7854 || s->aflag == MO_16
7855 || a.base < -1) {
7856 goto illegal_op;
7858 if (a.base >= 0) {
7859 tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp);
7860 } else {
7861 tcg_gen_movi_tl(cpu_A0, 0);
7863 gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override);
7864 if (a.index >= 0) {
7865 tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]);
7866 } else {
7867 tcg_gen_movi_tl(cpu_T0, 0);
7869 if (CODE64(s)) {
7870 gen_helper_bndstx64(cpu_env, cpu_A0, cpu_T0,
7871 cpu_bndl[reg], cpu_bndu[reg]);
7872 } else {
7873 gen_helper_bndstx32(cpu_env, cpu_A0, cpu_T0,
7874 cpu_bndl[reg], cpu_bndu[reg]);
7878 gen_nop_modrm(env, s, modrm);
7879 break;
7880 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
7881 modrm = cpu_ldub_code(env, s->pc++);
7882 gen_nop_modrm(env, s, modrm);
7883 break;
7884 case 0x120: /* mov reg, crN */
7885 case 0x122: /* mov crN, reg */
7886 if (s->cpl != 0) {
7887 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7888 } else {
7889 modrm = cpu_ldub_code(env, s->pc++);
7890 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7891 * AMD documentation (24594.pdf) and testing of
7892 * intel 386 and 486 processors all show that the mod bits
7893 * are assumed to be 1's, regardless of actual values.
7895 rm = (modrm & 7) | REX_B(s);
7896 reg = ((modrm >> 3) & 7) | rex_r;
7897 if (CODE64(s))
7898 ot = MO_64;
7899 else
7900 ot = MO_32;
7901 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7902 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7903 reg = 8;
7905 switch(reg) {
7906 case 0:
7907 case 2:
7908 case 3:
7909 case 4:
7910 case 8:
7911 gen_update_cc_op(s);
7912 gen_jmp_im(pc_start - s->cs_base);
7913 if (b & 2) {
7914 gen_op_mov_v_reg(ot, cpu_T0, rm);
7915 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7916 cpu_T0);
7917 gen_jmp_im(s->pc - s->cs_base);
7918 gen_eob(s);
7919 } else {
7920 gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg));
7921 gen_op_mov_reg_v(ot, rm, cpu_T0);
7923 break;
7924 default:
7925 goto unknown_op;
7928 break;
7929 case 0x121: /* mov reg, drN */
7930 case 0x123: /* mov drN, reg */
7931 if (s->cpl != 0) {
7932 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7933 } else {
7934 modrm = cpu_ldub_code(env, s->pc++);
7935 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7936 * AMD documentation (24594.pdf) and testing of
7937 * intel 386 and 486 processors all show that the mod bits
7938 * are assumed to be 1's, regardless of actual values.
7940 rm = (modrm & 7) | REX_B(s);
7941 reg = ((modrm >> 3) & 7) | rex_r;
7942 if (CODE64(s))
7943 ot = MO_64;
7944 else
7945 ot = MO_32;
7946 if (reg >= 8) {
7947 goto illegal_op;
7949 if (b & 2) {
7950 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7951 gen_op_mov_v_reg(ot, cpu_T0, rm);
7952 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7953 gen_helper_set_dr(cpu_env, cpu_tmp2_i32, cpu_T0);
7954 gen_jmp_im(s->pc - s->cs_base);
7955 gen_eob(s);
7956 } else {
7957 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7958 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7959 gen_helper_get_dr(cpu_T0, cpu_env, cpu_tmp2_i32);
7960 gen_op_mov_reg_v(ot, rm, cpu_T0);
7963 break;
7964 case 0x106: /* clts */
7965 if (s->cpl != 0) {
7966 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7967 } else {
7968 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7969 gen_helper_clts(cpu_env);
7970 /* abort block because static cpu state changed */
7971 gen_jmp_im(s->pc - s->cs_base);
7972 gen_eob(s);
7974 break;
7975 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
7976 case 0x1c3: /* MOVNTI reg, mem */
7977 if (!(s->cpuid_features & CPUID_SSE2))
7978 goto illegal_op;
7979 ot = mo_64_32(dflag);
7980 modrm = cpu_ldub_code(env, s->pc++);
7981 mod = (modrm >> 6) & 3;
7982 if (mod == 3)
7983 goto illegal_op;
7984 reg = ((modrm >> 3) & 7) | rex_r;
7985 /* generate a generic store */
7986 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
7987 break;
7988 case 0x1ae:
7989 modrm = cpu_ldub_code(env, s->pc++);
7990 switch (modrm) {
7991 CASE_MODRM_MEM_OP(0): /* fxsave */
7992 if (!(s->cpuid_features & CPUID_FXSR)
7993 || (prefixes & PREFIX_LOCK)) {
7994 goto illegal_op;
7996 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7997 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7998 break;
8000 gen_lea_modrm(env, s, modrm);
8001 gen_helper_fxsave(cpu_env, cpu_A0);
8002 break;
8004 CASE_MODRM_MEM_OP(1): /* fxrstor */
8005 if (!(s->cpuid_features & CPUID_FXSR)
8006 || (prefixes & PREFIX_LOCK)) {
8007 goto illegal_op;
8009 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8010 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8011 break;
8013 gen_lea_modrm(env, s, modrm);
8014 gen_helper_fxrstor(cpu_env, cpu_A0);
8015 break;
8017 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
8018 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8019 goto illegal_op;
8021 if (s->flags & HF_TS_MASK) {
8022 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8023 break;
8025 gen_lea_modrm(env, s, modrm);
8026 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, s->mem_index, MO_LEUL);
8027 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
8028 break;
8030 CASE_MODRM_MEM_OP(3): /* stmxcsr */
8031 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8032 goto illegal_op;
8034 if (s->flags & HF_TS_MASK) {
8035 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8036 break;
8038 gen_lea_modrm(env, s, modrm);
8039 tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, mxcsr));
8040 gen_op_st_v(s, MO_32, cpu_T0, cpu_A0);
8041 break;
8043 CASE_MODRM_MEM_OP(4): /* xsave */
8044 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8045 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8046 | PREFIX_REPZ | PREFIX_REPNZ))) {
8047 goto illegal_op;
8049 gen_lea_modrm(env, s, modrm);
8050 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8051 cpu_regs[R_EDX]);
8052 gen_helper_xsave(cpu_env, cpu_A0, cpu_tmp1_i64);
8053 break;
8055 CASE_MODRM_MEM_OP(5): /* xrstor */
8056 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8057 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8058 | PREFIX_REPZ | PREFIX_REPNZ))) {
8059 goto illegal_op;
8061 gen_lea_modrm(env, s, modrm);
8062 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8063 cpu_regs[R_EDX]);
8064 gen_helper_xrstor(cpu_env, cpu_A0, cpu_tmp1_i64);
8065 /* XRSTOR is how MPX is enabled, which changes how
8066 we translate. Thus we need to end the TB. */
8067 gen_update_cc_op(s);
8068 gen_jmp_im(s->pc - s->cs_base);
8069 gen_eob(s);
8070 break;
8072 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
8073 if (prefixes & PREFIX_LOCK) {
8074 goto illegal_op;
8076 if (prefixes & PREFIX_DATA) {
8077 /* clwb */
8078 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8079 goto illegal_op;
8081 gen_nop_modrm(env, s, modrm);
8082 } else {
8083 /* xsaveopt */
8084 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8085 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8086 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8087 goto illegal_op;
8089 gen_lea_modrm(env, s, modrm);
8090 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8091 cpu_regs[R_EDX]);
8092 gen_helper_xsaveopt(cpu_env, cpu_A0, cpu_tmp1_i64);
8094 break;
8096 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
8097 if (prefixes & PREFIX_LOCK) {
8098 goto illegal_op;
8100 if (prefixes & PREFIX_DATA) {
8101 /* clflushopt */
8102 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8103 goto illegal_op;
8105 } else {
8106 /* clflush */
8107 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8108 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8109 goto illegal_op;
8112 gen_nop_modrm(env, s, modrm);
8113 break;
8115 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
8116 case 0xc8 ... 0xc8: /* rdgsbase (f3 0f ae /1) */
8117 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
8118 case 0xd8 ... 0xd8: /* wrgsbase (f3 0f ae /3) */
8119 if (CODE64(s)
8120 && (prefixes & PREFIX_REPZ)
8121 && !(prefixes & PREFIX_LOCK)
8122 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8123 TCGv base, treg, src, dst;
8125 /* Preserve hflags bits by testing CR4 at runtime. */
8126 tcg_gen_movi_i32(cpu_tmp2_i32, CR4_FSGSBASE_MASK);
8127 gen_helper_cr4_testbit(cpu_env, cpu_tmp2_i32);
8129 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8130 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8132 if (modrm & 0x10) {
8133 /* wr*base */
8134 dst = base, src = treg;
8135 } else {
8136 /* rd*base */
8137 dst = treg, src = base;
8140 if (s->dflag == MO_32) {
8141 tcg_gen_ext32u_tl(dst, src);
8142 } else {
8143 tcg_gen_mov_tl(dst, src);
8145 break;
8147 goto unknown_op;
8149 case 0xf8: /* sfence / pcommit */
8150 if (prefixes & PREFIX_DATA) {
8151 /* pcommit */
8152 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8153 || (prefixes & PREFIX_LOCK)) {
8154 goto illegal_op;
8156 break;
8158 /* fallthru */
8159 case 0xf9 ... 0xff: /* sfence */
8160 if (!(s->cpuid_features & CPUID_SSE)
8161 || (prefixes & PREFIX_LOCK)) {
8162 goto illegal_op;
8164 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8165 break;
8166 case 0xe8 ... 0xef: /* lfence */
8167 if (!(s->cpuid_features & CPUID_SSE)
8168 || (prefixes & PREFIX_LOCK)) {
8169 goto illegal_op;
8171 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8172 break;
8173 case 0xf0 ... 0xf7: /* mfence */
8174 if (!(s->cpuid_features & CPUID_SSE2)
8175 || (prefixes & PREFIX_LOCK)) {
8176 goto illegal_op;
8178 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8179 break;
8181 default:
8182 goto unknown_op;
8184 break;
8186 case 0x10d: /* 3DNow! prefetch(w) */
8187 modrm = cpu_ldub_code(env, s->pc++);
8188 mod = (modrm >> 6) & 3;
8189 if (mod == 3)
8190 goto illegal_op;
8191 gen_nop_modrm(env, s, modrm);
8192 break;
8193 case 0x1aa: /* rsm */
8194 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8195 if (!(s->flags & HF_SMM_MASK))
8196 goto illegal_op;
8197 gen_update_cc_op(s);
8198 gen_jmp_im(s->pc - s->cs_base);
8199 gen_helper_rsm(cpu_env);
8200 gen_eob(s);
8201 break;
8202 case 0x1b8: /* SSE4.2 popcnt */
8203 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8204 PREFIX_REPZ)
8205 goto illegal_op;
8206 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8207 goto illegal_op;
8209 modrm = cpu_ldub_code(env, s->pc++);
8210 reg = ((modrm >> 3) & 7) | rex_r;
8212 if (s->prefix & PREFIX_DATA) {
8213 ot = MO_16;
8214 } else {
8215 ot = mo_64_32(dflag);
8218 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8219 gen_extu(ot, cpu_T0);
8220 tcg_gen_mov_tl(cpu_cc_src, cpu_T0);
8221 tcg_gen_ctpop_tl(cpu_T0, cpu_T0);
8222 gen_op_mov_reg_v(ot, reg, cpu_T0);
8224 set_cc_op(s, CC_OP_POPCNT);
8225 break;
8226 case 0x10e ... 0x10f:
8227 /* 3DNow! instructions, ignore prefixes */
8228 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8229 case 0x110 ... 0x117:
8230 case 0x128 ... 0x12f:
8231 case 0x138 ... 0x13a:
8232 case 0x150 ... 0x179:
8233 case 0x17c ... 0x17f:
8234 case 0x1c2:
8235 case 0x1c4 ... 0x1c6:
8236 case 0x1d0 ... 0x1fe:
8237 gen_sse(env, s, b, pc_start, rex_r);
8238 break;
8239 default:
8240 goto unknown_op;
8242 return s->pc;
8243 illegal_op:
8244 gen_illegal_opcode(s);
8245 return s->pc;
8246 unknown_op:
8247 gen_unknown_opcode(env, s);
8248 return s->pc;
8251 void tcg_x86_init(void)
8253 static const char reg_names[CPU_NB_REGS][4] = {
8254 #ifdef TARGET_X86_64
8255 [R_EAX] = "rax",
8256 [R_EBX] = "rbx",
8257 [R_ECX] = "rcx",
8258 [R_EDX] = "rdx",
8259 [R_ESI] = "rsi",
8260 [R_EDI] = "rdi",
8261 [R_EBP] = "rbp",
8262 [R_ESP] = "rsp",
8263 [8] = "r8",
8264 [9] = "r9",
8265 [10] = "r10",
8266 [11] = "r11",
8267 [12] = "r12",
8268 [13] = "r13",
8269 [14] = "r14",
8270 [15] = "r15",
8271 #else
8272 [R_EAX] = "eax",
8273 [R_EBX] = "ebx",
8274 [R_ECX] = "ecx",
8275 [R_EDX] = "edx",
8276 [R_ESI] = "esi",
8277 [R_EDI] = "edi",
8278 [R_EBP] = "ebp",
8279 [R_ESP] = "esp",
8280 #endif
8282 static const char seg_base_names[6][8] = {
8283 [R_CS] = "cs_base",
8284 [R_DS] = "ds_base",
8285 [R_ES] = "es_base",
8286 [R_FS] = "fs_base",
8287 [R_GS] = "gs_base",
8288 [R_SS] = "ss_base",
8290 static const char bnd_regl_names[4][8] = {
8291 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8293 static const char bnd_regu_names[4][8] = {
8294 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8296 int i;
8297 static bool initialized;
8299 if (initialized) {
8300 return;
8302 initialized = true;
8304 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8305 tcg_ctx.tcg_env = cpu_env;
8306 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8307 offsetof(CPUX86State, cc_op), "cc_op");
8308 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8309 "cc_dst");
8310 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8311 "cc_src");
8312 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8313 "cc_src2");
8315 for (i = 0; i < CPU_NB_REGS; ++i) {
8316 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8317 offsetof(CPUX86State, regs[i]),
8318 reg_names[i]);
8321 for (i = 0; i < 6; ++i) {
8322 cpu_seg_base[i]
8323 = tcg_global_mem_new(cpu_env,
8324 offsetof(CPUX86State, segs[i].base),
8325 seg_base_names[i]);
8328 for (i = 0; i < 4; ++i) {
8329 cpu_bndl[i]
8330 = tcg_global_mem_new_i64(cpu_env,
8331 offsetof(CPUX86State, bnd_regs[i].lb),
8332 bnd_regl_names[i]);
8333 cpu_bndu[i]
8334 = tcg_global_mem_new_i64(cpu_env,
8335 offsetof(CPUX86State, bnd_regs[i].ub),
8336 bnd_regu_names[i]);
8340 /* generate intermediate code for basic block 'tb'. */
8341 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
8343 X86CPU *cpu = x86_env_get_cpu(env);
8344 CPUState *cs = CPU(cpu);
8345 DisasContext dc1, *dc = &dc1;
8346 target_ulong pc_ptr;
8347 uint32_t flags;
8348 target_ulong pc_start;
8349 target_ulong cs_base;
8350 int num_insns;
8351 int max_insns;
8353 /* generate intermediate code */
8354 pc_start = tb->pc;
8355 cs_base = tb->cs_base;
8356 flags = tb->flags;
8358 dc->pe = (flags >> HF_PE_SHIFT) & 1;
8359 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8360 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8361 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8362 dc->f_st = 0;
8363 dc->vm86 = (flags >> VM_SHIFT) & 1;
8364 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8365 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8366 dc->tf = (flags >> TF_SHIFT) & 1;
8367 dc->singlestep_enabled = cs->singlestep_enabled;
8368 dc->cc_op = CC_OP_DYNAMIC;
8369 dc->cc_op_dirty = false;
8370 dc->cs_base = cs_base;
8371 dc->tb = tb;
8372 dc->popl_esp_hack = 0;
8373 /* select memory access functions */
8374 dc->mem_index = 0;
8375 #ifdef CONFIG_SOFTMMU
8376 dc->mem_index = cpu_mmu_index(env, false);
8377 #endif
8378 dc->cpuid_features = env->features[FEAT_1_EDX];
8379 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8380 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8381 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8382 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8383 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8384 #ifdef TARGET_X86_64
8385 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8386 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8387 #endif
8388 dc->flags = flags;
8389 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
8390 (flags & HF_INHIBIT_IRQ_MASK));
8391 /* Do not optimize repz jumps at all in icount mode, because
8392 rep movsS instructions are execured with different paths
8393 in !repz_opt and repz_opt modes. The first one was used
8394 always except single step mode. And this setting
8395 disables jumps optimization and control paths become
8396 equivalent in run and single step modes.
8397 Now there will be no jump optimization for repz in
8398 record/replay modes and there will always be an
8399 additional step for ecx=0 when icount is enabled.
8401 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
8402 #if 0
8403 /* check addseg logic */
8404 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8405 printf("ERROR addseg\n");
8406 #endif
8408 cpu_T0 = tcg_temp_new();
8409 cpu_T1 = tcg_temp_new();
8410 cpu_A0 = tcg_temp_new();
8412 cpu_tmp0 = tcg_temp_new();
8413 cpu_tmp1_i64 = tcg_temp_new_i64();
8414 cpu_tmp2_i32 = tcg_temp_new_i32();
8415 cpu_tmp3_i32 = tcg_temp_new_i32();
8416 cpu_tmp4 = tcg_temp_new();
8417 cpu_ptr0 = tcg_temp_new_ptr();
8418 cpu_ptr1 = tcg_temp_new_ptr();
8419 cpu_cc_srcT = tcg_temp_local_new();
8421 dc->is_jmp = DISAS_NEXT;
8422 pc_ptr = pc_start;
8423 num_insns = 0;
8424 max_insns = tb->cflags & CF_COUNT_MASK;
8425 if (max_insns == 0) {
8426 max_insns = CF_COUNT_MASK;
8428 if (max_insns > TCG_MAX_INSNS) {
8429 max_insns = TCG_MAX_INSNS;
8432 gen_tb_start(tb);
8433 for(;;) {
8434 #if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
8435 /* Detect vsyscall */
8436 if (unlikely(pc_ptr >= TARGET_VSYSCALL_START
8437 && pc_ptr < TARGET_VSYSCALL_END)) {
8438 gen_helper_vsyscall(cpu_env);
8439 break;
8441 #endif
8443 tcg_gen_insn_start(pc_ptr, dc->cc_op);
8444 num_insns++;
8446 /* If RF is set, suppress an internally generated breakpoint. */
8447 if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
8448 tb->flags & HF_RF_MASK
8449 ? BP_GDB : BP_ANY))) {
8450 gen_debug(dc, pc_ptr - dc->cs_base);
8451 /* The address covered by the breakpoint must be included in
8452 [tb->pc, tb->pc + tb->size) in order to for it to be
8453 properly cleared -- thus we increment the PC here so that
8454 the logic setting tb->size below does the right thing. */
8455 pc_ptr += 1;
8456 goto done_generating;
8458 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
8459 gen_io_start();
8462 pc_ptr = disas_insn(env, dc, pc_ptr);
8463 /* stop translation if indicated */
8464 if (dc->is_jmp)
8465 break;
8466 /* if single step mode, we generate only one instruction and
8467 generate an exception */
8468 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8469 the flag and abort the translation to give the irqs a
8470 change to be happen */
8471 if (dc->tf || dc->singlestep_enabled ||
8472 (flags & HF_INHIBIT_IRQ_MASK)) {
8473 gen_jmp_im(pc_ptr - dc->cs_base);
8474 gen_eob(dc);
8475 break;
8477 /* Do not cross the boundary of the pages in icount mode,
8478 it can cause an exception. Do it only when boundary is
8479 crossed by the first instruction in the block.
8480 If current instruction already crossed the bound - it's ok,
8481 because an exception hasn't stopped this code.
8483 if ((tb->cflags & CF_USE_ICOUNT)
8484 && ((pc_ptr & TARGET_PAGE_MASK)
8485 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
8486 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
8487 gen_jmp_im(pc_ptr - dc->cs_base);
8488 gen_eob(dc);
8489 break;
8491 /* if too long translation, stop generation too */
8492 if (tcg_op_buf_full() ||
8493 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8494 num_insns >= max_insns) {
8495 gen_jmp_im(pc_ptr - dc->cs_base);
8496 gen_eob(dc);
8497 break;
8499 if (singlestep) {
8500 gen_jmp_im(pc_ptr - dc->cs_base);
8501 gen_eob(dc);
8502 break;
8505 if (tb->cflags & CF_LAST_IO)
8506 gen_io_end();
8507 done_generating:
8508 gen_tb_end(tb, num_insns);
8510 #ifdef DEBUG_DISAS
8511 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
8512 && qemu_log_in_addr_range(pc_start)) {
8513 int disas_flags;
8514 qemu_log_lock();
8515 qemu_log("----------------\n");
8516 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8517 #ifdef TARGET_X86_64
8518 if (dc->code64)
8519 disas_flags = 2;
8520 else
8521 #endif
8522 disas_flags = !dc->code32;
8523 log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
8524 qemu_log("\n");
8525 qemu_log_unlock();
8527 #endif
8529 tb->size = pc_ptr - pc_start;
8530 tb->icount = num_insns;
8533 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8534 target_ulong *data)
8536 int cc_op = data[1];
8537 env->eip = data[0] - tb->cs_base;
8538 if (cc_op != CC_OP_DYNAMIC) {
8539 env->cc_op = cc_op;