target-i386: Remove gen_op_ldu_T0_A0
[qemu.git] / target-i386 / translate.c
blob97bbc1fa7109723b3bb32d5996a08c49d7eb2f65
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"
31 #include "helper.h"
32 #define GEN_HELPER 1
33 #include "helper.h"
35 #define PREFIX_REPZ 0x01
36 #define PREFIX_REPNZ 0x02
37 #define PREFIX_LOCK 0x04
38 #define PREFIX_DATA 0x08
39 #define PREFIX_ADR 0x10
40 #define PREFIX_VEX 0x20
42 #ifdef TARGET_X86_64
43 #define CODE64(s) ((s)->code64)
44 #define REX_X(s) ((s)->rex_x)
45 #define REX_B(s) ((s)->rex_b)
46 #else
47 #define CODE64(s) 0
48 #define REX_X(s) 0
49 #define REX_B(s) 0
50 #endif
52 #ifdef TARGET_X86_64
53 # define ctztl ctz64
54 # define clztl clz64
55 #else
56 # define ctztl ctz32
57 # define clztl clz32
58 #endif
60 //#define MACRO_TEST 1
62 /* global register indexes */
63 static TCGv_ptr cpu_env;
64 static TCGv cpu_A0;
65 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
66 static TCGv_i32 cpu_cc_op;
67 static TCGv cpu_regs[CPU_NB_REGS];
68 /* local temps */
69 static TCGv cpu_T[2];
70 /* local register indexes (only used inside old micro ops) */
71 static TCGv cpu_tmp0, cpu_tmp4;
72 static TCGv_ptr cpu_ptr0, cpu_ptr1;
73 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
74 static TCGv_i64 cpu_tmp1_i64;
76 static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
78 #include "exec/gen-icount.h"
80 #ifdef TARGET_X86_64
81 static int x86_64_hregs;
82 #endif
84 typedef struct DisasContext {
85 /* current insn context */
86 int override; /* -1 if no override */
87 int prefix;
88 int aflag, dflag;
89 target_ulong pc; /* pc = eip + cs_base */
90 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
91 static state change (stop translation) */
92 /* current block context */
93 target_ulong cs_base; /* base of CS segment */
94 int pe; /* protected mode */
95 int code32; /* 32 bit code segment */
96 #ifdef TARGET_X86_64
97 int lma; /* long mode active */
98 int code64; /* 64 bit code segment */
99 int rex_x, rex_b;
100 #endif
101 int vex_l; /* vex vector length */
102 int vex_v; /* vex vvvv register, without 1's compliment. */
103 int ss32; /* 32 bit stack segment */
104 CCOp cc_op; /* current CC operation */
105 bool cc_op_dirty;
106 int addseg; /* non zero if either DS/ES/SS have a non zero base */
107 int f_st; /* currently unused */
108 int vm86; /* vm86 mode */
109 int cpl;
110 int iopl;
111 int tf; /* TF cpu flag */
112 int singlestep_enabled; /* "hardware" single step enabled */
113 int jmp_opt; /* use direct block chaining for direct jumps */
114 int mem_index; /* select memory access functions */
115 uint64_t flags; /* all execution flags */
116 struct TranslationBlock *tb;
117 int popl_esp_hack; /* for correct popl with esp base handling */
118 int rip_offset; /* only used in x86_64, but left for simplicity */
119 int cpuid_features;
120 int cpuid_ext_features;
121 int cpuid_ext2_features;
122 int cpuid_ext3_features;
123 int cpuid_7_0_ebx_features;
124 } DisasContext;
126 static void gen_eob(DisasContext *s);
127 static void gen_jmp(DisasContext *s, target_ulong eip);
128 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
129 static void gen_op(DisasContext *s1, int op, int ot, int d);
131 /* i386 arith/logic operations */
132 enum {
133 OP_ADDL,
134 OP_ORL,
135 OP_ADCL,
136 OP_SBBL,
137 OP_ANDL,
138 OP_SUBL,
139 OP_XORL,
140 OP_CMPL,
143 /* i386 shift ops */
144 enum {
145 OP_ROL,
146 OP_ROR,
147 OP_RCL,
148 OP_RCR,
149 OP_SHL,
150 OP_SHR,
151 OP_SHL1, /* undocumented */
152 OP_SAR = 7,
155 enum {
156 JCC_O,
157 JCC_B,
158 JCC_Z,
159 JCC_BE,
160 JCC_S,
161 JCC_P,
162 JCC_L,
163 JCC_LE,
166 enum {
167 /* I386 int registers */
168 OR_EAX, /* MUST be even numbered */
169 OR_ECX,
170 OR_EDX,
171 OR_EBX,
172 OR_ESP,
173 OR_EBP,
174 OR_ESI,
175 OR_EDI,
177 OR_TMP0 = 16, /* temporary operand register */
178 OR_TMP1,
179 OR_A0, /* temporary register used when doing address evaluation */
182 enum {
183 USES_CC_DST = 1,
184 USES_CC_SRC = 2,
185 USES_CC_SRC2 = 4,
186 USES_CC_SRCT = 8,
189 /* Bit set if the global variable is live after setting CC_OP to X. */
190 static const uint8_t cc_op_live[CC_OP_NB] = {
191 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
192 [CC_OP_EFLAGS] = USES_CC_SRC,
193 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
194 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
195 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
196 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
197 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
198 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
199 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
200 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
201 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
202 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
203 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
204 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
205 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
206 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
207 [CC_OP_CLR] = 0,
210 static void set_cc_op(DisasContext *s, CCOp op)
212 int dead;
214 if (s->cc_op == op) {
215 return;
218 /* Discard CC computation that will no longer be used. */
219 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
220 if (dead & USES_CC_DST) {
221 tcg_gen_discard_tl(cpu_cc_dst);
223 if (dead & USES_CC_SRC) {
224 tcg_gen_discard_tl(cpu_cc_src);
226 if (dead & USES_CC_SRC2) {
227 tcg_gen_discard_tl(cpu_cc_src2);
229 if (dead & USES_CC_SRCT) {
230 tcg_gen_discard_tl(cpu_cc_srcT);
233 if (op == CC_OP_DYNAMIC) {
234 /* The DYNAMIC setting is translator only, and should never be
235 stored. Thus we always consider it clean. */
236 s->cc_op_dirty = false;
237 } else {
238 /* Discard any computed CC_OP value (see shifts). */
239 if (s->cc_op == CC_OP_DYNAMIC) {
240 tcg_gen_discard_i32(cpu_cc_op);
242 s->cc_op_dirty = true;
244 s->cc_op = op;
247 static void gen_update_cc_op(DisasContext *s)
249 if (s->cc_op_dirty) {
250 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
251 s->cc_op_dirty = false;
255 static inline void gen_op_movl_T0_0(void)
257 tcg_gen_movi_tl(cpu_T[0], 0);
260 static inline void gen_op_movl_T0_im(int32_t val)
262 tcg_gen_movi_tl(cpu_T[0], val);
265 static inline void gen_op_movl_T0_imu(uint32_t val)
267 tcg_gen_movi_tl(cpu_T[0], val);
270 static inline void gen_op_movl_T1_im(int32_t val)
272 tcg_gen_movi_tl(cpu_T[1], val);
275 static inline void gen_op_movl_T1_imu(uint32_t val)
277 tcg_gen_movi_tl(cpu_T[1], val);
280 static inline void gen_op_movl_A0_im(uint32_t val)
282 tcg_gen_movi_tl(cpu_A0, val);
285 #ifdef TARGET_X86_64
286 static inline void gen_op_movq_A0_im(int64_t val)
288 tcg_gen_movi_tl(cpu_A0, val);
290 #endif
292 static inline void gen_movtl_T0_im(target_ulong val)
294 tcg_gen_movi_tl(cpu_T[0], val);
297 static inline void gen_movtl_T1_im(target_ulong val)
299 tcg_gen_movi_tl(cpu_T[1], val);
302 static inline void gen_op_andl_T0_ffff(void)
304 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
307 static inline void gen_op_andl_T0_im(uint32_t val)
309 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
312 static inline void gen_op_movl_T0_T1(void)
314 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
317 static inline void gen_op_andl_A0_ffff(void)
319 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
322 #ifdef TARGET_X86_64
324 #define NB_OP_SIZES 4
326 #else /* !TARGET_X86_64 */
328 #define NB_OP_SIZES 3
330 #endif /* !TARGET_X86_64 */
332 #if defined(HOST_WORDS_BIGENDIAN)
333 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
334 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
335 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
336 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
337 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
338 #else
339 #define REG_B_OFFSET 0
340 #define REG_H_OFFSET 1
341 #define REG_W_OFFSET 0
342 #define REG_L_OFFSET 0
343 #define REG_LH_OFFSET 4
344 #endif
346 /* In instruction encodings for byte register accesses the
347 * register number usually indicates "low 8 bits of register N";
348 * however there are some special cases where N 4..7 indicates
349 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
350 * true for this special case, false otherwise.
352 static inline bool byte_reg_is_xH(int reg)
354 if (reg < 4) {
355 return false;
357 #ifdef TARGET_X86_64
358 if (reg >= 8 || x86_64_hregs) {
359 return false;
361 #endif
362 return true;
365 static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
367 switch(ot) {
368 case MO_8:
369 if (!byte_reg_is_xH(reg)) {
370 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
371 } else {
372 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
374 break;
375 case MO_16:
376 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
377 break;
378 default: /* XXX this shouldn't be reached; abort? */
379 case MO_32:
380 /* For x86_64, this sets the higher half of register to zero.
381 For i386, this is equivalent to a mov. */
382 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
383 break;
384 #ifdef TARGET_X86_64
385 case MO_64:
386 tcg_gen_mov_tl(cpu_regs[reg], t0);
387 break;
388 #endif
392 static inline void gen_op_mov_reg_T0(int ot, int reg)
394 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
397 static inline void gen_op_mov_reg_T1(int ot, int reg)
399 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
402 static inline void gen_op_mov_reg_A0(int size, int reg)
404 switch(size) {
405 case MO_8:
406 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
407 break;
408 default: /* XXX this shouldn't be reached; abort? */
409 case MO_16:
410 /* For x86_64, this sets the higher half of register to zero.
411 For i386, this is equivalent to a mov. */
412 tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
413 break;
414 #ifdef TARGET_X86_64
415 case MO_32:
416 tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
417 break;
418 #endif
422 static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
424 if (ot == MO_8 && byte_reg_is_xH(reg)) {
425 tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
426 tcg_gen_ext8u_tl(t0, t0);
427 } else {
428 tcg_gen_mov_tl(t0, cpu_regs[reg]);
432 static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
434 gen_op_mov_v_reg(ot, cpu_T[t_index], reg);
437 static inline void gen_op_movl_A0_reg(int reg)
439 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
442 static inline void gen_op_addl_A0_im(int32_t val)
444 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
445 #ifdef TARGET_X86_64
446 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
447 #endif
450 #ifdef TARGET_X86_64
451 static inline void gen_op_addq_A0_im(int64_t val)
453 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
455 #endif
457 static void gen_add_A0_im(DisasContext *s, int val)
459 #ifdef TARGET_X86_64
460 if (CODE64(s))
461 gen_op_addq_A0_im(val);
462 else
463 #endif
464 gen_op_addl_A0_im(val);
467 static inline void gen_op_addl_T0_T1(void)
469 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
472 static inline void gen_op_jmp_T0(void)
474 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
477 static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
479 switch(size) {
480 case MO_8:
481 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
482 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
483 break;
484 case MO_16:
485 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
486 /* For x86_64, this sets the higher half of register to zero.
487 For i386, this is equivalent to a nop. */
488 tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
489 tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
490 break;
491 #ifdef TARGET_X86_64
492 case MO_32:
493 tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
494 break;
495 #endif
499 static inline void gen_op_add_reg_T0(int size, int reg)
501 switch(size) {
502 case MO_8:
503 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
504 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
505 break;
506 case MO_16:
507 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
508 /* For x86_64, this sets the higher half of register to zero.
509 For i386, this is equivalent to a nop. */
510 tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
511 tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
512 break;
513 #ifdef TARGET_X86_64
514 case MO_32:
515 tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
516 break;
517 #endif
521 static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
523 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
524 if (shift != 0)
525 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
526 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
527 /* For x86_64, this sets the higher half of register to zero.
528 For i386, this is equivalent to a nop. */
529 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
532 static inline void gen_op_movl_A0_seg(int reg)
534 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
537 static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
539 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
540 #ifdef TARGET_X86_64
541 if (CODE64(s)) {
542 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
543 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
544 } else {
545 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
546 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
548 #else
549 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
550 #endif
553 #ifdef TARGET_X86_64
554 static inline void gen_op_movq_A0_seg(int reg)
556 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
559 static inline void gen_op_addq_A0_seg(int reg)
561 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
562 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
565 static inline void gen_op_movq_A0_reg(int reg)
567 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
570 static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
572 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
573 if (shift != 0)
574 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
575 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
577 #endif
579 static inline void gen_op_lds_T0_A0(DisasContext *s, int idx)
581 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0, s->mem_index, idx | MO_LE | MO_SIGN);
584 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
586 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
589 static inline void gen_op_ld_T1_A0(DisasContext *s, int idx)
591 gen_op_ld_v(s, idx, cpu_T[1], cpu_A0);
594 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
596 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
599 static inline void gen_op_st_T0_A0(DisasContext *s, int idx)
601 gen_op_st_v(s, idx, cpu_T[0], cpu_A0);
604 static inline void gen_op_st_T1_A0(DisasContext *s, int idx)
606 gen_op_st_v(s, idx, cpu_T[1], cpu_A0);
609 static inline void gen_jmp_im(target_ulong pc)
611 tcg_gen_movi_tl(cpu_tmp0, pc);
612 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, eip));
615 static inline void gen_string_movl_A0_ESI(DisasContext *s)
617 int override;
619 override = s->override;
620 #ifdef TARGET_X86_64
621 if (s->aflag == 2) {
622 if (override >= 0) {
623 gen_op_movq_A0_seg(override);
624 gen_op_addq_A0_reg_sN(0, R_ESI);
625 } else {
626 gen_op_movq_A0_reg(R_ESI);
628 } else
629 #endif
630 if (s->aflag) {
631 /* 32 bit address */
632 if (s->addseg && override < 0)
633 override = R_DS;
634 if (override >= 0) {
635 gen_op_movl_A0_seg(override);
636 gen_op_addl_A0_reg_sN(0, R_ESI);
637 } else {
638 gen_op_movl_A0_reg(R_ESI);
640 } else {
641 /* 16 address, always override */
642 if (override < 0)
643 override = R_DS;
644 gen_op_movl_A0_reg(R_ESI);
645 gen_op_andl_A0_ffff();
646 gen_op_addl_A0_seg(s, override);
650 static inline void gen_string_movl_A0_EDI(DisasContext *s)
652 #ifdef TARGET_X86_64
653 if (s->aflag == 2) {
654 gen_op_movq_A0_reg(R_EDI);
655 } else
656 #endif
657 if (s->aflag) {
658 if (s->addseg) {
659 gen_op_movl_A0_seg(R_ES);
660 gen_op_addl_A0_reg_sN(0, R_EDI);
661 } else {
662 gen_op_movl_A0_reg(R_EDI);
664 } else {
665 gen_op_movl_A0_reg(R_EDI);
666 gen_op_andl_A0_ffff();
667 gen_op_addl_A0_seg(s, R_ES);
671 static inline void gen_op_movl_T0_Dshift(int ot)
673 tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
674 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
677 static TCGv gen_ext_tl(TCGv dst, TCGv src, int size, bool sign)
679 switch (size) {
680 case MO_8:
681 if (sign) {
682 tcg_gen_ext8s_tl(dst, src);
683 } else {
684 tcg_gen_ext8u_tl(dst, src);
686 return dst;
687 case MO_16:
688 if (sign) {
689 tcg_gen_ext16s_tl(dst, src);
690 } else {
691 tcg_gen_ext16u_tl(dst, src);
693 return dst;
694 #ifdef TARGET_X86_64
695 case MO_32:
696 if (sign) {
697 tcg_gen_ext32s_tl(dst, src);
698 } else {
699 tcg_gen_ext32u_tl(dst, src);
701 return dst;
702 #endif
703 default:
704 return src;
708 static void gen_extu(int ot, TCGv reg)
710 gen_ext_tl(reg, reg, ot, false);
713 static void gen_exts(int ot, TCGv reg)
715 gen_ext_tl(reg, reg, ot, true);
718 static inline void gen_op_jnz_ecx(int size, int label1)
720 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
721 gen_extu(size + 1, cpu_tmp0);
722 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
725 static inline void gen_op_jz_ecx(int size, int label1)
727 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
728 gen_extu(size + 1, cpu_tmp0);
729 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
732 static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
734 switch (ot) {
735 case MO_8:
736 gen_helper_inb(v, n);
737 break;
738 case MO_16:
739 gen_helper_inw(v, n);
740 break;
741 case MO_32:
742 gen_helper_inl(v, n);
743 break;
747 static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
749 switch (ot) {
750 case MO_8:
751 gen_helper_outb(v, n);
752 break;
753 case MO_16:
754 gen_helper_outw(v, n);
755 break;
756 case MO_32:
757 gen_helper_outl(v, n);
758 break;
762 static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
763 uint32_t svm_flags)
765 int state_saved;
766 target_ulong next_eip;
768 state_saved = 0;
769 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
770 gen_update_cc_op(s);
771 gen_jmp_im(cur_eip);
772 state_saved = 1;
773 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
774 switch (ot) {
775 case MO_8:
776 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
777 break;
778 case MO_16:
779 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
780 break;
781 case MO_32:
782 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
783 break;
786 if(s->flags & HF_SVMI_MASK) {
787 if (!state_saved) {
788 gen_update_cc_op(s);
789 gen_jmp_im(cur_eip);
791 svm_flags |= (1 << (4 + ot));
792 next_eip = s->pc - s->cs_base;
793 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
794 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
795 tcg_const_i32(svm_flags),
796 tcg_const_i32(next_eip - cur_eip));
800 static inline void gen_movs(DisasContext *s, int ot)
802 gen_string_movl_A0_ESI(s);
803 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
804 gen_string_movl_A0_EDI(s);
805 gen_op_st_T0_A0(s, ot);
806 gen_op_movl_T0_Dshift(ot);
807 gen_op_add_reg_T0(s->aflag, R_ESI);
808 gen_op_add_reg_T0(s->aflag, R_EDI);
811 static void gen_op_update1_cc(void)
813 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
816 static void gen_op_update2_cc(void)
818 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
819 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
822 static void gen_op_update3_cc(TCGv reg)
824 tcg_gen_mov_tl(cpu_cc_src2, reg);
825 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
826 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
829 static inline void gen_op_testl_T0_T1_cc(void)
831 tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
834 static void gen_op_update_neg_cc(void)
836 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
837 tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]);
838 tcg_gen_movi_tl(cpu_cc_srcT, 0);
841 /* compute all eflags to cc_src */
842 static void gen_compute_eflags(DisasContext *s)
844 TCGv zero, dst, src1, src2;
845 int live, dead;
847 if (s->cc_op == CC_OP_EFLAGS) {
848 return;
850 if (s->cc_op == CC_OP_CLR) {
851 tcg_gen_movi_tl(cpu_cc_src, CC_Z);
852 set_cc_op(s, CC_OP_EFLAGS);
853 return;
856 TCGV_UNUSED(zero);
857 dst = cpu_cc_dst;
858 src1 = cpu_cc_src;
859 src2 = cpu_cc_src2;
861 /* Take care to not read values that are not live. */
862 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
863 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
864 if (dead) {
865 zero = tcg_const_tl(0);
866 if (dead & USES_CC_DST) {
867 dst = zero;
869 if (dead & USES_CC_SRC) {
870 src1 = zero;
872 if (dead & USES_CC_SRC2) {
873 src2 = zero;
877 gen_update_cc_op(s);
878 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
879 set_cc_op(s, CC_OP_EFLAGS);
881 if (dead) {
882 tcg_temp_free(zero);
886 typedef struct CCPrepare {
887 TCGCond cond;
888 TCGv reg;
889 TCGv reg2;
890 target_ulong imm;
891 target_ulong mask;
892 bool use_reg2;
893 bool no_setcond;
894 } CCPrepare;
896 /* compute eflags.C to reg */
897 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
899 TCGv t0, t1;
900 int size, shift;
902 switch (s->cc_op) {
903 case CC_OP_SUBB ... CC_OP_SUBQ:
904 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
905 size = s->cc_op - CC_OP_SUBB;
906 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
907 /* If no temporary was used, be careful not to alias t1 and t0. */
908 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
909 tcg_gen_mov_tl(t0, cpu_cc_srcT);
910 gen_extu(size, t0);
911 goto add_sub;
913 case CC_OP_ADDB ... CC_OP_ADDQ:
914 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
915 size = s->cc_op - CC_OP_ADDB;
916 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
917 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
918 add_sub:
919 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
920 .reg2 = t1, .mask = -1, .use_reg2 = true };
922 case CC_OP_LOGICB ... CC_OP_LOGICQ:
923 case CC_OP_CLR:
924 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
926 case CC_OP_INCB ... CC_OP_INCQ:
927 case CC_OP_DECB ... CC_OP_DECQ:
928 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
929 .mask = -1, .no_setcond = true };
931 case CC_OP_SHLB ... CC_OP_SHLQ:
932 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
933 size = s->cc_op - CC_OP_SHLB;
934 shift = (8 << size) - 1;
935 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
936 .mask = (target_ulong)1 << shift };
938 case CC_OP_MULB ... CC_OP_MULQ:
939 return (CCPrepare) { .cond = TCG_COND_NE,
940 .reg = cpu_cc_src, .mask = -1 };
942 case CC_OP_BMILGB ... CC_OP_BMILGQ:
943 size = s->cc_op - CC_OP_BMILGB;
944 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
945 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
947 case CC_OP_ADCX:
948 case CC_OP_ADCOX:
949 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
950 .mask = -1, .no_setcond = true };
952 case CC_OP_EFLAGS:
953 case CC_OP_SARB ... CC_OP_SARQ:
954 /* CC_SRC & 1 */
955 return (CCPrepare) { .cond = TCG_COND_NE,
956 .reg = cpu_cc_src, .mask = CC_C };
958 default:
959 /* The need to compute only C from CC_OP_DYNAMIC is important
960 in efficiently implementing e.g. INC at the start of a TB. */
961 gen_update_cc_op(s);
962 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
963 cpu_cc_src2, cpu_cc_op);
964 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
965 .mask = -1, .no_setcond = true };
969 /* compute eflags.P to reg */
970 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
972 gen_compute_eflags(s);
973 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
974 .mask = CC_P };
977 /* compute eflags.S to reg */
978 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
980 switch (s->cc_op) {
981 case CC_OP_DYNAMIC:
982 gen_compute_eflags(s);
983 /* FALLTHRU */
984 case CC_OP_EFLAGS:
985 case CC_OP_ADCX:
986 case CC_OP_ADOX:
987 case CC_OP_ADCOX:
988 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
989 .mask = CC_S };
990 case CC_OP_CLR:
991 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
992 default:
994 int size = (s->cc_op - CC_OP_ADDB) & 3;
995 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
996 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
1001 /* compute eflags.O to reg */
1002 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
1004 switch (s->cc_op) {
1005 case CC_OP_ADOX:
1006 case CC_OP_ADCOX:
1007 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
1008 .mask = -1, .no_setcond = true };
1009 case CC_OP_CLR:
1010 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
1011 default:
1012 gen_compute_eflags(s);
1013 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1014 .mask = CC_O };
1018 /* compute eflags.Z to reg */
1019 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
1021 switch (s->cc_op) {
1022 case CC_OP_DYNAMIC:
1023 gen_compute_eflags(s);
1024 /* FALLTHRU */
1025 case CC_OP_EFLAGS:
1026 case CC_OP_ADCX:
1027 case CC_OP_ADOX:
1028 case CC_OP_ADCOX:
1029 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1030 .mask = CC_Z };
1031 case CC_OP_CLR:
1032 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
1033 default:
1035 int size = (s->cc_op - CC_OP_ADDB) & 3;
1036 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
1037 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
1042 /* perform a conditional store into register 'reg' according to jump opcode
1043 value 'b'. In the fast case, T0 is guaranted not to be used. */
1044 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
1046 int inv, jcc_op, size, cond;
1047 CCPrepare cc;
1048 TCGv t0;
1050 inv = b & 1;
1051 jcc_op = (b >> 1) & 7;
1053 switch (s->cc_op) {
1054 case CC_OP_SUBB ... CC_OP_SUBQ:
1055 /* We optimize relational operators for the cmp/jcc case. */
1056 size = s->cc_op - CC_OP_SUBB;
1057 switch (jcc_op) {
1058 case JCC_BE:
1059 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
1060 gen_extu(size, cpu_tmp4);
1061 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
1062 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
1063 .reg2 = t0, .mask = -1, .use_reg2 = true };
1064 break;
1066 case JCC_L:
1067 cond = TCG_COND_LT;
1068 goto fast_jcc_l;
1069 case JCC_LE:
1070 cond = TCG_COND_LE;
1071 fast_jcc_l:
1072 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
1073 gen_exts(size, cpu_tmp4);
1074 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
1075 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
1076 .reg2 = t0, .mask = -1, .use_reg2 = true };
1077 break;
1079 default:
1080 goto slow_jcc;
1082 break;
1084 default:
1085 slow_jcc:
1086 /* This actually generates good code for JC, JZ and JS. */
1087 switch (jcc_op) {
1088 case JCC_O:
1089 cc = gen_prepare_eflags_o(s, reg);
1090 break;
1091 case JCC_B:
1092 cc = gen_prepare_eflags_c(s, reg);
1093 break;
1094 case JCC_Z:
1095 cc = gen_prepare_eflags_z(s, reg);
1096 break;
1097 case JCC_BE:
1098 gen_compute_eflags(s);
1099 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1100 .mask = CC_Z | CC_C };
1101 break;
1102 case JCC_S:
1103 cc = gen_prepare_eflags_s(s, reg);
1104 break;
1105 case JCC_P:
1106 cc = gen_prepare_eflags_p(s, reg);
1107 break;
1108 case JCC_L:
1109 gen_compute_eflags(s);
1110 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1111 reg = cpu_tmp0;
1113 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1114 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1115 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1116 .mask = CC_S };
1117 break;
1118 default:
1119 case JCC_LE:
1120 gen_compute_eflags(s);
1121 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1122 reg = cpu_tmp0;
1124 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1125 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1126 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1127 .mask = CC_S | CC_Z };
1128 break;
1130 break;
1133 if (inv) {
1134 cc.cond = tcg_invert_cond(cc.cond);
1136 return cc;
1139 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1141 CCPrepare cc = gen_prepare_cc(s, b, reg);
1143 if (cc.no_setcond) {
1144 if (cc.cond == TCG_COND_EQ) {
1145 tcg_gen_xori_tl(reg, cc.reg, 1);
1146 } else {
1147 tcg_gen_mov_tl(reg, cc.reg);
1149 return;
1152 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1153 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1154 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1155 tcg_gen_andi_tl(reg, reg, 1);
1156 return;
1158 if (cc.mask != -1) {
1159 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1160 cc.reg = reg;
1162 if (cc.use_reg2) {
1163 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1164 } else {
1165 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1169 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1171 gen_setcc1(s, JCC_B << 1, reg);
1174 /* generate a conditional jump to label 'l1' according to jump opcode
1175 value 'b'. In the fast case, T0 is guaranted not to be used. */
1176 static inline void gen_jcc1_noeob(DisasContext *s, int b, int l1)
1178 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1180 if (cc.mask != -1) {
1181 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1182 cc.reg = cpu_T[0];
1184 if (cc.use_reg2) {
1185 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1186 } else {
1187 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1191 /* Generate a conditional jump to label 'l1' according to jump opcode
1192 value 'b'. In the fast case, T0 is guaranted not to be used.
1193 A translation block must end soon. */
1194 static inline void gen_jcc1(DisasContext *s, int b, int l1)
1196 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1198 gen_update_cc_op(s);
1199 if (cc.mask != -1) {
1200 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1201 cc.reg = cpu_T[0];
1203 set_cc_op(s, CC_OP_DYNAMIC);
1204 if (cc.use_reg2) {
1205 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1206 } else {
1207 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1211 /* XXX: does not work with gdbstub "ice" single step - not a
1212 serious problem */
1213 static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1215 int l1, l2;
1217 l1 = gen_new_label();
1218 l2 = gen_new_label();
1219 gen_op_jnz_ecx(s->aflag, l1);
1220 gen_set_label(l2);
1221 gen_jmp_tb(s, next_eip, 1);
1222 gen_set_label(l1);
1223 return l2;
1226 static inline void gen_stos(DisasContext *s, int ot)
1228 gen_op_mov_TN_reg(MO_32, 0, R_EAX);
1229 gen_string_movl_A0_EDI(s);
1230 gen_op_st_T0_A0(s, ot);
1231 gen_op_movl_T0_Dshift(ot);
1232 gen_op_add_reg_T0(s->aflag, R_EDI);
1235 static inline void gen_lods(DisasContext *s, int ot)
1237 gen_string_movl_A0_ESI(s);
1238 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1239 gen_op_mov_reg_T0(ot, R_EAX);
1240 gen_op_movl_T0_Dshift(ot);
1241 gen_op_add_reg_T0(s->aflag, R_ESI);
1244 static inline void gen_scas(DisasContext *s, int ot)
1246 gen_string_movl_A0_EDI(s);
1247 gen_op_ld_T1_A0(s, ot);
1248 gen_op(s, OP_CMPL, ot, R_EAX);
1249 gen_op_movl_T0_Dshift(ot);
1250 gen_op_add_reg_T0(s->aflag, R_EDI);
1253 static inline void gen_cmps(DisasContext *s, int ot)
1255 gen_string_movl_A0_EDI(s);
1256 gen_op_ld_T1_A0(s, ot);
1257 gen_string_movl_A0_ESI(s);
1258 gen_op(s, OP_CMPL, ot, OR_TMP0);
1259 gen_op_movl_T0_Dshift(ot);
1260 gen_op_add_reg_T0(s->aflag, R_ESI);
1261 gen_op_add_reg_T0(s->aflag, R_EDI);
1264 static inline void gen_ins(DisasContext *s, int ot)
1266 if (use_icount)
1267 gen_io_start();
1268 gen_string_movl_A0_EDI(s);
1269 /* Note: we must do this dummy write first to be restartable in
1270 case of page fault. */
1271 gen_op_movl_T0_0();
1272 gen_op_st_T0_A0(s, ot);
1273 gen_op_mov_TN_reg(MO_16, 1, R_EDX);
1274 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1275 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1276 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
1277 gen_op_st_T0_A0(s, ot);
1278 gen_op_movl_T0_Dshift(ot);
1279 gen_op_add_reg_T0(s->aflag, R_EDI);
1280 if (use_icount)
1281 gen_io_end();
1284 static inline void gen_outs(DisasContext *s, int ot)
1286 if (use_icount)
1287 gen_io_start();
1288 gen_string_movl_A0_ESI(s);
1289 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1291 gen_op_mov_TN_reg(MO_16, 1, R_EDX);
1292 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1293 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1294 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
1295 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1297 gen_op_movl_T0_Dshift(ot);
1298 gen_op_add_reg_T0(s->aflag, R_ESI);
1299 if (use_icount)
1300 gen_io_end();
1303 /* same method as Valgrind : we generate jumps to current or next
1304 instruction */
1305 #define GEN_REPZ(op) \
1306 static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1307 target_ulong cur_eip, target_ulong next_eip) \
1309 int l2;\
1310 gen_update_cc_op(s); \
1311 l2 = gen_jz_ecx_string(s, next_eip); \
1312 gen_ ## op(s, ot); \
1313 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1314 /* a loop would cause two single step exceptions if ECX = 1 \
1315 before rep string_insn */ \
1316 if (!s->jmp_opt) \
1317 gen_op_jz_ecx(s->aflag, l2); \
1318 gen_jmp(s, cur_eip); \
1321 #define GEN_REPZ2(op) \
1322 static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1323 target_ulong cur_eip, \
1324 target_ulong next_eip, \
1325 int nz) \
1327 int l2;\
1328 gen_update_cc_op(s); \
1329 l2 = gen_jz_ecx_string(s, next_eip); \
1330 gen_ ## op(s, ot); \
1331 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1332 gen_update_cc_op(s); \
1333 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1334 if (!s->jmp_opt) \
1335 gen_op_jz_ecx(s->aflag, l2); \
1336 gen_jmp(s, cur_eip); \
1339 GEN_REPZ(movs)
1340 GEN_REPZ(stos)
1341 GEN_REPZ(lods)
1342 GEN_REPZ(ins)
1343 GEN_REPZ(outs)
1344 GEN_REPZ2(scas)
1345 GEN_REPZ2(cmps)
1347 static void gen_helper_fp_arith_ST0_FT0(int op)
1349 switch (op) {
1350 case 0:
1351 gen_helper_fadd_ST0_FT0(cpu_env);
1352 break;
1353 case 1:
1354 gen_helper_fmul_ST0_FT0(cpu_env);
1355 break;
1356 case 2:
1357 gen_helper_fcom_ST0_FT0(cpu_env);
1358 break;
1359 case 3:
1360 gen_helper_fcom_ST0_FT0(cpu_env);
1361 break;
1362 case 4:
1363 gen_helper_fsub_ST0_FT0(cpu_env);
1364 break;
1365 case 5:
1366 gen_helper_fsubr_ST0_FT0(cpu_env);
1367 break;
1368 case 6:
1369 gen_helper_fdiv_ST0_FT0(cpu_env);
1370 break;
1371 case 7:
1372 gen_helper_fdivr_ST0_FT0(cpu_env);
1373 break;
1377 /* NOTE the exception in "r" op ordering */
1378 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1380 TCGv_i32 tmp = tcg_const_i32(opreg);
1381 switch (op) {
1382 case 0:
1383 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1384 break;
1385 case 1:
1386 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1387 break;
1388 case 4:
1389 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1390 break;
1391 case 5:
1392 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1393 break;
1394 case 6:
1395 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1396 break;
1397 case 7:
1398 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1399 break;
1403 /* if d == OR_TMP0, it means memory operand (address in A0) */
1404 static void gen_op(DisasContext *s1, int op, int ot, int d)
1406 if (d != OR_TMP0) {
1407 gen_op_mov_TN_reg(ot, 0, d);
1408 } else {
1409 gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
1411 switch(op) {
1412 case OP_ADCL:
1413 gen_compute_eflags_c(s1, cpu_tmp4);
1414 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1415 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1416 if (d != OR_TMP0)
1417 gen_op_mov_reg_T0(ot, d);
1418 else
1419 gen_op_st_T0_A0(s1, ot);
1420 gen_op_update3_cc(cpu_tmp4);
1421 set_cc_op(s1, CC_OP_ADCB + ot);
1422 break;
1423 case OP_SBBL:
1424 gen_compute_eflags_c(s1, cpu_tmp4);
1425 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1426 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1427 if (d != OR_TMP0)
1428 gen_op_mov_reg_T0(ot, d);
1429 else
1430 gen_op_st_T0_A0(s1, ot);
1431 gen_op_update3_cc(cpu_tmp4);
1432 set_cc_op(s1, CC_OP_SBBB + ot);
1433 break;
1434 case OP_ADDL:
1435 gen_op_addl_T0_T1();
1436 if (d != OR_TMP0)
1437 gen_op_mov_reg_T0(ot, d);
1438 else
1439 gen_op_st_T0_A0(s1, ot);
1440 gen_op_update2_cc();
1441 set_cc_op(s1, CC_OP_ADDB + ot);
1442 break;
1443 case OP_SUBL:
1444 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1445 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1446 if (d != OR_TMP0)
1447 gen_op_mov_reg_T0(ot, d);
1448 else
1449 gen_op_st_T0_A0(s1, ot);
1450 gen_op_update2_cc();
1451 set_cc_op(s1, CC_OP_SUBB + ot);
1452 break;
1453 default:
1454 case OP_ANDL:
1455 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1456 if (d != OR_TMP0)
1457 gen_op_mov_reg_T0(ot, d);
1458 else
1459 gen_op_st_T0_A0(s1, ot);
1460 gen_op_update1_cc();
1461 set_cc_op(s1, CC_OP_LOGICB + ot);
1462 break;
1463 case OP_ORL:
1464 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1465 if (d != OR_TMP0)
1466 gen_op_mov_reg_T0(ot, d);
1467 else
1468 gen_op_st_T0_A0(s1, ot);
1469 gen_op_update1_cc();
1470 set_cc_op(s1, CC_OP_LOGICB + ot);
1471 break;
1472 case OP_XORL:
1473 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1474 if (d != OR_TMP0)
1475 gen_op_mov_reg_T0(ot, d);
1476 else
1477 gen_op_st_T0_A0(s1, ot);
1478 gen_op_update1_cc();
1479 set_cc_op(s1, CC_OP_LOGICB + ot);
1480 break;
1481 case OP_CMPL:
1482 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
1483 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1484 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
1485 set_cc_op(s1, CC_OP_SUBB + ot);
1486 break;
1490 /* if d == OR_TMP0, it means memory operand (address in A0) */
1491 static void gen_inc(DisasContext *s1, int ot, int d, int c)
1493 if (d != OR_TMP0) {
1494 gen_op_mov_TN_reg(ot, 0, d);
1495 } else {
1496 gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
1498 gen_compute_eflags_c(s1, cpu_cc_src);
1499 if (c > 0) {
1500 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
1501 set_cc_op(s1, CC_OP_INCB + ot);
1502 } else {
1503 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
1504 set_cc_op(s1, CC_OP_DECB + ot);
1506 if (d != OR_TMP0)
1507 gen_op_mov_reg_T0(ot, d);
1508 else
1509 gen_op_st_T0_A0(s1, ot);
1510 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1513 static void gen_shift_flags(DisasContext *s, int ot, TCGv result, TCGv shm1,
1514 TCGv count, bool is_right)
1516 TCGv_i32 z32, s32, oldop;
1517 TCGv z_tl;
1519 /* Store the results into the CC variables. If we know that the
1520 variable must be dead, store unconditionally. Otherwise we'll
1521 need to not disrupt the current contents. */
1522 z_tl = tcg_const_tl(0);
1523 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1524 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1525 result, cpu_cc_dst);
1526 } else {
1527 tcg_gen_mov_tl(cpu_cc_dst, result);
1529 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1530 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1531 shm1, cpu_cc_src);
1532 } else {
1533 tcg_gen_mov_tl(cpu_cc_src, shm1);
1535 tcg_temp_free(z_tl);
1537 /* Get the two potential CC_OP values into temporaries. */
1538 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1539 if (s->cc_op == CC_OP_DYNAMIC) {
1540 oldop = cpu_cc_op;
1541 } else {
1542 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1543 oldop = cpu_tmp3_i32;
1546 /* Conditionally store the CC_OP value. */
1547 z32 = tcg_const_i32(0);
1548 s32 = tcg_temp_new_i32();
1549 tcg_gen_trunc_tl_i32(s32, count);
1550 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1551 tcg_temp_free_i32(z32);
1552 tcg_temp_free_i32(s32);
1554 /* The CC_OP value is no longer predictable. */
1555 set_cc_op(s, CC_OP_DYNAMIC);
1558 static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
1559 int is_right, int is_arith)
1561 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1563 /* load */
1564 if (op1 == OR_TMP0) {
1565 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1566 } else {
1567 gen_op_mov_TN_reg(ot, 0, op1);
1570 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1571 tcg_gen_subi_tl(cpu_tmp0, cpu_T[1], 1);
1573 if (is_right) {
1574 if (is_arith) {
1575 gen_exts(ot, cpu_T[0]);
1576 tcg_gen_sar_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1577 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1578 } else {
1579 gen_extu(ot, cpu_T[0]);
1580 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1581 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1583 } else {
1584 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1585 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1588 /* store */
1589 if (op1 == OR_TMP0) {
1590 gen_op_st_T0_A0(s, ot);
1591 } else {
1592 gen_op_mov_reg_T0(ot, op1);
1595 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, cpu_T[1], is_right);
1598 static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
1599 int is_right, int is_arith)
1601 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1603 /* load */
1604 if (op1 == OR_TMP0)
1605 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1606 else
1607 gen_op_mov_TN_reg(ot, 0, op1);
1609 op2 &= mask;
1610 if (op2 != 0) {
1611 if (is_right) {
1612 if (is_arith) {
1613 gen_exts(ot, cpu_T[0]);
1614 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1615 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
1616 } else {
1617 gen_extu(ot, cpu_T[0]);
1618 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1619 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
1621 } else {
1622 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1623 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
1627 /* store */
1628 if (op1 == OR_TMP0)
1629 gen_op_st_T0_A0(s, ot);
1630 else
1631 gen_op_mov_reg_T0(ot, op1);
1633 /* update eflags if non zero shift */
1634 if (op2 != 0) {
1635 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1636 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1637 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1641 static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2)
1643 if (arg2 >= 0)
1644 tcg_gen_shli_tl(ret, arg1, arg2);
1645 else
1646 tcg_gen_shri_tl(ret, arg1, -arg2);
1649 static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
1651 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1652 TCGv_i32 t0, t1;
1654 /* load */
1655 if (op1 == OR_TMP0) {
1656 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1657 } else {
1658 gen_op_mov_TN_reg(ot, 0, op1);
1661 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1663 switch (ot) {
1664 case MO_8:
1665 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1666 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
1667 tcg_gen_muli_tl(cpu_T[0], cpu_T[0], 0x01010101);
1668 goto do_long;
1669 case MO_16:
1670 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1671 tcg_gen_deposit_tl(cpu_T[0], cpu_T[0], cpu_T[0], 16, 16);
1672 goto do_long;
1673 do_long:
1674 #ifdef TARGET_X86_64
1675 case MO_32:
1676 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1677 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
1678 if (is_right) {
1679 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1680 } else {
1681 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1683 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1684 break;
1685 #endif
1686 default:
1687 if (is_right) {
1688 tcg_gen_rotr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1689 } else {
1690 tcg_gen_rotl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1692 break;
1695 /* store */
1696 if (op1 == OR_TMP0) {
1697 gen_op_st_T0_A0(s, ot);
1698 } else {
1699 gen_op_mov_reg_T0(ot, op1);
1702 /* We'll need the flags computed into CC_SRC. */
1703 gen_compute_eflags(s);
1705 /* The value that was "rotated out" is now present at the other end
1706 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1707 since we've computed the flags into CC_SRC, these variables are
1708 currently dead. */
1709 if (is_right) {
1710 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1711 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1712 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1713 } else {
1714 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1715 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
1717 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1718 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1720 /* Now conditionally store the new CC_OP value. If the shift count
1721 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1722 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1723 exactly as we computed above. */
1724 t0 = tcg_const_i32(0);
1725 t1 = tcg_temp_new_i32();
1726 tcg_gen_trunc_tl_i32(t1, cpu_T[1]);
1727 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1728 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1729 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1730 cpu_tmp2_i32, cpu_tmp3_i32);
1731 tcg_temp_free_i32(t0);
1732 tcg_temp_free_i32(t1);
1734 /* The CC_OP value is no longer predictable. */
1735 set_cc_op(s, CC_OP_DYNAMIC);
1738 static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
1739 int is_right)
1741 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1742 int shift;
1744 /* load */
1745 if (op1 == OR_TMP0) {
1746 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1747 } else {
1748 gen_op_mov_TN_reg(ot, 0, op1);
1751 op2 &= mask;
1752 if (op2 != 0) {
1753 switch (ot) {
1754 #ifdef TARGET_X86_64
1755 case MO_32:
1756 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1757 if (is_right) {
1758 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1759 } else {
1760 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1762 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1763 break;
1764 #endif
1765 default:
1766 if (is_right) {
1767 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], op2);
1768 } else {
1769 tcg_gen_rotli_tl(cpu_T[0], cpu_T[0], op2);
1771 break;
1772 case MO_8:
1773 mask = 7;
1774 goto do_shifts;
1775 case MO_16:
1776 mask = 15;
1777 do_shifts:
1778 shift = op2 & mask;
1779 if (is_right) {
1780 shift = mask + 1 - shift;
1782 gen_extu(ot, cpu_T[0]);
1783 tcg_gen_shli_tl(cpu_tmp0, cpu_T[0], shift);
1784 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], mask + 1 - shift);
1785 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
1786 break;
1790 /* store */
1791 if (op1 == OR_TMP0) {
1792 gen_op_st_T0_A0(s, ot);
1793 } else {
1794 gen_op_mov_reg_T0(ot, op1);
1797 if (op2 != 0) {
1798 /* Compute the flags into CC_SRC. */
1799 gen_compute_eflags(s);
1801 /* The value that was "rotated out" is now present at the other end
1802 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1803 since we've computed the flags into CC_SRC, these variables are
1804 currently dead. */
1805 if (is_right) {
1806 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1807 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1808 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1809 } else {
1810 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1811 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
1813 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1814 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1815 set_cc_op(s, CC_OP_ADCOX);
1819 /* XXX: add faster immediate = 1 case */
1820 static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
1821 int is_right)
1823 gen_compute_eflags(s);
1824 assert(s->cc_op == CC_OP_EFLAGS);
1826 /* load */
1827 if (op1 == OR_TMP0)
1828 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1829 else
1830 gen_op_mov_TN_reg(ot, 0, op1);
1832 if (is_right) {
1833 switch (ot) {
1834 case MO_8:
1835 gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1836 break;
1837 case MO_16:
1838 gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1839 break;
1840 case MO_32:
1841 gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1842 break;
1843 #ifdef TARGET_X86_64
1844 case MO_64:
1845 gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1846 break;
1847 #endif
1849 } else {
1850 switch (ot) {
1851 case MO_8:
1852 gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1853 break;
1854 case MO_16:
1855 gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1856 break;
1857 case MO_32:
1858 gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1859 break;
1860 #ifdef TARGET_X86_64
1861 case MO_64:
1862 gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1863 break;
1864 #endif
1867 /* store */
1868 if (op1 == OR_TMP0)
1869 gen_op_st_T0_A0(s, ot);
1870 else
1871 gen_op_mov_reg_T0(ot, op1);
1874 /* XXX: add faster immediate case */
1875 static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
1876 bool is_right, TCGv count_in)
1878 target_ulong mask = (ot == MO_64 ? 63 : 31);
1879 TCGv count;
1881 /* load */
1882 if (op1 == OR_TMP0) {
1883 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1884 } else {
1885 gen_op_mov_TN_reg(ot, 0, op1);
1888 count = tcg_temp_new();
1889 tcg_gen_andi_tl(count, count_in, mask);
1891 switch (ot) {
1892 case MO_16:
1893 /* Note: we implement the Intel behaviour for shift count > 16.
1894 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1895 portion by constructing it as a 32-bit value. */
1896 if (is_right) {
1897 tcg_gen_deposit_tl(cpu_tmp0, cpu_T[0], cpu_T[1], 16, 16);
1898 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1899 tcg_gen_mov_tl(cpu_T[0], cpu_tmp0);
1900 } else {
1901 tcg_gen_deposit_tl(cpu_T[1], cpu_T[0], cpu_T[1], 16, 16);
1903 /* FALLTHRU */
1904 #ifdef TARGET_X86_64
1905 case MO_32:
1906 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1907 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1908 if (is_right) {
1909 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
1910 tcg_gen_shr_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1911 tcg_gen_shr_i64(cpu_T[0], cpu_T[0], count);
1912 } else {
1913 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[1], cpu_T[0]);
1914 tcg_gen_shl_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1915 tcg_gen_shl_i64(cpu_T[0], cpu_T[0], count);
1916 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1917 tcg_gen_shri_i64(cpu_T[0], cpu_T[0], 32);
1919 break;
1920 #endif
1921 default:
1922 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1923 if (is_right) {
1924 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1926 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1927 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], count);
1928 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
1929 } else {
1930 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1931 if (ot == MO_16) {
1932 /* Only needed if count > 16, for Intel behaviour. */
1933 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1934 tcg_gen_shr_tl(cpu_tmp4, cpu_T[1], cpu_tmp4);
1935 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1938 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1939 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], count);
1940 tcg_gen_shr_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
1942 tcg_gen_movi_tl(cpu_tmp4, 0);
1943 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[1], count, cpu_tmp4,
1944 cpu_tmp4, cpu_T[1]);
1945 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1946 break;
1949 /* store */
1950 if (op1 == OR_TMP0) {
1951 gen_op_st_T0_A0(s, ot);
1952 } else {
1953 gen_op_mov_reg_T0(ot, op1);
1956 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, count, is_right);
1957 tcg_temp_free(count);
1960 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1962 if (s != OR_TMP1)
1963 gen_op_mov_TN_reg(ot, 1, s);
1964 switch(op) {
1965 case OP_ROL:
1966 gen_rot_rm_T1(s1, ot, d, 0);
1967 break;
1968 case OP_ROR:
1969 gen_rot_rm_T1(s1, ot, d, 1);
1970 break;
1971 case OP_SHL:
1972 case OP_SHL1:
1973 gen_shift_rm_T1(s1, ot, d, 0, 0);
1974 break;
1975 case OP_SHR:
1976 gen_shift_rm_T1(s1, ot, d, 1, 0);
1977 break;
1978 case OP_SAR:
1979 gen_shift_rm_T1(s1, ot, d, 1, 1);
1980 break;
1981 case OP_RCL:
1982 gen_rotc_rm_T1(s1, ot, d, 0);
1983 break;
1984 case OP_RCR:
1985 gen_rotc_rm_T1(s1, ot, d, 1);
1986 break;
1990 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1992 switch(op) {
1993 case OP_ROL:
1994 gen_rot_rm_im(s1, ot, d, c, 0);
1995 break;
1996 case OP_ROR:
1997 gen_rot_rm_im(s1, ot, d, c, 1);
1998 break;
1999 case OP_SHL:
2000 case OP_SHL1:
2001 gen_shift_rm_im(s1, ot, d, c, 0, 0);
2002 break;
2003 case OP_SHR:
2004 gen_shift_rm_im(s1, ot, d, c, 1, 0);
2005 break;
2006 case OP_SAR:
2007 gen_shift_rm_im(s1, ot, d, c, 1, 1);
2008 break;
2009 default:
2010 /* currently not optimized */
2011 gen_op_movl_T1_im(c);
2012 gen_shift(s1, op, ot, d, OR_TMP1);
2013 break;
2017 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm,
2018 int *reg_ptr, int *offset_ptr)
2020 target_long disp;
2021 int havesib;
2022 int base;
2023 int index;
2024 int scale;
2025 int opreg;
2026 int mod, rm, code, override, must_add_seg;
2027 TCGv sum;
2029 override = s->override;
2030 must_add_seg = s->addseg;
2031 if (override >= 0)
2032 must_add_seg = 1;
2033 mod = (modrm >> 6) & 3;
2034 rm = modrm & 7;
2036 if (s->aflag) {
2037 havesib = 0;
2038 base = rm;
2039 index = -1;
2040 scale = 0;
2042 if (base == 4) {
2043 havesib = 1;
2044 code = cpu_ldub_code(env, s->pc++);
2045 scale = (code >> 6) & 3;
2046 index = ((code >> 3) & 7) | REX_X(s);
2047 if (index == 4) {
2048 index = -1; /* no index */
2050 base = (code & 7);
2052 base |= REX_B(s);
2054 switch (mod) {
2055 case 0:
2056 if ((base & 7) == 5) {
2057 base = -1;
2058 disp = (int32_t)cpu_ldl_code(env, s->pc);
2059 s->pc += 4;
2060 if (CODE64(s) && !havesib) {
2061 disp += s->pc + s->rip_offset;
2063 } else {
2064 disp = 0;
2066 break;
2067 case 1:
2068 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2069 break;
2070 default:
2071 case 2:
2072 disp = (int32_t)cpu_ldl_code(env, s->pc);
2073 s->pc += 4;
2074 break;
2077 /* For correct popl handling with esp. */
2078 if (base == R_ESP && s->popl_esp_hack) {
2079 disp += s->popl_esp_hack;
2082 /* Compute the address, with a minimum number of TCG ops. */
2083 TCGV_UNUSED(sum);
2084 if (index >= 0) {
2085 if (scale == 0) {
2086 sum = cpu_regs[index];
2087 } else {
2088 tcg_gen_shli_tl(cpu_A0, cpu_regs[index], scale);
2089 sum = cpu_A0;
2091 if (base >= 0) {
2092 tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]);
2093 sum = cpu_A0;
2095 } else if (base >= 0) {
2096 sum = cpu_regs[base];
2098 if (TCGV_IS_UNUSED(sum)) {
2099 tcg_gen_movi_tl(cpu_A0, disp);
2100 } else {
2101 tcg_gen_addi_tl(cpu_A0, sum, disp);
2104 if (must_add_seg) {
2105 if (override < 0) {
2106 if (base == R_EBP || base == R_ESP) {
2107 override = R_SS;
2108 } else {
2109 override = R_DS;
2113 tcg_gen_ld_tl(cpu_tmp0, cpu_env,
2114 offsetof(CPUX86State, segs[override].base));
2115 if (CODE64(s)) {
2116 if (s->aflag != 2) {
2117 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
2119 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
2120 goto done;
2123 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
2126 if (s->aflag != 2) {
2127 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
2129 } else {
2130 switch (mod) {
2131 case 0:
2132 if (rm == 6) {
2133 disp = cpu_lduw_code(env, s->pc);
2134 s->pc += 2;
2135 gen_op_movl_A0_im(disp);
2136 rm = 0; /* avoid SS override */
2137 goto no_rm;
2138 } else {
2139 disp = 0;
2141 break;
2142 case 1:
2143 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2144 break;
2145 default:
2146 case 2:
2147 disp = cpu_lduw_code(env, s->pc);
2148 s->pc += 2;
2149 break;
2151 switch(rm) {
2152 case 0:
2153 gen_op_movl_A0_reg(R_EBX);
2154 gen_op_addl_A0_reg_sN(0, R_ESI);
2155 break;
2156 case 1:
2157 gen_op_movl_A0_reg(R_EBX);
2158 gen_op_addl_A0_reg_sN(0, R_EDI);
2159 break;
2160 case 2:
2161 gen_op_movl_A0_reg(R_EBP);
2162 gen_op_addl_A0_reg_sN(0, R_ESI);
2163 break;
2164 case 3:
2165 gen_op_movl_A0_reg(R_EBP);
2166 gen_op_addl_A0_reg_sN(0, R_EDI);
2167 break;
2168 case 4:
2169 gen_op_movl_A0_reg(R_ESI);
2170 break;
2171 case 5:
2172 gen_op_movl_A0_reg(R_EDI);
2173 break;
2174 case 6:
2175 gen_op_movl_A0_reg(R_EBP);
2176 break;
2177 default:
2178 case 7:
2179 gen_op_movl_A0_reg(R_EBX);
2180 break;
2182 if (disp != 0)
2183 gen_op_addl_A0_im(disp);
2184 gen_op_andl_A0_ffff();
2185 no_rm:
2186 if (must_add_seg) {
2187 if (override < 0) {
2188 if (rm == 2 || rm == 3 || rm == 6)
2189 override = R_SS;
2190 else
2191 override = R_DS;
2193 gen_op_addl_A0_seg(s, override);
2197 done:
2198 opreg = OR_A0;
2199 disp = 0;
2200 *reg_ptr = opreg;
2201 *offset_ptr = disp;
2204 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2206 int mod, rm, base, code;
2208 mod = (modrm >> 6) & 3;
2209 if (mod == 3)
2210 return;
2211 rm = modrm & 7;
2213 if (s->aflag) {
2215 base = rm;
2217 if (base == 4) {
2218 code = cpu_ldub_code(env, s->pc++);
2219 base = (code & 7);
2222 switch (mod) {
2223 case 0:
2224 if (base == 5) {
2225 s->pc += 4;
2227 break;
2228 case 1:
2229 s->pc++;
2230 break;
2231 default:
2232 case 2:
2233 s->pc += 4;
2234 break;
2236 } else {
2237 switch (mod) {
2238 case 0:
2239 if (rm == 6) {
2240 s->pc += 2;
2242 break;
2243 case 1:
2244 s->pc++;
2245 break;
2246 default:
2247 case 2:
2248 s->pc += 2;
2249 break;
2254 /* used for LEA and MOV AX, mem */
2255 static void gen_add_A0_ds_seg(DisasContext *s)
2257 int override, must_add_seg;
2258 must_add_seg = s->addseg;
2259 override = R_DS;
2260 if (s->override >= 0) {
2261 override = s->override;
2262 must_add_seg = 1;
2264 if (must_add_seg) {
2265 #ifdef TARGET_X86_64
2266 if (CODE64(s)) {
2267 gen_op_addq_A0_seg(override);
2268 } else
2269 #endif
2271 gen_op_addl_A0_seg(s, override);
2276 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2277 OR_TMP0 */
2278 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2279 int ot, int reg, int is_store)
2281 int mod, rm, opreg, disp;
2283 mod = (modrm >> 6) & 3;
2284 rm = (modrm & 7) | REX_B(s);
2285 if (mod == 3) {
2286 if (is_store) {
2287 if (reg != OR_TMP0)
2288 gen_op_mov_TN_reg(ot, 0, reg);
2289 gen_op_mov_reg_T0(ot, rm);
2290 } else {
2291 gen_op_mov_TN_reg(ot, 0, rm);
2292 if (reg != OR_TMP0)
2293 gen_op_mov_reg_T0(ot, reg);
2295 } else {
2296 gen_lea_modrm(env, s, modrm, &opreg, &disp);
2297 if (is_store) {
2298 if (reg != OR_TMP0)
2299 gen_op_mov_TN_reg(ot, 0, reg);
2300 gen_op_st_T0_A0(s, ot);
2301 } else {
2302 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2303 if (reg != OR_TMP0)
2304 gen_op_mov_reg_T0(ot, reg);
2309 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
2311 uint32_t ret;
2313 switch(ot) {
2314 case MO_8:
2315 ret = cpu_ldub_code(env, s->pc);
2316 s->pc++;
2317 break;
2318 case MO_16:
2319 ret = cpu_lduw_code(env, s->pc);
2320 s->pc += 2;
2321 break;
2322 default:
2323 case MO_32:
2324 ret = cpu_ldl_code(env, s->pc);
2325 s->pc += 4;
2326 break;
2328 return ret;
2331 static inline int insn_const_size(unsigned int ot)
2333 if (ot <= MO_32) {
2334 return 1 << ot;
2335 } else {
2336 return 4;
2340 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2342 TranslationBlock *tb;
2343 target_ulong pc;
2345 pc = s->cs_base + eip;
2346 tb = s->tb;
2347 /* NOTE: we handle the case where the TB spans two pages here */
2348 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2349 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2350 /* jump to same page: we can use a direct jump */
2351 tcg_gen_goto_tb(tb_num);
2352 gen_jmp_im(eip);
2353 tcg_gen_exit_tb((uintptr_t)tb + tb_num);
2354 } else {
2355 /* jump to another page: currently not optimized */
2356 gen_jmp_im(eip);
2357 gen_eob(s);
2361 static inline void gen_jcc(DisasContext *s, int b,
2362 target_ulong val, target_ulong next_eip)
2364 int l1, l2;
2366 if (s->jmp_opt) {
2367 l1 = gen_new_label();
2368 gen_jcc1(s, b, l1);
2370 gen_goto_tb(s, 0, next_eip);
2372 gen_set_label(l1);
2373 gen_goto_tb(s, 1, val);
2374 s->is_jmp = DISAS_TB_JUMP;
2375 } else {
2376 l1 = gen_new_label();
2377 l2 = gen_new_label();
2378 gen_jcc1(s, b, l1);
2380 gen_jmp_im(next_eip);
2381 tcg_gen_br(l2);
2383 gen_set_label(l1);
2384 gen_jmp_im(val);
2385 gen_set_label(l2);
2386 gen_eob(s);
2390 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, int ot, int b,
2391 int modrm, int reg)
2393 CCPrepare cc;
2395 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2397 cc = gen_prepare_cc(s, b, cpu_T[1]);
2398 if (cc.mask != -1) {
2399 TCGv t0 = tcg_temp_new();
2400 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2401 cc.reg = t0;
2403 if (!cc.use_reg2) {
2404 cc.reg2 = tcg_const_tl(cc.imm);
2407 tcg_gen_movcond_tl(cc.cond, cpu_T[0], cc.reg, cc.reg2,
2408 cpu_T[0], cpu_regs[reg]);
2409 gen_op_mov_reg_T0(ot, reg);
2411 if (cc.mask != -1) {
2412 tcg_temp_free(cc.reg);
2414 if (!cc.use_reg2) {
2415 tcg_temp_free(cc.reg2);
2419 static inline void gen_op_movl_T0_seg(int seg_reg)
2421 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
2422 offsetof(CPUX86State,segs[seg_reg].selector));
2425 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2427 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
2428 tcg_gen_st32_tl(cpu_T[0], cpu_env,
2429 offsetof(CPUX86State,segs[seg_reg].selector));
2430 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
2431 tcg_gen_st_tl(cpu_T[0], cpu_env,
2432 offsetof(CPUX86State,segs[seg_reg].base));
2435 /* move T0 to seg_reg and compute if the CPU state may change. Never
2436 call this function with seg_reg == R_CS */
2437 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2439 if (s->pe && !s->vm86) {
2440 /* XXX: optimize by finding processor state dynamically */
2441 gen_update_cc_op(s);
2442 gen_jmp_im(cur_eip);
2443 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2444 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
2445 /* abort translation because the addseg value may change or
2446 because ss32 may change. For R_SS, translation must always
2447 stop as a special handling must be done to disable hardware
2448 interrupts for the next instruction */
2449 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
2450 s->is_jmp = DISAS_TB_JUMP;
2451 } else {
2452 gen_op_movl_seg_T0_vm(seg_reg);
2453 if (seg_reg == R_SS)
2454 s->is_jmp = DISAS_TB_JUMP;
2458 static inline int svm_is_rep(int prefixes)
2460 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2463 static inline void
2464 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2465 uint32_t type, uint64_t param)
2467 /* no SVM activated; fast case */
2468 if (likely(!(s->flags & HF_SVMI_MASK)))
2469 return;
2470 gen_update_cc_op(s);
2471 gen_jmp_im(pc_start - s->cs_base);
2472 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2473 tcg_const_i64(param));
2476 static inline void
2477 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2479 gen_svm_check_intercept_param(s, pc_start, type, 0);
2482 static inline void gen_stack_update(DisasContext *s, int addend)
2484 #ifdef TARGET_X86_64
2485 if (CODE64(s)) {
2486 gen_op_add_reg_im(2, R_ESP, addend);
2487 } else
2488 #endif
2489 if (s->ss32) {
2490 gen_op_add_reg_im(1, R_ESP, addend);
2491 } else {
2492 gen_op_add_reg_im(0, R_ESP, addend);
2496 /* generate a push. It depends on ss32, addseg and dflag */
2497 static void gen_push_T0(DisasContext *s)
2499 #ifdef TARGET_X86_64
2500 if (CODE64(s)) {
2501 gen_op_movq_A0_reg(R_ESP);
2502 if (s->dflag) {
2503 gen_op_addq_A0_im(-8);
2504 gen_op_st_T0_A0(s, MO_64);
2505 } else {
2506 gen_op_addq_A0_im(-2);
2507 gen_op_st_T0_A0(s, MO_16);
2509 gen_op_mov_reg_A0(2, R_ESP);
2510 } else
2511 #endif
2513 gen_op_movl_A0_reg(R_ESP);
2514 if (!s->dflag)
2515 gen_op_addl_A0_im(-2);
2516 else
2517 gen_op_addl_A0_im(-4);
2518 if (s->ss32) {
2519 if (s->addseg) {
2520 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2521 gen_op_addl_A0_seg(s, R_SS);
2523 } else {
2524 gen_op_andl_A0_ffff();
2525 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2526 gen_op_addl_A0_seg(s, R_SS);
2528 gen_op_st_T0_A0(s, s->dflag + 1);
2529 if (s->ss32 && !s->addseg)
2530 gen_op_mov_reg_A0(1, R_ESP);
2531 else
2532 gen_op_mov_reg_T1(s->ss32 + 1, R_ESP);
2536 /* generate a push. It depends on ss32, addseg and dflag */
2537 /* slower version for T1, only used for call Ev */
2538 static void gen_push_T1(DisasContext *s)
2540 #ifdef TARGET_X86_64
2541 if (CODE64(s)) {
2542 gen_op_movq_A0_reg(R_ESP);
2543 if (s->dflag) {
2544 gen_op_addq_A0_im(-8);
2545 gen_op_st_T1_A0(s, MO_64);
2546 } else {
2547 gen_op_addq_A0_im(-2);
2548 gen_op_st_T0_A0(s, MO_16);
2550 gen_op_mov_reg_A0(2, R_ESP);
2551 } else
2552 #endif
2554 gen_op_movl_A0_reg(R_ESP);
2555 if (!s->dflag)
2556 gen_op_addl_A0_im(-2);
2557 else
2558 gen_op_addl_A0_im(-4);
2559 if (s->ss32) {
2560 if (s->addseg) {
2561 gen_op_addl_A0_seg(s, R_SS);
2563 } else {
2564 gen_op_andl_A0_ffff();
2565 gen_op_addl_A0_seg(s, R_SS);
2567 gen_op_st_T1_A0(s, s->dflag + 1);
2569 if (s->ss32 && !s->addseg)
2570 gen_op_mov_reg_A0(1, R_ESP);
2571 else
2572 gen_stack_update(s, (-2) << s->dflag);
2576 /* two step pop is necessary for precise exceptions */
2577 static void gen_pop_T0(DisasContext *s)
2579 #ifdef TARGET_X86_64
2580 if (CODE64(s)) {
2581 gen_op_movq_A0_reg(R_ESP);
2582 gen_op_ld_v(s, s->dflag ? MO_64 : MO_16, cpu_T[0], cpu_A0);
2583 } else
2584 #endif
2586 gen_op_movl_A0_reg(R_ESP);
2587 if (s->ss32) {
2588 if (s->addseg)
2589 gen_op_addl_A0_seg(s, R_SS);
2590 } else {
2591 gen_op_andl_A0_ffff();
2592 gen_op_addl_A0_seg(s, R_SS);
2594 gen_op_ld_v(s, s->dflag + 1, cpu_T[0], cpu_A0);
2598 static void gen_pop_update(DisasContext *s)
2600 #ifdef TARGET_X86_64
2601 if (CODE64(s) && s->dflag) {
2602 gen_stack_update(s, 8);
2603 } else
2604 #endif
2606 gen_stack_update(s, 2 << s->dflag);
2610 static void gen_stack_A0(DisasContext *s)
2612 gen_op_movl_A0_reg(R_ESP);
2613 if (!s->ss32)
2614 gen_op_andl_A0_ffff();
2615 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2616 if (s->addseg)
2617 gen_op_addl_A0_seg(s, R_SS);
2620 /* NOTE: wrap around in 16 bit not fully handled */
2621 static void gen_pusha(DisasContext *s)
2623 int i;
2624 gen_op_movl_A0_reg(R_ESP);
2625 gen_op_addl_A0_im(-16 << s->dflag);
2626 if (!s->ss32)
2627 gen_op_andl_A0_ffff();
2628 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2629 if (s->addseg)
2630 gen_op_addl_A0_seg(s, R_SS);
2631 for(i = 0;i < 8; i++) {
2632 gen_op_mov_TN_reg(MO_32, 0, 7 - i);
2633 gen_op_st_T0_A0(s, MO_16 + s->dflag);
2634 gen_op_addl_A0_im(2 << s->dflag);
2636 gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
2639 /* NOTE: wrap around in 16 bit not fully handled */
2640 static void gen_popa(DisasContext *s)
2642 int i;
2643 gen_op_movl_A0_reg(R_ESP);
2644 if (!s->ss32)
2645 gen_op_andl_A0_ffff();
2646 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2647 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 << s->dflag);
2648 if (s->addseg)
2649 gen_op_addl_A0_seg(s, R_SS);
2650 for(i = 0;i < 8; i++) {
2651 /* ESP is not reloaded */
2652 if (i != 3) {
2653 gen_op_ld_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
2654 gen_op_mov_reg_T0(MO_16 + s->dflag, 7 - i);
2656 gen_op_addl_A0_im(2 << s->dflag);
2658 gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
2661 static void gen_enter(DisasContext *s, int esp_addend, int level)
2663 int ot, opsize;
2665 level &= 0x1f;
2666 #ifdef TARGET_X86_64
2667 if (CODE64(s)) {
2668 ot = s->dflag ? MO_64 : MO_16;
2669 opsize = 1 << ot;
2671 gen_op_movl_A0_reg(R_ESP);
2672 gen_op_addq_A0_im(-opsize);
2673 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2675 /* push bp */
2676 gen_op_mov_TN_reg(MO_32, 0, R_EBP);
2677 gen_op_st_T0_A0(s, ot);
2678 if (level) {
2679 /* XXX: must save state */
2680 gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
2681 tcg_const_i32((ot == MO_64)),
2682 cpu_T[1]);
2684 gen_op_mov_reg_T1(ot, R_EBP);
2685 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2686 gen_op_mov_reg_T1(MO_64, R_ESP);
2687 } else
2688 #endif
2690 ot = s->dflag + MO_16;
2691 opsize = 2 << s->dflag;
2693 gen_op_movl_A0_reg(R_ESP);
2694 gen_op_addl_A0_im(-opsize);
2695 if (!s->ss32)
2696 gen_op_andl_A0_ffff();
2697 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2698 if (s->addseg)
2699 gen_op_addl_A0_seg(s, R_SS);
2700 /* push bp */
2701 gen_op_mov_TN_reg(MO_32, 0, R_EBP);
2702 gen_op_st_T0_A0(s, ot);
2703 if (level) {
2704 /* XXX: must save state */
2705 gen_helper_enter_level(cpu_env, tcg_const_i32(level),
2706 tcg_const_i32(s->dflag),
2707 cpu_T[1]);
2709 gen_op_mov_reg_T1(ot, R_EBP);
2710 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2711 gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
2715 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2717 gen_update_cc_op(s);
2718 gen_jmp_im(cur_eip);
2719 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
2720 s->is_jmp = DISAS_TB_JUMP;
2723 /* an interrupt is different from an exception because of the
2724 privilege checks */
2725 static void gen_interrupt(DisasContext *s, int intno,
2726 target_ulong cur_eip, target_ulong next_eip)
2728 gen_update_cc_op(s);
2729 gen_jmp_im(cur_eip);
2730 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2731 tcg_const_i32(next_eip - cur_eip));
2732 s->is_jmp = DISAS_TB_JUMP;
2735 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2737 gen_update_cc_op(s);
2738 gen_jmp_im(cur_eip);
2739 gen_helper_debug(cpu_env);
2740 s->is_jmp = DISAS_TB_JUMP;
2743 /* generate a generic end of block. Trace exception is also generated
2744 if needed */
2745 static void gen_eob(DisasContext *s)
2747 gen_update_cc_op(s);
2748 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2749 gen_helper_reset_inhibit_irq(cpu_env);
2751 if (s->tb->flags & HF_RF_MASK) {
2752 gen_helper_reset_rf(cpu_env);
2754 if (s->singlestep_enabled) {
2755 gen_helper_debug(cpu_env);
2756 } else if (s->tf) {
2757 gen_helper_single_step(cpu_env);
2758 } else {
2759 tcg_gen_exit_tb(0);
2761 s->is_jmp = DISAS_TB_JUMP;
2764 /* generate a jump to eip. No segment change must happen before as a
2765 direct call to the next block may occur */
2766 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2768 gen_update_cc_op(s);
2769 set_cc_op(s, CC_OP_DYNAMIC);
2770 if (s->jmp_opt) {
2771 gen_goto_tb(s, tb_num, eip);
2772 s->is_jmp = DISAS_TB_JUMP;
2773 } else {
2774 gen_jmp_im(eip);
2775 gen_eob(s);
2779 static void gen_jmp(DisasContext *s, target_ulong eip)
2781 gen_jmp_tb(s, eip, 0);
2784 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2786 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2787 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2790 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2792 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2793 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
2796 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2798 int mem_index = s->mem_index;
2799 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2800 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2801 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2802 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2803 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2806 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2808 int mem_index = s->mem_index;
2809 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2810 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
2811 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2812 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2813 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
2816 static inline void gen_op_movo(int d_offset, int s_offset)
2818 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2819 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2820 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8);
2821 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8);
2824 static inline void gen_op_movq(int d_offset, int s_offset)
2826 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2827 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2830 static inline void gen_op_movl(int d_offset, int s_offset)
2832 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2833 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2836 static inline void gen_op_movq_env_0(int d_offset)
2838 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2839 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2842 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2843 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2844 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2845 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2846 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2847 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2848 TCGv_i32 val);
2849 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2850 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2851 TCGv val);
2853 #define SSE_SPECIAL ((void *)1)
2854 #define SSE_DUMMY ((void *)2)
2856 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2857 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2858 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2860 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2861 /* 3DNow! extensions */
2862 [0x0e] = { SSE_DUMMY }, /* femms */
2863 [0x0f] = { SSE_DUMMY }, /* pf... */
2864 /* pure SSE operations */
2865 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2866 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2867 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2868 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2869 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2870 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2871 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2872 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2874 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2875 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2876 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2877 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2878 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2879 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2880 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2881 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2882 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2883 [0x51] = SSE_FOP(sqrt),
2884 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2885 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2886 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2887 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2888 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2889 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2890 [0x58] = SSE_FOP(add),
2891 [0x59] = SSE_FOP(mul),
2892 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2893 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2894 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2895 [0x5c] = SSE_FOP(sub),
2896 [0x5d] = SSE_FOP(min),
2897 [0x5e] = SSE_FOP(div),
2898 [0x5f] = SSE_FOP(max),
2900 [0xc2] = SSE_FOP(cmpeq),
2901 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2902 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2904 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2905 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2906 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2908 /* MMX ops and their SSE extensions */
2909 [0x60] = MMX_OP2(punpcklbw),
2910 [0x61] = MMX_OP2(punpcklwd),
2911 [0x62] = MMX_OP2(punpckldq),
2912 [0x63] = MMX_OP2(packsswb),
2913 [0x64] = MMX_OP2(pcmpgtb),
2914 [0x65] = MMX_OP2(pcmpgtw),
2915 [0x66] = MMX_OP2(pcmpgtl),
2916 [0x67] = MMX_OP2(packuswb),
2917 [0x68] = MMX_OP2(punpckhbw),
2918 [0x69] = MMX_OP2(punpckhwd),
2919 [0x6a] = MMX_OP2(punpckhdq),
2920 [0x6b] = MMX_OP2(packssdw),
2921 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2922 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2923 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2924 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2925 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2926 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2927 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2928 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2929 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2930 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2931 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2932 [0x74] = MMX_OP2(pcmpeqb),
2933 [0x75] = MMX_OP2(pcmpeqw),
2934 [0x76] = MMX_OP2(pcmpeql),
2935 [0x77] = { SSE_DUMMY }, /* emms */
2936 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2937 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2938 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2939 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2940 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2941 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2942 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2943 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2944 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2945 [0xd1] = MMX_OP2(psrlw),
2946 [0xd2] = MMX_OP2(psrld),
2947 [0xd3] = MMX_OP2(psrlq),
2948 [0xd4] = MMX_OP2(paddq),
2949 [0xd5] = MMX_OP2(pmullw),
2950 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2951 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2952 [0xd8] = MMX_OP2(psubusb),
2953 [0xd9] = MMX_OP2(psubusw),
2954 [0xda] = MMX_OP2(pminub),
2955 [0xdb] = MMX_OP2(pand),
2956 [0xdc] = MMX_OP2(paddusb),
2957 [0xdd] = MMX_OP2(paddusw),
2958 [0xde] = MMX_OP2(pmaxub),
2959 [0xdf] = MMX_OP2(pandn),
2960 [0xe0] = MMX_OP2(pavgb),
2961 [0xe1] = MMX_OP2(psraw),
2962 [0xe2] = MMX_OP2(psrad),
2963 [0xe3] = MMX_OP2(pavgw),
2964 [0xe4] = MMX_OP2(pmulhuw),
2965 [0xe5] = MMX_OP2(pmulhw),
2966 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2967 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2968 [0xe8] = MMX_OP2(psubsb),
2969 [0xe9] = MMX_OP2(psubsw),
2970 [0xea] = MMX_OP2(pminsw),
2971 [0xeb] = MMX_OP2(por),
2972 [0xec] = MMX_OP2(paddsb),
2973 [0xed] = MMX_OP2(paddsw),
2974 [0xee] = MMX_OP2(pmaxsw),
2975 [0xef] = MMX_OP2(pxor),
2976 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2977 [0xf1] = MMX_OP2(psllw),
2978 [0xf2] = MMX_OP2(pslld),
2979 [0xf3] = MMX_OP2(psllq),
2980 [0xf4] = MMX_OP2(pmuludq),
2981 [0xf5] = MMX_OP2(pmaddwd),
2982 [0xf6] = MMX_OP2(psadbw),
2983 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2984 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2985 [0xf8] = MMX_OP2(psubb),
2986 [0xf9] = MMX_OP2(psubw),
2987 [0xfa] = MMX_OP2(psubl),
2988 [0xfb] = MMX_OP2(psubq),
2989 [0xfc] = MMX_OP2(paddb),
2990 [0xfd] = MMX_OP2(paddw),
2991 [0xfe] = MMX_OP2(paddl),
2994 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2995 [0 + 2] = MMX_OP2(psrlw),
2996 [0 + 4] = MMX_OP2(psraw),
2997 [0 + 6] = MMX_OP2(psllw),
2998 [8 + 2] = MMX_OP2(psrld),
2999 [8 + 4] = MMX_OP2(psrad),
3000 [8 + 6] = MMX_OP2(pslld),
3001 [16 + 2] = MMX_OP2(psrlq),
3002 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
3003 [16 + 6] = MMX_OP2(psllq),
3004 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
3007 static const SSEFunc_0_epi sse_op_table3ai[] = {
3008 gen_helper_cvtsi2ss,
3009 gen_helper_cvtsi2sd
3012 #ifdef TARGET_X86_64
3013 static const SSEFunc_0_epl sse_op_table3aq[] = {
3014 gen_helper_cvtsq2ss,
3015 gen_helper_cvtsq2sd
3017 #endif
3019 static const SSEFunc_i_ep sse_op_table3bi[] = {
3020 gen_helper_cvttss2si,
3021 gen_helper_cvtss2si,
3022 gen_helper_cvttsd2si,
3023 gen_helper_cvtsd2si
3026 #ifdef TARGET_X86_64
3027 static const SSEFunc_l_ep sse_op_table3bq[] = {
3028 gen_helper_cvttss2sq,
3029 gen_helper_cvtss2sq,
3030 gen_helper_cvttsd2sq,
3031 gen_helper_cvtsd2sq
3033 #endif
3035 static const SSEFunc_0_epp sse_op_table4[8][4] = {
3036 SSE_FOP(cmpeq),
3037 SSE_FOP(cmplt),
3038 SSE_FOP(cmple),
3039 SSE_FOP(cmpunord),
3040 SSE_FOP(cmpneq),
3041 SSE_FOP(cmpnlt),
3042 SSE_FOP(cmpnle),
3043 SSE_FOP(cmpord),
3046 static const SSEFunc_0_epp sse_op_table5[256] = {
3047 [0x0c] = gen_helper_pi2fw,
3048 [0x0d] = gen_helper_pi2fd,
3049 [0x1c] = gen_helper_pf2iw,
3050 [0x1d] = gen_helper_pf2id,
3051 [0x8a] = gen_helper_pfnacc,
3052 [0x8e] = gen_helper_pfpnacc,
3053 [0x90] = gen_helper_pfcmpge,
3054 [0x94] = gen_helper_pfmin,
3055 [0x96] = gen_helper_pfrcp,
3056 [0x97] = gen_helper_pfrsqrt,
3057 [0x9a] = gen_helper_pfsub,
3058 [0x9e] = gen_helper_pfadd,
3059 [0xa0] = gen_helper_pfcmpgt,
3060 [0xa4] = gen_helper_pfmax,
3061 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
3062 [0xa7] = gen_helper_movq, /* pfrsqit1 */
3063 [0xaa] = gen_helper_pfsubr,
3064 [0xae] = gen_helper_pfacc,
3065 [0xb0] = gen_helper_pfcmpeq,
3066 [0xb4] = gen_helper_pfmul,
3067 [0xb6] = gen_helper_movq, /* pfrcpit2 */
3068 [0xb7] = gen_helper_pmulhrw_mmx,
3069 [0xbb] = gen_helper_pswapd,
3070 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
3073 struct SSEOpHelper_epp {
3074 SSEFunc_0_epp op[2];
3075 uint32_t ext_mask;
3078 struct SSEOpHelper_eppi {
3079 SSEFunc_0_eppi op[2];
3080 uint32_t ext_mask;
3083 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
3084 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
3085 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
3086 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
3087 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
3088 CPUID_EXT_PCLMULQDQ }
3089 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
3091 static const struct SSEOpHelper_epp sse_op_table6[256] = {
3092 [0x00] = SSSE3_OP(pshufb),
3093 [0x01] = SSSE3_OP(phaddw),
3094 [0x02] = SSSE3_OP(phaddd),
3095 [0x03] = SSSE3_OP(phaddsw),
3096 [0x04] = SSSE3_OP(pmaddubsw),
3097 [0x05] = SSSE3_OP(phsubw),
3098 [0x06] = SSSE3_OP(phsubd),
3099 [0x07] = SSSE3_OP(phsubsw),
3100 [0x08] = SSSE3_OP(psignb),
3101 [0x09] = SSSE3_OP(psignw),
3102 [0x0a] = SSSE3_OP(psignd),
3103 [0x0b] = SSSE3_OP(pmulhrsw),
3104 [0x10] = SSE41_OP(pblendvb),
3105 [0x14] = SSE41_OP(blendvps),
3106 [0x15] = SSE41_OP(blendvpd),
3107 [0x17] = SSE41_OP(ptest),
3108 [0x1c] = SSSE3_OP(pabsb),
3109 [0x1d] = SSSE3_OP(pabsw),
3110 [0x1e] = SSSE3_OP(pabsd),
3111 [0x20] = SSE41_OP(pmovsxbw),
3112 [0x21] = SSE41_OP(pmovsxbd),
3113 [0x22] = SSE41_OP(pmovsxbq),
3114 [0x23] = SSE41_OP(pmovsxwd),
3115 [0x24] = SSE41_OP(pmovsxwq),
3116 [0x25] = SSE41_OP(pmovsxdq),
3117 [0x28] = SSE41_OP(pmuldq),
3118 [0x29] = SSE41_OP(pcmpeqq),
3119 [0x2a] = SSE41_SPECIAL, /* movntqda */
3120 [0x2b] = SSE41_OP(packusdw),
3121 [0x30] = SSE41_OP(pmovzxbw),
3122 [0x31] = SSE41_OP(pmovzxbd),
3123 [0x32] = SSE41_OP(pmovzxbq),
3124 [0x33] = SSE41_OP(pmovzxwd),
3125 [0x34] = SSE41_OP(pmovzxwq),
3126 [0x35] = SSE41_OP(pmovzxdq),
3127 [0x37] = SSE42_OP(pcmpgtq),
3128 [0x38] = SSE41_OP(pminsb),
3129 [0x39] = SSE41_OP(pminsd),
3130 [0x3a] = SSE41_OP(pminuw),
3131 [0x3b] = SSE41_OP(pminud),
3132 [0x3c] = SSE41_OP(pmaxsb),
3133 [0x3d] = SSE41_OP(pmaxsd),
3134 [0x3e] = SSE41_OP(pmaxuw),
3135 [0x3f] = SSE41_OP(pmaxud),
3136 [0x40] = SSE41_OP(pmulld),
3137 [0x41] = SSE41_OP(phminposuw),
3138 [0xdb] = AESNI_OP(aesimc),
3139 [0xdc] = AESNI_OP(aesenc),
3140 [0xdd] = AESNI_OP(aesenclast),
3141 [0xde] = AESNI_OP(aesdec),
3142 [0xdf] = AESNI_OP(aesdeclast),
3145 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
3146 [0x08] = SSE41_OP(roundps),
3147 [0x09] = SSE41_OP(roundpd),
3148 [0x0a] = SSE41_OP(roundss),
3149 [0x0b] = SSE41_OP(roundsd),
3150 [0x0c] = SSE41_OP(blendps),
3151 [0x0d] = SSE41_OP(blendpd),
3152 [0x0e] = SSE41_OP(pblendw),
3153 [0x0f] = SSSE3_OP(palignr),
3154 [0x14] = SSE41_SPECIAL, /* pextrb */
3155 [0x15] = SSE41_SPECIAL, /* pextrw */
3156 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3157 [0x17] = SSE41_SPECIAL, /* extractps */
3158 [0x20] = SSE41_SPECIAL, /* pinsrb */
3159 [0x21] = SSE41_SPECIAL, /* insertps */
3160 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3161 [0x40] = SSE41_OP(dpps),
3162 [0x41] = SSE41_OP(dppd),
3163 [0x42] = SSE41_OP(mpsadbw),
3164 [0x44] = PCLMULQDQ_OP(pclmulqdq),
3165 [0x60] = SSE42_OP(pcmpestrm),
3166 [0x61] = SSE42_OP(pcmpestri),
3167 [0x62] = SSE42_OP(pcmpistrm),
3168 [0x63] = SSE42_OP(pcmpistri),
3169 [0xdf] = AESNI_OP(aeskeygenassist),
3172 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3173 target_ulong pc_start, int rex_r)
3175 int b1, op1_offset, op2_offset, is_xmm, val, ot;
3176 int modrm, mod, rm, reg, reg_addr, offset_addr;
3177 SSEFunc_0_epp sse_fn_epp;
3178 SSEFunc_0_eppi sse_fn_eppi;
3179 SSEFunc_0_ppi sse_fn_ppi;
3180 SSEFunc_0_eppt sse_fn_eppt;
3182 b &= 0xff;
3183 if (s->prefix & PREFIX_DATA)
3184 b1 = 1;
3185 else if (s->prefix & PREFIX_REPZ)
3186 b1 = 2;
3187 else if (s->prefix & PREFIX_REPNZ)
3188 b1 = 3;
3189 else
3190 b1 = 0;
3191 sse_fn_epp = sse_op_table1[b][b1];
3192 if (!sse_fn_epp) {
3193 goto illegal_op;
3195 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3196 is_xmm = 1;
3197 } else {
3198 if (b1 == 0) {
3199 /* MMX case */
3200 is_xmm = 0;
3201 } else {
3202 is_xmm = 1;
3205 /* simple MMX/SSE operation */
3206 if (s->flags & HF_TS_MASK) {
3207 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3208 return;
3210 if (s->flags & HF_EM_MASK) {
3211 illegal_op:
3212 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
3213 return;
3215 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
3216 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
3217 goto illegal_op;
3218 if (b == 0x0e) {
3219 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3220 goto illegal_op;
3221 /* femms */
3222 gen_helper_emms(cpu_env);
3223 return;
3225 if (b == 0x77) {
3226 /* emms */
3227 gen_helper_emms(cpu_env);
3228 return;
3230 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3231 the static cpu state) */
3232 if (!is_xmm) {
3233 gen_helper_enter_mmx(cpu_env);
3236 modrm = cpu_ldub_code(env, s->pc++);
3237 reg = ((modrm >> 3) & 7);
3238 if (is_xmm)
3239 reg |= rex_r;
3240 mod = (modrm >> 6) & 3;
3241 if (sse_fn_epp == SSE_SPECIAL) {
3242 b |= (b1 << 8);
3243 switch(b) {
3244 case 0x0e7: /* movntq */
3245 if (mod == 3)
3246 goto illegal_op;
3247 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3248 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3249 break;
3250 case 0x1e7: /* movntdq */
3251 case 0x02b: /* movntps */
3252 case 0x12b: /* movntps */
3253 if (mod == 3)
3254 goto illegal_op;
3255 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3256 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3257 break;
3258 case 0x3f0: /* lddqu */
3259 if (mod == 3)
3260 goto illegal_op;
3261 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3262 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3263 break;
3264 case 0x22b: /* movntss */
3265 case 0x32b: /* movntsd */
3266 if (mod == 3)
3267 goto illegal_op;
3268 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3269 if (b1 & 1) {
3270 gen_stq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3271 } else {
3272 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3273 xmm_regs[reg].XMM_L(0)));
3274 gen_op_st_T0_A0(s, MO_32);
3276 break;
3277 case 0x6e: /* movd mm, ea */
3278 #ifdef TARGET_X86_64
3279 if (s->dflag == 2) {
3280 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3281 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3282 } else
3283 #endif
3285 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3286 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3287 offsetof(CPUX86State,fpregs[reg].mmx));
3288 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3289 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
3291 break;
3292 case 0x16e: /* movd xmm, ea */
3293 #ifdef TARGET_X86_64
3294 if (s->dflag == 2) {
3295 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3296 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3297 offsetof(CPUX86State,xmm_regs[reg]));
3298 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
3299 } else
3300 #endif
3302 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3303 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3304 offsetof(CPUX86State,xmm_regs[reg]));
3305 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3306 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
3308 break;
3309 case 0x6f: /* movq mm, ea */
3310 if (mod != 3) {
3311 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3312 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3313 } else {
3314 rm = (modrm & 7);
3315 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3316 offsetof(CPUX86State,fpregs[rm].mmx));
3317 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3318 offsetof(CPUX86State,fpregs[reg].mmx));
3320 break;
3321 case 0x010: /* movups */
3322 case 0x110: /* movupd */
3323 case 0x028: /* movaps */
3324 case 0x128: /* movapd */
3325 case 0x16f: /* movdqa xmm, ea */
3326 case 0x26f: /* movdqu xmm, ea */
3327 if (mod != 3) {
3328 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3329 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3330 } else {
3331 rm = (modrm & 7) | REX_B(s);
3332 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3333 offsetof(CPUX86State,xmm_regs[rm]));
3335 break;
3336 case 0x210: /* movss xmm, ea */
3337 if (mod != 3) {
3338 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3339 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
3340 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3341 gen_op_movl_T0_0();
3342 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3343 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3344 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3345 } else {
3346 rm = (modrm & 7) | REX_B(s);
3347 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3348 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3350 break;
3351 case 0x310: /* movsd xmm, ea */
3352 if (mod != 3) {
3353 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3354 gen_ldq_env_A0(s, offsetof(CPUX86State,
3355 xmm_regs[reg].XMM_Q(0)));
3356 gen_op_movl_T0_0();
3357 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3358 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3359 } else {
3360 rm = (modrm & 7) | REX_B(s);
3361 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3362 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3364 break;
3365 case 0x012: /* movlps */
3366 case 0x112: /* movlpd */
3367 if (mod != 3) {
3368 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3369 gen_ldq_env_A0(s, offsetof(CPUX86State,
3370 xmm_regs[reg].XMM_Q(0)));
3371 } else {
3372 /* movhlps */
3373 rm = (modrm & 7) | REX_B(s);
3374 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3375 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3377 break;
3378 case 0x212: /* movsldup */
3379 if (mod != 3) {
3380 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3381 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3382 } else {
3383 rm = (modrm & 7) | REX_B(s);
3384 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3385 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3386 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3387 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3389 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3390 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3391 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3392 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3393 break;
3394 case 0x312: /* movddup */
3395 if (mod != 3) {
3396 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3397 gen_ldq_env_A0(s, offsetof(CPUX86State,
3398 xmm_regs[reg].XMM_Q(0)));
3399 } else {
3400 rm = (modrm & 7) | REX_B(s);
3401 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3402 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3404 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3405 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3406 break;
3407 case 0x016: /* movhps */
3408 case 0x116: /* movhpd */
3409 if (mod != 3) {
3410 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3411 gen_ldq_env_A0(s, offsetof(CPUX86State,
3412 xmm_regs[reg].XMM_Q(1)));
3413 } else {
3414 /* movlhps */
3415 rm = (modrm & 7) | REX_B(s);
3416 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3417 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3419 break;
3420 case 0x216: /* movshdup */
3421 if (mod != 3) {
3422 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3423 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3424 } else {
3425 rm = (modrm & 7) | REX_B(s);
3426 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3427 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3428 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3429 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3431 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3432 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3433 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3434 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3435 break;
3436 case 0x178:
3437 case 0x378:
3439 int bit_index, field_length;
3441 if (b1 == 1 && reg != 0)
3442 goto illegal_op;
3443 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3444 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3445 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3446 offsetof(CPUX86State,xmm_regs[reg]));
3447 if (b1 == 1)
3448 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3449 tcg_const_i32(bit_index),
3450 tcg_const_i32(field_length));
3451 else
3452 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3453 tcg_const_i32(bit_index),
3454 tcg_const_i32(field_length));
3456 break;
3457 case 0x7e: /* movd ea, mm */
3458 #ifdef TARGET_X86_64
3459 if (s->dflag == 2) {
3460 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3461 offsetof(CPUX86State,fpregs[reg].mmx));
3462 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3463 } else
3464 #endif
3466 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3467 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3468 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3470 break;
3471 case 0x17e: /* movd ea, xmm */
3472 #ifdef TARGET_X86_64
3473 if (s->dflag == 2) {
3474 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3475 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3476 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3477 } else
3478 #endif
3480 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3481 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3482 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3484 break;
3485 case 0x27e: /* movq xmm, ea */
3486 if (mod != 3) {
3487 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3488 gen_ldq_env_A0(s, offsetof(CPUX86State,
3489 xmm_regs[reg].XMM_Q(0)));
3490 } else {
3491 rm = (modrm & 7) | REX_B(s);
3492 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3493 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3495 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3496 break;
3497 case 0x7f: /* movq ea, mm */
3498 if (mod != 3) {
3499 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3500 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3501 } else {
3502 rm = (modrm & 7);
3503 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3504 offsetof(CPUX86State,fpregs[reg].mmx));
3506 break;
3507 case 0x011: /* movups */
3508 case 0x111: /* movupd */
3509 case 0x029: /* movaps */
3510 case 0x129: /* movapd */
3511 case 0x17f: /* movdqa ea, xmm */
3512 case 0x27f: /* movdqu ea, xmm */
3513 if (mod != 3) {
3514 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3515 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3516 } else {
3517 rm = (modrm & 7) | REX_B(s);
3518 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3519 offsetof(CPUX86State,xmm_regs[reg]));
3521 break;
3522 case 0x211: /* movss ea, xmm */
3523 if (mod != 3) {
3524 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3525 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3526 gen_op_st_T0_A0(s, MO_32);
3527 } else {
3528 rm = (modrm & 7) | REX_B(s);
3529 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3530 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3532 break;
3533 case 0x311: /* movsd ea, xmm */
3534 if (mod != 3) {
3535 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3536 gen_stq_env_A0(s, offsetof(CPUX86State,
3537 xmm_regs[reg].XMM_Q(0)));
3538 } else {
3539 rm = (modrm & 7) | REX_B(s);
3540 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3541 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3543 break;
3544 case 0x013: /* movlps */
3545 case 0x113: /* movlpd */
3546 if (mod != 3) {
3547 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3548 gen_stq_env_A0(s, offsetof(CPUX86State,
3549 xmm_regs[reg].XMM_Q(0)));
3550 } else {
3551 goto illegal_op;
3553 break;
3554 case 0x017: /* movhps */
3555 case 0x117: /* movhpd */
3556 if (mod != 3) {
3557 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3558 gen_stq_env_A0(s, offsetof(CPUX86State,
3559 xmm_regs[reg].XMM_Q(1)));
3560 } else {
3561 goto illegal_op;
3563 break;
3564 case 0x71: /* shift mm, im */
3565 case 0x72:
3566 case 0x73:
3567 case 0x171: /* shift xmm, im */
3568 case 0x172:
3569 case 0x173:
3570 if (b1 >= 2) {
3571 goto illegal_op;
3573 val = cpu_ldub_code(env, s->pc++);
3574 if (is_xmm) {
3575 gen_op_movl_T0_im(val);
3576 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3577 gen_op_movl_T0_0();
3578 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
3579 op1_offset = offsetof(CPUX86State,xmm_t0);
3580 } else {
3581 gen_op_movl_T0_im(val);
3582 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3583 gen_op_movl_T0_0();
3584 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3585 op1_offset = offsetof(CPUX86State,mmx_t0);
3587 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3588 (((modrm >> 3)) & 7)][b1];
3589 if (!sse_fn_epp) {
3590 goto illegal_op;
3592 if (is_xmm) {
3593 rm = (modrm & 7) | REX_B(s);
3594 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3595 } else {
3596 rm = (modrm & 7);
3597 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3599 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3600 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3601 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3602 break;
3603 case 0x050: /* movmskps */
3604 rm = (modrm & 7) | REX_B(s);
3605 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3606 offsetof(CPUX86State,xmm_regs[rm]));
3607 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3608 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3609 gen_op_mov_reg_T0(MO_32, reg);
3610 break;
3611 case 0x150: /* movmskpd */
3612 rm = (modrm & 7) | REX_B(s);
3613 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3614 offsetof(CPUX86State,xmm_regs[rm]));
3615 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3616 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3617 gen_op_mov_reg_T0(MO_32, reg);
3618 break;
3619 case 0x02a: /* cvtpi2ps */
3620 case 0x12a: /* cvtpi2pd */
3621 gen_helper_enter_mmx(cpu_env);
3622 if (mod != 3) {
3623 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3624 op2_offset = offsetof(CPUX86State,mmx_t0);
3625 gen_ldq_env_A0(s, op2_offset);
3626 } else {
3627 rm = (modrm & 7);
3628 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3630 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3631 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3632 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3633 switch(b >> 8) {
3634 case 0x0:
3635 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3636 break;
3637 default:
3638 case 0x1:
3639 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3640 break;
3642 break;
3643 case 0x22a: /* cvtsi2ss */
3644 case 0x32a: /* cvtsi2sd */
3645 ot = (s->dflag == 2) ? MO_64 : MO_32;
3646 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3647 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3648 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3649 if (ot == MO_32) {
3650 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3651 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3652 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3653 } else {
3654 #ifdef TARGET_X86_64
3655 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3656 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T[0]);
3657 #else
3658 goto illegal_op;
3659 #endif
3661 break;
3662 case 0x02c: /* cvttps2pi */
3663 case 0x12c: /* cvttpd2pi */
3664 case 0x02d: /* cvtps2pi */
3665 case 0x12d: /* cvtpd2pi */
3666 gen_helper_enter_mmx(cpu_env);
3667 if (mod != 3) {
3668 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3669 op2_offset = offsetof(CPUX86State,xmm_t0);
3670 gen_ldo_env_A0(s, op2_offset);
3671 } else {
3672 rm = (modrm & 7) | REX_B(s);
3673 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3675 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3676 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3677 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3678 switch(b) {
3679 case 0x02c:
3680 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3681 break;
3682 case 0x12c:
3683 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3684 break;
3685 case 0x02d:
3686 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3687 break;
3688 case 0x12d:
3689 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3690 break;
3692 break;
3693 case 0x22c: /* cvttss2si */
3694 case 0x32c: /* cvttsd2si */
3695 case 0x22d: /* cvtss2si */
3696 case 0x32d: /* cvtsd2si */
3697 ot = (s->dflag == 2) ? MO_64 : MO_32;
3698 if (mod != 3) {
3699 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3700 if ((b >> 8) & 1) {
3701 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_Q(0)));
3702 } else {
3703 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
3704 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3706 op2_offset = offsetof(CPUX86State,xmm_t0);
3707 } else {
3708 rm = (modrm & 7) | REX_B(s);
3709 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3711 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3712 if (ot == MO_32) {
3713 SSEFunc_i_ep sse_fn_i_ep =
3714 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3715 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3716 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3717 } else {
3718 #ifdef TARGET_X86_64
3719 SSEFunc_l_ep sse_fn_l_ep =
3720 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3721 sse_fn_l_ep(cpu_T[0], cpu_env, cpu_ptr0);
3722 #else
3723 goto illegal_op;
3724 #endif
3726 gen_op_mov_reg_T0(ot, reg);
3727 break;
3728 case 0xc4: /* pinsrw */
3729 case 0x1c4:
3730 s->rip_offset = 1;
3731 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3732 val = cpu_ldub_code(env, s->pc++);
3733 if (b1) {
3734 val &= 7;
3735 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3736 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
3737 } else {
3738 val &= 3;
3739 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3740 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3742 break;
3743 case 0xc5: /* pextrw */
3744 case 0x1c5:
3745 if (mod != 3)
3746 goto illegal_op;
3747 ot = (s->dflag == 2) ? MO_64 : MO_32;
3748 val = cpu_ldub_code(env, s->pc++);
3749 if (b1) {
3750 val &= 7;
3751 rm = (modrm & 7) | REX_B(s);
3752 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3753 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
3754 } else {
3755 val &= 3;
3756 rm = (modrm & 7);
3757 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3758 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3760 reg = ((modrm >> 3) & 7) | rex_r;
3761 gen_op_mov_reg_T0(ot, reg);
3762 break;
3763 case 0x1d6: /* movq ea, xmm */
3764 if (mod != 3) {
3765 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3766 gen_stq_env_A0(s, offsetof(CPUX86State,
3767 xmm_regs[reg].XMM_Q(0)));
3768 } else {
3769 rm = (modrm & 7) | REX_B(s);
3770 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3771 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3772 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3774 break;
3775 case 0x2d6: /* movq2dq */
3776 gen_helper_enter_mmx(cpu_env);
3777 rm = (modrm & 7);
3778 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3779 offsetof(CPUX86State,fpregs[rm].mmx));
3780 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3781 break;
3782 case 0x3d6: /* movdq2q */
3783 gen_helper_enter_mmx(cpu_env);
3784 rm = (modrm & 7) | REX_B(s);
3785 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3786 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3787 break;
3788 case 0xd7: /* pmovmskb */
3789 case 0x1d7:
3790 if (mod != 3)
3791 goto illegal_op;
3792 if (b1) {
3793 rm = (modrm & 7) | REX_B(s);
3794 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3795 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3796 } else {
3797 rm = (modrm & 7);
3798 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3799 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3801 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3802 reg = ((modrm >> 3) & 7) | rex_r;
3803 gen_op_mov_reg_T0(MO_32, reg);
3804 break;
3806 case 0x138:
3807 case 0x038:
3808 b = modrm;
3809 if ((b & 0xf0) == 0xf0) {
3810 goto do_0f_38_fx;
3812 modrm = cpu_ldub_code(env, s->pc++);
3813 rm = modrm & 7;
3814 reg = ((modrm >> 3) & 7) | rex_r;
3815 mod = (modrm >> 6) & 3;
3816 if (b1 >= 2) {
3817 goto illegal_op;
3820 sse_fn_epp = sse_op_table6[b].op[b1];
3821 if (!sse_fn_epp) {
3822 goto illegal_op;
3824 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3825 goto illegal_op;
3827 if (b1) {
3828 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3829 if (mod == 3) {
3830 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3831 } else {
3832 op2_offset = offsetof(CPUX86State,xmm_t0);
3833 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3834 switch (b) {
3835 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3836 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3837 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3838 gen_ldq_env_A0(s, op2_offset +
3839 offsetof(XMMReg, XMM_Q(0)));
3840 break;
3841 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3842 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3843 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3844 s->mem_index, MO_LEUL);
3845 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3846 offsetof(XMMReg, XMM_L(0)));
3847 break;
3848 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3849 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3850 s->mem_index, MO_LEUW);
3851 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3852 offsetof(XMMReg, XMM_W(0)));
3853 break;
3854 case 0x2a: /* movntqda */
3855 gen_ldo_env_A0(s, op1_offset);
3856 return;
3857 default:
3858 gen_ldo_env_A0(s, op2_offset);
3861 } else {
3862 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3863 if (mod == 3) {
3864 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3865 } else {
3866 op2_offset = offsetof(CPUX86State,mmx_t0);
3867 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3868 gen_ldq_env_A0(s, op2_offset);
3871 if (sse_fn_epp == SSE_SPECIAL) {
3872 goto illegal_op;
3875 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3876 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3877 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3879 if (b == 0x17) {
3880 set_cc_op(s, CC_OP_EFLAGS);
3882 break;
3884 case 0x238:
3885 case 0x338:
3886 do_0f_38_fx:
3887 /* Various integer extensions at 0f 38 f[0-f]. */
3888 b = modrm | (b1 << 8);
3889 modrm = cpu_ldub_code(env, s->pc++);
3890 reg = ((modrm >> 3) & 7) | rex_r;
3892 switch (b) {
3893 case 0x3f0: /* crc32 Gd,Eb */
3894 case 0x3f1: /* crc32 Gd,Ey */
3895 do_crc32:
3896 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3897 goto illegal_op;
3899 if ((b & 0xff) == 0xf0) {
3900 ot = MO_8;
3901 } else if (s->dflag != 2) {
3902 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3903 } else {
3904 ot = MO_64;
3907 gen_op_mov_TN_reg(MO_32, 0, reg);
3908 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3909 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3910 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
3911 cpu_T[0], tcg_const_i32(8 << ot));
3913 ot = (s->dflag == 2) ? MO_64 : MO_32;
3914 gen_op_mov_reg_T0(ot, reg);
3915 break;
3917 case 0x1f0: /* crc32 or movbe */
3918 case 0x1f1:
3919 /* For these insns, the f3 prefix is supposed to have priority
3920 over the 66 prefix, but that's not what we implement above
3921 setting b1. */
3922 if (s->prefix & PREFIX_REPNZ) {
3923 goto do_crc32;
3925 /* FALLTHRU */
3926 case 0x0f0: /* movbe Gy,My */
3927 case 0x0f1: /* movbe My,Gy */
3928 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3929 goto illegal_op;
3931 if (s->dflag != 2) {
3932 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3933 } else {
3934 ot = MO_64;
3937 /* Load the data incoming to the bswap. Note that the TCG
3938 implementation of bswap requires the input be zero
3939 extended. In the case of the loads, we simply know that
3940 gen_op_ld_v via gen_ldst_modrm does that already. */
3941 if ((b & 1) == 0) {
3942 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3943 } else {
3944 switch (ot) {
3945 case MO_16:
3946 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[reg]);
3947 break;
3948 default:
3949 tcg_gen_ext32u_tl(cpu_T[0], cpu_regs[reg]);
3950 break;
3951 case MO_64:
3952 tcg_gen_mov_tl(cpu_T[0], cpu_regs[reg]);
3953 break;
3957 switch (ot) {
3958 case MO_16:
3959 tcg_gen_bswap16_tl(cpu_T[0], cpu_T[0]);
3960 break;
3961 default:
3962 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
3963 break;
3964 #ifdef TARGET_X86_64
3965 case MO_64:
3966 tcg_gen_bswap64_tl(cpu_T[0], cpu_T[0]);
3967 break;
3968 #endif
3971 if ((b & 1) == 0) {
3972 gen_op_mov_reg_T0(ot, reg);
3973 } else {
3974 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
3976 break;
3978 case 0x0f2: /* andn Gy, By, Ey */
3979 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3980 || !(s->prefix & PREFIX_VEX)
3981 || s->vex_l != 0) {
3982 goto illegal_op;
3984 ot = s->dflag == 2 ? MO_64 : MO_32;
3985 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3986 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
3987 gen_op_mov_reg_T0(ot, reg);
3988 gen_op_update1_cc();
3989 set_cc_op(s, CC_OP_LOGICB + ot);
3990 break;
3992 case 0x0f7: /* bextr Gy, Ey, By */
3993 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3994 || !(s->prefix & PREFIX_VEX)
3995 || s->vex_l != 0) {
3996 goto illegal_op;
3998 ot = s->dflag == 2 ? MO_64 : MO_32;
4000 TCGv bound, zero;
4002 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4003 /* Extract START, and shift the operand.
4004 Shifts larger than operand size get zeros. */
4005 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
4006 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_A0);
4008 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
4009 zero = tcg_const_tl(0);
4010 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T[0], cpu_A0, bound,
4011 cpu_T[0], zero);
4012 tcg_temp_free(zero);
4014 /* Extract the LEN into a mask. Lengths larger than
4015 operand size get all ones. */
4016 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
4017 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
4018 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
4019 cpu_A0, bound);
4020 tcg_temp_free(bound);
4021 tcg_gen_movi_tl(cpu_T[1], 1);
4022 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_A0);
4023 tcg_gen_subi_tl(cpu_T[1], cpu_T[1], 1);
4024 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4026 gen_op_mov_reg_T0(ot, reg);
4027 gen_op_update1_cc();
4028 set_cc_op(s, CC_OP_LOGICB + ot);
4030 break;
4032 case 0x0f5: /* bzhi Gy, Ey, By */
4033 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4034 || !(s->prefix & PREFIX_VEX)
4035 || s->vex_l != 0) {
4036 goto illegal_op;
4038 ot = s->dflag == 2 ? MO_64 : MO_32;
4039 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4040 tcg_gen_ext8u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4042 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
4043 /* Note that since we're using BMILG (in order to get O
4044 cleared) we need to store the inverse into C. */
4045 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
4046 cpu_T[1], bound);
4047 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T[1], cpu_T[1],
4048 bound, bound, cpu_T[1]);
4049 tcg_temp_free(bound);
4051 tcg_gen_movi_tl(cpu_A0, -1);
4052 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T[1]);
4053 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_A0);
4054 gen_op_mov_reg_T0(ot, reg);
4055 gen_op_update1_cc();
4056 set_cc_op(s, CC_OP_BMILGB + ot);
4057 break;
4059 case 0x3f6: /* mulx By, Gy, rdx, Ey */
4060 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4061 || !(s->prefix & PREFIX_VEX)
4062 || s->vex_l != 0) {
4063 goto illegal_op;
4065 ot = s->dflag == 2 ? MO_64 : MO_32;
4066 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4067 switch (ot) {
4068 default:
4069 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4070 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
4071 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4072 cpu_tmp2_i32, cpu_tmp3_i32);
4073 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
4074 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
4075 break;
4076 #ifdef TARGET_X86_64
4077 case MO_64:
4078 tcg_gen_mulu2_i64(cpu_regs[s->vex_v], cpu_regs[reg],
4079 cpu_T[0], cpu_regs[R_EDX]);
4080 break;
4081 #endif
4083 break;
4085 case 0x3f5: /* pdep Gy, By, Ey */
4086 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4087 || !(s->prefix & PREFIX_VEX)
4088 || s->vex_l != 0) {
4089 goto illegal_op;
4091 ot = s->dflag == 2 ? MO_64 : MO_32;
4092 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4093 /* Note that by zero-extending the mask operand, we
4094 automatically handle zero-extending the result. */
4095 if (s->dflag == 2) {
4096 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
4097 } else {
4098 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4100 gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]);
4101 break;
4103 case 0x2f5: /* pext Gy, By, Ey */
4104 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4105 || !(s->prefix & PREFIX_VEX)
4106 || s->vex_l != 0) {
4107 goto illegal_op;
4109 ot = s->dflag == 2 ? MO_64 : MO_32;
4110 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4111 /* Note that by zero-extending the mask operand, we
4112 automatically handle zero-extending the result. */
4113 if (s->dflag == 2) {
4114 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
4115 } else {
4116 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4118 gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]);
4119 break;
4121 case 0x1f6: /* adcx Gy, Ey */
4122 case 0x2f6: /* adox Gy, Ey */
4123 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
4124 goto illegal_op;
4125 } else {
4126 TCGv carry_in, carry_out, zero;
4127 int end_op;
4129 ot = (s->dflag == 2 ? MO_64 : MO_32);
4130 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4132 /* Re-use the carry-out from a previous round. */
4133 TCGV_UNUSED(carry_in);
4134 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
4135 switch (s->cc_op) {
4136 case CC_OP_ADCX:
4137 if (b == 0x1f6) {
4138 carry_in = cpu_cc_dst;
4139 end_op = CC_OP_ADCX;
4140 } else {
4141 end_op = CC_OP_ADCOX;
4143 break;
4144 case CC_OP_ADOX:
4145 if (b == 0x1f6) {
4146 end_op = CC_OP_ADCOX;
4147 } else {
4148 carry_in = cpu_cc_src2;
4149 end_op = CC_OP_ADOX;
4151 break;
4152 case CC_OP_ADCOX:
4153 end_op = CC_OP_ADCOX;
4154 carry_in = carry_out;
4155 break;
4156 default:
4157 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
4158 break;
4160 /* If we can't reuse carry-out, get it out of EFLAGS. */
4161 if (TCGV_IS_UNUSED(carry_in)) {
4162 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4163 gen_compute_eflags(s);
4165 carry_in = cpu_tmp0;
4166 tcg_gen_shri_tl(carry_in, cpu_cc_src,
4167 ctz32(b == 0x1f6 ? CC_C : CC_O));
4168 tcg_gen_andi_tl(carry_in, carry_in, 1);
4171 switch (ot) {
4172 #ifdef TARGET_X86_64
4173 case MO_32:
4174 /* If we know TL is 64-bit, and we want a 32-bit
4175 result, just do everything in 64-bit arithmetic. */
4176 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4177 tcg_gen_ext32u_i64(cpu_T[0], cpu_T[0]);
4178 tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_regs[reg]);
4179 tcg_gen_add_i64(cpu_T[0], cpu_T[0], carry_in);
4180 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T[0]);
4181 tcg_gen_shri_i64(carry_out, cpu_T[0], 32);
4182 break;
4183 #endif
4184 default:
4185 /* Otherwise compute the carry-out in two steps. */
4186 zero = tcg_const_tl(0);
4187 tcg_gen_add2_tl(cpu_T[0], carry_out,
4188 cpu_T[0], zero,
4189 carry_in, zero);
4190 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4191 cpu_regs[reg], carry_out,
4192 cpu_T[0], zero);
4193 tcg_temp_free(zero);
4194 break;
4196 set_cc_op(s, end_op);
4198 break;
4200 case 0x1f7: /* shlx Gy, Ey, By */
4201 case 0x2f7: /* sarx Gy, Ey, By */
4202 case 0x3f7: /* shrx Gy, Ey, By */
4203 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4204 || !(s->prefix & PREFIX_VEX)
4205 || s->vex_l != 0) {
4206 goto illegal_op;
4208 ot = (s->dflag == 2 ? MO_64 : MO_32);
4209 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4210 if (ot == MO_64) {
4211 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
4212 } else {
4213 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
4215 if (b == 0x1f7) {
4216 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4217 } else if (b == 0x2f7) {
4218 if (ot != MO_64) {
4219 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4221 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4222 } else {
4223 if (ot != MO_64) {
4224 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
4226 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4228 gen_op_mov_reg_T0(ot, reg);
4229 break;
4231 case 0x0f3:
4232 case 0x1f3:
4233 case 0x2f3:
4234 case 0x3f3: /* Group 17 */
4235 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4236 || !(s->prefix & PREFIX_VEX)
4237 || s->vex_l != 0) {
4238 goto illegal_op;
4240 ot = s->dflag == 2 ? MO_64 : MO_32;
4241 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4243 switch (reg & 7) {
4244 case 1: /* blsr By,Ey */
4245 tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
4246 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4247 gen_op_mov_reg_T0(ot, s->vex_v);
4248 gen_op_update2_cc();
4249 set_cc_op(s, CC_OP_BMILGB + ot);
4250 break;
4252 case 2: /* blsmsk By,Ey */
4253 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4254 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4255 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4256 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4257 set_cc_op(s, CC_OP_BMILGB + ot);
4258 break;
4260 case 3: /* blsi By, Ey */
4261 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4262 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4263 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4264 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4265 set_cc_op(s, CC_OP_BMILGB + ot);
4266 break;
4268 default:
4269 goto illegal_op;
4271 break;
4273 default:
4274 goto illegal_op;
4276 break;
4278 case 0x03a:
4279 case 0x13a:
4280 b = modrm;
4281 modrm = cpu_ldub_code(env, s->pc++);
4282 rm = modrm & 7;
4283 reg = ((modrm >> 3) & 7) | rex_r;
4284 mod = (modrm >> 6) & 3;
4285 if (b1 >= 2) {
4286 goto illegal_op;
4289 sse_fn_eppi = sse_op_table7[b].op[b1];
4290 if (!sse_fn_eppi) {
4291 goto illegal_op;
4293 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4294 goto illegal_op;
4296 if (sse_fn_eppi == SSE_SPECIAL) {
4297 ot = (s->dflag == 2) ? MO_64 : MO_32;
4298 rm = (modrm & 7) | REX_B(s);
4299 if (mod != 3)
4300 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4301 reg = ((modrm >> 3) & 7) | rex_r;
4302 val = cpu_ldub_code(env, s->pc++);
4303 switch (b) {
4304 case 0x14: /* pextrb */
4305 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4306 xmm_regs[reg].XMM_B(val & 15)));
4307 if (mod == 3) {
4308 gen_op_mov_reg_T0(ot, rm);
4309 } else {
4310 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4311 s->mem_index, MO_UB);
4313 break;
4314 case 0x15: /* pextrw */
4315 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4316 xmm_regs[reg].XMM_W(val & 7)));
4317 if (mod == 3) {
4318 gen_op_mov_reg_T0(ot, rm);
4319 } else {
4320 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4321 s->mem_index, MO_LEUW);
4323 break;
4324 case 0x16:
4325 if (ot == MO_32) { /* pextrd */
4326 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4327 offsetof(CPUX86State,
4328 xmm_regs[reg].XMM_L(val & 3)));
4329 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4330 if (mod == 3) {
4331 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4332 } else {
4333 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4334 s->mem_index, MO_LEUL);
4336 } else { /* pextrq */
4337 #ifdef TARGET_X86_64
4338 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4339 offsetof(CPUX86State,
4340 xmm_regs[reg].XMM_Q(val & 1)));
4341 if (mod == 3) {
4342 gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
4343 } else {
4344 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4345 s->mem_index, MO_LEQ);
4347 #else
4348 goto illegal_op;
4349 #endif
4351 break;
4352 case 0x17: /* extractps */
4353 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4354 xmm_regs[reg].XMM_L(val & 3)));
4355 if (mod == 3) {
4356 gen_op_mov_reg_T0(ot, rm);
4357 } else {
4358 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4359 s->mem_index, MO_LEUL);
4361 break;
4362 case 0x20: /* pinsrb */
4363 if (mod == 3) {
4364 gen_op_mov_TN_reg(MO_32, 0, rm);
4365 } else {
4366 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
4367 s->mem_index, MO_UB);
4369 tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4370 xmm_regs[reg].XMM_B(val & 15)));
4371 break;
4372 case 0x21: /* insertps */
4373 if (mod == 3) {
4374 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4375 offsetof(CPUX86State,xmm_regs[rm]
4376 .XMM_L((val >> 6) & 3)));
4377 } else {
4378 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4379 s->mem_index, MO_LEUL);
4381 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4382 offsetof(CPUX86State,xmm_regs[reg]
4383 .XMM_L((val >> 4) & 3)));
4384 if ((val >> 0) & 1)
4385 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4386 cpu_env, offsetof(CPUX86State,
4387 xmm_regs[reg].XMM_L(0)));
4388 if ((val >> 1) & 1)
4389 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4390 cpu_env, offsetof(CPUX86State,
4391 xmm_regs[reg].XMM_L(1)));
4392 if ((val >> 2) & 1)
4393 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4394 cpu_env, offsetof(CPUX86State,
4395 xmm_regs[reg].XMM_L(2)));
4396 if ((val >> 3) & 1)
4397 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4398 cpu_env, offsetof(CPUX86State,
4399 xmm_regs[reg].XMM_L(3)));
4400 break;
4401 case 0x22:
4402 if (ot == MO_32) { /* pinsrd */
4403 if (mod == 3) {
4404 gen_op_mov_v_reg(ot, cpu_tmp0, rm);
4405 } else {
4406 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
4407 s->mem_index, MO_LEUL);
4409 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
4410 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4411 offsetof(CPUX86State,
4412 xmm_regs[reg].XMM_L(val & 3)));
4413 } else { /* pinsrq */
4414 #ifdef TARGET_X86_64
4415 if (mod == 3) {
4416 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4417 } else {
4418 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4419 s->mem_index, MO_LEQ);
4421 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4422 offsetof(CPUX86State,
4423 xmm_regs[reg].XMM_Q(val & 1)));
4424 #else
4425 goto illegal_op;
4426 #endif
4428 break;
4430 return;
4433 if (b1) {
4434 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4435 if (mod == 3) {
4436 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4437 } else {
4438 op2_offset = offsetof(CPUX86State,xmm_t0);
4439 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4440 gen_ldo_env_A0(s, op2_offset);
4442 } else {
4443 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4444 if (mod == 3) {
4445 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4446 } else {
4447 op2_offset = offsetof(CPUX86State,mmx_t0);
4448 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4449 gen_ldq_env_A0(s, op2_offset);
4452 val = cpu_ldub_code(env, s->pc++);
4454 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4455 set_cc_op(s, CC_OP_EFLAGS);
4457 if (s->dflag == 2)
4458 /* The helper must use entire 64-bit gp registers */
4459 val |= 1 << 8;
4462 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4463 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4464 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4465 break;
4467 case 0x33a:
4468 /* Various integer extensions at 0f 3a f[0-f]. */
4469 b = modrm | (b1 << 8);
4470 modrm = cpu_ldub_code(env, s->pc++);
4471 reg = ((modrm >> 3) & 7) | rex_r;
4473 switch (b) {
4474 case 0x3f0: /* rorx Gy,Ey, Ib */
4475 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4476 || !(s->prefix & PREFIX_VEX)
4477 || s->vex_l != 0) {
4478 goto illegal_op;
4480 ot = s->dflag == 2 ? MO_64 : MO_32;
4481 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4482 b = cpu_ldub_code(env, s->pc++);
4483 if (ot == MO_64) {
4484 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
4485 } else {
4486 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4487 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4488 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4490 gen_op_mov_reg_T0(ot, reg);
4491 break;
4493 default:
4494 goto illegal_op;
4496 break;
4498 default:
4499 goto illegal_op;
4501 } else {
4502 /* generic MMX or SSE operation */
4503 switch(b) {
4504 case 0x70: /* pshufx insn */
4505 case 0xc6: /* pshufx insn */
4506 case 0xc2: /* compare insns */
4507 s->rip_offset = 1;
4508 break;
4509 default:
4510 break;
4512 if (is_xmm) {
4513 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4514 if (mod != 3) {
4515 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4516 op2_offset = offsetof(CPUX86State,xmm_t0);
4517 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
4518 b == 0xc2)) {
4519 /* specific case for SSE single instructions */
4520 if (b1 == 2) {
4521 /* 32 bit access */
4522 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
4523 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
4524 } else {
4525 /* 64 bit access */
4526 gen_ldq_env_A0(s, offsetof(CPUX86State,
4527 xmm_t0.XMM_D(0)));
4529 } else {
4530 gen_ldo_env_A0(s, op2_offset);
4532 } else {
4533 rm = (modrm & 7) | REX_B(s);
4534 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4536 } else {
4537 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4538 if (mod != 3) {
4539 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4540 op2_offset = offsetof(CPUX86State,mmx_t0);
4541 gen_ldq_env_A0(s, op2_offset);
4542 } else {
4543 rm = (modrm & 7);
4544 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4547 switch(b) {
4548 case 0x0f: /* 3DNow! data insns */
4549 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4550 goto illegal_op;
4551 val = cpu_ldub_code(env, s->pc++);
4552 sse_fn_epp = sse_op_table5[val];
4553 if (!sse_fn_epp) {
4554 goto illegal_op;
4556 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4557 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4558 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4559 break;
4560 case 0x70: /* pshufx insn */
4561 case 0xc6: /* pshufx insn */
4562 val = cpu_ldub_code(env, s->pc++);
4563 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4564 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4565 /* XXX: introduce a new table? */
4566 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4567 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4568 break;
4569 case 0xc2:
4570 /* compare insns */
4571 val = cpu_ldub_code(env, s->pc++);
4572 if (val >= 8)
4573 goto illegal_op;
4574 sse_fn_epp = sse_op_table4[val][b1];
4576 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4577 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4578 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4579 break;
4580 case 0xf7:
4581 /* maskmov : we must prepare A0 */
4582 if (mod != 3)
4583 goto illegal_op;
4584 #ifdef TARGET_X86_64
4585 if (s->aflag == 2) {
4586 gen_op_movq_A0_reg(R_EDI);
4587 } else
4588 #endif
4590 gen_op_movl_A0_reg(R_EDI);
4591 if (s->aflag == 0)
4592 gen_op_andl_A0_ffff();
4594 gen_add_A0_ds_seg(s);
4596 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4597 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4598 /* XXX: introduce a new table? */
4599 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4600 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4601 break;
4602 default:
4603 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4604 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4605 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4606 break;
4608 if (b == 0x2e || b == 0x2f) {
4609 set_cc_op(s, CC_OP_EFLAGS);
4614 /* convert one instruction. s->is_jmp is set if the translation must
4615 be stopped. Return the next pc value */
4616 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4617 target_ulong pc_start)
4619 int b, prefixes, aflag, dflag;
4620 int shift, ot;
4621 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
4622 target_ulong next_eip, tval;
4623 int rex_w, rex_r;
4625 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
4626 tcg_gen_debug_insn_start(pc_start);
4628 s->pc = pc_start;
4629 prefixes = 0;
4630 s->override = -1;
4631 rex_w = -1;
4632 rex_r = 0;
4633 #ifdef TARGET_X86_64
4634 s->rex_x = 0;
4635 s->rex_b = 0;
4636 x86_64_hregs = 0;
4637 #endif
4638 s->rip_offset = 0; /* for relative ip address */
4639 s->vex_l = 0;
4640 s->vex_v = 0;
4641 next_byte:
4642 b = cpu_ldub_code(env, s->pc);
4643 s->pc++;
4644 /* Collect prefixes. */
4645 switch (b) {
4646 case 0xf3:
4647 prefixes |= PREFIX_REPZ;
4648 goto next_byte;
4649 case 0xf2:
4650 prefixes |= PREFIX_REPNZ;
4651 goto next_byte;
4652 case 0xf0:
4653 prefixes |= PREFIX_LOCK;
4654 goto next_byte;
4655 case 0x2e:
4656 s->override = R_CS;
4657 goto next_byte;
4658 case 0x36:
4659 s->override = R_SS;
4660 goto next_byte;
4661 case 0x3e:
4662 s->override = R_DS;
4663 goto next_byte;
4664 case 0x26:
4665 s->override = R_ES;
4666 goto next_byte;
4667 case 0x64:
4668 s->override = R_FS;
4669 goto next_byte;
4670 case 0x65:
4671 s->override = R_GS;
4672 goto next_byte;
4673 case 0x66:
4674 prefixes |= PREFIX_DATA;
4675 goto next_byte;
4676 case 0x67:
4677 prefixes |= PREFIX_ADR;
4678 goto next_byte;
4679 #ifdef TARGET_X86_64
4680 case 0x40 ... 0x4f:
4681 if (CODE64(s)) {
4682 /* REX prefix */
4683 rex_w = (b >> 3) & 1;
4684 rex_r = (b & 0x4) << 1;
4685 s->rex_x = (b & 0x2) << 2;
4686 REX_B(s) = (b & 0x1) << 3;
4687 x86_64_hregs = 1; /* select uniform byte register addressing */
4688 goto next_byte;
4690 break;
4691 #endif
4692 case 0xc5: /* 2-byte VEX */
4693 case 0xc4: /* 3-byte VEX */
4694 /* VEX prefixes cannot be used except in 32-bit mode.
4695 Otherwise the instruction is LES or LDS. */
4696 if (s->code32 && !s->vm86) {
4697 static const int pp_prefix[4] = {
4698 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4700 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4702 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4703 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4704 otherwise the instruction is LES or LDS. */
4705 break;
4707 s->pc++;
4709 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4710 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4711 | PREFIX_LOCK | PREFIX_DATA)) {
4712 goto illegal_op;
4714 #ifdef TARGET_X86_64
4715 if (x86_64_hregs) {
4716 goto illegal_op;
4718 #endif
4719 rex_r = (~vex2 >> 4) & 8;
4720 if (b == 0xc5) {
4721 vex3 = vex2;
4722 b = cpu_ldub_code(env, s->pc++);
4723 } else {
4724 #ifdef TARGET_X86_64
4725 s->rex_x = (~vex2 >> 3) & 8;
4726 s->rex_b = (~vex2 >> 2) & 8;
4727 #endif
4728 vex3 = cpu_ldub_code(env, s->pc++);
4729 rex_w = (vex3 >> 7) & 1;
4730 switch (vex2 & 0x1f) {
4731 case 0x01: /* Implied 0f leading opcode bytes. */
4732 b = cpu_ldub_code(env, s->pc++) | 0x100;
4733 break;
4734 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4735 b = 0x138;
4736 break;
4737 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4738 b = 0x13a;
4739 break;
4740 default: /* Reserved for future use. */
4741 goto illegal_op;
4744 s->vex_v = (~vex3 >> 3) & 0xf;
4745 s->vex_l = (vex3 >> 2) & 1;
4746 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4748 break;
4751 /* Post-process prefixes. */
4752 if (CODE64(s)) {
4753 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4754 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4755 over 0x66 if both are present. */
4756 dflag = (rex_w > 0 ? 2 : prefixes & PREFIX_DATA ? 0 : 1);
4757 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4758 aflag = (prefixes & PREFIX_ADR ? 1 : 2);
4759 } else {
4760 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4761 dflag = s->code32;
4762 if (prefixes & PREFIX_DATA) {
4763 dflag ^= 1;
4765 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4766 aflag = s->code32;
4767 if (prefixes & PREFIX_ADR) {
4768 aflag ^= 1;
4772 s->prefix = prefixes;
4773 s->aflag = aflag;
4774 s->dflag = dflag;
4776 /* lock generation */
4777 if (prefixes & PREFIX_LOCK)
4778 gen_helper_lock();
4780 /* now check op code */
4781 reswitch:
4782 switch(b) {
4783 case 0x0f:
4784 /**************************/
4785 /* extended op code */
4786 b = cpu_ldub_code(env, s->pc++) | 0x100;
4787 goto reswitch;
4789 /**************************/
4790 /* arith & logic */
4791 case 0x00 ... 0x05:
4792 case 0x08 ... 0x0d:
4793 case 0x10 ... 0x15:
4794 case 0x18 ... 0x1d:
4795 case 0x20 ... 0x25:
4796 case 0x28 ... 0x2d:
4797 case 0x30 ... 0x35:
4798 case 0x38 ... 0x3d:
4800 int op, f, val;
4801 op = (b >> 3) & 7;
4802 f = (b >> 1) & 3;
4804 if ((b & 1) == 0)
4805 ot = MO_8;
4806 else
4807 ot = dflag + MO_16;
4809 switch(f) {
4810 case 0: /* OP Ev, Gv */
4811 modrm = cpu_ldub_code(env, s->pc++);
4812 reg = ((modrm >> 3) & 7) | rex_r;
4813 mod = (modrm >> 6) & 3;
4814 rm = (modrm & 7) | REX_B(s);
4815 if (mod != 3) {
4816 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4817 opreg = OR_TMP0;
4818 } else if (op == OP_XORL && rm == reg) {
4819 xor_zero:
4820 /* xor reg, reg optimisation */
4821 set_cc_op(s, CC_OP_CLR);
4822 gen_op_movl_T0_0();
4823 gen_op_mov_reg_T0(ot, reg);
4824 break;
4825 } else {
4826 opreg = rm;
4828 gen_op_mov_TN_reg(ot, 1, reg);
4829 gen_op(s, op, ot, opreg);
4830 break;
4831 case 1: /* OP Gv, Ev */
4832 modrm = cpu_ldub_code(env, s->pc++);
4833 mod = (modrm >> 6) & 3;
4834 reg = ((modrm >> 3) & 7) | rex_r;
4835 rm = (modrm & 7) | REX_B(s);
4836 if (mod != 3) {
4837 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4838 gen_op_ld_T1_A0(s, ot);
4839 } else if (op == OP_XORL && rm == reg) {
4840 goto xor_zero;
4841 } else {
4842 gen_op_mov_TN_reg(ot, 1, rm);
4844 gen_op(s, op, ot, reg);
4845 break;
4846 case 2: /* OP A, Iv */
4847 val = insn_get(env, s, ot);
4848 gen_op_movl_T1_im(val);
4849 gen_op(s, op, ot, OR_EAX);
4850 break;
4853 break;
4855 case 0x82:
4856 if (CODE64(s))
4857 goto illegal_op;
4858 case 0x80: /* GRP1 */
4859 case 0x81:
4860 case 0x83:
4862 int val;
4864 if ((b & 1) == 0)
4865 ot = MO_8;
4866 else
4867 ot = dflag + MO_16;
4869 modrm = cpu_ldub_code(env, s->pc++);
4870 mod = (modrm >> 6) & 3;
4871 rm = (modrm & 7) | REX_B(s);
4872 op = (modrm >> 3) & 7;
4874 if (mod != 3) {
4875 if (b == 0x83)
4876 s->rip_offset = 1;
4877 else
4878 s->rip_offset = insn_const_size(ot);
4879 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4880 opreg = OR_TMP0;
4881 } else {
4882 opreg = rm;
4885 switch(b) {
4886 default:
4887 case 0x80:
4888 case 0x81:
4889 case 0x82:
4890 val = insn_get(env, s, ot);
4891 break;
4892 case 0x83:
4893 val = (int8_t)insn_get(env, s, MO_8);
4894 break;
4896 gen_op_movl_T1_im(val);
4897 gen_op(s, op, ot, opreg);
4899 break;
4901 /**************************/
4902 /* inc, dec, and other misc arith */
4903 case 0x40 ... 0x47: /* inc Gv */
4904 ot = dflag ? MO_32 : MO_16;
4905 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4906 break;
4907 case 0x48 ... 0x4f: /* dec Gv */
4908 ot = dflag ? MO_32 : MO_16;
4909 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4910 break;
4911 case 0xf6: /* GRP3 */
4912 case 0xf7:
4913 if ((b & 1) == 0)
4914 ot = MO_8;
4915 else
4916 ot = dflag + MO_16;
4918 modrm = cpu_ldub_code(env, s->pc++);
4919 mod = (modrm >> 6) & 3;
4920 rm = (modrm & 7) | REX_B(s);
4921 op = (modrm >> 3) & 7;
4922 if (mod != 3) {
4923 if (op == 0)
4924 s->rip_offset = insn_const_size(ot);
4925 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4926 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
4927 } else {
4928 gen_op_mov_TN_reg(ot, 0, rm);
4931 switch(op) {
4932 case 0: /* test */
4933 val = insn_get(env, s, ot);
4934 gen_op_movl_T1_im(val);
4935 gen_op_testl_T0_T1_cc();
4936 set_cc_op(s, CC_OP_LOGICB + ot);
4937 break;
4938 case 2: /* not */
4939 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
4940 if (mod != 3) {
4941 gen_op_st_T0_A0(s, ot);
4942 } else {
4943 gen_op_mov_reg_T0(ot, rm);
4945 break;
4946 case 3: /* neg */
4947 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
4948 if (mod != 3) {
4949 gen_op_st_T0_A0(s, ot);
4950 } else {
4951 gen_op_mov_reg_T0(ot, rm);
4953 gen_op_update_neg_cc();
4954 set_cc_op(s, CC_OP_SUBB + ot);
4955 break;
4956 case 4: /* mul */
4957 switch(ot) {
4958 case MO_8:
4959 gen_op_mov_TN_reg(MO_8, 1, R_EAX);
4960 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4961 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4962 /* XXX: use 32 bit mul which could be faster */
4963 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4964 gen_op_mov_reg_T0(MO_16, R_EAX);
4965 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4966 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
4967 set_cc_op(s, CC_OP_MULB);
4968 break;
4969 case MO_16:
4970 gen_op_mov_TN_reg(MO_16, 1, R_EAX);
4971 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4972 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4973 /* XXX: use 32 bit mul which could be faster */
4974 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4975 gen_op_mov_reg_T0(MO_16, R_EAX);
4976 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4977 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4978 gen_op_mov_reg_T0(MO_16, R_EDX);
4979 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4980 set_cc_op(s, CC_OP_MULW);
4981 break;
4982 default:
4983 case MO_32:
4984 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4985 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4986 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4987 cpu_tmp2_i32, cpu_tmp3_i32);
4988 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4989 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4990 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4991 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4992 set_cc_op(s, CC_OP_MULL);
4993 break;
4994 #ifdef TARGET_X86_64
4995 case MO_64:
4996 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4997 cpu_T[0], cpu_regs[R_EAX]);
4998 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4999 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
5000 set_cc_op(s, CC_OP_MULQ);
5001 break;
5002 #endif
5004 break;
5005 case 5: /* imul */
5006 switch(ot) {
5007 case MO_8:
5008 gen_op_mov_TN_reg(MO_8, 1, R_EAX);
5009 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5010 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
5011 /* XXX: use 32 bit mul which could be faster */
5012 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5013 gen_op_mov_reg_T0(MO_16, R_EAX);
5014 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5015 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
5016 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5017 set_cc_op(s, CC_OP_MULB);
5018 break;
5019 case MO_16:
5020 gen_op_mov_TN_reg(MO_16, 1, R_EAX);
5021 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5022 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5023 /* XXX: use 32 bit mul which could be faster */
5024 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5025 gen_op_mov_reg_T0(MO_16, R_EAX);
5026 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5027 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5028 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5029 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
5030 gen_op_mov_reg_T0(MO_16, R_EDX);
5031 set_cc_op(s, CC_OP_MULW);
5032 break;
5033 default:
5034 case MO_32:
5035 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5036 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
5037 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5038 cpu_tmp2_i32, cpu_tmp3_i32);
5039 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
5040 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
5041 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5042 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5043 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5044 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5045 set_cc_op(s, CC_OP_MULL);
5046 break;
5047 #ifdef TARGET_X86_64
5048 case MO_64:
5049 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5050 cpu_T[0], cpu_regs[R_EAX]);
5051 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5052 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
5053 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
5054 set_cc_op(s, CC_OP_MULQ);
5055 break;
5056 #endif
5058 break;
5059 case 6: /* div */
5060 switch(ot) {
5061 case MO_8:
5062 gen_jmp_im(pc_start - s->cs_base);
5063 gen_helper_divb_AL(cpu_env, cpu_T[0]);
5064 break;
5065 case MO_16:
5066 gen_jmp_im(pc_start - s->cs_base);
5067 gen_helper_divw_AX(cpu_env, cpu_T[0]);
5068 break;
5069 default:
5070 case MO_32:
5071 gen_jmp_im(pc_start - s->cs_base);
5072 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
5073 break;
5074 #ifdef TARGET_X86_64
5075 case MO_64:
5076 gen_jmp_im(pc_start - s->cs_base);
5077 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
5078 break;
5079 #endif
5081 break;
5082 case 7: /* idiv */
5083 switch(ot) {
5084 case MO_8:
5085 gen_jmp_im(pc_start - s->cs_base);
5086 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
5087 break;
5088 case MO_16:
5089 gen_jmp_im(pc_start - s->cs_base);
5090 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
5091 break;
5092 default:
5093 case MO_32:
5094 gen_jmp_im(pc_start - s->cs_base);
5095 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
5096 break;
5097 #ifdef TARGET_X86_64
5098 case MO_64:
5099 gen_jmp_im(pc_start - s->cs_base);
5100 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
5101 break;
5102 #endif
5104 break;
5105 default:
5106 goto illegal_op;
5108 break;
5110 case 0xfe: /* GRP4 */
5111 case 0xff: /* GRP5 */
5112 if ((b & 1) == 0)
5113 ot = MO_8;
5114 else
5115 ot = dflag + MO_16;
5117 modrm = cpu_ldub_code(env, s->pc++);
5118 mod = (modrm >> 6) & 3;
5119 rm = (modrm & 7) | REX_B(s);
5120 op = (modrm >> 3) & 7;
5121 if (op >= 2 && b == 0xfe) {
5122 goto illegal_op;
5124 if (CODE64(s)) {
5125 if (op == 2 || op == 4) {
5126 /* operand size for jumps is 64 bit */
5127 ot = MO_64;
5128 } else if (op == 3 || op == 5) {
5129 ot = dflag ? MO_32 + (rex_w == 1) : MO_16;
5130 } else if (op == 6) {
5131 /* default push size is 64 bit */
5132 ot = dflag ? MO_64 : MO_16;
5135 if (mod != 3) {
5136 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5137 if (op >= 2 && op != 3 && op != 5)
5138 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
5139 } else {
5140 gen_op_mov_TN_reg(ot, 0, rm);
5143 switch(op) {
5144 case 0: /* inc Ev */
5145 if (mod != 3)
5146 opreg = OR_TMP0;
5147 else
5148 opreg = rm;
5149 gen_inc(s, ot, opreg, 1);
5150 break;
5151 case 1: /* dec Ev */
5152 if (mod != 3)
5153 opreg = OR_TMP0;
5154 else
5155 opreg = rm;
5156 gen_inc(s, ot, opreg, -1);
5157 break;
5158 case 2: /* call Ev */
5159 /* XXX: optimize if memory (no 'and' is necessary) */
5160 if (s->dflag == 0)
5161 gen_op_andl_T0_ffff();
5162 next_eip = s->pc - s->cs_base;
5163 gen_movtl_T1_im(next_eip);
5164 gen_push_T1(s);
5165 gen_op_jmp_T0();
5166 gen_eob(s);
5167 break;
5168 case 3: /* lcall Ev */
5169 gen_op_ld_T1_A0(s, ot);
5170 gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
5171 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
5172 do_lcall:
5173 if (s->pe && !s->vm86) {
5174 gen_update_cc_op(s);
5175 gen_jmp_im(pc_start - s->cs_base);
5176 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5177 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
5178 tcg_const_i32(dflag),
5179 tcg_const_i32(s->pc - pc_start));
5180 } else {
5181 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5182 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
5183 tcg_const_i32(dflag),
5184 tcg_const_i32(s->pc - s->cs_base));
5186 gen_eob(s);
5187 break;
5188 case 4: /* jmp Ev */
5189 if (s->dflag == 0)
5190 gen_op_andl_T0_ffff();
5191 gen_op_jmp_T0();
5192 gen_eob(s);
5193 break;
5194 case 5: /* ljmp Ev */
5195 gen_op_ld_T1_A0(s, ot);
5196 gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
5197 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
5198 do_ljmp:
5199 if (s->pe && !s->vm86) {
5200 gen_update_cc_op(s);
5201 gen_jmp_im(pc_start - s->cs_base);
5202 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5203 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
5204 tcg_const_i32(s->pc - pc_start));
5205 } else {
5206 gen_op_movl_seg_T0_vm(R_CS);
5207 gen_op_movl_T0_T1();
5208 gen_op_jmp_T0();
5210 gen_eob(s);
5211 break;
5212 case 6: /* push Ev */
5213 gen_push_T0(s);
5214 break;
5215 default:
5216 goto illegal_op;
5218 break;
5220 case 0x84: /* test Ev, Gv */
5221 case 0x85:
5222 if ((b & 1) == 0)
5223 ot = MO_8;
5224 else
5225 ot = dflag + MO_16;
5227 modrm = cpu_ldub_code(env, s->pc++);
5228 reg = ((modrm >> 3) & 7) | rex_r;
5230 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5231 gen_op_mov_TN_reg(ot, 1, reg);
5232 gen_op_testl_T0_T1_cc();
5233 set_cc_op(s, CC_OP_LOGICB + ot);
5234 break;
5236 case 0xa8: /* test eAX, Iv */
5237 case 0xa9:
5238 if ((b & 1) == 0)
5239 ot = MO_8;
5240 else
5241 ot = dflag + MO_16;
5242 val = insn_get(env, s, ot);
5244 gen_op_mov_TN_reg(ot, 0, OR_EAX);
5245 gen_op_movl_T1_im(val);
5246 gen_op_testl_T0_T1_cc();
5247 set_cc_op(s, CC_OP_LOGICB + ot);
5248 break;
5250 case 0x98: /* CWDE/CBW */
5251 #ifdef TARGET_X86_64
5252 if (dflag == 2) {
5253 gen_op_mov_TN_reg(MO_32, 0, R_EAX);
5254 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5255 gen_op_mov_reg_T0(MO_64, R_EAX);
5256 } else
5257 #endif
5258 if (dflag == 1) {
5259 gen_op_mov_TN_reg(MO_16, 0, R_EAX);
5260 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5261 gen_op_mov_reg_T0(MO_32, R_EAX);
5262 } else {
5263 gen_op_mov_TN_reg(MO_8, 0, R_EAX);
5264 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5265 gen_op_mov_reg_T0(MO_16, R_EAX);
5267 break;
5268 case 0x99: /* CDQ/CWD */
5269 #ifdef TARGET_X86_64
5270 if (dflag == 2) {
5271 gen_op_mov_TN_reg(MO_64, 0, R_EAX);
5272 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
5273 gen_op_mov_reg_T0(MO_64, R_EDX);
5274 } else
5275 #endif
5276 if (dflag == 1) {
5277 gen_op_mov_TN_reg(MO_32, 0, R_EAX);
5278 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5279 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
5280 gen_op_mov_reg_T0(MO_32, R_EDX);
5281 } else {
5282 gen_op_mov_TN_reg(MO_16, 0, R_EAX);
5283 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5284 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
5285 gen_op_mov_reg_T0(MO_16, R_EDX);
5287 break;
5288 case 0x1af: /* imul Gv, Ev */
5289 case 0x69: /* imul Gv, Ev, I */
5290 case 0x6b:
5291 ot = dflag + MO_16;
5292 modrm = cpu_ldub_code(env, s->pc++);
5293 reg = ((modrm >> 3) & 7) | rex_r;
5294 if (b == 0x69)
5295 s->rip_offset = insn_const_size(ot);
5296 else if (b == 0x6b)
5297 s->rip_offset = 1;
5298 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5299 if (b == 0x69) {
5300 val = insn_get(env, s, ot);
5301 gen_op_movl_T1_im(val);
5302 } else if (b == 0x6b) {
5303 val = (int8_t)insn_get(env, s, MO_8);
5304 gen_op_movl_T1_im(val);
5305 } else {
5306 gen_op_mov_TN_reg(ot, 1, reg);
5308 switch (ot) {
5309 #ifdef TARGET_X86_64
5310 case MO_64:
5311 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
5312 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5313 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5314 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
5315 break;
5316 #endif
5317 case MO_32:
5318 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5319 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5320 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5321 cpu_tmp2_i32, cpu_tmp3_i32);
5322 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5323 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5324 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5325 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5326 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5327 break;
5328 default:
5329 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5330 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5331 /* XXX: use 32 bit mul which could be faster */
5332 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5333 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5334 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5335 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5336 gen_op_mov_reg_T0(ot, reg);
5337 break;
5339 set_cc_op(s, CC_OP_MULB + ot);
5340 break;
5341 case 0x1c0:
5342 case 0x1c1: /* xadd Ev, Gv */
5343 if ((b & 1) == 0)
5344 ot = MO_8;
5345 else
5346 ot = dflag + MO_16;
5347 modrm = cpu_ldub_code(env, s->pc++);
5348 reg = ((modrm >> 3) & 7) | rex_r;
5349 mod = (modrm >> 6) & 3;
5350 if (mod == 3) {
5351 rm = (modrm & 7) | REX_B(s);
5352 gen_op_mov_TN_reg(ot, 0, reg);
5353 gen_op_mov_TN_reg(ot, 1, rm);
5354 gen_op_addl_T0_T1();
5355 gen_op_mov_reg_T1(ot, reg);
5356 gen_op_mov_reg_T0(ot, rm);
5357 } else {
5358 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5359 gen_op_mov_TN_reg(ot, 0, reg);
5360 gen_op_ld_T1_A0(s, ot);
5361 gen_op_addl_T0_T1();
5362 gen_op_st_T0_A0(s, ot);
5363 gen_op_mov_reg_T1(ot, reg);
5365 gen_op_update2_cc();
5366 set_cc_op(s, CC_OP_ADDB + ot);
5367 break;
5368 case 0x1b0:
5369 case 0x1b1: /* cmpxchg Ev, Gv */
5371 int label1, label2;
5372 TCGv t0, t1, t2, a0;
5374 if ((b & 1) == 0)
5375 ot = MO_8;
5376 else
5377 ot = dflag + MO_16;
5378 modrm = cpu_ldub_code(env, s->pc++);
5379 reg = ((modrm >> 3) & 7) | rex_r;
5380 mod = (modrm >> 6) & 3;
5381 t0 = tcg_temp_local_new();
5382 t1 = tcg_temp_local_new();
5383 t2 = tcg_temp_local_new();
5384 a0 = tcg_temp_local_new();
5385 gen_op_mov_v_reg(ot, t1, reg);
5386 if (mod == 3) {
5387 rm = (modrm & 7) | REX_B(s);
5388 gen_op_mov_v_reg(ot, t0, rm);
5389 } else {
5390 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5391 tcg_gen_mov_tl(a0, cpu_A0);
5392 gen_op_ld_v(s, ot, t0, a0);
5393 rm = 0; /* avoid warning */
5395 label1 = gen_new_label();
5396 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5397 gen_extu(ot, t0);
5398 gen_extu(ot, t2);
5399 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
5400 label2 = gen_new_label();
5401 if (mod == 3) {
5402 gen_op_mov_reg_v(ot, R_EAX, t0);
5403 tcg_gen_br(label2);
5404 gen_set_label(label1);
5405 gen_op_mov_reg_v(ot, rm, t1);
5406 } else {
5407 /* perform no-op store cycle like physical cpu; must be
5408 before changing accumulator to ensure idempotency if
5409 the store faults and the instruction is restarted */
5410 gen_op_st_v(s, ot, t0, a0);
5411 gen_op_mov_reg_v(ot, R_EAX, t0);
5412 tcg_gen_br(label2);
5413 gen_set_label(label1);
5414 gen_op_st_v(s, ot, t1, a0);
5416 gen_set_label(label2);
5417 tcg_gen_mov_tl(cpu_cc_src, t0);
5418 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5419 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
5420 set_cc_op(s, CC_OP_SUBB + ot);
5421 tcg_temp_free(t0);
5422 tcg_temp_free(t1);
5423 tcg_temp_free(t2);
5424 tcg_temp_free(a0);
5426 break;
5427 case 0x1c7: /* cmpxchg8b */
5428 modrm = cpu_ldub_code(env, s->pc++);
5429 mod = (modrm >> 6) & 3;
5430 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5431 goto illegal_op;
5432 #ifdef TARGET_X86_64
5433 if (dflag == 2) {
5434 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5435 goto illegal_op;
5436 gen_jmp_im(pc_start - s->cs_base);
5437 gen_update_cc_op(s);
5438 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5439 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5440 } else
5441 #endif
5443 if (!(s->cpuid_features & CPUID_CX8))
5444 goto illegal_op;
5445 gen_jmp_im(pc_start - s->cs_base);
5446 gen_update_cc_op(s);
5447 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5448 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5450 set_cc_op(s, CC_OP_EFLAGS);
5451 break;
5453 /**************************/
5454 /* push/pop */
5455 case 0x50 ... 0x57: /* push */
5456 gen_op_mov_TN_reg(MO_32, 0, (b & 7) | REX_B(s));
5457 gen_push_T0(s);
5458 break;
5459 case 0x58 ... 0x5f: /* pop */
5460 if (CODE64(s)) {
5461 ot = dflag ? MO_64 : MO_16;
5462 } else {
5463 ot = dflag + MO_16;
5465 gen_pop_T0(s);
5466 /* NOTE: order is important for pop %sp */
5467 gen_pop_update(s);
5468 gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
5469 break;
5470 case 0x60: /* pusha */
5471 if (CODE64(s))
5472 goto illegal_op;
5473 gen_pusha(s);
5474 break;
5475 case 0x61: /* popa */
5476 if (CODE64(s))
5477 goto illegal_op;
5478 gen_popa(s);
5479 break;
5480 case 0x68: /* push Iv */
5481 case 0x6a:
5482 if (CODE64(s)) {
5483 ot = dflag ? MO_64 : MO_16;
5484 } else {
5485 ot = dflag + MO_16;
5487 if (b == 0x68)
5488 val = insn_get(env, s, ot);
5489 else
5490 val = (int8_t)insn_get(env, s, MO_8);
5491 gen_op_movl_T0_im(val);
5492 gen_push_T0(s);
5493 break;
5494 case 0x8f: /* pop Ev */
5495 if (CODE64(s)) {
5496 ot = dflag ? MO_64 : MO_16;
5497 } else {
5498 ot = dflag + MO_16;
5500 modrm = cpu_ldub_code(env, s->pc++);
5501 mod = (modrm >> 6) & 3;
5502 gen_pop_T0(s);
5503 if (mod == 3) {
5504 /* NOTE: order is important for pop %sp */
5505 gen_pop_update(s);
5506 rm = (modrm & 7) | REX_B(s);
5507 gen_op_mov_reg_T0(ot, rm);
5508 } else {
5509 /* NOTE: order is important too for MMU exceptions */
5510 s->popl_esp_hack = 1 << ot;
5511 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5512 s->popl_esp_hack = 0;
5513 gen_pop_update(s);
5515 break;
5516 case 0xc8: /* enter */
5518 int level;
5519 val = cpu_lduw_code(env, s->pc);
5520 s->pc += 2;
5521 level = cpu_ldub_code(env, s->pc++);
5522 gen_enter(s, val, level);
5524 break;
5525 case 0xc9: /* leave */
5526 /* XXX: exception not precise (ESP is updated before potential exception) */
5527 if (CODE64(s)) {
5528 gen_op_mov_TN_reg(MO_64, 0, R_EBP);
5529 gen_op_mov_reg_T0(MO_64, R_ESP);
5530 } else if (s->ss32) {
5531 gen_op_mov_TN_reg(MO_32, 0, R_EBP);
5532 gen_op_mov_reg_T0(MO_32, R_ESP);
5533 } else {
5534 gen_op_mov_TN_reg(MO_16, 0, R_EBP);
5535 gen_op_mov_reg_T0(MO_16, R_ESP);
5537 gen_pop_T0(s);
5538 if (CODE64(s)) {
5539 ot = dflag ? MO_64 : MO_16;
5540 } else {
5541 ot = dflag + MO_16;
5543 gen_op_mov_reg_T0(ot, R_EBP);
5544 gen_pop_update(s);
5545 break;
5546 case 0x06: /* push es */
5547 case 0x0e: /* push cs */
5548 case 0x16: /* push ss */
5549 case 0x1e: /* push ds */
5550 if (CODE64(s))
5551 goto illegal_op;
5552 gen_op_movl_T0_seg(b >> 3);
5553 gen_push_T0(s);
5554 break;
5555 case 0x1a0: /* push fs */
5556 case 0x1a8: /* push gs */
5557 gen_op_movl_T0_seg((b >> 3) & 7);
5558 gen_push_T0(s);
5559 break;
5560 case 0x07: /* pop es */
5561 case 0x17: /* pop ss */
5562 case 0x1f: /* pop ds */
5563 if (CODE64(s))
5564 goto illegal_op;
5565 reg = b >> 3;
5566 gen_pop_T0(s);
5567 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5568 gen_pop_update(s);
5569 if (reg == R_SS) {
5570 /* if reg == SS, inhibit interrupts/trace. */
5571 /* If several instructions disable interrupts, only the
5572 _first_ does it */
5573 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5574 gen_helper_set_inhibit_irq(cpu_env);
5575 s->tf = 0;
5577 if (s->is_jmp) {
5578 gen_jmp_im(s->pc - s->cs_base);
5579 gen_eob(s);
5581 break;
5582 case 0x1a1: /* pop fs */
5583 case 0x1a9: /* pop gs */
5584 gen_pop_T0(s);
5585 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
5586 gen_pop_update(s);
5587 if (s->is_jmp) {
5588 gen_jmp_im(s->pc - s->cs_base);
5589 gen_eob(s);
5591 break;
5593 /**************************/
5594 /* mov */
5595 case 0x88:
5596 case 0x89: /* mov Gv, Ev */
5597 if ((b & 1) == 0)
5598 ot = MO_8;
5599 else
5600 ot = dflag + MO_16;
5601 modrm = cpu_ldub_code(env, s->pc++);
5602 reg = ((modrm >> 3) & 7) | rex_r;
5604 /* generate a generic store */
5605 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5606 break;
5607 case 0xc6:
5608 case 0xc7: /* mov Ev, Iv */
5609 if ((b & 1) == 0)
5610 ot = MO_8;
5611 else
5612 ot = dflag + MO_16;
5613 modrm = cpu_ldub_code(env, s->pc++);
5614 mod = (modrm >> 6) & 3;
5615 if (mod != 3) {
5616 s->rip_offset = insn_const_size(ot);
5617 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5619 val = insn_get(env, s, ot);
5620 gen_op_movl_T0_im(val);
5621 if (mod != 3)
5622 gen_op_st_T0_A0(s, ot);
5623 else
5624 gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
5625 break;
5626 case 0x8a:
5627 case 0x8b: /* mov Ev, Gv */
5628 if ((b & 1) == 0)
5629 ot = MO_8;
5630 else
5631 ot = MO_16 + dflag;
5632 modrm = cpu_ldub_code(env, s->pc++);
5633 reg = ((modrm >> 3) & 7) | rex_r;
5635 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5636 gen_op_mov_reg_T0(ot, reg);
5637 break;
5638 case 0x8e: /* mov seg, Gv */
5639 modrm = cpu_ldub_code(env, s->pc++);
5640 reg = (modrm >> 3) & 7;
5641 if (reg >= 6 || reg == R_CS)
5642 goto illegal_op;
5643 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5644 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5645 if (reg == R_SS) {
5646 /* if reg == SS, inhibit interrupts/trace */
5647 /* If several instructions disable interrupts, only the
5648 _first_ does it */
5649 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5650 gen_helper_set_inhibit_irq(cpu_env);
5651 s->tf = 0;
5653 if (s->is_jmp) {
5654 gen_jmp_im(s->pc - s->cs_base);
5655 gen_eob(s);
5657 break;
5658 case 0x8c: /* mov Gv, seg */
5659 modrm = cpu_ldub_code(env, s->pc++);
5660 reg = (modrm >> 3) & 7;
5661 mod = (modrm >> 6) & 3;
5662 if (reg >= 6)
5663 goto illegal_op;
5664 gen_op_movl_T0_seg(reg);
5665 if (mod == 3)
5666 ot = MO_16 + dflag;
5667 else
5668 ot = MO_16;
5669 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5670 break;
5672 case 0x1b6: /* movzbS Gv, Eb */
5673 case 0x1b7: /* movzwS Gv, Eb */
5674 case 0x1be: /* movsbS Gv, Eb */
5675 case 0x1bf: /* movswS Gv, Eb */
5677 int d_ot;
5678 /* d_ot is the size of destination */
5679 d_ot = dflag + MO_16;
5680 /* ot is the size of source */
5681 ot = (b & 1) + MO_8;
5682 modrm = cpu_ldub_code(env, s->pc++);
5683 reg = ((modrm >> 3) & 7) | rex_r;
5684 mod = (modrm >> 6) & 3;
5685 rm = (modrm & 7) | REX_B(s);
5687 if (mod == 3) {
5688 gen_op_mov_TN_reg(ot, 0, rm);
5689 switch(ot | (b & 8)) {
5690 case MO_8:
5691 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
5692 break;
5693 case MO_8 | 8:
5694 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5695 break;
5696 case MO_16:
5697 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
5698 break;
5699 default:
5700 case MO_16 | 8:
5701 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5702 break;
5704 gen_op_mov_reg_T0(d_ot, reg);
5705 } else {
5706 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5707 if (b & 8) {
5708 gen_op_lds_T0_A0(s, ot);
5709 } else {
5710 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
5712 gen_op_mov_reg_T0(d_ot, reg);
5715 break;
5717 case 0x8d: /* lea */
5718 ot = dflag + MO_16;
5719 modrm = cpu_ldub_code(env, s->pc++);
5720 mod = (modrm >> 6) & 3;
5721 if (mod == 3)
5722 goto illegal_op;
5723 reg = ((modrm >> 3) & 7) | rex_r;
5724 /* we must ensure that no segment is added */
5725 s->override = -1;
5726 val = s->addseg;
5727 s->addseg = 0;
5728 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5729 s->addseg = val;
5730 gen_op_mov_reg_A0(ot - MO_16, reg);
5731 break;
5733 case 0xa0: /* mov EAX, Ov */
5734 case 0xa1:
5735 case 0xa2: /* mov Ov, EAX */
5736 case 0xa3:
5738 target_ulong offset_addr;
5740 if ((b & 1) == 0)
5741 ot = MO_8;
5742 else
5743 ot = dflag + MO_16;
5744 #ifdef TARGET_X86_64
5745 if (s->aflag == 2) {
5746 offset_addr = cpu_ldq_code(env, s->pc);
5747 s->pc += 8;
5748 gen_op_movq_A0_im(offset_addr);
5749 } else
5750 #endif
5752 if (s->aflag) {
5753 offset_addr = insn_get(env, s, MO_32);
5754 } else {
5755 offset_addr = insn_get(env, s, MO_16);
5757 gen_op_movl_A0_im(offset_addr);
5759 gen_add_A0_ds_seg(s);
5760 if ((b & 2) == 0) {
5761 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
5762 gen_op_mov_reg_T0(ot, R_EAX);
5763 } else {
5764 gen_op_mov_TN_reg(ot, 0, R_EAX);
5765 gen_op_st_T0_A0(s, ot);
5768 break;
5769 case 0xd7: /* xlat */
5770 #ifdef TARGET_X86_64
5771 if (s->aflag == 2) {
5772 gen_op_movq_A0_reg(R_EBX);
5773 gen_op_mov_TN_reg(MO_64, 0, R_EAX);
5774 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5775 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5776 } else
5777 #endif
5779 gen_op_movl_A0_reg(R_EBX);
5780 gen_op_mov_TN_reg(MO_32, 0, R_EAX);
5781 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5782 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5783 if (s->aflag == 0)
5784 gen_op_andl_A0_ffff();
5785 else
5786 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
5788 gen_add_A0_ds_seg(s);
5789 gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
5790 gen_op_mov_reg_T0(MO_8, R_EAX);
5791 break;
5792 case 0xb0 ... 0xb7: /* mov R, Ib */
5793 val = insn_get(env, s, MO_8);
5794 gen_op_movl_T0_im(val);
5795 gen_op_mov_reg_T0(MO_8, (b & 7) | REX_B(s));
5796 break;
5797 case 0xb8 ... 0xbf: /* mov R, Iv */
5798 #ifdef TARGET_X86_64
5799 if (dflag == 2) {
5800 uint64_t tmp;
5801 /* 64 bit case */
5802 tmp = cpu_ldq_code(env, s->pc);
5803 s->pc += 8;
5804 reg = (b & 7) | REX_B(s);
5805 gen_movtl_T0_im(tmp);
5806 gen_op_mov_reg_T0(MO_64, reg);
5807 } else
5808 #endif
5810 ot = dflag ? MO_32 : MO_16;
5811 val = insn_get(env, s, ot);
5812 reg = (b & 7) | REX_B(s);
5813 gen_op_movl_T0_im(val);
5814 gen_op_mov_reg_T0(ot, reg);
5816 break;
5818 case 0x91 ... 0x97: /* xchg R, EAX */
5819 do_xchg_reg_eax:
5820 ot = dflag + MO_16;
5821 reg = (b & 7) | REX_B(s);
5822 rm = R_EAX;
5823 goto do_xchg_reg;
5824 case 0x86:
5825 case 0x87: /* xchg Ev, Gv */
5826 if ((b & 1) == 0)
5827 ot = MO_8;
5828 else
5829 ot = dflag + MO_16;
5830 modrm = cpu_ldub_code(env, s->pc++);
5831 reg = ((modrm >> 3) & 7) | rex_r;
5832 mod = (modrm >> 6) & 3;
5833 if (mod == 3) {
5834 rm = (modrm & 7) | REX_B(s);
5835 do_xchg_reg:
5836 gen_op_mov_TN_reg(ot, 0, reg);
5837 gen_op_mov_TN_reg(ot, 1, rm);
5838 gen_op_mov_reg_T0(ot, rm);
5839 gen_op_mov_reg_T1(ot, reg);
5840 } else {
5841 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5842 gen_op_mov_TN_reg(ot, 0, reg);
5843 /* for xchg, lock is implicit */
5844 if (!(prefixes & PREFIX_LOCK))
5845 gen_helper_lock();
5846 gen_op_ld_T1_A0(s, ot);
5847 gen_op_st_T0_A0(s, ot);
5848 if (!(prefixes & PREFIX_LOCK))
5849 gen_helper_unlock();
5850 gen_op_mov_reg_T1(ot, reg);
5852 break;
5853 case 0xc4: /* les Gv */
5854 /* In CODE64 this is VEX3; see above. */
5855 op = R_ES;
5856 goto do_lxx;
5857 case 0xc5: /* lds Gv */
5858 /* In CODE64 this is VEX2; see above. */
5859 op = R_DS;
5860 goto do_lxx;
5861 case 0x1b2: /* lss Gv */
5862 op = R_SS;
5863 goto do_lxx;
5864 case 0x1b4: /* lfs Gv */
5865 op = R_FS;
5866 goto do_lxx;
5867 case 0x1b5: /* lgs Gv */
5868 op = R_GS;
5869 do_lxx:
5870 ot = dflag ? MO_32 : MO_16;
5871 modrm = cpu_ldub_code(env, s->pc++);
5872 reg = ((modrm >> 3) & 7) | rex_r;
5873 mod = (modrm >> 6) & 3;
5874 if (mod == 3)
5875 goto illegal_op;
5876 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5877 gen_op_ld_T1_A0(s, ot);
5878 gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
5879 /* load the segment first to handle exceptions properly */
5880 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
5881 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5882 /* then put the data */
5883 gen_op_mov_reg_T1(ot, reg);
5884 if (s->is_jmp) {
5885 gen_jmp_im(s->pc - s->cs_base);
5886 gen_eob(s);
5888 break;
5890 /************************/
5891 /* shifts */
5892 case 0xc0:
5893 case 0xc1:
5894 /* shift Ev,Ib */
5895 shift = 2;
5896 grp2:
5898 if ((b & 1) == 0)
5899 ot = MO_8;
5900 else
5901 ot = dflag + MO_16;
5903 modrm = cpu_ldub_code(env, s->pc++);
5904 mod = (modrm >> 6) & 3;
5905 op = (modrm >> 3) & 7;
5907 if (mod != 3) {
5908 if (shift == 2) {
5909 s->rip_offset = 1;
5911 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5912 opreg = OR_TMP0;
5913 } else {
5914 opreg = (modrm & 7) | REX_B(s);
5917 /* simpler op */
5918 if (shift == 0) {
5919 gen_shift(s, op, ot, opreg, OR_ECX);
5920 } else {
5921 if (shift == 2) {
5922 shift = cpu_ldub_code(env, s->pc++);
5924 gen_shifti(s, op, ot, opreg, shift);
5927 break;
5928 case 0xd0:
5929 case 0xd1:
5930 /* shift Ev,1 */
5931 shift = 1;
5932 goto grp2;
5933 case 0xd2:
5934 case 0xd3:
5935 /* shift Ev,cl */
5936 shift = 0;
5937 goto grp2;
5939 case 0x1a4: /* shld imm */
5940 op = 0;
5941 shift = 1;
5942 goto do_shiftd;
5943 case 0x1a5: /* shld cl */
5944 op = 0;
5945 shift = 0;
5946 goto do_shiftd;
5947 case 0x1ac: /* shrd imm */
5948 op = 1;
5949 shift = 1;
5950 goto do_shiftd;
5951 case 0x1ad: /* shrd cl */
5952 op = 1;
5953 shift = 0;
5954 do_shiftd:
5955 ot = dflag + MO_16;
5956 modrm = cpu_ldub_code(env, s->pc++);
5957 mod = (modrm >> 6) & 3;
5958 rm = (modrm & 7) | REX_B(s);
5959 reg = ((modrm >> 3) & 7) | rex_r;
5960 if (mod != 3) {
5961 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5962 opreg = OR_TMP0;
5963 } else {
5964 opreg = rm;
5966 gen_op_mov_TN_reg(ot, 1, reg);
5968 if (shift) {
5969 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5970 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5971 tcg_temp_free(imm);
5972 } else {
5973 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5975 break;
5977 /************************/
5978 /* floats */
5979 case 0xd8 ... 0xdf:
5980 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5981 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5982 /* XXX: what to do if illegal op ? */
5983 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5984 break;
5986 modrm = cpu_ldub_code(env, s->pc++);
5987 mod = (modrm >> 6) & 3;
5988 rm = modrm & 7;
5989 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5990 if (mod != 3) {
5991 /* memory op */
5992 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5993 switch(op) {
5994 case 0x00 ... 0x07: /* fxxxs */
5995 case 0x10 ... 0x17: /* fixxxl */
5996 case 0x20 ... 0x27: /* fxxxl */
5997 case 0x30 ... 0x37: /* fixxx */
5999 int op1;
6000 op1 = op & 7;
6002 switch(op >> 4) {
6003 case 0:
6004 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
6005 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6006 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
6007 break;
6008 case 1:
6009 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
6010 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6011 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
6012 break;
6013 case 2:
6014 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
6015 s->mem_index, MO_LEQ);
6016 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
6017 break;
6018 case 3:
6019 default:
6020 gen_op_lds_T0_A0(s, MO_16);
6021 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6022 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
6023 break;
6026 gen_helper_fp_arith_ST0_FT0(op1);
6027 if (op1 == 3) {
6028 /* fcomp needs pop */
6029 gen_helper_fpop(cpu_env);
6032 break;
6033 case 0x08: /* flds */
6034 case 0x0a: /* fsts */
6035 case 0x0b: /* fstps */
6036 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
6037 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
6038 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
6039 switch(op & 7) {
6040 case 0:
6041 switch(op >> 4) {
6042 case 0:
6043 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
6044 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6045 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
6046 break;
6047 case 1:
6048 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
6049 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6050 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
6051 break;
6052 case 2:
6053 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
6054 s->mem_index, MO_LEQ);
6055 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
6056 break;
6057 case 3:
6058 default:
6059 gen_op_lds_T0_A0(s, MO_16);
6060 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6061 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
6062 break;
6064 break;
6065 case 1:
6066 /* XXX: the corresponding CPUID bit must be tested ! */
6067 switch(op >> 4) {
6068 case 1:
6069 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
6070 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6071 gen_op_st_T0_A0(s, MO_32);
6072 break;
6073 case 2:
6074 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
6075 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
6076 s->mem_index, MO_LEQ);
6077 break;
6078 case 3:
6079 default:
6080 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
6081 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6082 gen_op_st_T0_A0(s, MO_16);
6083 break;
6085 gen_helper_fpop(cpu_env);
6086 break;
6087 default:
6088 switch(op >> 4) {
6089 case 0:
6090 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
6091 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6092 gen_op_st_T0_A0(s, MO_32);
6093 break;
6094 case 1:
6095 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
6096 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6097 gen_op_st_T0_A0(s, MO_32);
6098 break;
6099 case 2:
6100 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
6101 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
6102 s->mem_index, MO_LEQ);
6103 break;
6104 case 3:
6105 default:
6106 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
6107 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6108 gen_op_st_T0_A0(s, MO_16);
6109 break;
6111 if ((op & 7) == 3)
6112 gen_helper_fpop(cpu_env);
6113 break;
6115 break;
6116 case 0x0c: /* fldenv mem */
6117 gen_update_cc_op(s);
6118 gen_jmp_im(pc_start - s->cs_base);
6119 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
6120 break;
6121 case 0x0d: /* fldcw mem */
6122 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
6123 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6124 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
6125 break;
6126 case 0x0e: /* fnstenv mem */
6127 gen_update_cc_op(s);
6128 gen_jmp_im(pc_start - s->cs_base);
6129 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
6130 break;
6131 case 0x0f: /* fnstcw mem */
6132 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
6133 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6134 gen_op_st_T0_A0(s, MO_16);
6135 break;
6136 case 0x1d: /* fldt mem */
6137 gen_update_cc_op(s);
6138 gen_jmp_im(pc_start - s->cs_base);
6139 gen_helper_fldt_ST0(cpu_env, cpu_A0);
6140 break;
6141 case 0x1f: /* fstpt mem */
6142 gen_update_cc_op(s);
6143 gen_jmp_im(pc_start - s->cs_base);
6144 gen_helper_fstt_ST0(cpu_env, cpu_A0);
6145 gen_helper_fpop(cpu_env);
6146 break;
6147 case 0x2c: /* frstor mem */
6148 gen_update_cc_op(s);
6149 gen_jmp_im(pc_start - s->cs_base);
6150 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
6151 break;
6152 case 0x2e: /* fnsave mem */
6153 gen_update_cc_op(s);
6154 gen_jmp_im(pc_start - s->cs_base);
6155 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
6156 break;
6157 case 0x2f: /* fnstsw mem */
6158 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6159 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6160 gen_op_st_T0_A0(s, MO_16);
6161 break;
6162 case 0x3c: /* fbld */
6163 gen_update_cc_op(s);
6164 gen_jmp_im(pc_start - s->cs_base);
6165 gen_helper_fbld_ST0(cpu_env, cpu_A0);
6166 break;
6167 case 0x3e: /* fbstp */
6168 gen_update_cc_op(s);
6169 gen_jmp_im(pc_start - s->cs_base);
6170 gen_helper_fbst_ST0(cpu_env, cpu_A0);
6171 gen_helper_fpop(cpu_env);
6172 break;
6173 case 0x3d: /* fildll */
6174 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
6175 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
6176 break;
6177 case 0x3f: /* fistpll */
6178 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
6179 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
6180 gen_helper_fpop(cpu_env);
6181 break;
6182 default:
6183 goto illegal_op;
6185 } else {
6186 /* register float ops */
6187 opreg = rm;
6189 switch(op) {
6190 case 0x08: /* fld sti */
6191 gen_helper_fpush(cpu_env);
6192 gen_helper_fmov_ST0_STN(cpu_env,
6193 tcg_const_i32((opreg + 1) & 7));
6194 break;
6195 case 0x09: /* fxchg sti */
6196 case 0x29: /* fxchg4 sti, undocumented op */
6197 case 0x39: /* fxchg7 sti, undocumented op */
6198 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
6199 break;
6200 case 0x0a: /* grp d9/2 */
6201 switch(rm) {
6202 case 0: /* fnop */
6203 /* check exceptions (FreeBSD FPU probe) */
6204 gen_update_cc_op(s);
6205 gen_jmp_im(pc_start - s->cs_base);
6206 gen_helper_fwait(cpu_env);
6207 break;
6208 default:
6209 goto illegal_op;
6211 break;
6212 case 0x0c: /* grp d9/4 */
6213 switch(rm) {
6214 case 0: /* fchs */
6215 gen_helper_fchs_ST0(cpu_env);
6216 break;
6217 case 1: /* fabs */
6218 gen_helper_fabs_ST0(cpu_env);
6219 break;
6220 case 4: /* ftst */
6221 gen_helper_fldz_FT0(cpu_env);
6222 gen_helper_fcom_ST0_FT0(cpu_env);
6223 break;
6224 case 5: /* fxam */
6225 gen_helper_fxam_ST0(cpu_env);
6226 break;
6227 default:
6228 goto illegal_op;
6230 break;
6231 case 0x0d: /* grp d9/5 */
6233 switch(rm) {
6234 case 0:
6235 gen_helper_fpush(cpu_env);
6236 gen_helper_fld1_ST0(cpu_env);
6237 break;
6238 case 1:
6239 gen_helper_fpush(cpu_env);
6240 gen_helper_fldl2t_ST0(cpu_env);
6241 break;
6242 case 2:
6243 gen_helper_fpush(cpu_env);
6244 gen_helper_fldl2e_ST0(cpu_env);
6245 break;
6246 case 3:
6247 gen_helper_fpush(cpu_env);
6248 gen_helper_fldpi_ST0(cpu_env);
6249 break;
6250 case 4:
6251 gen_helper_fpush(cpu_env);
6252 gen_helper_fldlg2_ST0(cpu_env);
6253 break;
6254 case 5:
6255 gen_helper_fpush(cpu_env);
6256 gen_helper_fldln2_ST0(cpu_env);
6257 break;
6258 case 6:
6259 gen_helper_fpush(cpu_env);
6260 gen_helper_fldz_ST0(cpu_env);
6261 break;
6262 default:
6263 goto illegal_op;
6266 break;
6267 case 0x0e: /* grp d9/6 */
6268 switch(rm) {
6269 case 0: /* f2xm1 */
6270 gen_helper_f2xm1(cpu_env);
6271 break;
6272 case 1: /* fyl2x */
6273 gen_helper_fyl2x(cpu_env);
6274 break;
6275 case 2: /* fptan */
6276 gen_helper_fptan(cpu_env);
6277 break;
6278 case 3: /* fpatan */
6279 gen_helper_fpatan(cpu_env);
6280 break;
6281 case 4: /* fxtract */
6282 gen_helper_fxtract(cpu_env);
6283 break;
6284 case 5: /* fprem1 */
6285 gen_helper_fprem1(cpu_env);
6286 break;
6287 case 6: /* fdecstp */
6288 gen_helper_fdecstp(cpu_env);
6289 break;
6290 default:
6291 case 7: /* fincstp */
6292 gen_helper_fincstp(cpu_env);
6293 break;
6295 break;
6296 case 0x0f: /* grp d9/7 */
6297 switch(rm) {
6298 case 0: /* fprem */
6299 gen_helper_fprem(cpu_env);
6300 break;
6301 case 1: /* fyl2xp1 */
6302 gen_helper_fyl2xp1(cpu_env);
6303 break;
6304 case 2: /* fsqrt */
6305 gen_helper_fsqrt(cpu_env);
6306 break;
6307 case 3: /* fsincos */
6308 gen_helper_fsincos(cpu_env);
6309 break;
6310 case 5: /* fscale */
6311 gen_helper_fscale(cpu_env);
6312 break;
6313 case 4: /* frndint */
6314 gen_helper_frndint(cpu_env);
6315 break;
6316 case 6: /* fsin */
6317 gen_helper_fsin(cpu_env);
6318 break;
6319 default:
6320 case 7: /* fcos */
6321 gen_helper_fcos(cpu_env);
6322 break;
6324 break;
6325 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6326 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6327 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6329 int op1;
6331 op1 = op & 7;
6332 if (op >= 0x20) {
6333 gen_helper_fp_arith_STN_ST0(op1, opreg);
6334 if (op >= 0x30)
6335 gen_helper_fpop(cpu_env);
6336 } else {
6337 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6338 gen_helper_fp_arith_ST0_FT0(op1);
6341 break;
6342 case 0x02: /* fcom */
6343 case 0x22: /* fcom2, undocumented op */
6344 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6345 gen_helper_fcom_ST0_FT0(cpu_env);
6346 break;
6347 case 0x03: /* fcomp */
6348 case 0x23: /* fcomp3, undocumented op */
6349 case 0x32: /* fcomp5, undocumented op */
6350 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6351 gen_helper_fcom_ST0_FT0(cpu_env);
6352 gen_helper_fpop(cpu_env);
6353 break;
6354 case 0x15: /* da/5 */
6355 switch(rm) {
6356 case 1: /* fucompp */
6357 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6358 gen_helper_fucom_ST0_FT0(cpu_env);
6359 gen_helper_fpop(cpu_env);
6360 gen_helper_fpop(cpu_env);
6361 break;
6362 default:
6363 goto illegal_op;
6365 break;
6366 case 0x1c:
6367 switch(rm) {
6368 case 0: /* feni (287 only, just do nop here) */
6369 break;
6370 case 1: /* fdisi (287 only, just do nop here) */
6371 break;
6372 case 2: /* fclex */
6373 gen_helper_fclex(cpu_env);
6374 break;
6375 case 3: /* fninit */
6376 gen_helper_fninit(cpu_env);
6377 break;
6378 case 4: /* fsetpm (287 only, just do nop here) */
6379 break;
6380 default:
6381 goto illegal_op;
6383 break;
6384 case 0x1d: /* fucomi */
6385 if (!(s->cpuid_features & CPUID_CMOV)) {
6386 goto illegal_op;
6388 gen_update_cc_op(s);
6389 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6390 gen_helper_fucomi_ST0_FT0(cpu_env);
6391 set_cc_op(s, CC_OP_EFLAGS);
6392 break;
6393 case 0x1e: /* fcomi */
6394 if (!(s->cpuid_features & CPUID_CMOV)) {
6395 goto illegal_op;
6397 gen_update_cc_op(s);
6398 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6399 gen_helper_fcomi_ST0_FT0(cpu_env);
6400 set_cc_op(s, CC_OP_EFLAGS);
6401 break;
6402 case 0x28: /* ffree sti */
6403 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6404 break;
6405 case 0x2a: /* fst sti */
6406 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6407 break;
6408 case 0x2b: /* fstp sti */
6409 case 0x0b: /* fstp1 sti, undocumented op */
6410 case 0x3a: /* fstp8 sti, undocumented op */
6411 case 0x3b: /* fstp9 sti, undocumented op */
6412 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6413 gen_helper_fpop(cpu_env);
6414 break;
6415 case 0x2c: /* fucom st(i) */
6416 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6417 gen_helper_fucom_ST0_FT0(cpu_env);
6418 break;
6419 case 0x2d: /* fucomp st(i) */
6420 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6421 gen_helper_fucom_ST0_FT0(cpu_env);
6422 gen_helper_fpop(cpu_env);
6423 break;
6424 case 0x33: /* de/3 */
6425 switch(rm) {
6426 case 1: /* fcompp */
6427 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6428 gen_helper_fcom_ST0_FT0(cpu_env);
6429 gen_helper_fpop(cpu_env);
6430 gen_helper_fpop(cpu_env);
6431 break;
6432 default:
6433 goto illegal_op;
6435 break;
6436 case 0x38: /* ffreep sti, undocumented op */
6437 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6438 gen_helper_fpop(cpu_env);
6439 break;
6440 case 0x3c: /* df/4 */
6441 switch(rm) {
6442 case 0:
6443 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6444 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6445 gen_op_mov_reg_T0(MO_16, R_EAX);
6446 break;
6447 default:
6448 goto illegal_op;
6450 break;
6451 case 0x3d: /* fucomip */
6452 if (!(s->cpuid_features & CPUID_CMOV)) {
6453 goto illegal_op;
6455 gen_update_cc_op(s);
6456 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6457 gen_helper_fucomi_ST0_FT0(cpu_env);
6458 gen_helper_fpop(cpu_env);
6459 set_cc_op(s, CC_OP_EFLAGS);
6460 break;
6461 case 0x3e: /* fcomip */
6462 if (!(s->cpuid_features & CPUID_CMOV)) {
6463 goto illegal_op;
6465 gen_update_cc_op(s);
6466 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6467 gen_helper_fcomi_ST0_FT0(cpu_env);
6468 gen_helper_fpop(cpu_env);
6469 set_cc_op(s, CC_OP_EFLAGS);
6470 break;
6471 case 0x10 ... 0x13: /* fcmovxx */
6472 case 0x18 ... 0x1b:
6474 int op1, l1;
6475 static const uint8_t fcmov_cc[8] = {
6476 (JCC_B << 1),
6477 (JCC_Z << 1),
6478 (JCC_BE << 1),
6479 (JCC_P << 1),
6482 if (!(s->cpuid_features & CPUID_CMOV)) {
6483 goto illegal_op;
6485 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6486 l1 = gen_new_label();
6487 gen_jcc1_noeob(s, op1, l1);
6488 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6489 gen_set_label(l1);
6491 break;
6492 default:
6493 goto illegal_op;
6496 break;
6497 /************************/
6498 /* string ops */
6500 case 0xa4: /* movsS */
6501 case 0xa5:
6502 if ((b & 1) == 0)
6503 ot = MO_8;
6504 else
6505 ot = dflag + MO_16;
6507 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6508 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6509 } else {
6510 gen_movs(s, ot);
6512 break;
6514 case 0xaa: /* stosS */
6515 case 0xab:
6516 if ((b & 1) == 0)
6517 ot = MO_8;
6518 else
6519 ot = dflag + MO_16;
6521 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6522 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6523 } else {
6524 gen_stos(s, ot);
6526 break;
6527 case 0xac: /* lodsS */
6528 case 0xad:
6529 if ((b & 1) == 0)
6530 ot = MO_8;
6531 else
6532 ot = dflag + MO_16;
6533 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6534 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6535 } else {
6536 gen_lods(s, ot);
6538 break;
6539 case 0xae: /* scasS */
6540 case 0xaf:
6541 if ((b & 1) == 0)
6542 ot = MO_8;
6543 else
6544 ot = dflag + MO_16;
6545 if (prefixes & PREFIX_REPNZ) {
6546 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6547 } else if (prefixes & PREFIX_REPZ) {
6548 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6549 } else {
6550 gen_scas(s, ot);
6552 break;
6554 case 0xa6: /* cmpsS */
6555 case 0xa7:
6556 if ((b & 1) == 0)
6557 ot = MO_8;
6558 else
6559 ot = dflag + MO_16;
6560 if (prefixes & PREFIX_REPNZ) {
6561 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6562 } else if (prefixes & PREFIX_REPZ) {
6563 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6564 } else {
6565 gen_cmps(s, ot);
6567 break;
6568 case 0x6c: /* insS */
6569 case 0x6d:
6570 if ((b & 1) == 0)
6571 ot = MO_8;
6572 else
6573 ot = dflag ? MO_32 : MO_16;
6574 gen_op_mov_TN_reg(MO_16, 0, R_EDX);
6575 gen_op_andl_T0_ffff();
6576 gen_check_io(s, ot, pc_start - s->cs_base,
6577 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6578 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6579 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6580 } else {
6581 gen_ins(s, ot);
6582 if (use_icount) {
6583 gen_jmp(s, s->pc - s->cs_base);
6586 break;
6587 case 0x6e: /* outsS */
6588 case 0x6f:
6589 if ((b & 1) == 0)
6590 ot = MO_8;
6591 else
6592 ot = dflag ? MO_32 : MO_16;
6593 gen_op_mov_TN_reg(MO_16, 0, R_EDX);
6594 gen_op_andl_T0_ffff();
6595 gen_check_io(s, ot, pc_start - s->cs_base,
6596 svm_is_rep(prefixes) | 4);
6597 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6598 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6599 } else {
6600 gen_outs(s, ot);
6601 if (use_icount) {
6602 gen_jmp(s, s->pc - s->cs_base);
6605 break;
6607 /************************/
6608 /* port I/O */
6610 case 0xe4:
6611 case 0xe5:
6612 if ((b & 1) == 0)
6613 ot = MO_8;
6614 else
6615 ot = dflag ? MO_32 : MO_16;
6616 val = cpu_ldub_code(env, s->pc++);
6617 gen_op_movl_T0_im(val);
6618 gen_check_io(s, ot, pc_start - s->cs_base,
6619 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6620 if (use_icount)
6621 gen_io_start();
6622 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6623 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6624 gen_op_mov_reg_T1(ot, R_EAX);
6625 if (use_icount) {
6626 gen_io_end();
6627 gen_jmp(s, s->pc - s->cs_base);
6629 break;
6630 case 0xe6:
6631 case 0xe7:
6632 if ((b & 1) == 0)
6633 ot = MO_8;
6634 else
6635 ot = dflag ? MO_32 : MO_16;
6636 val = cpu_ldub_code(env, s->pc++);
6637 gen_op_movl_T0_im(val);
6638 gen_check_io(s, ot, pc_start - s->cs_base,
6639 svm_is_rep(prefixes));
6640 gen_op_mov_TN_reg(ot, 1, R_EAX);
6642 if (use_icount)
6643 gen_io_start();
6644 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6645 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6646 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6647 if (use_icount) {
6648 gen_io_end();
6649 gen_jmp(s, s->pc - s->cs_base);
6651 break;
6652 case 0xec:
6653 case 0xed:
6654 if ((b & 1) == 0)
6655 ot = MO_8;
6656 else
6657 ot = dflag ? MO_32 : MO_16;
6658 gen_op_mov_TN_reg(MO_16, 0, R_EDX);
6659 gen_op_andl_T0_ffff();
6660 gen_check_io(s, ot, pc_start - s->cs_base,
6661 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6662 if (use_icount)
6663 gen_io_start();
6664 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6665 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6666 gen_op_mov_reg_T1(ot, R_EAX);
6667 if (use_icount) {
6668 gen_io_end();
6669 gen_jmp(s, s->pc - s->cs_base);
6671 break;
6672 case 0xee:
6673 case 0xef:
6674 if ((b & 1) == 0)
6675 ot = MO_8;
6676 else
6677 ot = dflag ? MO_32 : MO_16;
6678 gen_op_mov_TN_reg(MO_16, 0, R_EDX);
6679 gen_op_andl_T0_ffff();
6680 gen_check_io(s, ot, pc_start - s->cs_base,
6681 svm_is_rep(prefixes));
6682 gen_op_mov_TN_reg(ot, 1, R_EAX);
6684 if (use_icount)
6685 gen_io_start();
6686 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6687 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6688 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6689 if (use_icount) {
6690 gen_io_end();
6691 gen_jmp(s, s->pc - s->cs_base);
6693 break;
6695 /************************/
6696 /* control */
6697 case 0xc2: /* ret im */
6698 val = cpu_ldsw_code(env, s->pc);
6699 s->pc += 2;
6700 gen_pop_T0(s);
6701 if (CODE64(s) && s->dflag)
6702 s->dflag = 2;
6703 gen_stack_update(s, val + (2 << s->dflag));
6704 if (s->dflag == 0)
6705 gen_op_andl_T0_ffff();
6706 gen_op_jmp_T0();
6707 gen_eob(s);
6708 break;
6709 case 0xc3: /* ret */
6710 gen_pop_T0(s);
6711 gen_pop_update(s);
6712 if (s->dflag == 0)
6713 gen_op_andl_T0_ffff();
6714 gen_op_jmp_T0();
6715 gen_eob(s);
6716 break;
6717 case 0xca: /* lret im */
6718 val = cpu_ldsw_code(env, s->pc);
6719 s->pc += 2;
6720 do_lret:
6721 if (s->pe && !s->vm86) {
6722 gen_update_cc_op(s);
6723 gen_jmp_im(pc_start - s->cs_base);
6724 gen_helper_lret_protected(cpu_env, tcg_const_i32(s->dflag),
6725 tcg_const_i32(val));
6726 } else {
6727 gen_stack_A0(s);
6728 /* pop offset */
6729 gen_op_ld_v(s, 1 + s->dflag, cpu_T[0], cpu_A0);
6730 if (s->dflag == 0)
6731 gen_op_andl_T0_ffff();
6732 /* NOTE: keeping EIP updated is not a problem in case of
6733 exception */
6734 gen_op_jmp_T0();
6735 /* pop selector */
6736 gen_op_addl_A0_im(2 << s->dflag);
6737 gen_op_ld_v(s, 1 + s->dflag, cpu_T[0], cpu_A0);
6738 gen_op_movl_seg_T0_vm(R_CS);
6739 /* add stack offset */
6740 gen_stack_update(s, val + (4 << s->dflag));
6742 gen_eob(s);
6743 break;
6744 case 0xcb: /* lret */
6745 val = 0;
6746 goto do_lret;
6747 case 0xcf: /* iret */
6748 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6749 if (!s->pe) {
6750 /* real mode */
6751 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
6752 set_cc_op(s, CC_OP_EFLAGS);
6753 } else if (s->vm86) {
6754 if (s->iopl != 3) {
6755 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6756 } else {
6757 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
6758 set_cc_op(s, CC_OP_EFLAGS);
6760 } else {
6761 gen_update_cc_op(s);
6762 gen_jmp_im(pc_start - s->cs_base);
6763 gen_helper_iret_protected(cpu_env, tcg_const_i32(s->dflag),
6764 tcg_const_i32(s->pc - s->cs_base));
6765 set_cc_op(s, CC_OP_EFLAGS);
6767 gen_eob(s);
6768 break;
6769 case 0xe8: /* call im */
6771 if (dflag)
6772 tval = (int32_t)insn_get(env, s, MO_32);
6773 else
6774 tval = (int16_t)insn_get(env, s, MO_16);
6775 next_eip = s->pc - s->cs_base;
6776 tval += next_eip;
6777 if (s->dflag == 0)
6778 tval &= 0xffff;
6779 else if(!CODE64(s))
6780 tval &= 0xffffffff;
6781 gen_movtl_T0_im(next_eip);
6782 gen_push_T0(s);
6783 gen_jmp(s, tval);
6785 break;
6786 case 0x9a: /* lcall im */
6788 unsigned int selector, offset;
6790 if (CODE64(s))
6791 goto illegal_op;
6792 ot = dflag ? MO_32 : MO_16;
6793 offset = insn_get(env, s, ot);
6794 selector = insn_get(env, s, MO_16);
6796 gen_op_movl_T0_im(selector);
6797 gen_op_movl_T1_imu(offset);
6799 goto do_lcall;
6800 case 0xe9: /* jmp im */
6801 if (dflag)
6802 tval = (int32_t)insn_get(env, s, MO_32);
6803 else
6804 tval = (int16_t)insn_get(env, s, MO_16);
6805 tval += s->pc - s->cs_base;
6806 if (s->dflag == 0)
6807 tval &= 0xffff;
6808 else if(!CODE64(s))
6809 tval &= 0xffffffff;
6810 gen_jmp(s, tval);
6811 break;
6812 case 0xea: /* ljmp im */
6814 unsigned int selector, offset;
6816 if (CODE64(s))
6817 goto illegal_op;
6818 ot = dflag ? MO_32 : MO_16;
6819 offset = insn_get(env, s, ot);
6820 selector = insn_get(env, s, MO_16);
6822 gen_op_movl_T0_im(selector);
6823 gen_op_movl_T1_imu(offset);
6825 goto do_ljmp;
6826 case 0xeb: /* jmp Jb */
6827 tval = (int8_t)insn_get(env, s, MO_8);
6828 tval += s->pc - s->cs_base;
6829 if (s->dflag == 0)
6830 tval &= 0xffff;
6831 gen_jmp(s, tval);
6832 break;
6833 case 0x70 ... 0x7f: /* jcc Jb */
6834 tval = (int8_t)insn_get(env, s, MO_8);
6835 goto do_jcc;
6836 case 0x180 ... 0x18f: /* jcc Jv */
6837 if (dflag) {
6838 tval = (int32_t)insn_get(env, s, MO_32);
6839 } else {
6840 tval = (int16_t)insn_get(env, s, MO_16);
6842 do_jcc:
6843 next_eip = s->pc - s->cs_base;
6844 tval += next_eip;
6845 if (s->dflag == 0)
6846 tval &= 0xffff;
6847 gen_jcc(s, b, tval, next_eip);
6848 break;
6850 case 0x190 ... 0x19f: /* setcc Gv */
6851 modrm = cpu_ldub_code(env, s->pc++);
6852 gen_setcc1(s, b, cpu_T[0]);
6853 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6854 break;
6855 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6856 if (!(s->cpuid_features & CPUID_CMOV)) {
6857 goto illegal_op;
6859 ot = dflag + MO_16;
6860 modrm = cpu_ldub_code(env, s->pc++);
6861 reg = ((modrm >> 3) & 7) | rex_r;
6862 gen_cmovcc1(env, s, ot, b, modrm, reg);
6863 break;
6865 /************************/
6866 /* flags */
6867 case 0x9c: /* pushf */
6868 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6869 if (s->vm86 && s->iopl != 3) {
6870 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6871 } else {
6872 gen_update_cc_op(s);
6873 gen_helper_read_eflags(cpu_T[0], cpu_env);
6874 gen_push_T0(s);
6876 break;
6877 case 0x9d: /* popf */
6878 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6879 if (s->vm86 && s->iopl != 3) {
6880 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6881 } else {
6882 gen_pop_T0(s);
6883 if (s->cpl == 0) {
6884 if (s->dflag) {
6885 gen_helper_write_eflags(cpu_env, cpu_T[0],
6886 tcg_const_i32((TF_MASK | AC_MASK |
6887 ID_MASK | NT_MASK |
6888 IF_MASK |
6889 IOPL_MASK)));
6890 } else {
6891 gen_helper_write_eflags(cpu_env, cpu_T[0],
6892 tcg_const_i32((TF_MASK | AC_MASK |
6893 ID_MASK | NT_MASK |
6894 IF_MASK | IOPL_MASK)
6895 & 0xffff));
6897 } else {
6898 if (s->cpl <= s->iopl) {
6899 if (s->dflag) {
6900 gen_helper_write_eflags(cpu_env, cpu_T[0],
6901 tcg_const_i32((TF_MASK |
6902 AC_MASK |
6903 ID_MASK |
6904 NT_MASK |
6905 IF_MASK)));
6906 } else {
6907 gen_helper_write_eflags(cpu_env, cpu_T[0],
6908 tcg_const_i32((TF_MASK |
6909 AC_MASK |
6910 ID_MASK |
6911 NT_MASK |
6912 IF_MASK)
6913 & 0xffff));
6915 } else {
6916 if (s->dflag) {
6917 gen_helper_write_eflags(cpu_env, cpu_T[0],
6918 tcg_const_i32((TF_MASK | AC_MASK |
6919 ID_MASK | NT_MASK)));
6920 } else {
6921 gen_helper_write_eflags(cpu_env, cpu_T[0],
6922 tcg_const_i32((TF_MASK | AC_MASK |
6923 ID_MASK | NT_MASK)
6924 & 0xffff));
6928 gen_pop_update(s);
6929 set_cc_op(s, CC_OP_EFLAGS);
6930 /* abort translation because TF/AC flag may change */
6931 gen_jmp_im(s->pc - s->cs_base);
6932 gen_eob(s);
6934 break;
6935 case 0x9e: /* sahf */
6936 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6937 goto illegal_op;
6938 gen_op_mov_TN_reg(MO_8, 0, R_AH);
6939 gen_compute_eflags(s);
6940 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6941 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6942 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
6943 break;
6944 case 0x9f: /* lahf */
6945 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6946 goto illegal_op;
6947 gen_compute_eflags(s);
6948 /* Note: gen_compute_eflags() only gives the condition codes */
6949 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
6950 gen_op_mov_reg_T0(MO_8, R_AH);
6951 break;
6952 case 0xf5: /* cmc */
6953 gen_compute_eflags(s);
6954 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6955 break;
6956 case 0xf8: /* clc */
6957 gen_compute_eflags(s);
6958 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6959 break;
6960 case 0xf9: /* stc */
6961 gen_compute_eflags(s);
6962 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6963 break;
6964 case 0xfc: /* cld */
6965 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6966 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6967 break;
6968 case 0xfd: /* std */
6969 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6970 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6971 break;
6973 /************************/
6974 /* bit operations */
6975 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6976 ot = dflag + MO_16;
6977 modrm = cpu_ldub_code(env, s->pc++);
6978 op = (modrm >> 3) & 7;
6979 mod = (modrm >> 6) & 3;
6980 rm = (modrm & 7) | REX_B(s);
6981 if (mod != 3) {
6982 s->rip_offset = 1;
6983 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
6984 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
6985 } else {
6986 gen_op_mov_TN_reg(ot, 0, rm);
6988 /* load shift */
6989 val = cpu_ldub_code(env, s->pc++);
6990 gen_op_movl_T1_im(val);
6991 if (op < 4)
6992 goto illegal_op;
6993 op -= 4;
6994 goto bt_op;
6995 case 0x1a3: /* bt Gv, Ev */
6996 op = 0;
6997 goto do_btx;
6998 case 0x1ab: /* bts */
6999 op = 1;
7000 goto do_btx;
7001 case 0x1b3: /* btr */
7002 op = 2;
7003 goto do_btx;
7004 case 0x1bb: /* btc */
7005 op = 3;
7006 do_btx:
7007 ot = dflag + MO_16;
7008 modrm = cpu_ldub_code(env, s->pc++);
7009 reg = ((modrm >> 3) & 7) | rex_r;
7010 mod = (modrm >> 6) & 3;
7011 rm = (modrm & 7) | REX_B(s);
7012 gen_op_mov_TN_reg(MO_32, 1, reg);
7013 if (mod != 3) {
7014 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7015 /* specific case: we need to add a displacement */
7016 gen_exts(ot, cpu_T[1]);
7017 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
7018 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
7019 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
7020 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
7021 } else {
7022 gen_op_mov_TN_reg(ot, 0, rm);
7024 bt_op:
7025 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
7026 switch(op) {
7027 case 0:
7028 tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
7029 tcg_gen_movi_tl(cpu_cc_dst, 0);
7030 break;
7031 case 1:
7032 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7033 tcg_gen_movi_tl(cpu_tmp0, 1);
7034 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7035 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7036 break;
7037 case 2:
7038 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7039 tcg_gen_movi_tl(cpu_tmp0, 1);
7040 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7041 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
7042 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7043 break;
7044 default:
7045 case 3:
7046 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7047 tcg_gen_movi_tl(cpu_tmp0, 1);
7048 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7049 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7050 break;
7052 set_cc_op(s, CC_OP_SARB + ot);
7053 if (op != 0) {
7054 if (mod != 3)
7055 gen_op_st_T0_A0(s, ot);
7056 else
7057 gen_op_mov_reg_T0(ot, rm);
7058 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
7059 tcg_gen_movi_tl(cpu_cc_dst, 0);
7061 break;
7062 case 0x1bc: /* bsf / tzcnt */
7063 case 0x1bd: /* bsr / lzcnt */
7064 ot = dflag + MO_16;
7065 modrm = cpu_ldub_code(env, s->pc++);
7066 reg = ((modrm >> 3) & 7) | rex_r;
7067 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7068 gen_extu(ot, cpu_T[0]);
7070 /* Note that lzcnt and tzcnt are in different extensions. */
7071 if ((prefixes & PREFIX_REPZ)
7072 && (b & 1
7073 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
7074 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
7075 int size = 8 << ot;
7076 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
7077 if (b & 1) {
7078 /* For lzcnt, reduce the target_ulong result by the
7079 number of zeros that we expect to find at the top. */
7080 gen_helper_clz(cpu_T[0], cpu_T[0]);
7081 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - size);
7082 } else {
7083 /* For tzcnt, a zero input must return the operand size:
7084 force all bits outside the operand size to 1. */
7085 target_ulong mask = (target_ulong)-2 << (size - 1);
7086 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], mask);
7087 gen_helper_ctz(cpu_T[0], cpu_T[0]);
7089 /* For lzcnt/tzcnt, C and Z bits are defined and are
7090 related to the result. */
7091 gen_op_update1_cc();
7092 set_cc_op(s, CC_OP_BMILGB + ot);
7093 } else {
7094 /* For bsr/bsf, only the Z bit is defined and it is related
7095 to the input and not the result. */
7096 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
7097 set_cc_op(s, CC_OP_LOGICB + ot);
7098 if (b & 1) {
7099 /* For bsr, return the bit index of the first 1 bit,
7100 not the count of leading zeros. */
7101 gen_helper_clz(cpu_T[0], cpu_T[0]);
7102 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - 1);
7103 } else {
7104 gen_helper_ctz(cpu_T[0], cpu_T[0]);
7106 /* ??? The manual says that the output is undefined when the
7107 input is zero, but real hardware leaves it unchanged, and
7108 real programs appear to depend on that. */
7109 tcg_gen_movi_tl(cpu_tmp0, 0);
7110 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[0], cpu_cc_dst, cpu_tmp0,
7111 cpu_regs[reg], cpu_T[0]);
7113 gen_op_mov_reg_T0(ot, reg);
7114 break;
7115 /************************/
7116 /* bcd */
7117 case 0x27: /* daa */
7118 if (CODE64(s))
7119 goto illegal_op;
7120 gen_update_cc_op(s);
7121 gen_helper_daa(cpu_env);
7122 set_cc_op(s, CC_OP_EFLAGS);
7123 break;
7124 case 0x2f: /* das */
7125 if (CODE64(s))
7126 goto illegal_op;
7127 gen_update_cc_op(s);
7128 gen_helper_das(cpu_env);
7129 set_cc_op(s, CC_OP_EFLAGS);
7130 break;
7131 case 0x37: /* aaa */
7132 if (CODE64(s))
7133 goto illegal_op;
7134 gen_update_cc_op(s);
7135 gen_helper_aaa(cpu_env);
7136 set_cc_op(s, CC_OP_EFLAGS);
7137 break;
7138 case 0x3f: /* aas */
7139 if (CODE64(s))
7140 goto illegal_op;
7141 gen_update_cc_op(s);
7142 gen_helper_aas(cpu_env);
7143 set_cc_op(s, CC_OP_EFLAGS);
7144 break;
7145 case 0xd4: /* aam */
7146 if (CODE64(s))
7147 goto illegal_op;
7148 val = cpu_ldub_code(env, s->pc++);
7149 if (val == 0) {
7150 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7151 } else {
7152 gen_helper_aam(cpu_env, tcg_const_i32(val));
7153 set_cc_op(s, CC_OP_LOGICB);
7155 break;
7156 case 0xd5: /* aad */
7157 if (CODE64(s))
7158 goto illegal_op;
7159 val = cpu_ldub_code(env, s->pc++);
7160 gen_helper_aad(cpu_env, tcg_const_i32(val));
7161 set_cc_op(s, CC_OP_LOGICB);
7162 break;
7163 /************************/
7164 /* misc */
7165 case 0x90: /* nop */
7166 /* XXX: correct lock test for all insn */
7167 if (prefixes & PREFIX_LOCK) {
7168 goto illegal_op;
7170 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
7171 if (REX_B(s)) {
7172 goto do_xchg_reg_eax;
7174 if (prefixes & PREFIX_REPZ) {
7175 gen_update_cc_op(s);
7176 gen_jmp_im(pc_start - s->cs_base);
7177 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
7178 s->is_jmp = DISAS_TB_JUMP;
7180 break;
7181 case 0x9b: /* fwait */
7182 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7183 (HF_MP_MASK | HF_TS_MASK)) {
7184 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7185 } else {
7186 gen_update_cc_op(s);
7187 gen_jmp_im(pc_start - s->cs_base);
7188 gen_helper_fwait(cpu_env);
7190 break;
7191 case 0xcc: /* int3 */
7192 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7193 break;
7194 case 0xcd: /* int N */
7195 val = cpu_ldub_code(env, s->pc++);
7196 if (s->vm86 && s->iopl != 3) {
7197 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7198 } else {
7199 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7201 break;
7202 case 0xce: /* into */
7203 if (CODE64(s))
7204 goto illegal_op;
7205 gen_update_cc_op(s);
7206 gen_jmp_im(pc_start - s->cs_base);
7207 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
7208 break;
7209 #ifdef WANT_ICEBP
7210 case 0xf1: /* icebp (undocumented, exits to external debugger) */
7211 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
7212 #if 1
7213 gen_debug(s, pc_start - s->cs_base);
7214 #else
7215 /* start debug */
7216 tb_flush(env);
7217 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
7218 #endif
7219 break;
7220 #endif
7221 case 0xfa: /* cli */
7222 if (!s->vm86) {
7223 if (s->cpl <= s->iopl) {
7224 gen_helper_cli(cpu_env);
7225 } else {
7226 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7228 } else {
7229 if (s->iopl == 3) {
7230 gen_helper_cli(cpu_env);
7231 } else {
7232 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7235 break;
7236 case 0xfb: /* sti */
7237 if (!s->vm86) {
7238 if (s->cpl <= s->iopl) {
7239 gen_sti:
7240 gen_helper_sti(cpu_env);
7241 /* interruptions are enabled only the first insn after sti */
7242 /* If several instructions disable interrupts, only the
7243 _first_ does it */
7244 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
7245 gen_helper_set_inhibit_irq(cpu_env);
7246 /* give a chance to handle pending irqs */
7247 gen_jmp_im(s->pc - s->cs_base);
7248 gen_eob(s);
7249 } else {
7250 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7252 } else {
7253 if (s->iopl == 3) {
7254 goto gen_sti;
7255 } else {
7256 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7259 break;
7260 case 0x62: /* bound */
7261 if (CODE64(s))
7262 goto illegal_op;
7263 ot = dflag ? MO_32 : MO_16;
7264 modrm = cpu_ldub_code(env, s->pc++);
7265 reg = (modrm >> 3) & 7;
7266 mod = (modrm >> 6) & 3;
7267 if (mod == 3)
7268 goto illegal_op;
7269 gen_op_mov_TN_reg(ot, 0, reg);
7270 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7271 gen_jmp_im(pc_start - s->cs_base);
7272 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7273 if (ot == MO_16) {
7274 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
7275 } else {
7276 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
7278 break;
7279 case 0x1c8 ... 0x1cf: /* bswap reg */
7280 reg = (b & 7) | REX_B(s);
7281 #ifdef TARGET_X86_64
7282 if (dflag == 2) {
7283 gen_op_mov_TN_reg(MO_64, 0, reg);
7284 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
7285 gen_op_mov_reg_T0(MO_64, reg);
7286 } else
7287 #endif
7289 gen_op_mov_TN_reg(MO_32, 0, reg);
7290 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
7291 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
7292 gen_op_mov_reg_T0(MO_32, reg);
7294 break;
7295 case 0xd6: /* salc */
7296 if (CODE64(s))
7297 goto illegal_op;
7298 gen_compute_eflags_c(s, cpu_T[0]);
7299 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
7300 gen_op_mov_reg_T0(MO_8, R_EAX);
7301 break;
7302 case 0xe0: /* loopnz */
7303 case 0xe1: /* loopz */
7304 case 0xe2: /* loop */
7305 case 0xe3: /* jecxz */
7307 int l1, l2, l3;
7309 tval = (int8_t)insn_get(env, s, MO_8);
7310 next_eip = s->pc - s->cs_base;
7311 tval += next_eip;
7312 if (s->dflag == 0)
7313 tval &= 0xffff;
7315 l1 = gen_new_label();
7316 l2 = gen_new_label();
7317 l3 = gen_new_label();
7318 b &= 3;
7319 switch(b) {
7320 case 0: /* loopnz */
7321 case 1: /* loopz */
7322 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7323 gen_op_jz_ecx(s->aflag, l3);
7324 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7325 break;
7326 case 2: /* loop */
7327 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7328 gen_op_jnz_ecx(s->aflag, l1);
7329 break;
7330 default:
7331 case 3: /* jcxz */
7332 gen_op_jz_ecx(s->aflag, l1);
7333 break;
7336 gen_set_label(l3);
7337 gen_jmp_im(next_eip);
7338 tcg_gen_br(l2);
7340 gen_set_label(l1);
7341 gen_jmp_im(tval);
7342 gen_set_label(l2);
7343 gen_eob(s);
7345 break;
7346 case 0x130: /* wrmsr */
7347 case 0x132: /* rdmsr */
7348 if (s->cpl != 0) {
7349 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7350 } else {
7351 gen_update_cc_op(s);
7352 gen_jmp_im(pc_start - s->cs_base);
7353 if (b & 2) {
7354 gen_helper_rdmsr(cpu_env);
7355 } else {
7356 gen_helper_wrmsr(cpu_env);
7359 break;
7360 case 0x131: /* rdtsc */
7361 gen_update_cc_op(s);
7362 gen_jmp_im(pc_start - s->cs_base);
7363 if (use_icount)
7364 gen_io_start();
7365 gen_helper_rdtsc(cpu_env);
7366 if (use_icount) {
7367 gen_io_end();
7368 gen_jmp(s, s->pc - s->cs_base);
7370 break;
7371 case 0x133: /* rdpmc */
7372 gen_update_cc_op(s);
7373 gen_jmp_im(pc_start - s->cs_base);
7374 gen_helper_rdpmc(cpu_env);
7375 break;
7376 case 0x134: /* sysenter */
7377 /* For Intel SYSENTER is valid on 64-bit */
7378 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7379 goto illegal_op;
7380 if (!s->pe) {
7381 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7382 } else {
7383 gen_update_cc_op(s);
7384 gen_jmp_im(pc_start - s->cs_base);
7385 gen_helper_sysenter(cpu_env);
7386 gen_eob(s);
7388 break;
7389 case 0x135: /* sysexit */
7390 /* For Intel SYSEXIT is valid on 64-bit */
7391 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7392 goto illegal_op;
7393 if (!s->pe) {
7394 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7395 } else {
7396 gen_update_cc_op(s);
7397 gen_jmp_im(pc_start - s->cs_base);
7398 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag));
7399 gen_eob(s);
7401 break;
7402 #ifdef TARGET_X86_64
7403 case 0x105: /* syscall */
7404 /* XXX: is it usable in real mode ? */
7405 gen_update_cc_op(s);
7406 gen_jmp_im(pc_start - s->cs_base);
7407 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7408 gen_eob(s);
7409 break;
7410 case 0x107: /* sysret */
7411 if (!s->pe) {
7412 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7413 } else {
7414 gen_update_cc_op(s);
7415 gen_jmp_im(pc_start - s->cs_base);
7416 gen_helper_sysret(cpu_env, tcg_const_i32(s->dflag));
7417 /* condition codes are modified only in long mode */
7418 if (s->lma) {
7419 set_cc_op(s, CC_OP_EFLAGS);
7421 gen_eob(s);
7423 break;
7424 #endif
7425 case 0x1a2: /* cpuid */
7426 gen_update_cc_op(s);
7427 gen_jmp_im(pc_start - s->cs_base);
7428 gen_helper_cpuid(cpu_env);
7429 break;
7430 case 0xf4: /* hlt */
7431 if (s->cpl != 0) {
7432 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7433 } else {
7434 gen_update_cc_op(s);
7435 gen_jmp_im(pc_start - s->cs_base);
7436 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7437 s->is_jmp = DISAS_TB_JUMP;
7439 break;
7440 case 0x100:
7441 modrm = cpu_ldub_code(env, s->pc++);
7442 mod = (modrm >> 6) & 3;
7443 op = (modrm >> 3) & 7;
7444 switch(op) {
7445 case 0: /* sldt */
7446 if (!s->pe || s->vm86)
7447 goto illegal_op;
7448 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7449 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
7450 ot = MO_16;
7451 if (mod == 3)
7452 ot += s->dflag;
7453 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7454 break;
7455 case 2: /* lldt */
7456 if (!s->pe || s->vm86)
7457 goto illegal_op;
7458 if (s->cpl != 0) {
7459 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7460 } else {
7461 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7462 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7463 gen_jmp_im(pc_start - s->cs_base);
7464 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7465 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7467 break;
7468 case 1: /* str */
7469 if (!s->pe || s->vm86)
7470 goto illegal_op;
7471 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7472 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
7473 ot = MO_16;
7474 if (mod == 3)
7475 ot += s->dflag;
7476 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7477 break;
7478 case 3: /* ltr */
7479 if (!s->pe || s->vm86)
7480 goto illegal_op;
7481 if (s->cpl != 0) {
7482 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7483 } else {
7484 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7485 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7486 gen_jmp_im(pc_start - s->cs_base);
7487 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7488 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7490 break;
7491 case 4: /* verr */
7492 case 5: /* verw */
7493 if (!s->pe || s->vm86)
7494 goto illegal_op;
7495 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7496 gen_update_cc_op(s);
7497 if (op == 4) {
7498 gen_helper_verr(cpu_env, cpu_T[0]);
7499 } else {
7500 gen_helper_verw(cpu_env, cpu_T[0]);
7502 set_cc_op(s, CC_OP_EFLAGS);
7503 break;
7504 default:
7505 goto illegal_op;
7507 break;
7508 case 0x101:
7509 modrm = cpu_ldub_code(env, s->pc++);
7510 mod = (modrm >> 6) & 3;
7511 op = (modrm >> 3) & 7;
7512 rm = modrm & 7;
7513 switch(op) {
7514 case 0: /* sgdt */
7515 if (mod == 3)
7516 goto illegal_op;
7517 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7518 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7519 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
7520 gen_op_st_T0_A0(s, MO_16);
7521 gen_add_A0_im(s, 2);
7522 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
7523 if (!s->dflag)
7524 gen_op_andl_T0_im(0xffffff);
7525 gen_op_st_T0_A0(s, CODE64(s) + MO_32);
7526 break;
7527 case 1:
7528 if (mod == 3) {
7529 switch (rm) {
7530 case 0: /* monitor */
7531 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7532 s->cpl != 0)
7533 goto illegal_op;
7534 gen_update_cc_op(s);
7535 gen_jmp_im(pc_start - s->cs_base);
7536 #ifdef TARGET_X86_64
7537 if (s->aflag == 2) {
7538 gen_op_movq_A0_reg(R_EAX);
7539 } else
7540 #endif
7542 gen_op_movl_A0_reg(R_EAX);
7543 if (s->aflag == 0)
7544 gen_op_andl_A0_ffff();
7546 gen_add_A0_ds_seg(s);
7547 gen_helper_monitor(cpu_env, cpu_A0);
7548 break;
7549 case 1: /* mwait */
7550 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7551 s->cpl != 0)
7552 goto illegal_op;
7553 gen_update_cc_op(s);
7554 gen_jmp_im(pc_start - s->cs_base);
7555 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7556 gen_eob(s);
7557 break;
7558 case 2: /* clac */
7559 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7560 s->cpl != 0) {
7561 goto illegal_op;
7563 gen_helper_clac(cpu_env);
7564 gen_jmp_im(s->pc - s->cs_base);
7565 gen_eob(s);
7566 break;
7567 case 3: /* stac */
7568 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7569 s->cpl != 0) {
7570 goto illegal_op;
7572 gen_helper_stac(cpu_env);
7573 gen_jmp_im(s->pc - s->cs_base);
7574 gen_eob(s);
7575 break;
7576 default:
7577 goto illegal_op;
7579 } else { /* sidt */
7580 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7581 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7582 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
7583 gen_op_st_T0_A0(s, MO_16);
7584 gen_add_A0_im(s, 2);
7585 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
7586 if (!s->dflag)
7587 gen_op_andl_T0_im(0xffffff);
7588 gen_op_st_T0_A0(s, CODE64(s) + MO_32);
7590 break;
7591 case 2: /* lgdt */
7592 case 3: /* lidt */
7593 if (mod == 3) {
7594 gen_update_cc_op(s);
7595 gen_jmp_im(pc_start - s->cs_base);
7596 switch(rm) {
7597 case 0: /* VMRUN */
7598 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7599 goto illegal_op;
7600 if (s->cpl != 0) {
7601 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7602 break;
7603 } else {
7604 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag),
7605 tcg_const_i32(s->pc - pc_start));
7606 tcg_gen_exit_tb(0);
7607 s->is_jmp = DISAS_TB_JUMP;
7609 break;
7610 case 1: /* VMMCALL */
7611 if (!(s->flags & HF_SVME_MASK))
7612 goto illegal_op;
7613 gen_helper_vmmcall(cpu_env);
7614 break;
7615 case 2: /* VMLOAD */
7616 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7617 goto illegal_op;
7618 if (s->cpl != 0) {
7619 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7620 break;
7621 } else {
7622 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag));
7624 break;
7625 case 3: /* VMSAVE */
7626 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7627 goto illegal_op;
7628 if (s->cpl != 0) {
7629 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7630 break;
7631 } else {
7632 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag));
7634 break;
7635 case 4: /* STGI */
7636 if ((!(s->flags & HF_SVME_MASK) &&
7637 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7638 !s->pe)
7639 goto illegal_op;
7640 if (s->cpl != 0) {
7641 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7642 break;
7643 } else {
7644 gen_helper_stgi(cpu_env);
7646 break;
7647 case 5: /* CLGI */
7648 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7649 goto illegal_op;
7650 if (s->cpl != 0) {
7651 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7652 break;
7653 } else {
7654 gen_helper_clgi(cpu_env);
7656 break;
7657 case 6: /* SKINIT */
7658 if ((!(s->flags & HF_SVME_MASK) &&
7659 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7660 !s->pe)
7661 goto illegal_op;
7662 gen_helper_skinit(cpu_env);
7663 break;
7664 case 7: /* INVLPGA */
7665 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7666 goto illegal_op;
7667 if (s->cpl != 0) {
7668 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7669 break;
7670 } else {
7671 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag));
7673 break;
7674 default:
7675 goto illegal_op;
7677 } else if (s->cpl != 0) {
7678 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7679 } else {
7680 gen_svm_check_intercept(s, pc_start,
7681 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
7682 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7683 gen_op_ld_T1_A0(s, MO_16);
7684 gen_add_A0_im(s, 2);
7685 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
7686 if (!s->dflag)
7687 gen_op_andl_T0_im(0xffffff);
7688 if (op == 2) {
7689 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7690 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
7691 } else {
7692 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7693 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
7696 break;
7697 case 4: /* smsw */
7698 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7699 #if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
7700 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7701 #else
7702 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
7703 #endif
7704 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 1);
7705 break;
7706 case 6: /* lmsw */
7707 if (s->cpl != 0) {
7708 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7709 } else {
7710 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7711 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7712 gen_helper_lmsw(cpu_env, cpu_T[0]);
7713 gen_jmp_im(s->pc - s->cs_base);
7714 gen_eob(s);
7716 break;
7717 case 7:
7718 if (mod != 3) { /* invlpg */
7719 if (s->cpl != 0) {
7720 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7721 } else {
7722 gen_update_cc_op(s);
7723 gen_jmp_im(pc_start - s->cs_base);
7724 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7725 gen_helper_invlpg(cpu_env, cpu_A0);
7726 gen_jmp_im(s->pc - s->cs_base);
7727 gen_eob(s);
7729 } else {
7730 switch (rm) {
7731 case 0: /* swapgs */
7732 #ifdef TARGET_X86_64
7733 if (CODE64(s)) {
7734 if (s->cpl != 0) {
7735 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7736 } else {
7737 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7738 offsetof(CPUX86State,segs[R_GS].base));
7739 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7740 offsetof(CPUX86State,kernelgsbase));
7741 tcg_gen_st_tl(cpu_T[1], cpu_env,
7742 offsetof(CPUX86State,segs[R_GS].base));
7743 tcg_gen_st_tl(cpu_T[0], cpu_env,
7744 offsetof(CPUX86State,kernelgsbase));
7746 } else
7747 #endif
7749 goto illegal_op;
7751 break;
7752 case 1: /* rdtscp */
7753 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7754 goto illegal_op;
7755 gen_update_cc_op(s);
7756 gen_jmp_im(pc_start - s->cs_base);
7757 if (use_icount)
7758 gen_io_start();
7759 gen_helper_rdtscp(cpu_env);
7760 if (use_icount) {
7761 gen_io_end();
7762 gen_jmp(s, s->pc - s->cs_base);
7764 break;
7765 default:
7766 goto illegal_op;
7769 break;
7770 default:
7771 goto illegal_op;
7773 break;
7774 case 0x108: /* invd */
7775 case 0x109: /* wbinvd */
7776 if (s->cpl != 0) {
7777 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7778 } else {
7779 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7780 /* nothing to do */
7782 break;
7783 case 0x63: /* arpl or movslS (x86_64) */
7784 #ifdef TARGET_X86_64
7785 if (CODE64(s)) {
7786 int d_ot;
7787 /* d_ot is the size of destination */
7788 d_ot = dflag + MO_16;
7790 modrm = cpu_ldub_code(env, s->pc++);
7791 reg = ((modrm >> 3) & 7) | rex_r;
7792 mod = (modrm >> 6) & 3;
7793 rm = (modrm & 7) | REX_B(s);
7795 if (mod == 3) {
7796 gen_op_mov_TN_reg(MO_32, 0, rm);
7797 /* sign extend */
7798 if (d_ot == MO_64) {
7799 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
7801 gen_op_mov_reg_T0(d_ot, reg);
7802 } else {
7803 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7804 if (d_ot == MO_64) {
7805 gen_op_lds_T0_A0(s, MO_32);
7806 } else {
7807 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
7809 gen_op_mov_reg_T0(d_ot, reg);
7811 } else
7812 #endif
7814 int label1;
7815 TCGv t0, t1, t2, a0;
7817 if (!s->pe || s->vm86)
7818 goto illegal_op;
7819 t0 = tcg_temp_local_new();
7820 t1 = tcg_temp_local_new();
7821 t2 = tcg_temp_local_new();
7822 ot = MO_16;
7823 modrm = cpu_ldub_code(env, s->pc++);
7824 reg = (modrm >> 3) & 7;
7825 mod = (modrm >> 6) & 3;
7826 rm = modrm & 7;
7827 if (mod != 3) {
7828 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7829 gen_op_ld_v(s, ot, t0, cpu_A0);
7830 a0 = tcg_temp_local_new();
7831 tcg_gen_mov_tl(a0, cpu_A0);
7832 } else {
7833 gen_op_mov_v_reg(ot, t0, rm);
7834 TCGV_UNUSED(a0);
7836 gen_op_mov_v_reg(ot, t1, reg);
7837 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7838 tcg_gen_andi_tl(t1, t1, 3);
7839 tcg_gen_movi_tl(t2, 0);
7840 label1 = gen_new_label();
7841 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7842 tcg_gen_andi_tl(t0, t0, ~3);
7843 tcg_gen_or_tl(t0, t0, t1);
7844 tcg_gen_movi_tl(t2, CC_Z);
7845 gen_set_label(label1);
7846 if (mod != 3) {
7847 gen_op_st_v(s, ot, t0, a0);
7848 tcg_temp_free(a0);
7849 } else {
7850 gen_op_mov_reg_v(ot, rm, t0);
7852 gen_compute_eflags(s);
7853 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7854 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7855 tcg_temp_free(t0);
7856 tcg_temp_free(t1);
7857 tcg_temp_free(t2);
7859 break;
7860 case 0x102: /* lar */
7861 case 0x103: /* lsl */
7863 int label1;
7864 TCGv t0;
7865 if (!s->pe || s->vm86)
7866 goto illegal_op;
7867 ot = dflag ? MO_32 : MO_16;
7868 modrm = cpu_ldub_code(env, s->pc++);
7869 reg = ((modrm >> 3) & 7) | rex_r;
7870 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7871 t0 = tcg_temp_local_new();
7872 gen_update_cc_op(s);
7873 if (b == 0x102) {
7874 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7875 } else {
7876 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7878 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7879 label1 = gen_new_label();
7880 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7881 gen_op_mov_reg_v(ot, reg, t0);
7882 gen_set_label(label1);
7883 set_cc_op(s, CC_OP_EFLAGS);
7884 tcg_temp_free(t0);
7886 break;
7887 case 0x118:
7888 modrm = cpu_ldub_code(env, s->pc++);
7889 mod = (modrm >> 6) & 3;
7890 op = (modrm >> 3) & 7;
7891 switch(op) {
7892 case 0: /* prefetchnta */
7893 case 1: /* prefetchnt0 */
7894 case 2: /* prefetchnt0 */
7895 case 3: /* prefetchnt0 */
7896 if (mod == 3)
7897 goto illegal_op;
7898 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7899 /* nothing more to do */
7900 break;
7901 default: /* nop (multi byte) */
7902 gen_nop_modrm(env, s, modrm);
7903 break;
7905 break;
7906 case 0x119 ... 0x11f: /* nop (multi byte) */
7907 modrm = cpu_ldub_code(env, s->pc++);
7908 gen_nop_modrm(env, s, modrm);
7909 break;
7910 case 0x120: /* mov reg, crN */
7911 case 0x122: /* mov crN, reg */
7912 if (s->cpl != 0) {
7913 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7914 } else {
7915 modrm = cpu_ldub_code(env, s->pc++);
7916 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7917 * AMD documentation (24594.pdf) and testing of
7918 * intel 386 and 486 processors all show that the mod bits
7919 * are assumed to be 1's, regardless of actual values.
7921 rm = (modrm & 7) | REX_B(s);
7922 reg = ((modrm >> 3) & 7) | rex_r;
7923 if (CODE64(s))
7924 ot = MO_64;
7925 else
7926 ot = MO_32;
7927 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7928 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7929 reg = 8;
7931 switch(reg) {
7932 case 0:
7933 case 2:
7934 case 3:
7935 case 4:
7936 case 8:
7937 gen_update_cc_op(s);
7938 gen_jmp_im(pc_start - s->cs_base);
7939 if (b & 2) {
7940 gen_op_mov_TN_reg(ot, 0, rm);
7941 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7942 cpu_T[0]);
7943 gen_jmp_im(s->pc - s->cs_base);
7944 gen_eob(s);
7945 } else {
7946 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
7947 gen_op_mov_reg_T0(ot, rm);
7949 break;
7950 default:
7951 goto illegal_op;
7954 break;
7955 case 0x121: /* mov reg, drN */
7956 case 0x123: /* mov drN, reg */
7957 if (s->cpl != 0) {
7958 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7959 } else {
7960 modrm = cpu_ldub_code(env, s->pc++);
7961 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7962 * AMD documentation (24594.pdf) and testing of
7963 * intel 386 and 486 processors all show that the mod bits
7964 * are assumed to be 1's, regardless of actual values.
7966 rm = (modrm & 7) | REX_B(s);
7967 reg = ((modrm >> 3) & 7) | rex_r;
7968 if (CODE64(s))
7969 ot = MO_64;
7970 else
7971 ot = MO_32;
7972 /* XXX: do it dynamically with CR4.DE bit */
7973 if (reg == 4 || reg == 5 || reg >= 8)
7974 goto illegal_op;
7975 if (b & 2) {
7976 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7977 gen_op_mov_TN_reg(ot, 0, rm);
7978 gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]);
7979 gen_jmp_im(s->pc - s->cs_base);
7980 gen_eob(s);
7981 } else {
7982 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7983 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
7984 gen_op_mov_reg_T0(ot, rm);
7987 break;
7988 case 0x106: /* clts */
7989 if (s->cpl != 0) {
7990 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7991 } else {
7992 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7993 gen_helper_clts(cpu_env);
7994 /* abort block because static cpu state changed */
7995 gen_jmp_im(s->pc - s->cs_base);
7996 gen_eob(s);
7998 break;
7999 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
8000 case 0x1c3: /* MOVNTI reg, mem */
8001 if (!(s->cpuid_features & CPUID_SSE2))
8002 goto illegal_op;
8003 ot = s->dflag == 2 ? MO_64 : MO_32;
8004 modrm = cpu_ldub_code(env, s->pc++);
8005 mod = (modrm >> 6) & 3;
8006 if (mod == 3)
8007 goto illegal_op;
8008 reg = ((modrm >> 3) & 7) | rex_r;
8009 /* generate a generic store */
8010 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8011 break;
8012 case 0x1ae:
8013 modrm = cpu_ldub_code(env, s->pc++);
8014 mod = (modrm >> 6) & 3;
8015 op = (modrm >> 3) & 7;
8016 switch(op) {
8017 case 0: /* fxsave */
8018 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
8019 (s->prefix & PREFIX_LOCK))
8020 goto illegal_op;
8021 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8022 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8023 break;
8025 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8026 gen_update_cc_op(s);
8027 gen_jmp_im(pc_start - s->cs_base);
8028 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32((s->dflag == 2)));
8029 break;
8030 case 1: /* fxrstor */
8031 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
8032 (s->prefix & PREFIX_LOCK))
8033 goto illegal_op;
8034 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8035 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8036 break;
8038 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8039 gen_update_cc_op(s);
8040 gen_jmp_im(pc_start - s->cs_base);
8041 gen_helper_fxrstor(cpu_env, cpu_A0,
8042 tcg_const_i32((s->dflag == 2)));
8043 break;
8044 case 2: /* ldmxcsr */
8045 case 3: /* stmxcsr */
8046 if (s->flags & HF_TS_MASK) {
8047 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8048 break;
8050 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
8051 mod == 3)
8052 goto illegal_op;
8053 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8054 if (op == 2) {
8055 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
8056 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
8057 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
8058 } else {
8059 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
8060 gen_op_st_T0_A0(s, MO_32);
8062 break;
8063 case 5: /* lfence */
8064 case 6: /* mfence */
8065 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
8066 goto illegal_op;
8067 break;
8068 case 7: /* sfence / clflush */
8069 if ((modrm & 0xc7) == 0xc0) {
8070 /* sfence */
8071 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
8072 if (!(s->cpuid_features & CPUID_SSE))
8073 goto illegal_op;
8074 } else {
8075 /* clflush */
8076 if (!(s->cpuid_features & CPUID_CLFLUSH))
8077 goto illegal_op;
8078 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8080 break;
8081 default:
8082 goto illegal_op;
8084 break;
8085 case 0x10d: /* 3DNow! prefetch(w) */
8086 modrm = cpu_ldub_code(env, s->pc++);
8087 mod = (modrm >> 6) & 3;
8088 if (mod == 3)
8089 goto illegal_op;
8090 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8091 /* ignore for now */
8092 break;
8093 case 0x1aa: /* rsm */
8094 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8095 if (!(s->flags & HF_SMM_MASK))
8096 goto illegal_op;
8097 gen_update_cc_op(s);
8098 gen_jmp_im(s->pc - s->cs_base);
8099 gen_helper_rsm(cpu_env);
8100 gen_eob(s);
8101 break;
8102 case 0x1b8: /* SSE4.2 popcnt */
8103 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8104 PREFIX_REPZ)
8105 goto illegal_op;
8106 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8107 goto illegal_op;
8109 modrm = cpu_ldub_code(env, s->pc++);
8110 reg = ((modrm >> 3) & 7) | rex_r;
8112 if (s->prefix & PREFIX_DATA)
8113 ot = MO_16;
8114 else if (s->dflag != 2)
8115 ot = MO_32;
8116 else
8117 ot = MO_64;
8119 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8120 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
8121 gen_op_mov_reg_T0(ot, reg);
8123 set_cc_op(s, CC_OP_EFLAGS);
8124 break;
8125 case 0x10e ... 0x10f:
8126 /* 3DNow! instructions, ignore prefixes */
8127 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8128 case 0x110 ... 0x117:
8129 case 0x128 ... 0x12f:
8130 case 0x138 ... 0x13a:
8131 case 0x150 ... 0x179:
8132 case 0x17c ... 0x17f:
8133 case 0x1c2:
8134 case 0x1c4 ... 0x1c6:
8135 case 0x1d0 ... 0x1fe:
8136 gen_sse(env, s, b, pc_start, rex_r);
8137 break;
8138 default:
8139 goto illegal_op;
8141 /* lock generation */
8142 if (s->prefix & PREFIX_LOCK)
8143 gen_helper_unlock();
8144 return s->pc;
8145 illegal_op:
8146 if (s->prefix & PREFIX_LOCK)
8147 gen_helper_unlock();
8148 /* XXX: ensure that no lock was generated */
8149 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
8150 return s->pc;
8153 void optimize_flags_init(void)
8155 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8156 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
8157 offsetof(CPUX86State, cc_op), "cc_op");
8158 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
8159 "cc_dst");
8160 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
8161 "cc_src");
8162 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
8163 "cc_src2");
8165 #ifdef TARGET_X86_64
8166 cpu_regs[R_EAX] = tcg_global_mem_new_i64(TCG_AREG0,
8167 offsetof(CPUX86State, regs[R_EAX]), "rax");
8168 cpu_regs[R_ECX] = tcg_global_mem_new_i64(TCG_AREG0,
8169 offsetof(CPUX86State, regs[R_ECX]), "rcx");
8170 cpu_regs[R_EDX] = tcg_global_mem_new_i64(TCG_AREG0,
8171 offsetof(CPUX86State, regs[R_EDX]), "rdx");
8172 cpu_regs[R_EBX] = tcg_global_mem_new_i64(TCG_AREG0,
8173 offsetof(CPUX86State, regs[R_EBX]), "rbx");
8174 cpu_regs[R_ESP] = tcg_global_mem_new_i64(TCG_AREG0,
8175 offsetof(CPUX86State, regs[R_ESP]), "rsp");
8176 cpu_regs[R_EBP] = tcg_global_mem_new_i64(TCG_AREG0,
8177 offsetof(CPUX86State, regs[R_EBP]), "rbp");
8178 cpu_regs[R_ESI] = tcg_global_mem_new_i64(TCG_AREG0,
8179 offsetof(CPUX86State, regs[R_ESI]), "rsi");
8180 cpu_regs[R_EDI] = tcg_global_mem_new_i64(TCG_AREG0,
8181 offsetof(CPUX86State, regs[R_EDI]), "rdi");
8182 cpu_regs[8] = tcg_global_mem_new_i64(TCG_AREG0,
8183 offsetof(CPUX86State, regs[8]), "r8");
8184 cpu_regs[9] = tcg_global_mem_new_i64(TCG_AREG0,
8185 offsetof(CPUX86State, regs[9]), "r9");
8186 cpu_regs[10] = tcg_global_mem_new_i64(TCG_AREG0,
8187 offsetof(CPUX86State, regs[10]), "r10");
8188 cpu_regs[11] = tcg_global_mem_new_i64(TCG_AREG0,
8189 offsetof(CPUX86State, regs[11]), "r11");
8190 cpu_regs[12] = tcg_global_mem_new_i64(TCG_AREG0,
8191 offsetof(CPUX86State, regs[12]), "r12");
8192 cpu_regs[13] = tcg_global_mem_new_i64(TCG_AREG0,
8193 offsetof(CPUX86State, regs[13]), "r13");
8194 cpu_regs[14] = tcg_global_mem_new_i64(TCG_AREG0,
8195 offsetof(CPUX86State, regs[14]), "r14");
8196 cpu_regs[15] = tcg_global_mem_new_i64(TCG_AREG0,
8197 offsetof(CPUX86State, regs[15]), "r15");
8198 #else
8199 cpu_regs[R_EAX] = tcg_global_mem_new_i32(TCG_AREG0,
8200 offsetof(CPUX86State, regs[R_EAX]), "eax");
8201 cpu_regs[R_ECX] = tcg_global_mem_new_i32(TCG_AREG0,
8202 offsetof(CPUX86State, regs[R_ECX]), "ecx");
8203 cpu_regs[R_EDX] = tcg_global_mem_new_i32(TCG_AREG0,
8204 offsetof(CPUX86State, regs[R_EDX]), "edx");
8205 cpu_regs[R_EBX] = tcg_global_mem_new_i32(TCG_AREG0,
8206 offsetof(CPUX86State, regs[R_EBX]), "ebx");
8207 cpu_regs[R_ESP] = tcg_global_mem_new_i32(TCG_AREG0,
8208 offsetof(CPUX86State, regs[R_ESP]), "esp");
8209 cpu_regs[R_EBP] = tcg_global_mem_new_i32(TCG_AREG0,
8210 offsetof(CPUX86State, regs[R_EBP]), "ebp");
8211 cpu_regs[R_ESI] = tcg_global_mem_new_i32(TCG_AREG0,
8212 offsetof(CPUX86State, regs[R_ESI]), "esi");
8213 cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
8214 offsetof(CPUX86State, regs[R_EDI]), "edi");
8215 #endif
8218 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8219 basic block 'tb'. If search_pc is TRUE, also generate PC
8220 information for each intermediate instruction. */
8221 static inline void gen_intermediate_code_internal(X86CPU *cpu,
8222 TranslationBlock *tb,
8223 bool search_pc)
8225 CPUState *cs = CPU(cpu);
8226 CPUX86State *env = &cpu->env;
8227 DisasContext dc1, *dc = &dc1;
8228 target_ulong pc_ptr;
8229 uint16_t *gen_opc_end;
8230 CPUBreakpoint *bp;
8231 int j, lj;
8232 uint64_t flags;
8233 target_ulong pc_start;
8234 target_ulong cs_base;
8235 int num_insns;
8236 int max_insns;
8238 /* generate intermediate code */
8239 pc_start = tb->pc;
8240 cs_base = tb->cs_base;
8241 flags = tb->flags;
8243 dc->pe = (flags >> HF_PE_SHIFT) & 1;
8244 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8245 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8246 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8247 dc->f_st = 0;
8248 dc->vm86 = (flags >> VM_SHIFT) & 1;
8249 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8250 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8251 dc->tf = (flags >> TF_SHIFT) & 1;
8252 dc->singlestep_enabled = cs->singlestep_enabled;
8253 dc->cc_op = CC_OP_DYNAMIC;
8254 dc->cc_op_dirty = false;
8255 dc->cs_base = cs_base;
8256 dc->tb = tb;
8257 dc->popl_esp_hack = 0;
8258 /* select memory access functions */
8259 dc->mem_index = 0;
8260 if (flags & HF_SOFTMMU_MASK) {
8261 dc->mem_index = cpu_mmu_index(env);
8263 dc->cpuid_features = env->features[FEAT_1_EDX];
8264 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8265 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8266 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8267 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8268 #ifdef TARGET_X86_64
8269 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8270 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8271 #endif
8272 dc->flags = flags;
8273 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
8274 (flags & HF_INHIBIT_IRQ_MASK)
8275 #ifndef CONFIG_SOFTMMU
8276 || (flags & HF_SOFTMMU_MASK)
8277 #endif
8279 #if 0
8280 /* check addseg logic */
8281 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8282 printf("ERROR addseg\n");
8283 #endif
8285 cpu_T[0] = tcg_temp_new();
8286 cpu_T[1] = tcg_temp_new();
8287 cpu_A0 = tcg_temp_new();
8289 cpu_tmp0 = tcg_temp_new();
8290 cpu_tmp1_i64 = tcg_temp_new_i64();
8291 cpu_tmp2_i32 = tcg_temp_new_i32();
8292 cpu_tmp3_i32 = tcg_temp_new_i32();
8293 cpu_tmp4 = tcg_temp_new();
8294 cpu_ptr0 = tcg_temp_new_ptr();
8295 cpu_ptr1 = tcg_temp_new_ptr();
8296 cpu_cc_srcT = tcg_temp_local_new();
8298 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
8300 dc->is_jmp = DISAS_NEXT;
8301 pc_ptr = pc_start;
8302 lj = -1;
8303 num_insns = 0;
8304 max_insns = tb->cflags & CF_COUNT_MASK;
8305 if (max_insns == 0)
8306 max_insns = CF_COUNT_MASK;
8308 gen_tb_start();
8309 for(;;) {
8310 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8311 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8312 if (bp->pc == pc_ptr &&
8313 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
8314 gen_debug(dc, pc_ptr - dc->cs_base);
8315 break;
8319 if (search_pc) {
8320 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
8321 if (lj < j) {
8322 lj++;
8323 while (lj < j)
8324 tcg_ctx.gen_opc_instr_start[lj++] = 0;
8326 tcg_ctx.gen_opc_pc[lj] = pc_ptr;
8327 gen_opc_cc_op[lj] = dc->cc_op;
8328 tcg_ctx.gen_opc_instr_start[lj] = 1;
8329 tcg_ctx.gen_opc_icount[lj] = num_insns;
8331 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8332 gen_io_start();
8334 pc_ptr = disas_insn(env, dc, pc_ptr);
8335 num_insns++;
8336 /* stop translation if indicated */
8337 if (dc->is_jmp)
8338 break;
8339 /* if single step mode, we generate only one instruction and
8340 generate an exception */
8341 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8342 the flag and abort the translation to give the irqs a
8343 change to be happen */
8344 if (dc->tf || dc->singlestep_enabled ||
8345 (flags & HF_INHIBIT_IRQ_MASK)) {
8346 gen_jmp_im(pc_ptr - dc->cs_base);
8347 gen_eob(dc);
8348 break;
8350 /* if too long translation, stop generation too */
8351 if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
8352 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8353 num_insns >= max_insns) {
8354 gen_jmp_im(pc_ptr - dc->cs_base);
8355 gen_eob(dc);
8356 break;
8358 if (singlestep) {
8359 gen_jmp_im(pc_ptr - dc->cs_base);
8360 gen_eob(dc);
8361 break;
8364 if (tb->cflags & CF_LAST_IO)
8365 gen_io_end();
8366 gen_tb_end(tb, num_insns);
8367 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
8368 /* we don't forget to fill the last values */
8369 if (search_pc) {
8370 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
8371 lj++;
8372 while (lj <= j)
8373 tcg_ctx.gen_opc_instr_start[lj++] = 0;
8376 #ifdef DEBUG_DISAS
8377 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8378 int disas_flags;
8379 qemu_log("----------------\n");
8380 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8381 #ifdef TARGET_X86_64
8382 if (dc->code64)
8383 disas_flags = 2;
8384 else
8385 #endif
8386 disas_flags = !dc->code32;
8387 log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags);
8388 qemu_log("\n");
8390 #endif
8392 if (!search_pc) {
8393 tb->size = pc_ptr - pc_start;
8394 tb->icount = num_insns;
8398 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
8400 gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false);
8403 void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
8405 gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true);
8408 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
8410 int cc_op;
8411 #ifdef DEBUG_DISAS
8412 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
8413 int i;
8414 qemu_log("RESTORE:\n");
8415 for(i = 0;i <= pc_pos; i++) {
8416 if (tcg_ctx.gen_opc_instr_start[i]) {
8417 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
8418 tcg_ctx.gen_opc_pc[i]);
8421 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
8422 pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
8423 (uint32_t)tb->cs_base);
8425 #endif
8426 env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
8427 cc_op = gen_opc_cc_op[pc_pos];
8428 if (cc_op != CC_OP_DYNAMIC)
8429 env->cc_op = cc_op;