enable multi-function hot-add
[qemu/ar7.git] / target-i386 / translate.c
blob862f8e09fbd8dc414cb427ed81c00d7f3902e238
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_regs[s->vex_v], cpu_regs[reg],
3852 cpu_T[0], cpu_regs[R_EDX]);
3853 break;
3854 #endif
3856 break;
3858 case 0x3f5: /* pdep Gy, By, Ey */
3859 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3860 || !(s->prefix & PREFIX_VEX)
3861 || s->vex_l != 0) {
3862 goto illegal_op;
3864 ot = mo_64_32(s->dflag);
3865 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3866 /* Note that by zero-extending the mask operand, we
3867 automatically handle zero-extending the result. */
3868 if (ot == MO_64) {
3869 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3870 } else {
3871 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3873 gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3874 break;
3876 case 0x2f5: /* pext Gy, By, Ey */
3877 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3878 || !(s->prefix & PREFIX_VEX)
3879 || s->vex_l != 0) {
3880 goto illegal_op;
3882 ot = mo_64_32(s->dflag);
3883 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3884 /* Note that by zero-extending the mask operand, we
3885 automatically handle zero-extending the result. */
3886 if (ot == MO_64) {
3887 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3888 } else {
3889 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3891 gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3892 break;
3894 case 0x1f6: /* adcx Gy, Ey */
3895 case 0x2f6: /* adox Gy, Ey */
3896 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3897 goto illegal_op;
3898 } else {
3899 TCGv carry_in, carry_out, zero;
3900 int end_op;
3902 ot = mo_64_32(s->dflag);
3903 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3905 /* Re-use the carry-out from a previous round. */
3906 TCGV_UNUSED(carry_in);
3907 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3908 switch (s->cc_op) {
3909 case CC_OP_ADCX:
3910 if (b == 0x1f6) {
3911 carry_in = cpu_cc_dst;
3912 end_op = CC_OP_ADCX;
3913 } else {
3914 end_op = CC_OP_ADCOX;
3916 break;
3917 case CC_OP_ADOX:
3918 if (b == 0x1f6) {
3919 end_op = CC_OP_ADCOX;
3920 } else {
3921 carry_in = cpu_cc_src2;
3922 end_op = CC_OP_ADOX;
3924 break;
3925 case CC_OP_ADCOX:
3926 end_op = CC_OP_ADCOX;
3927 carry_in = carry_out;
3928 break;
3929 default:
3930 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
3931 break;
3933 /* If we can't reuse carry-out, get it out of EFLAGS. */
3934 if (TCGV_IS_UNUSED(carry_in)) {
3935 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3936 gen_compute_eflags(s);
3938 carry_in = cpu_tmp0;
3939 tcg_gen_shri_tl(carry_in, cpu_cc_src,
3940 ctz32(b == 0x1f6 ? CC_C : CC_O));
3941 tcg_gen_andi_tl(carry_in, carry_in, 1);
3944 switch (ot) {
3945 #ifdef TARGET_X86_64
3946 case MO_32:
3947 /* If we know TL is 64-bit, and we want a 32-bit
3948 result, just do everything in 64-bit arithmetic. */
3949 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3950 tcg_gen_ext32u_i64(cpu_T[0], cpu_T[0]);
3951 tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_regs[reg]);
3952 tcg_gen_add_i64(cpu_T[0], cpu_T[0], carry_in);
3953 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T[0]);
3954 tcg_gen_shri_i64(carry_out, cpu_T[0], 32);
3955 break;
3956 #endif
3957 default:
3958 /* Otherwise compute the carry-out in two steps. */
3959 zero = tcg_const_tl(0);
3960 tcg_gen_add2_tl(cpu_T[0], carry_out,
3961 cpu_T[0], zero,
3962 carry_in, zero);
3963 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3964 cpu_regs[reg], carry_out,
3965 cpu_T[0], zero);
3966 tcg_temp_free(zero);
3967 break;
3969 set_cc_op(s, end_op);
3971 break;
3973 case 0x1f7: /* shlx Gy, Ey, By */
3974 case 0x2f7: /* sarx Gy, Ey, By */
3975 case 0x3f7: /* shrx Gy, Ey, By */
3976 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3977 || !(s->prefix & PREFIX_VEX)
3978 || s->vex_l != 0) {
3979 goto illegal_op;
3981 ot = mo_64_32(s->dflag);
3982 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3983 if (ot == MO_64) {
3984 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
3985 } else {
3986 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
3988 if (b == 0x1f7) {
3989 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3990 } else if (b == 0x2f7) {
3991 if (ot != MO_64) {
3992 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
3994 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3995 } else {
3996 if (ot != MO_64) {
3997 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
3999 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4001 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4002 break;
4004 case 0x0f3:
4005 case 0x1f3:
4006 case 0x2f3:
4007 case 0x3f3: /* Group 17 */
4008 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4009 || !(s->prefix & PREFIX_VEX)
4010 || s->vex_l != 0) {
4011 goto illegal_op;
4013 ot = mo_64_32(s->dflag);
4014 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4016 switch (reg & 7) {
4017 case 1: /* blsr By,Ey */
4018 tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
4019 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4020 gen_op_mov_reg_v(ot, s->vex_v, cpu_T[0]);
4021 gen_op_update2_cc();
4022 set_cc_op(s, CC_OP_BMILGB + ot);
4023 break;
4025 case 2: /* blsmsk By,Ey */
4026 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4027 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4028 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4029 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4030 set_cc_op(s, CC_OP_BMILGB + ot);
4031 break;
4033 case 3: /* blsi By, Ey */
4034 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4035 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4036 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4037 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4038 set_cc_op(s, CC_OP_BMILGB + ot);
4039 break;
4041 default:
4042 goto illegal_op;
4044 break;
4046 default:
4047 goto illegal_op;
4049 break;
4051 case 0x03a:
4052 case 0x13a:
4053 b = modrm;
4054 modrm = cpu_ldub_code(env, s->pc++);
4055 rm = modrm & 7;
4056 reg = ((modrm >> 3) & 7) | rex_r;
4057 mod = (modrm >> 6) & 3;
4058 if (b1 >= 2) {
4059 goto illegal_op;
4062 sse_fn_eppi = sse_op_table7[b].op[b1];
4063 if (!sse_fn_eppi) {
4064 goto illegal_op;
4066 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4067 goto illegal_op;
4069 if (sse_fn_eppi == SSE_SPECIAL) {
4070 ot = mo_64_32(s->dflag);
4071 rm = (modrm & 7) | REX_B(s);
4072 if (mod != 3)
4073 gen_lea_modrm(env, s, modrm);
4074 reg = ((modrm >> 3) & 7) | rex_r;
4075 val = cpu_ldub_code(env, s->pc++);
4076 switch (b) {
4077 case 0x14: /* pextrb */
4078 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4079 xmm_regs[reg].XMM_B(val & 15)));
4080 if (mod == 3) {
4081 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4082 } else {
4083 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4084 s->mem_index, MO_UB);
4086 break;
4087 case 0x15: /* pextrw */
4088 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4089 xmm_regs[reg].XMM_W(val & 7)));
4090 if (mod == 3) {
4091 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4092 } else {
4093 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4094 s->mem_index, MO_LEUW);
4096 break;
4097 case 0x16:
4098 if (ot == MO_32) { /* pextrd */
4099 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4100 offsetof(CPUX86State,
4101 xmm_regs[reg].XMM_L(val & 3)));
4102 if (mod == 3) {
4103 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
4104 } else {
4105 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4106 s->mem_index, MO_LEUL);
4108 } else { /* pextrq */
4109 #ifdef TARGET_X86_64
4110 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4111 offsetof(CPUX86State,
4112 xmm_regs[reg].XMM_Q(val & 1)));
4113 if (mod == 3) {
4114 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
4115 } else {
4116 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4117 s->mem_index, MO_LEQ);
4119 #else
4120 goto illegal_op;
4121 #endif
4123 break;
4124 case 0x17: /* extractps */
4125 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4126 xmm_regs[reg].XMM_L(val & 3)));
4127 if (mod == 3) {
4128 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4129 } else {
4130 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4131 s->mem_index, MO_LEUL);
4133 break;
4134 case 0x20: /* pinsrb */
4135 if (mod == 3) {
4136 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
4137 } else {
4138 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
4139 s->mem_index, MO_UB);
4141 tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4142 xmm_regs[reg].XMM_B(val & 15)));
4143 break;
4144 case 0x21: /* insertps */
4145 if (mod == 3) {
4146 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4147 offsetof(CPUX86State,xmm_regs[rm]
4148 .XMM_L((val >> 6) & 3)));
4149 } else {
4150 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4151 s->mem_index, MO_LEUL);
4153 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4154 offsetof(CPUX86State,xmm_regs[reg]
4155 .XMM_L((val >> 4) & 3)));
4156 if ((val >> 0) & 1)
4157 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4158 cpu_env, offsetof(CPUX86State,
4159 xmm_regs[reg].XMM_L(0)));
4160 if ((val >> 1) & 1)
4161 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4162 cpu_env, offsetof(CPUX86State,
4163 xmm_regs[reg].XMM_L(1)));
4164 if ((val >> 2) & 1)
4165 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4166 cpu_env, offsetof(CPUX86State,
4167 xmm_regs[reg].XMM_L(2)));
4168 if ((val >> 3) & 1)
4169 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4170 cpu_env, offsetof(CPUX86State,
4171 xmm_regs[reg].XMM_L(3)));
4172 break;
4173 case 0x22:
4174 if (ot == MO_32) { /* pinsrd */
4175 if (mod == 3) {
4176 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
4177 } else {
4178 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4179 s->mem_index, MO_LEUL);
4181 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4182 offsetof(CPUX86State,
4183 xmm_regs[reg].XMM_L(val & 3)));
4184 } else { /* pinsrq */
4185 #ifdef TARGET_X86_64
4186 if (mod == 3) {
4187 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4188 } else {
4189 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4190 s->mem_index, MO_LEQ);
4192 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4193 offsetof(CPUX86State,
4194 xmm_regs[reg].XMM_Q(val & 1)));
4195 #else
4196 goto illegal_op;
4197 #endif
4199 break;
4201 return;
4204 if (b1) {
4205 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4206 if (mod == 3) {
4207 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4208 } else {
4209 op2_offset = offsetof(CPUX86State,xmm_t0);
4210 gen_lea_modrm(env, s, modrm);
4211 gen_ldo_env_A0(s, op2_offset);
4213 } else {
4214 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4215 if (mod == 3) {
4216 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4217 } else {
4218 op2_offset = offsetof(CPUX86State,mmx_t0);
4219 gen_lea_modrm(env, s, modrm);
4220 gen_ldq_env_A0(s, op2_offset);
4223 val = cpu_ldub_code(env, s->pc++);
4225 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4226 set_cc_op(s, CC_OP_EFLAGS);
4228 if (s->dflag == MO_64) {
4229 /* The helper must use entire 64-bit gp registers */
4230 val |= 1 << 8;
4234 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4235 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4236 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4237 break;
4239 case 0x33a:
4240 /* Various integer extensions at 0f 3a f[0-f]. */
4241 b = modrm | (b1 << 8);
4242 modrm = cpu_ldub_code(env, s->pc++);
4243 reg = ((modrm >> 3) & 7) | rex_r;
4245 switch (b) {
4246 case 0x3f0: /* rorx Gy,Ey, Ib */
4247 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4248 || !(s->prefix & PREFIX_VEX)
4249 || s->vex_l != 0) {
4250 goto illegal_op;
4252 ot = mo_64_32(s->dflag);
4253 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4254 b = cpu_ldub_code(env, s->pc++);
4255 if (ot == MO_64) {
4256 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
4257 } else {
4258 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4259 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4260 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4262 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4263 break;
4265 default:
4266 goto illegal_op;
4268 break;
4270 default:
4271 goto illegal_op;
4273 } else {
4274 /* generic MMX or SSE operation */
4275 switch(b) {
4276 case 0x70: /* pshufx insn */
4277 case 0xc6: /* pshufx insn */
4278 case 0xc2: /* compare insns */
4279 s->rip_offset = 1;
4280 break;
4281 default:
4282 break;
4284 if (is_xmm) {
4285 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4286 if (mod != 3) {
4287 int sz = 4;
4289 gen_lea_modrm(env, s, modrm);
4290 op2_offset = offsetof(CPUX86State,xmm_t0);
4292 switch (b) {
4293 case 0x50 ... 0x5a:
4294 case 0x5c ... 0x5f:
4295 case 0xc2:
4296 /* Most sse scalar operations. */
4297 if (b1 == 2) {
4298 sz = 2;
4299 } else if (b1 == 3) {
4300 sz = 3;
4302 break;
4304 case 0x2e: /* ucomis[sd] */
4305 case 0x2f: /* comis[sd] */
4306 if (b1 == 0) {
4307 sz = 2;
4308 } else {
4309 sz = 3;
4311 break;
4314 switch (sz) {
4315 case 2:
4316 /* 32 bit access */
4317 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
4318 tcg_gen_st32_tl(cpu_T[0], cpu_env,
4319 offsetof(CPUX86State,xmm_t0.XMM_L(0)));
4320 break;
4321 case 3:
4322 /* 64 bit access */
4323 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_D(0)));
4324 break;
4325 default:
4326 /* 128 bit access */
4327 gen_ldo_env_A0(s, op2_offset);
4328 break;
4330 } else {
4331 rm = (modrm & 7) | REX_B(s);
4332 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4334 } else {
4335 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4336 if (mod != 3) {
4337 gen_lea_modrm(env, s, modrm);
4338 op2_offset = offsetof(CPUX86State,mmx_t0);
4339 gen_ldq_env_A0(s, op2_offset);
4340 } else {
4341 rm = (modrm & 7);
4342 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4345 switch(b) {
4346 case 0x0f: /* 3DNow! data insns */
4347 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4348 goto illegal_op;
4349 val = cpu_ldub_code(env, s->pc++);
4350 sse_fn_epp = sse_op_table5[val];
4351 if (!sse_fn_epp) {
4352 goto illegal_op;
4354 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4355 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4356 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4357 break;
4358 case 0x70: /* pshufx insn */
4359 case 0xc6: /* pshufx insn */
4360 val = cpu_ldub_code(env, s->pc++);
4361 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4362 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4363 /* XXX: introduce a new table? */
4364 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4365 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4366 break;
4367 case 0xc2:
4368 /* compare insns */
4369 val = cpu_ldub_code(env, s->pc++);
4370 if (val >= 8)
4371 goto illegal_op;
4372 sse_fn_epp = sse_op_table4[val][b1];
4374 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4375 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4376 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4377 break;
4378 case 0xf7:
4379 /* maskmov : we must prepare A0 */
4380 if (mod != 3)
4381 goto illegal_op;
4382 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4383 gen_extu(s->aflag, cpu_A0);
4384 gen_add_A0_ds_seg(s);
4386 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4387 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4388 /* XXX: introduce a new table? */
4389 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4390 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4391 break;
4392 default:
4393 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4394 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4395 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4396 break;
4398 if (b == 0x2e || b == 0x2f) {
4399 set_cc_op(s, CC_OP_EFLAGS);
4404 /* convert one instruction. s->is_jmp is set if the translation must
4405 be stopped. Return the next pc value */
4406 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4407 target_ulong pc_start)
4409 int b, prefixes;
4410 int shift;
4411 TCGMemOp ot, aflag, dflag;
4412 int modrm, reg, rm, mod, op, opreg, val;
4413 target_ulong next_eip, tval;
4414 int rex_w, rex_r;
4416 s->pc = pc_start;
4417 prefixes = 0;
4418 s->override = -1;
4419 rex_w = -1;
4420 rex_r = 0;
4421 #ifdef TARGET_X86_64
4422 s->rex_x = 0;
4423 s->rex_b = 0;
4424 x86_64_hregs = 0;
4425 #endif
4426 s->rip_offset = 0; /* for relative ip address */
4427 s->vex_l = 0;
4428 s->vex_v = 0;
4429 next_byte:
4430 b = cpu_ldub_code(env, s->pc);
4431 s->pc++;
4432 /* Collect prefixes. */
4433 switch (b) {
4434 case 0xf3:
4435 prefixes |= PREFIX_REPZ;
4436 goto next_byte;
4437 case 0xf2:
4438 prefixes |= PREFIX_REPNZ;
4439 goto next_byte;
4440 case 0xf0:
4441 prefixes |= PREFIX_LOCK;
4442 goto next_byte;
4443 case 0x2e:
4444 s->override = R_CS;
4445 goto next_byte;
4446 case 0x36:
4447 s->override = R_SS;
4448 goto next_byte;
4449 case 0x3e:
4450 s->override = R_DS;
4451 goto next_byte;
4452 case 0x26:
4453 s->override = R_ES;
4454 goto next_byte;
4455 case 0x64:
4456 s->override = R_FS;
4457 goto next_byte;
4458 case 0x65:
4459 s->override = R_GS;
4460 goto next_byte;
4461 case 0x66:
4462 prefixes |= PREFIX_DATA;
4463 goto next_byte;
4464 case 0x67:
4465 prefixes |= PREFIX_ADR;
4466 goto next_byte;
4467 #ifdef TARGET_X86_64
4468 case 0x40 ... 0x4f:
4469 if (CODE64(s)) {
4470 /* REX prefix */
4471 rex_w = (b >> 3) & 1;
4472 rex_r = (b & 0x4) << 1;
4473 s->rex_x = (b & 0x2) << 2;
4474 REX_B(s) = (b & 0x1) << 3;
4475 x86_64_hregs = 1; /* select uniform byte register addressing */
4476 goto next_byte;
4478 break;
4479 #endif
4480 case 0xc5: /* 2-byte VEX */
4481 case 0xc4: /* 3-byte VEX */
4482 /* VEX prefixes cannot be used except in 32-bit mode.
4483 Otherwise the instruction is LES or LDS. */
4484 if (s->code32 && !s->vm86) {
4485 static const int pp_prefix[4] = {
4486 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4488 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4490 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4491 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4492 otherwise the instruction is LES or LDS. */
4493 break;
4495 s->pc++;
4497 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4498 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4499 | PREFIX_LOCK | PREFIX_DATA)) {
4500 goto illegal_op;
4502 #ifdef TARGET_X86_64
4503 if (x86_64_hregs) {
4504 goto illegal_op;
4506 #endif
4507 rex_r = (~vex2 >> 4) & 8;
4508 if (b == 0xc5) {
4509 vex3 = vex2;
4510 b = cpu_ldub_code(env, s->pc++);
4511 } else {
4512 #ifdef TARGET_X86_64
4513 s->rex_x = (~vex2 >> 3) & 8;
4514 s->rex_b = (~vex2 >> 2) & 8;
4515 #endif
4516 vex3 = cpu_ldub_code(env, s->pc++);
4517 rex_w = (vex3 >> 7) & 1;
4518 switch (vex2 & 0x1f) {
4519 case 0x01: /* Implied 0f leading opcode bytes. */
4520 b = cpu_ldub_code(env, s->pc++) | 0x100;
4521 break;
4522 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4523 b = 0x138;
4524 break;
4525 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4526 b = 0x13a;
4527 break;
4528 default: /* Reserved for future use. */
4529 goto illegal_op;
4532 s->vex_v = (~vex3 >> 3) & 0xf;
4533 s->vex_l = (vex3 >> 2) & 1;
4534 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4536 break;
4539 /* Post-process prefixes. */
4540 if (CODE64(s)) {
4541 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4542 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4543 over 0x66 if both are present. */
4544 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4545 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4546 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4547 } else {
4548 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4549 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4550 dflag = MO_32;
4551 } else {
4552 dflag = MO_16;
4554 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4555 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4556 aflag = MO_32;
4557 } else {
4558 aflag = MO_16;
4562 s->prefix = prefixes;
4563 s->aflag = aflag;
4564 s->dflag = dflag;
4566 /* lock generation */
4567 if (prefixes & PREFIX_LOCK)
4568 gen_helper_lock();
4570 /* now check op code */
4571 reswitch:
4572 switch(b) {
4573 case 0x0f:
4574 /**************************/
4575 /* extended op code */
4576 b = cpu_ldub_code(env, s->pc++) | 0x100;
4577 goto reswitch;
4579 /**************************/
4580 /* arith & logic */
4581 case 0x00 ... 0x05:
4582 case 0x08 ... 0x0d:
4583 case 0x10 ... 0x15:
4584 case 0x18 ... 0x1d:
4585 case 0x20 ... 0x25:
4586 case 0x28 ... 0x2d:
4587 case 0x30 ... 0x35:
4588 case 0x38 ... 0x3d:
4590 int op, f, val;
4591 op = (b >> 3) & 7;
4592 f = (b >> 1) & 3;
4594 ot = mo_b_d(b, dflag);
4596 switch(f) {
4597 case 0: /* OP Ev, Gv */
4598 modrm = cpu_ldub_code(env, s->pc++);
4599 reg = ((modrm >> 3) & 7) | rex_r;
4600 mod = (modrm >> 6) & 3;
4601 rm = (modrm & 7) | REX_B(s);
4602 if (mod != 3) {
4603 gen_lea_modrm(env, s, modrm);
4604 opreg = OR_TMP0;
4605 } else if (op == OP_XORL && rm == reg) {
4606 xor_zero:
4607 /* xor reg, reg optimisation */
4608 set_cc_op(s, CC_OP_CLR);
4609 tcg_gen_movi_tl(cpu_T[0], 0);
4610 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4611 break;
4612 } else {
4613 opreg = rm;
4615 gen_op_mov_v_reg(ot, cpu_T[1], reg);
4616 gen_op(s, op, ot, opreg);
4617 break;
4618 case 1: /* OP Gv, Ev */
4619 modrm = cpu_ldub_code(env, s->pc++);
4620 mod = (modrm >> 6) & 3;
4621 reg = ((modrm >> 3) & 7) | rex_r;
4622 rm = (modrm & 7) | REX_B(s);
4623 if (mod != 3) {
4624 gen_lea_modrm(env, s, modrm);
4625 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4626 } else if (op == OP_XORL && rm == reg) {
4627 goto xor_zero;
4628 } else {
4629 gen_op_mov_v_reg(ot, cpu_T[1], rm);
4631 gen_op(s, op, ot, reg);
4632 break;
4633 case 2: /* OP A, Iv */
4634 val = insn_get(env, s, ot);
4635 tcg_gen_movi_tl(cpu_T[1], val);
4636 gen_op(s, op, ot, OR_EAX);
4637 break;
4640 break;
4642 case 0x82:
4643 if (CODE64(s))
4644 goto illegal_op;
4645 case 0x80: /* GRP1 */
4646 case 0x81:
4647 case 0x83:
4649 int val;
4651 ot = mo_b_d(b, dflag);
4653 modrm = cpu_ldub_code(env, s->pc++);
4654 mod = (modrm >> 6) & 3;
4655 rm = (modrm & 7) | REX_B(s);
4656 op = (modrm >> 3) & 7;
4658 if (mod != 3) {
4659 if (b == 0x83)
4660 s->rip_offset = 1;
4661 else
4662 s->rip_offset = insn_const_size(ot);
4663 gen_lea_modrm(env, s, modrm);
4664 opreg = OR_TMP0;
4665 } else {
4666 opreg = rm;
4669 switch(b) {
4670 default:
4671 case 0x80:
4672 case 0x81:
4673 case 0x82:
4674 val = insn_get(env, s, ot);
4675 break;
4676 case 0x83:
4677 val = (int8_t)insn_get(env, s, MO_8);
4678 break;
4680 tcg_gen_movi_tl(cpu_T[1], val);
4681 gen_op(s, op, ot, opreg);
4683 break;
4685 /**************************/
4686 /* inc, dec, and other misc arith */
4687 case 0x40 ... 0x47: /* inc Gv */
4688 ot = dflag;
4689 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4690 break;
4691 case 0x48 ... 0x4f: /* dec Gv */
4692 ot = dflag;
4693 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4694 break;
4695 case 0xf6: /* GRP3 */
4696 case 0xf7:
4697 ot = mo_b_d(b, dflag);
4699 modrm = cpu_ldub_code(env, s->pc++);
4700 mod = (modrm >> 6) & 3;
4701 rm = (modrm & 7) | REX_B(s);
4702 op = (modrm >> 3) & 7;
4703 if (mod != 3) {
4704 if (op == 0)
4705 s->rip_offset = insn_const_size(ot);
4706 gen_lea_modrm(env, s, modrm);
4707 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
4708 } else {
4709 gen_op_mov_v_reg(ot, cpu_T[0], rm);
4712 switch(op) {
4713 case 0: /* test */
4714 val = insn_get(env, s, ot);
4715 tcg_gen_movi_tl(cpu_T[1], val);
4716 gen_op_testl_T0_T1_cc();
4717 set_cc_op(s, CC_OP_LOGICB + ot);
4718 break;
4719 case 2: /* not */
4720 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
4721 if (mod != 3) {
4722 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
4723 } else {
4724 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4726 break;
4727 case 3: /* neg */
4728 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
4729 if (mod != 3) {
4730 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
4731 } else {
4732 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4734 gen_op_update_neg_cc();
4735 set_cc_op(s, CC_OP_SUBB + ot);
4736 break;
4737 case 4: /* mul */
4738 switch(ot) {
4739 case MO_8:
4740 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
4741 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4742 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4743 /* XXX: use 32 bit mul which could be faster */
4744 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4745 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4746 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4747 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
4748 set_cc_op(s, CC_OP_MULB);
4749 break;
4750 case MO_16:
4751 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
4752 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4753 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4754 /* XXX: use 32 bit mul which could be faster */
4755 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4756 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4757 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4758 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4759 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
4760 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4761 set_cc_op(s, CC_OP_MULW);
4762 break;
4763 default:
4764 case MO_32:
4765 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4766 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4767 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4768 cpu_tmp2_i32, cpu_tmp3_i32);
4769 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4770 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4771 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4772 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4773 set_cc_op(s, CC_OP_MULL);
4774 break;
4775 #ifdef TARGET_X86_64
4776 case MO_64:
4777 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4778 cpu_T[0], cpu_regs[R_EAX]);
4779 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4780 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4781 set_cc_op(s, CC_OP_MULQ);
4782 break;
4783 #endif
4785 break;
4786 case 5: /* imul */
4787 switch(ot) {
4788 case MO_8:
4789 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
4790 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4791 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
4792 /* XXX: use 32 bit mul which could be faster */
4793 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4794 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4795 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4796 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
4797 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4798 set_cc_op(s, CC_OP_MULB);
4799 break;
4800 case MO_16:
4801 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
4802 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4803 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4804 /* XXX: use 32 bit mul which could be faster */
4805 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4806 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
4807 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4808 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4809 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4810 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4811 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
4812 set_cc_op(s, CC_OP_MULW);
4813 break;
4814 default:
4815 case MO_32:
4816 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4817 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4818 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4819 cpu_tmp2_i32, cpu_tmp3_i32);
4820 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4821 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4822 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4823 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4824 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4825 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
4826 set_cc_op(s, CC_OP_MULL);
4827 break;
4828 #ifdef TARGET_X86_64
4829 case MO_64:
4830 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4831 cpu_T[0], cpu_regs[R_EAX]);
4832 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4833 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4834 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4835 set_cc_op(s, CC_OP_MULQ);
4836 break;
4837 #endif
4839 break;
4840 case 6: /* div */
4841 switch(ot) {
4842 case MO_8:
4843 gen_helper_divb_AL(cpu_env, cpu_T[0]);
4844 break;
4845 case MO_16:
4846 gen_helper_divw_AX(cpu_env, cpu_T[0]);
4847 break;
4848 default:
4849 case MO_32:
4850 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
4851 break;
4852 #ifdef TARGET_X86_64
4853 case MO_64:
4854 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
4855 break;
4856 #endif
4858 break;
4859 case 7: /* idiv */
4860 switch(ot) {
4861 case MO_8:
4862 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
4863 break;
4864 case MO_16:
4865 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
4866 break;
4867 default:
4868 case MO_32:
4869 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
4870 break;
4871 #ifdef TARGET_X86_64
4872 case MO_64:
4873 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
4874 break;
4875 #endif
4877 break;
4878 default:
4879 goto illegal_op;
4881 break;
4883 case 0xfe: /* GRP4 */
4884 case 0xff: /* GRP5 */
4885 ot = mo_b_d(b, dflag);
4887 modrm = cpu_ldub_code(env, s->pc++);
4888 mod = (modrm >> 6) & 3;
4889 rm = (modrm & 7) | REX_B(s);
4890 op = (modrm >> 3) & 7;
4891 if (op >= 2 && b == 0xfe) {
4892 goto illegal_op;
4894 if (CODE64(s)) {
4895 if (op == 2 || op == 4) {
4896 /* operand size for jumps is 64 bit */
4897 ot = MO_64;
4898 } else if (op == 3 || op == 5) {
4899 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
4900 } else if (op == 6) {
4901 /* default push size is 64 bit */
4902 ot = mo_pushpop(s, dflag);
4905 if (mod != 3) {
4906 gen_lea_modrm(env, s, modrm);
4907 if (op >= 2 && op != 3 && op != 5)
4908 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
4909 } else {
4910 gen_op_mov_v_reg(ot, cpu_T[0], rm);
4913 switch(op) {
4914 case 0: /* inc Ev */
4915 if (mod != 3)
4916 opreg = OR_TMP0;
4917 else
4918 opreg = rm;
4919 gen_inc(s, ot, opreg, 1);
4920 break;
4921 case 1: /* dec Ev */
4922 if (mod != 3)
4923 opreg = OR_TMP0;
4924 else
4925 opreg = rm;
4926 gen_inc(s, ot, opreg, -1);
4927 break;
4928 case 2: /* call Ev */
4929 /* XXX: optimize if memory (no 'and' is necessary) */
4930 if (dflag == MO_16) {
4931 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4933 next_eip = s->pc - s->cs_base;
4934 tcg_gen_movi_tl(cpu_T[1], next_eip);
4935 gen_push_v(s, cpu_T[1]);
4936 gen_op_jmp_v(cpu_T[0]);
4937 gen_eob(s);
4938 break;
4939 case 3: /* lcall Ev */
4940 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4941 gen_add_A0_im(s, 1 << ot);
4942 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
4943 do_lcall:
4944 if (s->pe && !s->vm86) {
4945 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4946 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4947 tcg_const_i32(dflag - 1),
4948 tcg_const_tl(s->pc - s->cs_base));
4949 } else {
4950 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4951 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
4952 tcg_const_i32(dflag - 1),
4953 tcg_const_i32(s->pc - s->cs_base));
4955 gen_eob(s);
4956 break;
4957 case 4: /* jmp Ev */
4958 if (dflag == MO_16) {
4959 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4961 gen_op_jmp_v(cpu_T[0]);
4962 gen_eob(s);
4963 break;
4964 case 5: /* ljmp Ev */
4965 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
4966 gen_add_A0_im(s, 1 << ot);
4967 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
4968 do_ljmp:
4969 if (s->pe && !s->vm86) {
4970 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4971 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4972 tcg_const_tl(s->pc - s->cs_base));
4973 } else {
4974 gen_op_movl_seg_T0_vm(R_CS);
4975 gen_op_jmp_v(cpu_T[1]);
4977 gen_eob(s);
4978 break;
4979 case 6: /* push Ev */
4980 gen_push_v(s, cpu_T[0]);
4981 break;
4982 default:
4983 goto illegal_op;
4985 break;
4987 case 0x84: /* test Ev, Gv */
4988 case 0x85:
4989 ot = mo_b_d(b, dflag);
4991 modrm = cpu_ldub_code(env, s->pc++);
4992 reg = ((modrm >> 3) & 7) | rex_r;
4994 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4995 gen_op_mov_v_reg(ot, cpu_T[1], reg);
4996 gen_op_testl_T0_T1_cc();
4997 set_cc_op(s, CC_OP_LOGICB + ot);
4998 break;
5000 case 0xa8: /* test eAX, Iv */
5001 case 0xa9:
5002 ot = mo_b_d(b, dflag);
5003 val = insn_get(env, s, ot);
5005 gen_op_mov_v_reg(ot, cpu_T[0], OR_EAX);
5006 tcg_gen_movi_tl(cpu_T[1], val);
5007 gen_op_testl_T0_T1_cc();
5008 set_cc_op(s, CC_OP_LOGICB + ot);
5009 break;
5011 case 0x98: /* CWDE/CBW */
5012 switch (dflag) {
5013 #ifdef TARGET_X86_64
5014 case MO_64:
5015 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
5016 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5017 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T[0]);
5018 break;
5019 #endif
5020 case MO_32:
5021 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
5022 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5023 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T[0]);
5024 break;
5025 case MO_16:
5026 gen_op_mov_v_reg(MO_8, cpu_T[0], R_EAX);
5027 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5028 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
5029 break;
5030 default:
5031 tcg_abort();
5033 break;
5034 case 0x99: /* CDQ/CWD */
5035 switch (dflag) {
5036 #ifdef TARGET_X86_64
5037 case MO_64:
5038 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EAX);
5039 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
5040 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T[0]);
5041 break;
5042 #endif
5043 case MO_32:
5044 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
5045 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5046 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
5047 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T[0]);
5048 break;
5049 case MO_16:
5050 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
5051 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5052 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
5053 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
5054 break;
5055 default:
5056 tcg_abort();
5058 break;
5059 case 0x1af: /* imul Gv, Ev */
5060 case 0x69: /* imul Gv, Ev, I */
5061 case 0x6b:
5062 ot = dflag;
5063 modrm = cpu_ldub_code(env, s->pc++);
5064 reg = ((modrm >> 3) & 7) | rex_r;
5065 if (b == 0x69)
5066 s->rip_offset = insn_const_size(ot);
5067 else if (b == 0x6b)
5068 s->rip_offset = 1;
5069 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5070 if (b == 0x69) {
5071 val = insn_get(env, s, ot);
5072 tcg_gen_movi_tl(cpu_T[1], val);
5073 } else if (b == 0x6b) {
5074 val = (int8_t)insn_get(env, s, MO_8);
5075 tcg_gen_movi_tl(cpu_T[1], val);
5076 } else {
5077 gen_op_mov_v_reg(ot, cpu_T[1], reg);
5079 switch (ot) {
5080 #ifdef TARGET_X86_64
5081 case MO_64:
5082 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
5083 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5084 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5085 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
5086 break;
5087 #endif
5088 case MO_32:
5089 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5090 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5091 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5092 cpu_tmp2_i32, cpu_tmp3_i32);
5093 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5094 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5095 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5096 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5097 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5098 break;
5099 default:
5100 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5101 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5102 /* XXX: use 32 bit mul which could be faster */
5103 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5104 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5105 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5106 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5107 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5108 break;
5110 set_cc_op(s, CC_OP_MULB + ot);
5111 break;
5112 case 0x1c0:
5113 case 0x1c1: /* xadd Ev, Gv */
5114 ot = mo_b_d(b, dflag);
5115 modrm = cpu_ldub_code(env, s->pc++);
5116 reg = ((modrm >> 3) & 7) | rex_r;
5117 mod = (modrm >> 6) & 3;
5118 if (mod == 3) {
5119 rm = (modrm & 7) | REX_B(s);
5120 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5121 gen_op_mov_v_reg(ot, cpu_T[1], rm);
5122 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5123 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5124 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5125 } else {
5126 gen_lea_modrm(env, s, modrm);
5127 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5128 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5129 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5130 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5131 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5133 gen_op_update2_cc();
5134 set_cc_op(s, CC_OP_ADDB + ot);
5135 break;
5136 case 0x1b0:
5137 case 0x1b1: /* cmpxchg Ev, Gv */
5139 TCGLabel *label1, *label2;
5140 TCGv t0, t1, t2, a0;
5142 ot = mo_b_d(b, dflag);
5143 modrm = cpu_ldub_code(env, s->pc++);
5144 reg = ((modrm >> 3) & 7) | rex_r;
5145 mod = (modrm >> 6) & 3;
5146 t0 = tcg_temp_local_new();
5147 t1 = tcg_temp_local_new();
5148 t2 = tcg_temp_local_new();
5149 a0 = tcg_temp_local_new();
5150 gen_op_mov_v_reg(ot, t1, reg);
5151 if (mod == 3) {
5152 rm = (modrm & 7) | REX_B(s);
5153 gen_op_mov_v_reg(ot, t0, rm);
5154 } else {
5155 gen_lea_modrm(env, s, modrm);
5156 tcg_gen_mov_tl(a0, cpu_A0);
5157 gen_op_ld_v(s, ot, t0, a0);
5158 rm = 0; /* avoid warning */
5160 label1 = gen_new_label();
5161 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5162 gen_extu(ot, t0);
5163 gen_extu(ot, t2);
5164 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
5165 label2 = gen_new_label();
5166 if (mod == 3) {
5167 gen_op_mov_reg_v(ot, R_EAX, t0);
5168 tcg_gen_br(label2);
5169 gen_set_label(label1);
5170 gen_op_mov_reg_v(ot, rm, t1);
5171 } else {
5172 /* perform no-op store cycle like physical cpu; must be
5173 before changing accumulator to ensure idempotency if
5174 the store faults and the instruction is restarted */
5175 gen_op_st_v(s, ot, t0, a0);
5176 gen_op_mov_reg_v(ot, R_EAX, t0);
5177 tcg_gen_br(label2);
5178 gen_set_label(label1);
5179 gen_op_st_v(s, ot, t1, a0);
5181 gen_set_label(label2);
5182 tcg_gen_mov_tl(cpu_cc_src, t0);
5183 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5184 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
5185 set_cc_op(s, CC_OP_SUBB + ot);
5186 tcg_temp_free(t0);
5187 tcg_temp_free(t1);
5188 tcg_temp_free(t2);
5189 tcg_temp_free(a0);
5191 break;
5192 case 0x1c7: /* cmpxchg8b */
5193 modrm = cpu_ldub_code(env, s->pc++);
5194 mod = (modrm >> 6) & 3;
5195 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5196 goto illegal_op;
5197 #ifdef TARGET_X86_64
5198 if (dflag == MO_64) {
5199 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5200 goto illegal_op;
5201 gen_lea_modrm(env, s, modrm);
5202 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5203 } else
5204 #endif
5206 if (!(s->cpuid_features & CPUID_CX8))
5207 goto illegal_op;
5208 gen_lea_modrm(env, s, modrm);
5209 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5211 set_cc_op(s, CC_OP_EFLAGS);
5212 break;
5214 /**************************/
5215 /* push/pop */
5216 case 0x50 ... 0x57: /* push */
5217 gen_op_mov_v_reg(MO_32, cpu_T[0], (b & 7) | REX_B(s));
5218 gen_push_v(s, cpu_T[0]);
5219 break;
5220 case 0x58 ... 0x5f: /* pop */
5221 ot = gen_pop_T0(s);
5222 /* NOTE: order is important for pop %sp */
5223 gen_pop_update(s, ot);
5224 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T[0]);
5225 break;
5226 case 0x60: /* pusha */
5227 if (CODE64(s))
5228 goto illegal_op;
5229 gen_pusha(s);
5230 break;
5231 case 0x61: /* popa */
5232 if (CODE64(s))
5233 goto illegal_op;
5234 gen_popa(s);
5235 break;
5236 case 0x68: /* push Iv */
5237 case 0x6a:
5238 ot = mo_pushpop(s, dflag);
5239 if (b == 0x68)
5240 val = insn_get(env, s, ot);
5241 else
5242 val = (int8_t)insn_get(env, s, MO_8);
5243 tcg_gen_movi_tl(cpu_T[0], val);
5244 gen_push_v(s, cpu_T[0]);
5245 break;
5246 case 0x8f: /* pop Ev */
5247 modrm = cpu_ldub_code(env, s->pc++);
5248 mod = (modrm >> 6) & 3;
5249 ot = gen_pop_T0(s);
5250 if (mod == 3) {
5251 /* NOTE: order is important for pop %sp */
5252 gen_pop_update(s, ot);
5253 rm = (modrm & 7) | REX_B(s);
5254 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5255 } else {
5256 /* NOTE: order is important too for MMU exceptions */
5257 s->popl_esp_hack = 1 << ot;
5258 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5259 s->popl_esp_hack = 0;
5260 gen_pop_update(s, ot);
5262 break;
5263 case 0xc8: /* enter */
5265 int level;
5266 val = cpu_lduw_code(env, s->pc);
5267 s->pc += 2;
5268 level = cpu_ldub_code(env, s->pc++);
5269 gen_enter(s, val, level);
5271 break;
5272 case 0xc9: /* leave */
5273 /* XXX: exception not precise (ESP is updated before potential exception) */
5274 if (CODE64(s)) {
5275 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EBP);
5276 gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[0]);
5277 } else if (s->ss32) {
5278 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
5279 gen_op_mov_reg_v(MO_32, R_ESP, cpu_T[0]);
5280 } else {
5281 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EBP);
5282 gen_op_mov_reg_v(MO_16, R_ESP, cpu_T[0]);
5284 ot = gen_pop_T0(s);
5285 gen_op_mov_reg_v(ot, R_EBP, cpu_T[0]);
5286 gen_pop_update(s, ot);
5287 break;
5288 case 0x06: /* push es */
5289 case 0x0e: /* push cs */
5290 case 0x16: /* push ss */
5291 case 0x1e: /* push ds */
5292 if (CODE64(s))
5293 goto illegal_op;
5294 gen_op_movl_T0_seg(b >> 3);
5295 gen_push_v(s, cpu_T[0]);
5296 break;
5297 case 0x1a0: /* push fs */
5298 case 0x1a8: /* push gs */
5299 gen_op_movl_T0_seg((b >> 3) & 7);
5300 gen_push_v(s, cpu_T[0]);
5301 break;
5302 case 0x07: /* pop es */
5303 case 0x17: /* pop ss */
5304 case 0x1f: /* pop ds */
5305 if (CODE64(s))
5306 goto illegal_op;
5307 reg = b >> 3;
5308 ot = gen_pop_T0(s);
5309 gen_movl_seg_T0(s, reg);
5310 gen_pop_update(s, ot);
5311 if (reg == R_SS) {
5312 /* if reg == SS, inhibit interrupts/trace. */
5313 /* If several instructions disable interrupts, only the
5314 _first_ does it */
5315 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5316 gen_helper_set_inhibit_irq(cpu_env);
5317 s->tf = 0;
5319 if (s->is_jmp) {
5320 gen_jmp_im(s->pc - s->cs_base);
5321 gen_eob(s);
5323 break;
5324 case 0x1a1: /* pop fs */
5325 case 0x1a9: /* pop gs */
5326 ot = gen_pop_T0(s);
5327 gen_movl_seg_T0(s, (b >> 3) & 7);
5328 gen_pop_update(s, ot);
5329 if (s->is_jmp) {
5330 gen_jmp_im(s->pc - s->cs_base);
5331 gen_eob(s);
5333 break;
5335 /**************************/
5336 /* mov */
5337 case 0x88:
5338 case 0x89: /* mov Gv, Ev */
5339 ot = mo_b_d(b, dflag);
5340 modrm = cpu_ldub_code(env, s->pc++);
5341 reg = ((modrm >> 3) & 7) | rex_r;
5343 /* generate a generic store */
5344 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5345 break;
5346 case 0xc6:
5347 case 0xc7: /* mov Ev, Iv */
5348 ot = mo_b_d(b, dflag);
5349 modrm = cpu_ldub_code(env, s->pc++);
5350 mod = (modrm >> 6) & 3;
5351 if (mod != 3) {
5352 s->rip_offset = insn_const_size(ot);
5353 gen_lea_modrm(env, s, modrm);
5355 val = insn_get(env, s, ot);
5356 tcg_gen_movi_tl(cpu_T[0], val);
5357 if (mod != 3) {
5358 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5359 } else {
5360 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T[0]);
5362 break;
5363 case 0x8a:
5364 case 0x8b: /* mov Ev, Gv */
5365 ot = mo_b_d(b, dflag);
5366 modrm = cpu_ldub_code(env, s->pc++);
5367 reg = ((modrm >> 3) & 7) | rex_r;
5369 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5370 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5371 break;
5372 case 0x8e: /* mov seg, Gv */
5373 modrm = cpu_ldub_code(env, s->pc++);
5374 reg = (modrm >> 3) & 7;
5375 if (reg >= 6 || reg == R_CS)
5376 goto illegal_op;
5377 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5378 gen_movl_seg_T0(s, reg);
5379 if (reg == R_SS) {
5380 /* if reg == SS, inhibit interrupts/trace */
5381 /* If several instructions disable interrupts, only the
5382 _first_ does it */
5383 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5384 gen_helper_set_inhibit_irq(cpu_env);
5385 s->tf = 0;
5387 if (s->is_jmp) {
5388 gen_jmp_im(s->pc - s->cs_base);
5389 gen_eob(s);
5391 break;
5392 case 0x8c: /* mov Gv, seg */
5393 modrm = cpu_ldub_code(env, s->pc++);
5394 reg = (modrm >> 3) & 7;
5395 mod = (modrm >> 6) & 3;
5396 if (reg >= 6)
5397 goto illegal_op;
5398 gen_op_movl_T0_seg(reg);
5399 ot = mod == 3 ? dflag : MO_16;
5400 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5401 break;
5403 case 0x1b6: /* movzbS Gv, Eb */
5404 case 0x1b7: /* movzwS Gv, Eb */
5405 case 0x1be: /* movsbS Gv, Eb */
5406 case 0x1bf: /* movswS Gv, Eb */
5408 TCGMemOp d_ot;
5409 TCGMemOp s_ot;
5411 /* d_ot is the size of destination */
5412 d_ot = dflag;
5413 /* ot is the size of source */
5414 ot = (b & 1) + MO_8;
5415 /* s_ot is the sign+size of source */
5416 s_ot = b & 8 ? MO_SIGN | ot : ot;
5418 modrm = cpu_ldub_code(env, s->pc++);
5419 reg = ((modrm >> 3) & 7) | rex_r;
5420 mod = (modrm >> 6) & 3;
5421 rm = (modrm & 7) | REX_B(s);
5423 if (mod == 3) {
5424 gen_op_mov_v_reg(ot, cpu_T[0], rm);
5425 switch (s_ot) {
5426 case MO_UB:
5427 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
5428 break;
5429 case MO_SB:
5430 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5431 break;
5432 case MO_UW:
5433 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
5434 break;
5435 default:
5436 case MO_SW:
5437 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5438 break;
5440 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
5441 } else {
5442 gen_lea_modrm(env, s, modrm);
5443 gen_op_ld_v(s, s_ot, cpu_T[0], cpu_A0);
5444 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
5447 break;
5449 case 0x8d: /* lea */
5450 ot = dflag;
5451 modrm = cpu_ldub_code(env, s->pc++);
5452 mod = (modrm >> 6) & 3;
5453 if (mod == 3)
5454 goto illegal_op;
5455 reg = ((modrm >> 3) & 7) | rex_r;
5456 /* we must ensure that no segment is added */
5457 s->override = -1;
5458 val = s->addseg;
5459 s->addseg = 0;
5460 gen_lea_modrm(env, s, modrm);
5461 s->addseg = val;
5462 gen_op_mov_reg_v(ot, reg, cpu_A0);
5463 break;
5465 case 0xa0: /* mov EAX, Ov */
5466 case 0xa1:
5467 case 0xa2: /* mov Ov, EAX */
5468 case 0xa3:
5470 target_ulong offset_addr;
5472 ot = mo_b_d(b, dflag);
5473 switch (s->aflag) {
5474 #ifdef TARGET_X86_64
5475 case MO_64:
5476 offset_addr = cpu_ldq_code(env, s->pc);
5477 s->pc += 8;
5478 break;
5479 #endif
5480 default:
5481 offset_addr = insn_get(env, s, s->aflag);
5482 break;
5484 tcg_gen_movi_tl(cpu_A0, offset_addr);
5485 gen_add_A0_ds_seg(s);
5486 if ((b & 2) == 0) {
5487 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
5488 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
5489 } else {
5490 gen_op_mov_v_reg(ot, cpu_T[0], R_EAX);
5491 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5494 break;
5495 case 0xd7: /* xlat */
5496 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5497 tcg_gen_ext8u_tl(cpu_T[0], cpu_regs[R_EAX]);
5498 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5499 gen_extu(s->aflag, cpu_A0);
5500 gen_add_A0_ds_seg(s);
5501 gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
5502 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
5503 break;
5504 case 0xb0 ... 0xb7: /* mov R, Ib */
5505 val = insn_get(env, s, MO_8);
5506 tcg_gen_movi_tl(cpu_T[0], val);
5507 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T[0]);
5508 break;
5509 case 0xb8 ... 0xbf: /* mov R, Iv */
5510 #ifdef TARGET_X86_64
5511 if (dflag == MO_64) {
5512 uint64_t tmp;
5513 /* 64 bit case */
5514 tmp = cpu_ldq_code(env, s->pc);
5515 s->pc += 8;
5516 reg = (b & 7) | REX_B(s);
5517 tcg_gen_movi_tl(cpu_T[0], tmp);
5518 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
5519 } else
5520 #endif
5522 ot = dflag;
5523 val = insn_get(env, s, ot);
5524 reg = (b & 7) | REX_B(s);
5525 tcg_gen_movi_tl(cpu_T[0], val);
5526 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
5528 break;
5530 case 0x91 ... 0x97: /* xchg R, EAX */
5531 do_xchg_reg_eax:
5532 ot = dflag;
5533 reg = (b & 7) | REX_B(s);
5534 rm = R_EAX;
5535 goto do_xchg_reg;
5536 case 0x86:
5537 case 0x87: /* xchg Ev, Gv */
5538 ot = mo_b_d(b, dflag);
5539 modrm = cpu_ldub_code(env, s->pc++);
5540 reg = ((modrm >> 3) & 7) | rex_r;
5541 mod = (modrm >> 6) & 3;
5542 if (mod == 3) {
5543 rm = (modrm & 7) | REX_B(s);
5544 do_xchg_reg:
5545 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5546 gen_op_mov_v_reg(ot, cpu_T[1], rm);
5547 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
5548 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5549 } else {
5550 gen_lea_modrm(env, s, modrm);
5551 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5552 /* for xchg, lock is implicit */
5553 if (!(prefixes & PREFIX_LOCK))
5554 gen_helper_lock();
5555 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5556 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5557 if (!(prefixes & PREFIX_LOCK))
5558 gen_helper_unlock();
5559 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5561 break;
5562 case 0xc4: /* les Gv */
5563 /* In CODE64 this is VEX3; see above. */
5564 op = R_ES;
5565 goto do_lxx;
5566 case 0xc5: /* lds Gv */
5567 /* In CODE64 this is VEX2; see above. */
5568 op = R_DS;
5569 goto do_lxx;
5570 case 0x1b2: /* lss Gv */
5571 op = R_SS;
5572 goto do_lxx;
5573 case 0x1b4: /* lfs Gv */
5574 op = R_FS;
5575 goto do_lxx;
5576 case 0x1b5: /* lgs Gv */
5577 op = R_GS;
5578 do_lxx:
5579 ot = dflag != MO_16 ? MO_32 : MO_16;
5580 modrm = cpu_ldub_code(env, s->pc++);
5581 reg = ((modrm >> 3) & 7) | rex_r;
5582 mod = (modrm >> 6) & 3;
5583 if (mod == 3)
5584 goto illegal_op;
5585 gen_lea_modrm(env, s, modrm);
5586 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
5587 gen_add_A0_im(s, 1 << ot);
5588 /* load the segment first to handle exceptions properly */
5589 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
5590 gen_movl_seg_T0(s, op);
5591 /* then put the data */
5592 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
5593 if (s->is_jmp) {
5594 gen_jmp_im(s->pc - s->cs_base);
5595 gen_eob(s);
5597 break;
5599 /************************/
5600 /* shifts */
5601 case 0xc0:
5602 case 0xc1:
5603 /* shift Ev,Ib */
5604 shift = 2;
5605 grp2:
5607 ot = mo_b_d(b, dflag);
5608 modrm = cpu_ldub_code(env, s->pc++);
5609 mod = (modrm >> 6) & 3;
5610 op = (modrm >> 3) & 7;
5612 if (mod != 3) {
5613 if (shift == 2) {
5614 s->rip_offset = 1;
5616 gen_lea_modrm(env, s, modrm);
5617 opreg = OR_TMP0;
5618 } else {
5619 opreg = (modrm & 7) | REX_B(s);
5622 /* simpler op */
5623 if (shift == 0) {
5624 gen_shift(s, op, ot, opreg, OR_ECX);
5625 } else {
5626 if (shift == 2) {
5627 shift = cpu_ldub_code(env, s->pc++);
5629 gen_shifti(s, op, ot, opreg, shift);
5632 break;
5633 case 0xd0:
5634 case 0xd1:
5635 /* shift Ev,1 */
5636 shift = 1;
5637 goto grp2;
5638 case 0xd2:
5639 case 0xd3:
5640 /* shift Ev,cl */
5641 shift = 0;
5642 goto grp2;
5644 case 0x1a4: /* shld imm */
5645 op = 0;
5646 shift = 1;
5647 goto do_shiftd;
5648 case 0x1a5: /* shld cl */
5649 op = 0;
5650 shift = 0;
5651 goto do_shiftd;
5652 case 0x1ac: /* shrd imm */
5653 op = 1;
5654 shift = 1;
5655 goto do_shiftd;
5656 case 0x1ad: /* shrd cl */
5657 op = 1;
5658 shift = 0;
5659 do_shiftd:
5660 ot = dflag;
5661 modrm = cpu_ldub_code(env, s->pc++);
5662 mod = (modrm >> 6) & 3;
5663 rm = (modrm & 7) | REX_B(s);
5664 reg = ((modrm >> 3) & 7) | rex_r;
5665 if (mod != 3) {
5666 gen_lea_modrm(env, s, modrm);
5667 opreg = OR_TMP0;
5668 } else {
5669 opreg = rm;
5671 gen_op_mov_v_reg(ot, cpu_T[1], reg);
5673 if (shift) {
5674 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5675 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5676 tcg_temp_free(imm);
5677 } else {
5678 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5680 break;
5682 /************************/
5683 /* floats */
5684 case 0xd8 ... 0xdf:
5685 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5686 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5687 /* XXX: what to do if illegal op ? */
5688 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5689 break;
5691 modrm = cpu_ldub_code(env, s->pc++);
5692 mod = (modrm >> 6) & 3;
5693 rm = modrm & 7;
5694 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5695 if (mod != 3) {
5696 /* memory op */
5697 gen_lea_modrm(env, s, modrm);
5698 switch(op) {
5699 case 0x00 ... 0x07: /* fxxxs */
5700 case 0x10 ... 0x17: /* fixxxl */
5701 case 0x20 ... 0x27: /* fxxxl */
5702 case 0x30 ... 0x37: /* fixxx */
5704 int op1;
5705 op1 = op & 7;
5707 switch(op >> 4) {
5708 case 0:
5709 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5710 s->mem_index, MO_LEUL);
5711 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5712 break;
5713 case 1:
5714 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5715 s->mem_index, MO_LEUL);
5716 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5717 break;
5718 case 2:
5719 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5720 s->mem_index, MO_LEQ);
5721 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5722 break;
5723 case 3:
5724 default:
5725 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5726 s->mem_index, MO_LESW);
5727 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5728 break;
5731 gen_helper_fp_arith_ST0_FT0(op1);
5732 if (op1 == 3) {
5733 /* fcomp needs pop */
5734 gen_helper_fpop(cpu_env);
5737 break;
5738 case 0x08: /* flds */
5739 case 0x0a: /* fsts */
5740 case 0x0b: /* fstps */
5741 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5742 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5743 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5744 switch(op & 7) {
5745 case 0:
5746 switch(op >> 4) {
5747 case 0:
5748 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5749 s->mem_index, MO_LEUL);
5750 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5751 break;
5752 case 1:
5753 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5754 s->mem_index, MO_LEUL);
5755 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5756 break;
5757 case 2:
5758 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5759 s->mem_index, MO_LEQ);
5760 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5761 break;
5762 case 3:
5763 default:
5764 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5765 s->mem_index, MO_LESW);
5766 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5767 break;
5769 break;
5770 case 1:
5771 /* XXX: the corresponding CPUID bit must be tested ! */
5772 switch(op >> 4) {
5773 case 1:
5774 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5775 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5776 s->mem_index, MO_LEUL);
5777 break;
5778 case 2:
5779 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5780 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5781 s->mem_index, MO_LEQ);
5782 break;
5783 case 3:
5784 default:
5785 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5786 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5787 s->mem_index, MO_LEUW);
5788 break;
5790 gen_helper_fpop(cpu_env);
5791 break;
5792 default:
5793 switch(op >> 4) {
5794 case 0:
5795 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5796 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5797 s->mem_index, MO_LEUL);
5798 break;
5799 case 1:
5800 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5801 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5802 s->mem_index, MO_LEUL);
5803 break;
5804 case 2:
5805 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5806 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5807 s->mem_index, MO_LEQ);
5808 break;
5809 case 3:
5810 default:
5811 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5812 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5813 s->mem_index, MO_LEUW);
5814 break;
5816 if ((op & 7) == 3)
5817 gen_helper_fpop(cpu_env);
5818 break;
5820 break;
5821 case 0x0c: /* fldenv mem */
5822 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5823 break;
5824 case 0x0d: /* fldcw mem */
5825 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5826 s->mem_index, MO_LEUW);
5827 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5828 break;
5829 case 0x0e: /* fnstenv mem */
5830 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5831 break;
5832 case 0x0f: /* fnstcw mem */
5833 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5834 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5835 s->mem_index, MO_LEUW);
5836 break;
5837 case 0x1d: /* fldt mem */
5838 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5839 break;
5840 case 0x1f: /* fstpt mem */
5841 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5842 gen_helper_fpop(cpu_env);
5843 break;
5844 case 0x2c: /* frstor mem */
5845 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5846 break;
5847 case 0x2e: /* fnsave mem */
5848 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
5849 break;
5850 case 0x2f: /* fnstsw mem */
5851 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5852 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5853 s->mem_index, MO_LEUW);
5854 break;
5855 case 0x3c: /* fbld */
5856 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5857 break;
5858 case 0x3e: /* fbstp */
5859 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5860 gen_helper_fpop(cpu_env);
5861 break;
5862 case 0x3d: /* fildll */
5863 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5864 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5865 break;
5866 case 0x3f: /* fistpll */
5867 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5868 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
5869 gen_helper_fpop(cpu_env);
5870 break;
5871 default:
5872 goto illegal_op;
5874 } else {
5875 /* register float ops */
5876 opreg = rm;
5878 switch(op) {
5879 case 0x08: /* fld sti */
5880 gen_helper_fpush(cpu_env);
5881 gen_helper_fmov_ST0_STN(cpu_env,
5882 tcg_const_i32((opreg + 1) & 7));
5883 break;
5884 case 0x09: /* fxchg sti */
5885 case 0x29: /* fxchg4 sti, undocumented op */
5886 case 0x39: /* fxchg7 sti, undocumented op */
5887 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5888 break;
5889 case 0x0a: /* grp d9/2 */
5890 switch(rm) {
5891 case 0: /* fnop */
5892 /* check exceptions (FreeBSD FPU probe) */
5893 gen_helper_fwait(cpu_env);
5894 break;
5895 default:
5896 goto illegal_op;
5898 break;
5899 case 0x0c: /* grp d9/4 */
5900 switch(rm) {
5901 case 0: /* fchs */
5902 gen_helper_fchs_ST0(cpu_env);
5903 break;
5904 case 1: /* fabs */
5905 gen_helper_fabs_ST0(cpu_env);
5906 break;
5907 case 4: /* ftst */
5908 gen_helper_fldz_FT0(cpu_env);
5909 gen_helper_fcom_ST0_FT0(cpu_env);
5910 break;
5911 case 5: /* fxam */
5912 gen_helper_fxam_ST0(cpu_env);
5913 break;
5914 default:
5915 goto illegal_op;
5917 break;
5918 case 0x0d: /* grp d9/5 */
5920 switch(rm) {
5921 case 0:
5922 gen_helper_fpush(cpu_env);
5923 gen_helper_fld1_ST0(cpu_env);
5924 break;
5925 case 1:
5926 gen_helper_fpush(cpu_env);
5927 gen_helper_fldl2t_ST0(cpu_env);
5928 break;
5929 case 2:
5930 gen_helper_fpush(cpu_env);
5931 gen_helper_fldl2e_ST0(cpu_env);
5932 break;
5933 case 3:
5934 gen_helper_fpush(cpu_env);
5935 gen_helper_fldpi_ST0(cpu_env);
5936 break;
5937 case 4:
5938 gen_helper_fpush(cpu_env);
5939 gen_helper_fldlg2_ST0(cpu_env);
5940 break;
5941 case 5:
5942 gen_helper_fpush(cpu_env);
5943 gen_helper_fldln2_ST0(cpu_env);
5944 break;
5945 case 6:
5946 gen_helper_fpush(cpu_env);
5947 gen_helper_fldz_ST0(cpu_env);
5948 break;
5949 default:
5950 goto illegal_op;
5953 break;
5954 case 0x0e: /* grp d9/6 */
5955 switch(rm) {
5956 case 0: /* f2xm1 */
5957 gen_helper_f2xm1(cpu_env);
5958 break;
5959 case 1: /* fyl2x */
5960 gen_helper_fyl2x(cpu_env);
5961 break;
5962 case 2: /* fptan */
5963 gen_helper_fptan(cpu_env);
5964 break;
5965 case 3: /* fpatan */
5966 gen_helper_fpatan(cpu_env);
5967 break;
5968 case 4: /* fxtract */
5969 gen_helper_fxtract(cpu_env);
5970 break;
5971 case 5: /* fprem1 */
5972 gen_helper_fprem1(cpu_env);
5973 break;
5974 case 6: /* fdecstp */
5975 gen_helper_fdecstp(cpu_env);
5976 break;
5977 default:
5978 case 7: /* fincstp */
5979 gen_helper_fincstp(cpu_env);
5980 break;
5982 break;
5983 case 0x0f: /* grp d9/7 */
5984 switch(rm) {
5985 case 0: /* fprem */
5986 gen_helper_fprem(cpu_env);
5987 break;
5988 case 1: /* fyl2xp1 */
5989 gen_helper_fyl2xp1(cpu_env);
5990 break;
5991 case 2: /* fsqrt */
5992 gen_helper_fsqrt(cpu_env);
5993 break;
5994 case 3: /* fsincos */
5995 gen_helper_fsincos(cpu_env);
5996 break;
5997 case 5: /* fscale */
5998 gen_helper_fscale(cpu_env);
5999 break;
6000 case 4: /* frndint */
6001 gen_helper_frndint(cpu_env);
6002 break;
6003 case 6: /* fsin */
6004 gen_helper_fsin(cpu_env);
6005 break;
6006 default:
6007 case 7: /* fcos */
6008 gen_helper_fcos(cpu_env);
6009 break;
6011 break;
6012 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6013 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6014 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6016 int op1;
6018 op1 = op & 7;
6019 if (op >= 0x20) {
6020 gen_helper_fp_arith_STN_ST0(op1, opreg);
6021 if (op >= 0x30)
6022 gen_helper_fpop(cpu_env);
6023 } else {
6024 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6025 gen_helper_fp_arith_ST0_FT0(op1);
6028 break;
6029 case 0x02: /* fcom */
6030 case 0x22: /* fcom2, undocumented op */
6031 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6032 gen_helper_fcom_ST0_FT0(cpu_env);
6033 break;
6034 case 0x03: /* fcomp */
6035 case 0x23: /* fcomp3, undocumented op */
6036 case 0x32: /* fcomp5, undocumented op */
6037 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6038 gen_helper_fcom_ST0_FT0(cpu_env);
6039 gen_helper_fpop(cpu_env);
6040 break;
6041 case 0x15: /* da/5 */
6042 switch(rm) {
6043 case 1: /* fucompp */
6044 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6045 gen_helper_fucom_ST0_FT0(cpu_env);
6046 gen_helper_fpop(cpu_env);
6047 gen_helper_fpop(cpu_env);
6048 break;
6049 default:
6050 goto illegal_op;
6052 break;
6053 case 0x1c:
6054 switch(rm) {
6055 case 0: /* feni (287 only, just do nop here) */
6056 break;
6057 case 1: /* fdisi (287 only, just do nop here) */
6058 break;
6059 case 2: /* fclex */
6060 gen_helper_fclex(cpu_env);
6061 break;
6062 case 3: /* fninit */
6063 gen_helper_fninit(cpu_env);
6064 break;
6065 case 4: /* fsetpm (287 only, just do nop here) */
6066 break;
6067 default:
6068 goto illegal_op;
6070 break;
6071 case 0x1d: /* fucomi */
6072 if (!(s->cpuid_features & CPUID_CMOV)) {
6073 goto illegal_op;
6075 gen_update_cc_op(s);
6076 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6077 gen_helper_fucomi_ST0_FT0(cpu_env);
6078 set_cc_op(s, CC_OP_EFLAGS);
6079 break;
6080 case 0x1e: /* fcomi */
6081 if (!(s->cpuid_features & CPUID_CMOV)) {
6082 goto illegal_op;
6084 gen_update_cc_op(s);
6085 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6086 gen_helper_fcomi_ST0_FT0(cpu_env);
6087 set_cc_op(s, CC_OP_EFLAGS);
6088 break;
6089 case 0x28: /* ffree sti */
6090 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6091 break;
6092 case 0x2a: /* fst sti */
6093 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6094 break;
6095 case 0x2b: /* fstp sti */
6096 case 0x0b: /* fstp1 sti, undocumented op */
6097 case 0x3a: /* fstp8 sti, undocumented op */
6098 case 0x3b: /* fstp9 sti, undocumented op */
6099 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6100 gen_helper_fpop(cpu_env);
6101 break;
6102 case 0x2c: /* fucom st(i) */
6103 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6104 gen_helper_fucom_ST0_FT0(cpu_env);
6105 break;
6106 case 0x2d: /* fucomp st(i) */
6107 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6108 gen_helper_fucom_ST0_FT0(cpu_env);
6109 gen_helper_fpop(cpu_env);
6110 break;
6111 case 0x33: /* de/3 */
6112 switch(rm) {
6113 case 1: /* fcompp */
6114 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6115 gen_helper_fcom_ST0_FT0(cpu_env);
6116 gen_helper_fpop(cpu_env);
6117 gen_helper_fpop(cpu_env);
6118 break;
6119 default:
6120 goto illegal_op;
6122 break;
6123 case 0x38: /* ffreep sti, undocumented op */
6124 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6125 gen_helper_fpop(cpu_env);
6126 break;
6127 case 0x3c: /* df/4 */
6128 switch(rm) {
6129 case 0:
6130 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6131 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6132 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
6133 break;
6134 default:
6135 goto illegal_op;
6137 break;
6138 case 0x3d: /* fucomip */
6139 if (!(s->cpuid_features & CPUID_CMOV)) {
6140 goto illegal_op;
6142 gen_update_cc_op(s);
6143 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6144 gen_helper_fucomi_ST0_FT0(cpu_env);
6145 gen_helper_fpop(cpu_env);
6146 set_cc_op(s, CC_OP_EFLAGS);
6147 break;
6148 case 0x3e: /* fcomip */
6149 if (!(s->cpuid_features & CPUID_CMOV)) {
6150 goto illegal_op;
6152 gen_update_cc_op(s);
6153 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6154 gen_helper_fcomi_ST0_FT0(cpu_env);
6155 gen_helper_fpop(cpu_env);
6156 set_cc_op(s, CC_OP_EFLAGS);
6157 break;
6158 case 0x10 ... 0x13: /* fcmovxx */
6159 case 0x18 ... 0x1b:
6161 int op1;
6162 TCGLabel *l1;
6163 static const uint8_t fcmov_cc[8] = {
6164 (JCC_B << 1),
6165 (JCC_Z << 1),
6166 (JCC_BE << 1),
6167 (JCC_P << 1),
6170 if (!(s->cpuid_features & CPUID_CMOV)) {
6171 goto illegal_op;
6173 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6174 l1 = gen_new_label();
6175 gen_jcc1_noeob(s, op1, l1);
6176 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6177 gen_set_label(l1);
6179 break;
6180 default:
6181 goto illegal_op;
6184 break;
6185 /************************/
6186 /* string ops */
6188 case 0xa4: /* movsS */
6189 case 0xa5:
6190 ot = mo_b_d(b, dflag);
6191 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6192 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6193 } else {
6194 gen_movs(s, ot);
6196 break;
6198 case 0xaa: /* stosS */
6199 case 0xab:
6200 ot = mo_b_d(b, dflag);
6201 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6202 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6203 } else {
6204 gen_stos(s, ot);
6206 break;
6207 case 0xac: /* lodsS */
6208 case 0xad:
6209 ot = mo_b_d(b, dflag);
6210 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6211 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6212 } else {
6213 gen_lods(s, ot);
6215 break;
6216 case 0xae: /* scasS */
6217 case 0xaf:
6218 ot = mo_b_d(b, dflag);
6219 if (prefixes & PREFIX_REPNZ) {
6220 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6221 } else if (prefixes & PREFIX_REPZ) {
6222 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6223 } else {
6224 gen_scas(s, ot);
6226 break;
6228 case 0xa6: /* cmpsS */
6229 case 0xa7:
6230 ot = mo_b_d(b, dflag);
6231 if (prefixes & PREFIX_REPNZ) {
6232 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6233 } else if (prefixes & PREFIX_REPZ) {
6234 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6235 } else {
6236 gen_cmps(s, ot);
6238 break;
6239 case 0x6c: /* insS */
6240 case 0x6d:
6241 ot = mo_b_d32(b, dflag);
6242 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6243 gen_check_io(s, ot, pc_start - s->cs_base,
6244 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6245 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6246 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6247 } else {
6248 gen_ins(s, ot);
6249 if (s->tb->cflags & CF_USE_ICOUNT) {
6250 gen_jmp(s, s->pc - s->cs_base);
6253 break;
6254 case 0x6e: /* outsS */
6255 case 0x6f:
6256 ot = mo_b_d32(b, dflag);
6257 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6258 gen_check_io(s, ot, pc_start - s->cs_base,
6259 svm_is_rep(prefixes) | 4);
6260 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6261 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6262 } else {
6263 gen_outs(s, ot);
6264 if (s->tb->cflags & CF_USE_ICOUNT) {
6265 gen_jmp(s, s->pc - s->cs_base);
6268 break;
6270 /************************/
6271 /* port I/O */
6273 case 0xe4:
6274 case 0xe5:
6275 ot = mo_b_d32(b, dflag);
6276 val = cpu_ldub_code(env, s->pc++);
6277 tcg_gen_movi_tl(cpu_T[0], val);
6278 gen_check_io(s, ot, pc_start - s->cs_base,
6279 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6280 if (s->tb->cflags & CF_USE_ICOUNT) {
6281 gen_io_start();
6283 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6284 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6285 gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
6286 gen_bpt_io(s, cpu_tmp2_i32, ot);
6287 if (s->tb->cflags & CF_USE_ICOUNT) {
6288 gen_io_end();
6289 gen_jmp(s, s->pc - s->cs_base);
6291 break;
6292 case 0xe6:
6293 case 0xe7:
6294 ot = mo_b_d32(b, dflag);
6295 val = cpu_ldub_code(env, s->pc++);
6296 tcg_gen_movi_tl(cpu_T[0], val);
6297 gen_check_io(s, ot, pc_start - s->cs_base,
6298 svm_is_rep(prefixes));
6299 gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
6301 if (s->tb->cflags & CF_USE_ICOUNT) {
6302 gen_io_start();
6304 tcg_gen_movi_i32(cpu_tmp2_i32, val);
6305 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6306 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6307 gen_bpt_io(s, cpu_tmp2_i32, ot);
6308 if (s->tb->cflags & CF_USE_ICOUNT) {
6309 gen_io_end();
6310 gen_jmp(s, s->pc - s->cs_base);
6312 break;
6313 case 0xec:
6314 case 0xed:
6315 ot = mo_b_d32(b, dflag);
6316 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6317 gen_check_io(s, ot, pc_start - s->cs_base,
6318 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6319 if (s->tb->cflags & CF_USE_ICOUNT) {
6320 gen_io_start();
6322 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6323 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6324 gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
6325 gen_bpt_io(s, cpu_tmp2_i32, ot);
6326 if (s->tb->cflags & CF_USE_ICOUNT) {
6327 gen_io_end();
6328 gen_jmp(s, s->pc - s->cs_base);
6330 break;
6331 case 0xee:
6332 case 0xef:
6333 ot = mo_b_d32(b, dflag);
6334 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
6335 gen_check_io(s, ot, pc_start - s->cs_base,
6336 svm_is_rep(prefixes));
6337 gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
6339 if (s->tb->cflags & CF_USE_ICOUNT) {
6340 gen_io_start();
6342 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6343 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6344 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6345 gen_bpt_io(s, cpu_tmp2_i32, ot);
6346 if (s->tb->cflags & CF_USE_ICOUNT) {
6347 gen_io_end();
6348 gen_jmp(s, s->pc - s->cs_base);
6350 break;
6352 /************************/
6353 /* control */
6354 case 0xc2: /* ret im */
6355 val = cpu_ldsw_code(env, s->pc);
6356 s->pc += 2;
6357 ot = gen_pop_T0(s);
6358 gen_stack_update(s, val + (1 << ot));
6359 /* Note that gen_pop_T0 uses a zero-extending load. */
6360 gen_op_jmp_v(cpu_T[0]);
6361 gen_eob(s);
6362 break;
6363 case 0xc3: /* ret */
6364 ot = gen_pop_T0(s);
6365 gen_pop_update(s, ot);
6366 /* Note that gen_pop_T0 uses a zero-extending load. */
6367 gen_op_jmp_v(cpu_T[0]);
6368 gen_eob(s);
6369 break;
6370 case 0xca: /* lret im */
6371 val = cpu_ldsw_code(env, s->pc);
6372 s->pc += 2;
6373 do_lret:
6374 if (s->pe && !s->vm86) {
6375 gen_update_cc_op(s);
6376 gen_jmp_im(pc_start - s->cs_base);
6377 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6378 tcg_const_i32(val));
6379 } else {
6380 gen_stack_A0(s);
6381 /* pop offset */
6382 gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
6383 /* NOTE: keeping EIP updated is not a problem in case of
6384 exception */
6385 gen_op_jmp_v(cpu_T[0]);
6386 /* pop selector */
6387 gen_op_addl_A0_im(1 << dflag);
6388 gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
6389 gen_op_movl_seg_T0_vm(R_CS);
6390 /* add stack offset */
6391 gen_stack_update(s, val + (2 << dflag));
6393 gen_eob(s);
6394 break;
6395 case 0xcb: /* lret */
6396 val = 0;
6397 goto do_lret;
6398 case 0xcf: /* iret */
6399 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6400 if (!s->pe) {
6401 /* real mode */
6402 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6403 set_cc_op(s, CC_OP_EFLAGS);
6404 } else if (s->vm86) {
6405 if (s->iopl != 3) {
6406 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6407 } else {
6408 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6409 set_cc_op(s, CC_OP_EFLAGS);
6411 } else {
6412 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6413 tcg_const_i32(s->pc - s->cs_base));
6414 set_cc_op(s, CC_OP_EFLAGS);
6416 gen_eob(s);
6417 break;
6418 case 0xe8: /* call im */
6420 if (dflag != MO_16) {
6421 tval = (int32_t)insn_get(env, s, MO_32);
6422 } else {
6423 tval = (int16_t)insn_get(env, s, MO_16);
6425 next_eip = s->pc - s->cs_base;
6426 tval += next_eip;
6427 if (dflag == MO_16) {
6428 tval &= 0xffff;
6429 } else if (!CODE64(s)) {
6430 tval &= 0xffffffff;
6432 tcg_gen_movi_tl(cpu_T[0], next_eip);
6433 gen_push_v(s, cpu_T[0]);
6434 gen_jmp(s, tval);
6436 break;
6437 case 0x9a: /* lcall im */
6439 unsigned int selector, offset;
6441 if (CODE64(s))
6442 goto illegal_op;
6443 ot = dflag;
6444 offset = insn_get(env, s, ot);
6445 selector = insn_get(env, s, MO_16);
6447 tcg_gen_movi_tl(cpu_T[0], selector);
6448 tcg_gen_movi_tl(cpu_T[1], offset);
6450 goto do_lcall;
6451 case 0xe9: /* jmp im */
6452 if (dflag != MO_16) {
6453 tval = (int32_t)insn_get(env, s, MO_32);
6454 } else {
6455 tval = (int16_t)insn_get(env, s, MO_16);
6457 tval += s->pc - s->cs_base;
6458 if (dflag == MO_16) {
6459 tval &= 0xffff;
6460 } else if (!CODE64(s)) {
6461 tval &= 0xffffffff;
6463 gen_jmp(s, tval);
6464 break;
6465 case 0xea: /* ljmp im */
6467 unsigned int selector, offset;
6469 if (CODE64(s))
6470 goto illegal_op;
6471 ot = dflag;
6472 offset = insn_get(env, s, ot);
6473 selector = insn_get(env, s, MO_16);
6475 tcg_gen_movi_tl(cpu_T[0], selector);
6476 tcg_gen_movi_tl(cpu_T[1], offset);
6478 goto do_ljmp;
6479 case 0xeb: /* jmp Jb */
6480 tval = (int8_t)insn_get(env, s, MO_8);
6481 tval += s->pc - s->cs_base;
6482 if (dflag == MO_16) {
6483 tval &= 0xffff;
6485 gen_jmp(s, tval);
6486 break;
6487 case 0x70 ... 0x7f: /* jcc Jb */
6488 tval = (int8_t)insn_get(env, s, MO_8);
6489 goto do_jcc;
6490 case 0x180 ... 0x18f: /* jcc Jv */
6491 if (dflag != MO_16) {
6492 tval = (int32_t)insn_get(env, s, MO_32);
6493 } else {
6494 tval = (int16_t)insn_get(env, s, MO_16);
6496 do_jcc:
6497 next_eip = s->pc - s->cs_base;
6498 tval += next_eip;
6499 if (dflag == MO_16) {
6500 tval &= 0xffff;
6502 gen_jcc(s, b, tval, next_eip);
6503 break;
6505 case 0x190 ... 0x19f: /* setcc Gv */
6506 modrm = cpu_ldub_code(env, s->pc++);
6507 gen_setcc1(s, b, cpu_T[0]);
6508 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6509 break;
6510 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6511 if (!(s->cpuid_features & CPUID_CMOV)) {
6512 goto illegal_op;
6514 ot = dflag;
6515 modrm = cpu_ldub_code(env, s->pc++);
6516 reg = ((modrm >> 3) & 7) | rex_r;
6517 gen_cmovcc1(env, s, ot, b, modrm, reg);
6518 break;
6520 /************************/
6521 /* flags */
6522 case 0x9c: /* pushf */
6523 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6524 if (s->vm86 && s->iopl != 3) {
6525 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6526 } else {
6527 gen_update_cc_op(s);
6528 gen_helper_read_eflags(cpu_T[0], cpu_env);
6529 gen_push_v(s, cpu_T[0]);
6531 break;
6532 case 0x9d: /* popf */
6533 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6534 if (s->vm86 && s->iopl != 3) {
6535 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6536 } else {
6537 ot = gen_pop_T0(s);
6538 if (s->cpl == 0) {
6539 if (dflag != MO_16) {
6540 gen_helper_write_eflags(cpu_env, cpu_T[0],
6541 tcg_const_i32((TF_MASK | AC_MASK |
6542 ID_MASK | NT_MASK |
6543 IF_MASK |
6544 IOPL_MASK)));
6545 } else {
6546 gen_helper_write_eflags(cpu_env, cpu_T[0],
6547 tcg_const_i32((TF_MASK | AC_MASK |
6548 ID_MASK | NT_MASK |
6549 IF_MASK | IOPL_MASK)
6550 & 0xffff));
6552 } else {
6553 if (s->cpl <= s->iopl) {
6554 if (dflag != MO_16) {
6555 gen_helper_write_eflags(cpu_env, cpu_T[0],
6556 tcg_const_i32((TF_MASK |
6557 AC_MASK |
6558 ID_MASK |
6559 NT_MASK |
6560 IF_MASK)));
6561 } else {
6562 gen_helper_write_eflags(cpu_env, cpu_T[0],
6563 tcg_const_i32((TF_MASK |
6564 AC_MASK |
6565 ID_MASK |
6566 NT_MASK |
6567 IF_MASK)
6568 & 0xffff));
6570 } else {
6571 if (dflag != MO_16) {
6572 gen_helper_write_eflags(cpu_env, cpu_T[0],
6573 tcg_const_i32((TF_MASK | AC_MASK |
6574 ID_MASK | NT_MASK)));
6575 } else {
6576 gen_helper_write_eflags(cpu_env, cpu_T[0],
6577 tcg_const_i32((TF_MASK | AC_MASK |
6578 ID_MASK | NT_MASK)
6579 & 0xffff));
6583 gen_pop_update(s, ot);
6584 set_cc_op(s, CC_OP_EFLAGS);
6585 /* abort translation because TF/AC flag may change */
6586 gen_jmp_im(s->pc - s->cs_base);
6587 gen_eob(s);
6589 break;
6590 case 0x9e: /* sahf */
6591 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6592 goto illegal_op;
6593 gen_op_mov_v_reg(MO_8, cpu_T[0], R_AH);
6594 gen_compute_eflags(s);
6595 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6596 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6597 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
6598 break;
6599 case 0x9f: /* lahf */
6600 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6601 goto illegal_op;
6602 gen_compute_eflags(s);
6603 /* Note: gen_compute_eflags() only gives the condition codes */
6604 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
6605 gen_op_mov_reg_v(MO_8, R_AH, cpu_T[0]);
6606 break;
6607 case 0xf5: /* cmc */
6608 gen_compute_eflags(s);
6609 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6610 break;
6611 case 0xf8: /* clc */
6612 gen_compute_eflags(s);
6613 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6614 break;
6615 case 0xf9: /* stc */
6616 gen_compute_eflags(s);
6617 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6618 break;
6619 case 0xfc: /* cld */
6620 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6621 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6622 break;
6623 case 0xfd: /* std */
6624 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6625 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6626 break;
6628 /************************/
6629 /* bit operations */
6630 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6631 ot = dflag;
6632 modrm = cpu_ldub_code(env, s->pc++);
6633 op = (modrm >> 3) & 7;
6634 mod = (modrm >> 6) & 3;
6635 rm = (modrm & 7) | REX_B(s);
6636 if (mod != 3) {
6637 s->rip_offset = 1;
6638 gen_lea_modrm(env, s, modrm);
6639 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
6640 } else {
6641 gen_op_mov_v_reg(ot, cpu_T[0], rm);
6643 /* load shift */
6644 val = cpu_ldub_code(env, s->pc++);
6645 tcg_gen_movi_tl(cpu_T[1], val);
6646 if (op < 4)
6647 goto illegal_op;
6648 op -= 4;
6649 goto bt_op;
6650 case 0x1a3: /* bt Gv, Ev */
6651 op = 0;
6652 goto do_btx;
6653 case 0x1ab: /* bts */
6654 op = 1;
6655 goto do_btx;
6656 case 0x1b3: /* btr */
6657 op = 2;
6658 goto do_btx;
6659 case 0x1bb: /* btc */
6660 op = 3;
6661 do_btx:
6662 ot = dflag;
6663 modrm = cpu_ldub_code(env, s->pc++);
6664 reg = ((modrm >> 3) & 7) | rex_r;
6665 mod = (modrm >> 6) & 3;
6666 rm = (modrm & 7) | REX_B(s);
6667 gen_op_mov_v_reg(MO_32, cpu_T[1], reg);
6668 if (mod != 3) {
6669 gen_lea_modrm(env, s, modrm);
6670 /* specific case: we need to add a displacement */
6671 gen_exts(ot, cpu_T[1]);
6672 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
6673 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6674 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
6675 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
6676 } else {
6677 gen_op_mov_v_reg(ot, cpu_T[0], rm);
6679 bt_op:
6680 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
6681 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6682 switch(op) {
6683 case 0:
6684 break;
6685 case 1:
6686 tcg_gen_movi_tl(cpu_tmp0, 1);
6687 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6688 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6689 break;
6690 case 2:
6691 tcg_gen_movi_tl(cpu_tmp0, 1);
6692 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6693 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6694 break;
6695 default:
6696 case 3:
6697 tcg_gen_movi_tl(cpu_tmp0, 1);
6698 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6699 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6700 break;
6702 if (op != 0) {
6703 if (mod != 3) {
6704 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
6705 } else {
6706 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
6710 /* Delay all CC updates until after the store above. Note that
6711 C is the result of the test, Z is unchanged, and the others
6712 are all undefined. */
6713 switch (s->cc_op) {
6714 case CC_OP_MULB ... CC_OP_MULQ:
6715 case CC_OP_ADDB ... CC_OP_ADDQ:
6716 case CC_OP_ADCB ... CC_OP_ADCQ:
6717 case CC_OP_SUBB ... CC_OP_SUBQ:
6718 case CC_OP_SBBB ... CC_OP_SBBQ:
6719 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6720 case CC_OP_INCB ... CC_OP_INCQ:
6721 case CC_OP_DECB ... CC_OP_DECQ:
6722 case CC_OP_SHLB ... CC_OP_SHLQ:
6723 case CC_OP_SARB ... CC_OP_SARQ:
6724 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6725 /* Z was going to be computed from the non-zero status of CC_DST.
6726 We can get that same Z value (and the new C value) by leaving
6727 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6728 same width. */
6729 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6730 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6731 break;
6732 default:
6733 /* Otherwise, generate EFLAGS and replace the C bit. */
6734 gen_compute_eflags(s);
6735 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6736 ctz32(CC_C), 1);
6737 break;
6739 break;
6740 case 0x1bc: /* bsf / tzcnt */
6741 case 0x1bd: /* bsr / lzcnt */
6742 ot = dflag;
6743 modrm = cpu_ldub_code(env, s->pc++);
6744 reg = ((modrm >> 3) & 7) | rex_r;
6745 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6746 gen_extu(ot, cpu_T[0]);
6748 /* Note that lzcnt and tzcnt are in different extensions. */
6749 if ((prefixes & PREFIX_REPZ)
6750 && (b & 1
6751 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6752 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6753 int size = 8 << ot;
6754 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
6755 if (b & 1) {
6756 /* For lzcnt, reduce the target_ulong result by the
6757 number of zeros that we expect to find at the top. */
6758 gen_helper_clz(cpu_T[0], cpu_T[0]);
6759 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - size);
6760 } else {
6761 /* For tzcnt, a zero input must return the operand size:
6762 force all bits outside the operand size to 1. */
6763 target_ulong mask = (target_ulong)-2 << (size - 1);
6764 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], mask);
6765 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6767 /* For lzcnt/tzcnt, C and Z bits are defined and are
6768 related to the result. */
6769 gen_op_update1_cc();
6770 set_cc_op(s, CC_OP_BMILGB + ot);
6771 } else {
6772 /* For bsr/bsf, only the Z bit is defined and it is related
6773 to the input and not the result. */
6774 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
6775 set_cc_op(s, CC_OP_LOGICB + ot);
6776 if (b & 1) {
6777 /* For bsr, return the bit index of the first 1 bit,
6778 not the count of leading zeros. */
6779 gen_helper_clz(cpu_T[0], cpu_T[0]);
6780 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - 1);
6781 } else {
6782 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6784 /* ??? The manual says that the output is undefined when the
6785 input is zero, but real hardware leaves it unchanged, and
6786 real programs appear to depend on that. */
6787 tcg_gen_movi_tl(cpu_tmp0, 0);
6788 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[0], cpu_cc_dst, cpu_tmp0,
6789 cpu_regs[reg], cpu_T[0]);
6791 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
6792 break;
6793 /************************/
6794 /* bcd */
6795 case 0x27: /* daa */
6796 if (CODE64(s))
6797 goto illegal_op;
6798 gen_update_cc_op(s);
6799 gen_helper_daa(cpu_env);
6800 set_cc_op(s, CC_OP_EFLAGS);
6801 break;
6802 case 0x2f: /* das */
6803 if (CODE64(s))
6804 goto illegal_op;
6805 gen_update_cc_op(s);
6806 gen_helper_das(cpu_env);
6807 set_cc_op(s, CC_OP_EFLAGS);
6808 break;
6809 case 0x37: /* aaa */
6810 if (CODE64(s))
6811 goto illegal_op;
6812 gen_update_cc_op(s);
6813 gen_helper_aaa(cpu_env);
6814 set_cc_op(s, CC_OP_EFLAGS);
6815 break;
6816 case 0x3f: /* aas */
6817 if (CODE64(s))
6818 goto illegal_op;
6819 gen_update_cc_op(s);
6820 gen_helper_aas(cpu_env);
6821 set_cc_op(s, CC_OP_EFLAGS);
6822 break;
6823 case 0xd4: /* aam */
6824 if (CODE64(s))
6825 goto illegal_op;
6826 val = cpu_ldub_code(env, s->pc++);
6827 if (val == 0) {
6828 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6829 } else {
6830 gen_helper_aam(cpu_env, tcg_const_i32(val));
6831 set_cc_op(s, CC_OP_LOGICB);
6833 break;
6834 case 0xd5: /* aad */
6835 if (CODE64(s))
6836 goto illegal_op;
6837 val = cpu_ldub_code(env, s->pc++);
6838 gen_helper_aad(cpu_env, tcg_const_i32(val));
6839 set_cc_op(s, CC_OP_LOGICB);
6840 break;
6841 /************************/
6842 /* misc */
6843 case 0x90: /* nop */
6844 /* XXX: correct lock test for all insn */
6845 if (prefixes & PREFIX_LOCK) {
6846 goto illegal_op;
6848 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6849 if (REX_B(s)) {
6850 goto do_xchg_reg_eax;
6852 if (prefixes & PREFIX_REPZ) {
6853 gen_update_cc_op(s);
6854 gen_jmp_im(pc_start - s->cs_base);
6855 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6856 s->is_jmp = DISAS_TB_JUMP;
6858 break;
6859 case 0x9b: /* fwait */
6860 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6861 (HF_MP_MASK | HF_TS_MASK)) {
6862 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6863 } else {
6864 gen_helper_fwait(cpu_env);
6866 break;
6867 case 0xcc: /* int3 */
6868 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6869 break;
6870 case 0xcd: /* int N */
6871 val = cpu_ldub_code(env, s->pc++);
6872 if (s->vm86 && s->iopl != 3) {
6873 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6874 } else {
6875 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6877 break;
6878 case 0xce: /* into */
6879 if (CODE64(s))
6880 goto illegal_op;
6881 gen_update_cc_op(s);
6882 gen_jmp_im(pc_start - s->cs_base);
6883 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6884 break;
6885 #ifdef WANT_ICEBP
6886 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6887 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6888 #if 1
6889 gen_debug(s, pc_start - s->cs_base);
6890 #else
6891 /* start debug */
6892 tb_flush(CPU(x86_env_get_cpu(env)));
6893 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6894 #endif
6895 break;
6896 #endif
6897 case 0xfa: /* cli */
6898 if (!s->vm86) {
6899 if (s->cpl <= s->iopl) {
6900 gen_helper_cli(cpu_env);
6901 } else {
6902 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6904 } else {
6905 if (s->iopl == 3) {
6906 gen_helper_cli(cpu_env);
6907 } else {
6908 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6911 break;
6912 case 0xfb: /* sti */
6913 if (!s->vm86) {
6914 if (s->cpl <= s->iopl) {
6915 gen_sti:
6916 gen_helper_sti(cpu_env);
6917 /* interruptions are enabled only the first insn after sti */
6918 /* If several instructions disable interrupts, only the
6919 _first_ does it */
6920 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
6921 gen_helper_set_inhibit_irq(cpu_env);
6922 /* give a chance to handle pending irqs */
6923 gen_jmp_im(s->pc - s->cs_base);
6924 gen_eob(s);
6925 } else {
6926 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6928 } else {
6929 if (s->iopl == 3) {
6930 goto gen_sti;
6931 } else {
6932 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6935 break;
6936 case 0x62: /* bound */
6937 if (CODE64(s))
6938 goto illegal_op;
6939 ot = dflag;
6940 modrm = cpu_ldub_code(env, s->pc++);
6941 reg = (modrm >> 3) & 7;
6942 mod = (modrm >> 6) & 3;
6943 if (mod == 3)
6944 goto illegal_op;
6945 gen_op_mov_v_reg(ot, cpu_T[0], reg);
6946 gen_lea_modrm(env, s, modrm);
6947 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6948 if (ot == MO_16) {
6949 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
6950 } else {
6951 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
6953 break;
6954 case 0x1c8 ... 0x1cf: /* bswap reg */
6955 reg = (b & 7) | REX_B(s);
6956 #ifdef TARGET_X86_64
6957 if (dflag == MO_64) {
6958 gen_op_mov_v_reg(MO_64, cpu_T[0], reg);
6959 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
6960 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
6961 } else
6962 #endif
6964 gen_op_mov_v_reg(MO_32, cpu_T[0], reg);
6965 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
6966 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
6967 gen_op_mov_reg_v(MO_32, reg, cpu_T[0]);
6969 break;
6970 case 0xd6: /* salc */
6971 if (CODE64(s))
6972 goto illegal_op;
6973 gen_compute_eflags_c(s, cpu_T[0]);
6974 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
6975 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
6976 break;
6977 case 0xe0: /* loopnz */
6978 case 0xe1: /* loopz */
6979 case 0xe2: /* loop */
6980 case 0xe3: /* jecxz */
6982 TCGLabel *l1, *l2, *l3;
6984 tval = (int8_t)insn_get(env, s, MO_8);
6985 next_eip = s->pc - s->cs_base;
6986 tval += next_eip;
6987 if (dflag == MO_16) {
6988 tval &= 0xffff;
6991 l1 = gen_new_label();
6992 l2 = gen_new_label();
6993 l3 = gen_new_label();
6994 b &= 3;
6995 switch(b) {
6996 case 0: /* loopnz */
6997 case 1: /* loopz */
6998 gen_op_add_reg_im(s->aflag, R_ECX, -1);
6999 gen_op_jz_ecx(s->aflag, l3);
7000 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7001 break;
7002 case 2: /* loop */
7003 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7004 gen_op_jnz_ecx(s->aflag, l1);
7005 break;
7006 default:
7007 case 3: /* jcxz */
7008 gen_op_jz_ecx(s->aflag, l1);
7009 break;
7012 gen_set_label(l3);
7013 gen_jmp_im(next_eip);
7014 tcg_gen_br(l2);
7016 gen_set_label(l1);
7017 gen_jmp_im(tval);
7018 gen_set_label(l2);
7019 gen_eob(s);
7021 break;
7022 case 0x130: /* wrmsr */
7023 case 0x132: /* rdmsr */
7024 if (s->cpl != 0) {
7025 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7026 } else {
7027 gen_update_cc_op(s);
7028 gen_jmp_im(pc_start - s->cs_base);
7029 if (b & 2) {
7030 gen_helper_rdmsr(cpu_env);
7031 } else {
7032 gen_helper_wrmsr(cpu_env);
7035 break;
7036 case 0x131: /* rdtsc */
7037 gen_update_cc_op(s);
7038 gen_jmp_im(pc_start - s->cs_base);
7039 if (s->tb->cflags & CF_USE_ICOUNT) {
7040 gen_io_start();
7042 gen_helper_rdtsc(cpu_env);
7043 if (s->tb->cflags & CF_USE_ICOUNT) {
7044 gen_io_end();
7045 gen_jmp(s, s->pc - s->cs_base);
7047 break;
7048 case 0x133: /* rdpmc */
7049 gen_update_cc_op(s);
7050 gen_jmp_im(pc_start - s->cs_base);
7051 gen_helper_rdpmc(cpu_env);
7052 break;
7053 case 0x134: /* sysenter */
7054 /* For Intel SYSENTER is valid on 64-bit */
7055 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7056 goto illegal_op;
7057 if (!s->pe) {
7058 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7059 } else {
7060 gen_helper_sysenter(cpu_env);
7061 gen_eob(s);
7063 break;
7064 case 0x135: /* sysexit */
7065 /* For Intel SYSEXIT is valid on 64-bit */
7066 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7067 goto illegal_op;
7068 if (!s->pe) {
7069 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7070 } else {
7071 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7072 gen_eob(s);
7074 break;
7075 #ifdef TARGET_X86_64
7076 case 0x105: /* syscall */
7077 /* XXX: is it usable in real mode ? */
7078 gen_update_cc_op(s);
7079 gen_jmp_im(pc_start - s->cs_base);
7080 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7081 gen_eob(s);
7082 break;
7083 case 0x107: /* sysret */
7084 if (!s->pe) {
7085 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7086 } else {
7087 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7088 /* condition codes are modified only in long mode */
7089 if (s->lma) {
7090 set_cc_op(s, CC_OP_EFLAGS);
7092 gen_eob(s);
7094 break;
7095 #endif
7096 case 0x1a2: /* cpuid */
7097 gen_update_cc_op(s);
7098 gen_jmp_im(pc_start - s->cs_base);
7099 gen_helper_cpuid(cpu_env);
7100 break;
7101 case 0xf4: /* hlt */
7102 if (s->cpl != 0) {
7103 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7104 } else {
7105 gen_update_cc_op(s);
7106 gen_jmp_im(pc_start - s->cs_base);
7107 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7108 s->is_jmp = DISAS_TB_JUMP;
7110 break;
7111 case 0x100:
7112 modrm = cpu_ldub_code(env, s->pc++);
7113 mod = (modrm >> 6) & 3;
7114 op = (modrm >> 3) & 7;
7115 switch(op) {
7116 case 0: /* sldt */
7117 if (!s->pe || s->vm86)
7118 goto illegal_op;
7119 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7120 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
7121 ot = mod == 3 ? dflag : MO_16;
7122 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7123 break;
7124 case 2: /* lldt */
7125 if (!s->pe || s->vm86)
7126 goto illegal_op;
7127 if (s->cpl != 0) {
7128 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7129 } else {
7130 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7131 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7132 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7133 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7135 break;
7136 case 1: /* str */
7137 if (!s->pe || s->vm86)
7138 goto illegal_op;
7139 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7140 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
7141 ot = mod == 3 ? dflag : MO_16;
7142 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7143 break;
7144 case 3: /* ltr */
7145 if (!s->pe || s->vm86)
7146 goto illegal_op;
7147 if (s->cpl != 0) {
7148 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7149 } else {
7150 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7151 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7152 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7153 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7155 break;
7156 case 4: /* verr */
7157 case 5: /* verw */
7158 if (!s->pe || s->vm86)
7159 goto illegal_op;
7160 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7161 gen_update_cc_op(s);
7162 if (op == 4) {
7163 gen_helper_verr(cpu_env, cpu_T[0]);
7164 } else {
7165 gen_helper_verw(cpu_env, cpu_T[0]);
7167 set_cc_op(s, CC_OP_EFLAGS);
7168 break;
7169 default:
7170 goto illegal_op;
7172 break;
7173 case 0x101:
7174 modrm = cpu_ldub_code(env, s->pc++);
7175 mod = (modrm >> 6) & 3;
7176 op = (modrm >> 3) & 7;
7177 rm = modrm & 7;
7178 switch(op) {
7179 case 0: /* sgdt */
7180 if (mod == 3)
7181 goto illegal_op;
7182 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7183 gen_lea_modrm(env, s, modrm);
7184 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
7185 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
7186 gen_add_A0_im(s, 2);
7187 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
7188 if (dflag == MO_16) {
7189 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7191 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7192 break;
7193 case 1:
7194 if (mod == 3) {
7195 switch (rm) {
7196 case 0: /* monitor */
7197 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7198 s->cpl != 0)
7199 goto illegal_op;
7200 gen_update_cc_op(s);
7201 gen_jmp_im(pc_start - s->cs_base);
7202 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7203 gen_extu(s->aflag, cpu_A0);
7204 gen_add_A0_ds_seg(s);
7205 gen_helper_monitor(cpu_env, cpu_A0);
7206 break;
7207 case 1: /* mwait */
7208 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7209 s->cpl != 0)
7210 goto illegal_op;
7211 gen_update_cc_op(s);
7212 gen_jmp_im(pc_start - s->cs_base);
7213 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7214 gen_eob(s);
7215 break;
7216 case 2: /* clac */
7217 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7218 s->cpl != 0) {
7219 goto illegal_op;
7221 gen_helper_clac(cpu_env);
7222 gen_jmp_im(s->pc - s->cs_base);
7223 gen_eob(s);
7224 break;
7225 case 3: /* stac */
7226 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7227 s->cpl != 0) {
7228 goto illegal_op;
7230 gen_helper_stac(cpu_env);
7231 gen_jmp_im(s->pc - s->cs_base);
7232 gen_eob(s);
7233 break;
7234 default:
7235 goto illegal_op;
7237 } else { /* sidt */
7238 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7239 gen_lea_modrm(env, s, modrm);
7240 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
7241 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
7242 gen_add_A0_im(s, 2);
7243 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
7244 if (dflag == MO_16) {
7245 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7247 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7249 break;
7250 case 2: /* lgdt */
7251 case 3: /* lidt */
7252 if (mod == 3) {
7253 gen_update_cc_op(s);
7254 gen_jmp_im(pc_start - s->cs_base);
7255 switch(rm) {
7256 case 0: /* VMRUN */
7257 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7258 goto illegal_op;
7259 if (s->cpl != 0) {
7260 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7261 break;
7262 } else {
7263 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7264 tcg_const_i32(s->pc - pc_start));
7265 tcg_gen_exit_tb(0);
7266 s->is_jmp = DISAS_TB_JUMP;
7268 break;
7269 case 1: /* VMMCALL */
7270 if (!(s->flags & HF_SVME_MASK))
7271 goto illegal_op;
7272 gen_helper_vmmcall(cpu_env);
7273 break;
7274 case 2: /* VMLOAD */
7275 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7276 goto illegal_op;
7277 if (s->cpl != 0) {
7278 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7279 break;
7280 } else {
7281 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7283 break;
7284 case 3: /* VMSAVE */
7285 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7286 goto illegal_op;
7287 if (s->cpl != 0) {
7288 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7289 break;
7290 } else {
7291 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7293 break;
7294 case 4: /* STGI */
7295 if ((!(s->flags & HF_SVME_MASK) &&
7296 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7297 !s->pe)
7298 goto illegal_op;
7299 if (s->cpl != 0) {
7300 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7301 break;
7302 } else {
7303 gen_helper_stgi(cpu_env);
7305 break;
7306 case 5: /* CLGI */
7307 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7308 goto illegal_op;
7309 if (s->cpl != 0) {
7310 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7311 break;
7312 } else {
7313 gen_helper_clgi(cpu_env);
7315 break;
7316 case 6: /* SKINIT */
7317 if ((!(s->flags & HF_SVME_MASK) &&
7318 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7319 !s->pe)
7320 goto illegal_op;
7321 gen_helper_skinit(cpu_env);
7322 break;
7323 case 7: /* INVLPGA */
7324 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7325 goto illegal_op;
7326 if (s->cpl != 0) {
7327 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7328 break;
7329 } else {
7330 gen_helper_invlpga(cpu_env,
7331 tcg_const_i32(s->aflag - 1));
7333 break;
7334 default:
7335 goto illegal_op;
7337 } else if (s->cpl != 0) {
7338 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7339 } else {
7340 gen_svm_check_intercept(s, pc_start,
7341 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
7342 gen_lea_modrm(env, s, modrm);
7343 gen_op_ld_v(s, MO_16, cpu_T[1], cpu_A0);
7344 gen_add_A0_im(s, 2);
7345 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7346 if (dflag == MO_16) {
7347 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7349 if (op == 2) {
7350 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7351 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
7352 } else {
7353 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7354 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
7357 break;
7358 case 4: /* smsw */
7359 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7360 #if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
7361 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7362 #else
7363 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
7364 #endif
7365 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 1);
7366 break;
7367 case 6: /* lmsw */
7368 if (s->cpl != 0) {
7369 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7370 } else {
7371 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7372 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7373 gen_helper_lmsw(cpu_env, cpu_T[0]);
7374 gen_jmp_im(s->pc - s->cs_base);
7375 gen_eob(s);
7377 break;
7378 case 7:
7379 if (mod != 3) { /* invlpg */
7380 if (s->cpl != 0) {
7381 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7382 } else {
7383 gen_update_cc_op(s);
7384 gen_jmp_im(pc_start - s->cs_base);
7385 gen_lea_modrm(env, s, modrm);
7386 gen_helper_invlpg(cpu_env, cpu_A0);
7387 gen_jmp_im(s->pc - s->cs_base);
7388 gen_eob(s);
7390 } else {
7391 switch (rm) {
7392 case 0: /* swapgs */
7393 #ifdef TARGET_X86_64
7394 if (CODE64(s)) {
7395 if (s->cpl != 0) {
7396 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7397 } else {
7398 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7399 offsetof(CPUX86State,segs[R_GS].base));
7400 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7401 offsetof(CPUX86State,kernelgsbase));
7402 tcg_gen_st_tl(cpu_T[1], cpu_env,
7403 offsetof(CPUX86State,segs[R_GS].base));
7404 tcg_gen_st_tl(cpu_T[0], cpu_env,
7405 offsetof(CPUX86State,kernelgsbase));
7407 } else
7408 #endif
7410 goto illegal_op;
7412 break;
7413 case 1: /* rdtscp */
7414 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7415 goto illegal_op;
7416 gen_update_cc_op(s);
7417 gen_jmp_im(pc_start - s->cs_base);
7418 if (s->tb->cflags & CF_USE_ICOUNT) {
7419 gen_io_start();
7421 gen_helper_rdtscp(cpu_env);
7422 if (s->tb->cflags & CF_USE_ICOUNT) {
7423 gen_io_end();
7424 gen_jmp(s, s->pc - s->cs_base);
7426 break;
7427 default:
7428 goto illegal_op;
7431 break;
7432 default:
7433 goto illegal_op;
7435 break;
7436 case 0x108: /* invd */
7437 case 0x109: /* wbinvd */
7438 if (s->cpl != 0) {
7439 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7440 } else {
7441 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7442 /* nothing to do */
7444 break;
7445 case 0x63: /* arpl or movslS (x86_64) */
7446 #ifdef TARGET_X86_64
7447 if (CODE64(s)) {
7448 int d_ot;
7449 /* d_ot is the size of destination */
7450 d_ot = dflag;
7452 modrm = cpu_ldub_code(env, s->pc++);
7453 reg = ((modrm >> 3) & 7) | rex_r;
7454 mod = (modrm >> 6) & 3;
7455 rm = (modrm & 7) | REX_B(s);
7457 if (mod == 3) {
7458 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
7459 /* sign extend */
7460 if (d_ot == MO_64) {
7461 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
7463 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
7464 } else {
7465 gen_lea_modrm(env, s, modrm);
7466 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
7467 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
7469 } else
7470 #endif
7472 TCGLabel *label1;
7473 TCGv t0, t1, t2, a0;
7475 if (!s->pe || s->vm86)
7476 goto illegal_op;
7477 t0 = tcg_temp_local_new();
7478 t1 = tcg_temp_local_new();
7479 t2 = tcg_temp_local_new();
7480 ot = MO_16;
7481 modrm = cpu_ldub_code(env, s->pc++);
7482 reg = (modrm >> 3) & 7;
7483 mod = (modrm >> 6) & 3;
7484 rm = modrm & 7;
7485 if (mod != 3) {
7486 gen_lea_modrm(env, s, modrm);
7487 gen_op_ld_v(s, ot, t0, cpu_A0);
7488 a0 = tcg_temp_local_new();
7489 tcg_gen_mov_tl(a0, cpu_A0);
7490 } else {
7491 gen_op_mov_v_reg(ot, t0, rm);
7492 TCGV_UNUSED(a0);
7494 gen_op_mov_v_reg(ot, t1, reg);
7495 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7496 tcg_gen_andi_tl(t1, t1, 3);
7497 tcg_gen_movi_tl(t2, 0);
7498 label1 = gen_new_label();
7499 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7500 tcg_gen_andi_tl(t0, t0, ~3);
7501 tcg_gen_or_tl(t0, t0, t1);
7502 tcg_gen_movi_tl(t2, CC_Z);
7503 gen_set_label(label1);
7504 if (mod != 3) {
7505 gen_op_st_v(s, ot, t0, a0);
7506 tcg_temp_free(a0);
7507 } else {
7508 gen_op_mov_reg_v(ot, rm, t0);
7510 gen_compute_eflags(s);
7511 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7512 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7513 tcg_temp_free(t0);
7514 tcg_temp_free(t1);
7515 tcg_temp_free(t2);
7517 break;
7518 case 0x102: /* lar */
7519 case 0x103: /* lsl */
7521 TCGLabel *label1;
7522 TCGv t0;
7523 if (!s->pe || s->vm86)
7524 goto illegal_op;
7525 ot = dflag != MO_16 ? MO_32 : MO_16;
7526 modrm = cpu_ldub_code(env, s->pc++);
7527 reg = ((modrm >> 3) & 7) | rex_r;
7528 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7529 t0 = tcg_temp_local_new();
7530 gen_update_cc_op(s);
7531 if (b == 0x102) {
7532 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7533 } else {
7534 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7536 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7537 label1 = gen_new_label();
7538 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7539 gen_op_mov_reg_v(ot, reg, t0);
7540 gen_set_label(label1);
7541 set_cc_op(s, CC_OP_EFLAGS);
7542 tcg_temp_free(t0);
7544 break;
7545 case 0x118:
7546 modrm = cpu_ldub_code(env, s->pc++);
7547 mod = (modrm >> 6) & 3;
7548 op = (modrm >> 3) & 7;
7549 switch(op) {
7550 case 0: /* prefetchnta */
7551 case 1: /* prefetchnt0 */
7552 case 2: /* prefetchnt0 */
7553 case 3: /* prefetchnt0 */
7554 if (mod == 3)
7555 goto illegal_op;
7556 gen_lea_modrm(env, s, modrm);
7557 /* nothing more to do */
7558 break;
7559 default: /* nop (multi byte) */
7560 gen_nop_modrm(env, s, modrm);
7561 break;
7563 break;
7564 case 0x119 ... 0x11f: /* nop (multi byte) */
7565 modrm = cpu_ldub_code(env, s->pc++);
7566 gen_nop_modrm(env, s, modrm);
7567 break;
7568 case 0x120: /* mov reg, crN */
7569 case 0x122: /* mov crN, reg */
7570 if (s->cpl != 0) {
7571 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7572 } else {
7573 modrm = cpu_ldub_code(env, s->pc++);
7574 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7575 * AMD documentation (24594.pdf) and testing of
7576 * intel 386 and 486 processors all show that the mod bits
7577 * are assumed to be 1's, regardless of actual values.
7579 rm = (modrm & 7) | REX_B(s);
7580 reg = ((modrm >> 3) & 7) | rex_r;
7581 if (CODE64(s))
7582 ot = MO_64;
7583 else
7584 ot = MO_32;
7585 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7586 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7587 reg = 8;
7589 switch(reg) {
7590 case 0:
7591 case 2:
7592 case 3:
7593 case 4:
7594 case 8:
7595 gen_update_cc_op(s);
7596 gen_jmp_im(pc_start - s->cs_base);
7597 if (b & 2) {
7598 gen_op_mov_v_reg(ot, cpu_T[0], rm);
7599 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7600 cpu_T[0]);
7601 gen_jmp_im(s->pc - s->cs_base);
7602 gen_eob(s);
7603 } else {
7604 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
7605 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
7607 break;
7608 default:
7609 goto illegal_op;
7612 break;
7613 case 0x121: /* mov reg, drN */
7614 case 0x123: /* mov drN, reg */
7615 if (s->cpl != 0) {
7616 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7617 } else {
7618 modrm = cpu_ldub_code(env, s->pc++);
7619 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7620 * AMD documentation (24594.pdf) and testing of
7621 * intel 386 and 486 processors all show that the mod bits
7622 * are assumed to be 1's, regardless of actual values.
7624 rm = (modrm & 7) | REX_B(s);
7625 reg = ((modrm >> 3) & 7) | rex_r;
7626 if (CODE64(s))
7627 ot = MO_64;
7628 else
7629 ot = MO_32;
7630 if (reg >= 8) {
7631 goto illegal_op;
7633 if (b & 2) {
7634 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7635 gen_op_mov_v_reg(ot, cpu_T[0], rm);
7636 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7637 gen_helper_set_dr(cpu_env, cpu_tmp2_i32, cpu_T[0]);
7638 gen_jmp_im(s->pc - s->cs_base);
7639 gen_eob(s);
7640 } else {
7641 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7642 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
7643 gen_helper_get_dr(cpu_T[0], cpu_env, cpu_tmp2_i32);
7644 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
7647 break;
7648 case 0x106: /* clts */
7649 if (s->cpl != 0) {
7650 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7651 } else {
7652 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7653 gen_helper_clts(cpu_env);
7654 /* abort block because static cpu state changed */
7655 gen_jmp_im(s->pc - s->cs_base);
7656 gen_eob(s);
7658 break;
7659 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
7660 case 0x1c3: /* MOVNTI reg, mem */
7661 if (!(s->cpuid_features & CPUID_SSE2))
7662 goto illegal_op;
7663 ot = mo_64_32(dflag);
7664 modrm = cpu_ldub_code(env, s->pc++);
7665 mod = (modrm >> 6) & 3;
7666 if (mod == 3)
7667 goto illegal_op;
7668 reg = ((modrm >> 3) & 7) | rex_r;
7669 /* generate a generic store */
7670 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
7671 break;
7672 case 0x1ae:
7673 modrm = cpu_ldub_code(env, s->pc++);
7674 mod = (modrm >> 6) & 3;
7675 op = (modrm >> 3) & 7;
7676 switch(op) {
7677 case 0: /* fxsave */
7678 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7679 (s->prefix & PREFIX_LOCK))
7680 goto illegal_op;
7681 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7682 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7683 break;
7685 gen_lea_modrm(env, s, modrm);
7686 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
7687 break;
7688 case 1: /* fxrstor */
7689 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7690 (s->prefix & PREFIX_LOCK))
7691 goto illegal_op;
7692 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7693 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7694 break;
7696 gen_lea_modrm(env, s, modrm);
7697 gen_helper_fxrstor(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
7698 break;
7699 case 2: /* ldmxcsr */
7700 case 3: /* stmxcsr */
7701 if (s->flags & HF_TS_MASK) {
7702 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7703 break;
7705 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7706 mod == 3)
7707 goto illegal_op;
7708 gen_lea_modrm(env, s, modrm);
7709 if (op == 2) {
7710 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
7711 s->mem_index, MO_LEUL);
7712 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
7713 } else {
7714 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
7715 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
7717 break;
7718 case 5: /* lfence */
7719 case 6: /* mfence */
7720 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
7721 goto illegal_op;
7722 break;
7723 case 7: /* sfence / clflush */
7724 if ((modrm & 0xc7) == 0xc0) {
7725 /* sfence */
7726 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
7727 if (!(s->cpuid_features & CPUID_SSE))
7728 goto illegal_op;
7729 } else {
7730 /* clflush */
7731 if (!(s->cpuid_features & CPUID_CLFLUSH))
7732 goto illegal_op;
7733 gen_lea_modrm(env, s, modrm);
7735 break;
7736 default:
7737 goto illegal_op;
7739 break;
7740 case 0x10d: /* 3DNow! prefetch(w) */
7741 modrm = cpu_ldub_code(env, s->pc++);
7742 mod = (modrm >> 6) & 3;
7743 if (mod == 3)
7744 goto illegal_op;
7745 gen_lea_modrm(env, s, modrm);
7746 /* ignore for now */
7747 break;
7748 case 0x1aa: /* rsm */
7749 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
7750 if (!(s->flags & HF_SMM_MASK))
7751 goto illegal_op;
7752 gen_update_cc_op(s);
7753 gen_jmp_im(s->pc - s->cs_base);
7754 gen_helper_rsm(cpu_env);
7755 gen_eob(s);
7756 break;
7757 case 0x1b8: /* SSE4.2 popcnt */
7758 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
7759 PREFIX_REPZ)
7760 goto illegal_op;
7761 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
7762 goto illegal_op;
7764 modrm = cpu_ldub_code(env, s->pc++);
7765 reg = ((modrm >> 3) & 7) | rex_r;
7767 if (s->prefix & PREFIX_DATA) {
7768 ot = MO_16;
7769 } else {
7770 ot = mo_64_32(dflag);
7773 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7774 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
7775 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
7777 set_cc_op(s, CC_OP_EFLAGS);
7778 break;
7779 case 0x10e ... 0x10f:
7780 /* 3DNow! instructions, ignore prefixes */
7781 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
7782 case 0x110 ... 0x117:
7783 case 0x128 ... 0x12f:
7784 case 0x138 ... 0x13a:
7785 case 0x150 ... 0x179:
7786 case 0x17c ... 0x17f:
7787 case 0x1c2:
7788 case 0x1c4 ... 0x1c6:
7789 case 0x1d0 ... 0x1fe:
7790 gen_sse(env, s, b, pc_start, rex_r);
7791 break;
7792 default:
7793 goto illegal_op;
7795 /* lock generation */
7796 if (s->prefix & PREFIX_LOCK)
7797 gen_helper_unlock();
7798 return s->pc;
7799 illegal_op:
7800 if (s->prefix & PREFIX_LOCK)
7801 gen_helper_unlock();
7802 /* XXX: ensure that no lock was generated */
7803 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7804 return s->pc;
7807 void optimize_flags_init(void)
7809 static const char reg_names[CPU_NB_REGS][4] = {
7810 #ifdef TARGET_X86_64
7811 [R_EAX] = "rax",
7812 [R_EBX] = "rbx",
7813 [R_ECX] = "rcx",
7814 [R_EDX] = "rdx",
7815 [R_ESI] = "rsi",
7816 [R_EDI] = "rdi",
7817 [R_EBP] = "rbp",
7818 [R_ESP] = "rsp",
7819 [8] = "r8",
7820 [9] = "r9",
7821 [10] = "r10",
7822 [11] = "r11",
7823 [12] = "r12",
7824 [13] = "r13",
7825 [14] = "r14",
7826 [15] = "r15",
7827 #else
7828 [R_EAX] = "eax",
7829 [R_EBX] = "ebx",
7830 [R_ECX] = "ecx",
7831 [R_EDX] = "edx",
7832 [R_ESI] = "esi",
7833 [R_EDI] = "edi",
7834 [R_EBP] = "ebp",
7835 [R_ESP] = "esp",
7836 #endif
7838 int i;
7840 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7841 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
7842 offsetof(CPUX86State, cc_op), "cc_op");
7843 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
7844 "cc_dst");
7845 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
7846 "cc_src");
7847 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
7848 "cc_src2");
7850 for (i = 0; i < CPU_NB_REGS; ++i) {
7851 cpu_regs[i] = tcg_global_mem_new(TCG_AREG0,
7852 offsetof(CPUX86State, regs[i]),
7853 reg_names[i]);
7856 helper_lock_init();
7859 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7860 basic block 'tb'. */
7861 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
7863 X86CPU *cpu = x86_env_get_cpu(env);
7864 CPUState *cs = CPU(cpu);
7865 DisasContext dc1, *dc = &dc1;
7866 target_ulong pc_ptr;
7867 uint64_t flags;
7868 target_ulong pc_start;
7869 target_ulong cs_base;
7870 int num_insns;
7871 int max_insns;
7873 /* generate intermediate code */
7874 pc_start = tb->pc;
7875 cs_base = tb->cs_base;
7876 flags = tb->flags;
7878 dc->pe = (flags >> HF_PE_SHIFT) & 1;
7879 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7880 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7881 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7882 dc->f_st = 0;
7883 dc->vm86 = (flags >> VM_SHIFT) & 1;
7884 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7885 dc->iopl = (flags >> IOPL_SHIFT) & 3;
7886 dc->tf = (flags >> TF_SHIFT) & 1;
7887 dc->singlestep_enabled = cs->singlestep_enabled;
7888 dc->cc_op = CC_OP_DYNAMIC;
7889 dc->cc_op_dirty = false;
7890 dc->cs_base = cs_base;
7891 dc->tb = tb;
7892 dc->popl_esp_hack = 0;
7893 /* select memory access functions */
7894 dc->mem_index = 0;
7895 if (flags & HF_SOFTMMU_MASK) {
7896 dc->mem_index = cpu_mmu_index(env, false);
7898 dc->cpuid_features = env->features[FEAT_1_EDX];
7899 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
7900 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
7901 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
7902 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
7903 #ifdef TARGET_X86_64
7904 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7905 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7906 #endif
7907 dc->flags = flags;
7908 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
7909 (flags & HF_INHIBIT_IRQ_MASK)
7910 #ifndef CONFIG_SOFTMMU
7911 || (flags & HF_SOFTMMU_MASK)
7912 #endif
7914 /* Do not optimize repz jumps at all in icount mode, because
7915 rep movsS instructions are execured with different paths
7916 in !repz_opt and repz_opt modes. The first one was used
7917 always except single step mode. And this setting
7918 disables jumps optimization and control paths become
7919 equivalent in run and single step modes.
7920 Now there will be no jump optimization for repz in
7921 record/replay modes and there will always be an
7922 additional step for ecx=0 when icount is enabled.
7924 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
7925 #if 0
7926 /* check addseg logic */
7927 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
7928 printf("ERROR addseg\n");
7929 #endif
7931 cpu_T[0] = tcg_temp_new();
7932 cpu_T[1] = tcg_temp_new();
7933 cpu_A0 = tcg_temp_new();
7935 cpu_tmp0 = tcg_temp_new();
7936 cpu_tmp1_i64 = tcg_temp_new_i64();
7937 cpu_tmp2_i32 = tcg_temp_new_i32();
7938 cpu_tmp3_i32 = tcg_temp_new_i32();
7939 cpu_tmp4 = tcg_temp_new();
7940 cpu_ptr0 = tcg_temp_new_ptr();
7941 cpu_ptr1 = tcg_temp_new_ptr();
7942 cpu_cc_srcT = tcg_temp_local_new();
7944 dc->is_jmp = DISAS_NEXT;
7945 pc_ptr = pc_start;
7946 num_insns = 0;
7947 max_insns = tb->cflags & CF_COUNT_MASK;
7948 if (max_insns == 0) {
7949 max_insns = CF_COUNT_MASK;
7951 if (max_insns > TCG_MAX_INSNS) {
7952 max_insns = TCG_MAX_INSNS;
7955 gen_tb_start(tb);
7956 for(;;) {
7957 tcg_gen_insn_start(pc_ptr, dc->cc_op);
7958 num_insns++;
7960 /* If RF is set, suppress an internally generated breakpoint. */
7961 if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
7962 tb->flags & HF_RF_MASK
7963 ? BP_GDB : BP_ANY))) {
7964 gen_debug(dc, pc_ptr - dc->cs_base);
7965 goto done_generating;
7967 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
7968 gen_io_start();
7971 pc_ptr = disas_insn(env, dc, pc_ptr);
7972 /* stop translation if indicated */
7973 if (dc->is_jmp)
7974 break;
7975 /* if single step mode, we generate only one instruction and
7976 generate an exception */
7977 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
7978 the flag and abort the translation to give the irqs a
7979 change to be happen */
7980 if (dc->tf || dc->singlestep_enabled ||
7981 (flags & HF_INHIBIT_IRQ_MASK)) {
7982 gen_jmp_im(pc_ptr - dc->cs_base);
7983 gen_eob(dc);
7984 break;
7986 /* Do not cross the boundary of the pages in icount mode,
7987 it can cause an exception. Do it only when boundary is
7988 crossed by the first instruction in the block.
7989 If current instruction already crossed the bound - it's ok,
7990 because an exception hasn't stopped this code.
7992 if ((tb->cflags & CF_USE_ICOUNT)
7993 && ((pc_ptr & TARGET_PAGE_MASK)
7994 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
7995 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
7996 gen_jmp_im(pc_ptr - dc->cs_base);
7997 gen_eob(dc);
7998 break;
8000 /* if too long translation, stop generation too */
8001 if (tcg_op_buf_full() ||
8002 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8003 num_insns >= max_insns) {
8004 gen_jmp_im(pc_ptr - dc->cs_base);
8005 gen_eob(dc);
8006 break;
8008 if (singlestep) {
8009 gen_jmp_im(pc_ptr - dc->cs_base);
8010 gen_eob(dc);
8011 break;
8014 if (tb->cflags & CF_LAST_IO)
8015 gen_io_end();
8016 done_generating:
8017 gen_tb_end(tb, num_insns);
8019 #ifdef DEBUG_DISAS
8020 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8021 int disas_flags;
8022 qemu_log("----------------\n");
8023 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8024 #ifdef TARGET_X86_64
8025 if (dc->code64)
8026 disas_flags = 2;
8027 else
8028 #endif
8029 disas_flags = !dc->code32;
8030 log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
8031 qemu_log("\n");
8033 #endif
8035 tb->size = pc_ptr - pc_start;
8036 tb->icount = num_insns;
8039 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8040 target_ulong *data)
8042 int cc_op = data[1];
8043 env->eip = data[0] - tb->cs_base;
8044 if (cc_op != CC_OP_DYNAMIC) {
8045 env->cc_op = cc_op;