Merge tag 'v2.4.0-rc1'
[qemu/ar7.git] / target-i386 / translate.c
blobf90fb80194dd8e02e43bf0ddeb5cb49698ab556f
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/>.
20 #include <signal.h>
22 #include "qemu-common.h"
23 #include "qemu/host-utils.h"
24 #include "cpu.h"
25 #include "disas/disas.h"
26 #include "tcg-op.h"
27 #include "exec/cpu_ldst.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
32 #if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
33 #include "vsyscall.h"
34 #endif
36 #include "trace-tcg.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 //#define MACRO_TEST 1
66 /* global register indexes */
67 static TCGv_ptr cpu_env;
68 static TCGv cpu_A0;
69 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
70 static TCGv_i32 cpu_cc_op;
71 static TCGv cpu_regs[CPU_NB_REGS];
72 /* local temps */
73 static TCGv cpu_T[2];
74 /* local register indexes (only used inside old micro ops) */
75 static TCGv cpu_tmp0, cpu_tmp4;
76 static TCGv_ptr cpu_ptr0, cpu_ptr1;
77 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
78 static TCGv_i64 cpu_tmp1_i64;
80 static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
82 #include "exec/gen-icount.h"
84 #ifdef TARGET_X86_64
85 static int x86_64_hregs;
86 #endif
88 typedef struct DisasContext {
89 /* current insn context */
90 int override; /* -1 if no override */
91 int prefix;
92 TCGMemOp aflag;
93 TCGMemOp dflag;
94 target_ulong pc; /* pc = eip + cs_base */
95 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
96 static state change (stop translation) */
97 /* current block context */
98 target_ulong cs_base; /* base of CS segment */
99 int pe; /* protected mode */
100 int code32; /* 32 bit code segment */
101 #ifdef TARGET_X86_64
102 int lma; /* long mode active */
103 int code64; /* 64 bit code segment */
104 int rex_x, rex_b;
105 #endif
106 int vex_l; /* vex vector length */
107 int vex_v; /* vex vvvv register, without 1's compliment. */
108 int ss32; /* 32 bit stack segment */
109 CCOp cc_op; /* current CC operation */
110 bool cc_op_dirty;
111 int addseg; /* non zero if either DS/ES/SS have a non zero base */
112 int f_st; /* currently unused */
113 int vm86; /* vm86 mode */
114 int cpl;
115 int iopl;
116 int tf; /* TF cpu flag */
117 int singlestep_enabled; /* "hardware" single step enabled */
118 int jmp_opt; /* use direct block chaining for direct jumps */
119 int repz_opt; /* optimize jumps within repz instructions */
120 int mem_index; /* select memory access functions */
121 uint64_t flags; /* all execution flags */
122 struct TranslationBlock *tb;
123 int popl_esp_hack; /* for correct popl with esp base handling */
124 int rip_offset; /* only used in x86_64, but left for simplicity */
125 int cpuid_features;
126 int cpuid_ext_features;
127 int cpuid_ext2_features;
128 int cpuid_ext3_features;
129 int cpuid_7_0_ebx_features;
130 } DisasContext;
132 static void gen_eob(DisasContext *s);
133 static void gen_jmp(DisasContext *s, target_ulong eip);
134 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
135 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d);
137 /* i386 arith/logic operations */
138 enum {
139 OP_ADDL,
140 OP_ORL,
141 OP_ADCL,
142 OP_SBBL,
143 OP_ANDL,
144 OP_SUBL,
145 OP_XORL,
146 OP_CMPL,
149 /* i386 shift ops */
150 enum {
151 OP_ROL,
152 OP_ROR,
153 OP_RCL,
154 OP_RCR,
155 OP_SHL,
156 OP_SHR,
157 OP_SHL1, /* undocumented */
158 OP_SAR = 7,
161 enum {
162 JCC_O,
163 JCC_B,
164 JCC_Z,
165 JCC_BE,
166 JCC_S,
167 JCC_P,
168 JCC_L,
169 JCC_LE,
172 enum {
173 /* I386 int registers */
174 OR_EAX, /* MUST be even numbered */
175 OR_ECX,
176 OR_EDX,
177 OR_EBX,
178 OR_ESP,
179 OR_EBP,
180 OR_ESI,
181 OR_EDI,
183 OR_TMP0 = 16, /* temporary operand register */
184 OR_TMP1,
185 OR_A0, /* temporary register used when doing address evaluation */
188 enum {
189 USES_CC_DST = 1,
190 USES_CC_SRC = 2,
191 USES_CC_SRC2 = 4,
192 USES_CC_SRCT = 8,
195 /* Bit set if the global variable is live after setting CC_OP to X. */
196 static const uint8_t cc_op_live[CC_OP_NB] = {
197 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
198 [CC_OP_EFLAGS] = USES_CC_SRC,
199 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
200 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
201 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
202 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
203 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
204 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
205 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
206 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
207 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
208 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
209 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
210 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
211 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
212 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
213 [CC_OP_CLR] = 0,
216 static void set_cc_op(DisasContext *s, CCOp op)
218 int dead;
220 if (s->cc_op == op) {
221 return;
224 /* Discard CC computation that will no longer be used. */
225 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
226 if (dead & USES_CC_DST) {
227 tcg_gen_discard_tl(cpu_cc_dst);
229 if (dead & USES_CC_SRC) {
230 tcg_gen_discard_tl(cpu_cc_src);
232 if (dead & USES_CC_SRC2) {
233 tcg_gen_discard_tl(cpu_cc_src2);
235 if (dead & USES_CC_SRCT) {
236 tcg_gen_discard_tl(cpu_cc_srcT);
239 if (op == CC_OP_DYNAMIC) {
240 /* The DYNAMIC setting is translator only, and should never be
241 stored. Thus we always consider it clean. */
242 s->cc_op_dirty = false;
243 } else {
244 /* Discard any computed CC_OP value (see shifts). */
245 if (s->cc_op == CC_OP_DYNAMIC) {
246 tcg_gen_discard_i32(cpu_cc_op);
248 s->cc_op_dirty = true;
250 s->cc_op = op;
253 static void gen_update_cc_op(DisasContext *s)
255 if (s->cc_op_dirty) {
256 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
257 s->cc_op_dirty = false;
261 #ifdef TARGET_X86_64
263 #define NB_OP_SIZES 4
265 #else /* !TARGET_X86_64 */
267 #define NB_OP_SIZES 3
269 #endif /* !TARGET_X86_64 */
271 #if defined(HOST_WORDS_BIGENDIAN)
272 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
273 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
274 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
275 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
276 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
277 #else
278 #define REG_B_OFFSET 0
279 #define REG_H_OFFSET 1
280 #define REG_W_OFFSET 0
281 #define REG_L_OFFSET 0
282 #define REG_LH_OFFSET 4
283 #endif
285 /* In instruction encodings for byte register accesses the
286 * register number usually indicates "low 8 bits of register N";
287 * however there are some special cases where N 4..7 indicates
288 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
289 * true for this special case, false otherwise.
291 static inline bool byte_reg_is_xH(int reg)
293 if (reg < 4) {
294 return false;
296 #ifdef TARGET_X86_64
297 if (reg >= 8 || x86_64_hregs) {
298 return false;
300 #endif
301 return true;
304 /* Select the size of a push/pop operation. */
305 static inline TCGMemOp mo_pushpop(DisasContext *s, TCGMemOp ot)
307 if (CODE64(s)) {
308 return ot == MO_16 ? MO_16 : MO_64;
309 } else {
310 return ot;
314 /* Select only size 64 else 32. Used for SSE operand sizes. */
315 static inline TCGMemOp mo_64_32(TCGMemOp ot)
317 #ifdef TARGET_X86_64
318 return ot == MO_64 ? MO_64 : MO_32;
319 #else
320 return MO_32;
321 #endif
324 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
325 byte vs word opcodes. */
326 static inline TCGMemOp mo_b_d(int b, TCGMemOp ot)
328 return b & 1 ? ot : MO_8;
331 /* Select size 8 if lsb of B is clear, else OT capped at 32.
332 Used for decoding operand size of port opcodes. */
333 static inline TCGMemOp mo_b_d32(int b, TCGMemOp ot)
335 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
338 static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
340 switch(ot) {
341 case MO_8:
342 if (!byte_reg_is_xH(reg)) {
343 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
344 } else {
345 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
347 break;
348 case MO_16:
349 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
350 break;
351 case MO_32:
352 /* For x86_64, this sets the higher half of register to zero.
353 For i386, this is equivalent to a mov. */
354 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
355 break;
356 #ifdef TARGET_X86_64
357 case MO_64:
358 tcg_gen_mov_tl(cpu_regs[reg], t0);
359 break;
360 #endif
361 default:
362 tcg_abort();
366 static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
368 if (ot == MO_8 && byte_reg_is_xH(reg)) {
369 tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
370 tcg_gen_ext8u_tl(t0, t0);
371 } else {
372 tcg_gen_mov_tl(t0, cpu_regs[reg]);
376 static inline void gen_op_movl_A0_reg(int reg)
378 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
381 static inline void gen_op_addl_A0_im(int32_t val)
383 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
384 #ifdef TARGET_X86_64
385 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
386 #endif
389 #ifdef TARGET_X86_64
390 static inline void gen_op_addq_A0_im(int64_t val)
392 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
394 #endif
396 static void gen_add_A0_im(DisasContext *s, int val)
398 #ifdef TARGET_X86_64
399 if (CODE64(s))
400 gen_op_addq_A0_im(val);
401 else
402 #endif
403 gen_op_addl_A0_im(val);
406 static inline void gen_op_jmp_v(TCGv dest)
408 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
411 static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
413 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
414 gen_op_mov_reg_v(size, reg, cpu_tmp0);
417 static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
419 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
420 gen_op_mov_reg_v(size, reg, cpu_tmp0);
423 static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
425 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
426 if (shift != 0)
427 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
428 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
429 /* For x86_64, this sets the higher half of register to zero.
430 For i386, this is equivalent to a nop. */
431 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
434 static inline void gen_op_movl_A0_seg(int reg)
436 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
439 static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
441 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
442 #ifdef TARGET_X86_64
443 if (CODE64(s)) {
444 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
445 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
446 } else {
447 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
448 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
450 #else
451 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
452 #endif
455 #ifdef TARGET_X86_64
456 static inline void gen_op_movq_A0_seg(int reg)
458 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
461 static inline void gen_op_addq_A0_seg(int reg)
463 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
464 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
467 static inline void gen_op_movq_A0_reg(int reg)
469 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
472 static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
474 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
475 if (shift != 0)
476 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
477 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
479 #endif
481 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
483 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
486 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
488 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
491 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
493 if (d == OR_TMP0) {
494 gen_op_st_v(s, idx, cpu_T[0], cpu_A0);
495 } else {
496 gen_op_mov_reg_v(idx, d, cpu_T[0]);
500 static inline void gen_jmp_im(target_ulong pc)
502 tcg_gen_movi_tl(cpu_tmp0, pc);
503 gen_op_jmp_v(cpu_tmp0);
506 static inline void gen_string_movl_A0_ESI(DisasContext *s)
508 int override;
510 override = s->override;
511 switch (s->aflag) {
512 #ifdef TARGET_X86_64
513 case MO_64:
514 if (override >= 0) {
515 gen_op_movq_A0_seg(override);
516 gen_op_addq_A0_reg_sN(0, R_ESI);
517 } else {
518 gen_op_movq_A0_reg(R_ESI);
520 break;
521 #endif
522 case MO_32:
523 /* 32 bit address */
524 if (s->addseg && override < 0)
525 override = R_DS;
526 if (override >= 0) {
527 gen_op_movl_A0_seg(override);
528 gen_op_addl_A0_reg_sN(0, R_ESI);
529 } else {
530 gen_op_movl_A0_reg(R_ESI);
532 break;
533 case MO_16:
534 /* 16 address, always override */
535 if (override < 0)
536 override = R_DS;
537 tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESI]);
538 gen_op_addl_A0_seg(s, override);
539 break;
540 default:
541 tcg_abort();
545 static inline void gen_string_movl_A0_EDI(DisasContext *s)
547 switch (s->aflag) {
548 #ifdef TARGET_X86_64
549 case MO_64:
550 gen_op_movq_A0_reg(R_EDI);
551 break;
552 #endif
553 case MO_32:
554 if (s->addseg) {
555 gen_op_movl_A0_seg(R_ES);
556 gen_op_addl_A0_reg_sN(0, R_EDI);
557 } else {
558 gen_op_movl_A0_reg(R_EDI);
560 break;
561 case MO_16:
562 tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_EDI]);
563 gen_op_addl_A0_seg(s, R_ES);
564 break;
565 default:
566 tcg_abort();
570 static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
572 tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
573 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
576 static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign)
578 switch (size) {
579 case MO_8:
580 if (sign) {
581 tcg_gen_ext8s_tl(dst, src);
582 } else {
583 tcg_gen_ext8u_tl(dst, src);
585 return dst;
586 case MO_16:
587 if (sign) {
588 tcg_gen_ext16s_tl(dst, src);
589 } else {
590 tcg_gen_ext16u_tl(dst, src);
592 return dst;
593 #ifdef TARGET_X86_64
594 case MO_32:
595 if (sign) {
596 tcg_gen_ext32s_tl(dst, src);
597 } else {
598 tcg_gen_ext32u_tl(dst, src);
600 return dst;
601 #endif
602 default:
603 return src;
607 static void gen_extu(TCGMemOp ot, TCGv reg)
609 gen_ext_tl(reg, reg, ot, false);
612 static void gen_exts(TCGMemOp ot, TCGv reg)
614 gen_ext_tl(reg, reg, ot, true);
617 static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1)
619 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
620 gen_extu(size, cpu_tmp0);
621 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
624 static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1)
626 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
627 gen_extu(size, cpu_tmp0);
628 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
631 static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n)
633 switch (ot) {
634 case MO_8:
635 gen_helper_inb(v, cpu_env, n);
636 break;
637 case MO_16:
638 gen_helper_inw(v, cpu_env, n);
639 break;
640 case MO_32:
641 gen_helper_inl(v, cpu_env, n);
642 break;
643 default:
644 tcg_abort();
648 static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n)
650 switch (ot) {
651 case MO_8:
652 gen_helper_outb(cpu_env, v, n);
653 break;
654 case MO_16:
655 gen_helper_outw(cpu_env, v, n);
656 break;
657 case MO_32:
658 gen_helper_outl(cpu_env, v, n);
659 break;
660 default:
661 tcg_abort();
665 static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
666 uint32_t svm_flags)
668 int state_saved;
669 target_ulong next_eip;
671 state_saved = 0;
672 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
673 gen_update_cc_op(s);
674 gen_jmp_im(cur_eip);
675 state_saved = 1;
676 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
677 switch (ot) {
678 case MO_8:
679 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
680 break;
681 case MO_16:
682 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
683 break;
684 case MO_32:
685 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
686 break;
687 default:
688 tcg_abort();
691 if(s->flags & HF_SVMI_MASK) {
692 if (!state_saved) {
693 gen_update_cc_op(s);
694 gen_jmp_im(cur_eip);
696 svm_flags |= (1 << (4 + ot));
697 next_eip = s->pc - s->cs_base;
698 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
699 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
700 tcg_const_i32(svm_flags),
701 tcg_const_i32(next_eip - cur_eip));
705 static inline void gen_movs(DisasContext *s, TCGMemOp ot)
707 gen_string_movl_A0_ESI(s);
708 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
709 gen_string_movl_A0_EDI(s);
710 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
711 gen_op_movl_T0_Dshift(ot);
712 gen_op_add_reg_T0(s->aflag, R_ESI);
713 gen_op_add_reg_T0(s->aflag, R_EDI);
716 static void gen_op_update1_cc(void)
718 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
721 static void gen_op_update2_cc(void)
723 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
724 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
727 static void gen_op_update3_cc(TCGv reg)
729 tcg_gen_mov_tl(cpu_cc_src2, reg);
730 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
731 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
734 static inline void gen_op_testl_T0_T1_cc(void)
736 tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
739 static void gen_op_update_neg_cc(void)
741 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
742 tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]);
743 tcg_gen_movi_tl(cpu_cc_srcT, 0);
746 /* compute all eflags to cc_src */
747 static void gen_compute_eflags(DisasContext *s)
749 TCGv zero, dst, src1, src2;
750 int live, dead;
752 if (s->cc_op == CC_OP_EFLAGS) {
753 return;
755 if (s->cc_op == CC_OP_CLR) {
756 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
757 set_cc_op(s, CC_OP_EFLAGS);
758 return;
761 TCGV_UNUSED(zero);
762 dst = cpu_cc_dst;
763 src1 = cpu_cc_src;
764 src2 = cpu_cc_src2;
766 /* Take care to not read values that are not live. */
767 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
768 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
769 if (dead) {
770 zero = tcg_const_tl(0);
771 if (dead & USES_CC_DST) {
772 dst = zero;
774 if (dead & USES_CC_SRC) {
775 src1 = zero;
777 if (dead & USES_CC_SRC2) {
778 src2 = zero;
782 gen_update_cc_op(s);
783 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
784 set_cc_op(s, CC_OP_EFLAGS);
786 if (dead) {
787 tcg_temp_free(zero);
791 typedef struct CCPrepare {
792 TCGCond cond;
793 TCGv reg;
794 TCGv reg2;
795 target_ulong imm;
796 target_ulong mask;
797 bool use_reg2;
798 bool no_setcond;
799 } CCPrepare;
801 /* compute eflags.C to reg */
802 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
804 TCGv t0, t1;
805 int size, shift;
807 switch (s->cc_op) {
808 case CC_OP_SUBB ... CC_OP_SUBQ:
809 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
810 size = s->cc_op - CC_OP_SUBB;
811 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
812 /* If no temporary was used, be careful not to alias t1 and t0. */
813 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
814 tcg_gen_mov_tl(t0, cpu_cc_srcT);
815 gen_extu(size, t0);
816 goto add_sub;
818 case CC_OP_ADDB ... CC_OP_ADDQ:
819 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
820 size = s->cc_op - CC_OP_ADDB;
821 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
822 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
823 add_sub:
824 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
825 .reg2 = t1, .mask = -1, .use_reg2 = true };
827 case CC_OP_LOGICB ... CC_OP_LOGICQ:
828 case CC_OP_CLR:
829 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
831 case CC_OP_INCB ... CC_OP_INCQ:
832 case CC_OP_DECB ... CC_OP_DECQ:
833 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
834 .mask = -1, .no_setcond = true };
836 case CC_OP_SHLB ... CC_OP_SHLQ:
837 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
838 size = s->cc_op - CC_OP_SHLB;
839 shift = (8 << size) - 1;
840 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
841 .mask = (target_ulong)1 << shift };
843 case CC_OP_MULB ... CC_OP_MULQ:
844 return (CCPrepare) { .cond = TCG_COND_NE,
845 .reg = cpu_cc_src, .mask = -1 };
847 case CC_OP_BMILGB ... CC_OP_BMILGQ:
848 size = s->cc_op - CC_OP_BMILGB;
849 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
850 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
852 case CC_OP_ADCX:
853 case CC_OP_ADCOX:
854 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
855 .mask = -1, .no_setcond = true };
857 case CC_OP_EFLAGS:
858 case CC_OP_SARB ... CC_OP_SARQ:
859 /* CC_SRC & 1 */
860 return (CCPrepare) { .cond = TCG_COND_NE,
861 .reg = cpu_cc_src, .mask = CC_C };
863 default:
864 /* The need to compute only C from CC_OP_DYNAMIC is important
865 in efficiently implementing e.g. INC at the start of a TB. */
866 gen_update_cc_op(s);
867 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
868 cpu_cc_src2, cpu_cc_op);
869 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
870 .mask = -1, .no_setcond = true };
874 /* compute eflags.P to reg */
875 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
877 gen_compute_eflags(s);
878 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
879 .mask = CC_P };
882 /* compute eflags.S to reg */
883 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
885 switch (s->cc_op) {
886 case CC_OP_DYNAMIC:
887 gen_compute_eflags(s);
888 /* FALLTHRU */
889 case CC_OP_EFLAGS:
890 case CC_OP_ADCX:
891 case CC_OP_ADOX:
892 case CC_OP_ADCOX:
893 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
894 .mask = CC_S };
895 case CC_OP_CLR:
896 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
897 default:
899 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
900 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
901 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
906 /* compute eflags.O to reg */
907 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
909 switch (s->cc_op) {
910 case CC_OP_ADOX:
911 case CC_OP_ADCOX:
912 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
913 .mask = -1, .no_setcond = true };
914 case CC_OP_CLR:
915 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
916 default:
917 gen_compute_eflags(s);
918 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
919 .mask = CC_O };
923 /* compute eflags.Z to reg */
924 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
926 switch (s->cc_op) {
927 case CC_OP_DYNAMIC:
928 gen_compute_eflags(s);
929 /* FALLTHRU */
930 case CC_OP_EFLAGS:
931 case CC_OP_ADCX:
932 case CC_OP_ADOX:
933 case CC_OP_ADCOX:
934 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
935 .mask = CC_Z };
936 case CC_OP_CLR:
937 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
938 default:
940 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
941 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
942 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
947 /* perform a conditional store into register 'reg' according to jump opcode
948 value 'b'. In the fast case, T0 is guaranted not to be used. */
949 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
951 int inv, jcc_op, cond;
952 TCGMemOp size;
953 CCPrepare cc;
954 TCGv t0;
956 inv = b & 1;
957 jcc_op = (b >> 1) & 7;
959 switch (s->cc_op) {
960 case CC_OP_SUBB ... CC_OP_SUBQ:
961 /* We optimize relational operators for the cmp/jcc case. */
962 size = s->cc_op - CC_OP_SUBB;
963 switch (jcc_op) {
964 case JCC_BE:
965 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
966 gen_extu(size, cpu_tmp4);
967 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
968 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
969 .reg2 = t0, .mask = -1, .use_reg2 = true };
970 break;
972 case JCC_L:
973 cond = TCG_COND_LT;
974 goto fast_jcc_l;
975 case JCC_LE:
976 cond = TCG_COND_LE;
977 fast_jcc_l:
978 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
979 gen_exts(size, cpu_tmp4);
980 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
981 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
982 .reg2 = t0, .mask = -1, .use_reg2 = true };
983 break;
985 default:
986 goto slow_jcc;
988 break;
990 default:
991 slow_jcc:
992 /* This actually generates good code for JC, JZ and JS. */
993 switch (jcc_op) {
994 case JCC_O:
995 cc = gen_prepare_eflags_o(s, reg);
996 break;
997 case JCC_B:
998 cc = gen_prepare_eflags_c(s, reg);
999 break;
1000 case JCC_Z:
1001 cc = gen_prepare_eflags_z(s, reg);
1002 break;
1003 case JCC_BE:
1004 gen_compute_eflags(s);
1005 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1006 .mask = CC_Z | CC_C };
1007 break;
1008 case JCC_S:
1009 cc = gen_prepare_eflags_s(s, reg);
1010 break;
1011 case JCC_P:
1012 cc = gen_prepare_eflags_p(s, reg);
1013 break;
1014 case JCC_L:
1015 gen_compute_eflags(s);
1016 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1017 reg = cpu_tmp0;
1019 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1020 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1021 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1022 .mask = CC_S };
1023 break;
1024 default:
1025 case JCC_LE:
1026 gen_compute_eflags(s);
1027 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1028 reg = cpu_tmp0;
1030 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1031 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1032 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1033 .mask = CC_S | CC_Z };
1034 break;
1036 break;
1039 if (inv) {
1040 cc.cond = tcg_invert_cond(cc.cond);
1042 return cc;
1045 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1047 CCPrepare cc = gen_prepare_cc(s, b, reg);
1049 if (cc.no_setcond) {
1050 if (cc.cond == TCG_COND_EQ) {
1051 tcg_gen_xori_tl(reg, cc.reg, 1);
1052 } else {
1053 tcg_gen_mov_tl(reg, cc.reg);
1055 return;
1058 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1059 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1060 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1061 tcg_gen_andi_tl(reg, reg, 1);
1062 return;
1064 if (cc.mask != -1) {
1065 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1066 cc.reg = reg;
1068 if (cc.use_reg2) {
1069 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1070 } else {
1071 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1075 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1077 gen_setcc1(s, JCC_B << 1, reg);
1080 /* generate a conditional jump to label 'l1' according to jump opcode
1081 value 'b'. In the fast case, T0 is guaranted not to be used. */
1082 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1084 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1086 if (cc.mask != -1) {
1087 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1088 cc.reg = cpu_T[0];
1090 if (cc.use_reg2) {
1091 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1092 } else {
1093 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1097 /* Generate a conditional jump to label 'l1' according to jump opcode
1098 value 'b'. In the fast case, T0 is guaranted not to be used.
1099 A translation block must end soon. */
1100 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1102 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1104 gen_update_cc_op(s);
1105 if (cc.mask != -1) {
1106 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1107 cc.reg = cpu_T[0];
1109 set_cc_op(s, CC_OP_DYNAMIC);
1110 if (cc.use_reg2) {
1111 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1112 } else {
1113 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1117 /* XXX: does not work with gdbstub "ice" single step - not a
1118 serious problem */
1119 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1121 TCGLabel *l1 = gen_new_label();
1122 TCGLabel *l2 = gen_new_label();
1123 gen_op_jnz_ecx(s->aflag, l1);
1124 gen_set_label(l2);
1125 gen_jmp_tb(s, next_eip, 1);
1126 gen_set_label(l1);
1127 return l2;
1130 static inline void gen_stos(DisasContext *s, TCGMemOp ot)
1132 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
1133 gen_string_movl_A0_EDI(s);
1134 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
1135 gen_op_movl_T0_Dshift(ot);
1136 gen_op_add_reg_T0(s->aflag, R_EDI);
1139 static inline void gen_lods(DisasContext *s, TCGMemOp ot)
1141 gen_string_movl_A0_ESI(s);
1142 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1143 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
1144 gen_op_movl_T0_Dshift(ot);
1145 gen_op_add_reg_T0(s->aflag, R_ESI);
1148 static inline void gen_scas(DisasContext *s, TCGMemOp ot)
1150 gen_string_movl_A0_EDI(s);
1151 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
1152 gen_op(s, OP_CMPL, ot, R_EAX);
1153 gen_op_movl_T0_Dshift(ot);
1154 gen_op_add_reg_T0(s->aflag, R_EDI);
1157 static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
1159 gen_string_movl_A0_EDI(s);
1160 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
1161 gen_string_movl_A0_ESI(s);
1162 gen_op(s, OP_CMPL, ot, OR_TMP0);
1163 gen_op_movl_T0_Dshift(ot);
1164 gen_op_add_reg_T0(s->aflag, R_ESI);
1165 gen_op_add_reg_T0(s->aflag, R_EDI);
1168 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
1170 if (s->tb->cflags & CF_USE_ICOUNT) {
1171 gen_io_start();
1173 gen_string_movl_A0_EDI(s);
1174 /* Note: we must do this dummy write first to be restartable in
1175 case of page fault. */
1176 tcg_gen_movi_tl(cpu_T[0], 0);
1177 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
1178 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1179 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1180 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
1181 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
1182 gen_op_movl_T0_Dshift(ot);
1183 gen_op_add_reg_T0(s->aflag, R_EDI);
1184 if (s->tb->cflags & CF_USE_ICOUNT) {
1185 gen_io_end();
1189 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
1191 if (s->tb->cflags & CF_USE_ICOUNT) {
1192 gen_io_start();
1194 gen_string_movl_A0_ESI(s);
1195 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1197 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1198 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1199 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
1200 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1202 gen_op_movl_T0_Dshift(ot);
1203 gen_op_add_reg_T0(s->aflag, R_ESI);
1204 if (s->tb->cflags & CF_USE_ICOUNT) {
1205 gen_io_end();
1209 /* same method as Valgrind : we generate jumps to current or next
1210 instruction */
1211 #define GEN_REPZ(op) \
1212 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1213 target_ulong cur_eip, target_ulong next_eip) \
1215 TCGLabel *l2; \
1216 gen_update_cc_op(s); \
1217 l2 = gen_jz_ecx_string(s, next_eip); \
1218 gen_ ## op(s, ot); \
1219 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1220 /* a loop would cause two single step exceptions if ECX = 1 \
1221 before rep string_insn */ \
1222 if (s->repz_opt) \
1223 gen_op_jz_ecx(s->aflag, l2); \
1224 gen_jmp(s, cur_eip); \
1227 #define GEN_REPZ2(op) \
1228 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1229 target_ulong cur_eip, \
1230 target_ulong next_eip, \
1231 int nz) \
1233 TCGLabel *l2; \
1234 gen_update_cc_op(s); \
1235 l2 = gen_jz_ecx_string(s, next_eip); \
1236 gen_ ## op(s, ot); \
1237 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1238 gen_update_cc_op(s); \
1239 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1240 if (s->repz_opt) \
1241 gen_op_jz_ecx(s->aflag, l2); \
1242 gen_jmp(s, cur_eip); \
1245 GEN_REPZ(movs)
1246 GEN_REPZ(stos)
1247 GEN_REPZ(lods)
1248 GEN_REPZ(ins)
1249 GEN_REPZ(outs)
1250 GEN_REPZ2(scas)
1251 GEN_REPZ2(cmps)
1253 static void gen_helper_fp_arith_ST0_FT0(int op)
1255 switch (op) {
1256 case 0:
1257 gen_helper_fadd_ST0_FT0(cpu_env);
1258 break;
1259 case 1:
1260 gen_helper_fmul_ST0_FT0(cpu_env);
1261 break;
1262 case 2:
1263 gen_helper_fcom_ST0_FT0(cpu_env);
1264 break;
1265 case 3:
1266 gen_helper_fcom_ST0_FT0(cpu_env);
1267 break;
1268 case 4:
1269 gen_helper_fsub_ST0_FT0(cpu_env);
1270 break;
1271 case 5:
1272 gen_helper_fsubr_ST0_FT0(cpu_env);
1273 break;
1274 case 6:
1275 gen_helper_fdiv_ST0_FT0(cpu_env);
1276 break;
1277 case 7:
1278 gen_helper_fdivr_ST0_FT0(cpu_env);
1279 break;
1283 /* NOTE the exception in "r" op ordering */
1284 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1286 TCGv_i32 tmp = tcg_const_i32(opreg);
1287 switch (op) {
1288 case 0:
1289 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1290 break;
1291 case 1:
1292 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1293 break;
1294 case 4:
1295 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1296 break;
1297 case 5:
1298 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1299 break;
1300 case 6:
1301 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1302 break;
1303 case 7:
1304 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1305 break;
1309 /* if d == OR_TMP0, it means memory operand (address in A0) */
1310 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
1312 if (d != OR_TMP0) {
1313 gen_op_mov_v_reg(ot, cpu_T[0], d);
1314 } else {
1315 gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
1317 switch(op) {
1318 case OP_ADCL:
1319 gen_compute_eflags_c(s1, cpu_tmp4);
1320 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1321 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1322 gen_op_st_rm_T0_A0(s1, ot, d);
1323 gen_op_update3_cc(cpu_tmp4);
1324 set_cc_op(s1, CC_OP_ADCB + ot);
1325 break;
1326 case OP_SBBL:
1327 gen_compute_eflags_c(s1, cpu_tmp4);
1328 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1329 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1330 gen_op_st_rm_T0_A0(s1, ot, d);
1331 gen_op_update3_cc(cpu_tmp4);
1332 set_cc_op(s1, CC_OP_SBBB + ot);
1333 break;
1334 case OP_ADDL:
1335 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1336 gen_op_st_rm_T0_A0(s1, ot, d);
1337 gen_op_update2_cc();
1338 set_cc_op(s1, CC_OP_ADDB + ot);
1339 break;
1340 case OP_SUBL:
1341 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1342 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1343 gen_op_st_rm_T0_A0(s1, ot, d);
1344 gen_op_update2_cc();
1345 set_cc_op(s1, CC_OP_SUBB + ot);
1346 break;
1347 default:
1348 case OP_ANDL:
1349 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1350 gen_op_st_rm_T0_A0(s1, ot, d);
1351 gen_op_update1_cc();
1352 set_cc_op(s1, CC_OP_LOGICB + ot);
1353 break;
1354 case OP_ORL:
1355 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1356 gen_op_st_rm_T0_A0(s1, ot, d);
1357 gen_op_update1_cc();
1358 set_cc_op(s1, CC_OP_LOGICB + ot);
1359 break;
1360 case OP_XORL:
1361 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1362 gen_op_st_rm_T0_A0(s1, ot, d);
1363 gen_op_update1_cc();
1364 set_cc_op(s1, CC_OP_LOGICB + ot);
1365 break;
1366 case OP_CMPL:
1367 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
1368 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1369 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
1370 set_cc_op(s1, CC_OP_SUBB + ot);
1371 break;
1375 /* if d == OR_TMP0, it means memory operand (address in A0) */
1376 static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
1378 if (d != OR_TMP0) {
1379 gen_op_mov_v_reg(ot, cpu_T[0], d);
1380 } else {
1381 gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
1383 gen_compute_eflags_c(s1, cpu_cc_src);
1384 if (c > 0) {
1385 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
1386 set_cc_op(s1, CC_OP_INCB + ot);
1387 } else {
1388 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
1389 set_cc_op(s1, CC_OP_DECB + ot);
1391 gen_op_st_rm_T0_A0(s1, ot, d);
1392 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1395 static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
1396 TCGv shm1, TCGv count, bool is_right)
1398 TCGv_i32 z32, s32, oldop;
1399 TCGv z_tl;
1401 /* Store the results into the CC variables. If we know that the
1402 variable must be dead, store unconditionally. Otherwise we'll
1403 need to not disrupt the current contents. */
1404 z_tl = tcg_const_tl(0);
1405 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1406 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1407 result, cpu_cc_dst);
1408 } else {
1409 tcg_gen_mov_tl(cpu_cc_dst, result);
1411 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1412 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1413 shm1, cpu_cc_src);
1414 } else {
1415 tcg_gen_mov_tl(cpu_cc_src, shm1);
1417 tcg_temp_free(z_tl);
1419 /* Get the two potential CC_OP values into temporaries. */
1420 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1421 if (s->cc_op == CC_OP_DYNAMIC) {
1422 oldop = cpu_cc_op;
1423 } else {
1424 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1425 oldop = cpu_tmp3_i32;
1428 /* Conditionally store the CC_OP value. */
1429 z32 = tcg_const_i32(0);
1430 s32 = tcg_temp_new_i32();
1431 tcg_gen_trunc_tl_i32(s32, count);
1432 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1433 tcg_temp_free_i32(z32);
1434 tcg_temp_free_i32(s32);
1436 /* The CC_OP value is no longer predictable. */
1437 set_cc_op(s, CC_OP_DYNAMIC);
1440 static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1441 int is_right, int is_arith)
1443 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1445 /* load */
1446 if (op1 == OR_TMP0) {
1447 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1448 } else {
1449 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1452 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1453 tcg_gen_subi_tl(cpu_tmp0, cpu_T[1], 1);
1455 if (is_right) {
1456 if (is_arith) {
1457 gen_exts(ot, cpu_T[0]);
1458 tcg_gen_sar_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1459 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1460 } else {
1461 gen_extu(ot, cpu_T[0]);
1462 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1463 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1465 } else {
1466 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1467 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1470 /* store */
1471 gen_op_st_rm_T0_A0(s, ot, op1);
1473 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, cpu_T[1], is_right);
1476 static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1477 int is_right, int is_arith)
1479 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1481 /* load */
1482 if (op1 == OR_TMP0)
1483 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1484 else
1485 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1487 op2 &= mask;
1488 if (op2 != 0) {
1489 if (is_right) {
1490 if (is_arith) {
1491 gen_exts(ot, cpu_T[0]);
1492 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1493 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
1494 } else {
1495 gen_extu(ot, cpu_T[0]);
1496 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1497 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
1499 } else {
1500 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1501 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
1505 /* store */
1506 gen_op_st_rm_T0_A0(s, ot, op1);
1508 /* update eflags if non zero shift */
1509 if (op2 != 0) {
1510 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1511 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1512 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1516 static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
1518 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1519 TCGv_i32 t0, t1;
1521 /* load */
1522 if (op1 == OR_TMP0) {
1523 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1524 } else {
1525 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1528 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1530 switch (ot) {
1531 case MO_8:
1532 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1533 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
1534 tcg_gen_muli_tl(cpu_T[0], cpu_T[0], 0x01010101);
1535 goto do_long;
1536 case MO_16:
1537 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1538 tcg_gen_deposit_tl(cpu_T[0], cpu_T[0], cpu_T[0], 16, 16);
1539 goto do_long;
1540 do_long:
1541 #ifdef TARGET_X86_64
1542 case MO_32:
1543 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1544 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
1545 if (is_right) {
1546 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1547 } else {
1548 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1550 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1551 break;
1552 #endif
1553 default:
1554 if (is_right) {
1555 tcg_gen_rotr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1556 } else {
1557 tcg_gen_rotl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1559 break;
1562 /* store */
1563 gen_op_st_rm_T0_A0(s, ot, op1);
1565 /* We'll need the flags computed into CC_SRC. */
1566 gen_compute_eflags(s);
1568 /* The value that was "rotated out" is now present at the other end
1569 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1570 since we've computed the flags into CC_SRC, these variables are
1571 currently dead. */
1572 if (is_right) {
1573 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1574 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1575 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1576 } else {
1577 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1578 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
1580 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1581 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1583 /* Now conditionally store the new CC_OP value. If the shift count
1584 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1585 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1586 exactly as we computed above. */
1587 t0 = tcg_const_i32(0);
1588 t1 = tcg_temp_new_i32();
1589 tcg_gen_trunc_tl_i32(t1, cpu_T[1]);
1590 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1591 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1592 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1593 cpu_tmp2_i32, cpu_tmp3_i32);
1594 tcg_temp_free_i32(t0);
1595 tcg_temp_free_i32(t1);
1597 /* The CC_OP value is no longer predictable. */
1598 set_cc_op(s, CC_OP_DYNAMIC);
1601 static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1602 int is_right)
1604 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1605 int shift;
1607 /* load */
1608 if (op1 == OR_TMP0) {
1609 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1610 } else {
1611 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1614 op2 &= mask;
1615 if (op2 != 0) {
1616 switch (ot) {
1617 #ifdef TARGET_X86_64
1618 case MO_32:
1619 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1620 if (is_right) {
1621 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1622 } else {
1623 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1625 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1626 break;
1627 #endif
1628 default:
1629 if (is_right) {
1630 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], op2);
1631 } else {
1632 tcg_gen_rotli_tl(cpu_T[0], cpu_T[0], op2);
1634 break;
1635 case MO_8:
1636 mask = 7;
1637 goto do_shifts;
1638 case MO_16:
1639 mask = 15;
1640 do_shifts:
1641 shift = op2 & mask;
1642 if (is_right) {
1643 shift = mask + 1 - shift;
1645 gen_extu(ot, cpu_T[0]);
1646 tcg_gen_shli_tl(cpu_tmp0, cpu_T[0], shift);
1647 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], mask + 1 - shift);
1648 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
1649 break;
1653 /* store */
1654 gen_op_st_rm_T0_A0(s, ot, op1);
1656 if (op2 != 0) {
1657 /* Compute the flags into CC_SRC. */
1658 gen_compute_eflags(s);
1660 /* The value that was "rotated out" is now present at the other end
1661 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1662 since we've computed the flags into CC_SRC, these variables are
1663 currently dead. */
1664 if (is_right) {
1665 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1666 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1667 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1668 } else {
1669 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1670 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
1672 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1673 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1674 set_cc_op(s, CC_OP_ADCOX);
1678 /* XXX: add faster immediate = 1 case */
1679 static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1680 int is_right)
1682 gen_compute_eflags(s);
1683 assert(s->cc_op == CC_OP_EFLAGS);
1685 /* load */
1686 if (op1 == OR_TMP0)
1687 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1688 else
1689 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1691 if (is_right) {
1692 switch (ot) {
1693 case MO_8:
1694 gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1695 break;
1696 case MO_16:
1697 gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1698 break;
1699 case MO_32:
1700 gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1701 break;
1702 #ifdef TARGET_X86_64
1703 case MO_64:
1704 gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1705 break;
1706 #endif
1707 default:
1708 tcg_abort();
1710 } else {
1711 switch (ot) {
1712 case MO_8:
1713 gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1714 break;
1715 case MO_16:
1716 gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1717 break;
1718 case MO_32:
1719 gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1720 break;
1721 #ifdef TARGET_X86_64
1722 case MO_64:
1723 gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1724 break;
1725 #endif
1726 default:
1727 tcg_abort();
1730 /* store */
1731 gen_op_st_rm_T0_A0(s, ot, op1);
1734 /* XXX: add faster immediate case */
1735 static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1736 bool is_right, TCGv count_in)
1738 target_ulong mask = (ot == MO_64 ? 63 : 31);
1739 TCGv count;
1741 /* load */
1742 if (op1 == OR_TMP0) {
1743 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1744 } else {
1745 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1748 count = tcg_temp_new();
1749 tcg_gen_andi_tl(count, count_in, mask);
1751 switch (ot) {
1752 case MO_16:
1753 /* Note: we implement the Intel behaviour for shift count > 16.
1754 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1755 portion by constructing it as a 32-bit value. */
1756 if (is_right) {
1757 tcg_gen_deposit_tl(cpu_tmp0, cpu_T[0], cpu_T[1], 16, 16);
1758 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1759 tcg_gen_mov_tl(cpu_T[0], cpu_tmp0);
1760 } else {
1761 tcg_gen_deposit_tl(cpu_T[1], cpu_T[0], cpu_T[1], 16, 16);
1763 /* FALLTHRU */
1764 #ifdef TARGET_X86_64
1765 case MO_32:
1766 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1767 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1768 if (is_right) {
1769 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
1770 tcg_gen_shr_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1771 tcg_gen_shr_i64(cpu_T[0], cpu_T[0], count);
1772 } else {
1773 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[1], cpu_T[0]);
1774 tcg_gen_shl_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1775 tcg_gen_shl_i64(cpu_T[0], cpu_T[0], count);
1776 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1777 tcg_gen_shri_i64(cpu_T[0], cpu_T[0], 32);
1779 break;
1780 #endif
1781 default:
1782 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1783 if (is_right) {
1784 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1786 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1787 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], count);
1788 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
1789 } else {
1790 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1791 if (ot == MO_16) {
1792 /* Only needed if count > 16, for Intel behaviour. */
1793 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1794 tcg_gen_shr_tl(cpu_tmp4, cpu_T[1], cpu_tmp4);
1795 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1798 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1799 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], count);
1800 tcg_gen_shr_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
1802 tcg_gen_movi_tl(cpu_tmp4, 0);
1803 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[1], count, cpu_tmp4,
1804 cpu_tmp4, cpu_T[1]);
1805 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1806 break;
1809 /* store */
1810 gen_op_st_rm_T0_A0(s, ot, op1);
1812 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, count, is_right);
1813 tcg_temp_free(count);
1816 static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
1818 if (s != OR_TMP1)
1819 gen_op_mov_v_reg(ot, cpu_T[1], s);
1820 switch(op) {
1821 case OP_ROL:
1822 gen_rot_rm_T1(s1, ot, d, 0);
1823 break;
1824 case OP_ROR:
1825 gen_rot_rm_T1(s1, ot, d, 1);
1826 break;
1827 case OP_SHL:
1828 case OP_SHL1:
1829 gen_shift_rm_T1(s1, ot, d, 0, 0);
1830 break;
1831 case OP_SHR:
1832 gen_shift_rm_T1(s1, ot, d, 1, 0);
1833 break;
1834 case OP_SAR:
1835 gen_shift_rm_T1(s1, ot, d, 1, 1);
1836 break;
1837 case OP_RCL:
1838 gen_rotc_rm_T1(s1, ot, d, 0);
1839 break;
1840 case OP_RCR:
1841 gen_rotc_rm_T1(s1, ot, d, 1);
1842 break;
1846 static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
1848 switch(op) {
1849 case OP_ROL:
1850 gen_rot_rm_im(s1, ot, d, c, 0);
1851 break;
1852 case OP_ROR:
1853 gen_rot_rm_im(s1, ot, d, c, 1);
1854 break;
1855 case OP_SHL:
1856 case OP_SHL1:
1857 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1858 break;
1859 case OP_SHR:
1860 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1861 break;
1862 case OP_SAR:
1863 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1864 break;
1865 default:
1866 /* currently not optimized */
1867 tcg_gen_movi_tl(cpu_T[1], c);
1868 gen_shift(s1, op, ot, d, OR_TMP1);
1869 break;
1873 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
1875 target_long disp;
1876 int havesib;
1877 int base;
1878 int index;
1879 int scale;
1880 int mod, rm, code, override, must_add_seg;
1881 TCGv sum;
1883 override = s->override;
1884 must_add_seg = s->addseg;
1885 if (override >= 0)
1886 must_add_seg = 1;
1887 mod = (modrm >> 6) & 3;
1888 rm = modrm & 7;
1890 switch (s->aflag) {
1891 case MO_64:
1892 case MO_32:
1893 havesib = 0;
1894 base = rm;
1895 index = -1;
1896 scale = 0;
1898 if (base == 4) {
1899 havesib = 1;
1900 code = cpu_ldub_code(env, s->pc++);
1901 scale = (code >> 6) & 3;
1902 index = ((code >> 3) & 7) | REX_X(s);
1903 if (index == 4) {
1904 index = -1; /* no index */
1906 base = (code & 7);
1908 base |= REX_B(s);
1910 switch (mod) {
1911 case 0:
1912 if ((base & 7) == 5) {
1913 base = -1;
1914 disp = (int32_t)cpu_ldl_code(env, s->pc);
1915 s->pc += 4;
1916 if (CODE64(s) && !havesib) {
1917 disp += s->pc + s->rip_offset;
1919 } else {
1920 disp = 0;
1922 break;
1923 case 1:
1924 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1925 break;
1926 default:
1927 case 2:
1928 disp = (int32_t)cpu_ldl_code(env, s->pc);
1929 s->pc += 4;
1930 break;
1933 /* For correct popl handling with esp. */
1934 if (base == R_ESP && s->popl_esp_hack) {
1935 disp += s->popl_esp_hack;
1938 /* Compute the address, with a minimum number of TCG ops. */
1939 TCGV_UNUSED(sum);
1940 if (index >= 0) {
1941 if (scale == 0) {
1942 sum = cpu_regs[index];
1943 } else {
1944 tcg_gen_shli_tl(cpu_A0, cpu_regs[index], scale);
1945 sum = cpu_A0;
1947 if (base >= 0) {
1948 tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]);
1949 sum = cpu_A0;
1951 } else if (base >= 0) {
1952 sum = cpu_regs[base];
1954 if (TCGV_IS_UNUSED(sum)) {
1955 tcg_gen_movi_tl(cpu_A0, disp);
1956 } else {
1957 tcg_gen_addi_tl(cpu_A0, sum, disp);
1960 if (must_add_seg) {
1961 if (override < 0) {
1962 if (base == R_EBP || base == R_ESP) {
1963 override = R_SS;
1964 } else {
1965 override = R_DS;
1969 tcg_gen_ld_tl(cpu_tmp0, cpu_env,
1970 offsetof(CPUX86State, segs[override].base));
1971 if (CODE64(s)) {
1972 if (s->aflag == MO_32) {
1973 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
1975 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
1976 return;
1979 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
1982 if (s->aflag == MO_32) {
1983 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
1985 break;
1987 case MO_16:
1988 switch (mod) {
1989 case 0:
1990 if (rm == 6) {
1991 disp = cpu_lduw_code(env, s->pc);
1992 s->pc += 2;
1993 tcg_gen_movi_tl(cpu_A0, disp);
1994 rm = 0; /* avoid SS override */
1995 goto no_rm;
1996 } else {
1997 disp = 0;
1999 break;
2000 case 1:
2001 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2002 break;
2003 default:
2004 case 2:
2005 disp = (int16_t)cpu_lduw_code(env, s->pc);
2006 s->pc += 2;
2007 break;
2010 sum = cpu_A0;
2011 switch (rm) {
2012 case 0:
2013 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_ESI]);
2014 break;
2015 case 1:
2016 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_EDI]);
2017 break;
2018 case 2:
2019 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_ESI]);
2020 break;
2021 case 3:
2022 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_EDI]);
2023 break;
2024 case 4:
2025 sum = cpu_regs[R_ESI];
2026 break;
2027 case 5:
2028 sum = cpu_regs[R_EDI];
2029 break;
2030 case 6:
2031 sum = cpu_regs[R_EBP];
2032 break;
2033 default:
2034 case 7:
2035 sum = cpu_regs[R_EBX];
2036 break;
2038 tcg_gen_addi_tl(cpu_A0, sum, disp);
2039 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2040 no_rm:
2041 if (must_add_seg) {
2042 if (override < 0) {
2043 if (rm == 2 || rm == 3 || rm == 6) {
2044 override = R_SS;
2045 } else {
2046 override = R_DS;
2049 gen_op_addl_A0_seg(s, override);
2051 break;
2053 default:
2054 tcg_abort();
2058 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2060 int mod, rm, base, code;
2062 mod = (modrm >> 6) & 3;
2063 if (mod == 3)
2064 return;
2065 rm = modrm & 7;
2067 switch (s->aflag) {
2068 case MO_64:
2069 case MO_32:
2070 base = rm;
2072 if (base == 4) {
2073 code = cpu_ldub_code(env, s->pc++);
2074 base = (code & 7);
2077 switch (mod) {
2078 case 0:
2079 if (base == 5) {
2080 s->pc += 4;
2082 break;
2083 case 1:
2084 s->pc++;
2085 break;
2086 default:
2087 case 2:
2088 s->pc += 4;
2089 break;
2091 break;
2093 case MO_16:
2094 switch (mod) {
2095 case 0:
2096 if (rm == 6) {
2097 s->pc += 2;
2099 break;
2100 case 1:
2101 s->pc++;
2102 break;
2103 default:
2104 case 2:
2105 s->pc += 2;
2106 break;
2108 break;
2110 default:
2111 tcg_abort();
2115 /* used for LEA and MOV AX, mem */
2116 static void gen_add_A0_ds_seg(DisasContext *s)
2118 int override, must_add_seg;
2119 must_add_seg = s->addseg;
2120 override = R_DS;
2121 if (s->override >= 0) {
2122 override = s->override;
2123 must_add_seg = 1;
2125 if (must_add_seg) {
2126 #ifdef TARGET_X86_64
2127 if (CODE64(s)) {
2128 gen_op_addq_A0_seg(override);
2129 } else
2130 #endif
2132 gen_op_addl_A0_seg(s, override);
2137 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2138 OR_TMP0 */
2139 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2140 TCGMemOp ot, int reg, int is_store)
2142 int mod, rm;
2144 mod = (modrm >> 6) & 3;
2145 rm = (modrm & 7) | REX_B(s);
2146 if (mod == 3) {
2147 if (is_store) {
2148 if (reg != OR_TMP0)
2149 gen_op_mov_v_reg(ot, cpu_T[0], reg);
2150 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2151 } else {
2152 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2153 if (reg != OR_TMP0)
2154 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2156 } else {
2157 gen_lea_modrm(env, s, modrm);
2158 if (is_store) {
2159 if (reg != OR_TMP0)
2160 gen_op_mov_v_reg(ot, cpu_T[0], reg);
2161 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2162 } else {
2163 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2164 if (reg != OR_TMP0)
2165 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2170 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
2172 uint32_t ret;
2174 switch (ot) {
2175 case MO_8:
2176 ret = cpu_ldub_code(env, s->pc);
2177 s->pc++;
2178 break;
2179 case MO_16:
2180 ret = cpu_lduw_code(env, s->pc);
2181 s->pc += 2;
2182 break;
2183 case MO_32:
2184 #ifdef TARGET_X86_64
2185 case MO_64:
2186 #endif
2187 ret = cpu_ldl_code(env, s->pc);
2188 s->pc += 4;
2189 break;
2190 default:
2191 tcg_abort();
2193 return ret;
2196 static inline int insn_const_size(TCGMemOp ot)
2198 if (ot <= MO_32) {
2199 return 1 << ot;
2200 } else {
2201 return 4;
2205 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2207 TranslationBlock *tb;
2208 target_ulong pc;
2210 pc = s->cs_base + eip;
2211 tb = s->tb;
2212 /* NOTE: we handle the case where the TB spans two pages here */
2213 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2214 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2215 /* jump to same page: we can use a direct jump */
2216 tcg_gen_goto_tb(tb_num);
2217 gen_jmp_im(eip);
2218 tcg_gen_exit_tb((uintptr_t)tb + tb_num);
2219 } else {
2220 /* jump to another page: currently not optimized */
2221 gen_jmp_im(eip);
2222 gen_eob(s);
2226 static inline void gen_jcc(DisasContext *s, int b,
2227 target_ulong val, target_ulong next_eip)
2229 TCGLabel *l1, *l2;
2231 if (s->jmp_opt) {
2232 l1 = gen_new_label();
2233 gen_jcc1(s, b, l1);
2235 gen_goto_tb(s, 0, next_eip);
2237 gen_set_label(l1);
2238 gen_goto_tb(s, 1, val);
2239 s->is_jmp = DISAS_TB_JUMP;
2240 } else {
2241 l1 = gen_new_label();
2242 l2 = gen_new_label();
2243 gen_jcc1(s, b, l1);
2245 gen_jmp_im(next_eip);
2246 tcg_gen_br(l2);
2248 gen_set_label(l1);
2249 gen_jmp_im(val);
2250 gen_set_label(l2);
2251 gen_eob(s);
2255 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
2256 int modrm, int reg)
2258 CCPrepare cc;
2260 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2262 cc = gen_prepare_cc(s, b, cpu_T[1]);
2263 if (cc.mask != -1) {
2264 TCGv t0 = tcg_temp_new();
2265 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2266 cc.reg = t0;
2268 if (!cc.use_reg2) {
2269 cc.reg2 = tcg_const_tl(cc.imm);
2272 tcg_gen_movcond_tl(cc.cond, cpu_T[0], cc.reg, cc.reg2,
2273 cpu_T[0], cpu_regs[reg]);
2274 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2276 if (cc.mask != -1) {
2277 tcg_temp_free(cc.reg);
2279 if (!cc.use_reg2) {
2280 tcg_temp_free(cc.reg2);
2284 static inline void gen_op_movl_T0_seg(int seg_reg)
2286 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
2287 offsetof(CPUX86State,segs[seg_reg].selector));
2290 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2292 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
2293 tcg_gen_st32_tl(cpu_T[0], cpu_env,
2294 offsetof(CPUX86State,segs[seg_reg].selector));
2295 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
2296 tcg_gen_st_tl(cpu_T[0], cpu_env,
2297 offsetof(CPUX86State,segs[seg_reg].base));
2300 /* move T0 to seg_reg and compute if the CPU state may change. Never
2301 call this function with seg_reg == R_CS */
2302 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2304 if (s->pe && !s->vm86) {
2305 /* XXX: optimize by finding processor state dynamically */
2306 gen_update_cc_op(s);
2307 gen_jmp_im(cur_eip);
2308 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2309 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
2310 /* abort translation because the addseg value may change or
2311 because ss32 may change. For R_SS, translation must always
2312 stop as a special handling must be done to disable hardware
2313 interrupts for the next instruction */
2314 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
2315 s->is_jmp = DISAS_TB_JUMP;
2316 } else {
2317 gen_op_movl_seg_T0_vm(seg_reg);
2318 if (seg_reg == R_SS)
2319 s->is_jmp = DISAS_TB_JUMP;
2323 static inline int svm_is_rep(int prefixes)
2325 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2328 static inline void
2329 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2330 uint32_t type, uint64_t param)
2332 /* no SVM activated; fast case */
2333 if (likely(!(s->flags & HF_SVMI_MASK)))
2334 return;
2335 gen_update_cc_op(s);
2336 gen_jmp_im(pc_start - s->cs_base);
2337 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2338 tcg_const_i64(param));
2341 static inline void
2342 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2344 gen_svm_check_intercept_param(s, pc_start, type, 0);
2347 static inline void gen_stack_update(DisasContext *s, int addend)
2349 #ifdef TARGET_X86_64
2350 if (CODE64(s)) {
2351 gen_op_add_reg_im(MO_64, R_ESP, addend);
2352 } else
2353 #endif
2354 if (s->ss32) {
2355 gen_op_add_reg_im(MO_32, R_ESP, addend);
2356 } else {
2357 gen_op_add_reg_im(MO_16, R_ESP, addend);
2361 /* Generate a push. It depends on ss32, addseg and dflag. */
2362 static void gen_push_v(DisasContext *s, TCGv val)
2364 TCGMemOp a_ot, d_ot = mo_pushpop(s, s->dflag);
2365 int size = 1 << d_ot;
2366 TCGv new_esp = cpu_A0;
2368 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
2370 if (CODE64(s)) {
2371 a_ot = MO_64;
2372 } else if (s->ss32) {
2373 a_ot = MO_32;
2374 if (s->addseg) {
2375 new_esp = cpu_tmp4;
2376 tcg_gen_mov_tl(new_esp, cpu_A0);
2377 gen_op_addl_A0_seg(s, R_SS);
2378 } else {
2379 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
2381 } else {
2382 a_ot = MO_16;
2383 new_esp = cpu_tmp4;
2384 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2385 tcg_gen_mov_tl(new_esp, cpu_A0);
2386 gen_op_addl_A0_seg(s, R_SS);
2389 gen_op_st_v(s, d_ot, val, cpu_A0);
2390 gen_op_mov_reg_v(a_ot, R_ESP, new_esp);
2393 /* two step pop is necessary for precise exceptions */
2394 static TCGMemOp gen_pop_T0(DisasContext *s)
2396 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2397 TCGv addr = cpu_A0;
2399 if (CODE64(s)) {
2400 addr = cpu_regs[R_ESP];
2401 } else if (!s->ss32) {
2402 tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESP]);
2403 gen_op_addl_A0_seg(s, R_SS);
2404 } else if (s->addseg) {
2405 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_ESP]);
2406 gen_op_addl_A0_seg(s, R_SS);
2407 } else {
2408 tcg_gen_ext32u_tl(cpu_A0, cpu_regs[R_ESP]);
2411 gen_op_ld_v(s, d_ot, cpu_T[0], addr);
2412 return d_ot;
2415 static void gen_pop_update(DisasContext *s, TCGMemOp ot)
2417 gen_stack_update(s, 1 << ot);
2420 static void gen_stack_A0(DisasContext *s)
2422 gen_op_movl_A0_reg(R_ESP);
2423 if (!s->ss32)
2424 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2425 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2426 if (s->addseg)
2427 gen_op_addl_A0_seg(s, R_SS);
2430 /* NOTE: wrap around in 16 bit not fully handled */
2431 static void gen_pusha(DisasContext *s)
2433 int i;
2434 gen_op_movl_A0_reg(R_ESP);
2435 gen_op_addl_A0_im(-8 << s->dflag);
2436 if (!s->ss32)
2437 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2438 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2439 if (s->addseg)
2440 gen_op_addl_A0_seg(s, R_SS);
2441 for(i = 0;i < 8; i++) {
2442 gen_op_mov_v_reg(MO_32, cpu_T[0], 7 - i);
2443 gen_op_st_v(s, s->dflag, cpu_T[0], cpu_A0);
2444 gen_op_addl_A0_im(1 << s->dflag);
2446 gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
2449 /* NOTE: wrap around in 16 bit not fully handled */
2450 static void gen_popa(DisasContext *s)
2452 int i;
2453 gen_op_movl_A0_reg(R_ESP);
2454 if (!s->ss32)
2455 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2456 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2457 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 8 << s->dflag);
2458 if (s->addseg)
2459 gen_op_addl_A0_seg(s, R_SS);
2460 for(i = 0;i < 8; i++) {
2461 /* ESP is not reloaded */
2462 if (i != 3) {
2463 gen_op_ld_v(s, s->dflag, cpu_T[0], cpu_A0);
2464 gen_op_mov_reg_v(s->dflag, 7 - i, cpu_T[0]);
2466 gen_op_addl_A0_im(1 << s->dflag);
2468 gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
2471 static void gen_enter(DisasContext *s, int esp_addend, int level)
2473 TCGMemOp ot = mo_pushpop(s, s->dflag);
2474 int opsize = 1 << ot;
2476 level &= 0x1f;
2477 #ifdef TARGET_X86_64
2478 if (CODE64(s)) {
2479 gen_op_movl_A0_reg(R_ESP);
2480 gen_op_addq_A0_im(-opsize);
2481 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2483 /* push bp */
2484 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
2485 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2486 if (level) {
2487 /* XXX: must save state */
2488 gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
2489 tcg_const_i32((ot == MO_64)),
2490 cpu_T[1]);
2492 gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]);
2493 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2494 gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[1]);
2495 } else
2496 #endif
2498 gen_op_movl_A0_reg(R_ESP);
2499 gen_op_addl_A0_im(-opsize);
2500 if (!s->ss32)
2501 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2502 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2503 if (s->addseg)
2504 gen_op_addl_A0_seg(s, R_SS);
2505 /* push bp */
2506 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
2507 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2508 if (level) {
2509 /* XXX: must save state */
2510 gen_helper_enter_level(cpu_env, tcg_const_i32(level),
2511 tcg_const_i32(s->dflag - 1),
2512 cpu_T[1]);
2514 gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]);
2515 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2516 gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
2520 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2522 gen_update_cc_op(s);
2523 gen_jmp_im(cur_eip);
2524 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
2525 s->is_jmp = DISAS_TB_JUMP;
2528 /* an interrupt is different from an exception because of the
2529 privilege checks */
2530 static void gen_interrupt(DisasContext *s, int intno,
2531 target_ulong cur_eip, target_ulong next_eip)
2533 gen_update_cc_op(s);
2534 gen_jmp_im(cur_eip);
2535 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2536 tcg_const_i32(next_eip - cur_eip));
2537 s->is_jmp = DISAS_TB_JUMP;
2540 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2542 gen_update_cc_op(s);
2543 gen_jmp_im(cur_eip);
2544 gen_helper_debug(cpu_env);
2545 s->is_jmp = DISAS_TB_JUMP;
2548 /* generate a generic end of block. Trace exception is also generated
2549 if needed */
2550 static void gen_eob(DisasContext *s)
2552 gen_update_cc_op(s);
2553 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2554 gen_helper_reset_inhibit_irq(cpu_env);
2556 if (s->tb->flags & HF_RF_MASK) {
2557 gen_helper_reset_rf(cpu_env);
2559 if (s->singlestep_enabled) {
2560 gen_helper_debug(cpu_env);
2561 } else if (s->tf) {
2562 gen_helper_single_step(cpu_env);
2563 } else {
2564 tcg_gen_exit_tb(0);
2566 s->is_jmp = DISAS_TB_JUMP;
2569 /* generate a jump to eip. No segment change must happen before as a
2570 direct call to the next block may occur */
2571 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2573 gen_update_cc_op(s);
2574 set_cc_op(s, CC_OP_DYNAMIC);
2575 if (s->jmp_opt) {
2576 gen_goto_tb(s, tb_num, eip);
2577 s->is_jmp = DISAS_TB_JUMP;
2578 } else {
2579 gen_jmp_im(eip);
2580 gen_eob(s);
2584 static void gen_jmp(DisasContext *s, target_ulong eip)
2586 gen_jmp_tb(s, eip, 0);
2589 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2591 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2592 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2595 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2597 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2598 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2601 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2603 int mem_index = s->mem_index;
2604 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2605 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2606 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2607 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2608 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2611 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2613 int mem_index = s->mem_index;
2614 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2615 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2616 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2617 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2618 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2621 static inline void gen_op_movo(int d_offset, int s_offset)
2623 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(0)));
2624 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(0)));
2625 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(1)));
2626 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(1)));
2629 static inline void gen_op_movq(int d_offset, int s_offset)
2631 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2632 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2635 static inline void gen_op_movl(int d_offset, int s_offset)
2637 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2638 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2641 static inline void gen_op_movq_env_0(int d_offset)
2643 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2644 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2647 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2648 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2649 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2650 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2651 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2652 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2653 TCGv_i32 val);
2654 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2655 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2656 TCGv val);
2658 #define SSE_SPECIAL ((void *)1)
2659 #define SSE_DUMMY ((void *)2)
2661 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2662 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2663 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2665 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2666 /* 3DNow! extensions */
2667 [0x0e] = { SSE_DUMMY }, /* femms */
2668 [0x0f] = { SSE_DUMMY }, /* pf... */
2669 /* pure SSE operations */
2670 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2671 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2672 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2673 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2674 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2675 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2676 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2677 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2679 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2680 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2681 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2682 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2683 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2684 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2685 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2686 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2687 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2688 [0x51] = SSE_FOP(sqrt),
2689 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2690 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2691 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2692 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2693 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2694 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2695 [0x58] = SSE_FOP(add),
2696 [0x59] = SSE_FOP(mul),
2697 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2698 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2699 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2700 [0x5c] = SSE_FOP(sub),
2701 [0x5d] = SSE_FOP(min),
2702 [0x5e] = SSE_FOP(div),
2703 [0x5f] = SSE_FOP(max),
2705 [0xc2] = SSE_FOP(cmpeq),
2706 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2707 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2709 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2710 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2711 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2713 /* MMX ops and their SSE extensions */
2714 [0x60] = MMX_OP2(punpcklbw),
2715 [0x61] = MMX_OP2(punpcklwd),
2716 [0x62] = MMX_OP2(punpckldq),
2717 [0x63] = MMX_OP2(packsswb),
2718 [0x64] = MMX_OP2(pcmpgtb),
2719 [0x65] = MMX_OP2(pcmpgtw),
2720 [0x66] = MMX_OP2(pcmpgtl),
2721 [0x67] = MMX_OP2(packuswb),
2722 [0x68] = MMX_OP2(punpckhbw),
2723 [0x69] = MMX_OP2(punpckhwd),
2724 [0x6a] = MMX_OP2(punpckhdq),
2725 [0x6b] = MMX_OP2(packssdw),
2726 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2727 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2728 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2729 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2730 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2731 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2732 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2733 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2734 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2735 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2736 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2737 [0x74] = MMX_OP2(pcmpeqb),
2738 [0x75] = MMX_OP2(pcmpeqw),
2739 [0x76] = MMX_OP2(pcmpeql),
2740 [0x77] = { SSE_DUMMY }, /* emms */
2741 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2742 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2743 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2744 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2745 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2746 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2747 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2748 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2749 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2750 [0xd1] = MMX_OP2(psrlw),
2751 [0xd2] = MMX_OP2(psrld),
2752 [0xd3] = MMX_OP2(psrlq),
2753 [0xd4] = MMX_OP2(paddq),
2754 [0xd5] = MMX_OP2(pmullw),
2755 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2756 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2757 [0xd8] = MMX_OP2(psubusb),
2758 [0xd9] = MMX_OP2(psubusw),
2759 [0xda] = MMX_OP2(pminub),
2760 [0xdb] = MMX_OP2(pand),
2761 [0xdc] = MMX_OP2(paddusb),
2762 [0xdd] = MMX_OP2(paddusw),
2763 [0xde] = MMX_OP2(pmaxub),
2764 [0xdf] = MMX_OP2(pandn),
2765 [0xe0] = MMX_OP2(pavgb),
2766 [0xe1] = MMX_OP2(psraw),
2767 [0xe2] = MMX_OP2(psrad),
2768 [0xe3] = MMX_OP2(pavgw),
2769 [0xe4] = MMX_OP2(pmulhuw),
2770 [0xe5] = MMX_OP2(pmulhw),
2771 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2772 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2773 [0xe8] = MMX_OP2(psubsb),
2774 [0xe9] = MMX_OP2(psubsw),
2775 [0xea] = MMX_OP2(pminsw),
2776 [0xeb] = MMX_OP2(por),
2777 [0xec] = MMX_OP2(paddsb),
2778 [0xed] = MMX_OP2(paddsw),
2779 [0xee] = MMX_OP2(pmaxsw),
2780 [0xef] = MMX_OP2(pxor),
2781 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2782 [0xf1] = MMX_OP2(psllw),
2783 [0xf2] = MMX_OP2(pslld),
2784 [0xf3] = MMX_OP2(psllq),
2785 [0xf4] = MMX_OP2(pmuludq),
2786 [0xf5] = MMX_OP2(pmaddwd),
2787 [0xf6] = MMX_OP2(psadbw),
2788 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2789 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2790 [0xf8] = MMX_OP2(psubb),
2791 [0xf9] = MMX_OP2(psubw),
2792 [0xfa] = MMX_OP2(psubl),
2793 [0xfb] = MMX_OP2(psubq),
2794 [0xfc] = MMX_OP2(paddb),
2795 [0xfd] = MMX_OP2(paddw),
2796 [0xfe] = MMX_OP2(paddl),
2799 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2800 [0 + 2] = MMX_OP2(psrlw),
2801 [0 + 4] = MMX_OP2(psraw),
2802 [0 + 6] = MMX_OP2(psllw),
2803 [8 + 2] = MMX_OP2(psrld),
2804 [8 + 4] = MMX_OP2(psrad),
2805 [8 + 6] = MMX_OP2(pslld),
2806 [16 + 2] = MMX_OP2(psrlq),
2807 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2808 [16 + 6] = MMX_OP2(psllq),
2809 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2812 static const SSEFunc_0_epi sse_op_table3ai[] = {
2813 gen_helper_cvtsi2ss,
2814 gen_helper_cvtsi2sd
2817 #ifdef TARGET_X86_64
2818 static const SSEFunc_0_epl sse_op_table3aq[] = {
2819 gen_helper_cvtsq2ss,
2820 gen_helper_cvtsq2sd
2822 #endif
2824 static const SSEFunc_i_ep sse_op_table3bi[] = {
2825 gen_helper_cvttss2si,
2826 gen_helper_cvtss2si,
2827 gen_helper_cvttsd2si,
2828 gen_helper_cvtsd2si
2831 #ifdef TARGET_X86_64
2832 static const SSEFunc_l_ep sse_op_table3bq[] = {
2833 gen_helper_cvttss2sq,
2834 gen_helper_cvtss2sq,
2835 gen_helper_cvttsd2sq,
2836 gen_helper_cvtsd2sq
2838 #endif
2840 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2841 SSE_FOP(cmpeq),
2842 SSE_FOP(cmplt),
2843 SSE_FOP(cmple),
2844 SSE_FOP(cmpunord),
2845 SSE_FOP(cmpneq),
2846 SSE_FOP(cmpnlt),
2847 SSE_FOP(cmpnle),
2848 SSE_FOP(cmpord),
2851 static const SSEFunc_0_epp sse_op_table5[256] = {
2852 [0x0c] = gen_helper_pi2fw,
2853 [0x0d] = gen_helper_pi2fd,
2854 [0x1c] = gen_helper_pf2iw,
2855 [0x1d] = gen_helper_pf2id,
2856 [0x8a] = gen_helper_pfnacc,
2857 [0x8e] = gen_helper_pfpnacc,
2858 [0x90] = gen_helper_pfcmpge,
2859 [0x94] = gen_helper_pfmin,
2860 [0x96] = gen_helper_pfrcp,
2861 [0x97] = gen_helper_pfrsqrt,
2862 [0x9a] = gen_helper_pfsub,
2863 [0x9e] = gen_helper_pfadd,
2864 [0xa0] = gen_helper_pfcmpgt,
2865 [0xa4] = gen_helper_pfmax,
2866 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2867 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2868 [0xaa] = gen_helper_pfsubr,
2869 [0xae] = gen_helper_pfacc,
2870 [0xb0] = gen_helper_pfcmpeq,
2871 [0xb4] = gen_helper_pfmul,
2872 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2873 [0xb7] = gen_helper_pmulhrw_mmx,
2874 [0xbb] = gen_helper_pswapd,
2875 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
2878 struct SSEOpHelper_epp {
2879 SSEFunc_0_epp op[2];
2880 uint32_t ext_mask;
2883 struct SSEOpHelper_eppi {
2884 SSEFunc_0_eppi op[2];
2885 uint32_t ext_mask;
2888 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2889 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2890 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
2891 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
2892 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2893 CPUID_EXT_PCLMULQDQ }
2894 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
2896 static const struct SSEOpHelper_epp sse_op_table6[256] = {
2897 [0x00] = SSSE3_OP(pshufb),
2898 [0x01] = SSSE3_OP(phaddw),
2899 [0x02] = SSSE3_OP(phaddd),
2900 [0x03] = SSSE3_OP(phaddsw),
2901 [0x04] = SSSE3_OP(pmaddubsw),
2902 [0x05] = SSSE3_OP(phsubw),
2903 [0x06] = SSSE3_OP(phsubd),
2904 [0x07] = SSSE3_OP(phsubsw),
2905 [0x08] = SSSE3_OP(psignb),
2906 [0x09] = SSSE3_OP(psignw),
2907 [0x0a] = SSSE3_OP(psignd),
2908 [0x0b] = SSSE3_OP(pmulhrsw),
2909 [0x10] = SSE41_OP(pblendvb),
2910 [0x14] = SSE41_OP(blendvps),
2911 [0x15] = SSE41_OP(blendvpd),
2912 [0x17] = SSE41_OP(ptest),
2913 [0x1c] = SSSE3_OP(pabsb),
2914 [0x1d] = SSSE3_OP(pabsw),
2915 [0x1e] = SSSE3_OP(pabsd),
2916 [0x20] = SSE41_OP(pmovsxbw),
2917 [0x21] = SSE41_OP(pmovsxbd),
2918 [0x22] = SSE41_OP(pmovsxbq),
2919 [0x23] = SSE41_OP(pmovsxwd),
2920 [0x24] = SSE41_OP(pmovsxwq),
2921 [0x25] = SSE41_OP(pmovsxdq),
2922 [0x28] = SSE41_OP(pmuldq),
2923 [0x29] = SSE41_OP(pcmpeqq),
2924 [0x2a] = SSE41_SPECIAL, /* movntqda */
2925 [0x2b] = SSE41_OP(packusdw),
2926 [0x30] = SSE41_OP(pmovzxbw),
2927 [0x31] = SSE41_OP(pmovzxbd),
2928 [0x32] = SSE41_OP(pmovzxbq),
2929 [0x33] = SSE41_OP(pmovzxwd),
2930 [0x34] = SSE41_OP(pmovzxwq),
2931 [0x35] = SSE41_OP(pmovzxdq),
2932 [0x37] = SSE42_OP(pcmpgtq),
2933 [0x38] = SSE41_OP(pminsb),
2934 [0x39] = SSE41_OP(pminsd),
2935 [0x3a] = SSE41_OP(pminuw),
2936 [0x3b] = SSE41_OP(pminud),
2937 [0x3c] = SSE41_OP(pmaxsb),
2938 [0x3d] = SSE41_OP(pmaxsd),
2939 [0x3e] = SSE41_OP(pmaxuw),
2940 [0x3f] = SSE41_OP(pmaxud),
2941 [0x40] = SSE41_OP(pmulld),
2942 [0x41] = SSE41_OP(phminposuw),
2943 [0xdb] = AESNI_OP(aesimc),
2944 [0xdc] = AESNI_OP(aesenc),
2945 [0xdd] = AESNI_OP(aesenclast),
2946 [0xde] = AESNI_OP(aesdec),
2947 [0xdf] = AESNI_OP(aesdeclast),
2950 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
2951 [0x08] = SSE41_OP(roundps),
2952 [0x09] = SSE41_OP(roundpd),
2953 [0x0a] = SSE41_OP(roundss),
2954 [0x0b] = SSE41_OP(roundsd),
2955 [0x0c] = SSE41_OP(blendps),
2956 [0x0d] = SSE41_OP(blendpd),
2957 [0x0e] = SSE41_OP(pblendw),
2958 [0x0f] = SSSE3_OP(palignr),
2959 [0x14] = SSE41_SPECIAL, /* pextrb */
2960 [0x15] = SSE41_SPECIAL, /* pextrw */
2961 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
2962 [0x17] = SSE41_SPECIAL, /* extractps */
2963 [0x20] = SSE41_SPECIAL, /* pinsrb */
2964 [0x21] = SSE41_SPECIAL, /* insertps */
2965 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
2966 [0x40] = SSE41_OP(dpps),
2967 [0x41] = SSE41_OP(dppd),
2968 [0x42] = SSE41_OP(mpsadbw),
2969 [0x44] = PCLMULQDQ_OP(pclmulqdq),
2970 [0x60] = SSE42_OP(pcmpestrm),
2971 [0x61] = SSE42_OP(pcmpestri),
2972 [0x62] = SSE42_OP(pcmpistrm),
2973 [0x63] = SSE42_OP(pcmpistri),
2974 [0xdf] = AESNI_OP(aeskeygenassist),
2977 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
2978 target_ulong pc_start, int rex_r)
2980 int b1, op1_offset, op2_offset, is_xmm, val;
2981 int modrm, mod, rm, reg;
2982 SSEFunc_0_epp sse_fn_epp;
2983 SSEFunc_0_eppi sse_fn_eppi;
2984 SSEFunc_0_ppi sse_fn_ppi;
2985 SSEFunc_0_eppt sse_fn_eppt;
2986 TCGMemOp ot;
2988 b &= 0xff;
2989 if (s->prefix & PREFIX_DATA)
2990 b1 = 1;
2991 else if (s->prefix & PREFIX_REPZ)
2992 b1 = 2;
2993 else if (s->prefix & PREFIX_REPNZ)
2994 b1 = 3;
2995 else
2996 b1 = 0;
2997 sse_fn_epp = sse_op_table1[b][b1];
2998 if (!sse_fn_epp) {
2999 goto illegal_op;
3001 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3002 is_xmm = 1;
3003 } else {
3004 if (b1 == 0) {
3005 /* MMX case */
3006 is_xmm = 0;
3007 } else {
3008 is_xmm = 1;
3011 /* simple MMX/SSE operation */
3012 if (s->flags & HF_TS_MASK) {
3013 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3014 return;
3016 if (s->flags & HF_EM_MASK) {
3017 illegal_op:
3018 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
3019 return;
3021 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
3022 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
3023 goto illegal_op;
3024 if (b == 0x0e) {
3025 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3026 goto illegal_op;
3027 /* femms */
3028 gen_helper_emms(cpu_env);
3029 return;
3031 if (b == 0x77) {
3032 /* emms */
3033 gen_helper_emms(cpu_env);
3034 return;
3036 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3037 the static cpu state) */
3038 if (!is_xmm) {
3039 gen_helper_enter_mmx(cpu_env);
3042 modrm = cpu_ldub_code(env, s->pc++);
3043 reg = ((modrm >> 3) & 7);
3044 if (is_xmm)
3045 reg |= rex_r;
3046 mod = (modrm >> 6) & 3;
3047 if (sse_fn_epp == SSE_SPECIAL) {
3048 b |= (b1 << 8);
3049 switch(b) {
3050 case 0x0e7: /* movntq */
3051 if (mod == 3)
3052 goto illegal_op;
3053 gen_lea_modrm(env, s, modrm);
3054 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3055 break;
3056 case 0x1e7: /* movntdq */
3057 case 0x02b: /* movntps */
3058 case 0x12b: /* movntps */
3059 if (mod == 3)
3060 goto illegal_op;
3061 gen_lea_modrm(env, s, modrm);
3062 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3063 break;
3064 case 0x3f0: /* lddqu */
3065 if (mod == 3)
3066 goto illegal_op;
3067 gen_lea_modrm(env, s, modrm);
3068 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3069 break;
3070 case 0x22b: /* movntss */
3071 case 0x32b: /* movntsd */
3072 if (mod == 3)
3073 goto illegal_op;
3074 gen_lea_modrm(env, s, modrm);
3075 if (b1 & 1) {
3076 gen_stq_env_A0(s, offsetof(CPUX86State,
3077 xmm_regs[reg].XMM_Q(0)));
3078 } else {
3079 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3080 xmm_regs[reg].XMM_L(0)));
3081 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
3083 break;
3084 case 0x6e: /* movd mm, ea */
3085 #ifdef TARGET_X86_64
3086 if (s->dflag == MO_64) {
3087 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3088 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3089 } else
3090 #endif
3092 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3093 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3094 offsetof(CPUX86State,fpregs[reg].mmx));
3095 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3096 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
3098 break;
3099 case 0x16e: /* movd xmm, ea */
3100 #ifdef TARGET_X86_64
3101 if (s->dflag == MO_64) {
3102 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3103 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3104 offsetof(CPUX86State,xmm_regs[reg]));
3105 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
3106 } else
3107 #endif
3109 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3110 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3111 offsetof(CPUX86State,xmm_regs[reg]));
3112 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3113 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
3115 break;
3116 case 0x6f: /* movq mm, ea */
3117 if (mod != 3) {
3118 gen_lea_modrm(env, s, modrm);
3119 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3120 } else {
3121 rm = (modrm & 7);
3122 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3123 offsetof(CPUX86State,fpregs[rm].mmx));
3124 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3125 offsetof(CPUX86State,fpregs[reg].mmx));
3127 break;
3128 case 0x010: /* movups */
3129 case 0x110: /* movupd */
3130 case 0x028: /* movaps */
3131 case 0x128: /* movapd */
3132 case 0x16f: /* movdqa xmm, ea */
3133 case 0x26f: /* movdqu xmm, ea */
3134 if (mod != 3) {
3135 gen_lea_modrm(env, s, modrm);
3136 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3137 } else {
3138 rm = (modrm & 7) | REX_B(s);
3139 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3140 offsetof(CPUX86State,xmm_regs[rm]));
3142 break;
3143 case 0x210: /* movss xmm, ea */
3144 if (mod != 3) {
3145 gen_lea_modrm(env, s, modrm);
3146 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
3147 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3148 tcg_gen_movi_tl(cpu_T[0], 0);
3149 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3150 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3151 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3152 } else {
3153 rm = (modrm & 7) | REX_B(s);
3154 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3155 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3157 break;
3158 case 0x310: /* movsd xmm, ea */
3159 if (mod != 3) {
3160 gen_lea_modrm(env, s, modrm);
3161 gen_ldq_env_A0(s, offsetof(CPUX86State,
3162 xmm_regs[reg].XMM_Q(0)));
3163 tcg_gen_movi_tl(cpu_T[0], 0);
3164 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3165 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3166 } else {
3167 rm = (modrm & 7) | REX_B(s);
3168 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3169 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3171 break;
3172 case 0x012: /* movlps */
3173 case 0x112: /* movlpd */
3174 if (mod != 3) {
3175 gen_lea_modrm(env, s, modrm);
3176 gen_ldq_env_A0(s, offsetof(CPUX86State,
3177 xmm_regs[reg].XMM_Q(0)));
3178 } else {
3179 /* movhlps */
3180 rm = (modrm & 7) | REX_B(s);
3181 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3182 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3184 break;
3185 case 0x212: /* movsldup */
3186 if (mod != 3) {
3187 gen_lea_modrm(env, s, modrm);
3188 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3189 } else {
3190 rm = (modrm & 7) | REX_B(s);
3191 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3192 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3193 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3194 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3196 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3197 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3198 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3199 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3200 break;
3201 case 0x312: /* movddup */
3202 if (mod != 3) {
3203 gen_lea_modrm(env, s, modrm);
3204 gen_ldq_env_A0(s, offsetof(CPUX86State,
3205 xmm_regs[reg].XMM_Q(0)));
3206 } else {
3207 rm = (modrm & 7) | REX_B(s);
3208 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3209 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3211 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3212 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3213 break;
3214 case 0x016: /* movhps */
3215 case 0x116: /* movhpd */
3216 if (mod != 3) {
3217 gen_lea_modrm(env, s, modrm);
3218 gen_ldq_env_A0(s, offsetof(CPUX86State,
3219 xmm_regs[reg].XMM_Q(1)));
3220 } else {
3221 /* movlhps */
3222 rm = (modrm & 7) | REX_B(s);
3223 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3224 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3226 break;
3227 case 0x216: /* movshdup */
3228 if (mod != 3) {
3229 gen_lea_modrm(env, s, modrm);
3230 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3231 } else {
3232 rm = (modrm & 7) | REX_B(s);
3233 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3234 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3235 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3236 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3238 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3239 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3240 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3241 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3242 break;
3243 case 0x178:
3244 case 0x378:
3246 int bit_index, field_length;
3248 if (b1 == 1 && reg != 0)
3249 goto illegal_op;
3250 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3251 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3252 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3253 offsetof(CPUX86State,xmm_regs[reg]));
3254 if (b1 == 1)
3255 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3256 tcg_const_i32(bit_index),
3257 tcg_const_i32(field_length));
3258 else
3259 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3260 tcg_const_i32(bit_index),
3261 tcg_const_i32(field_length));
3263 break;
3264 case 0x7e: /* movd ea, mm */
3265 #ifdef TARGET_X86_64
3266 if (s->dflag == MO_64) {
3267 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3268 offsetof(CPUX86State,fpregs[reg].mmx));
3269 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3270 } else
3271 #endif
3273 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3274 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3275 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3277 break;
3278 case 0x17e: /* movd ea, xmm */
3279 #ifdef TARGET_X86_64
3280 if (s->dflag == MO_64) {
3281 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3282 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3283 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3284 } else
3285 #endif
3287 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3288 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3289 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3291 break;
3292 case 0x27e: /* movq xmm, ea */
3293 if (mod != 3) {
3294 gen_lea_modrm(env, s, modrm);
3295 gen_ldq_env_A0(s, offsetof(CPUX86State,
3296 xmm_regs[reg].XMM_Q(0)));
3297 } else {
3298 rm = (modrm & 7) | REX_B(s);
3299 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3300 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3302 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3303 break;
3304 case 0x7f: /* movq ea, mm */
3305 if (mod != 3) {
3306 gen_lea_modrm(env, s, modrm);
3307 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3308 } else {
3309 rm = (modrm & 7);
3310 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3311 offsetof(CPUX86State,fpregs[reg].mmx));
3313 break;
3314 case 0x011: /* movups */
3315 case 0x111: /* movupd */
3316 case 0x029: /* movaps */
3317 case 0x129: /* movapd */
3318 case 0x17f: /* movdqa ea, xmm */
3319 case 0x27f: /* movdqu ea, xmm */
3320 if (mod != 3) {
3321 gen_lea_modrm(env, s, modrm);
3322 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3323 } else {
3324 rm = (modrm & 7) | REX_B(s);
3325 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3326 offsetof(CPUX86State,xmm_regs[reg]));
3328 break;
3329 case 0x211: /* movss ea, xmm */
3330 if (mod != 3) {
3331 gen_lea_modrm(env, s, modrm);
3332 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3333 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
3334 } else {
3335 rm = (modrm & 7) | REX_B(s);
3336 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3337 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3339 break;
3340 case 0x311: /* movsd ea, xmm */
3341 if (mod != 3) {
3342 gen_lea_modrm(env, s, modrm);
3343 gen_stq_env_A0(s, offsetof(CPUX86State,
3344 xmm_regs[reg].XMM_Q(0)));
3345 } else {
3346 rm = (modrm & 7) | REX_B(s);
3347 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3348 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3350 break;
3351 case 0x013: /* movlps */
3352 case 0x113: /* movlpd */
3353 if (mod != 3) {
3354 gen_lea_modrm(env, s, modrm);
3355 gen_stq_env_A0(s, offsetof(CPUX86State,
3356 xmm_regs[reg].XMM_Q(0)));
3357 } else {
3358 goto illegal_op;
3360 break;
3361 case 0x017: /* movhps */
3362 case 0x117: /* movhpd */
3363 if (mod != 3) {
3364 gen_lea_modrm(env, s, modrm);
3365 gen_stq_env_A0(s, offsetof(CPUX86State,
3366 xmm_regs[reg].XMM_Q(1)));
3367 } else {
3368 goto illegal_op;
3370 break;
3371 case 0x71: /* shift mm, im */
3372 case 0x72:
3373 case 0x73:
3374 case 0x171: /* shift xmm, im */
3375 case 0x172:
3376 case 0x173:
3377 if (b1 >= 2) {
3378 goto illegal_op;
3380 val = cpu_ldub_code(env, s->pc++);
3381 if (is_xmm) {
3382 tcg_gen_movi_tl(cpu_T[0], val);
3383 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3384 tcg_gen_movi_tl(cpu_T[0], 0);
3385 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
3386 op1_offset = offsetof(CPUX86State,xmm_t0);
3387 } else {
3388 tcg_gen_movi_tl(cpu_T[0], val);
3389 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3390 tcg_gen_movi_tl(cpu_T[0], 0);
3391 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3392 op1_offset = offsetof(CPUX86State,mmx_t0);
3394 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3395 (((modrm >> 3)) & 7)][b1];
3396 if (!sse_fn_epp) {
3397 goto illegal_op;
3399 if (is_xmm) {
3400 rm = (modrm & 7) | REX_B(s);
3401 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3402 } else {
3403 rm = (modrm & 7);
3404 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3406 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3407 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3408 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3409 break;
3410 case 0x050: /* movmskps */
3411 rm = (modrm & 7) | REX_B(s);
3412 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3413 offsetof(CPUX86State,xmm_regs[rm]));
3414 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3415 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3416 break;
3417 case 0x150: /* movmskpd */
3418 rm = (modrm & 7) | REX_B(s);
3419 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3420 offsetof(CPUX86State,xmm_regs[rm]));
3421 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3422 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3423 break;
3424 case 0x02a: /* cvtpi2ps */
3425 case 0x12a: /* cvtpi2pd */
3426 gen_helper_enter_mmx(cpu_env);
3427 if (mod != 3) {
3428 gen_lea_modrm(env, s, modrm);
3429 op2_offset = offsetof(CPUX86State,mmx_t0);
3430 gen_ldq_env_A0(s, op2_offset);
3431 } else {
3432 rm = (modrm & 7);
3433 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3435 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3436 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3437 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3438 switch(b >> 8) {
3439 case 0x0:
3440 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3441 break;
3442 default:
3443 case 0x1:
3444 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3445 break;
3447 break;
3448 case 0x22a: /* cvtsi2ss */
3449 case 0x32a: /* cvtsi2sd */
3450 ot = mo_64_32(s->dflag);
3451 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3452 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3453 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3454 if (ot == MO_32) {
3455 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3456 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3457 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3458 } else {
3459 #ifdef TARGET_X86_64
3460 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3461 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T[0]);
3462 #else
3463 goto illegal_op;
3464 #endif
3466 break;
3467 case 0x02c: /* cvttps2pi */
3468 case 0x12c: /* cvttpd2pi */
3469 case 0x02d: /* cvtps2pi */
3470 case 0x12d: /* cvtpd2pi */
3471 gen_helper_enter_mmx(cpu_env);
3472 if (mod != 3) {
3473 gen_lea_modrm(env, s, modrm);
3474 op2_offset = offsetof(CPUX86State,xmm_t0);
3475 gen_ldo_env_A0(s, op2_offset);
3476 } else {
3477 rm = (modrm & 7) | REX_B(s);
3478 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3480 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3481 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3482 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3483 switch(b) {
3484 case 0x02c:
3485 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3486 break;
3487 case 0x12c:
3488 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3489 break;
3490 case 0x02d:
3491 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3492 break;
3493 case 0x12d:
3494 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3495 break;
3497 break;
3498 case 0x22c: /* cvttss2si */
3499 case 0x22d: /* cvtss2si */
3500 case 0x32c: /* cvttsd2si */
3501 case 0x32d: /* cvtsd2si */
3502 ot = mo_64_32(s->dflag);
3503 if (mod != 3) {
3504 gen_lea_modrm(env, s, modrm);
3505 if ((b >> 8) & 1) {
3506 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_Q(0)));
3507 } else {
3508 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
3509 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3511 op2_offset = offsetof(CPUX86State,xmm_t0);
3512 } else {
3513 rm = (modrm & 7) | REX_B(s);
3514 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3516 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3517 if (ot == MO_32) {
3518 SSEFunc_i_ep sse_fn_i_ep =
3519 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3520 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3521 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3522 } else {
3523 #ifdef TARGET_X86_64
3524 SSEFunc_l_ep sse_fn_l_ep =
3525 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3526 sse_fn_l_ep(cpu_T[0], cpu_env, cpu_ptr0);
3527 #else
3528 goto illegal_op;
3529 #endif
3531 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
3532 break;
3533 case 0xc4: /* pinsrw */
3534 case 0x1c4:
3535 s->rip_offset = 1;
3536 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3537 val = cpu_ldub_code(env, s->pc++);
3538 if (b1) {
3539 val &= 7;
3540 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3541 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
3542 } else {
3543 val &= 3;
3544 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3545 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3547 break;
3548 case 0xc5: /* pextrw */
3549 case 0x1c5:
3550 if (mod != 3)
3551 goto illegal_op;
3552 ot = mo_64_32(s->dflag);
3553 val = cpu_ldub_code(env, s->pc++);
3554 if (b1) {
3555 val &= 7;
3556 rm = (modrm & 7) | REX_B(s);
3557 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3558 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
3559 } else {
3560 val &= 3;
3561 rm = (modrm & 7);
3562 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3563 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3565 reg = ((modrm >> 3) & 7) | rex_r;
3566 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
3567 break;
3568 case 0x1d6: /* movq ea, xmm */
3569 if (mod != 3) {
3570 gen_lea_modrm(env, s, modrm);
3571 gen_stq_env_A0(s, offsetof(CPUX86State,
3572 xmm_regs[reg].XMM_Q(0)));
3573 } else {
3574 rm = (modrm & 7) | REX_B(s);
3575 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3576 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3577 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3579 break;
3580 case 0x2d6: /* movq2dq */
3581 gen_helper_enter_mmx(cpu_env);
3582 rm = (modrm & 7);
3583 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3584 offsetof(CPUX86State,fpregs[rm].mmx));
3585 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3586 break;
3587 case 0x3d6: /* movdq2q */
3588 gen_helper_enter_mmx(cpu_env);
3589 rm = (modrm & 7) | REX_B(s);
3590 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3591 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3592 break;
3593 case 0xd7: /* pmovmskb */
3594 case 0x1d7:
3595 if (mod != 3)
3596 goto illegal_op;
3597 if (b1) {
3598 rm = (modrm & 7) | REX_B(s);
3599 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3600 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3601 } else {
3602 rm = (modrm & 7);
3603 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3604 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3606 reg = ((modrm >> 3) & 7) | rex_r;
3607 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
3608 break;
3610 case 0x138:
3611 case 0x038:
3612 b = modrm;
3613 if ((b & 0xf0) == 0xf0) {
3614 goto do_0f_38_fx;
3616 modrm = cpu_ldub_code(env, s->pc++);
3617 rm = modrm & 7;
3618 reg = ((modrm >> 3) & 7) | rex_r;
3619 mod = (modrm >> 6) & 3;
3620 if (b1 >= 2) {
3621 goto illegal_op;
3624 sse_fn_epp = sse_op_table6[b].op[b1];
3625 if (!sse_fn_epp) {
3626 goto illegal_op;
3628 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3629 goto illegal_op;
3631 if (b1) {
3632 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3633 if (mod == 3) {
3634 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3635 } else {
3636 op2_offset = offsetof(CPUX86State,xmm_t0);
3637 gen_lea_modrm(env, s, modrm);
3638 switch (b) {
3639 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3640 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3641 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3642 gen_ldq_env_A0(s, op2_offset +
3643 offsetof(XMMReg, XMM_Q(0)));
3644 break;
3645 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3646 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3647 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3648 s->mem_index, MO_LEUL);
3649 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3650 offsetof(XMMReg, XMM_L(0)));
3651 break;
3652 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3653 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3654 s->mem_index, MO_LEUW);
3655 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3656 offsetof(XMMReg, XMM_W(0)));
3657 break;
3658 case 0x2a: /* movntqda */
3659 gen_ldo_env_A0(s, op1_offset);
3660 return;
3661 default:
3662 gen_ldo_env_A0(s, op2_offset);
3665 } else {
3666 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3667 if (mod == 3) {
3668 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3669 } else {
3670 op2_offset = offsetof(CPUX86State,mmx_t0);
3671 gen_lea_modrm(env, s, modrm);
3672 gen_ldq_env_A0(s, op2_offset);
3675 if (sse_fn_epp == SSE_SPECIAL) {
3676 goto illegal_op;
3679 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3680 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3681 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3683 if (b == 0x17) {
3684 set_cc_op(s, CC_OP_EFLAGS);
3686 break;
3688 case 0x238:
3689 case 0x338:
3690 do_0f_38_fx:
3691 /* Various integer extensions at 0f 38 f[0-f]. */
3692 b = modrm | (b1 << 8);
3693 modrm = cpu_ldub_code(env, s->pc++);
3694 reg = ((modrm >> 3) & 7) | rex_r;
3696 switch (b) {
3697 case 0x3f0: /* crc32 Gd,Eb */
3698 case 0x3f1: /* crc32 Gd,Ey */
3699 do_crc32:
3700 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3701 goto illegal_op;
3703 if ((b & 0xff) == 0xf0) {
3704 ot = MO_8;
3705 } else if (s->dflag != MO_64) {
3706 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3707 } else {
3708 ot = MO_64;
3711 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
3712 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3713 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
3714 cpu_T[0], tcg_const_i32(8 << ot));
3716 ot = mo_64_32(s->dflag);
3717 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
3718 break;
3720 case 0x1f0: /* crc32 or movbe */
3721 case 0x1f1:
3722 /* For these insns, the f3 prefix is supposed to have priority
3723 over the 66 prefix, but that's not what we implement above
3724 setting b1. */
3725 if (s->prefix & PREFIX_REPNZ) {
3726 goto do_crc32;
3728 /* FALLTHRU */
3729 case 0x0f0: /* movbe Gy,My */
3730 case 0x0f1: /* movbe My,Gy */
3731 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3732 goto illegal_op;
3734 if (s->dflag != MO_64) {
3735 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3736 } else {
3737 ot = MO_64;
3740 gen_lea_modrm(env, s, modrm);
3741 if ((b & 1) == 0) {
3742 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
3743 s->mem_index, ot | MO_BE);
3744 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
3745 } else {
3746 tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
3747 s->mem_index, ot | MO_BE);
3749 break;
3751 case 0x0f2: /* andn Gy, By, Ey */
3752 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3753 || !(s->prefix & PREFIX_VEX)
3754 || s->vex_l != 0) {
3755 goto illegal_op;
3757 ot = mo_64_32(s->dflag);
3758 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3759 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
3760 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
3761 gen_op_update1_cc();
3762 set_cc_op(s, CC_OP_LOGICB + ot);
3763 break;
3765 case 0x0f7: /* bextr Gy, Ey, By */
3766 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3767 || !(s->prefix & PREFIX_VEX)
3768 || s->vex_l != 0) {
3769 goto illegal_op;
3771 ot = mo_64_32(s->dflag);
3773 TCGv bound, zero;
3775 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3776 /* Extract START, and shift the operand.
3777 Shifts larger than operand size get zeros. */
3778 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
3779 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_A0);
3781 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3782 zero = tcg_const_tl(0);
3783 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T[0], cpu_A0, bound,
3784 cpu_T[0], zero);
3785 tcg_temp_free(zero);
3787 /* Extract the LEN into a mask. Lengths larger than
3788 operand size get all ones. */
3789 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
3790 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
3791 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
3792 cpu_A0, bound);
3793 tcg_temp_free(bound);
3794 tcg_gen_movi_tl(cpu_T[1], 1);
3795 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_A0);
3796 tcg_gen_subi_tl(cpu_T[1], cpu_T[1], 1);
3797 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3799 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
3800 gen_op_update1_cc();
3801 set_cc_op(s, CC_OP_LOGICB + ot);
3803 break;
3805 case 0x0f5: /* bzhi Gy, Ey, By */
3806 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3807 || !(s->prefix & PREFIX_VEX)
3808 || s->vex_l != 0) {
3809 goto illegal_op;
3811 ot = mo_64_32(s->dflag);
3812 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3813 tcg_gen_ext8u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3815 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3816 /* Note that since we're using BMILG (in order to get O
3817 cleared) we need to store the inverse into C. */
3818 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3819 cpu_T[1], bound);
3820 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T[1], cpu_T[1],
3821 bound, bound, cpu_T[1]);
3822 tcg_temp_free(bound);
3824 tcg_gen_movi_tl(cpu_A0, -1);
3825 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T[1]);
3826 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_A0);
3827 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
3828 gen_op_update1_cc();
3829 set_cc_op(s, CC_OP_BMILGB + ot);
3830 break;
3832 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3833 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3834 || !(s->prefix & PREFIX_VEX)
3835 || s->vex_l != 0) {
3836 goto illegal_op;
3838 ot = mo_64_32(s->dflag);
3839 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3840 switch (ot) {
3841 default:
3842 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3843 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3844 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3845 cpu_tmp2_i32, cpu_tmp3_i32);
3846 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3847 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
3848 break;
3849 #ifdef TARGET_X86_64
3850 case MO_64:
3851 tcg_gen_mulu2_i64(cpu_regs[s->vex_v], cpu_regs[reg],
3852 cpu_T[0], cpu_regs[R_EDX]);
3853 break;
3854 #endif
3856 break;
3858 case 0x3f5: /* pdep Gy, By, Ey */
3859 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3860 || !(s->prefix & PREFIX_VEX)
3861 || s->vex_l != 0) {
3862 goto illegal_op;
3864 ot = mo_64_32(s->dflag);
3865 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3866 /* Note that by zero-extending the mask operand, we
3867 automatically handle zero-extending the result. */
3868 if (ot == MO_64) {
3869 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3870 } else {
3871 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3873 gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3874 break;
3876 case 0x2f5: /* pext Gy, By, Ey */
3877 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3878 || !(s->prefix & PREFIX_VEX)
3879 || s->vex_l != 0) {
3880 goto illegal_op;
3882 ot = mo_64_32(s->dflag);
3883 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3884 /* Note that by zero-extending the mask operand, we
3885 automatically handle zero-extending the result. */
3886 if (ot == MO_64) {
3887 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3888 } else {
3889 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3891 gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3892 break;
3894 case 0x1f6: /* adcx Gy, Ey */
3895 case 0x2f6: /* adox Gy, Ey */
3896 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3897 goto illegal_op;
3898 } else {
3899 TCGv carry_in, carry_out, zero;
3900 int end_op;
3902 ot = mo_64_32(s->dflag);
3903 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3905 /* Re-use the carry-out from a previous round. */
3906 TCGV_UNUSED(carry_in);
3907 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3908 switch (s->cc_op) {
3909 case CC_OP_ADCX:
3910 if (b == 0x1f6) {
3911 carry_in = cpu_cc_dst;
3912 end_op = CC_OP_ADCX;
3913 } else {
3914 end_op = CC_OP_ADCOX;
3916 break;
3917 case CC_OP_ADOX:
3918 if (b == 0x1f6) {
3919 end_op = CC_OP_ADCOX;
3920 } else {
3921 carry_in = cpu_cc_src2;
3922 end_op = CC_OP_ADOX;
3924 break;
3925 case CC_OP_ADCOX:
3926 end_op = CC_OP_ADCOX;
3927 carry_in = carry_out;
3928 break;
3929 default:
3930 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
3931 break;
3933 /* If we can't reuse carry-out, get it out of EFLAGS. */
3934 if (TCGV_IS_UNUSED(carry_in)) {
3935 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3936 gen_compute_eflags(s);
3938 carry_in = cpu_tmp0;
3939 tcg_gen_shri_tl(carry_in, cpu_cc_src,
3940 ctz32(b == 0x1f6 ? CC_C : CC_O));
3941 tcg_gen_andi_tl(carry_in, carry_in, 1);
3944 switch (ot) {
3945 #ifdef TARGET_X86_64
3946 case MO_32:
3947 /* If we know TL is 64-bit, and we want a 32-bit
3948 result, just do everything in 64-bit arithmetic. */
3949 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3950 tcg_gen_ext32u_i64(cpu_T[0], cpu_T[0]);
3951 tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_regs[reg]);
3952 tcg_gen_add_i64(cpu_T[0], cpu_T[0], carry_in);
3953 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T[0]);
3954 tcg_gen_shri_i64(carry_out, cpu_T[0], 32);
3955 break;
3956 #endif
3957 default:
3958 /* Otherwise compute the carry-out in two steps. */
3959 zero = tcg_const_tl(0);
3960 tcg_gen_add2_tl(cpu_T[0], carry_out,
3961 cpu_T[0], zero,
3962 carry_in, zero);
3963 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3964 cpu_regs[reg], carry_out,
3965 cpu_T[0], zero);
3966 tcg_temp_free(zero);
3967 break;
3969 set_cc_op(s, end_op);
3971 break;
3973 case 0x1f7: /* shlx Gy, Ey, By */
3974 case 0x2f7: /* sarx Gy, Ey, By */
3975 case 0x3f7: /* shrx Gy, Ey, By */
3976 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3977 || !(s->prefix & PREFIX_VEX)
3978 || s->vex_l != 0) {
3979 goto illegal_op;
3981 ot = mo_64_32(s->dflag);
3982 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3983 if (ot == MO_64) {
3984 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
3985 } else {
3986 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
3988 if (b == 0x1f7) {
3989 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3990 } else if (b == 0x2f7) {
3991 if (ot != MO_64) {
3992 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
3994 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3995 } else {
3996 if (ot != MO_64) {
3997 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
3999 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4001 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4002 break;
4004 case 0x0f3:
4005 case 0x1f3:
4006 case 0x2f3:
4007 case 0x3f3: /* Group 17 */
4008 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4009 || !(s->prefix & PREFIX_VEX)
4010 || s->vex_l != 0) {
4011 goto illegal_op;
4013 ot = mo_64_32(s->dflag);
4014 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4016 switch (reg & 7) {
4017 case 1: /* blsr By,Ey */
4018 tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
4019 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4020 gen_op_mov_reg_v(ot, s->vex_v, cpu_T[0]);
4021 gen_op_update2_cc();
4022 set_cc_op(s, CC_OP_BMILGB + ot);
4023 break;
4025 case 2: /* blsmsk By,Ey */
4026 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4027 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4028 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4029 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4030 set_cc_op(s, CC_OP_BMILGB + ot);
4031 break;
4033 case 3: /* blsi By, Ey */
4034 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4035 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4036 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4037 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4038 set_cc_op(s, CC_OP_BMILGB + ot);
4039 break;
4041 default:
4042 goto illegal_op;
4044 break;
4046 default:
4047 goto illegal_op;
4049 break;
4051 case 0x03a:
4052 case 0x13a:
4053 b = modrm;
4054 modrm = cpu_ldub_code(env, s->pc++);
4055 rm = modrm & 7;
4056 reg = ((modrm >> 3) & 7) | rex_r;
4057 mod = (modrm >> 6) & 3;
4058 if (b1 >= 2) {
4059 goto illegal_op;
4062 sse_fn_eppi = sse_op_table7[b].op[b1];
4063 if (!sse_fn_eppi) {
4064 goto illegal_op;
4066 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4067 goto illegal_op;
4069 if (sse_fn_eppi == SSE_SPECIAL) {
4070 ot = mo_64_32(s->dflag);
4071 rm = (modrm & 7) | REX_B(s);
4072 if (mod != 3)
4073 gen_lea_modrm(env, s, modrm);
4074 reg = ((modrm >> 3) & 7) | rex_r;
4075 val = cpu_ldub_code(env, s->pc++);
4076 switch (b) {
4077 case 0x14: /* pextrb */
4078 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4079 xmm_regs[reg].XMM_B(val & 15)));
4080 if (mod == 3) {
4081 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4082 } else {
4083 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4084 s->mem_index, MO_UB);
4086 break;
4087 case 0x15: /* pextrw */
4088 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4089 xmm_regs[reg].XMM_W(val & 7)));
4090 if (mod == 3) {
4091 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4092 } else {
4093 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4094 s->mem_index, MO_LEUW);
4096 break;
4097 case 0x16:
4098 if (ot == MO_32) { /* pextrd */
4099 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4100 offsetof(CPUX86State,
4101 xmm_regs[reg].XMM_L(val & 3)));
4102 if (mod == 3) {
4103 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
4104 } else {
4105 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4106 s->mem_index, MO_LEUL);
4108 } else { /* pextrq */
4109 #ifdef TARGET_X86_64
4110 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4111 offsetof(CPUX86State,
4112 xmm_regs[reg].XMM_Q(val & 1)));
4113 if (mod == 3) {
4114 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
4115 } else {
4116 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4117 s->mem_index, MO_LEQ);
4119 #else
4120 goto illegal_op;
4121 #endif
4123 break;
4124 case 0x17: /* extractps */
4125 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4126 xmm_regs[reg].XMM_L(val & 3)));
4127 if (mod == 3) {
4128 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4129 } else {
4130 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4131 s->mem_index, MO_LEUL);
4133 break;
4134 case 0x20: /* pinsrb */
4135 if (mod == 3) {
4136 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
4137 } else {
4138 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
4139 s->mem_index, MO_UB);
4141 tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4142 xmm_regs[reg].XMM_B(val & 15)));
4143 break;
4144 case 0x21: /* insertps */
4145 if (mod == 3) {
4146 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4147 offsetof(CPUX86State,xmm_regs[rm]
4148 .XMM_L((val >> 6) & 3)));
4149 } else {
4150 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4151 s->mem_index, MO_LEUL);
4153 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4154 offsetof(CPUX86State,xmm_regs[reg]
4155 .XMM_L((val >> 4) & 3)));
4156 if ((val >> 0) & 1)
4157 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4158 cpu_env, offsetof(CPUX86State,
4159 xmm_regs[reg].XMM_L(0)));
4160 if ((val >> 1) & 1)
4161 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4162 cpu_env, offsetof(CPUX86State,
4163 xmm_regs[reg].XMM_L(1)));
4164 if ((val >> 2) & 1)
4165 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4166 cpu_env, offsetof(CPUX86State,
4167 xmm_regs[reg].XMM_L(2)));
4168 if ((val >> 3) & 1)
4169 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4170 cpu_env, offsetof(CPUX86State,
4171 xmm_regs[reg].XMM_L(3)));
4172 break;
4173 case 0x22:
4174 if (ot == MO_32) { /* pinsrd */
4175 if (mod == 3) {
4176 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
4177 } else {
4178 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4179 s->mem_index, MO_LEUL);
4181 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4182 offsetof(CPUX86State,
4183 xmm_regs[reg].XMM_L(val & 3)));
4184 } else { /* pinsrq */
4185 #ifdef TARGET_X86_64
4186 if (mod == 3) {
4187 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4188 } else {
4189 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4190 s->mem_index, MO_LEQ);
4192 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4193 offsetof(CPUX86State,
4194 xmm_regs[reg].XMM_Q(val & 1)));
4195 #else
4196 goto illegal_op;
4197 #endif
4199 break;
4201 return;
4204 if (b1) {
4205 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4206 if (mod == 3) {
4207 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4208 } else {
4209 op2_offset = offsetof(CPUX86State,xmm_t0);
4210 gen_lea_modrm(env, s, modrm);
4211 gen_ldo_env_A0(s, op2_offset);
4213 } else {
4214 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4215 if (mod == 3) {
4216 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4217 } else {
4218 op2_offset = offsetof(CPUX86State,mmx_t0);
4219 gen_lea_modrm(env, s, modrm);
4220 gen_ldq_env_A0(s, op2_offset);
4223 val = cpu_ldub_code(env, s->pc++);
4225 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4226 set_cc_op(s, CC_OP_EFLAGS);
4228 if (s->dflag == MO_64) {
4229 /* The helper must use entire 64-bit gp registers */
4230 val |= 1 << 8;
4234 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4235 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4236 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4237 break;
4239 case 0x33a:
4240 /* Various integer extensions at 0f 3a f[0-f]. */
4241 b = modrm | (b1 << 8);
4242 modrm = cpu_ldub_code(env, s->pc++);
4243 reg = ((modrm >> 3) & 7) | rex_r;
4245 switch (b) {
4246 case 0x3f0: /* rorx Gy,Ey, Ib */
4247 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4248 || !(s->prefix & PREFIX_VEX)
4249 || s->vex_l != 0) {
4250 goto illegal_op;
4252 ot = mo_64_32(s->dflag);
4253 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4254 b = cpu_ldub_code(env, s->pc++);
4255 if (ot == MO_64) {
4256 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
4257 } else {
4258 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4259 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4260 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4262 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4263 break;
4265 default:
4266 goto illegal_op;
4268 break;
4270 default:
4271 goto illegal_op;
4273 } else {
4274 /* generic MMX or SSE operation */
4275 switch(b) {
4276 case 0x70: /* pshufx insn */
4277 case 0xc6: /* pshufx insn */
4278 case 0xc2: /* compare insns */
4279 s->rip_offset = 1;
4280 break;
4281 default:
4282 break;
4284 if (is_xmm) {
4285 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4286 if (mod != 3) {
4287 int sz = 4;
4289 gen_lea_modrm(env, s, modrm);
4290 op2_offset = offsetof(CPUX86State,xmm_t0);
4292 switch (b) {
4293 case 0x50 ... 0x5a:
4294 case 0x5c ... 0x5f:
4295 case 0xc2:
4296 /* Most sse scalar operations. */
4297 if (b1 == 2) {
4298 sz = 2;
4299 } else if (b1 == 3) {
4300 sz = 3;
4302 break;
4304 case 0x2e: /* ucomis[sd] */
4305 case 0x2f: /* comis[sd] */
4306 if (b1 == 0) {
4307 sz = 2;
4308 } else {
4309 sz = 3;
4311 break;
4314 switch (sz) {
4315 case 2:
4316 /* 32 bit access */
4317 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
4318 tcg_gen_st32_tl(cpu_T[0], cpu_env,
4319 offsetof(CPUX86State,xmm_t0.XMM_L(0)));
4320 break;
4321 case 3:
4322 /* 64 bit access */
4323 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_D(0)));
4324 break;
4325 default:
4326 /* 128 bit access */
4327 gen_ldo_env_A0(s, op2_offset);
4328 break;
4330 } else {
4331 rm = (modrm & 7) | REX_B(s);
4332 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4334 } else {
4335 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4336 if (mod != 3) {
4337 gen_lea_modrm(env, s, modrm);
4338 op2_offset = offsetof(CPUX86State,mmx_t0);
4339 gen_ldq_env_A0(s, op2_offset);
4340 } else {
4341 rm = (modrm & 7);
4342 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4345 switch(b) {
4346 case 0x0f: /* 3DNow! data insns */
4347 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4348 goto illegal_op;
4349 val = cpu_ldub_code(env, s->pc++);
4350 sse_fn_epp = sse_op_table5[val];
4351 if (!sse_fn_epp) {
4352 goto illegal_op;
4354 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4355 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4356 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4357 break;
4358 case 0x70: /* pshufx insn */
4359 case 0xc6: /* pshufx insn */
4360 val = cpu_ldub_code(env, s->pc++);
4361 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4362 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4363 /* XXX: introduce a new table? */
4364 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4365 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4366 break;
4367 case 0xc2:
4368 /* compare insns */
4369 val = cpu_ldub_code(env, s->pc++);
4370 if (val >= 8)
4371 goto illegal_op;
4372 sse_fn_epp = sse_op_table4[val][b1];
4374 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4375 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4376 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4377 break;
4378 case 0xf7:
4379 /* maskmov : we must prepare A0 */
4380 if (mod != 3)
4381 goto illegal_op;
4382 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4383 gen_extu(s->aflag, cpu_A0);
4384 gen_add_A0_ds_seg(s);
4386 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4387 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4388 /* XXX: introduce a new table? */
4389 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4390 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4391 break;
4392 default:
4393 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4394 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4395 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4396 break;
4398 if (b == 0x2e || b == 0x2f) {
4399 set_cc_op(s, CC_OP_EFLAGS);
4404 /* convert one instruction. s->is_jmp is set if the translation must
4405 be stopped. Return the next pc value */
4406 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4407 target_ulong pc_start)
4409 int b, prefixes;
4410 int shift;
4411 TCGMemOp ot, aflag, dflag;
4412 int modrm, reg, rm, mod, op, opreg, val;
4413 target_ulong next_eip, tval;
4414 int rex_w, rex_r;
4416 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
4417 tcg_gen_debug_insn_start(pc_start);
4419 s->pc = pc_start;
4420 prefixes = 0;
4421 s->override = -1;
4422 rex_w = -1;
4423 rex_r = 0;
4424 #ifdef TARGET_X86_64
4425 s->rex_x = 0;
4426 s->rex_b = 0;
4427 x86_64_hregs = 0;
4428 #endif
4429 s->rip_offset = 0; /* for relative ip address */
4430 s->vex_l = 0;
4431 s->vex_v = 0;
4432 next_byte:
4433 b = cpu_ldub_code(env, s->pc);
4434 s->pc++;
4435 /* Collect prefixes. */
4436 switch (b) {
4437 case 0xf3:
4438 prefixes |= PREFIX_REPZ;
4439 goto next_byte;
4440 case 0xf2:
4441 prefixes |= PREFIX_REPNZ;
4442 goto next_byte;
4443 case 0xf0:
4444 prefixes |= PREFIX_LOCK;
4445 goto next_byte;
4446 case 0x2e:
4447 s->override = R_CS;
4448 goto next_byte;
4449 case 0x36:
4450 s->override = R_SS;
4451 goto next_byte;
4452 case 0x3e:
4453 s->override = R_DS;
4454 goto next_byte;
4455 case 0x26:
4456 s->override = R_ES;
4457 goto next_byte;
4458 case 0x64:
4459 s->override = R_FS;
4460 goto next_byte;
4461 case 0x65:
4462 s->override = R_GS;
4463 goto next_byte;
4464 case 0x66:
4465 prefixes |= PREFIX_DATA;
4466 goto next_byte;
4467 case 0x67:
4468 prefixes |= PREFIX_ADR;
4469 goto next_byte;
4470 #ifdef TARGET_X86_64
4471 case 0x40 ... 0x4f:
4472 if (CODE64(s)) {
4473 /* REX prefix */
4474 rex_w = (b >> 3) & 1;
4475 rex_r = (b & 0x4) << 1;
4476 s->rex_x = (b & 0x2) << 2;
4477 REX_B(s) = (b & 0x1) << 3;
4478 x86_64_hregs = 1; /* select uniform byte register addressing */
4479 goto next_byte;
4481 break;
4482 #endif
4483 case 0xc5: /* 2-byte VEX */
4484 case 0xc4: /* 3-byte VEX */
4485 /* VEX prefixes cannot be used except in 32-bit mode.
4486 Otherwise the instruction is LES or LDS. */
4487 if (s->code32 && !s->vm86) {
4488 static const int pp_prefix[4] = {
4489 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4491 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4493 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4494 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4495 otherwise the instruction is LES or LDS. */
4496 break;
4498 s->pc++;
4500 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4501 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4502 | PREFIX_LOCK | PREFIX_DATA)) {
4503 goto illegal_op;
4505 #ifdef TARGET_X86_64
4506 if (x86_64_hregs) {
4507 goto illegal_op;
4509 #endif
4510 rex_r = (~vex2 >> 4) & 8;
4511 if (b == 0xc5) {
4512 vex3 = vex2;
4513 b = cpu_ldub_code(env, s->pc++);
4514 } else {
4515 #ifdef TARGET_X86_64
4516 s->rex_x = (~vex2 >> 3) & 8;
4517 s->rex_b = (~vex2 >> 2) & 8;
4518 #endif
4519 vex3 = cpu_ldub_code(env, s->pc++);
4520 rex_w = (vex3 >> 7) & 1;
4521 switch (vex2 & 0x1f) {
4522 case 0x01: /* Implied 0f leading opcode bytes. */
4523 b = cpu_ldub_code(env, s->pc++) | 0x100;
4524 break;
4525 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4526 b = 0x138;
4527 break;
4528 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4529 b = 0x13a;
4530 break;
4531 default: /* Reserved for future use. */
4532 goto illegal_op;
4535 s->vex_v = (~vex3 >> 3) & 0xf;
4536 s->vex_l = (vex3 >> 2) & 1;
4537 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4539 break;
4542 /* Post-process prefixes. */
4543 if (CODE64(s)) {
4544 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4545 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4546 over 0x66 if both are present. */
4547 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4548 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4549 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4550 } else {
4551 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4552 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4553 dflag = MO_32;
4554 } else {
4555 dflag = MO_16;
4557 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4558 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4559 aflag = MO_32;
4560 } else {
4561 aflag = MO_16;
4565 s->prefix = prefixes;
4566 s->aflag = aflag;
4567 s->dflag = dflag;
4569 /* lock generation */
4570 if (prefixes & PREFIX_LOCK)
4571 gen_helper_lock();
4573 /* now check op code */
4574 reswitch:
4575 switch(b) {
4576 case 0x0f:
4577 /**************************/
4578 /* extended op code */
4579 b = cpu_ldub_code(env, s->pc++) | 0x100;
4580 goto reswitch;
4582 /**************************/
4583 /* arith & logic */
4584 case 0x00 ... 0x05:
4585 case 0x08 ... 0x0d:
4586 case 0x10 ... 0x15:
4587 case 0x18 ... 0x1d:
4588 case 0x20 ... 0x25:
4589 case 0x28 ... 0x2d:
4590 case 0x30 ... 0x35:
4591 case 0x38 ... 0x3d:
4593 int op, f, val;
4594 op = (b >> 3) & 7;
4595 f = (b >> 1) & 3;
4597 ot = mo_b_d(b, dflag);
4599 switch(f) {
4600 case 0: /* OP Ev, Gv */
4601 modrm = cpu_ldub_code(env, s->pc++);
4602 reg = ((modrm >> 3) & 7) | rex_r;
4603 mod = (modrm >> 6) & 3;
4604 rm = (modrm & 7) | REX_B(s);
4605 if (mod != 3) {
4606 gen_lea_modrm(env, s, modrm);
4607 opreg = OR_TMP0;
4608 } else if (op == OP_XORL && rm == reg) {
4609 xor_zero:
4610 /* xor reg, reg optimisation */
4611 set_cc_op(s, CC_OP_CLR);
4612 tcg_gen_movi_tl(cpu_T[0], 0);
4613 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4614 break;
4615 } else {
4616 opreg = rm;
4618 gen_op_mov_v_reg(ot, cpu_T[1], reg);
4619 gen_op(s, op, ot, opreg);
4620 break;
4621 case 1: /* OP Gv, Ev */
4622 modrm = cpu_ldub_code(env, s->pc++);
4623 mod = (modrm >> 6) & 3;
4624 reg = ((modrm >> 3) & 7) | rex_r;
4625 rm = (modrm & 7) | REX_B(s);
4626 if (mod != 3) {
4627 gen_lea_modrm(env, s, modrm);
4628 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4629 } else if (op == OP_XORL && rm == reg) {
4630 goto xor_zero;
4631 } else {
4632 gen_op_mov_v_reg(ot, cpu_T[1], rm);
4634 gen_op(s, op, ot, reg);
4635 break;
4636 case 2: /* OP A, Iv */
4637 val = insn_get(env, s, ot);
4638 tcg_gen_movi_tl(cpu_T[1], val);
4639 gen_op(s, op, ot, OR_EAX);
4640 break;
4643 break;
4645 case 0x82:
4646 if (CODE64(s))
4647 goto illegal_op;
4648 case 0x80: /* GRP1 */
4649 case 0x81:
4650 case 0x83:
4652 int val;
4654 ot = mo_b_d(b, dflag);
4656 modrm = cpu_ldub_code(env, s->pc++);
4657 mod = (modrm >> 6) & 3;
4658 rm = (modrm & 7) | REX_B(s);
4659 op = (modrm >> 3) & 7;
4661 if (mod != 3) {
4662 if (b == 0x83)
4663 s->rip_offset = 1;
4664 else
4665 s->rip_offset = insn_const_size(ot);
4666 gen_lea_modrm(env, s, modrm);
4667 opreg = OR_TMP0;
4668 } else {
4669 opreg = rm;
4672 switch(b) {
4673 default:
4674 case 0x80:
4675 case 0x81:
4676 case 0x82:
4677 val = insn_get(env, s, ot);
4678 break;
4679 case 0x83:
4680 val = (int8_t)insn_get(env, s, MO_8);
4681 break;
4683 tcg_gen_movi_tl(cpu_T[1], val);
4684 gen_op(s, op, ot, opreg);
4686 break;
4688 /**************************/
4689 /* inc, dec, and other misc arith */
4690 case 0x40 ... 0x47: /* inc Gv */
4691 ot = dflag;
4692 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4693 break;
4694 case 0x48 ... 0x4f: /* dec Gv */
4695 ot = dflag;
4696 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4697 break;
4698 case 0xf6: /* GRP3 */
4699 case 0xf7:
4700 ot = mo_b_d(b, dflag);
4702 modrm = cpu_ldub_code(env, s->pc++);
4703 mod = (modrm >> 6) & 3;
4704 rm = (modrm & 7) | REX_B(s);
4705 op = (modrm >> 3) & 7;
4706 if (mod != 3) {
4707 if (op == 0)
4708 s->rip_offset = insn_const_size(ot);
4709 gen_lea_modrm(env, s, modrm);
4710 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
4711 } else {
4712 gen_op_mov_v_reg(ot, cpu_T[0], rm);
4715 switch(op) {
4716 case 0: /* test */
4717 val = insn_get(env, s, ot);
4718 tcg_gen_movi_tl(cpu_T[1], val);
4719 gen_op_testl_T0_T1_cc();
4720 set_cc_op(s, CC_OP_LOGICB + ot);
4721 break;
4722 case 2: /* not */
4723 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
4724 if (mod != 3) {
4725 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
4726 } else {
4727 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4729 break;
4730 case 3: /* neg */
4731 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
4732 if (mod != 3) {
4733 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
4734 } else {
4735 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4737 gen_op_update_neg_cc();
4738 set_cc_op(s, CC_OP_SUBB + ot);
4739 break;
4740 case 4: /* mul */
4741 switch(ot) {
4742 case MO_8:
4743 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
4744 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4745 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4746 /* XXX: use 32 bit mul which could be faster */
4747 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4748 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4749 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4750 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
4751 set_cc_op(s, CC_OP_MULB);
4752 break;
4753 case MO_16:
4754 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
4755 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4756 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4757 /* XXX: use 32 bit mul which could be faster */
4758 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4759 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4760 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4761 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4762 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
4763 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4764 set_cc_op(s, CC_OP_MULW);
4765 break;
4766 default:
4767 case MO_32:
4768 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4769 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4770 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4771 cpu_tmp2_i32, cpu_tmp3_i32);
4772 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4773 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4774 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4775 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4776 set_cc_op(s, CC_OP_MULL);
4777 break;
4778 #ifdef TARGET_X86_64
4779 case MO_64:
4780 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4781 cpu_T[0], cpu_regs[R_EAX]);
4782 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4783 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4784 set_cc_op(s, CC_OP_MULQ);
4785 break;
4786 #endif
4788 break;
4789 case 5: /* imul */
4790 switch(ot) {
4791 case MO_8:
4792 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
4793 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4794 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
4795 /* XXX: use 32 bit mul which could be faster */
4796 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4797 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4798 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4799 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
4800 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4801 set_cc_op(s, CC_OP_MULB);
4802 break;
4803 case MO_16:
4804 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
4805 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4806 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4807 /* XXX: use 32 bit mul which could be faster */
4808 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4809 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4810 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4811 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4812 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4813 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4814 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
4815 set_cc_op(s, CC_OP_MULW);
4816 break;
4817 default:
4818 case MO_32:
4819 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4820 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4821 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4822 cpu_tmp2_i32, cpu_tmp3_i32);
4823 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4824 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4825 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4826 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4827 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4828 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4829 set_cc_op(s, CC_OP_MULL);
4830 break;
4831 #ifdef TARGET_X86_64
4832 case MO_64:
4833 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4834 cpu_T[0], cpu_regs[R_EAX]);
4835 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4836 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4837 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4838 set_cc_op(s, CC_OP_MULQ);
4839 break;
4840 #endif
4842 break;
4843 case 6: /* div */
4844 switch(ot) {
4845 case MO_8:
4846 gen_jmp_im(pc_start - s->cs_base);
4847 gen_helper_divb_AL(cpu_env, cpu_T[0]);
4848 break;
4849 case MO_16:
4850 gen_jmp_im(pc_start - s->cs_base);
4851 gen_helper_divw_AX(cpu_env, cpu_T[0]);
4852 break;
4853 default:
4854 case MO_32:
4855 gen_jmp_im(pc_start - s->cs_base);
4856 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
4857 break;
4858 #ifdef TARGET_X86_64
4859 case MO_64:
4860 gen_jmp_im(pc_start - s->cs_base);
4861 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
4862 break;
4863 #endif
4865 break;
4866 case 7: /* idiv */
4867 switch(ot) {
4868 case MO_8:
4869 gen_jmp_im(pc_start - s->cs_base);
4870 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
4871 break;
4872 case MO_16:
4873 gen_jmp_im(pc_start - s->cs_base);
4874 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
4875 break;
4876 default:
4877 case MO_32:
4878 gen_jmp_im(pc_start - s->cs_base);
4879 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
4880 break;
4881 #ifdef TARGET_X86_64
4882 case MO_64:
4883 gen_jmp_im(pc_start - s->cs_base);
4884 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
4885 break;
4886 #endif
4888 break;
4889 default:
4890 goto illegal_op;
4892 break;
4894 case 0xfe: /* GRP4 */
4895 case 0xff: /* GRP5 */
4896 ot = mo_b_d(b, dflag);
4898 modrm = cpu_ldub_code(env, s->pc++);
4899 mod = (modrm >> 6) & 3;
4900 rm = (modrm & 7) | REX_B(s);
4901 op = (modrm >> 3) & 7;
4902 if (op >= 2 && b == 0xfe) {
4903 goto illegal_op;
4905 if (CODE64(s)) {
4906 if (op == 2 || op == 4) {
4907 /* operand size for jumps is 64 bit */
4908 ot = MO_64;
4909 } else if (op == 3 || op == 5) {
4910 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
4911 } else if (op == 6) {
4912 /* default push size is 64 bit */
4913 ot = mo_pushpop(s, dflag);
4916 if (mod != 3) {
4917 gen_lea_modrm(env, s, modrm);
4918 if (op >= 2 && op != 3 && op != 5)
4919 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
4920 } else {
4921 gen_op_mov_v_reg(ot, cpu_T[0], rm);
4924 switch(op) {
4925 case 0: /* inc Ev */
4926 if (mod != 3)
4927 opreg = OR_TMP0;
4928 else
4929 opreg = rm;
4930 gen_inc(s, ot, opreg, 1);
4931 break;
4932 case 1: /* dec Ev */
4933 if (mod != 3)
4934 opreg = OR_TMP0;
4935 else
4936 opreg = rm;
4937 gen_inc(s, ot, opreg, -1);
4938 break;
4939 case 2: /* call Ev */
4940 /* XXX: optimize if memory (no 'and' is necessary) */
4941 if (dflag == MO_16) {
4942 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4944 next_eip = s->pc - s->cs_base;
4945 tcg_gen_movi_tl(cpu_T[1], next_eip);
4946 gen_push_v(s, cpu_T[1]);
4947 gen_op_jmp_v(cpu_T[0]);
4948 gen_eob(s);
4949 break;
4950 case 3: /* lcall Ev */
4951 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4952 gen_add_A0_im(s, 1 << ot);
4953 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
4954 do_lcall:
4955 if (s->pe && !s->vm86) {
4956 gen_update_cc_op(s);
4957 gen_jmp_im(pc_start - s->cs_base);
4958 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4959 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4960 tcg_const_i32(dflag - 1),
4961 tcg_const_i32(s->pc - pc_start));
4962 } else {
4963 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4964 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
4965 tcg_const_i32(dflag - 1),
4966 tcg_const_i32(s->pc - s->cs_base));
4968 gen_eob(s);
4969 break;
4970 case 4: /* jmp Ev */
4971 if (dflag == MO_16) {
4972 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4974 gen_op_jmp_v(cpu_T[0]);
4975 gen_eob(s);
4976 break;
4977 case 5: /* ljmp Ev */
4978 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4979 gen_add_A0_im(s, 1 << ot);
4980 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
4981 do_ljmp:
4982 if (s->pe && !s->vm86) {
4983 gen_update_cc_op(s);
4984 gen_jmp_im(pc_start - s->cs_base);
4985 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4986 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4987 tcg_const_i32(s->pc - pc_start));
4988 } else {
4989 gen_op_movl_seg_T0_vm(R_CS);
4990 gen_op_jmp_v(cpu_T[1]);
4992 gen_eob(s);
4993 break;
4994 case 6: /* push Ev */
4995 gen_push_v(s, cpu_T[0]);
4996 break;
4997 default:
4998 goto illegal_op;
5000 break;
5002 case 0x84: /* test Ev, Gv */
5003 case 0x85:
5004 ot = mo_b_d(b, dflag);
5006 modrm = cpu_ldub_code(env, s->pc++);
5007 reg = ((modrm >> 3) & 7) | rex_r;
5009 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5010 gen_op_mov_v_reg(ot, cpu_T[1], reg);
5011 gen_op_testl_T0_T1_cc();
5012 set_cc_op(s, CC_OP_LOGICB + ot);
5013 break;
5015 case 0xa8: /* test eAX, Iv */
5016 case 0xa9:
5017 ot = mo_b_d(b, dflag);
5018 val = insn_get(env, s, ot);
5020 gen_op_mov_v_reg(ot, cpu_T[0], OR_EAX);
5021 tcg_gen_movi_tl(cpu_T[1], val);
5022 gen_op_testl_T0_T1_cc();
5023 set_cc_op(s, CC_OP_LOGICB + ot);
5024 break;
5026 case 0x98: /* CWDE/CBW */
5027 switch (dflag) {
5028 #ifdef TARGET_X86_64
5029 case MO_64:
5030 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
5031 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5032 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T[0]);
5033 break;
5034 #endif
5035 case MO_32:
5036 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
5037 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5038 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T[0]);
5039 break;
5040 case MO_16:
5041 gen_op_mov_v_reg(MO_8, cpu_T[0], R_EAX);
5042 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5043 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
5044 break;
5045 default:
5046 tcg_abort();
5048 break;
5049 case 0x99: /* CDQ/CWD */
5050 switch (dflag) {
5051 #ifdef TARGET_X86_64
5052 case MO_64:
5053 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EAX);
5054 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
5055 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T[0]);
5056 break;
5057 #endif
5058 case MO_32:
5059 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
5060 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5061 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
5062 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T[0]);
5063 break;
5064 case MO_16:
5065 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
5066 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5067 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
5068 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
5069 break;
5070 default:
5071 tcg_abort();
5073 break;
5074 case 0x1af: /* imul Gv, Ev */
5075 case 0x69: /* imul Gv, Ev, I */
5076 case 0x6b:
5077 ot = dflag;
5078 modrm = cpu_ldub_code(env, s->pc++);
5079 reg = ((modrm >> 3) & 7) | rex_r;
5080 if (b == 0x69)
5081 s->rip_offset = insn_const_size(ot);
5082 else if (b == 0x6b)
5083 s->rip_offset = 1;
5084 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5085 if (b == 0x69) {
5086 val = insn_get(env, s, ot);
5087 tcg_gen_movi_tl(cpu_T[1], val);
5088 } else if (b == 0x6b) {
5089 val = (int8_t)insn_get(env, s, MO_8);
5090 tcg_gen_movi_tl(cpu_T[1], val);
5091 } else {
5092 gen_op_mov_v_reg(ot, cpu_T[1], reg);
5094 switch (ot) {
5095 #ifdef TARGET_X86_64
5096 case MO_64:
5097 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
5098 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5099 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5100 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
5101 break;
5102 #endif
5103 case MO_32:
5104 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5105 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5106 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5107 cpu_tmp2_i32, cpu_tmp3_i32);
5108 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5109 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5110 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5111 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5112 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5113 break;
5114 default:
5115 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5116 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5117 /* XXX: use 32 bit mul which could be faster */
5118 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5119 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5120 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5121 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5122 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5123 break;
5125 set_cc_op(s, CC_OP_MULB + ot);
5126 break;
5127 case 0x1c0:
5128 case 0x1c1: /* xadd Ev, Gv */
5129 ot = mo_b_d(b, dflag);
5130 modrm = cpu_ldub_code(env, s->pc++);
5131 reg = ((modrm >> 3) & 7) | rex_r;
5132 mod = (modrm >> 6) & 3;
5133 if (mod == 3) {
5134 rm = (modrm & 7) | REX_B(s);
5135 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5136 gen_op_mov_v_reg(ot, cpu_T[1], rm);
5137 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5138 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5139 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5140 } else {
5141 gen_lea_modrm(env, s, modrm);
5142 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5143 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5144 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5145 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5146 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5148 gen_op_update2_cc();
5149 set_cc_op(s, CC_OP_ADDB + ot);
5150 break;
5151 case 0x1b0:
5152 case 0x1b1: /* cmpxchg Ev, Gv */
5154 TCGLabel *label1, *label2;
5155 TCGv t0, t1, t2, a0;
5157 ot = mo_b_d(b, dflag);
5158 modrm = cpu_ldub_code(env, s->pc++);
5159 reg = ((modrm >> 3) & 7) | rex_r;
5160 mod = (modrm >> 6) & 3;
5161 t0 = tcg_temp_local_new();
5162 t1 = tcg_temp_local_new();
5163 t2 = tcg_temp_local_new();
5164 a0 = tcg_temp_local_new();
5165 gen_op_mov_v_reg(ot, t1, reg);
5166 if (mod == 3) {
5167 rm = (modrm & 7) | REX_B(s);
5168 gen_op_mov_v_reg(ot, t0, rm);
5169 } else {
5170 gen_lea_modrm(env, s, modrm);
5171 tcg_gen_mov_tl(a0, cpu_A0);
5172 gen_op_ld_v(s, ot, t0, a0);
5173 rm = 0; /* avoid warning */
5175 label1 = gen_new_label();
5176 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5177 gen_extu(ot, t0);
5178 gen_extu(ot, t2);
5179 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
5180 label2 = gen_new_label();
5181 if (mod == 3) {
5182 gen_op_mov_reg_v(ot, R_EAX, t0);
5183 tcg_gen_br(label2);
5184 gen_set_label(label1);
5185 gen_op_mov_reg_v(ot, rm, t1);
5186 } else {
5187 /* perform no-op store cycle like physical cpu; must be
5188 before changing accumulator to ensure idempotency if
5189 the store faults and the instruction is restarted */
5190 gen_op_st_v(s, ot, t0, a0);
5191 gen_op_mov_reg_v(ot, R_EAX, t0);
5192 tcg_gen_br(label2);
5193 gen_set_label(label1);
5194 gen_op_st_v(s, ot, t1, a0);
5196 gen_set_label(label2);
5197 tcg_gen_mov_tl(cpu_cc_src, t0);
5198 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5199 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
5200 set_cc_op(s, CC_OP_SUBB + ot);
5201 tcg_temp_free(t0);
5202 tcg_temp_free(t1);
5203 tcg_temp_free(t2);
5204 tcg_temp_free(a0);
5206 break;
5207 case 0x1c7: /* cmpxchg8b */
5208 modrm = cpu_ldub_code(env, s->pc++);
5209 mod = (modrm >> 6) & 3;
5210 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5211 goto illegal_op;
5212 #ifdef TARGET_X86_64
5213 if (dflag == MO_64) {
5214 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5215 goto illegal_op;
5216 gen_jmp_im(pc_start - s->cs_base);
5217 gen_update_cc_op(s);
5218 gen_lea_modrm(env, s, modrm);
5219 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5220 } else
5221 #endif
5223 if (!(s->cpuid_features & CPUID_CX8))
5224 goto illegal_op;
5225 gen_jmp_im(pc_start - s->cs_base);
5226 gen_update_cc_op(s);
5227 gen_lea_modrm(env, s, modrm);
5228 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5230 set_cc_op(s, CC_OP_EFLAGS);
5231 break;
5233 /**************************/
5234 /* push/pop */
5235 case 0x50 ... 0x57: /* push */
5236 gen_op_mov_v_reg(MO_32, cpu_T[0], (b & 7) | REX_B(s));
5237 gen_push_v(s, cpu_T[0]);
5238 break;
5239 case 0x58 ... 0x5f: /* pop */
5240 ot = gen_pop_T0(s);
5241 /* NOTE: order is important for pop %sp */
5242 gen_pop_update(s, ot);
5243 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T[0]);
5244 break;
5245 case 0x60: /* pusha */
5246 if (CODE64(s))
5247 goto illegal_op;
5248 gen_pusha(s);
5249 break;
5250 case 0x61: /* popa */
5251 if (CODE64(s))
5252 goto illegal_op;
5253 gen_popa(s);
5254 break;
5255 case 0x68: /* push Iv */
5256 case 0x6a:
5257 ot = mo_pushpop(s, dflag);
5258 if (b == 0x68)
5259 val = insn_get(env, s, ot);
5260 else
5261 val = (int8_t)insn_get(env, s, MO_8);
5262 tcg_gen_movi_tl(cpu_T[0], val);
5263 gen_push_v(s, cpu_T[0]);
5264 break;
5265 case 0x8f: /* pop Ev */
5266 modrm = cpu_ldub_code(env, s->pc++);
5267 mod = (modrm >> 6) & 3;
5268 ot = gen_pop_T0(s);
5269 if (mod == 3) {
5270 /* NOTE: order is important for pop %sp */
5271 gen_pop_update(s, ot);
5272 rm = (modrm & 7) | REX_B(s);
5273 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5274 } else {
5275 /* NOTE: order is important too for MMU exceptions */
5276 s->popl_esp_hack = 1 << ot;
5277 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5278 s->popl_esp_hack = 0;
5279 gen_pop_update(s, ot);
5281 break;
5282 case 0xc8: /* enter */
5284 int level;
5285 val = cpu_lduw_code(env, s->pc);
5286 s->pc += 2;
5287 level = cpu_ldub_code(env, s->pc++);
5288 gen_enter(s, val, level);
5290 break;
5291 case 0xc9: /* leave */
5292 /* XXX: exception not precise (ESP is updated before potential exception) */
5293 if (CODE64(s)) {
5294 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EBP);
5295 gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[0]);
5296 } else if (s->ss32) {
5297 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
5298 gen_op_mov_reg_v(MO_32, R_ESP, cpu_T[0]);
5299 } else {
5300 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EBP);
5301 gen_op_mov_reg_v(MO_16, R_ESP, cpu_T[0]);
5303 ot = gen_pop_T0(s);
5304 gen_op_mov_reg_v(ot, R_EBP, cpu_T[0]);
5305 gen_pop_update(s, ot);
5306 break;
5307 case 0x06: /* push es */
5308 case 0x0e: /* push cs */
5309 case 0x16: /* push ss */
5310 case 0x1e: /* push ds */
5311 if (CODE64(s))
5312 goto illegal_op;
5313 gen_op_movl_T0_seg(b >> 3);
5314 gen_push_v(s, cpu_T[0]);
5315 break;
5316 case 0x1a0: /* push fs */
5317 case 0x1a8: /* push gs */
5318 gen_op_movl_T0_seg((b >> 3) & 7);
5319 gen_push_v(s, cpu_T[0]);
5320 break;
5321 case 0x07: /* pop es */
5322 case 0x17: /* pop ss */
5323 case 0x1f: /* pop ds */
5324 if (CODE64(s))
5325 goto illegal_op;
5326 reg = b >> 3;
5327 ot = gen_pop_T0(s);
5328 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5329 gen_pop_update(s, ot);
5330 if (reg == R_SS) {
5331 /* if reg == SS, inhibit interrupts/trace. */
5332 /* If several instructions disable interrupts, only the
5333 _first_ does it */
5334 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5335 gen_helper_set_inhibit_irq(cpu_env);
5336 s->tf = 0;
5338 if (s->is_jmp) {
5339 gen_jmp_im(s->pc - s->cs_base);
5340 gen_eob(s);
5342 break;
5343 case 0x1a1: /* pop fs */
5344 case 0x1a9: /* pop gs */
5345 ot = gen_pop_T0(s);
5346 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
5347 gen_pop_update(s, ot);
5348 if (s->is_jmp) {
5349 gen_jmp_im(s->pc - s->cs_base);
5350 gen_eob(s);
5352 break;
5354 /**************************/
5355 /* mov */
5356 case 0x88:
5357 case 0x89: /* mov Gv, Ev */
5358 ot = mo_b_d(b, dflag);
5359 modrm = cpu_ldub_code(env, s->pc++);
5360 reg = ((modrm >> 3) & 7) | rex_r;
5362 /* generate a generic store */
5363 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5364 break;
5365 case 0xc6:
5366 case 0xc7: /* mov Ev, Iv */
5367 ot = mo_b_d(b, dflag);
5368 modrm = cpu_ldub_code(env, s->pc++);
5369 mod = (modrm >> 6) & 3;
5370 if (mod != 3) {
5371 s->rip_offset = insn_const_size(ot);
5372 gen_lea_modrm(env, s, modrm);
5374 val = insn_get(env, s, ot);
5375 tcg_gen_movi_tl(cpu_T[0], val);
5376 if (mod != 3) {
5377 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5378 } else {
5379 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T[0]);
5381 break;
5382 case 0x8a:
5383 case 0x8b: /* mov Ev, Gv */
5384 ot = mo_b_d(b, dflag);
5385 modrm = cpu_ldub_code(env, s->pc++);
5386 reg = ((modrm >> 3) & 7) | rex_r;
5388 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5389 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5390 break;
5391 case 0x8e: /* mov seg, Gv */
5392 modrm = cpu_ldub_code(env, s->pc++);
5393 reg = (modrm >> 3) & 7;
5394 if (reg >= 6 || reg == R_CS)
5395 goto illegal_op;
5396 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5397 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5398 if (reg == R_SS) {
5399 /* if reg == SS, inhibit interrupts/trace */
5400 /* If several instructions disable interrupts, only the
5401 _first_ does it */
5402 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5403 gen_helper_set_inhibit_irq(cpu_env);
5404 s->tf = 0;
5406 if (s->is_jmp) {
5407 gen_jmp_im(s->pc - s->cs_base);
5408 gen_eob(s);
5410 break;
5411 case 0x8c: /* mov Gv, seg */
5412 modrm = cpu_ldub_code(env, s->pc++);
5413 reg = (modrm >> 3) & 7;
5414 mod = (modrm >> 6) & 3;
5415 if (reg >= 6)
5416 goto illegal_op;
5417 gen_op_movl_T0_seg(reg);
5418 ot = mod == 3 ? dflag : MO_16;
5419 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5420 break;
5422 case 0x1b6: /* movzbS Gv, Eb */
5423 case 0x1b7: /* movzwS Gv, Eb */
5424 case 0x1be: /* movsbS Gv, Eb */
5425 case 0x1bf: /* movswS Gv, Eb */
5427 TCGMemOp d_ot;
5428 TCGMemOp s_ot;
5430 /* d_ot is the size of destination */
5431 d_ot = dflag;
5432 /* ot is the size of source */
5433 ot = (b & 1) + MO_8;
5434 /* s_ot is the sign+size of source */
5435 s_ot = b & 8 ? MO_SIGN | ot : ot;
5437 modrm = cpu_ldub_code(env, s->pc++);
5438 reg = ((modrm >> 3) & 7) | rex_r;
5439 mod = (modrm >> 6) & 3;
5440 rm = (modrm & 7) | REX_B(s);
5442 if (mod == 3) {
5443 gen_op_mov_v_reg(ot, cpu_T[0], rm);
5444 switch (s_ot) {
5445 case MO_UB:
5446 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
5447 break;
5448 case MO_SB:
5449 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5450 break;
5451 case MO_UW:
5452 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
5453 break;
5454 default:
5455 case MO_SW:
5456 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5457 break;
5459 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
5460 } else {
5461 gen_lea_modrm(env, s, modrm);
5462 gen_op_ld_v(s, s_ot, cpu_T[0], cpu_A0);
5463 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
5466 break;
5468 case 0x8d: /* lea */
5469 ot = dflag;
5470 modrm = cpu_ldub_code(env, s->pc++);
5471 mod = (modrm >> 6) & 3;
5472 if (mod == 3)
5473 goto illegal_op;
5474 reg = ((modrm >> 3) & 7) | rex_r;
5475 /* we must ensure that no segment is added */
5476 s->override = -1;
5477 val = s->addseg;
5478 s->addseg = 0;
5479 gen_lea_modrm(env, s, modrm);
5480 s->addseg = val;
5481 gen_op_mov_reg_v(ot, reg, cpu_A0);
5482 break;
5484 case 0xa0: /* mov EAX, Ov */
5485 case 0xa1:
5486 case 0xa2: /* mov Ov, EAX */
5487 case 0xa3:
5489 target_ulong offset_addr;
5491 ot = mo_b_d(b, dflag);
5492 switch (s->aflag) {
5493 #ifdef TARGET_X86_64
5494 case MO_64:
5495 offset_addr = cpu_ldq_code(env, s->pc);
5496 s->pc += 8;
5497 break;
5498 #endif
5499 default:
5500 offset_addr = insn_get(env, s, s->aflag);
5501 break;
5503 tcg_gen_movi_tl(cpu_A0, offset_addr);
5504 gen_add_A0_ds_seg(s);
5505 if ((b & 2) == 0) {
5506 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
5507 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
5508 } else {
5509 gen_op_mov_v_reg(ot, cpu_T[0], R_EAX);
5510 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5513 break;
5514 case 0xd7: /* xlat */
5515 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5516 tcg_gen_ext8u_tl(cpu_T[0], cpu_regs[R_EAX]);
5517 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5518 gen_extu(s->aflag, cpu_A0);
5519 gen_add_A0_ds_seg(s);
5520 gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
5521 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
5522 break;
5523 case 0xb0 ... 0xb7: /* mov R, Ib */
5524 val = insn_get(env, s, MO_8);
5525 tcg_gen_movi_tl(cpu_T[0], val);
5526 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T[0]);
5527 break;
5528 case 0xb8 ... 0xbf: /* mov R, Iv */
5529 #ifdef TARGET_X86_64
5530 if (dflag == MO_64) {
5531 uint64_t tmp;
5532 /* 64 bit case */
5533 tmp = cpu_ldq_code(env, s->pc);
5534 s->pc += 8;
5535 reg = (b & 7) | REX_B(s);
5536 tcg_gen_movi_tl(cpu_T[0], tmp);
5537 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
5538 } else
5539 #endif
5541 ot = dflag;
5542 val = insn_get(env, s, ot);
5543 reg = (b & 7) | REX_B(s);
5544 tcg_gen_movi_tl(cpu_T[0], val);
5545 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5547 break;
5549 case 0x91 ... 0x97: /* xchg R, EAX */
5550 do_xchg_reg_eax:
5551 ot = dflag;
5552 reg = (b & 7) | REX_B(s);
5553 rm = R_EAX;
5554 goto do_xchg_reg;
5555 case 0x86:
5556 case 0x87: /* xchg Ev, Gv */
5557 ot = mo_b_d(b, dflag);
5558 modrm = cpu_ldub_code(env, s->pc++);
5559 reg = ((modrm >> 3) & 7) | rex_r;
5560 mod = (modrm >> 6) & 3;
5561 if (mod == 3) {
5562 rm = (modrm & 7) | REX_B(s);
5563 do_xchg_reg:
5564 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5565 gen_op_mov_v_reg(ot, cpu_T[1], rm);
5566 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5567 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5568 } else {
5569 gen_lea_modrm(env, s, modrm);
5570 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5571 /* for xchg, lock is implicit */
5572 if (!(prefixes & PREFIX_LOCK))
5573 gen_helper_lock();
5574 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5575 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5576 if (!(prefixes & PREFIX_LOCK))
5577 gen_helper_unlock();
5578 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5580 break;
5581 case 0xc4: /* les Gv */
5582 /* In CODE64 this is VEX3; see above. */
5583 op = R_ES;
5584 goto do_lxx;
5585 case 0xc5: /* lds Gv */
5586 /* In CODE64 this is VEX2; see above. */
5587 op = R_DS;
5588 goto do_lxx;
5589 case 0x1b2: /* lss Gv */
5590 op = R_SS;
5591 goto do_lxx;
5592 case 0x1b4: /* lfs Gv */
5593 op = R_FS;
5594 goto do_lxx;
5595 case 0x1b5: /* lgs Gv */
5596 op = R_GS;
5597 do_lxx:
5598 ot = dflag != MO_16 ? MO_32 : MO_16;
5599 modrm = cpu_ldub_code(env, s->pc++);
5600 reg = ((modrm >> 3) & 7) | rex_r;
5601 mod = (modrm >> 6) & 3;
5602 if (mod == 3)
5603 goto illegal_op;
5604 gen_lea_modrm(env, s, modrm);
5605 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5606 gen_add_A0_im(s, 1 << ot);
5607 /* load the segment first to handle exceptions properly */
5608 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
5609 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5610 /* then put the data */
5611 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5612 if (s->is_jmp) {
5613 gen_jmp_im(s->pc - s->cs_base);
5614 gen_eob(s);
5616 break;
5618 /************************/
5619 /* shifts */
5620 case 0xc0:
5621 case 0xc1:
5622 /* shift Ev,Ib */
5623 shift = 2;
5624 grp2:
5626 ot = mo_b_d(b, dflag);
5627 modrm = cpu_ldub_code(env, s->pc++);
5628 mod = (modrm >> 6) & 3;
5629 op = (modrm >> 3) & 7;
5631 if (mod != 3) {
5632 if (shift == 2) {
5633 s->rip_offset = 1;
5635 gen_lea_modrm(env, s, modrm);
5636 opreg = OR_TMP0;
5637 } else {
5638 opreg = (modrm & 7) | REX_B(s);
5641 /* simpler op */
5642 if (shift == 0) {
5643 gen_shift(s, op, ot, opreg, OR_ECX);
5644 } else {
5645 if (shift == 2) {
5646 shift = cpu_ldub_code(env, s->pc++);
5648 gen_shifti(s, op, ot, opreg, shift);
5651 break;
5652 case 0xd0:
5653 case 0xd1:
5654 /* shift Ev,1 */
5655 shift = 1;
5656 goto grp2;
5657 case 0xd2:
5658 case 0xd3:
5659 /* shift Ev,cl */
5660 shift = 0;
5661 goto grp2;
5663 case 0x1a4: /* shld imm */
5664 op = 0;
5665 shift = 1;
5666 goto do_shiftd;
5667 case 0x1a5: /* shld cl */
5668 op = 0;
5669 shift = 0;
5670 goto do_shiftd;
5671 case 0x1ac: /* shrd imm */
5672 op = 1;
5673 shift = 1;
5674 goto do_shiftd;
5675 case 0x1ad: /* shrd cl */
5676 op = 1;
5677 shift = 0;
5678 do_shiftd:
5679 ot = dflag;
5680 modrm = cpu_ldub_code(env, s->pc++);
5681 mod = (modrm >> 6) & 3;
5682 rm = (modrm & 7) | REX_B(s);
5683 reg = ((modrm >> 3) & 7) | rex_r;
5684 if (mod != 3) {
5685 gen_lea_modrm(env, s, modrm);
5686 opreg = OR_TMP0;
5687 } else {
5688 opreg = rm;
5690 gen_op_mov_v_reg(ot, cpu_T[1], reg);
5692 if (shift) {
5693 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5694 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5695 tcg_temp_free(imm);
5696 } else {
5697 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5699 break;
5701 /************************/
5702 /* floats */
5703 case 0xd8 ... 0xdf:
5704 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5705 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5706 /* XXX: what to do if illegal op ? */
5707 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5708 break;
5710 modrm = cpu_ldub_code(env, s->pc++);
5711 mod = (modrm >> 6) & 3;
5712 rm = modrm & 7;
5713 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5714 if (mod != 3) {
5715 /* memory op */
5716 gen_lea_modrm(env, s, modrm);
5717 switch(op) {
5718 case 0x00 ... 0x07: /* fxxxs */
5719 case 0x10 ... 0x17: /* fixxxl */
5720 case 0x20 ... 0x27: /* fxxxl */
5721 case 0x30 ... 0x37: /* fixxx */
5723 int op1;
5724 op1 = op & 7;
5726 switch(op >> 4) {
5727 case 0:
5728 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5729 s->mem_index, MO_LEUL);
5730 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5731 break;
5732 case 1:
5733 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5734 s->mem_index, MO_LEUL);
5735 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5736 break;
5737 case 2:
5738 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5739 s->mem_index, MO_LEQ);
5740 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5741 break;
5742 case 3:
5743 default:
5744 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5745 s->mem_index, MO_LESW);
5746 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5747 break;
5750 gen_helper_fp_arith_ST0_FT0(op1);
5751 if (op1 == 3) {
5752 /* fcomp needs pop */
5753 gen_helper_fpop(cpu_env);
5756 break;
5757 case 0x08: /* flds */
5758 case 0x0a: /* fsts */
5759 case 0x0b: /* fstps */
5760 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5761 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5762 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5763 switch(op & 7) {
5764 case 0:
5765 switch(op >> 4) {
5766 case 0:
5767 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5768 s->mem_index, MO_LEUL);
5769 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5770 break;
5771 case 1:
5772 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5773 s->mem_index, MO_LEUL);
5774 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5775 break;
5776 case 2:
5777 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5778 s->mem_index, MO_LEQ);
5779 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5780 break;
5781 case 3:
5782 default:
5783 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5784 s->mem_index, MO_LESW);
5785 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5786 break;
5788 break;
5789 case 1:
5790 /* XXX: the corresponding CPUID bit must be tested ! */
5791 switch(op >> 4) {
5792 case 1:
5793 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5794 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5795 s->mem_index, MO_LEUL);
5796 break;
5797 case 2:
5798 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5799 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5800 s->mem_index, MO_LEQ);
5801 break;
5802 case 3:
5803 default:
5804 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5805 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5806 s->mem_index, MO_LEUW);
5807 break;
5809 gen_helper_fpop(cpu_env);
5810 break;
5811 default:
5812 switch(op >> 4) {
5813 case 0:
5814 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5815 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5816 s->mem_index, MO_LEUL);
5817 break;
5818 case 1:
5819 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5820 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5821 s->mem_index, MO_LEUL);
5822 break;
5823 case 2:
5824 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5825 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5826 s->mem_index, MO_LEQ);
5827 break;
5828 case 3:
5829 default:
5830 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5831 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5832 s->mem_index, MO_LEUW);
5833 break;
5835 if ((op & 7) == 3)
5836 gen_helper_fpop(cpu_env);
5837 break;
5839 break;
5840 case 0x0c: /* fldenv mem */
5841 gen_update_cc_op(s);
5842 gen_jmp_im(pc_start - s->cs_base);
5843 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5844 break;
5845 case 0x0d: /* fldcw mem */
5846 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5847 s->mem_index, MO_LEUW);
5848 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5849 break;
5850 case 0x0e: /* fnstenv mem */
5851 gen_update_cc_op(s);
5852 gen_jmp_im(pc_start - s->cs_base);
5853 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5854 break;
5855 case 0x0f: /* fnstcw mem */
5856 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5857 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5858 s->mem_index, MO_LEUW);
5859 break;
5860 case 0x1d: /* fldt mem */
5861 gen_update_cc_op(s);
5862 gen_jmp_im(pc_start - s->cs_base);
5863 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5864 break;
5865 case 0x1f: /* fstpt mem */
5866 gen_update_cc_op(s);
5867 gen_jmp_im(pc_start - s->cs_base);
5868 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5869 gen_helper_fpop(cpu_env);
5870 break;
5871 case 0x2c: /* frstor mem */
5872 gen_update_cc_op(s);
5873 gen_jmp_im(pc_start - s->cs_base);
5874 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5875 break;
5876 case 0x2e: /* fnsave mem */
5877 gen_update_cc_op(s);
5878 gen_jmp_im(pc_start - s->cs_base);
5879 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5880 break;
5881 case 0x2f: /* fnstsw mem */
5882 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5883 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5884 s->mem_index, MO_LEUW);
5885 break;
5886 case 0x3c: /* fbld */
5887 gen_update_cc_op(s);
5888 gen_jmp_im(pc_start - s->cs_base);
5889 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5890 break;
5891 case 0x3e: /* fbstp */
5892 gen_update_cc_op(s);
5893 gen_jmp_im(pc_start - s->cs_base);
5894 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5895 gen_helper_fpop(cpu_env);
5896 break;
5897 case 0x3d: /* fildll */
5898 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5899 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5900 break;
5901 case 0x3f: /* fistpll */
5902 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5903 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5904 gen_helper_fpop(cpu_env);
5905 break;
5906 default:
5907 goto illegal_op;
5909 } else {
5910 /* register float ops */
5911 opreg = rm;
5913 switch(op) {
5914 case 0x08: /* fld sti */
5915 gen_helper_fpush(cpu_env);
5916 gen_helper_fmov_ST0_STN(cpu_env,
5917 tcg_const_i32((opreg + 1) & 7));
5918 break;
5919 case 0x09: /* fxchg sti */
5920 case 0x29: /* fxchg4 sti, undocumented op */
5921 case 0x39: /* fxchg7 sti, undocumented op */
5922 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5923 break;
5924 case 0x0a: /* grp d9/2 */
5925 switch(rm) {
5926 case 0: /* fnop */
5927 /* check exceptions (FreeBSD FPU probe) */
5928 gen_update_cc_op(s);
5929 gen_jmp_im(pc_start - s->cs_base);
5930 gen_helper_fwait(cpu_env);
5931 break;
5932 default:
5933 goto illegal_op;
5935 break;
5936 case 0x0c: /* grp d9/4 */
5937 switch(rm) {
5938 case 0: /* fchs */
5939 gen_helper_fchs_ST0(cpu_env);
5940 break;
5941 case 1: /* fabs */
5942 gen_helper_fabs_ST0(cpu_env);
5943 break;
5944 case 4: /* ftst */
5945 gen_helper_fldz_FT0(cpu_env);
5946 gen_helper_fcom_ST0_FT0(cpu_env);
5947 break;
5948 case 5: /* fxam */
5949 gen_helper_fxam_ST0(cpu_env);
5950 break;
5951 default:
5952 goto illegal_op;
5954 break;
5955 case 0x0d: /* grp d9/5 */
5957 switch(rm) {
5958 case 0:
5959 gen_helper_fpush(cpu_env);
5960 gen_helper_fld1_ST0(cpu_env);
5961 break;
5962 case 1:
5963 gen_helper_fpush(cpu_env);
5964 gen_helper_fldl2t_ST0(cpu_env);
5965 break;
5966 case 2:
5967 gen_helper_fpush(cpu_env);
5968 gen_helper_fldl2e_ST0(cpu_env);
5969 break;
5970 case 3:
5971 gen_helper_fpush(cpu_env);
5972 gen_helper_fldpi_ST0(cpu_env);
5973 break;
5974 case 4:
5975 gen_helper_fpush(cpu_env);
5976 gen_helper_fldlg2_ST0(cpu_env);
5977 break;
5978 case 5:
5979 gen_helper_fpush(cpu_env);
5980 gen_helper_fldln2_ST0(cpu_env);
5981 break;
5982 case 6:
5983 gen_helper_fpush(cpu_env);
5984 gen_helper_fldz_ST0(cpu_env);
5985 break;
5986 default:
5987 goto illegal_op;
5990 break;
5991 case 0x0e: /* grp d9/6 */
5992 switch(rm) {
5993 case 0: /* f2xm1 */
5994 gen_helper_f2xm1(cpu_env);
5995 break;
5996 case 1: /* fyl2x */
5997 gen_helper_fyl2x(cpu_env);
5998 break;
5999 case 2: /* fptan */
6000 gen_helper_fptan(cpu_env);
6001 break;
6002 case 3: /* fpatan */
6003 gen_helper_fpatan(cpu_env);
6004 break;
6005 case 4: /* fxtract */
6006 gen_helper_fxtract(cpu_env);
6007 break;
6008 case 5: /* fprem1 */
6009 gen_helper_fprem1(cpu_env);
6010 break;
6011 case 6: /* fdecstp */
6012 gen_helper_fdecstp(cpu_env);
6013 break;
6014 default:
6015 case 7: /* fincstp */
6016 gen_helper_fincstp(cpu_env);
6017 break;
6019 break;
6020 case 0x0f: /* grp d9/7 */
6021 switch(rm) {
6022 case 0: /* fprem */
6023 gen_helper_fprem(cpu_env);
6024 break;
6025 case 1: /* fyl2xp1 */
6026 gen_helper_fyl2xp1(cpu_env);
6027 break;
6028 case 2: /* fsqrt */
6029 gen_helper_fsqrt(cpu_env);
6030 break;
6031 case 3: /* fsincos */
6032 gen_helper_fsincos(cpu_env);
6033 break;
6034 case 5: /* fscale */
6035 gen_helper_fscale(cpu_env);
6036 break;
6037 case 4: /* frndint */
6038 gen_helper_frndint(cpu_env);
6039 break;
6040 case 6: /* fsin */
6041 gen_helper_fsin(cpu_env);
6042 break;
6043 default:
6044 case 7: /* fcos */
6045 gen_helper_fcos(cpu_env);
6046 break;
6048 break;
6049 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6050 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6051 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6053 int op1;
6055 op1 = op & 7;
6056 if (op >= 0x20) {
6057 gen_helper_fp_arith_STN_ST0(op1, opreg);
6058 if (op >= 0x30)
6059 gen_helper_fpop(cpu_env);
6060 } else {
6061 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6062 gen_helper_fp_arith_ST0_FT0(op1);
6065 break;
6066 case 0x02: /* fcom */
6067 case 0x22: /* fcom2, undocumented op */
6068 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6069 gen_helper_fcom_ST0_FT0(cpu_env);
6070 break;
6071 case 0x03: /* fcomp */
6072 case 0x23: /* fcomp3, undocumented op */
6073 case 0x32: /* fcomp5, undocumented op */
6074 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6075 gen_helper_fcom_ST0_FT0(cpu_env);
6076 gen_helper_fpop(cpu_env);
6077 break;
6078 case 0x15: /* da/5 */
6079 switch(rm) {
6080 case 1: /* fucompp */
6081 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6082 gen_helper_fucom_ST0_FT0(cpu_env);
6083 gen_helper_fpop(cpu_env);
6084 gen_helper_fpop(cpu_env);
6085 break;
6086 default:
6087 goto illegal_op;
6089 break;
6090 case 0x1c:
6091 switch(rm) {
6092 case 0: /* feni (287 only, just do nop here) */
6093 break;
6094 case 1: /* fdisi (287 only, just do nop here) */
6095 break;
6096 case 2: /* fclex */
6097 gen_helper_fclex(cpu_env);
6098 break;
6099 case 3: /* fninit */
6100 gen_helper_fninit(cpu_env);
6101 break;
6102 case 4: /* fsetpm (287 only, just do nop here) */
6103 break;
6104 default:
6105 goto illegal_op;
6107 break;
6108 case 0x1d: /* fucomi */
6109 if (!(s->cpuid_features & CPUID_CMOV)) {
6110 goto illegal_op;
6112 gen_update_cc_op(s);
6113 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6114 gen_helper_fucomi_ST0_FT0(cpu_env);
6115 set_cc_op(s, CC_OP_EFLAGS);
6116 break;
6117 case 0x1e: /* fcomi */
6118 if (!(s->cpuid_features & CPUID_CMOV)) {
6119 goto illegal_op;
6121 gen_update_cc_op(s);
6122 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6123 gen_helper_fcomi_ST0_FT0(cpu_env);
6124 set_cc_op(s, CC_OP_EFLAGS);
6125 break;
6126 case 0x28: /* ffree sti */
6127 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6128 break;
6129 case 0x2a: /* fst sti */
6130 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6131 break;
6132 case 0x2b: /* fstp sti */
6133 case 0x0b: /* fstp1 sti, undocumented op */
6134 case 0x3a: /* fstp8 sti, undocumented op */
6135 case 0x3b: /* fstp9 sti, undocumented op */
6136 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6137 gen_helper_fpop(cpu_env);
6138 break;
6139 case 0x2c: /* fucom st(i) */
6140 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6141 gen_helper_fucom_ST0_FT0(cpu_env);
6142 break;
6143 case 0x2d: /* fucomp st(i) */
6144 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6145 gen_helper_fucom_ST0_FT0(cpu_env);
6146 gen_helper_fpop(cpu_env);
6147 break;
6148 case 0x33: /* de/3 */
6149 switch(rm) {
6150 case 1: /* fcompp */
6151 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6152 gen_helper_fcom_ST0_FT0(cpu_env);
6153 gen_helper_fpop(cpu_env);
6154 gen_helper_fpop(cpu_env);
6155 break;
6156 default:
6157 goto illegal_op;
6159 break;
6160 case 0x38: /* ffreep sti, undocumented op */
6161 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6162 gen_helper_fpop(cpu_env);
6163 break;
6164 case 0x3c: /* df/4 */
6165 switch(rm) {
6166 case 0:
6167 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6168 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6169 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
6170 break;
6171 default:
6172 goto illegal_op;
6174 break;
6175 case 0x3d: /* fucomip */
6176 if (!(s->cpuid_features & CPUID_CMOV)) {
6177 goto illegal_op;
6179 gen_update_cc_op(s);
6180 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6181 gen_helper_fucomi_ST0_FT0(cpu_env);
6182 gen_helper_fpop(cpu_env);
6183 set_cc_op(s, CC_OP_EFLAGS);
6184 break;
6185 case 0x3e: /* fcomip */
6186 if (!(s->cpuid_features & CPUID_CMOV)) {
6187 goto illegal_op;
6189 gen_update_cc_op(s);
6190 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6191 gen_helper_fcomi_ST0_FT0(cpu_env);
6192 gen_helper_fpop(cpu_env);
6193 set_cc_op(s, CC_OP_EFLAGS);
6194 break;
6195 case 0x10 ... 0x13: /* fcmovxx */
6196 case 0x18 ... 0x1b:
6198 int op1;
6199 TCGLabel *l1;
6200 static const uint8_t fcmov_cc[8] = {
6201 (JCC_B << 1),
6202 (JCC_Z << 1),
6203 (JCC_BE << 1),
6204 (JCC_P << 1),
6207 if (!(s->cpuid_features & CPUID_CMOV)) {
6208 goto illegal_op;
6210 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6211 l1 = gen_new_label();
6212 gen_jcc1_noeob(s, op1, l1);
6213 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6214 gen_set_label(l1);
6216 break;
6217 default:
6218 goto illegal_op;
6221 break;
6222 /************************/
6223 /* string ops */
6225 case 0xa4: /* movsS */
6226 case 0xa5:
6227 ot = mo_b_d(b, dflag);
6228 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6229 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6230 } else {
6231 gen_movs(s, ot);
6233 break;
6235 case 0xaa: /* stosS */
6236 case 0xab:
6237 ot = mo_b_d(b, dflag);
6238 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6239 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6240 } else {
6241 gen_stos(s, ot);
6243 break;
6244 case 0xac: /* lodsS */
6245 case 0xad:
6246 ot = mo_b_d(b, dflag);
6247 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6248 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6249 } else {
6250 gen_lods(s, ot);
6252 break;
6253 case 0xae: /* scasS */
6254 case 0xaf:
6255 ot = mo_b_d(b, dflag);
6256 if (prefixes & PREFIX_REPNZ) {
6257 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6258 } else if (prefixes & PREFIX_REPZ) {
6259 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6260 } else {
6261 gen_scas(s, ot);
6263 break;
6265 case 0xa6: /* cmpsS */
6266 case 0xa7:
6267 ot = mo_b_d(b, dflag);
6268 if (prefixes & PREFIX_REPNZ) {
6269 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6270 } else if (prefixes & PREFIX_REPZ) {
6271 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6272 } else {
6273 gen_cmps(s, ot);
6275 break;
6276 case 0x6c: /* insS */
6277 case 0x6d:
6278 ot = mo_b_d32(b, dflag);
6279 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6280 gen_check_io(s, ot, pc_start - s->cs_base,
6281 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6282 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6283 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6284 } else {
6285 gen_ins(s, ot);
6286 if (s->tb->cflags & CF_USE_ICOUNT) {
6287 gen_jmp(s, s->pc - s->cs_base);
6290 break;
6291 case 0x6e: /* outsS */
6292 case 0x6f:
6293 ot = mo_b_d32(b, dflag);
6294 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6295 gen_check_io(s, ot, pc_start - s->cs_base,
6296 svm_is_rep(prefixes) | 4);
6297 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6298 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6299 } else {
6300 gen_outs(s, ot);
6301 if (s->tb->cflags & CF_USE_ICOUNT) {
6302 gen_jmp(s, s->pc - s->cs_base);
6305 break;
6307 /************************/
6308 /* port I/O */
6310 case 0xe4:
6311 case 0xe5:
6312 ot = mo_b_d32(b, dflag);
6313 val = cpu_ldub_code(env, s->pc++);
6314 tcg_gen_movi_tl(cpu_T[0], val);
6315 gen_check_io(s, ot, pc_start - s->cs_base,
6316 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6317 if (s->tb->cflags & CF_USE_ICOUNT) {
6318 gen_io_start();
6320 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6321 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6322 gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
6323 if (s->tb->cflags & CF_USE_ICOUNT) {
6324 gen_io_end();
6325 gen_jmp(s, s->pc - s->cs_base);
6327 break;
6328 case 0xe6:
6329 case 0xe7:
6330 ot = mo_b_d32(b, dflag);
6331 val = cpu_ldub_code(env, s->pc++);
6332 tcg_gen_movi_tl(cpu_T[0], val);
6333 gen_check_io(s, ot, pc_start - s->cs_base,
6334 svm_is_rep(prefixes));
6335 gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
6337 if (s->tb->cflags & CF_USE_ICOUNT) {
6338 gen_io_start();
6340 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6341 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6342 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6343 if (s->tb->cflags & CF_USE_ICOUNT) {
6344 gen_io_end();
6345 gen_jmp(s, s->pc - s->cs_base);
6347 break;
6348 case 0xec:
6349 case 0xed:
6350 ot = mo_b_d32(b, dflag);
6351 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6352 gen_check_io(s, ot, pc_start - s->cs_base,
6353 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6354 if (s->tb->cflags & CF_USE_ICOUNT) {
6355 gen_io_start();
6357 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6358 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6359 gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
6360 if (s->tb->cflags & CF_USE_ICOUNT) {
6361 gen_io_end();
6362 gen_jmp(s, s->pc - s->cs_base);
6364 break;
6365 case 0xee:
6366 case 0xef:
6367 ot = mo_b_d32(b, dflag);
6368 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6369 gen_check_io(s, ot, pc_start - s->cs_base,
6370 svm_is_rep(prefixes));
6371 gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
6373 if (s->tb->cflags & CF_USE_ICOUNT) {
6374 gen_io_start();
6376 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6377 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6378 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6379 if (s->tb->cflags & CF_USE_ICOUNT) {
6380 gen_io_end();
6381 gen_jmp(s, s->pc - s->cs_base);
6383 break;
6385 /************************/
6386 /* control */
6387 case 0xc2: /* ret im */
6388 val = cpu_ldsw_code(env, s->pc);
6389 s->pc += 2;
6390 ot = gen_pop_T0(s);
6391 gen_stack_update(s, val + (1 << ot));
6392 /* Note that gen_pop_T0 uses a zero-extending load. */
6393 gen_op_jmp_v(cpu_T[0]);
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_T[0]);
6401 gen_eob(s);
6402 break;
6403 case 0xca: /* lret im */
6404 val = cpu_ldsw_code(env, s->pc);
6405 s->pc += 2;
6406 do_lret:
6407 if (s->pe && !s->vm86) {
6408 gen_update_cc_op(s);
6409 gen_jmp_im(pc_start - s->cs_base);
6410 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6411 tcg_const_i32(val));
6412 } else {
6413 gen_stack_A0(s);
6414 /* pop offset */
6415 gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
6416 /* NOTE: keeping EIP updated is not a problem in case of
6417 exception */
6418 gen_op_jmp_v(cpu_T[0]);
6419 /* pop selector */
6420 gen_op_addl_A0_im(1 << dflag);
6421 gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
6422 gen_op_movl_seg_T0_vm(R_CS);
6423 /* add stack offset */
6424 gen_stack_update(s, val + (2 << dflag));
6426 gen_eob(s);
6427 break;
6428 case 0xcb: /* lret */
6429 val = 0;
6430 goto do_lret;
6431 case 0xcf: /* iret */
6432 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6433 if (!s->pe) {
6434 /* real mode */
6435 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6436 set_cc_op(s, CC_OP_EFLAGS);
6437 } else if (s->vm86) {
6438 if (s->iopl != 3) {
6439 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6440 } else {
6441 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6442 set_cc_op(s, CC_OP_EFLAGS);
6444 } else {
6445 gen_update_cc_op(s);
6446 gen_jmp_im(pc_start - s->cs_base);
6447 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6448 tcg_const_i32(s->pc - s->cs_base));
6449 set_cc_op(s, CC_OP_EFLAGS);
6451 gen_eob(s);
6452 break;
6453 case 0xe8: /* call im */
6455 if (dflag != MO_16) {
6456 tval = (int32_t)insn_get(env, s, MO_32);
6457 } else {
6458 tval = (int16_t)insn_get(env, s, MO_16);
6460 next_eip = s->pc - s->cs_base;
6461 tval += next_eip;
6462 if (dflag == MO_16) {
6463 tval &= 0xffff;
6464 } else if (!CODE64(s)) {
6465 tval &= 0xffffffff;
6467 tcg_gen_movi_tl(cpu_T[0], next_eip);
6468 gen_push_v(s, cpu_T[0]);
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_T[0], selector);
6483 tcg_gen_movi_tl(cpu_T[1], 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_jmp(s, tval);
6499 break;
6500 case 0xea: /* ljmp im */
6502 unsigned int selector, offset;
6504 if (CODE64(s))
6505 goto illegal_op;
6506 ot = dflag;
6507 offset = insn_get(env, s, ot);
6508 selector = insn_get(env, s, MO_16);
6510 tcg_gen_movi_tl(cpu_T[0], selector);
6511 tcg_gen_movi_tl(cpu_T[1], offset);
6513 goto do_ljmp;
6514 case 0xeb: /* jmp Jb */
6515 tval = (int8_t)insn_get(env, s, MO_8);
6516 tval += s->pc - s->cs_base;
6517 if (dflag == MO_16) {
6518 tval &= 0xffff;
6520 gen_jmp(s, tval);
6521 break;
6522 case 0x70 ... 0x7f: /* jcc Jb */
6523 tval = (int8_t)insn_get(env, s, MO_8);
6524 goto do_jcc;
6525 case 0x180 ... 0x18f: /* jcc Jv */
6526 if (dflag != MO_16) {
6527 tval = (int32_t)insn_get(env, s, MO_32);
6528 } else {
6529 tval = (int16_t)insn_get(env, s, MO_16);
6531 do_jcc:
6532 next_eip = s->pc - s->cs_base;
6533 tval += next_eip;
6534 if (dflag == MO_16) {
6535 tval &= 0xffff;
6537 gen_jcc(s, b, tval, next_eip);
6538 break;
6540 case 0x190 ... 0x19f: /* setcc Gv */
6541 modrm = cpu_ldub_code(env, s->pc++);
6542 gen_setcc1(s, b, cpu_T[0]);
6543 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6544 break;
6545 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6546 if (!(s->cpuid_features & CPUID_CMOV)) {
6547 goto illegal_op;
6549 ot = dflag;
6550 modrm = cpu_ldub_code(env, s->pc++);
6551 reg = ((modrm >> 3) & 7) | rex_r;
6552 gen_cmovcc1(env, s, ot, b, modrm, reg);
6553 break;
6555 /************************/
6556 /* flags */
6557 case 0x9c: /* pushf */
6558 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6559 if (s->vm86 && s->iopl != 3) {
6560 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6561 } else {
6562 gen_update_cc_op(s);
6563 gen_helper_read_eflags(cpu_T[0], cpu_env);
6564 gen_push_v(s, cpu_T[0]);
6566 break;
6567 case 0x9d: /* popf */
6568 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6569 if (s->vm86 && s->iopl != 3) {
6570 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6571 } else {
6572 ot = gen_pop_T0(s);
6573 if (s->cpl == 0) {
6574 if (dflag != MO_16) {
6575 gen_helper_write_eflags(cpu_env, cpu_T[0],
6576 tcg_const_i32((TF_MASK | AC_MASK |
6577 ID_MASK | NT_MASK |
6578 IF_MASK |
6579 IOPL_MASK)));
6580 } else {
6581 gen_helper_write_eflags(cpu_env, cpu_T[0],
6582 tcg_const_i32((TF_MASK | AC_MASK |
6583 ID_MASK | NT_MASK |
6584 IF_MASK | IOPL_MASK)
6585 & 0xffff));
6587 } else {
6588 if (s->cpl <= s->iopl) {
6589 if (dflag != MO_16) {
6590 gen_helper_write_eflags(cpu_env, cpu_T[0],
6591 tcg_const_i32((TF_MASK |
6592 AC_MASK |
6593 ID_MASK |
6594 NT_MASK |
6595 IF_MASK)));
6596 } else {
6597 gen_helper_write_eflags(cpu_env, cpu_T[0],
6598 tcg_const_i32((TF_MASK |
6599 AC_MASK |
6600 ID_MASK |
6601 NT_MASK |
6602 IF_MASK)
6603 & 0xffff));
6605 } else {
6606 if (dflag != MO_16) {
6607 gen_helper_write_eflags(cpu_env, cpu_T[0],
6608 tcg_const_i32((TF_MASK | AC_MASK |
6609 ID_MASK | NT_MASK)));
6610 } else {
6611 gen_helper_write_eflags(cpu_env, cpu_T[0],
6612 tcg_const_i32((TF_MASK | AC_MASK |
6613 ID_MASK | NT_MASK)
6614 & 0xffff));
6618 gen_pop_update(s, ot);
6619 set_cc_op(s, CC_OP_EFLAGS);
6620 /* abort translation because TF/AC flag may change */
6621 gen_jmp_im(s->pc - s->cs_base);
6622 gen_eob(s);
6624 break;
6625 case 0x9e: /* sahf */
6626 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6627 goto illegal_op;
6628 gen_op_mov_v_reg(MO_8, cpu_T[0], R_AH);
6629 gen_compute_eflags(s);
6630 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6631 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6632 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
6633 break;
6634 case 0x9f: /* lahf */
6635 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6636 goto illegal_op;
6637 gen_compute_eflags(s);
6638 /* Note: gen_compute_eflags() only gives the condition codes */
6639 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
6640 gen_op_mov_reg_v(MO_8, R_AH, cpu_T[0]);
6641 break;
6642 case 0xf5: /* cmc */
6643 gen_compute_eflags(s);
6644 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6645 break;
6646 case 0xf8: /* clc */
6647 gen_compute_eflags(s);
6648 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6649 break;
6650 case 0xf9: /* stc */
6651 gen_compute_eflags(s);
6652 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6653 break;
6654 case 0xfc: /* cld */
6655 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6656 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6657 break;
6658 case 0xfd: /* std */
6659 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6660 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6661 break;
6663 /************************/
6664 /* bit operations */
6665 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6666 ot = dflag;
6667 modrm = cpu_ldub_code(env, s->pc++);
6668 op = (modrm >> 3) & 7;
6669 mod = (modrm >> 6) & 3;
6670 rm = (modrm & 7) | REX_B(s);
6671 if (mod != 3) {
6672 s->rip_offset = 1;
6673 gen_lea_modrm(env, s, modrm);
6674 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
6675 } else {
6676 gen_op_mov_v_reg(ot, cpu_T[0], rm);
6678 /* load shift */
6679 val = cpu_ldub_code(env, s->pc++);
6680 tcg_gen_movi_tl(cpu_T[1], val);
6681 if (op < 4)
6682 goto illegal_op;
6683 op -= 4;
6684 goto bt_op;
6685 case 0x1a3: /* bt Gv, Ev */
6686 op = 0;
6687 goto do_btx;
6688 case 0x1ab: /* bts */
6689 op = 1;
6690 goto do_btx;
6691 case 0x1b3: /* btr */
6692 op = 2;
6693 goto do_btx;
6694 case 0x1bb: /* btc */
6695 op = 3;
6696 do_btx:
6697 ot = dflag;
6698 modrm = cpu_ldub_code(env, s->pc++);
6699 reg = ((modrm >> 3) & 7) | rex_r;
6700 mod = (modrm >> 6) & 3;
6701 rm = (modrm & 7) | REX_B(s);
6702 gen_op_mov_v_reg(MO_32, cpu_T[1], reg);
6703 if (mod != 3) {
6704 gen_lea_modrm(env, s, modrm);
6705 /* specific case: we need to add a displacement */
6706 gen_exts(ot, cpu_T[1]);
6707 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
6708 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6709 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
6710 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
6711 } else {
6712 gen_op_mov_v_reg(ot, cpu_T[0], rm);
6714 bt_op:
6715 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
6716 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6717 switch(op) {
6718 case 0:
6719 break;
6720 case 1:
6721 tcg_gen_movi_tl(cpu_tmp0, 1);
6722 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6723 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6724 break;
6725 case 2:
6726 tcg_gen_movi_tl(cpu_tmp0, 1);
6727 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6728 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6729 break;
6730 default:
6731 case 3:
6732 tcg_gen_movi_tl(cpu_tmp0, 1);
6733 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6734 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6735 break;
6737 if (op != 0) {
6738 if (mod != 3) {
6739 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
6740 } else {
6741 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
6745 /* Delay all CC updates until after the store above. Note that
6746 C is the result of the test, Z is unchanged, and the others
6747 are all undefined. */
6748 switch (s->cc_op) {
6749 case CC_OP_MULB ... CC_OP_MULQ:
6750 case CC_OP_ADDB ... CC_OP_ADDQ:
6751 case CC_OP_ADCB ... CC_OP_ADCQ:
6752 case CC_OP_SUBB ... CC_OP_SUBQ:
6753 case CC_OP_SBBB ... CC_OP_SBBQ:
6754 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6755 case CC_OP_INCB ... CC_OP_INCQ:
6756 case CC_OP_DECB ... CC_OP_DECQ:
6757 case CC_OP_SHLB ... CC_OP_SHLQ:
6758 case CC_OP_SARB ... CC_OP_SARQ:
6759 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6760 /* Z was going to be computed from the non-zero status of CC_DST.
6761 We can get that same Z value (and the new C value) by leaving
6762 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6763 same width. */
6764 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6765 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6766 break;
6767 default:
6768 /* Otherwise, generate EFLAGS and replace the C bit. */
6769 gen_compute_eflags(s);
6770 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6771 ctz32(CC_C), 1);
6772 break;
6774 break;
6775 case 0x1bc: /* bsf / tzcnt */
6776 case 0x1bd: /* bsr / lzcnt */
6777 ot = dflag;
6778 modrm = cpu_ldub_code(env, s->pc++);
6779 reg = ((modrm >> 3) & 7) | rex_r;
6780 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6781 gen_extu(ot, cpu_T[0]);
6783 /* Note that lzcnt and tzcnt are in different extensions. */
6784 if ((prefixes & PREFIX_REPZ)
6785 && (b & 1
6786 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6787 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6788 int size = 8 << ot;
6789 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
6790 if (b & 1) {
6791 /* For lzcnt, reduce the target_ulong result by the
6792 number of zeros that we expect to find at the top. */
6793 gen_helper_clz(cpu_T[0], cpu_T[0]);
6794 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - size);
6795 } else {
6796 /* For tzcnt, a zero input must return the operand size:
6797 force all bits outside the operand size to 1. */
6798 target_ulong mask = (target_ulong)-2 << (size - 1);
6799 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], mask);
6800 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6802 /* For lzcnt/tzcnt, C and Z bits are defined and are
6803 related to the result. */
6804 gen_op_update1_cc();
6805 set_cc_op(s, CC_OP_BMILGB + ot);
6806 } else {
6807 /* For bsr/bsf, only the Z bit is defined and it is related
6808 to the input and not the result. */
6809 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
6810 set_cc_op(s, CC_OP_LOGICB + ot);
6811 if (b & 1) {
6812 /* For bsr, return the bit index of the first 1 bit,
6813 not the count of leading zeros. */
6814 gen_helper_clz(cpu_T[0], cpu_T[0]);
6815 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - 1);
6816 } else {
6817 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6819 /* ??? The manual says that the output is undefined when the
6820 input is zero, but real hardware leaves it unchanged, and
6821 real programs appear to depend on that. */
6822 tcg_gen_movi_tl(cpu_tmp0, 0);
6823 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[0], cpu_cc_dst, cpu_tmp0,
6824 cpu_regs[reg], cpu_T[0]);
6826 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
6827 break;
6828 /************************/
6829 /* bcd */
6830 case 0x27: /* daa */
6831 if (CODE64(s))
6832 goto illegal_op;
6833 gen_update_cc_op(s);
6834 gen_helper_daa(cpu_env);
6835 set_cc_op(s, CC_OP_EFLAGS);
6836 break;
6837 case 0x2f: /* das */
6838 if (CODE64(s))
6839 goto illegal_op;
6840 gen_update_cc_op(s);
6841 gen_helper_das(cpu_env);
6842 set_cc_op(s, CC_OP_EFLAGS);
6843 break;
6844 case 0x37: /* aaa */
6845 if (CODE64(s))
6846 goto illegal_op;
6847 gen_update_cc_op(s);
6848 gen_helper_aaa(cpu_env);
6849 set_cc_op(s, CC_OP_EFLAGS);
6850 break;
6851 case 0x3f: /* aas */
6852 if (CODE64(s))
6853 goto illegal_op;
6854 gen_update_cc_op(s);
6855 gen_helper_aas(cpu_env);
6856 set_cc_op(s, CC_OP_EFLAGS);
6857 break;
6858 case 0xd4: /* aam */
6859 if (CODE64(s))
6860 goto illegal_op;
6861 val = cpu_ldub_code(env, s->pc++);
6862 if (val == 0) {
6863 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6864 } else {
6865 gen_helper_aam(cpu_env, tcg_const_i32(val));
6866 set_cc_op(s, CC_OP_LOGICB);
6868 break;
6869 case 0xd5: /* aad */
6870 if (CODE64(s))
6871 goto illegal_op;
6872 val = cpu_ldub_code(env, s->pc++);
6873 gen_helper_aad(cpu_env, tcg_const_i32(val));
6874 set_cc_op(s, CC_OP_LOGICB);
6875 break;
6876 /************************/
6877 /* misc */
6878 case 0x90: /* nop */
6879 /* XXX: correct lock test for all insn */
6880 if (prefixes & PREFIX_LOCK) {
6881 goto illegal_op;
6883 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6884 if (REX_B(s)) {
6885 goto do_xchg_reg_eax;
6887 if (prefixes & PREFIX_REPZ) {
6888 gen_update_cc_op(s);
6889 gen_jmp_im(pc_start - s->cs_base);
6890 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6891 s->is_jmp = DISAS_TB_JUMP;
6893 break;
6894 case 0x9b: /* fwait */
6895 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6896 (HF_MP_MASK | HF_TS_MASK)) {
6897 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6898 } else {
6899 gen_update_cc_op(s);
6900 gen_jmp_im(pc_start - s->cs_base);
6901 gen_helper_fwait(cpu_env);
6903 break;
6904 case 0xcc: /* int3 */
6905 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6906 break;
6907 case 0xcd: /* int N */
6908 val = cpu_ldub_code(env, s->pc++);
6909 if (s->vm86 && s->iopl != 3) {
6910 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6911 } else {
6912 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6914 break;
6915 case 0xce: /* into */
6916 if (CODE64(s))
6917 goto illegal_op;
6918 gen_update_cc_op(s);
6919 gen_jmp_im(pc_start - s->cs_base);
6920 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6921 break;
6922 #ifdef WANT_ICEBP
6923 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6924 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6925 #if 1
6926 gen_debug(s, pc_start - s->cs_base);
6927 #else
6928 /* start debug */
6929 tb_flush(CPU(x86_env_get_cpu(env)));
6930 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6931 #endif
6932 break;
6933 #endif
6934 case 0xfa: /* cli */
6935 if (!s->vm86) {
6936 if (s->cpl <= s->iopl) {
6937 gen_helper_cli(cpu_env);
6938 } else {
6939 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6941 } else {
6942 if (s->iopl == 3) {
6943 gen_helper_cli(cpu_env);
6944 } else {
6945 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6948 break;
6949 case 0xfb: /* sti */
6950 if (!s->vm86) {
6951 if (s->cpl <= s->iopl) {
6952 gen_sti:
6953 gen_helper_sti(cpu_env);
6954 /* interruptions are enabled only the first insn after sti */
6955 /* If several instructions disable interrupts, only the
6956 _first_ does it */
6957 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
6958 gen_helper_set_inhibit_irq(cpu_env);
6959 /* give a chance to handle pending irqs */
6960 gen_jmp_im(s->pc - s->cs_base);
6961 gen_eob(s);
6962 } else {
6963 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6965 } else {
6966 if (s->iopl == 3) {
6967 goto gen_sti;
6968 } else {
6969 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6972 break;
6973 case 0x62: /* bound */
6974 if (CODE64(s))
6975 goto illegal_op;
6976 ot = dflag;
6977 modrm = cpu_ldub_code(env, s->pc++);
6978 reg = (modrm >> 3) & 7;
6979 mod = (modrm >> 6) & 3;
6980 if (mod == 3)
6981 goto illegal_op;
6982 gen_op_mov_v_reg(ot, cpu_T[0], reg);
6983 gen_lea_modrm(env, s, modrm);
6984 gen_jmp_im(pc_start - s->cs_base);
6985 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6986 if (ot == MO_16) {
6987 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
6988 } else {
6989 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
6991 break;
6992 case 0x1c8 ... 0x1cf: /* bswap reg */
6993 reg = (b & 7) | REX_B(s);
6994 #ifdef TARGET_X86_64
6995 if (dflag == MO_64) {
6996 gen_op_mov_v_reg(MO_64, cpu_T[0], reg);
6997 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
6998 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
6999 } else
7000 #endif
7002 gen_op_mov_v_reg(MO_32, cpu_T[0], reg);
7003 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
7004 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
7005 gen_op_mov_reg_v(MO_32, reg, cpu_T[0]);
7007 break;
7008 case 0xd6: /* salc */
7009 if (CODE64(s))
7010 goto illegal_op;
7011 gen_compute_eflags_c(s, cpu_T[0]);
7012 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
7013 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
7014 break;
7015 case 0xe0: /* loopnz */
7016 case 0xe1: /* loopz */
7017 case 0xe2: /* loop */
7018 case 0xe3: /* jecxz */
7020 TCGLabel *l1, *l2, *l3;
7022 tval = (int8_t)insn_get(env, s, MO_8);
7023 next_eip = s->pc - s->cs_base;
7024 tval += next_eip;
7025 if (dflag == MO_16) {
7026 tval &= 0xffff;
7029 l1 = gen_new_label();
7030 l2 = gen_new_label();
7031 l3 = gen_new_label();
7032 b &= 3;
7033 switch(b) {
7034 case 0: /* loopnz */
7035 case 1: /* loopz */
7036 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7037 gen_op_jz_ecx(s->aflag, l3);
7038 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7039 break;
7040 case 2: /* loop */
7041 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7042 gen_op_jnz_ecx(s->aflag, l1);
7043 break;
7044 default:
7045 case 3: /* jcxz */
7046 gen_op_jz_ecx(s->aflag, l1);
7047 break;
7050 gen_set_label(l3);
7051 gen_jmp_im(next_eip);
7052 tcg_gen_br(l2);
7054 gen_set_label(l1);
7055 gen_jmp_im(tval);
7056 gen_set_label(l2);
7057 gen_eob(s);
7059 break;
7060 case 0x130: /* wrmsr */
7061 case 0x132: /* rdmsr */
7062 if (s->cpl != 0) {
7063 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7064 } else {
7065 gen_update_cc_op(s);
7066 gen_jmp_im(pc_start - s->cs_base);
7067 if (b & 2) {
7068 gen_helper_rdmsr(cpu_env);
7069 } else {
7070 gen_helper_wrmsr(cpu_env);
7073 break;
7074 case 0x131: /* rdtsc */
7075 gen_update_cc_op(s);
7076 gen_jmp_im(pc_start - s->cs_base);
7077 if (s->tb->cflags & CF_USE_ICOUNT) {
7078 gen_io_start();
7080 gen_helper_rdtsc(cpu_env);
7081 if (s->tb->cflags & CF_USE_ICOUNT) {
7082 gen_io_end();
7083 gen_jmp(s, s->pc - s->cs_base);
7085 break;
7086 case 0x133: /* rdpmc */
7087 gen_update_cc_op(s);
7088 gen_jmp_im(pc_start - s->cs_base);
7089 gen_helper_rdpmc(cpu_env);
7090 break;
7091 case 0x134: /* sysenter */
7092 /* For Intel SYSENTER is valid on 64-bit */
7093 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7094 goto illegal_op;
7095 if (!s->pe) {
7096 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7097 } else {
7098 gen_update_cc_op(s);
7099 gen_jmp_im(pc_start - s->cs_base);
7100 gen_helper_sysenter(cpu_env);
7101 gen_eob(s);
7103 break;
7104 case 0x135: /* sysexit */
7105 /* For Intel SYSEXIT is valid on 64-bit */
7106 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7107 goto illegal_op;
7108 if (!s->pe) {
7109 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7110 } else {
7111 gen_update_cc_op(s);
7112 gen_jmp_im(pc_start - s->cs_base);
7113 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7114 gen_eob(s);
7116 break;
7117 #ifdef TARGET_X86_64
7118 case 0x105: /* syscall */
7119 /* XXX: is it usable in real mode ? */
7120 gen_update_cc_op(s);
7121 gen_jmp_im(pc_start - s->cs_base);
7122 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7123 gen_eob(s);
7124 break;
7125 case 0x107: /* sysret */
7126 if (!s->pe) {
7127 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7128 } else {
7129 gen_update_cc_op(s);
7130 gen_jmp_im(pc_start - s->cs_base);
7131 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7132 /* condition codes are modified only in long mode */
7133 if (s->lma) {
7134 set_cc_op(s, CC_OP_EFLAGS);
7136 gen_eob(s);
7138 break;
7139 #endif
7140 case 0x1a2: /* cpuid */
7141 gen_update_cc_op(s);
7142 gen_jmp_im(pc_start - s->cs_base);
7143 gen_helper_cpuid(cpu_env);
7144 break;
7145 case 0xf4: /* hlt */
7146 if (s->cpl != 0) {
7147 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7148 } else {
7149 gen_update_cc_op(s);
7150 gen_jmp_im(pc_start - s->cs_base);
7151 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7152 s->is_jmp = DISAS_TB_JUMP;
7154 break;
7155 case 0x100:
7156 modrm = cpu_ldub_code(env, s->pc++);
7157 mod = (modrm >> 6) & 3;
7158 op = (modrm >> 3) & 7;
7159 switch(op) {
7160 case 0: /* sldt */
7161 if (!s->pe || s->vm86)
7162 goto illegal_op;
7163 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7164 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
7165 ot = mod == 3 ? dflag : MO_16;
7166 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7167 break;
7168 case 2: /* lldt */
7169 if (!s->pe || s->vm86)
7170 goto illegal_op;
7171 if (s->cpl != 0) {
7172 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7173 } else {
7174 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7175 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7176 gen_jmp_im(pc_start - s->cs_base);
7177 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7178 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7180 break;
7181 case 1: /* str */
7182 if (!s->pe || s->vm86)
7183 goto illegal_op;
7184 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7185 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
7186 ot = mod == 3 ? dflag : MO_16;
7187 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7188 break;
7189 case 3: /* ltr */
7190 if (!s->pe || s->vm86)
7191 goto illegal_op;
7192 if (s->cpl != 0) {
7193 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7194 } else {
7195 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7196 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7197 gen_jmp_im(pc_start - s->cs_base);
7198 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7199 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7201 break;
7202 case 4: /* verr */
7203 case 5: /* verw */
7204 if (!s->pe || s->vm86)
7205 goto illegal_op;
7206 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7207 gen_update_cc_op(s);
7208 if (op == 4) {
7209 gen_helper_verr(cpu_env, cpu_T[0]);
7210 } else {
7211 gen_helper_verw(cpu_env, cpu_T[0]);
7213 set_cc_op(s, CC_OP_EFLAGS);
7214 break;
7215 default:
7216 goto illegal_op;
7218 break;
7219 case 0x101:
7220 modrm = cpu_ldub_code(env, s->pc++);
7221 mod = (modrm >> 6) & 3;
7222 op = (modrm >> 3) & 7;
7223 rm = modrm & 7;
7224 switch(op) {
7225 case 0: /* sgdt */
7226 if (mod == 3)
7227 goto illegal_op;
7228 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7229 gen_lea_modrm(env, s, modrm);
7230 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
7231 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
7232 gen_add_A0_im(s, 2);
7233 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
7234 if (dflag == MO_16) {
7235 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7237 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7238 break;
7239 case 1:
7240 if (mod == 3) {
7241 switch (rm) {
7242 case 0: /* monitor */
7243 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7244 s->cpl != 0)
7245 goto illegal_op;
7246 gen_update_cc_op(s);
7247 gen_jmp_im(pc_start - s->cs_base);
7248 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7249 gen_extu(s->aflag, cpu_A0);
7250 gen_add_A0_ds_seg(s);
7251 gen_helper_monitor(cpu_env, cpu_A0);
7252 break;
7253 case 1: /* mwait */
7254 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7255 s->cpl != 0)
7256 goto illegal_op;
7257 gen_update_cc_op(s);
7258 gen_jmp_im(pc_start - s->cs_base);
7259 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7260 gen_eob(s);
7261 break;
7262 case 2: /* clac */
7263 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7264 s->cpl != 0) {
7265 goto illegal_op;
7267 gen_helper_clac(cpu_env);
7268 gen_jmp_im(s->pc - s->cs_base);
7269 gen_eob(s);
7270 break;
7271 case 3: /* stac */
7272 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7273 s->cpl != 0) {
7274 goto illegal_op;
7276 gen_helper_stac(cpu_env);
7277 gen_jmp_im(s->pc - s->cs_base);
7278 gen_eob(s);
7279 break;
7280 default:
7281 goto illegal_op;
7283 } else { /* sidt */
7284 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7285 gen_lea_modrm(env, s, modrm);
7286 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
7287 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
7288 gen_add_A0_im(s, 2);
7289 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
7290 if (dflag == MO_16) {
7291 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7293 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7295 break;
7296 case 2: /* lgdt */
7297 case 3: /* lidt */
7298 if (mod == 3) {
7299 gen_update_cc_op(s);
7300 gen_jmp_im(pc_start - s->cs_base);
7301 switch(rm) {
7302 case 0: /* VMRUN */
7303 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7304 goto illegal_op;
7305 if (s->cpl != 0) {
7306 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7307 break;
7308 } else {
7309 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7310 tcg_const_i32(s->pc - pc_start));
7311 tcg_gen_exit_tb(0);
7312 s->is_jmp = DISAS_TB_JUMP;
7314 break;
7315 case 1: /* VMMCALL */
7316 if (!(s->flags & HF_SVME_MASK))
7317 goto illegal_op;
7318 gen_helper_vmmcall(cpu_env);
7319 break;
7320 case 2: /* VMLOAD */
7321 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7322 goto illegal_op;
7323 if (s->cpl != 0) {
7324 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7325 break;
7326 } else {
7327 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7329 break;
7330 case 3: /* VMSAVE */
7331 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7332 goto illegal_op;
7333 if (s->cpl != 0) {
7334 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7335 break;
7336 } else {
7337 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7339 break;
7340 case 4: /* STGI */
7341 if ((!(s->flags & HF_SVME_MASK) &&
7342 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7343 !s->pe)
7344 goto illegal_op;
7345 if (s->cpl != 0) {
7346 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7347 break;
7348 } else {
7349 gen_helper_stgi(cpu_env);
7351 break;
7352 case 5: /* CLGI */
7353 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7354 goto illegal_op;
7355 if (s->cpl != 0) {
7356 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7357 break;
7358 } else {
7359 gen_helper_clgi(cpu_env);
7361 break;
7362 case 6: /* SKINIT */
7363 if ((!(s->flags & HF_SVME_MASK) &&
7364 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7365 !s->pe)
7366 goto illegal_op;
7367 gen_helper_skinit(cpu_env);
7368 break;
7369 case 7: /* INVLPGA */
7370 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7371 goto illegal_op;
7372 if (s->cpl != 0) {
7373 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7374 break;
7375 } else {
7376 gen_helper_invlpga(cpu_env,
7377 tcg_const_i32(s->aflag - 1));
7379 break;
7380 default:
7381 goto illegal_op;
7383 } else if (s->cpl != 0) {
7384 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7385 } else {
7386 gen_svm_check_intercept(s, pc_start,
7387 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
7388 gen_lea_modrm(env, s, modrm);
7389 gen_op_ld_v(s, MO_16, cpu_T[1], cpu_A0);
7390 gen_add_A0_im(s, 2);
7391 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7392 if (dflag == MO_16) {
7393 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7395 if (op == 2) {
7396 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7397 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
7398 } else {
7399 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7400 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
7403 break;
7404 case 4: /* smsw */
7405 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7406 #if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
7407 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7408 #else
7409 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
7410 #endif
7411 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 1);
7412 break;
7413 case 6: /* lmsw */
7414 if (s->cpl != 0) {
7415 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7416 } else {
7417 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7418 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7419 gen_helper_lmsw(cpu_env, cpu_T[0]);
7420 gen_jmp_im(s->pc - s->cs_base);
7421 gen_eob(s);
7423 break;
7424 case 7:
7425 if (mod != 3) { /* invlpg */
7426 if (s->cpl != 0) {
7427 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7428 } else {
7429 gen_update_cc_op(s);
7430 gen_jmp_im(pc_start - s->cs_base);
7431 gen_lea_modrm(env, s, modrm);
7432 gen_helper_invlpg(cpu_env, cpu_A0);
7433 gen_jmp_im(s->pc - s->cs_base);
7434 gen_eob(s);
7436 } else {
7437 switch (rm) {
7438 case 0: /* swapgs */
7439 #ifdef TARGET_X86_64
7440 if (CODE64(s)) {
7441 if (s->cpl != 0) {
7442 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7443 } else {
7444 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7445 offsetof(CPUX86State,segs[R_GS].base));
7446 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7447 offsetof(CPUX86State,kernelgsbase));
7448 tcg_gen_st_tl(cpu_T[1], cpu_env,
7449 offsetof(CPUX86State,segs[R_GS].base));
7450 tcg_gen_st_tl(cpu_T[0], cpu_env,
7451 offsetof(CPUX86State,kernelgsbase));
7453 } else
7454 #endif
7456 goto illegal_op;
7458 break;
7459 case 1: /* rdtscp */
7460 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7461 goto illegal_op;
7462 gen_update_cc_op(s);
7463 gen_jmp_im(pc_start - s->cs_base);
7464 if (s->tb->cflags & CF_USE_ICOUNT) {
7465 gen_io_start();
7467 gen_helper_rdtscp(cpu_env);
7468 if (s->tb->cflags & CF_USE_ICOUNT) {
7469 gen_io_end();
7470 gen_jmp(s, s->pc - s->cs_base);
7472 break;
7473 default:
7474 goto illegal_op;
7477 break;
7478 default:
7479 goto illegal_op;
7481 break;
7482 case 0x108: /* invd */
7483 case 0x109: /* wbinvd */
7484 if (s->cpl != 0) {
7485 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7486 } else {
7487 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7488 /* nothing to do */
7490 break;
7491 case 0x63: /* arpl or movslS (x86_64) */
7492 #ifdef TARGET_X86_64
7493 if (CODE64(s)) {
7494 int d_ot;
7495 /* d_ot is the size of destination */
7496 d_ot = dflag;
7498 modrm = cpu_ldub_code(env, s->pc++);
7499 reg = ((modrm >> 3) & 7) | rex_r;
7500 mod = (modrm >> 6) & 3;
7501 rm = (modrm & 7) | REX_B(s);
7503 if (mod == 3) {
7504 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
7505 /* sign extend */
7506 if (d_ot == MO_64) {
7507 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
7509 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
7510 } else {
7511 gen_lea_modrm(env, s, modrm);
7512 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
7513 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
7515 } else
7516 #endif
7518 TCGLabel *label1;
7519 TCGv t0, t1, t2, a0;
7521 if (!s->pe || s->vm86)
7522 goto illegal_op;
7523 t0 = tcg_temp_local_new();
7524 t1 = tcg_temp_local_new();
7525 t2 = tcg_temp_local_new();
7526 ot = MO_16;
7527 modrm = cpu_ldub_code(env, s->pc++);
7528 reg = (modrm >> 3) & 7;
7529 mod = (modrm >> 6) & 3;
7530 rm = modrm & 7;
7531 if (mod != 3) {
7532 gen_lea_modrm(env, s, modrm);
7533 gen_op_ld_v(s, ot, t0, cpu_A0);
7534 a0 = tcg_temp_local_new();
7535 tcg_gen_mov_tl(a0, cpu_A0);
7536 } else {
7537 gen_op_mov_v_reg(ot, t0, rm);
7538 TCGV_UNUSED(a0);
7540 gen_op_mov_v_reg(ot, t1, reg);
7541 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7542 tcg_gen_andi_tl(t1, t1, 3);
7543 tcg_gen_movi_tl(t2, 0);
7544 label1 = gen_new_label();
7545 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7546 tcg_gen_andi_tl(t0, t0, ~3);
7547 tcg_gen_or_tl(t0, t0, t1);
7548 tcg_gen_movi_tl(t2, CC_Z);
7549 gen_set_label(label1);
7550 if (mod != 3) {
7551 gen_op_st_v(s, ot, t0, a0);
7552 tcg_temp_free(a0);
7553 } else {
7554 gen_op_mov_reg_v(ot, rm, t0);
7556 gen_compute_eflags(s);
7557 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7558 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7559 tcg_temp_free(t0);
7560 tcg_temp_free(t1);
7561 tcg_temp_free(t2);
7563 break;
7564 case 0x102: /* lar */
7565 case 0x103: /* lsl */
7567 TCGLabel *label1;
7568 TCGv t0;
7569 if (!s->pe || s->vm86)
7570 goto illegal_op;
7571 ot = dflag != MO_16 ? MO_32 : MO_16;
7572 modrm = cpu_ldub_code(env, s->pc++);
7573 reg = ((modrm >> 3) & 7) | rex_r;
7574 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7575 t0 = tcg_temp_local_new();
7576 gen_update_cc_op(s);
7577 if (b == 0x102) {
7578 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7579 } else {
7580 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7582 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7583 label1 = gen_new_label();
7584 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7585 gen_op_mov_reg_v(ot, reg, t0);
7586 gen_set_label(label1);
7587 set_cc_op(s, CC_OP_EFLAGS);
7588 tcg_temp_free(t0);
7590 break;
7591 case 0x118:
7592 modrm = cpu_ldub_code(env, s->pc++);
7593 mod = (modrm >> 6) & 3;
7594 op = (modrm >> 3) & 7;
7595 switch(op) {
7596 case 0: /* prefetchnta */
7597 case 1: /* prefetchnt0 */
7598 case 2: /* prefetchnt0 */
7599 case 3: /* prefetchnt0 */
7600 if (mod == 3)
7601 goto illegal_op;
7602 gen_lea_modrm(env, s, modrm);
7603 /* nothing more to do */
7604 break;
7605 default: /* nop (multi byte) */
7606 gen_nop_modrm(env, s, modrm);
7607 break;
7609 break;
7610 case 0x119 ... 0x11f: /* nop (multi byte) */
7611 modrm = cpu_ldub_code(env, s->pc++);
7612 gen_nop_modrm(env, s, modrm);
7613 break;
7614 case 0x120: /* mov reg, crN */
7615 case 0x122: /* mov crN, reg */
7616 if (s->cpl != 0) {
7617 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7618 } else {
7619 modrm = cpu_ldub_code(env, s->pc++);
7620 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7621 * AMD documentation (24594.pdf) and testing of
7622 * intel 386 and 486 processors all show that the mod bits
7623 * are assumed to be 1's, regardless of actual values.
7625 rm = (modrm & 7) | REX_B(s);
7626 reg = ((modrm >> 3) & 7) | rex_r;
7627 if (CODE64(s))
7628 ot = MO_64;
7629 else
7630 ot = MO_32;
7631 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7632 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7633 reg = 8;
7635 switch(reg) {
7636 case 0:
7637 case 2:
7638 case 3:
7639 case 4:
7640 case 8:
7641 gen_update_cc_op(s);
7642 gen_jmp_im(pc_start - s->cs_base);
7643 if (b & 2) {
7644 gen_op_mov_v_reg(ot, cpu_T[0], rm);
7645 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7646 cpu_T[0]);
7647 gen_jmp_im(s->pc - s->cs_base);
7648 gen_eob(s);
7649 } else {
7650 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
7651 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
7653 break;
7654 default:
7655 goto illegal_op;
7658 break;
7659 case 0x121: /* mov reg, drN */
7660 case 0x123: /* mov drN, reg */
7661 if (s->cpl != 0) {
7662 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7663 } else {
7664 modrm = cpu_ldub_code(env, s->pc++);
7665 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7666 * AMD documentation (24594.pdf) and testing of
7667 * intel 386 and 486 processors all show that the mod bits
7668 * are assumed to be 1's, regardless of actual values.
7670 rm = (modrm & 7) | REX_B(s);
7671 reg = ((modrm >> 3) & 7) | rex_r;
7672 if (CODE64(s))
7673 ot = MO_64;
7674 else
7675 ot = MO_32;
7676 /* XXX: do it dynamically with CR4.DE bit */
7677 if (reg == 4 || reg == 5 || reg >= 8)
7678 goto illegal_op;
7679 if (b & 2) {
7680 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7681 gen_op_mov_v_reg(ot, cpu_T[0], rm);
7682 gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]);
7683 gen_jmp_im(s->pc - s->cs_base);
7684 gen_eob(s);
7685 } else {
7686 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7687 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
7688 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
7691 break;
7692 case 0x106: /* clts */
7693 if (s->cpl != 0) {
7694 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7695 } else {
7696 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7697 gen_helper_clts(cpu_env);
7698 /* abort block because static cpu state changed */
7699 gen_jmp_im(s->pc - s->cs_base);
7700 gen_eob(s);
7702 break;
7703 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
7704 case 0x1c3: /* MOVNTI reg, mem */
7705 if (!(s->cpuid_features & CPUID_SSE2))
7706 goto illegal_op;
7707 ot = mo_64_32(dflag);
7708 modrm = cpu_ldub_code(env, s->pc++);
7709 mod = (modrm >> 6) & 3;
7710 if (mod == 3)
7711 goto illegal_op;
7712 reg = ((modrm >> 3) & 7) | rex_r;
7713 /* generate a generic store */
7714 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
7715 break;
7716 case 0x1ae:
7717 modrm = cpu_ldub_code(env, s->pc++);
7718 mod = (modrm >> 6) & 3;
7719 op = (modrm >> 3) & 7;
7720 switch(op) {
7721 case 0: /* fxsave */
7722 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7723 (s->prefix & PREFIX_LOCK))
7724 goto illegal_op;
7725 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7726 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7727 break;
7729 gen_lea_modrm(env, s, modrm);
7730 gen_update_cc_op(s);
7731 gen_jmp_im(pc_start - s->cs_base);
7732 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
7733 break;
7734 case 1: /* fxrstor */
7735 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7736 (s->prefix & PREFIX_LOCK))
7737 goto illegal_op;
7738 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7739 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7740 break;
7742 gen_lea_modrm(env, s, modrm);
7743 gen_update_cc_op(s);
7744 gen_jmp_im(pc_start - s->cs_base);
7745 gen_helper_fxrstor(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
7746 break;
7747 case 2: /* ldmxcsr */
7748 case 3: /* stmxcsr */
7749 if (s->flags & HF_TS_MASK) {
7750 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7751 break;
7753 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7754 mod == 3)
7755 goto illegal_op;
7756 gen_lea_modrm(env, s, modrm);
7757 if (op == 2) {
7758 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
7759 s->mem_index, MO_LEUL);
7760 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
7761 } else {
7762 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
7763 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
7765 break;
7766 case 5: /* lfence */
7767 case 6: /* mfence */
7768 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
7769 goto illegal_op;
7770 break;
7771 case 7: /* sfence / clflush */
7772 if ((modrm & 0xc7) == 0xc0) {
7773 /* sfence */
7774 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
7775 if (!(s->cpuid_features & CPUID_SSE))
7776 goto illegal_op;
7777 } else {
7778 /* clflush */
7779 if (!(s->cpuid_features & CPUID_CLFLUSH))
7780 goto illegal_op;
7781 gen_lea_modrm(env, s, modrm);
7783 break;
7784 default:
7785 goto illegal_op;
7787 break;
7788 case 0x10d: /* 3DNow! prefetch(w) */
7789 modrm = cpu_ldub_code(env, s->pc++);
7790 mod = (modrm >> 6) & 3;
7791 if (mod == 3)
7792 goto illegal_op;
7793 gen_lea_modrm(env, s, modrm);
7794 /* ignore for now */
7795 break;
7796 case 0x1aa: /* rsm */
7797 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
7798 if (!(s->flags & HF_SMM_MASK))
7799 goto illegal_op;
7800 gen_update_cc_op(s);
7801 gen_jmp_im(s->pc - s->cs_base);
7802 gen_helper_rsm(cpu_env);
7803 gen_eob(s);
7804 break;
7805 case 0x1b8: /* SSE4.2 popcnt */
7806 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
7807 PREFIX_REPZ)
7808 goto illegal_op;
7809 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
7810 goto illegal_op;
7812 modrm = cpu_ldub_code(env, s->pc++);
7813 reg = ((modrm >> 3) & 7) | rex_r;
7815 if (s->prefix & PREFIX_DATA) {
7816 ot = MO_16;
7817 } else {
7818 ot = mo_64_32(dflag);
7821 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7822 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
7823 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
7825 set_cc_op(s, CC_OP_EFLAGS);
7826 break;
7827 case 0x10e ... 0x10f:
7828 /* 3DNow! instructions, ignore prefixes */
7829 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
7830 case 0x110 ... 0x117:
7831 case 0x128 ... 0x12f:
7832 case 0x138 ... 0x13a:
7833 case 0x150 ... 0x179:
7834 case 0x17c ... 0x17f:
7835 case 0x1c2:
7836 case 0x1c4 ... 0x1c6:
7837 case 0x1d0 ... 0x1fe:
7838 gen_sse(env, s, b, pc_start, rex_r);
7839 break;
7840 default:
7841 goto illegal_op;
7843 /* lock generation */
7844 if (s->prefix & PREFIX_LOCK)
7845 gen_helper_unlock();
7846 return s->pc;
7847 illegal_op:
7848 if (s->prefix & PREFIX_LOCK)
7849 gen_helper_unlock();
7850 /* XXX: ensure that no lock was generated */
7851 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7852 return s->pc;
7855 void optimize_flags_init(void)
7857 static const char reg_names[CPU_NB_REGS][4] = {
7858 #ifdef TARGET_X86_64
7859 [R_EAX] = "rax",
7860 [R_EBX] = "rbx",
7861 [R_ECX] = "rcx",
7862 [R_EDX] = "rdx",
7863 [R_ESI] = "rsi",
7864 [R_EDI] = "rdi",
7865 [R_EBP] = "rbp",
7866 [R_ESP] = "rsp",
7867 [8] = "r8",
7868 [9] = "r9",
7869 [10] = "r10",
7870 [11] = "r11",
7871 [12] = "r12",
7872 [13] = "r13",
7873 [14] = "r14",
7874 [15] = "r15",
7875 #else
7876 [R_EAX] = "eax",
7877 [R_EBX] = "ebx",
7878 [R_ECX] = "ecx",
7879 [R_EDX] = "edx",
7880 [R_ESI] = "esi",
7881 [R_EDI] = "edi",
7882 [R_EBP] = "ebp",
7883 [R_ESP] = "esp",
7884 #endif
7886 int i;
7888 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7889 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
7890 offsetof(CPUX86State, cc_op), "cc_op");
7891 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
7892 "cc_dst");
7893 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
7894 "cc_src");
7895 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
7896 "cc_src2");
7898 for (i = 0; i < CPU_NB_REGS; ++i) {
7899 cpu_regs[i] = tcg_global_mem_new(TCG_AREG0,
7900 offsetof(CPUX86State, regs[i]),
7901 reg_names[i]);
7905 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7906 basic block 'tb'. If search_pc is TRUE, also generate PC
7907 information for each intermediate instruction. */
7908 static inline void gen_intermediate_code_internal(X86CPU *cpu,
7909 TranslationBlock *tb,
7910 bool search_pc)
7912 CPUState *cs = CPU(cpu);
7913 CPUX86State *env = &cpu->env;
7914 DisasContext dc1, *dc = &dc1;
7915 target_ulong pc_ptr;
7916 CPUBreakpoint *bp;
7917 int j, lj;
7918 uint64_t flags;
7919 target_ulong pc_start;
7920 target_ulong cs_base;
7921 int num_insns;
7922 int max_insns;
7924 /* generate intermediate code */
7925 pc_start = tb->pc;
7926 cs_base = tb->cs_base;
7927 flags = tb->flags;
7929 dc->pe = (flags >> HF_PE_SHIFT) & 1;
7930 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7931 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7932 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7933 dc->f_st = 0;
7934 dc->vm86 = (flags >> VM_SHIFT) & 1;
7935 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7936 dc->iopl = (flags >> IOPL_SHIFT) & 3;
7937 dc->tf = (flags >> TF_SHIFT) & 1;
7938 dc->singlestep_enabled = cs->singlestep_enabled;
7939 dc->cc_op = CC_OP_DYNAMIC;
7940 dc->cc_op_dirty = false;
7941 dc->cs_base = cs_base;
7942 dc->tb = tb;
7943 dc->popl_esp_hack = 0;
7944 /* select memory access functions */
7945 dc->mem_index = 0;
7946 if (flags & HF_SOFTMMU_MASK) {
7947 dc->mem_index = cpu_mmu_index(env);
7949 dc->cpuid_features = env->features[FEAT_1_EDX];
7950 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
7951 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
7952 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
7953 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
7954 #ifdef TARGET_X86_64
7955 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7956 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7957 #endif
7958 dc->flags = flags;
7959 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
7960 (flags & HF_INHIBIT_IRQ_MASK)
7961 #ifndef CONFIG_SOFTMMU
7962 || (flags & HF_SOFTMMU_MASK)
7963 #endif
7965 /* Do not optimize repz jumps at all in icount mode, because
7966 rep movsS instructions are execured with different paths
7967 in !repz_opt and repz_opt modes. The first one was used
7968 always except single step mode. And this setting
7969 disables jumps optimization and control paths become
7970 equivalent in run and single step modes.
7971 Now there will be no jump optimization for repz in
7972 record/replay modes and there will always be an
7973 additional step for ecx=0 when icount is enabled.
7975 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
7976 #if 0
7977 /* check addseg logic */
7978 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
7979 printf("ERROR addseg\n");
7980 #endif
7982 cpu_T[0] = tcg_temp_new();
7983 cpu_T[1] = tcg_temp_new();
7984 cpu_A0 = tcg_temp_new();
7986 cpu_tmp0 = tcg_temp_new();
7987 cpu_tmp1_i64 = tcg_temp_new_i64();
7988 cpu_tmp2_i32 = tcg_temp_new_i32();
7989 cpu_tmp3_i32 = tcg_temp_new_i32();
7990 cpu_tmp4 = tcg_temp_new();
7991 cpu_ptr0 = tcg_temp_new_ptr();
7992 cpu_ptr1 = tcg_temp_new_ptr();
7993 cpu_cc_srcT = tcg_temp_local_new();
7995 dc->is_jmp = DISAS_NEXT;
7996 pc_ptr = pc_start;
7997 lj = -1;
7998 num_insns = 0;
7999 max_insns = tb->cflags & CF_COUNT_MASK;
8000 if (max_insns == 0)
8001 max_insns = CF_COUNT_MASK;
8003 gen_tb_start(tb);
8004 for(;;) {
8005 #if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
8006 /* Detect vsyscall */
8007 if (unlikely(pc_ptr >= TARGET_VSYSCALL_START
8008 && pc_ptr < TARGET_VSYSCALL_END)) {
8009 gen_helper_vsyscall(cpu_env);
8010 break;
8012 #endif
8014 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
8015 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
8016 if (bp->pc == pc_ptr &&
8017 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
8018 gen_debug(dc, pc_ptr - dc->cs_base);
8019 goto done_generating;
8023 if (search_pc) {
8024 j = tcg_op_buf_count();
8025 if (lj < j) {
8026 lj++;
8027 while (lj < j)
8028 tcg_ctx.gen_opc_instr_start[lj++] = 0;
8030 tcg_ctx.gen_opc_pc[lj] = pc_ptr;
8031 gen_opc_cc_op[lj] = dc->cc_op;
8032 tcg_ctx.gen_opc_instr_start[lj] = 1;
8033 tcg_ctx.gen_opc_icount[lj] = num_insns;
8035 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8036 gen_io_start();
8038 pc_ptr = disas_insn(env, dc, pc_ptr);
8039 num_insns++;
8040 /* stop translation if indicated */
8041 if (dc->is_jmp)
8042 break;
8043 /* if single step mode, we generate only one instruction and
8044 generate an exception */
8045 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8046 the flag and abort the translation to give the irqs a
8047 change to be happen */
8048 if (dc->tf || dc->singlestep_enabled ||
8049 (flags & HF_INHIBIT_IRQ_MASK)) {
8050 gen_jmp_im(pc_ptr - dc->cs_base);
8051 gen_eob(dc);
8052 break;
8054 /* Do not cross the boundary of the pages in icount mode,
8055 it can cause an exception. Do it only when boundary is
8056 crossed by the first instruction in the block.
8057 If current instruction already crossed the bound - it's ok,
8058 because an exception hasn't stopped this code.
8060 if ((tb->cflags & CF_USE_ICOUNT)
8061 && ((pc_ptr & TARGET_PAGE_MASK)
8062 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
8063 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
8064 gen_jmp_im(pc_ptr - dc->cs_base);
8065 gen_eob(dc);
8066 break;
8068 /* if too long translation, stop generation too */
8069 if (tcg_op_buf_full() ||
8070 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8071 num_insns >= max_insns) {
8072 gen_jmp_im(pc_ptr - dc->cs_base);
8073 gen_eob(dc);
8074 break;
8076 if (singlestep) {
8077 gen_jmp_im(pc_ptr - dc->cs_base);
8078 gen_eob(dc);
8079 break;
8082 if (tb->cflags & CF_LAST_IO)
8083 gen_io_end();
8084 done_generating:
8085 gen_tb_end(tb, num_insns);
8087 /* we don't forget to fill the last values */
8088 if (search_pc) {
8089 j = tcg_op_buf_count();
8090 lj++;
8091 while (lj <= j)
8092 tcg_ctx.gen_opc_instr_start[lj++] = 0;
8095 #ifdef DEBUG_DISAS
8096 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8097 int disas_flags;
8098 qemu_log("----------------\n");
8099 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8100 #ifdef TARGET_X86_64
8101 if (dc->code64)
8102 disas_flags = 2;
8103 else
8104 #endif
8105 disas_flags = !dc->code32;
8106 log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
8107 qemu_log("\n");
8109 #endif
8111 if (!search_pc) {
8112 tb->size = pc_ptr - pc_start;
8113 tb->icount = num_insns;
8117 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
8119 gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false);
8122 void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
8124 gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true);
8127 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
8129 int cc_op;
8130 #ifdef DEBUG_DISAS
8131 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
8132 int i;
8133 qemu_log("RESTORE:\n");
8134 for(i = 0;i <= pc_pos; i++) {
8135 if (tcg_ctx.gen_opc_instr_start[i]) {
8136 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
8137 tcg_ctx.gen_opc_pc[i]);
8140 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
8141 pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
8142 (uint32_t)tb->cs_base);
8144 #endif
8145 env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
8146 cc_op = gen_opc_cc_op[pc_pos];
8147 if (cc_op != CC_OP_DYNAMIC)
8148 env->cc_op = cc_op;