target-arm: dump-guest-memory: add prfpreg notes for aarch64
[qemu/ar7.git] / target-i386 / translate.c
bloba3dd167a9b20c0d25d612659908f04c00e0a1ead
1 /*
2 * i386 translation
4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
25 #include "qemu/host-utils.h"
26 #include "cpu.h"
27 #include "disas/disas.h"
28 #include "tcg-op.h"
29 #include "exec/cpu_ldst.h"
31 #include "exec/helper-proto.h"
32 #include "exec/helper-gen.h"
34 #include "trace-tcg.h"
37 #define PREFIX_REPZ 0x01
38 #define PREFIX_REPNZ 0x02
39 #define PREFIX_LOCK 0x04
40 #define PREFIX_DATA 0x08
41 #define PREFIX_ADR 0x10
42 #define PREFIX_VEX 0x20
44 #ifdef TARGET_X86_64
45 #define CODE64(s) ((s)->code64)
46 #define REX_X(s) ((s)->rex_x)
47 #define REX_B(s) ((s)->rex_b)
48 #else
49 #define CODE64(s) 0
50 #define REX_X(s) 0
51 #define REX_B(s) 0
52 #endif
54 #ifdef TARGET_X86_64
55 # define ctztl ctz64
56 # define clztl clz64
57 #else
58 # define ctztl ctz32
59 # define clztl clz32
60 #endif
62 //#define MACRO_TEST 1
64 /* global register indexes */
65 static TCGv_ptr cpu_env;
66 static TCGv cpu_A0;
67 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
68 static TCGv_i32 cpu_cc_op;
69 static TCGv cpu_regs[CPU_NB_REGS];
70 /* local temps */
71 static TCGv cpu_T[2];
72 /* local register indexes (only used inside old micro ops) */
73 static TCGv cpu_tmp0, cpu_tmp4;
74 static TCGv_ptr cpu_ptr0, cpu_ptr1;
75 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
76 static TCGv_i64 cpu_tmp1_i64;
78 #include "exec/gen-icount.h"
80 #ifdef TARGET_X86_64
81 static int x86_64_hregs;
82 #endif
84 typedef struct DisasContext {
85 /* current insn context */
86 int override; /* -1 if no override */
87 int prefix;
88 TCGMemOp aflag;
89 TCGMemOp dflag;
90 target_ulong pc; /* pc = eip + cs_base */
91 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
92 static state change (stop translation) */
93 /* current block context */
94 target_ulong cs_base; /* base of CS segment */
95 int pe; /* protected mode */
96 int code32; /* 32 bit code segment */
97 #ifdef TARGET_X86_64
98 int lma; /* long mode active */
99 int code64; /* 64 bit code segment */
100 int rex_x, rex_b;
101 #endif
102 int vex_l; /* vex vector length */
103 int vex_v; /* vex vvvv register, without 1's compliment. */
104 int ss32; /* 32 bit stack segment */
105 CCOp cc_op; /* current CC operation */
106 bool cc_op_dirty;
107 int addseg; /* non zero if either DS/ES/SS have a non zero base */
108 int f_st; /* currently unused */
109 int vm86; /* vm86 mode */
110 int cpl;
111 int iopl;
112 int tf; /* TF cpu flag */
113 int singlestep_enabled; /* "hardware" single step enabled */
114 int jmp_opt; /* use direct block chaining for direct jumps */
115 int repz_opt; /* optimize jumps within repz instructions */
116 int mem_index; /* select memory access functions */
117 uint64_t flags; /* all execution flags */
118 struct TranslationBlock *tb;
119 int popl_esp_hack; /* for correct popl with esp base handling */
120 int rip_offset; /* only used in x86_64, but left for simplicity */
121 int cpuid_features;
122 int cpuid_ext_features;
123 int cpuid_ext2_features;
124 int cpuid_ext3_features;
125 int cpuid_7_0_ebx_features;
126 } DisasContext;
128 static void gen_eob(DisasContext *s);
129 static void gen_jmp(DisasContext *s, target_ulong eip);
130 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
131 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d);
133 /* i386 arith/logic operations */
134 enum {
135 OP_ADDL,
136 OP_ORL,
137 OP_ADCL,
138 OP_SBBL,
139 OP_ANDL,
140 OP_SUBL,
141 OP_XORL,
142 OP_CMPL,
145 /* i386 shift ops */
146 enum {
147 OP_ROL,
148 OP_ROR,
149 OP_RCL,
150 OP_RCR,
151 OP_SHL,
152 OP_SHR,
153 OP_SHL1, /* undocumented */
154 OP_SAR = 7,
157 enum {
158 JCC_O,
159 JCC_B,
160 JCC_Z,
161 JCC_BE,
162 JCC_S,
163 JCC_P,
164 JCC_L,
165 JCC_LE,
168 enum {
169 /* I386 int registers */
170 OR_EAX, /* MUST be even numbered */
171 OR_ECX,
172 OR_EDX,
173 OR_EBX,
174 OR_ESP,
175 OR_EBP,
176 OR_ESI,
177 OR_EDI,
179 OR_TMP0 = 16, /* temporary operand register */
180 OR_TMP1,
181 OR_A0, /* temporary register used when doing address evaluation */
184 enum {
185 USES_CC_DST = 1,
186 USES_CC_SRC = 2,
187 USES_CC_SRC2 = 4,
188 USES_CC_SRCT = 8,
191 /* Bit set if the global variable is live after setting CC_OP to X. */
192 static const uint8_t cc_op_live[CC_OP_NB] = {
193 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
194 [CC_OP_EFLAGS] = USES_CC_SRC,
195 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
196 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
197 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
198 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
199 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
200 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
201 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
202 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
203 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
204 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
205 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
206 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
207 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
208 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
209 [CC_OP_CLR] = 0,
212 static void set_cc_op(DisasContext *s, CCOp op)
214 int dead;
216 if (s->cc_op == op) {
217 return;
220 /* Discard CC computation that will no longer be used. */
221 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
222 if (dead & USES_CC_DST) {
223 tcg_gen_discard_tl(cpu_cc_dst);
225 if (dead & USES_CC_SRC) {
226 tcg_gen_discard_tl(cpu_cc_src);
228 if (dead & USES_CC_SRC2) {
229 tcg_gen_discard_tl(cpu_cc_src2);
231 if (dead & USES_CC_SRCT) {
232 tcg_gen_discard_tl(cpu_cc_srcT);
235 if (op == CC_OP_DYNAMIC) {
236 /* The DYNAMIC setting is translator only, and should never be
237 stored. Thus we always consider it clean. */
238 s->cc_op_dirty = false;
239 } else {
240 /* Discard any computed CC_OP value (see shifts). */
241 if (s->cc_op == CC_OP_DYNAMIC) {
242 tcg_gen_discard_i32(cpu_cc_op);
244 s->cc_op_dirty = true;
246 s->cc_op = op;
249 static void gen_update_cc_op(DisasContext *s)
251 if (s->cc_op_dirty) {
252 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
253 s->cc_op_dirty = false;
257 #ifdef TARGET_X86_64
259 #define NB_OP_SIZES 4
261 #else /* !TARGET_X86_64 */
263 #define NB_OP_SIZES 3
265 #endif /* !TARGET_X86_64 */
267 #if defined(HOST_WORDS_BIGENDIAN)
268 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
269 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
270 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
271 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
272 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
273 #else
274 #define REG_B_OFFSET 0
275 #define REG_H_OFFSET 1
276 #define REG_W_OFFSET 0
277 #define REG_L_OFFSET 0
278 #define REG_LH_OFFSET 4
279 #endif
281 /* In instruction encodings for byte register accesses the
282 * register number usually indicates "low 8 bits of register N";
283 * however there are some special cases where N 4..7 indicates
284 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
285 * true for this special case, false otherwise.
287 static inline bool byte_reg_is_xH(int reg)
289 if (reg < 4) {
290 return false;
292 #ifdef TARGET_X86_64
293 if (reg >= 8 || x86_64_hregs) {
294 return false;
296 #endif
297 return true;
300 /* Select the size of a push/pop operation. */
301 static inline TCGMemOp mo_pushpop(DisasContext *s, TCGMemOp ot)
303 if (CODE64(s)) {
304 return ot == MO_16 ? MO_16 : MO_64;
305 } else {
306 return ot;
310 /* Select only size 64 else 32. Used for SSE operand sizes. */
311 static inline TCGMemOp mo_64_32(TCGMemOp ot)
313 #ifdef TARGET_X86_64
314 return ot == MO_64 ? MO_64 : MO_32;
315 #else
316 return MO_32;
317 #endif
320 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
321 byte vs word opcodes. */
322 static inline TCGMemOp mo_b_d(int b, TCGMemOp ot)
324 return b & 1 ? ot : MO_8;
327 /* Select size 8 if lsb of B is clear, else OT capped at 32.
328 Used for decoding operand size of port opcodes. */
329 static inline TCGMemOp mo_b_d32(int b, TCGMemOp ot)
331 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
334 static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
336 switch(ot) {
337 case MO_8:
338 if (!byte_reg_is_xH(reg)) {
339 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
340 } else {
341 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
343 break;
344 case MO_16:
345 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
346 break;
347 case MO_32:
348 /* For x86_64, this sets the higher half of register to zero.
349 For i386, this is equivalent to a mov. */
350 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
351 break;
352 #ifdef TARGET_X86_64
353 case MO_64:
354 tcg_gen_mov_tl(cpu_regs[reg], t0);
355 break;
356 #endif
357 default:
358 tcg_abort();
362 static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
364 if (ot == MO_8 && byte_reg_is_xH(reg)) {
365 tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
366 tcg_gen_ext8u_tl(t0, t0);
367 } else {
368 tcg_gen_mov_tl(t0, cpu_regs[reg]);
372 static inline void gen_op_movl_A0_reg(int reg)
374 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
377 static inline void gen_op_addl_A0_im(int32_t val)
379 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
380 #ifdef TARGET_X86_64
381 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
382 #endif
385 #ifdef TARGET_X86_64
386 static inline void gen_op_addq_A0_im(int64_t val)
388 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
390 #endif
392 static void gen_add_A0_im(DisasContext *s, int val)
394 #ifdef TARGET_X86_64
395 if (CODE64(s))
396 gen_op_addq_A0_im(val);
397 else
398 #endif
399 gen_op_addl_A0_im(val);
402 static inline void gen_op_jmp_v(TCGv dest)
404 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
407 static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
409 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
410 gen_op_mov_reg_v(size, reg, cpu_tmp0);
413 static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
415 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
416 gen_op_mov_reg_v(size, reg, cpu_tmp0);
419 static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
421 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
422 if (shift != 0)
423 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
424 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
425 /* For x86_64, this sets the higher half of register to zero.
426 For i386, this is equivalent to a nop. */
427 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
430 static inline void gen_op_movl_A0_seg(int reg)
432 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
435 static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
437 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
438 #ifdef TARGET_X86_64
439 if (CODE64(s)) {
440 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
441 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
442 } else {
443 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
444 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
446 #else
447 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
448 #endif
451 #ifdef TARGET_X86_64
452 static inline void gen_op_movq_A0_seg(int reg)
454 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
457 static inline void gen_op_addq_A0_seg(int reg)
459 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
460 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
463 static inline void gen_op_movq_A0_reg(int reg)
465 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
468 static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
470 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
471 if (shift != 0)
472 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
473 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
475 #endif
477 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
479 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
482 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
484 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
487 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
489 if (d == OR_TMP0) {
490 gen_op_st_v(s, idx, cpu_T[0], cpu_A0);
491 } else {
492 gen_op_mov_reg_v(idx, d, cpu_T[0]);
496 static inline void gen_jmp_im(target_ulong pc)
498 tcg_gen_movi_tl(cpu_tmp0, pc);
499 gen_op_jmp_v(cpu_tmp0);
502 static inline void gen_string_movl_A0_ESI(DisasContext *s)
504 int override;
506 override = s->override;
507 switch (s->aflag) {
508 #ifdef TARGET_X86_64
509 case MO_64:
510 if (override >= 0) {
511 gen_op_movq_A0_seg(override);
512 gen_op_addq_A0_reg_sN(0, R_ESI);
513 } else {
514 gen_op_movq_A0_reg(R_ESI);
516 break;
517 #endif
518 case MO_32:
519 /* 32 bit address */
520 if (s->addseg && override < 0)
521 override = R_DS;
522 if (override >= 0) {
523 gen_op_movl_A0_seg(override);
524 gen_op_addl_A0_reg_sN(0, R_ESI);
525 } else {
526 gen_op_movl_A0_reg(R_ESI);
528 break;
529 case MO_16:
530 /* 16 address, always override */
531 if (override < 0)
532 override = R_DS;
533 tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESI]);
534 gen_op_addl_A0_seg(s, override);
535 break;
536 default:
537 tcg_abort();
541 static inline void gen_string_movl_A0_EDI(DisasContext *s)
543 switch (s->aflag) {
544 #ifdef TARGET_X86_64
545 case MO_64:
546 gen_op_movq_A0_reg(R_EDI);
547 break;
548 #endif
549 case MO_32:
550 if (s->addseg) {
551 gen_op_movl_A0_seg(R_ES);
552 gen_op_addl_A0_reg_sN(0, R_EDI);
553 } else {
554 gen_op_movl_A0_reg(R_EDI);
556 break;
557 case MO_16:
558 tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_EDI]);
559 gen_op_addl_A0_seg(s, R_ES);
560 break;
561 default:
562 tcg_abort();
566 static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
568 tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
569 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
572 static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign)
574 switch (size) {
575 case MO_8:
576 if (sign) {
577 tcg_gen_ext8s_tl(dst, src);
578 } else {
579 tcg_gen_ext8u_tl(dst, src);
581 return dst;
582 case MO_16:
583 if (sign) {
584 tcg_gen_ext16s_tl(dst, src);
585 } else {
586 tcg_gen_ext16u_tl(dst, src);
588 return dst;
589 #ifdef TARGET_X86_64
590 case MO_32:
591 if (sign) {
592 tcg_gen_ext32s_tl(dst, src);
593 } else {
594 tcg_gen_ext32u_tl(dst, src);
596 return dst;
597 #endif
598 default:
599 return src;
603 static void gen_extu(TCGMemOp ot, TCGv reg)
605 gen_ext_tl(reg, reg, ot, false);
608 static void gen_exts(TCGMemOp ot, TCGv reg)
610 gen_ext_tl(reg, reg, ot, true);
613 static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1)
615 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
616 gen_extu(size, cpu_tmp0);
617 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
620 static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1)
622 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
623 gen_extu(size, cpu_tmp0);
624 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
627 static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n)
629 switch (ot) {
630 case MO_8:
631 gen_helper_inb(v, cpu_env, n);
632 break;
633 case MO_16:
634 gen_helper_inw(v, cpu_env, n);
635 break;
636 case MO_32:
637 gen_helper_inl(v, cpu_env, n);
638 break;
639 default:
640 tcg_abort();
644 static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n)
646 switch (ot) {
647 case MO_8:
648 gen_helper_outb(cpu_env, v, n);
649 break;
650 case MO_16:
651 gen_helper_outw(cpu_env, v, n);
652 break;
653 case MO_32:
654 gen_helper_outl(cpu_env, v, n);
655 break;
656 default:
657 tcg_abort();
661 static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
662 uint32_t svm_flags)
664 target_ulong next_eip;
666 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
667 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
668 switch (ot) {
669 case MO_8:
670 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
671 break;
672 case MO_16:
673 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
674 break;
675 case MO_32:
676 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
677 break;
678 default:
679 tcg_abort();
682 if(s->flags & HF_SVMI_MASK) {
683 gen_update_cc_op(s);
684 gen_jmp_im(cur_eip);
685 svm_flags |= (1 << (4 + ot));
686 next_eip = s->pc - s->cs_base;
687 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
688 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
689 tcg_const_i32(svm_flags),
690 tcg_const_i32(next_eip - cur_eip));
694 static inline void gen_movs(DisasContext *s, TCGMemOp ot)
696 gen_string_movl_A0_ESI(s);
697 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
698 gen_string_movl_A0_EDI(s);
699 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
700 gen_op_movl_T0_Dshift(ot);
701 gen_op_add_reg_T0(s->aflag, R_ESI);
702 gen_op_add_reg_T0(s->aflag, R_EDI);
705 static void gen_op_update1_cc(void)
707 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
710 static void gen_op_update2_cc(void)
712 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
713 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
716 static void gen_op_update3_cc(TCGv reg)
718 tcg_gen_mov_tl(cpu_cc_src2, reg);
719 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
720 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
723 static inline void gen_op_testl_T0_T1_cc(void)
725 tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
728 static void gen_op_update_neg_cc(void)
730 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
731 tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]);
732 tcg_gen_movi_tl(cpu_cc_srcT, 0);
735 /* compute all eflags to cc_src */
736 static void gen_compute_eflags(DisasContext *s)
738 TCGv zero, dst, src1, src2;
739 int live, dead;
741 if (s->cc_op == CC_OP_EFLAGS) {
742 return;
744 if (s->cc_op == CC_OP_CLR) {
745 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
746 set_cc_op(s, CC_OP_EFLAGS);
747 return;
750 TCGV_UNUSED(zero);
751 dst = cpu_cc_dst;
752 src1 = cpu_cc_src;
753 src2 = cpu_cc_src2;
755 /* Take care to not read values that are not live. */
756 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
757 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
758 if (dead) {
759 zero = tcg_const_tl(0);
760 if (dead & USES_CC_DST) {
761 dst = zero;
763 if (dead & USES_CC_SRC) {
764 src1 = zero;
766 if (dead & USES_CC_SRC2) {
767 src2 = zero;
771 gen_update_cc_op(s);
772 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
773 set_cc_op(s, CC_OP_EFLAGS);
775 if (dead) {
776 tcg_temp_free(zero);
780 typedef struct CCPrepare {
781 TCGCond cond;
782 TCGv reg;
783 TCGv reg2;
784 target_ulong imm;
785 target_ulong mask;
786 bool use_reg2;
787 bool no_setcond;
788 } CCPrepare;
790 /* compute eflags.C to reg */
791 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
793 TCGv t0, t1;
794 int size, shift;
796 switch (s->cc_op) {
797 case CC_OP_SUBB ... CC_OP_SUBQ:
798 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
799 size = s->cc_op - CC_OP_SUBB;
800 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
801 /* If no temporary was used, be careful not to alias t1 and t0. */
802 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
803 tcg_gen_mov_tl(t0, cpu_cc_srcT);
804 gen_extu(size, t0);
805 goto add_sub;
807 case CC_OP_ADDB ... CC_OP_ADDQ:
808 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
809 size = s->cc_op - CC_OP_ADDB;
810 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
811 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
812 add_sub:
813 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
814 .reg2 = t1, .mask = -1, .use_reg2 = true };
816 case CC_OP_LOGICB ... CC_OP_LOGICQ:
817 case CC_OP_CLR:
818 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
820 case CC_OP_INCB ... CC_OP_INCQ:
821 case CC_OP_DECB ... CC_OP_DECQ:
822 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
823 .mask = -1, .no_setcond = true };
825 case CC_OP_SHLB ... CC_OP_SHLQ:
826 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
827 size = s->cc_op - CC_OP_SHLB;
828 shift = (8 << size) - 1;
829 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
830 .mask = (target_ulong)1 << shift };
832 case CC_OP_MULB ... CC_OP_MULQ:
833 return (CCPrepare) { .cond = TCG_COND_NE,
834 .reg = cpu_cc_src, .mask = -1 };
836 case CC_OP_BMILGB ... CC_OP_BMILGQ:
837 size = s->cc_op - CC_OP_BMILGB;
838 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
839 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
841 case CC_OP_ADCX:
842 case CC_OP_ADCOX:
843 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
844 .mask = -1, .no_setcond = true };
846 case CC_OP_EFLAGS:
847 case CC_OP_SARB ... CC_OP_SARQ:
848 /* CC_SRC & 1 */
849 return (CCPrepare) { .cond = TCG_COND_NE,
850 .reg = cpu_cc_src, .mask = CC_C };
852 default:
853 /* The need to compute only C from CC_OP_DYNAMIC is important
854 in efficiently implementing e.g. INC at the start of a TB. */
855 gen_update_cc_op(s);
856 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
857 cpu_cc_src2, cpu_cc_op);
858 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
859 .mask = -1, .no_setcond = true };
863 /* compute eflags.P to reg */
864 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
866 gen_compute_eflags(s);
867 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
868 .mask = CC_P };
871 /* compute eflags.S to reg */
872 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
874 switch (s->cc_op) {
875 case CC_OP_DYNAMIC:
876 gen_compute_eflags(s);
877 /* FALLTHRU */
878 case CC_OP_EFLAGS:
879 case CC_OP_ADCX:
880 case CC_OP_ADOX:
881 case CC_OP_ADCOX:
882 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
883 .mask = CC_S };
884 case CC_OP_CLR:
885 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
886 default:
888 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
889 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
890 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
895 /* compute eflags.O to reg */
896 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
898 switch (s->cc_op) {
899 case CC_OP_ADOX:
900 case CC_OP_ADCOX:
901 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
902 .mask = -1, .no_setcond = true };
903 case CC_OP_CLR:
904 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
905 default:
906 gen_compute_eflags(s);
907 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
908 .mask = CC_O };
912 /* compute eflags.Z to reg */
913 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
915 switch (s->cc_op) {
916 case CC_OP_DYNAMIC:
917 gen_compute_eflags(s);
918 /* FALLTHRU */
919 case CC_OP_EFLAGS:
920 case CC_OP_ADCX:
921 case CC_OP_ADOX:
922 case CC_OP_ADCOX:
923 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
924 .mask = CC_Z };
925 case CC_OP_CLR:
926 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
927 default:
929 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
930 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
931 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
936 /* perform a conditional store into register 'reg' according to jump opcode
937 value 'b'. In the fast case, T0 is guaranted not to be used. */
938 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
940 int inv, jcc_op, cond;
941 TCGMemOp size;
942 CCPrepare cc;
943 TCGv t0;
945 inv = b & 1;
946 jcc_op = (b >> 1) & 7;
948 switch (s->cc_op) {
949 case CC_OP_SUBB ... CC_OP_SUBQ:
950 /* We optimize relational operators for the cmp/jcc case. */
951 size = s->cc_op - CC_OP_SUBB;
952 switch (jcc_op) {
953 case JCC_BE:
954 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
955 gen_extu(size, cpu_tmp4);
956 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
957 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
958 .reg2 = t0, .mask = -1, .use_reg2 = true };
959 break;
961 case JCC_L:
962 cond = TCG_COND_LT;
963 goto fast_jcc_l;
964 case JCC_LE:
965 cond = TCG_COND_LE;
966 fast_jcc_l:
967 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
968 gen_exts(size, cpu_tmp4);
969 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
970 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
971 .reg2 = t0, .mask = -1, .use_reg2 = true };
972 break;
974 default:
975 goto slow_jcc;
977 break;
979 default:
980 slow_jcc:
981 /* This actually generates good code for JC, JZ and JS. */
982 switch (jcc_op) {
983 case JCC_O:
984 cc = gen_prepare_eflags_o(s, reg);
985 break;
986 case JCC_B:
987 cc = gen_prepare_eflags_c(s, reg);
988 break;
989 case JCC_Z:
990 cc = gen_prepare_eflags_z(s, reg);
991 break;
992 case JCC_BE:
993 gen_compute_eflags(s);
994 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
995 .mask = CC_Z | CC_C };
996 break;
997 case JCC_S:
998 cc = gen_prepare_eflags_s(s, reg);
999 break;
1000 case JCC_P:
1001 cc = gen_prepare_eflags_p(s, reg);
1002 break;
1003 case JCC_L:
1004 gen_compute_eflags(s);
1005 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1006 reg = cpu_tmp0;
1008 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1009 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1010 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1011 .mask = CC_S };
1012 break;
1013 default:
1014 case JCC_LE:
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 | CC_Z };
1023 break;
1025 break;
1028 if (inv) {
1029 cc.cond = tcg_invert_cond(cc.cond);
1031 return cc;
1034 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1036 CCPrepare cc = gen_prepare_cc(s, b, reg);
1038 if (cc.no_setcond) {
1039 if (cc.cond == TCG_COND_EQ) {
1040 tcg_gen_xori_tl(reg, cc.reg, 1);
1041 } else {
1042 tcg_gen_mov_tl(reg, cc.reg);
1044 return;
1047 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1048 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1049 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1050 tcg_gen_andi_tl(reg, reg, 1);
1051 return;
1053 if (cc.mask != -1) {
1054 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1055 cc.reg = reg;
1057 if (cc.use_reg2) {
1058 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1059 } else {
1060 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1064 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1066 gen_setcc1(s, JCC_B << 1, reg);
1069 /* generate a conditional jump to label 'l1' according to jump opcode
1070 value 'b'. In the fast case, T0 is guaranted not to be used. */
1071 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1073 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1075 if (cc.mask != -1) {
1076 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1077 cc.reg = cpu_T[0];
1079 if (cc.use_reg2) {
1080 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1081 } else {
1082 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1086 /* Generate a conditional jump to label 'l1' according to jump opcode
1087 value 'b'. In the fast case, T0 is guaranted not to be used.
1088 A translation block must end soon. */
1089 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1091 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1093 gen_update_cc_op(s);
1094 if (cc.mask != -1) {
1095 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1096 cc.reg = cpu_T[0];
1098 set_cc_op(s, CC_OP_DYNAMIC);
1099 if (cc.use_reg2) {
1100 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1101 } else {
1102 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1106 /* XXX: does not work with gdbstub "ice" single step - not a
1107 serious problem */
1108 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1110 TCGLabel *l1 = gen_new_label();
1111 TCGLabel *l2 = gen_new_label();
1112 gen_op_jnz_ecx(s->aflag, l1);
1113 gen_set_label(l2);
1114 gen_jmp_tb(s, next_eip, 1);
1115 gen_set_label(l1);
1116 return l2;
1119 static inline void gen_stos(DisasContext *s, TCGMemOp ot)
1121 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
1122 gen_string_movl_A0_EDI(s);
1123 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
1124 gen_op_movl_T0_Dshift(ot);
1125 gen_op_add_reg_T0(s->aflag, R_EDI);
1128 static inline void gen_lods(DisasContext *s, TCGMemOp ot)
1130 gen_string_movl_A0_ESI(s);
1131 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1132 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
1133 gen_op_movl_T0_Dshift(ot);
1134 gen_op_add_reg_T0(s->aflag, R_ESI);
1137 static inline void gen_scas(DisasContext *s, TCGMemOp ot)
1139 gen_string_movl_A0_EDI(s);
1140 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
1141 gen_op(s, OP_CMPL, ot, R_EAX);
1142 gen_op_movl_T0_Dshift(ot);
1143 gen_op_add_reg_T0(s->aflag, R_EDI);
1146 static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
1148 gen_string_movl_A0_EDI(s);
1149 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
1150 gen_string_movl_A0_ESI(s);
1151 gen_op(s, OP_CMPL, ot, OR_TMP0);
1152 gen_op_movl_T0_Dshift(ot);
1153 gen_op_add_reg_T0(s->aflag, R_ESI);
1154 gen_op_add_reg_T0(s->aflag, R_EDI);
1157 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1159 if (s->flags & HF_IOBPT_MASK) {
1160 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1161 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1163 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1164 tcg_temp_free_i32(t_size);
1165 tcg_temp_free(t_next);
1170 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
1172 if (s->tb->cflags & CF_USE_ICOUNT) {
1173 gen_io_start();
1175 gen_string_movl_A0_EDI(s);
1176 /* Note: we must do this dummy write first to be restartable in
1177 case of page fault. */
1178 tcg_gen_movi_tl(cpu_T[0], 0);
1179 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
1180 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1181 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1182 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
1183 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
1184 gen_op_movl_T0_Dshift(ot);
1185 gen_op_add_reg_T0(s->aflag, R_EDI);
1186 gen_bpt_io(s, cpu_tmp2_i32, ot);
1187 if (s->tb->cflags & CF_USE_ICOUNT) {
1188 gen_io_end();
1192 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
1194 if (s->tb->cflags & CF_USE_ICOUNT) {
1195 gen_io_start();
1197 gen_string_movl_A0_ESI(s);
1198 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1200 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
1201 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1202 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
1203 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1204 gen_op_movl_T0_Dshift(ot);
1205 gen_op_add_reg_T0(s->aflag, R_ESI);
1206 gen_bpt_io(s, cpu_tmp2_i32, ot);
1207 if (s->tb->cflags & CF_USE_ICOUNT) {
1208 gen_io_end();
1212 /* same method as Valgrind : we generate jumps to current or next
1213 instruction */
1214 #define GEN_REPZ(op) \
1215 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1216 target_ulong cur_eip, target_ulong next_eip) \
1218 TCGLabel *l2; \
1219 gen_update_cc_op(s); \
1220 l2 = gen_jz_ecx_string(s, next_eip); \
1221 gen_ ## op(s, ot); \
1222 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1223 /* a loop would cause two single step exceptions if ECX = 1 \
1224 before rep string_insn */ \
1225 if (s->repz_opt) \
1226 gen_op_jz_ecx(s->aflag, l2); \
1227 gen_jmp(s, cur_eip); \
1230 #define GEN_REPZ2(op) \
1231 static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
1232 target_ulong cur_eip, \
1233 target_ulong next_eip, \
1234 int nz) \
1236 TCGLabel *l2; \
1237 gen_update_cc_op(s); \
1238 l2 = gen_jz_ecx_string(s, next_eip); \
1239 gen_ ## op(s, ot); \
1240 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1241 gen_update_cc_op(s); \
1242 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1243 if (s->repz_opt) \
1244 gen_op_jz_ecx(s->aflag, l2); \
1245 gen_jmp(s, cur_eip); \
1248 GEN_REPZ(movs)
1249 GEN_REPZ(stos)
1250 GEN_REPZ(lods)
1251 GEN_REPZ(ins)
1252 GEN_REPZ(outs)
1253 GEN_REPZ2(scas)
1254 GEN_REPZ2(cmps)
1256 static void gen_helper_fp_arith_ST0_FT0(int op)
1258 switch (op) {
1259 case 0:
1260 gen_helper_fadd_ST0_FT0(cpu_env);
1261 break;
1262 case 1:
1263 gen_helper_fmul_ST0_FT0(cpu_env);
1264 break;
1265 case 2:
1266 gen_helper_fcom_ST0_FT0(cpu_env);
1267 break;
1268 case 3:
1269 gen_helper_fcom_ST0_FT0(cpu_env);
1270 break;
1271 case 4:
1272 gen_helper_fsub_ST0_FT0(cpu_env);
1273 break;
1274 case 5:
1275 gen_helper_fsubr_ST0_FT0(cpu_env);
1276 break;
1277 case 6:
1278 gen_helper_fdiv_ST0_FT0(cpu_env);
1279 break;
1280 case 7:
1281 gen_helper_fdivr_ST0_FT0(cpu_env);
1282 break;
1286 /* NOTE the exception in "r" op ordering */
1287 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1289 TCGv_i32 tmp = tcg_const_i32(opreg);
1290 switch (op) {
1291 case 0:
1292 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1293 break;
1294 case 1:
1295 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1296 break;
1297 case 4:
1298 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1299 break;
1300 case 5:
1301 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1302 break;
1303 case 6:
1304 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1305 break;
1306 case 7:
1307 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1308 break;
1312 /* if d == OR_TMP0, it means memory operand (address in A0) */
1313 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
1315 if (d != OR_TMP0) {
1316 gen_op_mov_v_reg(ot, cpu_T[0], d);
1317 } else {
1318 gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
1320 switch(op) {
1321 case OP_ADCL:
1322 gen_compute_eflags_c(s1, cpu_tmp4);
1323 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1324 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1325 gen_op_st_rm_T0_A0(s1, ot, d);
1326 gen_op_update3_cc(cpu_tmp4);
1327 set_cc_op(s1, CC_OP_ADCB + ot);
1328 break;
1329 case OP_SBBL:
1330 gen_compute_eflags_c(s1, cpu_tmp4);
1331 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1332 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1333 gen_op_st_rm_T0_A0(s1, ot, d);
1334 gen_op_update3_cc(cpu_tmp4);
1335 set_cc_op(s1, CC_OP_SBBB + ot);
1336 break;
1337 case OP_ADDL:
1338 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1339 gen_op_st_rm_T0_A0(s1, ot, d);
1340 gen_op_update2_cc();
1341 set_cc_op(s1, CC_OP_ADDB + ot);
1342 break;
1343 case OP_SUBL:
1344 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1345 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1346 gen_op_st_rm_T0_A0(s1, ot, d);
1347 gen_op_update2_cc();
1348 set_cc_op(s1, CC_OP_SUBB + ot);
1349 break;
1350 default:
1351 case OP_ANDL:
1352 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1353 gen_op_st_rm_T0_A0(s1, ot, d);
1354 gen_op_update1_cc();
1355 set_cc_op(s1, CC_OP_LOGICB + ot);
1356 break;
1357 case OP_ORL:
1358 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1359 gen_op_st_rm_T0_A0(s1, ot, d);
1360 gen_op_update1_cc();
1361 set_cc_op(s1, CC_OP_LOGICB + ot);
1362 break;
1363 case OP_XORL:
1364 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1365 gen_op_st_rm_T0_A0(s1, ot, d);
1366 gen_op_update1_cc();
1367 set_cc_op(s1, CC_OP_LOGICB + ot);
1368 break;
1369 case OP_CMPL:
1370 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
1371 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1372 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
1373 set_cc_op(s1, CC_OP_SUBB + ot);
1374 break;
1378 /* if d == OR_TMP0, it means memory operand (address in A0) */
1379 static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
1381 if (d != OR_TMP0) {
1382 gen_op_mov_v_reg(ot, cpu_T[0], d);
1383 } else {
1384 gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
1386 gen_compute_eflags_c(s1, cpu_cc_src);
1387 if (c > 0) {
1388 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
1389 set_cc_op(s1, CC_OP_INCB + ot);
1390 } else {
1391 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
1392 set_cc_op(s1, CC_OP_DECB + ot);
1394 gen_op_st_rm_T0_A0(s1, ot, d);
1395 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1398 static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
1399 TCGv shm1, TCGv count, bool is_right)
1401 TCGv_i32 z32, s32, oldop;
1402 TCGv z_tl;
1404 /* Store the results into the CC variables. If we know that the
1405 variable must be dead, store unconditionally. Otherwise we'll
1406 need to not disrupt the current contents. */
1407 z_tl = tcg_const_tl(0);
1408 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1409 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1410 result, cpu_cc_dst);
1411 } else {
1412 tcg_gen_mov_tl(cpu_cc_dst, result);
1414 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1415 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1416 shm1, cpu_cc_src);
1417 } else {
1418 tcg_gen_mov_tl(cpu_cc_src, shm1);
1420 tcg_temp_free(z_tl);
1422 /* Get the two potential CC_OP values into temporaries. */
1423 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1424 if (s->cc_op == CC_OP_DYNAMIC) {
1425 oldop = cpu_cc_op;
1426 } else {
1427 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1428 oldop = cpu_tmp3_i32;
1431 /* Conditionally store the CC_OP value. */
1432 z32 = tcg_const_i32(0);
1433 s32 = tcg_temp_new_i32();
1434 tcg_gen_trunc_tl_i32(s32, count);
1435 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1436 tcg_temp_free_i32(z32);
1437 tcg_temp_free_i32(s32);
1439 /* The CC_OP value is no longer predictable. */
1440 set_cc_op(s, CC_OP_DYNAMIC);
1443 static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1444 int is_right, int is_arith)
1446 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1448 /* load */
1449 if (op1 == OR_TMP0) {
1450 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1451 } else {
1452 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1455 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1456 tcg_gen_subi_tl(cpu_tmp0, cpu_T[1], 1);
1458 if (is_right) {
1459 if (is_arith) {
1460 gen_exts(ot, cpu_T[0]);
1461 tcg_gen_sar_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1462 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1463 } else {
1464 gen_extu(ot, cpu_T[0]);
1465 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1466 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1468 } else {
1469 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1470 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1473 /* store */
1474 gen_op_st_rm_T0_A0(s, ot, op1);
1476 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, cpu_T[1], is_right);
1479 static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1480 int is_right, int is_arith)
1482 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1484 /* load */
1485 if (op1 == OR_TMP0)
1486 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1487 else
1488 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1490 op2 &= mask;
1491 if (op2 != 0) {
1492 if (is_right) {
1493 if (is_arith) {
1494 gen_exts(ot, cpu_T[0]);
1495 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1496 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
1497 } else {
1498 gen_extu(ot, cpu_T[0]);
1499 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1500 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
1502 } else {
1503 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1504 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
1508 /* store */
1509 gen_op_st_rm_T0_A0(s, ot, op1);
1511 /* update eflags if non zero shift */
1512 if (op2 != 0) {
1513 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1514 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1515 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1519 static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
1521 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1522 TCGv_i32 t0, t1;
1524 /* load */
1525 if (op1 == OR_TMP0) {
1526 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1527 } else {
1528 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1531 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1533 switch (ot) {
1534 case MO_8:
1535 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1536 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
1537 tcg_gen_muli_tl(cpu_T[0], cpu_T[0], 0x01010101);
1538 goto do_long;
1539 case MO_16:
1540 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1541 tcg_gen_deposit_tl(cpu_T[0], cpu_T[0], cpu_T[0], 16, 16);
1542 goto do_long;
1543 do_long:
1544 #ifdef TARGET_X86_64
1545 case MO_32:
1546 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1547 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
1548 if (is_right) {
1549 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1550 } else {
1551 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1553 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1554 break;
1555 #endif
1556 default:
1557 if (is_right) {
1558 tcg_gen_rotr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1559 } else {
1560 tcg_gen_rotl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1562 break;
1565 /* store */
1566 gen_op_st_rm_T0_A0(s, ot, op1);
1568 /* We'll need the flags computed into CC_SRC. */
1569 gen_compute_eflags(s);
1571 /* The value that was "rotated out" is now present at the other end
1572 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1573 since we've computed the flags into CC_SRC, these variables are
1574 currently dead. */
1575 if (is_right) {
1576 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1577 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1578 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1579 } else {
1580 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1581 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
1583 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1584 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1586 /* Now conditionally store the new CC_OP value. If the shift count
1587 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1588 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1589 exactly as we computed above. */
1590 t0 = tcg_const_i32(0);
1591 t1 = tcg_temp_new_i32();
1592 tcg_gen_trunc_tl_i32(t1, cpu_T[1]);
1593 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1594 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1595 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1596 cpu_tmp2_i32, cpu_tmp3_i32);
1597 tcg_temp_free_i32(t0);
1598 tcg_temp_free_i32(t1);
1600 /* The CC_OP value is no longer predictable. */
1601 set_cc_op(s, CC_OP_DYNAMIC);
1604 static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
1605 int is_right)
1607 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1608 int shift;
1610 /* load */
1611 if (op1 == OR_TMP0) {
1612 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1613 } else {
1614 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1617 op2 &= mask;
1618 if (op2 != 0) {
1619 switch (ot) {
1620 #ifdef TARGET_X86_64
1621 case MO_32:
1622 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1623 if (is_right) {
1624 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1625 } else {
1626 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1628 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1629 break;
1630 #endif
1631 default:
1632 if (is_right) {
1633 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], op2);
1634 } else {
1635 tcg_gen_rotli_tl(cpu_T[0], cpu_T[0], op2);
1637 break;
1638 case MO_8:
1639 mask = 7;
1640 goto do_shifts;
1641 case MO_16:
1642 mask = 15;
1643 do_shifts:
1644 shift = op2 & mask;
1645 if (is_right) {
1646 shift = mask + 1 - shift;
1648 gen_extu(ot, cpu_T[0]);
1649 tcg_gen_shli_tl(cpu_tmp0, cpu_T[0], shift);
1650 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], mask + 1 - shift);
1651 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
1652 break;
1656 /* store */
1657 gen_op_st_rm_T0_A0(s, ot, op1);
1659 if (op2 != 0) {
1660 /* Compute the flags into CC_SRC. */
1661 gen_compute_eflags(s);
1663 /* The value that was "rotated out" is now present at the other end
1664 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1665 since we've computed the flags into CC_SRC, these variables are
1666 currently dead. */
1667 if (is_right) {
1668 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1669 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1670 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1671 } else {
1672 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1673 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
1675 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1676 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1677 set_cc_op(s, CC_OP_ADCOX);
1681 /* XXX: add faster immediate = 1 case */
1682 static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1683 int is_right)
1685 gen_compute_eflags(s);
1686 assert(s->cc_op == CC_OP_EFLAGS);
1688 /* load */
1689 if (op1 == OR_TMP0)
1690 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1691 else
1692 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1694 if (is_right) {
1695 switch (ot) {
1696 case MO_8:
1697 gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1698 break;
1699 case MO_16:
1700 gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1701 break;
1702 case MO_32:
1703 gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1704 break;
1705 #ifdef TARGET_X86_64
1706 case MO_64:
1707 gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1708 break;
1709 #endif
1710 default:
1711 tcg_abort();
1713 } else {
1714 switch (ot) {
1715 case MO_8:
1716 gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1717 break;
1718 case MO_16:
1719 gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1720 break;
1721 case MO_32:
1722 gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1723 break;
1724 #ifdef TARGET_X86_64
1725 case MO_64:
1726 gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1727 break;
1728 #endif
1729 default:
1730 tcg_abort();
1733 /* store */
1734 gen_op_st_rm_T0_A0(s, ot, op1);
1737 /* XXX: add faster immediate case */
1738 static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
1739 bool is_right, TCGv count_in)
1741 target_ulong mask = (ot == MO_64 ? 63 : 31);
1742 TCGv count;
1744 /* load */
1745 if (op1 == OR_TMP0) {
1746 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1747 } else {
1748 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1751 count = tcg_temp_new();
1752 tcg_gen_andi_tl(count, count_in, mask);
1754 switch (ot) {
1755 case MO_16:
1756 /* Note: we implement the Intel behaviour for shift count > 16.
1757 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1758 portion by constructing it as a 32-bit value. */
1759 if (is_right) {
1760 tcg_gen_deposit_tl(cpu_tmp0, cpu_T[0], cpu_T[1], 16, 16);
1761 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1762 tcg_gen_mov_tl(cpu_T[0], cpu_tmp0);
1763 } else {
1764 tcg_gen_deposit_tl(cpu_T[1], cpu_T[0], cpu_T[1], 16, 16);
1766 /* FALLTHRU */
1767 #ifdef TARGET_X86_64
1768 case MO_32:
1769 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1770 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1771 if (is_right) {
1772 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
1773 tcg_gen_shr_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1774 tcg_gen_shr_i64(cpu_T[0], cpu_T[0], count);
1775 } else {
1776 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[1], cpu_T[0]);
1777 tcg_gen_shl_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1778 tcg_gen_shl_i64(cpu_T[0], cpu_T[0], count);
1779 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1780 tcg_gen_shri_i64(cpu_T[0], cpu_T[0], 32);
1782 break;
1783 #endif
1784 default:
1785 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1786 if (is_right) {
1787 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1789 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1790 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], count);
1791 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
1792 } else {
1793 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1794 if (ot == MO_16) {
1795 /* Only needed if count > 16, for Intel behaviour. */
1796 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1797 tcg_gen_shr_tl(cpu_tmp4, cpu_T[1], cpu_tmp4);
1798 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1801 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1802 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], count);
1803 tcg_gen_shr_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
1805 tcg_gen_movi_tl(cpu_tmp4, 0);
1806 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[1], count, cpu_tmp4,
1807 cpu_tmp4, cpu_T[1]);
1808 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1809 break;
1812 /* store */
1813 gen_op_st_rm_T0_A0(s, ot, op1);
1815 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, count, is_right);
1816 tcg_temp_free(count);
1819 static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
1821 if (s != OR_TMP1)
1822 gen_op_mov_v_reg(ot, cpu_T[1], s);
1823 switch(op) {
1824 case OP_ROL:
1825 gen_rot_rm_T1(s1, ot, d, 0);
1826 break;
1827 case OP_ROR:
1828 gen_rot_rm_T1(s1, ot, d, 1);
1829 break;
1830 case OP_SHL:
1831 case OP_SHL1:
1832 gen_shift_rm_T1(s1, ot, d, 0, 0);
1833 break;
1834 case OP_SHR:
1835 gen_shift_rm_T1(s1, ot, d, 1, 0);
1836 break;
1837 case OP_SAR:
1838 gen_shift_rm_T1(s1, ot, d, 1, 1);
1839 break;
1840 case OP_RCL:
1841 gen_rotc_rm_T1(s1, ot, d, 0);
1842 break;
1843 case OP_RCR:
1844 gen_rotc_rm_T1(s1, ot, d, 1);
1845 break;
1849 static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
1851 switch(op) {
1852 case OP_ROL:
1853 gen_rot_rm_im(s1, ot, d, c, 0);
1854 break;
1855 case OP_ROR:
1856 gen_rot_rm_im(s1, ot, d, c, 1);
1857 break;
1858 case OP_SHL:
1859 case OP_SHL1:
1860 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1861 break;
1862 case OP_SHR:
1863 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1864 break;
1865 case OP_SAR:
1866 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1867 break;
1868 default:
1869 /* currently not optimized */
1870 tcg_gen_movi_tl(cpu_T[1], c);
1871 gen_shift(s1, op, ot, d, OR_TMP1);
1872 break;
1876 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
1878 target_long disp;
1879 int havesib;
1880 int base;
1881 int index;
1882 int scale;
1883 int mod, rm, code, override, must_add_seg;
1884 TCGv sum;
1886 override = s->override;
1887 must_add_seg = s->addseg;
1888 if (override >= 0)
1889 must_add_seg = 1;
1890 mod = (modrm >> 6) & 3;
1891 rm = modrm & 7;
1893 switch (s->aflag) {
1894 case MO_64:
1895 case MO_32:
1896 havesib = 0;
1897 base = rm;
1898 index = -1;
1899 scale = 0;
1901 if (base == 4) {
1902 havesib = 1;
1903 code = cpu_ldub_code(env, s->pc++);
1904 scale = (code >> 6) & 3;
1905 index = ((code >> 3) & 7) | REX_X(s);
1906 if (index == 4) {
1907 index = -1; /* no index */
1909 base = (code & 7);
1911 base |= REX_B(s);
1913 switch (mod) {
1914 case 0:
1915 if ((base & 7) == 5) {
1916 base = -1;
1917 disp = (int32_t)cpu_ldl_code(env, s->pc);
1918 s->pc += 4;
1919 if (CODE64(s) && !havesib) {
1920 disp += s->pc + s->rip_offset;
1922 } else {
1923 disp = 0;
1925 break;
1926 case 1:
1927 disp = (int8_t)cpu_ldub_code(env, s->pc++);
1928 break;
1929 default:
1930 case 2:
1931 disp = (int32_t)cpu_ldl_code(env, s->pc);
1932 s->pc += 4;
1933 break;
1936 /* For correct popl handling with esp. */
1937 if (base == R_ESP && s->popl_esp_hack) {
1938 disp += s->popl_esp_hack;
1941 /* Compute the address, with a minimum number of TCG ops. */
1942 TCGV_UNUSED(sum);
1943 if (index >= 0) {
1944 if (scale == 0) {
1945 sum = cpu_regs[index];
1946 } else {
1947 tcg_gen_shli_tl(cpu_A0, cpu_regs[index], scale);
1948 sum = cpu_A0;
1950 if (base >= 0) {
1951 tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]);
1952 sum = cpu_A0;
1954 } else if (base >= 0) {
1955 sum = cpu_regs[base];
1957 if (TCGV_IS_UNUSED(sum)) {
1958 tcg_gen_movi_tl(cpu_A0, disp);
1959 } else {
1960 tcg_gen_addi_tl(cpu_A0, sum, disp);
1963 if (must_add_seg) {
1964 if (override < 0) {
1965 if (base == R_EBP || base == R_ESP) {
1966 override = R_SS;
1967 } else {
1968 override = R_DS;
1972 tcg_gen_ld_tl(cpu_tmp0, cpu_env,
1973 offsetof(CPUX86State, segs[override].base));
1974 if (CODE64(s)) {
1975 if (s->aflag == MO_32) {
1976 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
1978 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
1979 return;
1982 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
1985 if (s->aflag == MO_32) {
1986 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
1988 break;
1990 case MO_16:
1991 switch (mod) {
1992 case 0:
1993 if (rm == 6) {
1994 disp = cpu_lduw_code(env, s->pc);
1995 s->pc += 2;
1996 tcg_gen_movi_tl(cpu_A0, disp);
1997 rm = 0; /* avoid SS override */
1998 goto no_rm;
1999 } else {
2000 disp = 0;
2002 break;
2003 case 1:
2004 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2005 break;
2006 default:
2007 case 2:
2008 disp = (int16_t)cpu_lduw_code(env, s->pc);
2009 s->pc += 2;
2010 break;
2013 sum = cpu_A0;
2014 switch (rm) {
2015 case 0:
2016 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_ESI]);
2017 break;
2018 case 1:
2019 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_EDI]);
2020 break;
2021 case 2:
2022 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_ESI]);
2023 break;
2024 case 3:
2025 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_EDI]);
2026 break;
2027 case 4:
2028 sum = cpu_regs[R_ESI];
2029 break;
2030 case 5:
2031 sum = cpu_regs[R_EDI];
2032 break;
2033 case 6:
2034 sum = cpu_regs[R_EBP];
2035 break;
2036 default:
2037 case 7:
2038 sum = cpu_regs[R_EBX];
2039 break;
2041 tcg_gen_addi_tl(cpu_A0, sum, disp);
2042 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2043 no_rm:
2044 if (must_add_seg) {
2045 if (override < 0) {
2046 if (rm == 2 || rm == 3 || rm == 6) {
2047 override = R_SS;
2048 } else {
2049 override = R_DS;
2052 gen_op_addl_A0_seg(s, override);
2054 break;
2056 default:
2057 tcg_abort();
2061 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2063 int mod, rm, base, code;
2065 mod = (modrm >> 6) & 3;
2066 if (mod == 3)
2067 return;
2068 rm = modrm & 7;
2070 switch (s->aflag) {
2071 case MO_64:
2072 case MO_32:
2073 base = rm;
2075 if (base == 4) {
2076 code = cpu_ldub_code(env, s->pc++);
2077 base = (code & 7);
2080 switch (mod) {
2081 case 0:
2082 if (base == 5) {
2083 s->pc += 4;
2085 break;
2086 case 1:
2087 s->pc++;
2088 break;
2089 default:
2090 case 2:
2091 s->pc += 4;
2092 break;
2094 break;
2096 case MO_16:
2097 switch (mod) {
2098 case 0:
2099 if (rm == 6) {
2100 s->pc += 2;
2102 break;
2103 case 1:
2104 s->pc++;
2105 break;
2106 default:
2107 case 2:
2108 s->pc += 2;
2109 break;
2111 break;
2113 default:
2114 tcg_abort();
2118 /* used for LEA and MOV AX, mem */
2119 static void gen_add_A0_ds_seg(DisasContext *s)
2121 int override, must_add_seg;
2122 must_add_seg = s->addseg;
2123 override = R_DS;
2124 if (s->override >= 0) {
2125 override = s->override;
2126 must_add_seg = 1;
2128 if (must_add_seg) {
2129 #ifdef TARGET_X86_64
2130 if (CODE64(s)) {
2131 gen_op_addq_A0_seg(override);
2132 } else
2133 #endif
2135 gen_op_addl_A0_seg(s, override);
2140 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2141 OR_TMP0 */
2142 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2143 TCGMemOp ot, int reg, int is_store)
2145 int mod, rm;
2147 mod = (modrm >> 6) & 3;
2148 rm = (modrm & 7) | REX_B(s);
2149 if (mod == 3) {
2150 if (is_store) {
2151 if (reg != OR_TMP0)
2152 gen_op_mov_v_reg(ot, cpu_T[0], reg);
2153 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2154 } else {
2155 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2156 if (reg != OR_TMP0)
2157 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2159 } else {
2160 gen_lea_modrm(env, s, modrm);
2161 if (is_store) {
2162 if (reg != OR_TMP0)
2163 gen_op_mov_v_reg(ot, cpu_T[0], reg);
2164 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2165 } else {
2166 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2167 if (reg != OR_TMP0)
2168 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2173 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
2175 uint32_t ret;
2177 switch (ot) {
2178 case MO_8:
2179 ret = cpu_ldub_code(env, s->pc);
2180 s->pc++;
2181 break;
2182 case MO_16:
2183 ret = cpu_lduw_code(env, s->pc);
2184 s->pc += 2;
2185 break;
2186 case MO_32:
2187 #ifdef TARGET_X86_64
2188 case MO_64:
2189 #endif
2190 ret = cpu_ldl_code(env, s->pc);
2191 s->pc += 4;
2192 break;
2193 default:
2194 tcg_abort();
2196 return ret;
2199 static inline int insn_const_size(TCGMemOp ot)
2201 if (ot <= MO_32) {
2202 return 1 << ot;
2203 } else {
2204 return 4;
2208 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2210 TranslationBlock *tb;
2211 target_ulong pc;
2213 pc = s->cs_base + eip;
2214 tb = s->tb;
2215 /* NOTE: we handle the case where the TB spans two pages here */
2216 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2217 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2218 /* jump to same page: we can use a direct jump */
2219 tcg_gen_goto_tb(tb_num);
2220 gen_jmp_im(eip);
2221 tcg_gen_exit_tb((uintptr_t)tb + tb_num);
2222 } else {
2223 /* jump to another page: currently not optimized */
2224 gen_jmp_im(eip);
2225 gen_eob(s);
2229 static inline void gen_jcc(DisasContext *s, int b,
2230 target_ulong val, target_ulong next_eip)
2232 TCGLabel *l1, *l2;
2234 if (s->jmp_opt) {
2235 l1 = gen_new_label();
2236 gen_jcc1(s, b, l1);
2238 gen_goto_tb(s, 0, next_eip);
2240 gen_set_label(l1);
2241 gen_goto_tb(s, 1, val);
2242 s->is_jmp = DISAS_TB_JUMP;
2243 } else {
2244 l1 = gen_new_label();
2245 l2 = gen_new_label();
2246 gen_jcc1(s, b, l1);
2248 gen_jmp_im(next_eip);
2249 tcg_gen_br(l2);
2251 gen_set_label(l1);
2252 gen_jmp_im(val);
2253 gen_set_label(l2);
2254 gen_eob(s);
2258 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
2259 int modrm, int reg)
2261 CCPrepare cc;
2263 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2265 cc = gen_prepare_cc(s, b, cpu_T[1]);
2266 if (cc.mask != -1) {
2267 TCGv t0 = tcg_temp_new();
2268 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2269 cc.reg = t0;
2271 if (!cc.use_reg2) {
2272 cc.reg2 = tcg_const_tl(cc.imm);
2275 tcg_gen_movcond_tl(cc.cond, cpu_T[0], cc.reg, cc.reg2,
2276 cpu_T[0], cpu_regs[reg]);
2277 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2279 if (cc.mask != -1) {
2280 tcg_temp_free(cc.reg);
2282 if (!cc.use_reg2) {
2283 tcg_temp_free(cc.reg2);
2287 static inline void gen_op_movl_T0_seg(int seg_reg)
2289 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
2290 offsetof(CPUX86State,segs[seg_reg].selector));
2293 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2295 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
2296 tcg_gen_st32_tl(cpu_T[0], cpu_env,
2297 offsetof(CPUX86State,segs[seg_reg].selector));
2298 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
2299 tcg_gen_st_tl(cpu_T[0], cpu_env,
2300 offsetof(CPUX86State,segs[seg_reg].base));
2303 /* move T0 to seg_reg and compute if the CPU state may change. Never
2304 call this function with seg_reg == R_CS */
2305 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
2307 if (s->pe && !s->vm86) {
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 0x32c: /* cvttsd2si */
3500 case 0x22d: /* cvtss2si */
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_T[0], cpu_T[1],
3852 cpu_T[0], cpu_regs[R_EDX]);
3853 tcg_gen_mov_i64(cpu_regs[s->vex_v], cpu_T[0]);
3854 tcg_gen_mov_i64(cpu_regs[reg], cpu_T[1]);
3855 break;
3856 #endif
3858 break;
3860 case 0x3f5: /* pdep Gy, By, Ey */
3861 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3862 || !(s->prefix & PREFIX_VEX)
3863 || s->vex_l != 0) {
3864 goto illegal_op;
3866 ot = mo_64_32(s->dflag);
3867 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3868 /* Note that by zero-extending the mask operand, we
3869 automatically handle zero-extending the result. */
3870 if (ot == MO_64) {
3871 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3872 } else {
3873 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3875 gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3876 break;
3878 case 0x2f5: /* pext Gy, By, Ey */
3879 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3880 || !(s->prefix & PREFIX_VEX)
3881 || s->vex_l != 0) {
3882 goto illegal_op;
3884 ot = mo_64_32(s->dflag);
3885 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3886 /* Note that by zero-extending the mask operand, we
3887 automatically handle zero-extending the result. */
3888 if (ot == MO_64) {
3889 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3890 } else {
3891 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3893 gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3894 break;
3896 case 0x1f6: /* adcx Gy, Ey */
3897 case 0x2f6: /* adox Gy, Ey */
3898 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3899 goto illegal_op;
3900 } else {
3901 TCGv carry_in, carry_out, zero;
3902 int end_op;
3904 ot = mo_64_32(s->dflag);
3905 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3907 /* Re-use the carry-out from a previous round. */
3908 TCGV_UNUSED(carry_in);
3909 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3910 switch (s->cc_op) {
3911 case CC_OP_ADCX:
3912 if (b == 0x1f6) {
3913 carry_in = cpu_cc_dst;
3914 end_op = CC_OP_ADCX;
3915 } else {
3916 end_op = CC_OP_ADCOX;
3918 break;
3919 case CC_OP_ADOX:
3920 if (b == 0x1f6) {
3921 end_op = CC_OP_ADCOX;
3922 } else {
3923 carry_in = cpu_cc_src2;
3924 end_op = CC_OP_ADOX;
3926 break;
3927 case CC_OP_ADCOX:
3928 end_op = CC_OP_ADCOX;
3929 carry_in = carry_out;
3930 break;
3931 default:
3932 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
3933 break;
3935 /* If we can't reuse carry-out, get it out of EFLAGS. */
3936 if (TCGV_IS_UNUSED(carry_in)) {
3937 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3938 gen_compute_eflags(s);
3940 carry_in = cpu_tmp0;
3941 tcg_gen_shri_tl(carry_in, cpu_cc_src,
3942 ctz32(b == 0x1f6 ? CC_C : CC_O));
3943 tcg_gen_andi_tl(carry_in, carry_in, 1);
3946 switch (ot) {
3947 #ifdef TARGET_X86_64
3948 case MO_32:
3949 /* If we know TL is 64-bit, and we want a 32-bit
3950 result, just do everything in 64-bit arithmetic. */
3951 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3952 tcg_gen_ext32u_i64(cpu_T[0], cpu_T[0]);
3953 tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_regs[reg]);
3954 tcg_gen_add_i64(cpu_T[0], cpu_T[0], carry_in);
3955 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T[0]);
3956 tcg_gen_shri_i64(carry_out, cpu_T[0], 32);
3957 break;
3958 #endif
3959 default:
3960 /* Otherwise compute the carry-out in two steps. */
3961 zero = tcg_const_tl(0);
3962 tcg_gen_add2_tl(cpu_T[0], carry_out,
3963 cpu_T[0], zero,
3964 carry_in, zero);
3965 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3966 cpu_regs[reg], carry_out,
3967 cpu_T[0], zero);
3968 tcg_temp_free(zero);
3969 break;
3971 set_cc_op(s, end_op);
3973 break;
3975 case 0x1f7: /* shlx Gy, Ey, By */
3976 case 0x2f7: /* sarx Gy, Ey, By */
3977 case 0x3f7: /* shrx Gy, Ey, By */
3978 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3979 || !(s->prefix & PREFIX_VEX)
3980 || s->vex_l != 0) {
3981 goto illegal_op;
3983 ot = mo_64_32(s->dflag);
3984 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3985 if (ot == MO_64) {
3986 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
3987 } else {
3988 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
3990 if (b == 0x1f7) {
3991 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3992 } else if (b == 0x2f7) {
3993 if (ot != MO_64) {
3994 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
3996 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3997 } else {
3998 if (ot != MO_64) {
3999 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
4001 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4003 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4004 break;
4006 case 0x0f3:
4007 case 0x1f3:
4008 case 0x2f3:
4009 case 0x3f3: /* Group 17 */
4010 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4011 || !(s->prefix & PREFIX_VEX)
4012 || s->vex_l != 0) {
4013 goto illegal_op;
4015 ot = mo_64_32(s->dflag);
4016 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4018 switch (reg & 7) {
4019 case 1: /* blsr By,Ey */
4020 tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
4021 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4022 gen_op_mov_reg_v(ot, s->vex_v, cpu_T[0]);
4023 gen_op_update2_cc();
4024 set_cc_op(s, CC_OP_BMILGB + ot);
4025 break;
4027 case 2: /* blsmsk By,Ey */
4028 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4029 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4030 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4031 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4032 set_cc_op(s, CC_OP_BMILGB + ot);
4033 break;
4035 case 3: /* blsi By, Ey */
4036 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4037 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4038 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4039 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4040 set_cc_op(s, CC_OP_BMILGB + ot);
4041 break;
4043 default:
4044 goto illegal_op;
4046 break;
4048 default:
4049 goto illegal_op;
4051 break;
4053 case 0x03a:
4054 case 0x13a:
4055 b = modrm;
4056 modrm = cpu_ldub_code(env, s->pc++);
4057 rm = modrm & 7;
4058 reg = ((modrm >> 3) & 7) | rex_r;
4059 mod = (modrm >> 6) & 3;
4060 if (b1 >= 2) {
4061 goto illegal_op;
4064 sse_fn_eppi = sse_op_table7[b].op[b1];
4065 if (!sse_fn_eppi) {
4066 goto illegal_op;
4068 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4069 goto illegal_op;
4071 if (sse_fn_eppi == SSE_SPECIAL) {
4072 ot = mo_64_32(s->dflag);
4073 rm = (modrm & 7) | REX_B(s);
4074 if (mod != 3)
4075 gen_lea_modrm(env, s, modrm);
4076 reg = ((modrm >> 3) & 7) | rex_r;
4077 val = cpu_ldub_code(env, s->pc++);
4078 switch (b) {
4079 case 0x14: /* pextrb */
4080 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4081 xmm_regs[reg].XMM_B(val & 15)));
4082 if (mod == 3) {
4083 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4084 } else {
4085 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4086 s->mem_index, MO_UB);
4088 break;
4089 case 0x15: /* pextrw */
4090 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4091 xmm_regs[reg].XMM_W(val & 7)));
4092 if (mod == 3) {
4093 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4094 } else {
4095 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4096 s->mem_index, MO_LEUW);
4098 break;
4099 case 0x16:
4100 if (ot == MO_32) { /* pextrd */
4101 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4102 offsetof(CPUX86State,
4103 xmm_regs[reg].XMM_L(val & 3)));
4104 if (mod == 3) {
4105 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
4106 } else {
4107 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4108 s->mem_index, MO_LEUL);
4110 } else { /* pextrq */
4111 #ifdef TARGET_X86_64
4112 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4113 offsetof(CPUX86State,
4114 xmm_regs[reg].XMM_Q(val & 1)));
4115 if (mod == 3) {
4116 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
4117 } else {
4118 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4119 s->mem_index, MO_LEQ);
4121 #else
4122 goto illegal_op;
4123 #endif
4125 break;
4126 case 0x17: /* extractps */
4127 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4128 xmm_regs[reg].XMM_L(val & 3)));
4129 if (mod == 3) {
4130 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4131 } else {
4132 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4133 s->mem_index, MO_LEUL);
4135 break;
4136 case 0x20: /* pinsrb */
4137 if (mod == 3) {
4138 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
4139 } else {
4140 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
4141 s->mem_index, MO_UB);
4143 tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4144 xmm_regs[reg].XMM_B(val & 15)));
4145 break;
4146 case 0x21: /* insertps */
4147 if (mod == 3) {
4148 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4149 offsetof(CPUX86State,xmm_regs[rm]
4150 .XMM_L((val >> 6) & 3)));
4151 } else {
4152 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4153 s->mem_index, MO_LEUL);
4155 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4156 offsetof(CPUX86State,xmm_regs[reg]
4157 .XMM_L((val >> 4) & 3)));
4158 if ((val >> 0) & 1)
4159 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4160 cpu_env, offsetof(CPUX86State,
4161 xmm_regs[reg].XMM_L(0)));
4162 if ((val >> 1) & 1)
4163 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4164 cpu_env, offsetof(CPUX86State,
4165 xmm_regs[reg].XMM_L(1)));
4166 if ((val >> 2) & 1)
4167 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4168 cpu_env, offsetof(CPUX86State,
4169 xmm_regs[reg].XMM_L(2)));
4170 if ((val >> 3) & 1)
4171 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4172 cpu_env, offsetof(CPUX86State,
4173 xmm_regs[reg].XMM_L(3)));
4174 break;
4175 case 0x22:
4176 if (ot == MO_32) { /* pinsrd */
4177 if (mod == 3) {
4178 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
4179 } else {
4180 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4181 s->mem_index, MO_LEUL);
4183 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4184 offsetof(CPUX86State,
4185 xmm_regs[reg].XMM_L(val & 3)));
4186 } else { /* pinsrq */
4187 #ifdef TARGET_X86_64
4188 if (mod == 3) {
4189 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4190 } else {
4191 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4192 s->mem_index, MO_LEQ);
4194 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4195 offsetof(CPUX86State,
4196 xmm_regs[reg].XMM_Q(val & 1)));
4197 #else
4198 goto illegal_op;
4199 #endif
4201 break;
4203 return;
4206 if (b1) {
4207 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4208 if (mod == 3) {
4209 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4210 } else {
4211 op2_offset = offsetof(CPUX86State,xmm_t0);
4212 gen_lea_modrm(env, s, modrm);
4213 gen_ldo_env_A0(s, op2_offset);
4215 } else {
4216 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4217 if (mod == 3) {
4218 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4219 } else {
4220 op2_offset = offsetof(CPUX86State,mmx_t0);
4221 gen_lea_modrm(env, s, modrm);
4222 gen_ldq_env_A0(s, op2_offset);
4225 val = cpu_ldub_code(env, s->pc++);
4227 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4228 set_cc_op(s, CC_OP_EFLAGS);
4230 if (s->dflag == MO_64) {
4231 /* The helper must use entire 64-bit gp registers */
4232 val |= 1 << 8;
4236 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4237 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4238 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4239 break;
4241 case 0x33a:
4242 /* Various integer extensions at 0f 3a f[0-f]. */
4243 b = modrm | (b1 << 8);
4244 modrm = cpu_ldub_code(env, s->pc++);
4245 reg = ((modrm >> 3) & 7) | rex_r;
4247 switch (b) {
4248 case 0x3f0: /* rorx Gy,Ey, Ib */
4249 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4250 || !(s->prefix & PREFIX_VEX)
4251 || s->vex_l != 0) {
4252 goto illegal_op;
4254 ot = mo_64_32(s->dflag);
4255 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4256 b = cpu_ldub_code(env, s->pc++);
4257 if (ot == MO_64) {
4258 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
4259 } else {
4260 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4261 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4262 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4264 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4265 break;
4267 default:
4268 goto illegal_op;
4270 break;
4272 default:
4273 goto illegal_op;
4275 } else {
4276 /* generic MMX or SSE operation */
4277 switch(b) {
4278 case 0x70: /* pshufx insn */
4279 case 0xc6: /* pshufx insn */
4280 case 0xc2: /* compare insns */
4281 s->rip_offset = 1;
4282 break;
4283 default:
4284 break;
4286 if (is_xmm) {
4287 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4288 if (mod != 3) {
4289 int sz = 4;
4291 gen_lea_modrm(env, s, modrm);
4292 op2_offset = offsetof(CPUX86State,xmm_t0);
4294 switch (b) {
4295 case 0x50 ... 0x5a:
4296 case 0x5c ... 0x5f:
4297 case 0xc2:
4298 /* Most sse scalar operations. */
4299 if (b1 == 2) {
4300 sz = 2;
4301 } else if (b1 == 3) {
4302 sz = 3;
4304 break;
4306 case 0x2e: /* ucomis[sd] */
4307 case 0x2f: /* comis[sd] */
4308 if (b1 == 0) {
4309 sz = 2;
4310 } else {
4311 sz = 3;
4313 break;
4316 switch (sz) {
4317 case 2:
4318 /* 32 bit access */
4319 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
4320 tcg_gen_st32_tl(cpu_T[0], cpu_env,
4321 offsetof(CPUX86State,xmm_t0.XMM_L(0)));
4322 break;
4323 case 3:
4324 /* 64 bit access */
4325 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_D(0)));
4326 break;
4327 default:
4328 /* 128 bit access */
4329 gen_ldo_env_A0(s, op2_offset);
4330 break;
4332 } else {
4333 rm = (modrm & 7) | REX_B(s);
4334 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4336 } else {
4337 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4338 if (mod != 3) {
4339 gen_lea_modrm(env, s, modrm);
4340 op2_offset = offsetof(CPUX86State,mmx_t0);
4341 gen_ldq_env_A0(s, op2_offset);
4342 } else {
4343 rm = (modrm & 7);
4344 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4347 switch(b) {
4348 case 0x0f: /* 3DNow! data insns */
4349 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4350 goto illegal_op;
4351 val = cpu_ldub_code(env, s->pc++);
4352 sse_fn_epp = sse_op_table5[val];
4353 if (!sse_fn_epp) {
4354 goto illegal_op;
4356 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4357 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4358 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4359 break;
4360 case 0x70: /* pshufx insn */
4361 case 0xc6: /* pshufx insn */
4362 val = cpu_ldub_code(env, s->pc++);
4363 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4364 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4365 /* XXX: introduce a new table? */
4366 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4367 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4368 break;
4369 case 0xc2:
4370 /* compare insns */
4371 val = cpu_ldub_code(env, s->pc++);
4372 if (val >= 8)
4373 goto illegal_op;
4374 sse_fn_epp = sse_op_table4[val][b1];
4376 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4377 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4378 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4379 break;
4380 case 0xf7:
4381 /* maskmov : we must prepare A0 */
4382 if (mod != 3)
4383 goto illegal_op;
4384 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4385 gen_extu(s->aflag, cpu_A0);
4386 gen_add_A0_ds_seg(s);
4388 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4389 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4390 /* XXX: introduce a new table? */
4391 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4392 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4393 break;
4394 default:
4395 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4396 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4397 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4398 break;
4400 if (b == 0x2e || b == 0x2f) {
4401 set_cc_op(s, CC_OP_EFLAGS);
4406 /* convert one instruction. s->is_jmp is set if the translation must
4407 be stopped. Return the next pc value */
4408 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4409 target_ulong pc_start)
4411 int b, prefixes;
4412 int shift;
4413 TCGMemOp ot, aflag, dflag;
4414 int modrm, reg, rm, mod, op, opreg, val;
4415 target_ulong next_eip, tval;
4416 int rex_w, rex_r;
4418 s->pc = pc_start;
4419 prefixes = 0;
4420 s->override = -1;
4421 rex_w = -1;
4422 rex_r = 0;
4423 #ifdef TARGET_X86_64
4424 s->rex_x = 0;
4425 s->rex_b = 0;
4426 x86_64_hregs = 0;
4427 #endif
4428 s->rip_offset = 0; /* for relative ip address */
4429 s->vex_l = 0;
4430 s->vex_v = 0;
4431 next_byte:
4432 b = cpu_ldub_code(env, s->pc);
4433 s->pc++;
4434 /* Collect prefixes. */
4435 switch (b) {
4436 case 0xf3:
4437 prefixes |= PREFIX_REPZ;
4438 goto next_byte;
4439 case 0xf2:
4440 prefixes |= PREFIX_REPNZ;
4441 goto next_byte;
4442 case 0xf0:
4443 prefixes |= PREFIX_LOCK;
4444 goto next_byte;
4445 case 0x2e:
4446 s->override = R_CS;
4447 goto next_byte;
4448 case 0x36:
4449 s->override = R_SS;
4450 goto next_byte;
4451 case 0x3e:
4452 s->override = R_DS;
4453 goto next_byte;
4454 case 0x26:
4455 s->override = R_ES;
4456 goto next_byte;
4457 case 0x64:
4458 s->override = R_FS;
4459 goto next_byte;
4460 case 0x65:
4461 s->override = R_GS;
4462 goto next_byte;
4463 case 0x66:
4464 prefixes |= PREFIX_DATA;
4465 goto next_byte;
4466 case 0x67:
4467 prefixes |= PREFIX_ADR;
4468 goto next_byte;
4469 #ifdef TARGET_X86_64
4470 case 0x40 ... 0x4f:
4471 if (CODE64(s)) {
4472 /* REX prefix */
4473 rex_w = (b >> 3) & 1;
4474 rex_r = (b & 0x4) << 1;
4475 s->rex_x = (b & 0x2) << 2;
4476 REX_B(s) = (b & 0x1) << 3;
4477 x86_64_hregs = 1; /* select uniform byte register addressing */
4478 goto next_byte;
4480 break;
4481 #endif
4482 case 0xc5: /* 2-byte VEX */
4483 case 0xc4: /* 3-byte VEX */
4484 /* VEX prefixes cannot be used except in 32-bit mode.
4485 Otherwise the instruction is LES or LDS. */
4486 if (s->code32 && !s->vm86) {
4487 static const int pp_prefix[4] = {
4488 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4490 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4492 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4493 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4494 otherwise the instruction is LES or LDS. */
4495 break;
4497 s->pc++;
4499 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4500 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4501 | PREFIX_LOCK | PREFIX_DATA)) {
4502 goto illegal_op;
4504 #ifdef TARGET_X86_64
4505 if (x86_64_hregs) {
4506 goto illegal_op;
4508 #endif
4509 rex_r = (~vex2 >> 4) & 8;
4510 if (b == 0xc5) {
4511 vex3 = vex2;
4512 b = cpu_ldub_code(env, s->pc++);
4513 } else {
4514 #ifdef TARGET_X86_64
4515 s->rex_x = (~vex2 >> 3) & 8;
4516 s->rex_b = (~vex2 >> 2) & 8;
4517 #endif
4518 vex3 = cpu_ldub_code(env, s->pc++);
4519 rex_w = (vex3 >> 7) & 1;
4520 switch (vex2 & 0x1f) {
4521 case 0x01: /* Implied 0f leading opcode bytes. */
4522 b = cpu_ldub_code(env, s->pc++) | 0x100;
4523 break;
4524 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4525 b = 0x138;
4526 break;
4527 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4528 b = 0x13a;
4529 break;
4530 default: /* Reserved for future use. */
4531 goto illegal_op;
4534 s->vex_v = (~vex3 >> 3) & 0xf;
4535 s->vex_l = (vex3 >> 2) & 1;
4536 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4538 break;
4541 /* Post-process prefixes. */
4542 if (CODE64(s)) {
4543 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4544 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4545 over 0x66 if both are present. */
4546 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4547 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4548 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4549 } else {
4550 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4551 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4552 dflag = MO_32;
4553 } else {
4554 dflag = MO_16;
4556 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4557 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4558 aflag = MO_32;
4559 } else {
4560 aflag = MO_16;
4564 s->prefix = prefixes;
4565 s->aflag = aflag;
4566 s->dflag = dflag;
4568 /* lock generation */
4569 if (prefixes & PREFIX_LOCK)
4570 gen_helper_lock();
4572 /* now check op code */
4573 reswitch:
4574 switch(b) {
4575 case 0x0f:
4576 /**************************/
4577 /* extended op code */
4578 b = cpu_ldub_code(env, s->pc++) | 0x100;
4579 goto reswitch;
4581 /**************************/
4582 /* arith & logic */
4583 case 0x00 ... 0x05:
4584 case 0x08 ... 0x0d:
4585 case 0x10 ... 0x15:
4586 case 0x18 ... 0x1d:
4587 case 0x20 ... 0x25:
4588 case 0x28 ... 0x2d:
4589 case 0x30 ... 0x35:
4590 case 0x38 ... 0x3d:
4592 int op, f, val;
4593 op = (b >> 3) & 7;
4594 f = (b >> 1) & 3;
4596 ot = mo_b_d(b, dflag);
4598 switch(f) {
4599 case 0: /* OP Ev, Gv */
4600 modrm = cpu_ldub_code(env, s->pc++);
4601 reg = ((modrm >> 3) & 7) | rex_r;
4602 mod = (modrm >> 6) & 3;
4603 rm = (modrm & 7) | REX_B(s);
4604 if (mod != 3) {
4605 gen_lea_modrm(env, s, modrm);
4606 opreg = OR_TMP0;
4607 } else if (op == OP_XORL && rm == reg) {
4608 xor_zero:
4609 /* xor reg, reg optimisation */
4610 set_cc_op(s, CC_OP_CLR);
4611 tcg_gen_movi_tl(cpu_T[0], 0);
4612 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4613 break;
4614 } else {
4615 opreg = rm;
4617 gen_op_mov_v_reg(ot, cpu_T[1], reg);
4618 gen_op(s, op, ot, opreg);
4619 break;
4620 case 1: /* OP Gv, Ev */
4621 modrm = cpu_ldub_code(env, s->pc++);
4622 mod = (modrm >> 6) & 3;
4623 reg = ((modrm >> 3) & 7) | rex_r;
4624 rm = (modrm & 7) | REX_B(s);
4625 if (mod != 3) {
4626 gen_lea_modrm(env, s, modrm);
4627 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4628 } else if (op == OP_XORL && rm == reg) {
4629 goto xor_zero;
4630 } else {
4631 gen_op_mov_v_reg(ot, cpu_T[1], rm);
4633 gen_op(s, op, ot, reg);
4634 break;
4635 case 2: /* OP A, Iv */
4636 val = insn_get(env, s, ot);
4637 tcg_gen_movi_tl(cpu_T[1], val);
4638 gen_op(s, op, ot, OR_EAX);
4639 break;
4642 break;
4644 case 0x82:
4645 if (CODE64(s))
4646 goto illegal_op;
4647 case 0x80: /* GRP1 */
4648 case 0x81:
4649 case 0x83:
4651 int val;
4653 ot = mo_b_d(b, dflag);
4655 modrm = cpu_ldub_code(env, s->pc++);
4656 mod = (modrm >> 6) & 3;
4657 rm = (modrm & 7) | REX_B(s);
4658 op = (modrm >> 3) & 7;
4660 if (mod != 3) {
4661 if (b == 0x83)
4662 s->rip_offset = 1;
4663 else
4664 s->rip_offset = insn_const_size(ot);
4665 gen_lea_modrm(env, s, modrm);
4666 opreg = OR_TMP0;
4667 } else {
4668 opreg = rm;
4671 switch(b) {
4672 default:
4673 case 0x80:
4674 case 0x81:
4675 case 0x82:
4676 val = insn_get(env, s, ot);
4677 break;
4678 case 0x83:
4679 val = (int8_t)insn_get(env, s, MO_8);
4680 break;
4682 tcg_gen_movi_tl(cpu_T[1], val);
4683 gen_op(s, op, ot, opreg);
4685 break;
4687 /**************************/
4688 /* inc, dec, and other misc arith */
4689 case 0x40 ... 0x47: /* inc Gv */
4690 ot = dflag;
4691 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4692 break;
4693 case 0x48 ... 0x4f: /* dec Gv */
4694 ot = dflag;
4695 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4696 break;
4697 case 0xf6: /* GRP3 */
4698 case 0xf7:
4699 ot = mo_b_d(b, dflag);
4701 modrm = cpu_ldub_code(env, s->pc++);
4702 mod = (modrm >> 6) & 3;
4703 rm = (modrm & 7) | REX_B(s);
4704 op = (modrm >> 3) & 7;
4705 if (mod != 3) {
4706 if (op == 0)
4707 s->rip_offset = insn_const_size(ot);
4708 gen_lea_modrm(env, s, modrm);
4709 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
4710 } else {
4711 gen_op_mov_v_reg(ot, cpu_T[0], rm);
4714 switch(op) {
4715 case 0: /* test */
4716 val = insn_get(env, s, ot);
4717 tcg_gen_movi_tl(cpu_T[1], val);
4718 gen_op_testl_T0_T1_cc();
4719 set_cc_op(s, CC_OP_LOGICB + ot);
4720 break;
4721 case 2: /* not */
4722 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
4723 if (mod != 3) {
4724 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
4725 } else {
4726 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4728 break;
4729 case 3: /* neg */
4730 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
4731 if (mod != 3) {
4732 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
4733 } else {
4734 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4736 gen_op_update_neg_cc();
4737 set_cc_op(s, CC_OP_SUBB + ot);
4738 break;
4739 case 4: /* mul */
4740 switch(ot) {
4741 case MO_8:
4742 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
4743 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4744 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4745 /* XXX: use 32 bit mul which could be faster */
4746 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4747 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4748 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4749 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
4750 set_cc_op(s, CC_OP_MULB);
4751 break;
4752 case MO_16:
4753 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
4754 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4755 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4756 /* XXX: use 32 bit mul which could be faster */
4757 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4758 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4759 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4760 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4761 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
4762 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4763 set_cc_op(s, CC_OP_MULW);
4764 break;
4765 default:
4766 case MO_32:
4767 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4768 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4769 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4770 cpu_tmp2_i32, cpu_tmp3_i32);
4771 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4772 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4773 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4774 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4775 set_cc_op(s, CC_OP_MULL);
4776 break;
4777 #ifdef TARGET_X86_64
4778 case MO_64:
4779 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4780 cpu_T[0], cpu_regs[R_EAX]);
4781 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4782 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4783 set_cc_op(s, CC_OP_MULQ);
4784 break;
4785 #endif
4787 break;
4788 case 5: /* imul */
4789 switch(ot) {
4790 case MO_8:
4791 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
4792 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4793 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
4794 /* XXX: use 32 bit mul which could be faster */
4795 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4796 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4797 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4798 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
4799 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4800 set_cc_op(s, CC_OP_MULB);
4801 break;
4802 case MO_16:
4803 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
4804 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4805 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4806 /* XXX: use 32 bit mul which could be faster */
4807 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4808 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4809 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4810 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4811 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4812 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4813 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
4814 set_cc_op(s, CC_OP_MULW);
4815 break;
4816 default:
4817 case MO_32:
4818 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4819 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4820 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4821 cpu_tmp2_i32, cpu_tmp3_i32);
4822 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4823 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4824 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4825 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4826 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4827 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4828 set_cc_op(s, CC_OP_MULL);
4829 break;
4830 #ifdef TARGET_X86_64
4831 case MO_64:
4832 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4833 cpu_T[0], cpu_regs[R_EAX]);
4834 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4835 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4836 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4837 set_cc_op(s, CC_OP_MULQ);
4838 break;
4839 #endif
4841 break;
4842 case 6: /* div */
4843 switch(ot) {
4844 case MO_8:
4845 gen_helper_divb_AL(cpu_env, cpu_T[0]);
4846 break;
4847 case MO_16:
4848 gen_helper_divw_AX(cpu_env, cpu_T[0]);
4849 break;
4850 default:
4851 case MO_32:
4852 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
4853 break;
4854 #ifdef TARGET_X86_64
4855 case MO_64:
4856 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
4857 break;
4858 #endif
4860 break;
4861 case 7: /* idiv */
4862 switch(ot) {
4863 case MO_8:
4864 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
4865 break;
4866 case MO_16:
4867 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
4868 break;
4869 default:
4870 case MO_32:
4871 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
4872 break;
4873 #ifdef TARGET_X86_64
4874 case MO_64:
4875 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
4876 break;
4877 #endif
4879 break;
4880 default:
4881 goto illegal_op;
4883 break;
4885 case 0xfe: /* GRP4 */
4886 case 0xff: /* GRP5 */
4887 ot = mo_b_d(b, dflag);
4889 modrm = cpu_ldub_code(env, s->pc++);
4890 mod = (modrm >> 6) & 3;
4891 rm = (modrm & 7) | REX_B(s);
4892 op = (modrm >> 3) & 7;
4893 if (op >= 2 && b == 0xfe) {
4894 goto illegal_op;
4896 if (CODE64(s)) {
4897 if (op == 2 || op == 4) {
4898 /* operand size for jumps is 64 bit */
4899 ot = MO_64;
4900 } else if (op == 3 || op == 5) {
4901 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
4902 } else if (op == 6) {
4903 /* default push size is 64 bit */
4904 ot = mo_pushpop(s, dflag);
4907 if (mod != 3) {
4908 gen_lea_modrm(env, s, modrm);
4909 if (op >= 2 && op != 3 && op != 5)
4910 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
4911 } else {
4912 gen_op_mov_v_reg(ot, cpu_T[0], rm);
4915 switch(op) {
4916 case 0: /* inc Ev */
4917 if (mod != 3)
4918 opreg = OR_TMP0;
4919 else
4920 opreg = rm;
4921 gen_inc(s, ot, opreg, 1);
4922 break;
4923 case 1: /* dec Ev */
4924 if (mod != 3)
4925 opreg = OR_TMP0;
4926 else
4927 opreg = rm;
4928 gen_inc(s, ot, opreg, -1);
4929 break;
4930 case 2: /* call Ev */
4931 /* XXX: optimize if memory (no 'and' is necessary) */
4932 if (dflag == MO_16) {
4933 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4935 next_eip = s->pc - s->cs_base;
4936 tcg_gen_movi_tl(cpu_T[1], next_eip);
4937 gen_push_v(s, cpu_T[1]);
4938 gen_op_jmp_v(cpu_T[0]);
4939 gen_eob(s);
4940 break;
4941 case 3: /* lcall Ev */
4942 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4943 gen_add_A0_im(s, 1 << ot);
4944 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
4945 do_lcall:
4946 if (s->pe && !s->vm86) {
4947 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4948 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4949 tcg_const_i32(dflag - 1),
4950 tcg_const_tl(s->pc - s->cs_base));
4951 } else {
4952 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4953 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
4954 tcg_const_i32(dflag - 1),
4955 tcg_const_i32(s->pc - s->cs_base));
4957 gen_eob(s);
4958 break;
4959 case 4: /* jmp Ev */
4960 if (dflag == MO_16) {
4961 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4963 gen_op_jmp_v(cpu_T[0]);
4964 gen_eob(s);
4965 break;
4966 case 5: /* ljmp Ev */
4967 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4968 gen_add_A0_im(s, 1 << ot);
4969 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
4970 do_ljmp:
4971 if (s->pe && !s->vm86) {
4972 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4973 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4974 tcg_const_tl(s->pc - s->cs_base));
4975 } else {
4976 gen_op_movl_seg_T0_vm(R_CS);
4977 gen_op_jmp_v(cpu_T[1]);
4979 gen_eob(s);
4980 break;
4981 case 6: /* push Ev */
4982 gen_push_v(s, cpu_T[0]);
4983 break;
4984 default:
4985 goto illegal_op;
4987 break;
4989 case 0x84: /* test Ev, Gv */
4990 case 0x85:
4991 ot = mo_b_d(b, dflag);
4993 modrm = cpu_ldub_code(env, s->pc++);
4994 reg = ((modrm >> 3) & 7) | rex_r;
4996 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4997 gen_op_mov_v_reg(ot, cpu_T[1], reg);
4998 gen_op_testl_T0_T1_cc();
4999 set_cc_op(s, CC_OP_LOGICB + ot);
5000 break;
5002 case 0xa8: /* test eAX, Iv */
5003 case 0xa9:
5004 ot = mo_b_d(b, dflag);
5005 val = insn_get(env, s, ot);
5007 gen_op_mov_v_reg(ot, cpu_T[0], OR_EAX);
5008 tcg_gen_movi_tl(cpu_T[1], val);
5009 gen_op_testl_T0_T1_cc();
5010 set_cc_op(s, CC_OP_LOGICB + ot);
5011 break;
5013 case 0x98: /* CWDE/CBW */
5014 switch (dflag) {
5015 #ifdef TARGET_X86_64
5016 case MO_64:
5017 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
5018 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5019 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T[0]);
5020 break;
5021 #endif
5022 case MO_32:
5023 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
5024 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5025 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T[0]);
5026 break;
5027 case MO_16:
5028 gen_op_mov_v_reg(MO_8, cpu_T[0], R_EAX);
5029 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5030 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
5031 break;
5032 default:
5033 tcg_abort();
5035 break;
5036 case 0x99: /* CDQ/CWD */
5037 switch (dflag) {
5038 #ifdef TARGET_X86_64
5039 case MO_64:
5040 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EAX);
5041 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
5042 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T[0]);
5043 break;
5044 #endif
5045 case MO_32:
5046 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
5047 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5048 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
5049 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T[0]);
5050 break;
5051 case MO_16:
5052 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
5053 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5054 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
5055 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
5056 break;
5057 default:
5058 tcg_abort();
5060 break;
5061 case 0x1af: /* imul Gv, Ev */
5062 case 0x69: /* imul Gv, Ev, I */
5063 case 0x6b:
5064 ot = dflag;
5065 modrm = cpu_ldub_code(env, s->pc++);
5066 reg = ((modrm >> 3) & 7) | rex_r;
5067 if (b == 0x69)
5068 s->rip_offset = insn_const_size(ot);
5069 else if (b == 0x6b)
5070 s->rip_offset = 1;
5071 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5072 if (b == 0x69) {
5073 val = insn_get(env, s, ot);
5074 tcg_gen_movi_tl(cpu_T[1], val);
5075 } else if (b == 0x6b) {
5076 val = (int8_t)insn_get(env, s, MO_8);
5077 tcg_gen_movi_tl(cpu_T[1], val);
5078 } else {
5079 gen_op_mov_v_reg(ot, cpu_T[1], reg);
5081 switch (ot) {
5082 #ifdef TARGET_X86_64
5083 case MO_64:
5084 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
5085 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5086 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5087 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
5088 break;
5089 #endif
5090 case MO_32:
5091 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5092 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5093 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5094 cpu_tmp2_i32, cpu_tmp3_i32);
5095 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5096 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5097 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5098 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5099 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5100 break;
5101 default:
5102 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5103 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5104 /* XXX: use 32 bit mul which could be faster */
5105 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5106 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5107 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5108 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5109 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5110 break;
5112 set_cc_op(s, CC_OP_MULB + ot);
5113 break;
5114 case 0x1c0:
5115 case 0x1c1: /* xadd Ev, Gv */
5116 ot = mo_b_d(b, dflag);
5117 modrm = cpu_ldub_code(env, s->pc++);
5118 reg = ((modrm >> 3) & 7) | rex_r;
5119 mod = (modrm >> 6) & 3;
5120 if (mod == 3) {
5121 rm = (modrm & 7) | REX_B(s);
5122 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5123 gen_op_mov_v_reg(ot, cpu_T[1], rm);
5124 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5125 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5126 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5127 } else {
5128 gen_lea_modrm(env, s, modrm);
5129 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5130 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5131 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5132 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5133 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5135 gen_op_update2_cc();
5136 set_cc_op(s, CC_OP_ADDB + ot);
5137 break;
5138 case 0x1b0:
5139 case 0x1b1: /* cmpxchg Ev, Gv */
5141 TCGLabel *label1, *label2;
5142 TCGv t0, t1, t2, a0;
5144 ot = mo_b_d(b, dflag);
5145 modrm = cpu_ldub_code(env, s->pc++);
5146 reg = ((modrm >> 3) & 7) | rex_r;
5147 mod = (modrm >> 6) & 3;
5148 t0 = tcg_temp_local_new();
5149 t1 = tcg_temp_local_new();
5150 t2 = tcg_temp_local_new();
5151 a0 = tcg_temp_local_new();
5152 gen_op_mov_v_reg(ot, t1, reg);
5153 if (mod == 3) {
5154 rm = (modrm & 7) | REX_B(s);
5155 gen_op_mov_v_reg(ot, t0, rm);
5156 } else {
5157 gen_lea_modrm(env, s, modrm);
5158 tcg_gen_mov_tl(a0, cpu_A0);
5159 gen_op_ld_v(s, ot, t0, a0);
5160 rm = 0; /* avoid warning */
5162 label1 = gen_new_label();
5163 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5164 gen_extu(ot, t0);
5165 gen_extu(ot, t2);
5166 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
5167 label2 = gen_new_label();
5168 if (mod == 3) {
5169 gen_op_mov_reg_v(ot, R_EAX, t0);
5170 tcg_gen_br(label2);
5171 gen_set_label(label1);
5172 gen_op_mov_reg_v(ot, rm, t1);
5173 } else {
5174 /* perform no-op store cycle like physical cpu; must be
5175 before changing accumulator to ensure idempotency if
5176 the store faults and the instruction is restarted */
5177 gen_op_st_v(s, ot, t0, a0);
5178 gen_op_mov_reg_v(ot, R_EAX, t0);
5179 tcg_gen_br(label2);
5180 gen_set_label(label1);
5181 gen_op_st_v(s, ot, t1, a0);
5183 gen_set_label(label2);
5184 tcg_gen_mov_tl(cpu_cc_src, t0);
5185 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5186 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
5187 set_cc_op(s, CC_OP_SUBB + ot);
5188 tcg_temp_free(t0);
5189 tcg_temp_free(t1);
5190 tcg_temp_free(t2);
5191 tcg_temp_free(a0);
5193 break;
5194 case 0x1c7: /* cmpxchg8b */
5195 modrm = cpu_ldub_code(env, s->pc++);
5196 mod = (modrm >> 6) & 3;
5197 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5198 goto illegal_op;
5199 #ifdef TARGET_X86_64
5200 if (dflag == MO_64) {
5201 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5202 goto illegal_op;
5203 gen_lea_modrm(env, s, modrm);
5204 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5205 } else
5206 #endif
5208 if (!(s->cpuid_features & CPUID_CX8))
5209 goto illegal_op;
5210 gen_lea_modrm(env, s, modrm);
5211 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5213 set_cc_op(s, CC_OP_EFLAGS);
5214 break;
5216 /**************************/
5217 /* push/pop */
5218 case 0x50 ... 0x57: /* push */
5219 gen_op_mov_v_reg(MO_32, cpu_T[0], (b & 7) | REX_B(s));
5220 gen_push_v(s, cpu_T[0]);
5221 break;
5222 case 0x58 ... 0x5f: /* pop */
5223 ot = gen_pop_T0(s);
5224 /* NOTE: order is important for pop %sp */
5225 gen_pop_update(s, ot);
5226 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T[0]);
5227 break;
5228 case 0x60: /* pusha */
5229 if (CODE64(s))
5230 goto illegal_op;
5231 gen_pusha(s);
5232 break;
5233 case 0x61: /* popa */
5234 if (CODE64(s))
5235 goto illegal_op;
5236 gen_popa(s);
5237 break;
5238 case 0x68: /* push Iv */
5239 case 0x6a:
5240 ot = mo_pushpop(s, dflag);
5241 if (b == 0x68)
5242 val = insn_get(env, s, ot);
5243 else
5244 val = (int8_t)insn_get(env, s, MO_8);
5245 tcg_gen_movi_tl(cpu_T[0], val);
5246 gen_push_v(s, cpu_T[0]);
5247 break;
5248 case 0x8f: /* pop Ev */
5249 modrm = cpu_ldub_code(env, s->pc++);
5250 mod = (modrm >> 6) & 3;
5251 ot = gen_pop_T0(s);
5252 if (mod == 3) {
5253 /* NOTE: order is important for pop %sp */
5254 gen_pop_update(s, ot);
5255 rm = (modrm & 7) | REX_B(s);
5256 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5257 } else {
5258 /* NOTE: order is important too for MMU exceptions */
5259 s->popl_esp_hack = 1 << ot;
5260 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5261 s->popl_esp_hack = 0;
5262 gen_pop_update(s, ot);
5264 break;
5265 case 0xc8: /* enter */
5267 int level;
5268 val = cpu_lduw_code(env, s->pc);
5269 s->pc += 2;
5270 level = cpu_ldub_code(env, s->pc++);
5271 gen_enter(s, val, level);
5273 break;
5274 case 0xc9: /* leave */
5275 /* XXX: exception not precise (ESP is updated before potential exception) */
5276 if (CODE64(s)) {
5277 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EBP);
5278 gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[0]);
5279 } else if (s->ss32) {
5280 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
5281 gen_op_mov_reg_v(MO_32, R_ESP, cpu_T[0]);
5282 } else {
5283 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EBP);
5284 gen_op_mov_reg_v(MO_16, R_ESP, cpu_T[0]);
5286 ot = gen_pop_T0(s);
5287 gen_op_mov_reg_v(ot, R_EBP, cpu_T[0]);
5288 gen_pop_update(s, ot);
5289 break;
5290 case 0x06: /* push es */
5291 case 0x0e: /* push cs */
5292 case 0x16: /* push ss */
5293 case 0x1e: /* push ds */
5294 if (CODE64(s))
5295 goto illegal_op;
5296 gen_op_movl_T0_seg(b >> 3);
5297 gen_push_v(s, cpu_T[0]);
5298 break;
5299 case 0x1a0: /* push fs */
5300 case 0x1a8: /* push gs */
5301 gen_op_movl_T0_seg((b >> 3) & 7);
5302 gen_push_v(s, cpu_T[0]);
5303 break;
5304 case 0x07: /* pop es */
5305 case 0x17: /* pop ss */
5306 case 0x1f: /* pop ds */
5307 if (CODE64(s))
5308 goto illegal_op;
5309 reg = b >> 3;
5310 ot = gen_pop_T0(s);
5311 gen_movl_seg_T0(s, reg);
5312 gen_pop_update(s, ot);
5313 if (reg == R_SS) {
5314 /* if reg == SS, inhibit interrupts/trace. */
5315 /* If several instructions disable interrupts, only the
5316 _first_ does it */
5317 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5318 gen_helper_set_inhibit_irq(cpu_env);
5319 s->tf = 0;
5321 if (s->is_jmp) {
5322 gen_jmp_im(s->pc - s->cs_base);
5323 gen_eob(s);
5325 break;
5326 case 0x1a1: /* pop fs */
5327 case 0x1a9: /* pop gs */
5328 ot = gen_pop_T0(s);
5329 gen_movl_seg_T0(s, (b >> 3) & 7);
5330 gen_pop_update(s, ot);
5331 if (s->is_jmp) {
5332 gen_jmp_im(s->pc - s->cs_base);
5333 gen_eob(s);
5335 break;
5337 /**************************/
5338 /* mov */
5339 case 0x88:
5340 case 0x89: /* mov Gv, Ev */
5341 ot = mo_b_d(b, dflag);
5342 modrm = cpu_ldub_code(env, s->pc++);
5343 reg = ((modrm >> 3) & 7) | rex_r;
5345 /* generate a generic store */
5346 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5347 break;
5348 case 0xc6:
5349 case 0xc7: /* mov Ev, Iv */
5350 ot = mo_b_d(b, dflag);
5351 modrm = cpu_ldub_code(env, s->pc++);
5352 mod = (modrm >> 6) & 3;
5353 if (mod != 3) {
5354 s->rip_offset = insn_const_size(ot);
5355 gen_lea_modrm(env, s, modrm);
5357 val = insn_get(env, s, ot);
5358 tcg_gen_movi_tl(cpu_T[0], val);
5359 if (mod != 3) {
5360 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5361 } else {
5362 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T[0]);
5364 break;
5365 case 0x8a:
5366 case 0x8b: /* mov Ev, Gv */
5367 ot = mo_b_d(b, dflag);
5368 modrm = cpu_ldub_code(env, s->pc++);
5369 reg = ((modrm >> 3) & 7) | rex_r;
5371 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5372 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5373 break;
5374 case 0x8e: /* mov seg, Gv */
5375 modrm = cpu_ldub_code(env, s->pc++);
5376 reg = (modrm >> 3) & 7;
5377 if (reg >= 6 || reg == R_CS)
5378 goto illegal_op;
5379 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5380 gen_movl_seg_T0(s, reg);
5381 if (reg == R_SS) {
5382 /* if reg == SS, inhibit interrupts/trace */
5383 /* If several instructions disable interrupts, only the
5384 _first_ does it */
5385 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5386 gen_helper_set_inhibit_irq(cpu_env);
5387 s->tf = 0;
5389 if (s->is_jmp) {
5390 gen_jmp_im(s->pc - s->cs_base);
5391 gen_eob(s);
5393 break;
5394 case 0x8c: /* mov Gv, seg */
5395 modrm = cpu_ldub_code(env, s->pc++);
5396 reg = (modrm >> 3) & 7;
5397 mod = (modrm >> 6) & 3;
5398 if (reg >= 6)
5399 goto illegal_op;
5400 gen_op_movl_T0_seg(reg);
5401 ot = mod == 3 ? dflag : MO_16;
5402 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5403 break;
5405 case 0x1b6: /* movzbS Gv, Eb */
5406 case 0x1b7: /* movzwS Gv, Eb */
5407 case 0x1be: /* movsbS Gv, Eb */
5408 case 0x1bf: /* movswS Gv, Eb */
5410 TCGMemOp d_ot;
5411 TCGMemOp s_ot;
5413 /* d_ot is the size of destination */
5414 d_ot = dflag;
5415 /* ot is the size of source */
5416 ot = (b & 1) + MO_8;
5417 /* s_ot is the sign+size of source */
5418 s_ot = b & 8 ? MO_SIGN | ot : ot;
5420 modrm = cpu_ldub_code(env, s->pc++);
5421 reg = ((modrm >> 3) & 7) | rex_r;
5422 mod = (modrm >> 6) & 3;
5423 rm = (modrm & 7) | REX_B(s);
5425 if (mod == 3) {
5426 gen_op_mov_v_reg(ot, cpu_T[0], rm);
5427 switch (s_ot) {
5428 case MO_UB:
5429 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
5430 break;
5431 case MO_SB:
5432 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5433 break;
5434 case MO_UW:
5435 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
5436 break;
5437 default:
5438 case MO_SW:
5439 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5440 break;
5442 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
5443 } else {
5444 gen_lea_modrm(env, s, modrm);
5445 gen_op_ld_v(s, s_ot, cpu_T[0], cpu_A0);
5446 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
5449 break;
5451 case 0x8d: /* lea */
5452 ot = dflag;
5453 modrm = cpu_ldub_code(env, s->pc++);
5454 mod = (modrm >> 6) & 3;
5455 if (mod == 3)
5456 goto illegal_op;
5457 reg = ((modrm >> 3) & 7) | rex_r;
5458 /* we must ensure that no segment is added */
5459 s->override = -1;
5460 val = s->addseg;
5461 s->addseg = 0;
5462 gen_lea_modrm(env, s, modrm);
5463 s->addseg = val;
5464 gen_op_mov_reg_v(ot, reg, cpu_A0);
5465 break;
5467 case 0xa0: /* mov EAX, Ov */
5468 case 0xa1:
5469 case 0xa2: /* mov Ov, EAX */
5470 case 0xa3:
5472 target_ulong offset_addr;
5474 ot = mo_b_d(b, dflag);
5475 switch (s->aflag) {
5476 #ifdef TARGET_X86_64
5477 case MO_64:
5478 offset_addr = cpu_ldq_code(env, s->pc);
5479 s->pc += 8;
5480 break;
5481 #endif
5482 default:
5483 offset_addr = insn_get(env, s, s->aflag);
5484 break;
5486 tcg_gen_movi_tl(cpu_A0, offset_addr);
5487 gen_add_A0_ds_seg(s);
5488 if ((b & 2) == 0) {
5489 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
5490 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
5491 } else {
5492 gen_op_mov_v_reg(ot, cpu_T[0], R_EAX);
5493 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5496 break;
5497 case 0xd7: /* xlat */
5498 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5499 tcg_gen_ext8u_tl(cpu_T[0], cpu_regs[R_EAX]);
5500 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5501 gen_extu(s->aflag, cpu_A0);
5502 gen_add_A0_ds_seg(s);
5503 gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
5504 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
5505 break;
5506 case 0xb0 ... 0xb7: /* mov R, Ib */
5507 val = insn_get(env, s, MO_8);
5508 tcg_gen_movi_tl(cpu_T[0], val);
5509 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T[0]);
5510 break;
5511 case 0xb8 ... 0xbf: /* mov R, Iv */
5512 #ifdef TARGET_X86_64
5513 if (dflag == MO_64) {
5514 uint64_t tmp;
5515 /* 64 bit case */
5516 tmp = cpu_ldq_code(env, s->pc);
5517 s->pc += 8;
5518 reg = (b & 7) | REX_B(s);
5519 tcg_gen_movi_tl(cpu_T[0], tmp);
5520 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
5521 } else
5522 #endif
5524 ot = dflag;
5525 val = insn_get(env, s, ot);
5526 reg = (b & 7) | REX_B(s);
5527 tcg_gen_movi_tl(cpu_T[0], val);
5528 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5530 break;
5532 case 0x91 ... 0x97: /* xchg R, EAX */
5533 do_xchg_reg_eax:
5534 ot = dflag;
5535 reg = (b & 7) | REX_B(s);
5536 rm = R_EAX;
5537 goto do_xchg_reg;
5538 case 0x86:
5539 case 0x87: /* xchg Ev, Gv */
5540 ot = mo_b_d(b, dflag);
5541 modrm = cpu_ldub_code(env, s->pc++);
5542 reg = ((modrm >> 3) & 7) | rex_r;
5543 mod = (modrm >> 6) & 3;
5544 if (mod == 3) {
5545 rm = (modrm & 7) | REX_B(s);
5546 do_xchg_reg:
5547 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5548 gen_op_mov_v_reg(ot, cpu_T[1], rm);
5549 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5550 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5551 } else {
5552 gen_lea_modrm(env, s, modrm);
5553 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5554 /* for xchg, lock is implicit */
5555 if (!(prefixes & PREFIX_LOCK))
5556 gen_helper_lock();
5557 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5558 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5559 if (!(prefixes & PREFIX_LOCK))
5560 gen_helper_unlock();
5561 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5563 break;
5564 case 0xc4: /* les Gv */
5565 /* In CODE64 this is VEX3; see above. */
5566 op = R_ES;
5567 goto do_lxx;
5568 case 0xc5: /* lds Gv */
5569 /* In CODE64 this is VEX2; see above. */
5570 op = R_DS;
5571 goto do_lxx;
5572 case 0x1b2: /* lss Gv */
5573 op = R_SS;
5574 goto do_lxx;
5575 case 0x1b4: /* lfs Gv */
5576 op = R_FS;
5577 goto do_lxx;
5578 case 0x1b5: /* lgs Gv */
5579 op = R_GS;
5580 do_lxx:
5581 ot = dflag != MO_16 ? MO_32 : MO_16;
5582 modrm = cpu_ldub_code(env, s->pc++);
5583 reg = ((modrm >> 3) & 7) | rex_r;
5584 mod = (modrm >> 6) & 3;
5585 if (mod == 3)
5586 goto illegal_op;
5587 gen_lea_modrm(env, s, modrm);
5588 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5589 gen_add_A0_im(s, 1 << ot);
5590 /* load the segment first to handle exceptions properly */
5591 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
5592 gen_movl_seg_T0(s, op);
5593 /* then put the data */
5594 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5595 if (s->is_jmp) {
5596 gen_jmp_im(s->pc - s->cs_base);
5597 gen_eob(s);
5599 break;
5601 /************************/
5602 /* shifts */
5603 case 0xc0:
5604 case 0xc1:
5605 /* shift Ev,Ib */
5606 shift = 2;
5607 grp2:
5609 ot = mo_b_d(b, dflag);
5610 modrm = cpu_ldub_code(env, s->pc++);
5611 mod = (modrm >> 6) & 3;
5612 op = (modrm >> 3) & 7;
5614 if (mod != 3) {
5615 if (shift == 2) {
5616 s->rip_offset = 1;
5618 gen_lea_modrm(env, s, modrm);
5619 opreg = OR_TMP0;
5620 } else {
5621 opreg = (modrm & 7) | REX_B(s);
5624 /* simpler op */
5625 if (shift == 0) {
5626 gen_shift(s, op, ot, opreg, OR_ECX);
5627 } else {
5628 if (shift == 2) {
5629 shift = cpu_ldub_code(env, s->pc++);
5631 gen_shifti(s, op, ot, opreg, shift);
5634 break;
5635 case 0xd0:
5636 case 0xd1:
5637 /* shift Ev,1 */
5638 shift = 1;
5639 goto grp2;
5640 case 0xd2:
5641 case 0xd3:
5642 /* shift Ev,cl */
5643 shift = 0;
5644 goto grp2;
5646 case 0x1a4: /* shld imm */
5647 op = 0;
5648 shift = 1;
5649 goto do_shiftd;
5650 case 0x1a5: /* shld cl */
5651 op = 0;
5652 shift = 0;
5653 goto do_shiftd;
5654 case 0x1ac: /* shrd imm */
5655 op = 1;
5656 shift = 1;
5657 goto do_shiftd;
5658 case 0x1ad: /* shrd cl */
5659 op = 1;
5660 shift = 0;
5661 do_shiftd:
5662 ot = dflag;
5663 modrm = cpu_ldub_code(env, s->pc++);
5664 mod = (modrm >> 6) & 3;
5665 rm = (modrm & 7) | REX_B(s);
5666 reg = ((modrm >> 3) & 7) | rex_r;
5667 if (mod != 3) {
5668 gen_lea_modrm(env, s, modrm);
5669 opreg = OR_TMP0;
5670 } else {
5671 opreg = rm;
5673 gen_op_mov_v_reg(ot, cpu_T[1], reg);
5675 if (shift) {
5676 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5677 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5678 tcg_temp_free(imm);
5679 } else {
5680 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5682 break;
5684 /************************/
5685 /* floats */
5686 case 0xd8 ... 0xdf:
5687 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5688 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5689 /* XXX: what to do if illegal op ? */
5690 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5691 break;
5693 modrm = cpu_ldub_code(env, s->pc++);
5694 mod = (modrm >> 6) & 3;
5695 rm = modrm & 7;
5696 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5697 if (mod != 3) {
5698 /* memory op */
5699 gen_lea_modrm(env, s, modrm);
5700 switch(op) {
5701 case 0x00 ... 0x07: /* fxxxs */
5702 case 0x10 ... 0x17: /* fixxxl */
5703 case 0x20 ... 0x27: /* fxxxl */
5704 case 0x30 ... 0x37: /* fixxx */
5706 int op1;
5707 op1 = op & 7;
5709 switch(op >> 4) {
5710 case 0:
5711 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5712 s->mem_index, MO_LEUL);
5713 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5714 break;
5715 case 1:
5716 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5717 s->mem_index, MO_LEUL);
5718 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5719 break;
5720 case 2:
5721 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5722 s->mem_index, MO_LEQ);
5723 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5724 break;
5725 case 3:
5726 default:
5727 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5728 s->mem_index, MO_LESW);
5729 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5730 break;
5733 gen_helper_fp_arith_ST0_FT0(op1);
5734 if (op1 == 3) {
5735 /* fcomp needs pop */
5736 gen_helper_fpop(cpu_env);
5739 break;
5740 case 0x08: /* flds */
5741 case 0x0a: /* fsts */
5742 case 0x0b: /* fstps */
5743 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5744 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5745 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5746 switch(op & 7) {
5747 case 0:
5748 switch(op >> 4) {
5749 case 0:
5750 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5751 s->mem_index, MO_LEUL);
5752 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5753 break;
5754 case 1:
5755 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5756 s->mem_index, MO_LEUL);
5757 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5758 break;
5759 case 2:
5760 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5761 s->mem_index, MO_LEQ);
5762 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5763 break;
5764 case 3:
5765 default:
5766 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5767 s->mem_index, MO_LESW);
5768 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5769 break;
5771 break;
5772 case 1:
5773 /* XXX: the corresponding CPUID bit must be tested ! */
5774 switch(op >> 4) {
5775 case 1:
5776 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5777 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5778 s->mem_index, MO_LEUL);
5779 break;
5780 case 2:
5781 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5782 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5783 s->mem_index, MO_LEQ);
5784 break;
5785 case 3:
5786 default:
5787 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5788 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5789 s->mem_index, MO_LEUW);
5790 break;
5792 gen_helper_fpop(cpu_env);
5793 break;
5794 default:
5795 switch(op >> 4) {
5796 case 0:
5797 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5798 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5799 s->mem_index, MO_LEUL);
5800 break;
5801 case 1:
5802 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5803 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5804 s->mem_index, MO_LEUL);
5805 break;
5806 case 2:
5807 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5808 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5809 s->mem_index, MO_LEQ);
5810 break;
5811 case 3:
5812 default:
5813 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5814 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5815 s->mem_index, MO_LEUW);
5816 break;
5818 if ((op & 7) == 3)
5819 gen_helper_fpop(cpu_env);
5820 break;
5822 break;
5823 case 0x0c: /* fldenv mem */
5824 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5825 break;
5826 case 0x0d: /* fldcw mem */
5827 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5828 s->mem_index, MO_LEUW);
5829 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5830 break;
5831 case 0x0e: /* fnstenv mem */
5832 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5833 break;
5834 case 0x0f: /* fnstcw mem */
5835 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5836 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5837 s->mem_index, MO_LEUW);
5838 break;
5839 case 0x1d: /* fldt mem */
5840 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5841 break;
5842 case 0x1f: /* fstpt mem */
5843 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5844 gen_helper_fpop(cpu_env);
5845 break;
5846 case 0x2c: /* frstor mem */
5847 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5848 break;
5849 case 0x2e: /* fnsave mem */
5850 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5851 break;
5852 case 0x2f: /* fnstsw mem */
5853 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5854 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5855 s->mem_index, MO_LEUW);
5856 break;
5857 case 0x3c: /* fbld */
5858 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5859 break;
5860 case 0x3e: /* fbstp */
5861 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5862 gen_helper_fpop(cpu_env);
5863 break;
5864 case 0x3d: /* fildll */
5865 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5866 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5867 break;
5868 case 0x3f: /* fistpll */
5869 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5870 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5871 gen_helper_fpop(cpu_env);
5872 break;
5873 default:
5874 goto illegal_op;
5876 } else {
5877 /* register float ops */
5878 opreg = rm;
5880 switch(op) {
5881 case 0x08: /* fld sti */
5882 gen_helper_fpush(cpu_env);
5883 gen_helper_fmov_ST0_STN(cpu_env,
5884 tcg_const_i32((opreg + 1) & 7));
5885 break;
5886 case 0x09: /* fxchg sti */
5887 case 0x29: /* fxchg4 sti, undocumented op */
5888 case 0x39: /* fxchg7 sti, undocumented op */
5889 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5890 break;
5891 case 0x0a: /* grp d9/2 */
5892 switch(rm) {
5893 case 0: /* fnop */
5894 /* check exceptions (FreeBSD FPU probe) */
5895 gen_helper_fwait(cpu_env);
5896 break;
5897 default:
5898 goto illegal_op;
5900 break;
5901 case 0x0c: /* grp d9/4 */
5902 switch(rm) {
5903 case 0: /* fchs */
5904 gen_helper_fchs_ST0(cpu_env);
5905 break;
5906 case 1: /* fabs */
5907 gen_helper_fabs_ST0(cpu_env);
5908 break;
5909 case 4: /* ftst */
5910 gen_helper_fldz_FT0(cpu_env);
5911 gen_helper_fcom_ST0_FT0(cpu_env);
5912 break;
5913 case 5: /* fxam */
5914 gen_helper_fxam_ST0(cpu_env);
5915 break;
5916 default:
5917 goto illegal_op;
5919 break;
5920 case 0x0d: /* grp d9/5 */
5922 switch(rm) {
5923 case 0:
5924 gen_helper_fpush(cpu_env);
5925 gen_helper_fld1_ST0(cpu_env);
5926 break;
5927 case 1:
5928 gen_helper_fpush(cpu_env);
5929 gen_helper_fldl2t_ST0(cpu_env);
5930 break;
5931 case 2:
5932 gen_helper_fpush(cpu_env);
5933 gen_helper_fldl2e_ST0(cpu_env);
5934 break;
5935 case 3:
5936 gen_helper_fpush(cpu_env);
5937 gen_helper_fldpi_ST0(cpu_env);
5938 break;
5939 case 4:
5940 gen_helper_fpush(cpu_env);
5941 gen_helper_fldlg2_ST0(cpu_env);
5942 break;
5943 case 5:
5944 gen_helper_fpush(cpu_env);
5945 gen_helper_fldln2_ST0(cpu_env);
5946 break;
5947 case 6:
5948 gen_helper_fpush(cpu_env);
5949 gen_helper_fldz_ST0(cpu_env);
5950 break;
5951 default:
5952 goto illegal_op;
5955 break;
5956 case 0x0e: /* grp d9/6 */
5957 switch(rm) {
5958 case 0: /* f2xm1 */
5959 gen_helper_f2xm1(cpu_env);
5960 break;
5961 case 1: /* fyl2x */
5962 gen_helper_fyl2x(cpu_env);
5963 break;
5964 case 2: /* fptan */
5965 gen_helper_fptan(cpu_env);
5966 break;
5967 case 3: /* fpatan */
5968 gen_helper_fpatan(cpu_env);
5969 break;
5970 case 4: /* fxtract */
5971 gen_helper_fxtract(cpu_env);
5972 break;
5973 case 5: /* fprem1 */
5974 gen_helper_fprem1(cpu_env);
5975 break;
5976 case 6: /* fdecstp */
5977 gen_helper_fdecstp(cpu_env);
5978 break;
5979 default:
5980 case 7: /* fincstp */
5981 gen_helper_fincstp(cpu_env);
5982 break;
5984 break;
5985 case 0x0f: /* grp d9/7 */
5986 switch(rm) {
5987 case 0: /* fprem */
5988 gen_helper_fprem(cpu_env);
5989 break;
5990 case 1: /* fyl2xp1 */
5991 gen_helper_fyl2xp1(cpu_env);
5992 break;
5993 case 2: /* fsqrt */
5994 gen_helper_fsqrt(cpu_env);
5995 break;
5996 case 3: /* fsincos */
5997 gen_helper_fsincos(cpu_env);
5998 break;
5999 case 5: /* fscale */
6000 gen_helper_fscale(cpu_env);
6001 break;
6002 case 4: /* frndint */
6003 gen_helper_frndint(cpu_env);
6004 break;
6005 case 6: /* fsin */
6006 gen_helper_fsin(cpu_env);
6007 break;
6008 default:
6009 case 7: /* fcos */
6010 gen_helper_fcos(cpu_env);
6011 break;
6013 break;
6014 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6015 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6016 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6018 int op1;
6020 op1 = op & 7;
6021 if (op >= 0x20) {
6022 gen_helper_fp_arith_STN_ST0(op1, opreg);
6023 if (op >= 0x30)
6024 gen_helper_fpop(cpu_env);
6025 } else {
6026 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6027 gen_helper_fp_arith_ST0_FT0(op1);
6030 break;
6031 case 0x02: /* fcom */
6032 case 0x22: /* fcom2, undocumented op */
6033 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6034 gen_helper_fcom_ST0_FT0(cpu_env);
6035 break;
6036 case 0x03: /* fcomp */
6037 case 0x23: /* fcomp3, undocumented op */
6038 case 0x32: /* fcomp5, undocumented op */
6039 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6040 gen_helper_fcom_ST0_FT0(cpu_env);
6041 gen_helper_fpop(cpu_env);
6042 break;
6043 case 0x15: /* da/5 */
6044 switch(rm) {
6045 case 1: /* fucompp */
6046 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6047 gen_helper_fucom_ST0_FT0(cpu_env);
6048 gen_helper_fpop(cpu_env);
6049 gen_helper_fpop(cpu_env);
6050 break;
6051 default:
6052 goto illegal_op;
6054 break;
6055 case 0x1c:
6056 switch(rm) {
6057 case 0: /* feni (287 only, just do nop here) */
6058 break;
6059 case 1: /* fdisi (287 only, just do nop here) */
6060 break;
6061 case 2: /* fclex */
6062 gen_helper_fclex(cpu_env);
6063 break;
6064 case 3: /* fninit */
6065 gen_helper_fninit(cpu_env);
6066 break;
6067 case 4: /* fsetpm (287 only, just do nop here) */
6068 break;
6069 default:
6070 goto illegal_op;
6072 break;
6073 case 0x1d: /* fucomi */
6074 if (!(s->cpuid_features & CPUID_CMOV)) {
6075 goto illegal_op;
6077 gen_update_cc_op(s);
6078 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6079 gen_helper_fucomi_ST0_FT0(cpu_env);
6080 set_cc_op(s, CC_OP_EFLAGS);
6081 break;
6082 case 0x1e: /* fcomi */
6083 if (!(s->cpuid_features & CPUID_CMOV)) {
6084 goto illegal_op;
6086 gen_update_cc_op(s);
6087 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6088 gen_helper_fcomi_ST0_FT0(cpu_env);
6089 set_cc_op(s, CC_OP_EFLAGS);
6090 break;
6091 case 0x28: /* ffree sti */
6092 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6093 break;
6094 case 0x2a: /* fst sti */
6095 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6096 break;
6097 case 0x2b: /* fstp sti */
6098 case 0x0b: /* fstp1 sti, undocumented op */
6099 case 0x3a: /* fstp8 sti, undocumented op */
6100 case 0x3b: /* fstp9 sti, undocumented op */
6101 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6102 gen_helper_fpop(cpu_env);
6103 break;
6104 case 0x2c: /* fucom st(i) */
6105 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6106 gen_helper_fucom_ST0_FT0(cpu_env);
6107 break;
6108 case 0x2d: /* fucomp st(i) */
6109 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6110 gen_helper_fucom_ST0_FT0(cpu_env);
6111 gen_helper_fpop(cpu_env);
6112 break;
6113 case 0x33: /* de/3 */
6114 switch(rm) {
6115 case 1: /* fcompp */
6116 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6117 gen_helper_fcom_ST0_FT0(cpu_env);
6118 gen_helper_fpop(cpu_env);
6119 gen_helper_fpop(cpu_env);
6120 break;
6121 default:
6122 goto illegal_op;
6124 break;
6125 case 0x38: /* ffreep sti, undocumented op */
6126 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6127 gen_helper_fpop(cpu_env);
6128 break;
6129 case 0x3c: /* df/4 */
6130 switch(rm) {
6131 case 0:
6132 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6133 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6134 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
6135 break;
6136 default:
6137 goto illegal_op;
6139 break;
6140 case 0x3d: /* fucomip */
6141 if (!(s->cpuid_features & CPUID_CMOV)) {
6142 goto illegal_op;
6144 gen_update_cc_op(s);
6145 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6146 gen_helper_fucomi_ST0_FT0(cpu_env);
6147 gen_helper_fpop(cpu_env);
6148 set_cc_op(s, CC_OP_EFLAGS);
6149 break;
6150 case 0x3e: /* fcomip */
6151 if (!(s->cpuid_features & CPUID_CMOV)) {
6152 goto illegal_op;
6154 gen_update_cc_op(s);
6155 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6156 gen_helper_fcomi_ST0_FT0(cpu_env);
6157 gen_helper_fpop(cpu_env);
6158 set_cc_op(s, CC_OP_EFLAGS);
6159 break;
6160 case 0x10 ... 0x13: /* fcmovxx */
6161 case 0x18 ... 0x1b:
6163 int op1;
6164 TCGLabel *l1;
6165 static const uint8_t fcmov_cc[8] = {
6166 (JCC_B << 1),
6167 (JCC_Z << 1),
6168 (JCC_BE << 1),
6169 (JCC_P << 1),
6172 if (!(s->cpuid_features & CPUID_CMOV)) {
6173 goto illegal_op;
6175 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6176 l1 = gen_new_label();
6177 gen_jcc1_noeob(s, op1, l1);
6178 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6179 gen_set_label(l1);
6181 break;
6182 default:
6183 goto illegal_op;
6186 break;
6187 /************************/
6188 /* string ops */
6190 case 0xa4: /* movsS */
6191 case 0xa5:
6192 ot = mo_b_d(b, dflag);
6193 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6194 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6195 } else {
6196 gen_movs(s, ot);
6198 break;
6200 case 0xaa: /* stosS */
6201 case 0xab:
6202 ot = mo_b_d(b, dflag);
6203 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6204 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6205 } else {
6206 gen_stos(s, ot);
6208 break;
6209 case 0xac: /* lodsS */
6210 case 0xad:
6211 ot = mo_b_d(b, dflag);
6212 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6213 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6214 } else {
6215 gen_lods(s, ot);
6217 break;
6218 case 0xae: /* scasS */
6219 case 0xaf:
6220 ot = mo_b_d(b, dflag);
6221 if (prefixes & PREFIX_REPNZ) {
6222 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6223 } else if (prefixes & PREFIX_REPZ) {
6224 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6225 } else {
6226 gen_scas(s, ot);
6228 break;
6230 case 0xa6: /* cmpsS */
6231 case 0xa7:
6232 ot = mo_b_d(b, dflag);
6233 if (prefixes & PREFIX_REPNZ) {
6234 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6235 } else if (prefixes & PREFIX_REPZ) {
6236 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6237 } else {
6238 gen_cmps(s, ot);
6240 break;
6241 case 0x6c: /* insS */
6242 case 0x6d:
6243 ot = mo_b_d32(b, dflag);
6244 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6245 gen_check_io(s, ot, pc_start - s->cs_base,
6246 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6247 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6248 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6249 } else {
6250 gen_ins(s, ot);
6251 if (s->tb->cflags & CF_USE_ICOUNT) {
6252 gen_jmp(s, s->pc - s->cs_base);
6255 break;
6256 case 0x6e: /* outsS */
6257 case 0x6f:
6258 ot = mo_b_d32(b, dflag);
6259 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6260 gen_check_io(s, ot, pc_start - s->cs_base,
6261 svm_is_rep(prefixes) | 4);
6262 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6263 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6264 } else {
6265 gen_outs(s, ot);
6266 if (s->tb->cflags & CF_USE_ICOUNT) {
6267 gen_jmp(s, s->pc - s->cs_base);
6270 break;
6272 /************************/
6273 /* port I/O */
6275 case 0xe4:
6276 case 0xe5:
6277 ot = mo_b_d32(b, dflag);
6278 val = cpu_ldub_code(env, s->pc++);
6279 tcg_gen_movi_tl(cpu_T[0], val);
6280 gen_check_io(s, ot, pc_start - s->cs_base,
6281 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6282 if (s->tb->cflags & CF_USE_ICOUNT) {
6283 gen_io_start();
6285 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6286 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6287 gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
6288 gen_bpt_io(s, cpu_tmp2_i32, ot);
6289 if (s->tb->cflags & CF_USE_ICOUNT) {
6290 gen_io_end();
6291 gen_jmp(s, s->pc - s->cs_base);
6293 break;
6294 case 0xe6:
6295 case 0xe7:
6296 ot = mo_b_d32(b, dflag);
6297 val = cpu_ldub_code(env, s->pc++);
6298 tcg_gen_movi_tl(cpu_T[0], val);
6299 gen_check_io(s, ot, pc_start - s->cs_base,
6300 svm_is_rep(prefixes));
6301 gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
6303 if (s->tb->cflags & CF_USE_ICOUNT) {
6304 gen_io_start();
6306 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6307 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6308 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6309 gen_bpt_io(s, cpu_tmp2_i32, ot);
6310 if (s->tb->cflags & CF_USE_ICOUNT) {
6311 gen_io_end();
6312 gen_jmp(s, s->pc - s->cs_base);
6314 break;
6315 case 0xec:
6316 case 0xed:
6317 ot = mo_b_d32(b, dflag);
6318 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6319 gen_check_io(s, ot, pc_start - s->cs_base,
6320 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6321 if (s->tb->cflags & CF_USE_ICOUNT) {
6322 gen_io_start();
6324 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6325 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6326 gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
6327 gen_bpt_io(s, cpu_tmp2_i32, ot);
6328 if (s->tb->cflags & CF_USE_ICOUNT) {
6329 gen_io_end();
6330 gen_jmp(s, s->pc - s->cs_base);
6332 break;
6333 case 0xee:
6334 case 0xef:
6335 ot = mo_b_d32(b, dflag);
6336 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6337 gen_check_io(s, ot, pc_start - s->cs_base,
6338 svm_is_rep(prefixes));
6339 gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
6341 if (s->tb->cflags & CF_USE_ICOUNT) {
6342 gen_io_start();
6344 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6345 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6346 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6347 gen_bpt_io(s, cpu_tmp2_i32, ot);
6348 if (s->tb->cflags & CF_USE_ICOUNT) {
6349 gen_io_end();
6350 gen_jmp(s, s->pc - s->cs_base);
6352 break;
6354 /************************/
6355 /* control */
6356 case 0xc2: /* ret im */
6357 val = cpu_ldsw_code(env, s->pc);
6358 s->pc += 2;
6359 ot = gen_pop_T0(s);
6360 gen_stack_update(s, val + (1 << ot));
6361 /* Note that gen_pop_T0 uses a zero-extending load. */
6362 gen_op_jmp_v(cpu_T[0]);
6363 gen_eob(s);
6364 break;
6365 case 0xc3: /* ret */
6366 ot = gen_pop_T0(s);
6367 gen_pop_update(s, ot);
6368 /* Note that gen_pop_T0 uses a zero-extending load. */
6369 gen_op_jmp_v(cpu_T[0]);
6370 gen_eob(s);
6371 break;
6372 case 0xca: /* lret im */
6373 val = cpu_ldsw_code(env, s->pc);
6374 s->pc += 2;
6375 do_lret:
6376 if (s->pe && !s->vm86) {
6377 gen_update_cc_op(s);
6378 gen_jmp_im(pc_start - s->cs_base);
6379 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6380 tcg_const_i32(val));
6381 } else {
6382 gen_stack_A0(s);
6383 /* pop offset */
6384 gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
6385 /* NOTE: keeping EIP updated is not a problem in case of
6386 exception */
6387 gen_op_jmp_v(cpu_T[0]);
6388 /* pop selector */
6389 gen_op_addl_A0_im(1 << dflag);
6390 gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
6391 gen_op_movl_seg_T0_vm(R_CS);
6392 /* add stack offset */
6393 gen_stack_update(s, val + (2 << dflag));
6395 gen_eob(s);
6396 break;
6397 case 0xcb: /* lret */
6398 val = 0;
6399 goto do_lret;
6400 case 0xcf: /* iret */
6401 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6402 if (!s->pe) {
6403 /* real mode */
6404 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6405 set_cc_op(s, CC_OP_EFLAGS);
6406 } else if (s->vm86) {
6407 if (s->iopl != 3) {
6408 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6409 } else {
6410 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6411 set_cc_op(s, CC_OP_EFLAGS);
6413 } else {
6414 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6415 tcg_const_i32(s->pc - s->cs_base));
6416 set_cc_op(s, CC_OP_EFLAGS);
6418 gen_eob(s);
6419 break;
6420 case 0xe8: /* call im */
6422 if (dflag != MO_16) {
6423 tval = (int32_t)insn_get(env, s, MO_32);
6424 } else {
6425 tval = (int16_t)insn_get(env, s, MO_16);
6427 next_eip = s->pc - s->cs_base;
6428 tval += next_eip;
6429 if (dflag == MO_16) {
6430 tval &= 0xffff;
6431 } else if (!CODE64(s)) {
6432 tval &= 0xffffffff;
6434 tcg_gen_movi_tl(cpu_T[0], next_eip);
6435 gen_push_v(s, cpu_T[0]);
6436 gen_jmp(s, tval);
6438 break;
6439 case 0x9a: /* lcall im */
6441 unsigned int selector, offset;
6443 if (CODE64(s))
6444 goto illegal_op;
6445 ot = dflag;
6446 offset = insn_get(env, s, ot);
6447 selector = insn_get(env, s, MO_16);
6449 tcg_gen_movi_tl(cpu_T[0], selector);
6450 tcg_gen_movi_tl(cpu_T[1], offset);
6452 goto do_lcall;
6453 case 0xe9: /* jmp im */
6454 if (dflag != MO_16) {
6455 tval = (int32_t)insn_get(env, s, MO_32);
6456 } else {
6457 tval = (int16_t)insn_get(env, s, MO_16);
6459 tval += s->pc - s->cs_base;
6460 if (dflag == MO_16) {
6461 tval &= 0xffff;
6462 } else if (!CODE64(s)) {
6463 tval &= 0xffffffff;
6465 gen_jmp(s, tval);
6466 break;
6467 case 0xea: /* ljmp im */
6469 unsigned int selector, offset;
6471 if (CODE64(s))
6472 goto illegal_op;
6473 ot = dflag;
6474 offset = insn_get(env, s, ot);
6475 selector = insn_get(env, s, MO_16);
6477 tcg_gen_movi_tl(cpu_T[0], selector);
6478 tcg_gen_movi_tl(cpu_T[1], offset);
6480 goto do_ljmp;
6481 case 0xeb: /* jmp Jb */
6482 tval = (int8_t)insn_get(env, s, MO_8);
6483 tval += s->pc - s->cs_base;
6484 if (dflag == MO_16) {
6485 tval &= 0xffff;
6487 gen_jmp(s, tval);
6488 break;
6489 case 0x70 ... 0x7f: /* jcc Jb */
6490 tval = (int8_t)insn_get(env, s, MO_8);
6491 goto do_jcc;
6492 case 0x180 ... 0x18f: /* jcc Jv */
6493 if (dflag != MO_16) {
6494 tval = (int32_t)insn_get(env, s, MO_32);
6495 } else {
6496 tval = (int16_t)insn_get(env, s, MO_16);
6498 do_jcc:
6499 next_eip = s->pc - s->cs_base;
6500 tval += next_eip;
6501 if (dflag == MO_16) {
6502 tval &= 0xffff;
6504 gen_jcc(s, b, tval, next_eip);
6505 break;
6507 case 0x190 ... 0x19f: /* setcc Gv */
6508 modrm = cpu_ldub_code(env, s->pc++);
6509 gen_setcc1(s, b, cpu_T[0]);
6510 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6511 break;
6512 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6513 if (!(s->cpuid_features & CPUID_CMOV)) {
6514 goto illegal_op;
6516 ot = dflag;
6517 modrm = cpu_ldub_code(env, s->pc++);
6518 reg = ((modrm >> 3) & 7) | rex_r;
6519 gen_cmovcc1(env, s, ot, b, modrm, reg);
6520 break;
6522 /************************/
6523 /* flags */
6524 case 0x9c: /* pushf */
6525 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6526 if (s->vm86 && s->iopl != 3) {
6527 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6528 } else {
6529 gen_update_cc_op(s);
6530 gen_helper_read_eflags(cpu_T[0], cpu_env);
6531 gen_push_v(s, cpu_T[0]);
6533 break;
6534 case 0x9d: /* popf */
6535 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6536 if (s->vm86 && s->iopl != 3) {
6537 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6538 } else {
6539 ot = gen_pop_T0(s);
6540 if (s->cpl == 0) {
6541 if (dflag != MO_16) {
6542 gen_helper_write_eflags(cpu_env, cpu_T[0],
6543 tcg_const_i32((TF_MASK | AC_MASK |
6544 ID_MASK | NT_MASK |
6545 IF_MASK |
6546 IOPL_MASK)));
6547 } else {
6548 gen_helper_write_eflags(cpu_env, cpu_T[0],
6549 tcg_const_i32((TF_MASK | AC_MASK |
6550 ID_MASK | NT_MASK |
6551 IF_MASK | IOPL_MASK)
6552 & 0xffff));
6554 } else {
6555 if (s->cpl <= s->iopl) {
6556 if (dflag != MO_16) {
6557 gen_helper_write_eflags(cpu_env, cpu_T[0],
6558 tcg_const_i32((TF_MASK |
6559 AC_MASK |
6560 ID_MASK |
6561 NT_MASK |
6562 IF_MASK)));
6563 } else {
6564 gen_helper_write_eflags(cpu_env, cpu_T[0],
6565 tcg_const_i32((TF_MASK |
6566 AC_MASK |
6567 ID_MASK |
6568 NT_MASK |
6569 IF_MASK)
6570 & 0xffff));
6572 } else {
6573 if (dflag != MO_16) {
6574 gen_helper_write_eflags(cpu_env, cpu_T[0],
6575 tcg_const_i32((TF_MASK | AC_MASK |
6576 ID_MASK | NT_MASK)));
6577 } else {
6578 gen_helper_write_eflags(cpu_env, cpu_T[0],
6579 tcg_const_i32((TF_MASK | AC_MASK |
6580 ID_MASK | NT_MASK)
6581 & 0xffff));
6585 gen_pop_update(s, ot);
6586 set_cc_op(s, CC_OP_EFLAGS);
6587 /* abort translation because TF/AC flag may change */
6588 gen_jmp_im(s->pc - s->cs_base);
6589 gen_eob(s);
6591 break;
6592 case 0x9e: /* sahf */
6593 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6594 goto illegal_op;
6595 gen_op_mov_v_reg(MO_8, cpu_T[0], R_AH);
6596 gen_compute_eflags(s);
6597 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6598 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6599 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
6600 break;
6601 case 0x9f: /* lahf */
6602 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6603 goto illegal_op;
6604 gen_compute_eflags(s);
6605 /* Note: gen_compute_eflags() only gives the condition codes */
6606 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
6607 gen_op_mov_reg_v(MO_8, R_AH, cpu_T[0]);
6608 break;
6609 case 0xf5: /* cmc */
6610 gen_compute_eflags(s);
6611 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6612 break;
6613 case 0xf8: /* clc */
6614 gen_compute_eflags(s);
6615 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6616 break;
6617 case 0xf9: /* stc */
6618 gen_compute_eflags(s);
6619 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6620 break;
6621 case 0xfc: /* cld */
6622 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6623 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6624 break;
6625 case 0xfd: /* std */
6626 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6627 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6628 break;
6630 /************************/
6631 /* bit operations */
6632 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6633 ot = dflag;
6634 modrm = cpu_ldub_code(env, s->pc++);
6635 op = (modrm >> 3) & 7;
6636 mod = (modrm >> 6) & 3;
6637 rm = (modrm & 7) | REX_B(s);
6638 if (mod != 3) {
6639 s->rip_offset = 1;
6640 gen_lea_modrm(env, s, modrm);
6641 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
6642 } else {
6643 gen_op_mov_v_reg(ot, cpu_T[0], rm);
6645 /* load shift */
6646 val = cpu_ldub_code(env, s->pc++);
6647 tcg_gen_movi_tl(cpu_T[1], val);
6648 if (op < 4)
6649 goto illegal_op;
6650 op -= 4;
6651 goto bt_op;
6652 case 0x1a3: /* bt Gv, Ev */
6653 op = 0;
6654 goto do_btx;
6655 case 0x1ab: /* bts */
6656 op = 1;
6657 goto do_btx;
6658 case 0x1b3: /* btr */
6659 op = 2;
6660 goto do_btx;
6661 case 0x1bb: /* btc */
6662 op = 3;
6663 do_btx:
6664 ot = dflag;
6665 modrm = cpu_ldub_code(env, s->pc++);
6666 reg = ((modrm >> 3) & 7) | rex_r;
6667 mod = (modrm >> 6) & 3;
6668 rm = (modrm & 7) | REX_B(s);
6669 gen_op_mov_v_reg(MO_32, cpu_T[1], reg);
6670 if (mod != 3) {
6671 gen_lea_modrm(env, s, modrm);
6672 /* specific case: we need to add a displacement */
6673 gen_exts(ot, cpu_T[1]);
6674 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
6675 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6676 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
6677 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
6678 } else {
6679 gen_op_mov_v_reg(ot, cpu_T[0], rm);
6681 bt_op:
6682 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
6683 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6684 switch(op) {
6685 case 0:
6686 break;
6687 case 1:
6688 tcg_gen_movi_tl(cpu_tmp0, 1);
6689 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6690 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6691 break;
6692 case 2:
6693 tcg_gen_movi_tl(cpu_tmp0, 1);
6694 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6695 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6696 break;
6697 default:
6698 case 3:
6699 tcg_gen_movi_tl(cpu_tmp0, 1);
6700 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6701 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6702 break;
6704 if (op != 0) {
6705 if (mod != 3) {
6706 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
6707 } else {
6708 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
6712 /* Delay all CC updates until after the store above. Note that
6713 C is the result of the test, Z is unchanged, and the others
6714 are all undefined. */
6715 switch (s->cc_op) {
6716 case CC_OP_MULB ... CC_OP_MULQ:
6717 case CC_OP_ADDB ... CC_OP_ADDQ:
6718 case CC_OP_ADCB ... CC_OP_ADCQ:
6719 case CC_OP_SUBB ... CC_OP_SUBQ:
6720 case CC_OP_SBBB ... CC_OP_SBBQ:
6721 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6722 case CC_OP_INCB ... CC_OP_INCQ:
6723 case CC_OP_DECB ... CC_OP_DECQ:
6724 case CC_OP_SHLB ... CC_OP_SHLQ:
6725 case CC_OP_SARB ... CC_OP_SARQ:
6726 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6727 /* Z was going to be computed from the non-zero status of CC_DST.
6728 We can get that same Z value (and the new C value) by leaving
6729 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6730 same width. */
6731 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6732 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6733 break;
6734 default:
6735 /* Otherwise, generate EFLAGS and replace the C bit. */
6736 gen_compute_eflags(s);
6737 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6738 ctz32(CC_C), 1);
6739 break;
6741 break;
6742 case 0x1bc: /* bsf / tzcnt */
6743 case 0x1bd: /* bsr / lzcnt */
6744 ot = dflag;
6745 modrm = cpu_ldub_code(env, s->pc++);
6746 reg = ((modrm >> 3) & 7) | rex_r;
6747 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6748 gen_extu(ot, cpu_T[0]);
6750 /* Note that lzcnt and tzcnt are in different extensions. */
6751 if ((prefixes & PREFIX_REPZ)
6752 && (b & 1
6753 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6754 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6755 int size = 8 << ot;
6756 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
6757 if (b & 1) {
6758 /* For lzcnt, reduce the target_ulong result by the
6759 number of zeros that we expect to find at the top. */
6760 gen_helper_clz(cpu_T[0], cpu_T[0]);
6761 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - size);
6762 } else {
6763 /* For tzcnt, a zero input must return the operand size:
6764 force all bits outside the operand size to 1. */
6765 target_ulong mask = (target_ulong)-2 << (size - 1);
6766 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], mask);
6767 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6769 /* For lzcnt/tzcnt, C and Z bits are defined and are
6770 related to the result. */
6771 gen_op_update1_cc();
6772 set_cc_op(s, CC_OP_BMILGB + ot);
6773 } else {
6774 /* For bsr/bsf, only the Z bit is defined and it is related
6775 to the input and not the result. */
6776 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
6777 set_cc_op(s, CC_OP_LOGICB + ot);
6778 if (b & 1) {
6779 /* For bsr, return the bit index of the first 1 bit,
6780 not the count of leading zeros. */
6781 gen_helper_clz(cpu_T[0], cpu_T[0]);
6782 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - 1);
6783 } else {
6784 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6786 /* ??? The manual says that the output is undefined when the
6787 input is zero, but real hardware leaves it unchanged, and
6788 real programs appear to depend on that. */
6789 tcg_gen_movi_tl(cpu_tmp0, 0);
6790 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[0], cpu_cc_dst, cpu_tmp0,
6791 cpu_regs[reg], cpu_T[0]);
6793 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
6794 break;
6795 /************************/
6796 /* bcd */
6797 case 0x27: /* daa */
6798 if (CODE64(s))
6799 goto illegal_op;
6800 gen_update_cc_op(s);
6801 gen_helper_daa(cpu_env);
6802 set_cc_op(s, CC_OP_EFLAGS);
6803 break;
6804 case 0x2f: /* das */
6805 if (CODE64(s))
6806 goto illegal_op;
6807 gen_update_cc_op(s);
6808 gen_helper_das(cpu_env);
6809 set_cc_op(s, CC_OP_EFLAGS);
6810 break;
6811 case 0x37: /* aaa */
6812 if (CODE64(s))
6813 goto illegal_op;
6814 gen_update_cc_op(s);
6815 gen_helper_aaa(cpu_env);
6816 set_cc_op(s, CC_OP_EFLAGS);
6817 break;
6818 case 0x3f: /* aas */
6819 if (CODE64(s))
6820 goto illegal_op;
6821 gen_update_cc_op(s);
6822 gen_helper_aas(cpu_env);
6823 set_cc_op(s, CC_OP_EFLAGS);
6824 break;
6825 case 0xd4: /* aam */
6826 if (CODE64(s))
6827 goto illegal_op;
6828 val = cpu_ldub_code(env, s->pc++);
6829 if (val == 0) {
6830 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6831 } else {
6832 gen_helper_aam(cpu_env, tcg_const_i32(val));
6833 set_cc_op(s, CC_OP_LOGICB);
6835 break;
6836 case 0xd5: /* aad */
6837 if (CODE64(s))
6838 goto illegal_op;
6839 val = cpu_ldub_code(env, s->pc++);
6840 gen_helper_aad(cpu_env, tcg_const_i32(val));
6841 set_cc_op(s, CC_OP_LOGICB);
6842 break;
6843 /************************/
6844 /* misc */
6845 case 0x90: /* nop */
6846 /* XXX: correct lock test for all insn */
6847 if (prefixes & PREFIX_LOCK) {
6848 goto illegal_op;
6850 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6851 if (REX_B(s)) {
6852 goto do_xchg_reg_eax;
6854 if (prefixes & PREFIX_REPZ) {
6855 gen_update_cc_op(s);
6856 gen_jmp_im(pc_start - s->cs_base);
6857 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6858 s->is_jmp = DISAS_TB_JUMP;
6860 break;
6861 case 0x9b: /* fwait */
6862 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6863 (HF_MP_MASK | HF_TS_MASK)) {
6864 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6865 } else {
6866 gen_helper_fwait(cpu_env);
6868 break;
6869 case 0xcc: /* int3 */
6870 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6871 break;
6872 case 0xcd: /* int N */
6873 val = cpu_ldub_code(env, s->pc++);
6874 if (s->vm86 && s->iopl != 3) {
6875 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6876 } else {
6877 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6879 break;
6880 case 0xce: /* into */
6881 if (CODE64(s))
6882 goto illegal_op;
6883 gen_update_cc_op(s);
6884 gen_jmp_im(pc_start - s->cs_base);
6885 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6886 break;
6887 #ifdef WANT_ICEBP
6888 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6889 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6890 #if 1
6891 gen_debug(s, pc_start - s->cs_base);
6892 #else
6893 /* start debug */
6894 tb_flush(CPU(x86_env_get_cpu(env)));
6895 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6896 #endif
6897 break;
6898 #endif
6899 case 0xfa: /* cli */
6900 if (!s->vm86) {
6901 if (s->cpl <= s->iopl) {
6902 gen_helper_cli(cpu_env);
6903 } else {
6904 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6906 } else {
6907 if (s->iopl == 3) {
6908 gen_helper_cli(cpu_env);
6909 } else {
6910 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6913 break;
6914 case 0xfb: /* sti */
6915 if (!s->vm86) {
6916 if (s->cpl <= s->iopl) {
6917 gen_sti:
6918 gen_helper_sti(cpu_env);
6919 /* interruptions are enabled only the first insn after sti */
6920 /* If several instructions disable interrupts, only the
6921 _first_ does it */
6922 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
6923 gen_helper_set_inhibit_irq(cpu_env);
6924 /* give a chance to handle pending irqs */
6925 gen_jmp_im(s->pc - s->cs_base);
6926 gen_eob(s);
6927 } else {
6928 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6930 } else {
6931 if (s->iopl == 3) {
6932 goto gen_sti;
6933 } else {
6934 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6937 break;
6938 case 0x62: /* bound */
6939 if (CODE64(s))
6940 goto illegal_op;
6941 ot = dflag;
6942 modrm = cpu_ldub_code(env, s->pc++);
6943 reg = (modrm >> 3) & 7;
6944 mod = (modrm >> 6) & 3;
6945 if (mod == 3)
6946 goto illegal_op;
6947 gen_op_mov_v_reg(ot, cpu_T[0], reg);
6948 gen_lea_modrm(env, s, modrm);
6949 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6950 if (ot == MO_16) {
6951 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
6952 } else {
6953 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
6955 break;
6956 case 0x1c8 ... 0x1cf: /* bswap reg */
6957 reg = (b & 7) | REX_B(s);
6958 #ifdef TARGET_X86_64
6959 if (dflag == MO_64) {
6960 gen_op_mov_v_reg(MO_64, cpu_T[0], reg);
6961 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
6962 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
6963 } else
6964 #endif
6966 gen_op_mov_v_reg(MO_32, cpu_T[0], reg);
6967 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
6968 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
6969 gen_op_mov_reg_v(MO_32, reg, cpu_T[0]);
6971 break;
6972 case 0xd6: /* salc */
6973 if (CODE64(s))
6974 goto illegal_op;
6975 gen_compute_eflags_c(s, cpu_T[0]);
6976 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
6977 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
6978 break;
6979 case 0xe0: /* loopnz */
6980 case 0xe1: /* loopz */
6981 case 0xe2: /* loop */
6982 case 0xe3: /* jecxz */
6984 TCGLabel *l1, *l2, *l3;
6986 tval = (int8_t)insn_get(env, s, MO_8);
6987 next_eip = s->pc - s->cs_base;
6988 tval += next_eip;
6989 if (dflag == MO_16) {
6990 tval &= 0xffff;
6993 l1 = gen_new_label();
6994 l2 = gen_new_label();
6995 l3 = gen_new_label();
6996 b &= 3;
6997 switch(b) {
6998 case 0: /* loopnz */
6999 case 1: /* loopz */
7000 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7001 gen_op_jz_ecx(s->aflag, l3);
7002 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7003 break;
7004 case 2: /* loop */
7005 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7006 gen_op_jnz_ecx(s->aflag, l1);
7007 break;
7008 default:
7009 case 3: /* jcxz */
7010 gen_op_jz_ecx(s->aflag, l1);
7011 break;
7014 gen_set_label(l3);
7015 gen_jmp_im(next_eip);
7016 tcg_gen_br(l2);
7018 gen_set_label(l1);
7019 gen_jmp_im(tval);
7020 gen_set_label(l2);
7021 gen_eob(s);
7023 break;
7024 case 0x130: /* wrmsr */
7025 case 0x132: /* rdmsr */
7026 if (s->cpl != 0) {
7027 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7028 } else {
7029 gen_update_cc_op(s);
7030 gen_jmp_im(pc_start - s->cs_base);
7031 if (b & 2) {
7032 gen_helper_rdmsr(cpu_env);
7033 } else {
7034 gen_helper_wrmsr(cpu_env);
7037 break;
7038 case 0x131: /* rdtsc */
7039 gen_update_cc_op(s);
7040 gen_jmp_im(pc_start - s->cs_base);
7041 if (s->tb->cflags & CF_USE_ICOUNT) {
7042 gen_io_start();
7044 gen_helper_rdtsc(cpu_env);
7045 if (s->tb->cflags & CF_USE_ICOUNT) {
7046 gen_io_end();
7047 gen_jmp(s, s->pc - s->cs_base);
7049 break;
7050 case 0x133: /* rdpmc */
7051 gen_update_cc_op(s);
7052 gen_jmp_im(pc_start - s->cs_base);
7053 gen_helper_rdpmc(cpu_env);
7054 break;
7055 case 0x134: /* sysenter */
7056 /* For Intel SYSENTER is valid on 64-bit */
7057 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7058 goto illegal_op;
7059 if (!s->pe) {
7060 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7061 } else {
7062 gen_helper_sysenter(cpu_env);
7063 gen_eob(s);
7065 break;
7066 case 0x135: /* sysexit */
7067 /* For Intel SYSEXIT is valid on 64-bit */
7068 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7069 goto illegal_op;
7070 if (!s->pe) {
7071 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7072 } else {
7073 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7074 gen_eob(s);
7076 break;
7077 #ifdef TARGET_X86_64
7078 case 0x105: /* syscall */
7079 /* XXX: is it usable in real mode ? */
7080 gen_update_cc_op(s);
7081 gen_jmp_im(pc_start - s->cs_base);
7082 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7083 gen_eob(s);
7084 break;
7085 case 0x107: /* sysret */
7086 if (!s->pe) {
7087 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7088 } else {
7089 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7090 /* condition codes are modified only in long mode */
7091 if (s->lma) {
7092 set_cc_op(s, CC_OP_EFLAGS);
7094 gen_eob(s);
7096 break;
7097 #endif
7098 case 0x1a2: /* cpuid */
7099 gen_update_cc_op(s);
7100 gen_jmp_im(pc_start - s->cs_base);
7101 gen_helper_cpuid(cpu_env);
7102 break;
7103 case 0xf4: /* hlt */
7104 if (s->cpl != 0) {
7105 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7106 } else {
7107 gen_update_cc_op(s);
7108 gen_jmp_im(pc_start - s->cs_base);
7109 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7110 s->is_jmp = DISAS_TB_JUMP;
7112 break;
7113 case 0x100:
7114 modrm = cpu_ldub_code(env, s->pc++);
7115 mod = (modrm >> 6) & 3;
7116 op = (modrm >> 3) & 7;
7117 switch(op) {
7118 case 0: /* sldt */
7119 if (!s->pe || s->vm86)
7120 goto illegal_op;
7121 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7122 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
7123 ot = mod == 3 ? dflag : MO_16;
7124 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7125 break;
7126 case 2: /* lldt */
7127 if (!s->pe || s->vm86)
7128 goto illegal_op;
7129 if (s->cpl != 0) {
7130 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7131 } else {
7132 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7133 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7134 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7135 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7137 break;
7138 case 1: /* str */
7139 if (!s->pe || s->vm86)
7140 goto illegal_op;
7141 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7142 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
7143 ot = mod == 3 ? dflag : MO_16;
7144 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7145 break;
7146 case 3: /* ltr */
7147 if (!s->pe || s->vm86)
7148 goto illegal_op;
7149 if (s->cpl != 0) {
7150 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7151 } else {
7152 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7153 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7154 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7155 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7157 break;
7158 case 4: /* verr */
7159 case 5: /* verw */
7160 if (!s->pe || s->vm86)
7161 goto illegal_op;
7162 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7163 gen_update_cc_op(s);
7164 if (op == 4) {
7165 gen_helper_verr(cpu_env, cpu_T[0]);
7166 } else {
7167 gen_helper_verw(cpu_env, cpu_T[0]);
7169 set_cc_op(s, CC_OP_EFLAGS);
7170 break;
7171 default:
7172 goto illegal_op;
7174 break;
7175 case 0x101:
7176 modrm = cpu_ldub_code(env, s->pc++);
7177 mod = (modrm >> 6) & 3;
7178 op = (modrm >> 3) & 7;
7179 rm = modrm & 7;
7180 switch(op) {
7181 case 0: /* sgdt */
7182 if (mod == 3)
7183 goto illegal_op;
7184 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7185 gen_lea_modrm(env, s, modrm);
7186 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
7187 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
7188 gen_add_A0_im(s, 2);
7189 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
7190 if (dflag == MO_16) {
7191 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7193 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7194 break;
7195 case 1:
7196 if (mod == 3) {
7197 switch (rm) {
7198 case 0: /* monitor */
7199 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7200 s->cpl != 0)
7201 goto illegal_op;
7202 gen_update_cc_op(s);
7203 gen_jmp_im(pc_start - s->cs_base);
7204 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7205 gen_extu(s->aflag, cpu_A0);
7206 gen_add_A0_ds_seg(s);
7207 gen_helper_monitor(cpu_env, cpu_A0);
7208 break;
7209 case 1: /* mwait */
7210 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7211 s->cpl != 0)
7212 goto illegal_op;
7213 gen_update_cc_op(s);
7214 gen_jmp_im(pc_start - s->cs_base);
7215 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7216 gen_eob(s);
7217 break;
7218 case 2: /* clac */
7219 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7220 s->cpl != 0) {
7221 goto illegal_op;
7223 gen_helper_clac(cpu_env);
7224 gen_jmp_im(s->pc - s->cs_base);
7225 gen_eob(s);
7226 break;
7227 case 3: /* stac */
7228 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7229 s->cpl != 0) {
7230 goto illegal_op;
7232 gen_helper_stac(cpu_env);
7233 gen_jmp_im(s->pc - s->cs_base);
7234 gen_eob(s);
7235 break;
7236 default:
7237 goto illegal_op;
7239 } else { /* sidt */
7240 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7241 gen_lea_modrm(env, s, modrm);
7242 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
7243 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
7244 gen_add_A0_im(s, 2);
7245 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
7246 if (dflag == MO_16) {
7247 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7249 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7251 break;
7252 case 2: /* lgdt */
7253 case 3: /* lidt */
7254 if (mod == 3) {
7255 gen_update_cc_op(s);
7256 gen_jmp_im(pc_start - s->cs_base);
7257 switch(rm) {
7258 case 0: /* VMRUN */
7259 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7260 goto illegal_op;
7261 if (s->cpl != 0) {
7262 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7263 break;
7264 } else {
7265 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7266 tcg_const_i32(s->pc - pc_start));
7267 tcg_gen_exit_tb(0);
7268 s->is_jmp = DISAS_TB_JUMP;
7270 break;
7271 case 1: /* VMMCALL */
7272 if (!(s->flags & HF_SVME_MASK))
7273 goto illegal_op;
7274 gen_helper_vmmcall(cpu_env);
7275 break;
7276 case 2: /* VMLOAD */
7277 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7278 goto illegal_op;
7279 if (s->cpl != 0) {
7280 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7281 break;
7282 } else {
7283 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7285 break;
7286 case 3: /* VMSAVE */
7287 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7288 goto illegal_op;
7289 if (s->cpl != 0) {
7290 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7291 break;
7292 } else {
7293 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7295 break;
7296 case 4: /* STGI */
7297 if ((!(s->flags & HF_SVME_MASK) &&
7298 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7299 !s->pe)
7300 goto illegal_op;
7301 if (s->cpl != 0) {
7302 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7303 break;
7304 } else {
7305 gen_helper_stgi(cpu_env);
7307 break;
7308 case 5: /* CLGI */
7309 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7310 goto illegal_op;
7311 if (s->cpl != 0) {
7312 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7313 break;
7314 } else {
7315 gen_helper_clgi(cpu_env);
7317 break;
7318 case 6: /* SKINIT */
7319 if ((!(s->flags & HF_SVME_MASK) &&
7320 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7321 !s->pe)
7322 goto illegal_op;
7323 gen_helper_skinit(cpu_env);
7324 break;
7325 case 7: /* INVLPGA */
7326 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7327 goto illegal_op;
7328 if (s->cpl != 0) {
7329 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7330 break;
7331 } else {
7332 gen_helper_invlpga(cpu_env,
7333 tcg_const_i32(s->aflag - 1));
7335 break;
7336 default:
7337 goto illegal_op;
7339 } else if (s->cpl != 0) {
7340 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7341 } else {
7342 gen_svm_check_intercept(s, pc_start,
7343 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
7344 gen_lea_modrm(env, s, modrm);
7345 gen_op_ld_v(s, MO_16, cpu_T[1], cpu_A0);
7346 gen_add_A0_im(s, 2);
7347 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7348 if (dflag == MO_16) {
7349 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7351 if (op == 2) {
7352 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7353 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
7354 } else {
7355 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7356 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
7359 break;
7360 case 4: /* smsw */
7361 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7362 #if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
7363 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7364 #else
7365 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
7366 #endif
7367 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 1);
7368 break;
7369 case 6: /* lmsw */
7370 if (s->cpl != 0) {
7371 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7372 } else {
7373 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7374 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7375 gen_helper_lmsw(cpu_env, cpu_T[0]);
7376 gen_jmp_im(s->pc - s->cs_base);
7377 gen_eob(s);
7379 break;
7380 case 7:
7381 if (mod != 3) { /* invlpg */
7382 if (s->cpl != 0) {
7383 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7384 } else {
7385 gen_update_cc_op(s);
7386 gen_jmp_im(pc_start - s->cs_base);
7387 gen_lea_modrm(env, s, modrm);
7388 gen_helper_invlpg(cpu_env, cpu_A0);
7389 gen_jmp_im(s->pc - s->cs_base);
7390 gen_eob(s);
7392 } else {
7393 switch (rm) {
7394 case 0: /* swapgs */
7395 #ifdef TARGET_X86_64
7396 if (CODE64(s)) {
7397 if (s->cpl != 0) {
7398 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7399 } else {
7400 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7401 offsetof(CPUX86State,segs[R_GS].base));
7402 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7403 offsetof(CPUX86State,kernelgsbase));
7404 tcg_gen_st_tl(cpu_T[1], cpu_env,
7405 offsetof(CPUX86State,segs[R_GS].base));
7406 tcg_gen_st_tl(cpu_T[0], cpu_env,
7407 offsetof(CPUX86State,kernelgsbase));
7409 } else
7410 #endif
7412 goto illegal_op;
7414 break;
7415 case 1: /* rdtscp */
7416 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7417 goto illegal_op;
7418 gen_update_cc_op(s);
7419 gen_jmp_im(pc_start - s->cs_base);
7420 if (s->tb->cflags & CF_USE_ICOUNT) {
7421 gen_io_start();
7423 gen_helper_rdtscp(cpu_env);
7424 if (s->tb->cflags & CF_USE_ICOUNT) {
7425 gen_io_end();
7426 gen_jmp(s, s->pc - s->cs_base);
7428 break;
7429 default:
7430 goto illegal_op;
7433 break;
7434 default:
7435 goto illegal_op;
7437 break;
7438 case 0x108: /* invd */
7439 case 0x109: /* wbinvd */
7440 if (s->cpl != 0) {
7441 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7442 } else {
7443 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7444 /* nothing to do */
7446 break;
7447 case 0x63: /* arpl or movslS (x86_64) */
7448 #ifdef TARGET_X86_64
7449 if (CODE64(s)) {
7450 int d_ot;
7451 /* d_ot is the size of destination */
7452 d_ot = dflag;
7454 modrm = cpu_ldub_code(env, s->pc++);
7455 reg = ((modrm >> 3) & 7) | rex_r;
7456 mod = (modrm >> 6) & 3;
7457 rm = (modrm & 7) | REX_B(s);
7459 if (mod == 3) {
7460 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
7461 /* sign extend */
7462 if (d_ot == MO_64) {
7463 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
7465 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
7466 } else {
7467 gen_lea_modrm(env, s, modrm);
7468 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
7469 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
7471 } else
7472 #endif
7474 TCGLabel *label1;
7475 TCGv t0, t1, t2, a0;
7477 if (!s->pe || s->vm86)
7478 goto illegal_op;
7479 t0 = tcg_temp_local_new();
7480 t1 = tcg_temp_local_new();
7481 t2 = tcg_temp_local_new();
7482 ot = MO_16;
7483 modrm = cpu_ldub_code(env, s->pc++);
7484 reg = (modrm >> 3) & 7;
7485 mod = (modrm >> 6) & 3;
7486 rm = modrm & 7;
7487 if (mod != 3) {
7488 gen_lea_modrm(env, s, modrm);
7489 gen_op_ld_v(s, ot, t0, cpu_A0);
7490 a0 = tcg_temp_local_new();
7491 tcg_gen_mov_tl(a0, cpu_A0);
7492 } else {
7493 gen_op_mov_v_reg(ot, t0, rm);
7494 TCGV_UNUSED(a0);
7496 gen_op_mov_v_reg(ot, t1, reg);
7497 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7498 tcg_gen_andi_tl(t1, t1, 3);
7499 tcg_gen_movi_tl(t2, 0);
7500 label1 = gen_new_label();
7501 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7502 tcg_gen_andi_tl(t0, t0, ~3);
7503 tcg_gen_or_tl(t0, t0, t1);
7504 tcg_gen_movi_tl(t2, CC_Z);
7505 gen_set_label(label1);
7506 if (mod != 3) {
7507 gen_op_st_v(s, ot, t0, a0);
7508 tcg_temp_free(a0);
7509 } else {
7510 gen_op_mov_reg_v(ot, rm, t0);
7512 gen_compute_eflags(s);
7513 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7514 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7515 tcg_temp_free(t0);
7516 tcg_temp_free(t1);
7517 tcg_temp_free(t2);
7519 break;
7520 case 0x102: /* lar */
7521 case 0x103: /* lsl */
7523 TCGLabel *label1;
7524 TCGv t0;
7525 if (!s->pe || s->vm86)
7526 goto illegal_op;
7527 ot = dflag != MO_16 ? MO_32 : MO_16;
7528 modrm = cpu_ldub_code(env, s->pc++);
7529 reg = ((modrm >> 3) & 7) | rex_r;
7530 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7531 t0 = tcg_temp_local_new();
7532 gen_update_cc_op(s);
7533 if (b == 0x102) {
7534 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7535 } else {
7536 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7538 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7539 label1 = gen_new_label();
7540 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7541 gen_op_mov_reg_v(ot, reg, t0);
7542 gen_set_label(label1);
7543 set_cc_op(s, CC_OP_EFLAGS);
7544 tcg_temp_free(t0);
7546 break;
7547 case 0x118:
7548 modrm = cpu_ldub_code(env, s->pc++);
7549 mod = (modrm >> 6) & 3;
7550 op = (modrm >> 3) & 7;
7551 switch(op) {
7552 case 0: /* prefetchnta */
7553 case 1: /* prefetchnt0 */
7554 case 2: /* prefetchnt0 */
7555 case 3: /* prefetchnt0 */
7556 if (mod == 3)
7557 goto illegal_op;
7558 gen_lea_modrm(env, s, modrm);
7559 /* nothing more to do */
7560 break;
7561 default: /* nop (multi byte) */
7562 gen_nop_modrm(env, s, modrm);
7563 break;
7565 break;
7566 case 0x119 ... 0x11f: /* nop (multi byte) */
7567 modrm = cpu_ldub_code(env, s->pc++);
7568 gen_nop_modrm(env, s, modrm);
7569 break;
7570 case 0x120: /* mov reg, crN */
7571 case 0x122: /* mov crN, reg */
7572 if (s->cpl != 0) {
7573 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7574 } else {
7575 modrm = cpu_ldub_code(env, s->pc++);
7576 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7577 * AMD documentation (24594.pdf) and testing of
7578 * intel 386 and 486 processors all show that the mod bits
7579 * are assumed to be 1's, regardless of actual values.
7581 rm = (modrm & 7) | REX_B(s);
7582 reg = ((modrm >> 3) & 7) | rex_r;
7583 if (CODE64(s))
7584 ot = MO_64;
7585 else
7586 ot = MO_32;
7587 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7588 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7589 reg = 8;
7591 switch(reg) {
7592 case 0:
7593 case 2:
7594 case 3:
7595 case 4:
7596 case 8:
7597 gen_update_cc_op(s);
7598 gen_jmp_im(pc_start - s->cs_base);
7599 if (b & 2) {
7600 gen_op_mov_v_reg(ot, cpu_T[0], rm);
7601 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7602 cpu_T[0]);
7603 gen_jmp_im(s->pc - s->cs_base);
7604 gen_eob(s);
7605 } else {
7606 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
7607 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
7609 break;
7610 default:
7611 goto illegal_op;
7614 break;
7615 case 0x121: /* mov reg, drN */
7616 case 0x123: /* mov drN, reg */
7617 if (s->cpl != 0) {
7618 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7619 } else {
7620 modrm = cpu_ldub_code(env, s->pc++);
7621 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7622 * AMD documentation (24594.pdf) and testing of
7623 * intel 386 and 486 processors all show that the mod bits
7624 * are assumed to be 1's, regardless of actual values.
7626 rm = (modrm & 7) | REX_B(s);
7627 reg = ((modrm >> 3) & 7) | rex_r;
7628 if (CODE64(s))
7629 ot = MO_64;
7630 else
7631 ot = MO_32;
7632 if (reg >= 8) {
7633 goto illegal_op;
7635 if (b & 2) {
7636 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7637 gen_op_mov_v_reg(ot, cpu_T[0], rm);
7638 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7639 gen_helper_set_dr(cpu_env, cpu_tmp2_i32, cpu_T[0]);
7640 gen_jmp_im(s->pc - s->cs_base);
7641 gen_eob(s);
7642 } else {
7643 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7644 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7645 gen_helper_get_dr(cpu_T[0], cpu_env, cpu_tmp2_i32);
7646 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
7649 break;
7650 case 0x106: /* clts */
7651 if (s->cpl != 0) {
7652 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7653 } else {
7654 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7655 gen_helper_clts(cpu_env);
7656 /* abort block because static cpu state changed */
7657 gen_jmp_im(s->pc - s->cs_base);
7658 gen_eob(s);
7660 break;
7661 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
7662 case 0x1c3: /* MOVNTI reg, mem */
7663 if (!(s->cpuid_features & CPUID_SSE2))
7664 goto illegal_op;
7665 ot = mo_64_32(dflag);
7666 modrm = cpu_ldub_code(env, s->pc++);
7667 mod = (modrm >> 6) & 3;
7668 if (mod == 3)
7669 goto illegal_op;
7670 reg = ((modrm >> 3) & 7) | rex_r;
7671 /* generate a generic store */
7672 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
7673 break;
7674 case 0x1ae:
7675 modrm = cpu_ldub_code(env, s->pc++);
7676 mod = (modrm >> 6) & 3;
7677 op = (modrm >> 3) & 7;
7678 switch(op) {
7679 case 0: /* fxsave */
7680 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7681 (s->prefix & PREFIX_LOCK))
7682 goto illegal_op;
7683 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7684 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7685 break;
7687 gen_lea_modrm(env, s, modrm);
7688 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
7689 break;
7690 case 1: /* fxrstor */
7691 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7692 (s->prefix & PREFIX_LOCK))
7693 goto illegal_op;
7694 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7695 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7696 break;
7698 gen_lea_modrm(env, s, modrm);
7699 gen_helper_fxrstor(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
7700 break;
7701 case 2: /* ldmxcsr */
7702 case 3: /* stmxcsr */
7703 if (s->flags & HF_TS_MASK) {
7704 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7705 break;
7707 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7708 mod == 3)
7709 goto illegal_op;
7710 gen_lea_modrm(env, s, modrm);
7711 if (op == 2) {
7712 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
7713 s->mem_index, MO_LEUL);
7714 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
7715 } else {
7716 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
7717 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
7719 break;
7720 case 5: /* lfence */
7721 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
7722 goto illegal_op;
7723 break;
7724 case 6: /* mfence/clwb */
7725 if (s->prefix & PREFIX_DATA) {
7726 /* clwb */
7727 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB))
7728 goto illegal_op;
7729 gen_nop_modrm(env, s, modrm);
7730 } else {
7731 /* mfence */
7732 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
7733 goto illegal_op;
7735 break;
7736 case 7: /* sfence / clflush / clflushopt / pcommit */
7737 if ((modrm & 0xc7) == 0xc0) {
7738 if (s->prefix & PREFIX_DATA) {
7739 /* pcommit */
7740 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT))
7741 goto illegal_op;
7742 } else {
7743 /* sfence */
7744 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
7745 if (!(s->cpuid_features & CPUID_SSE))
7746 goto illegal_op;
7748 } else {
7749 if (s->prefix & PREFIX_DATA) {
7750 /* clflushopt */
7751 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT))
7752 goto illegal_op;
7753 } else {
7754 /* clflush */
7755 if (!(s->cpuid_features & CPUID_CLFLUSH))
7756 goto illegal_op;
7758 gen_lea_modrm(env, s, modrm);
7760 break;
7761 default:
7762 goto illegal_op;
7764 break;
7765 case 0x10d: /* 3DNow! prefetch(w) */
7766 modrm = cpu_ldub_code(env, s->pc++);
7767 mod = (modrm >> 6) & 3;
7768 if (mod == 3)
7769 goto illegal_op;
7770 gen_lea_modrm(env, s, modrm);
7771 /* ignore for now */
7772 break;
7773 case 0x1aa: /* rsm */
7774 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
7775 if (!(s->flags & HF_SMM_MASK))
7776 goto illegal_op;
7777 gen_update_cc_op(s);
7778 gen_jmp_im(s->pc - s->cs_base);
7779 gen_helper_rsm(cpu_env);
7780 gen_eob(s);
7781 break;
7782 case 0x1b8: /* SSE4.2 popcnt */
7783 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
7784 PREFIX_REPZ)
7785 goto illegal_op;
7786 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
7787 goto illegal_op;
7789 modrm = cpu_ldub_code(env, s->pc++);
7790 reg = ((modrm >> 3) & 7) | rex_r;
7792 if (s->prefix & PREFIX_DATA) {
7793 ot = MO_16;
7794 } else {
7795 ot = mo_64_32(dflag);
7798 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7799 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
7800 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
7802 set_cc_op(s, CC_OP_EFLAGS);
7803 break;
7804 case 0x10e ... 0x10f:
7805 /* 3DNow! instructions, ignore prefixes */
7806 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
7807 case 0x110 ... 0x117:
7808 case 0x128 ... 0x12f:
7809 case 0x138 ... 0x13a:
7810 case 0x150 ... 0x179:
7811 case 0x17c ... 0x17f:
7812 case 0x1c2:
7813 case 0x1c4 ... 0x1c6:
7814 case 0x1d0 ... 0x1fe:
7815 gen_sse(env, s, b, pc_start, rex_r);
7816 break;
7817 default:
7818 goto illegal_op;
7820 /* lock generation */
7821 if (s->prefix & PREFIX_LOCK)
7822 gen_helper_unlock();
7823 return s->pc;
7824 illegal_op:
7825 if (s->prefix & PREFIX_LOCK)
7826 gen_helper_unlock();
7827 /* XXX: ensure that no lock was generated */
7828 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7829 return s->pc;
7832 void optimize_flags_init(void)
7834 static const char reg_names[CPU_NB_REGS][4] = {
7835 #ifdef TARGET_X86_64
7836 [R_EAX] = "rax",
7837 [R_EBX] = "rbx",
7838 [R_ECX] = "rcx",
7839 [R_EDX] = "rdx",
7840 [R_ESI] = "rsi",
7841 [R_EDI] = "rdi",
7842 [R_EBP] = "rbp",
7843 [R_ESP] = "rsp",
7844 [8] = "r8",
7845 [9] = "r9",
7846 [10] = "r10",
7847 [11] = "r11",
7848 [12] = "r12",
7849 [13] = "r13",
7850 [14] = "r14",
7851 [15] = "r15",
7852 #else
7853 [R_EAX] = "eax",
7854 [R_EBX] = "ebx",
7855 [R_ECX] = "ecx",
7856 [R_EDX] = "edx",
7857 [R_ESI] = "esi",
7858 [R_EDI] = "edi",
7859 [R_EBP] = "ebp",
7860 [R_ESP] = "esp",
7861 #endif
7863 int i;
7865 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7866 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
7867 offsetof(CPUX86State, cc_op), "cc_op");
7868 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
7869 "cc_dst");
7870 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
7871 "cc_src");
7872 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
7873 "cc_src2");
7875 for (i = 0; i < CPU_NB_REGS; ++i) {
7876 cpu_regs[i] = tcg_global_mem_new(TCG_AREG0,
7877 offsetof(CPUX86State, regs[i]),
7878 reg_names[i]);
7881 helper_lock_init();
7884 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7885 basic block 'tb'. */
7886 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
7888 X86CPU *cpu = x86_env_get_cpu(env);
7889 CPUState *cs = CPU(cpu);
7890 DisasContext dc1, *dc = &dc1;
7891 target_ulong pc_ptr;
7892 uint64_t flags;
7893 target_ulong pc_start;
7894 target_ulong cs_base;
7895 int num_insns;
7896 int max_insns;
7898 /* generate intermediate code */
7899 pc_start = tb->pc;
7900 cs_base = tb->cs_base;
7901 flags = tb->flags;
7903 dc->pe = (flags >> HF_PE_SHIFT) & 1;
7904 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7905 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7906 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7907 dc->f_st = 0;
7908 dc->vm86 = (flags >> VM_SHIFT) & 1;
7909 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7910 dc->iopl = (flags >> IOPL_SHIFT) & 3;
7911 dc->tf = (flags >> TF_SHIFT) & 1;
7912 dc->singlestep_enabled = cs->singlestep_enabled;
7913 dc->cc_op = CC_OP_DYNAMIC;
7914 dc->cc_op_dirty = false;
7915 dc->cs_base = cs_base;
7916 dc->tb = tb;
7917 dc->popl_esp_hack = 0;
7918 /* select memory access functions */
7919 dc->mem_index = 0;
7920 if (flags & HF_SOFTMMU_MASK) {
7921 dc->mem_index = cpu_mmu_index(env, false);
7923 dc->cpuid_features = env->features[FEAT_1_EDX];
7924 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
7925 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
7926 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
7927 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
7928 #ifdef TARGET_X86_64
7929 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7930 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7931 #endif
7932 dc->flags = flags;
7933 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
7934 (flags & HF_INHIBIT_IRQ_MASK)
7935 #ifndef CONFIG_SOFTMMU
7936 || (flags & HF_SOFTMMU_MASK)
7937 #endif
7939 /* Do not optimize repz jumps at all in icount mode, because
7940 rep movsS instructions are execured with different paths
7941 in !repz_opt and repz_opt modes. The first one was used
7942 always except single step mode. And this setting
7943 disables jumps optimization and control paths become
7944 equivalent in run and single step modes.
7945 Now there will be no jump optimization for repz in
7946 record/replay modes and there will always be an
7947 additional step for ecx=0 when icount is enabled.
7949 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
7950 #if 0
7951 /* check addseg logic */
7952 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
7953 printf("ERROR addseg\n");
7954 #endif
7956 cpu_T[0] = tcg_temp_new();
7957 cpu_T[1] = tcg_temp_new();
7958 cpu_A0 = tcg_temp_new();
7960 cpu_tmp0 = tcg_temp_new();
7961 cpu_tmp1_i64 = tcg_temp_new_i64();
7962 cpu_tmp2_i32 = tcg_temp_new_i32();
7963 cpu_tmp3_i32 = tcg_temp_new_i32();
7964 cpu_tmp4 = tcg_temp_new();
7965 cpu_ptr0 = tcg_temp_new_ptr();
7966 cpu_ptr1 = tcg_temp_new_ptr();
7967 cpu_cc_srcT = tcg_temp_local_new();
7969 dc->is_jmp = DISAS_NEXT;
7970 pc_ptr = pc_start;
7971 num_insns = 0;
7972 max_insns = tb->cflags & CF_COUNT_MASK;
7973 if (max_insns == 0) {
7974 max_insns = CF_COUNT_MASK;
7976 if (max_insns > TCG_MAX_INSNS) {
7977 max_insns = TCG_MAX_INSNS;
7980 gen_tb_start(tb);
7981 for(;;) {
7982 tcg_gen_insn_start(pc_ptr, dc->cc_op);
7983 num_insns++;
7985 /* If RF is set, suppress an internally generated breakpoint. */
7986 if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
7987 tb->flags & HF_RF_MASK
7988 ? BP_GDB : BP_ANY))) {
7989 gen_debug(dc, pc_ptr - dc->cs_base);
7990 /* The address covered by the breakpoint must be included in
7991 [tb->pc, tb->pc + tb->size) in order to for it to be
7992 properly cleared -- thus we increment the PC here so that
7993 the logic setting tb->size below does the right thing. */
7994 pc_ptr += 1;
7995 goto done_generating;
7997 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
7998 gen_io_start();
8001 pc_ptr = disas_insn(env, dc, pc_ptr);
8002 /* stop translation if indicated */
8003 if (dc->is_jmp)
8004 break;
8005 /* if single step mode, we generate only one instruction and
8006 generate an exception */
8007 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8008 the flag and abort the translation to give the irqs a
8009 change to be happen */
8010 if (dc->tf || dc->singlestep_enabled ||
8011 (flags & HF_INHIBIT_IRQ_MASK)) {
8012 gen_jmp_im(pc_ptr - dc->cs_base);
8013 gen_eob(dc);
8014 break;
8016 /* Do not cross the boundary of the pages in icount mode,
8017 it can cause an exception. Do it only when boundary is
8018 crossed by the first instruction in the block.
8019 If current instruction already crossed the bound - it's ok,
8020 because an exception hasn't stopped this code.
8022 if ((tb->cflags & CF_USE_ICOUNT)
8023 && ((pc_ptr & TARGET_PAGE_MASK)
8024 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
8025 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
8026 gen_jmp_im(pc_ptr - dc->cs_base);
8027 gen_eob(dc);
8028 break;
8030 /* if too long translation, stop generation too */
8031 if (tcg_op_buf_full() ||
8032 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8033 num_insns >= max_insns) {
8034 gen_jmp_im(pc_ptr - dc->cs_base);
8035 gen_eob(dc);
8036 break;
8038 if (singlestep) {
8039 gen_jmp_im(pc_ptr - dc->cs_base);
8040 gen_eob(dc);
8041 break;
8044 if (tb->cflags & CF_LAST_IO)
8045 gen_io_end();
8046 done_generating:
8047 gen_tb_end(tb, num_insns);
8049 #ifdef DEBUG_DISAS
8050 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8051 int disas_flags;
8052 qemu_log("----------------\n");
8053 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8054 #ifdef TARGET_X86_64
8055 if (dc->code64)
8056 disas_flags = 2;
8057 else
8058 #endif
8059 disas_flags = !dc->code32;
8060 log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
8061 qemu_log("\n");
8063 #endif
8065 tb->size = pc_ptr - pc_start;
8066 tb->icount = num_insns;
8069 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8070 target_ulong *data)
8072 int cc_op = data[1];
8073 env->eip = data[0] - tb->cs_base;
8074 if (cc_op != CC_OP_DYNAMIC) {
8075 env->cc_op = cc_op;