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