target-i386: Use mulu2 and muls2
[qemu/pbrook.git] / target-i386 / translate.c
blob3b92f3b227a92843bdb11511064264b15d02a72c
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 /* operand size */
167 enum {
168 OT_BYTE = 0,
169 OT_WORD,
170 OT_LONG,
171 OT_QUAD,
174 enum {
175 /* I386 int registers */
176 OR_EAX, /* MUST be even numbered */
177 OR_ECX,
178 OR_EDX,
179 OR_EBX,
180 OR_ESP,
181 OR_EBP,
182 OR_ESI,
183 OR_EDI,
185 OR_TMP0 = 16, /* temporary operand register */
186 OR_TMP1,
187 OR_A0, /* temporary register used when doing address evaluation */
190 enum {
191 USES_CC_DST = 1,
192 USES_CC_SRC = 2,
193 USES_CC_SRC2 = 4,
194 USES_CC_SRCT = 8,
197 /* Bit set if the global variable is live after setting CC_OP to X. */
198 static const uint8_t cc_op_live[CC_OP_NB] = {
199 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
200 [CC_OP_EFLAGS] = USES_CC_SRC,
201 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
202 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
203 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
204 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
205 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
206 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
207 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
208 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
209 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
210 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
211 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
212 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
213 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
214 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
215 [CC_OP_CLR] = 0,
218 static void set_cc_op(DisasContext *s, CCOp op)
220 int dead;
222 if (s->cc_op == op) {
223 return;
226 /* Discard CC computation that will no longer be used. */
227 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
228 if (dead & USES_CC_DST) {
229 tcg_gen_discard_tl(cpu_cc_dst);
231 if (dead & USES_CC_SRC) {
232 tcg_gen_discard_tl(cpu_cc_src);
234 if (dead & USES_CC_SRC2) {
235 tcg_gen_discard_tl(cpu_cc_src2);
237 if (dead & USES_CC_SRCT) {
238 tcg_gen_discard_tl(cpu_cc_srcT);
241 if (op == CC_OP_DYNAMIC) {
242 /* The DYNAMIC setting is translator only, and should never be
243 stored. Thus we always consider it clean. */
244 s->cc_op_dirty = false;
245 } else {
246 /* Discard any computed CC_OP value (see shifts). */
247 if (s->cc_op == CC_OP_DYNAMIC) {
248 tcg_gen_discard_i32(cpu_cc_op);
250 s->cc_op_dirty = true;
252 s->cc_op = op;
255 static void gen_update_cc_op(DisasContext *s)
257 if (s->cc_op_dirty) {
258 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
259 s->cc_op_dirty = false;
263 static inline void gen_op_movl_T0_0(void)
265 tcg_gen_movi_tl(cpu_T[0], 0);
268 static inline void gen_op_movl_T0_im(int32_t val)
270 tcg_gen_movi_tl(cpu_T[0], val);
273 static inline void gen_op_movl_T0_imu(uint32_t val)
275 tcg_gen_movi_tl(cpu_T[0], val);
278 static inline void gen_op_movl_T1_im(int32_t val)
280 tcg_gen_movi_tl(cpu_T[1], val);
283 static inline void gen_op_movl_T1_imu(uint32_t val)
285 tcg_gen_movi_tl(cpu_T[1], val);
288 static inline void gen_op_movl_A0_im(uint32_t val)
290 tcg_gen_movi_tl(cpu_A0, val);
293 #ifdef TARGET_X86_64
294 static inline void gen_op_movq_A0_im(int64_t val)
296 tcg_gen_movi_tl(cpu_A0, val);
298 #endif
300 static inline void gen_movtl_T0_im(target_ulong val)
302 tcg_gen_movi_tl(cpu_T[0], val);
305 static inline void gen_movtl_T1_im(target_ulong val)
307 tcg_gen_movi_tl(cpu_T[1], val);
310 static inline void gen_op_andl_T0_ffff(void)
312 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
315 static inline void gen_op_andl_T0_im(uint32_t val)
317 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
320 static inline void gen_op_movl_T0_T1(void)
322 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
325 static inline void gen_op_andl_A0_ffff(void)
327 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
330 #ifdef TARGET_X86_64
332 #define NB_OP_SIZES 4
334 #else /* !TARGET_X86_64 */
336 #define NB_OP_SIZES 3
338 #endif /* !TARGET_X86_64 */
340 #if defined(HOST_WORDS_BIGENDIAN)
341 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
342 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
343 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
344 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
345 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
346 #else
347 #define REG_B_OFFSET 0
348 #define REG_H_OFFSET 1
349 #define REG_W_OFFSET 0
350 #define REG_L_OFFSET 0
351 #define REG_LH_OFFSET 4
352 #endif
354 /* In instruction encodings for byte register accesses the
355 * register number usually indicates "low 8 bits of register N";
356 * however there are some special cases where N 4..7 indicates
357 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
358 * true for this special case, false otherwise.
360 static inline bool byte_reg_is_xH(int reg)
362 if (reg < 4) {
363 return false;
365 #ifdef TARGET_X86_64
366 if (reg >= 8 || x86_64_hregs) {
367 return false;
369 #endif
370 return true;
373 static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
375 switch(ot) {
376 case OT_BYTE:
377 if (!byte_reg_is_xH(reg)) {
378 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
379 } else {
380 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
382 break;
383 case OT_WORD:
384 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
385 break;
386 default: /* XXX this shouldn't be reached; abort? */
387 case OT_LONG:
388 /* For x86_64, this sets the higher half of register to zero.
389 For i386, this is equivalent to a mov. */
390 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
391 break;
392 #ifdef TARGET_X86_64
393 case OT_QUAD:
394 tcg_gen_mov_tl(cpu_regs[reg], t0);
395 break;
396 #endif
400 static inline void gen_op_mov_reg_T0(int ot, int reg)
402 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
405 static inline void gen_op_mov_reg_T1(int ot, int reg)
407 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
410 static inline void gen_op_mov_reg_A0(int size, int reg)
412 switch(size) {
413 case OT_BYTE:
414 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
415 break;
416 default: /* XXX this shouldn't be reached; abort? */
417 case OT_WORD:
418 /* For x86_64, this sets the higher half of register to zero.
419 For i386, this is equivalent to a mov. */
420 tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
421 break;
422 #ifdef TARGET_X86_64
423 case OT_LONG:
424 tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
425 break;
426 #endif
430 static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
432 if (ot == OT_BYTE && byte_reg_is_xH(reg)) {
433 tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
434 tcg_gen_ext8u_tl(t0, t0);
435 } else {
436 tcg_gen_mov_tl(t0, cpu_regs[reg]);
440 static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
442 gen_op_mov_v_reg(ot, cpu_T[t_index], reg);
445 static inline void gen_op_movl_A0_reg(int reg)
447 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
450 static inline void gen_op_addl_A0_im(int32_t val)
452 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
453 #ifdef TARGET_X86_64
454 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
455 #endif
458 #ifdef TARGET_X86_64
459 static inline void gen_op_addq_A0_im(int64_t val)
461 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
463 #endif
465 static void gen_add_A0_im(DisasContext *s, int val)
467 #ifdef TARGET_X86_64
468 if (CODE64(s))
469 gen_op_addq_A0_im(val);
470 else
471 #endif
472 gen_op_addl_A0_im(val);
475 static inline void gen_op_addl_T0_T1(void)
477 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480 static inline void gen_op_jmp_T0(void)
482 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
485 static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
487 switch(size) {
488 case OT_BYTE:
489 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
490 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
491 break;
492 case OT_WORD:
493 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
494 /* For x86_64, this sets the higher half of register to zero.
495 For i386, this is equivalent to a nop. */
496 tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
497 tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
498 break;
499 #ifdef TARGET_X86_64
500 case OT_LONG:
501 tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
502 break;
503 #endif
507 static inline void gen_op_add_reg_T0(int size, int reg)
509 switch(size) {
510 case OT_BYTE:
511 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
512 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
513 break;
514 case OT_WORD:
515 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
516 /* For x86_64, this sets the higher half of register to zero.
517 For i386, this is equivalent to a nop. */
518 tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
519 tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
520 break;
521 #ifdef TARGET_X86_64
522 case OT_LONG:
523 tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
524 break;
525 #endif
529 static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
531 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
532 if (shift != 0)
533 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
534 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
535 /* For x86_64, this sets the higher half of register to zero.
536 For i386, this is equivalent to a nop. */
537 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
540 static inline void gen_op_movl_A0_seg(int reg)
542 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
545 static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
547 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
548 #ifdef TARGET_X86_64
549 if (CODE64(s)) {
550 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
551 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
552 } else {
553 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
554 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
556 #else
557 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
558 #endif
561 #ifdef TARGET_X86_64
562 static inline void gen_op_movq_A0_seg(int reg)
564 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
567 static inline void gen_op_addq_A0_seg(int reg)
569 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
570 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
573 static inline void gen_op_movq_A0_reg(int reg)
575 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
578 static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
580 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
581 if (shift != 0)
582 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
583 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
585 #endif
587 static inline void gen_op_lds_T0_A0(int idx)
589 int mem_index = (idx >> 2) - 1;
590 switch(idx & 3) {
591 case OT_BYTE:
592 tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index);
593 break;
594 case OT_WORD:
595 tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index);
596 break;
597 default:
598 case OT_LONG:
599 tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index);
600 break;
604 static inline void gen_op_ld_v(int idx, TCGv t0, TCGv a0)
606 int mem_index = (idx >> 2) - 1;
607 switch(idx & 3) {
608 case OT_BYTE:
609 tcg_gen_qemu_ld8u(t0, a0, mem_index);
610 break;
611 case OT_WORD:
612 tcg_gen_qemu_ld16u(t0, a0, mem_index);
613 break;
614 case OT_LONG:
615 tcg_gen_qemu_ld32u(t0, a0, mem_index);
616 break;
617 default:
618 case OT_QUAD:
619 /* Should never happen on 32-bit targets. */
620 #ifdef TARGET_X86_64
621 tcg_gen_qemu_ld64(t0, a0, mem_index);
622 #endif
623 break;
627 /* XXX: always use ldu or lds */
628 static inline void gen_op_ld_T0_A0(int idx)
630 gen_op_ld_v(idx, cpu_T[0], cpu_A0);
633 static inline void gen_op_ldu_T0_A0(int idx)
635 gen_op_ld_v(idx, cpu_T[0], cpu_A0);
638 static inline void gen_op_ld_T1_A0(int idx)
640 gen_op_ld_v(idx, cpu_T[1], cpu_A0);
643 static inline void gen_op_st_v(int idx, TCGv t0, TCGv a0)
645 int mem_index = (idx >> 2) - 1;
646 switch(idx & 3) {
647 case OT_BYTE:
648 tcg_gen_qemu_st8(t0, a0, mem_index);
649 break;
650 case OT_WORD:
651 tcg_gen_qemu_st16(t0, a0, mem_index);
652 break;
653 case OT_LONG:
654 tcg_gen_qemu_st32(t0, a0, mem_index);
655 break;
656 default:
657 case OT_QUAD:
658 /* Should never happen on 32-bit targets. */
659 #ifdef TARGET_X86_64
660 tcg_gen_qemu_st64(t0, a0, mem_index);
661 #endif
662 break;
666 static inline void gen_op_st_T0_A0(int idx)
668 gen_op_st_v(idx, cpu_T[0], cpu_A0);
671 static inline void gen_op_st_T1_A0(int idx)
673 gen_op_st_v(idx, cpu_T[1], cpu_A0);
676 static inline void gen_jmp_im(target_ulong pc)
678 tcg_gen_movi_tl(cpu_tmp0, pc);
679 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, eip));
682 static inline void gen_string_movl_A0_ESI(DisasContext *s)
684 int override;
686 override = s->override;
687 #ifdef TARGET_X86_64
688 if (s->aflag == 2) {
689 if (override >= 0) {
690 gen_op_movq_A0_seg(override);
691 gen_op_addq_A0_reg_sN(0, R_ESI);
692 } else {
693 gen_op_movq_A0_reg(R_ESI);
695 } else
696 #endif
697 if (s->aflag) {
698 /* 32 bit address */
699 if (s->addseg && override < 0)
700 override = R_DS;
701 if (override >= 0) {
702 gen_op_movl_A0_seg(override);
703 gen_op_addl_A0_reg_sN(0, R_ESI);
704 } else {
705 gen_op_movl_A0_reg(R_ESI);
707 } else {
708 /* 16 address, always override */
709 if (override < 0)
710 override = R_DS;
711 gen_op_movl_A0_reg(R_ESI);
712 gen_op_andl_A0_ffff();
713 gen_op_addl_A0_seg(s, override);
717 static inline void gen_string_movl_A0_EDI(DisasContext *s)
719 #ifdef TARGET_X86_64
720 if (s->aflag == 2) {
721 gen_op_movq_A0_reg(R_EDI);
722 } else
723 #endif
724 if (s->aflag) {
725 if (s->addseg) {
726 gen_op_movl_A0_seg(R_ES);
727 gen_op_addl_A0_reg_sN(0, R_EDI);
728 } else {
729 gen_op_movl_A0_reg(R_EDI);
731 } else {
732 gen_op_movl_A0_reg(R_EDI);
733 gen_op_andl_A0_ffff();
734 gen_op_addl_A0_seg(s, R_ES);
738 static inline void gen_op_movl_T0_Dshift(int ot)
740 tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
741 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
744 static TCGv gen_ext_tl(TCGv dst, TCGv src, int size, bool sign)
746 switch (size) {
747 case OT_BYTE:
748 if (sign) {
749 tcg_gen_ext8s_tl(dst, src);
750 } else {
751 tcg_gen_ext8u_tl(dst, src);
753 return dst;
754 case OT_WORD:
755 if (sign) {
756 tcg_gen_ext16s_tl(dst, src);
757 } else {
758 tcg_gen_ext16u_tl(dst, src);
760 return dst;
761 #ifdef TARGET_X86_64
762 case OT_LONG:
763 if (sign) {
764 tcg_gen_ext32s_tl(dst, src);
765 } else {
766 tcg_gen_ext32u_tl(dst, src);
768 return dst;
769 #endif
770 default:
771 return src;
775 static void gen_extu(int ot, TCGv reg)
777 gen_ext_tl(reg, reg, ot, false);
780 static void gen_exts(int ot, TCGv reg)
782 gen_ext_tl(reg, reg, ot, true);
785 static inline void gen_op_jnz_ecx(int size, int label1)
787 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
788 gen_extu(size + 1, cpu_tmp0);
789 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
792 static inline void gen_op_jz_ecx(int size, int label1)
794 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
795 gen_extu(size + 1, cpu_tmp0);
796 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
799 static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
801 switch (ot) {
802 case OT_BYTE:
803 gen_helper_inb(v, n);
804 break;
805 case OT_WORD:
806 gen_helper_inw(v, n);
807 break;
808 case OT_LONG:
809 gen_helper_inl(v, n);
810 break;
814 static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
816 switch (ot) {
817 case OT_BYTE:
818 gen_helper_outb(v, n);
819 break;
820 case OT_WORD:
821 gen_helper_outw(v, n);
822 break;
823 case OT_LONG:
824 gen_helper_outl(v, n);
825 break;
829 static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
830 uint32_t svm_flags)
832 int state_saved;
833 target_ulong next_eip;
835 state_saved = 0;
836 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
837 gen_update_cc_op(s);
838 gen_jmp_im(cur_eip);
839 state_saved = 1;
840 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
841 switch (ot) {
842 case OT_BYTE:
843 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
844 break;
845 case OT_WORD:
846 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
847 break;
848 case OT_LONG:
849 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
850 break;
853 if(s->flags & HF_SVMI_MASK) {
854 if (!state_saved) {
855 gen_update_cc_op(s);
856 gen_jmp_im(cur_eip);
858 svm_flags |= (1 << (4 + ot));
859 next_eip = s->pc - s->cs_base;
860 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
861 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
862 tcg_const_i32(svm_flags),
863 tcg_const_i32(next_eip - cur_eip));
867 static inline void gen_movs(DisasContext *s, int ot)
869 gen_string_movl_A0_ESI(s);
870 gen_op_ld_T0_A0(ot + s->mem_index);
871 gen_string_movl_A0_EDI(s);
872 gen_op_st_T0_A0(ot + s->mem_index);
873 gen_op_movl_T0_Dshift(ot);
874 gen_op_add_reg_T0(s->aflag, R_ESI);
875 gen_op_add_reg_T0(s->aflag, R_EDI);
878 static void gen_op_update1_cc(void)
880 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
883 static void gen_op_update2_cc(void)
885 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
886 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
889 static void gen_op_update3_cc(TCGv reg)
891 tcg_gen_mov_tl(cpu_cc_src2, reg);
892 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
893 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
896 static inline void gen_op_testl_T0_T1_cc(void)
898 tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
901 static void gen_op_update_neg_cc(void)
903 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
904 tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]);
905 tcg_gen_movi_tl(cpu_cc_srcT, 0);
908 /* compute all eflags to cc_src */
909 static void gen_compute_eflags(DisasContext *s)
911 TCGv zero, dst, src1, src2;
912 int live, dead;
914 if (s->cc_op == CC_OP_EFLAGS) {
915 return;
917 if (s->cc_op == CC_OP_CLR) {
918 tcg_gen_movi_tl(cpu_cc_src, CC_Z);
919 set_cc_op(s, CC_OP_EFLAGS);
920 return;
923 TCGV_UNUSED(zero);
924 dst = cpu_cc_dst;
925 src1 = cpu_cc_src;
926 src2 = cpu_cc_src2;
928 /* Take care to not read values that are not live. */
929 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
930 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
931 if (dead) {
932 zero = tcg_const_tl(0);
933 if (dead & USES_CC_DST) {
934 dst = zero;
936 if (dead & USES_CC_SRC) {
937 src1 = zero;
939 if (dead & USES_CC_SRC2) {
940 src2 = zero;
944 gen_update_cc_op(s);
945 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
946 set_cc_op(s, CC_OP_EFLAGS);
948 if (dead) {
949 tcg_temp_free(zero);
953 typedef struct CCPrepare {
954 TCGCond cond;
955 TCGv reg;
956 TCGv reg2;
957 target_ulong imm;
958 target_ulong mask;
959 bool use_reg2;
960 bool no_setcond;
961 } CCPrepare;
963 /* compute eflags.C to reg */
964 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
966 TCGv t0, t1;
967 int size, shift;
969 switch (s->cc_op) {
970 case CC_OP_SUBB ... CC_OP_SUBQ:
971 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
972 size = s->cc_op - CC_OP_SUBB;
973 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
974 /* If no temporary was used, be careful not to alias t1 and t0. */
975 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
976 tcg_gen_mov_tl(t0, cpu_cc_srcT);
977 gen_extu(size, t0);
978 goto add_sub;
980 case CC_OP_ADDB ... CC_OP_ADDQ:
981 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
982 size = s->cc_op - CC_OP_ADDB;
983 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
984 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
985 add_sub:
986 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
987 .reg2 = t1, .mask = -1, .use_reg2 = true };
989 case CC_OP_LOGICB ... CC_OP_LOGICQ:
990 case CC_OP_CLR:
991 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
993 case CC_OP_INCB ... CC_OP_INCQ:
994 case CC_OP_DECB ... CC_OP_DECQ:
995 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
996 .mask = -1, .no_setcond = true };
998 case CC_OP_SHLB ... CC_OP_SHLQ:
999 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
1000 size = s->cc_op - CC_OP_SHLB;
1001 shift = (8 << size) - 1;
1002 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1003 .mask = (target_ulong)1 << shift };
1005 case CC_OP_MULB ... CC_OP_MULQ:
1006 return (CCPrepare) { .cond = TCG_COND_NE,
1007 .reg = cpu_cc_src, .mask = -1 };
1009 case CC_OP_BMILGB ... CC_OP_BMILGQ:
1010 size = s->cc_op - CC_OP_BMILGB;
1011 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
1012 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
1014 case CC_OP_ADCX:
1015 case CC_OP_ADCOX:
1016 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
1017 .mask = -1, .no_setcond = true };
1019 case CC_OP_EFLAGS:
1020 case CC_OP_SARB ... CC_OP_SARQ:
1021 /* CC_SRC & 1 */
1022 return (CCPrepare) { .cond = TCG_COND_NE,
1023 .reg = cpu_cc_src, .mask = CC_C };
1025 default:
1026 /* The need to compute only C from CC_OP_DYNAMIC is important
1027 in efficiently implementing e.g. INC at the start of a TB. */
1028 gen_update_cc_op(s);
1029 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
1030 cpu_cc_src2, cpu_cc_op);
1031 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1032 .mask = -1, .no_setcond = true };
1036 /* compute eflags.P to reg */
1037 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
1039 gen_compute_eflags(s);
1040 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1041 .mask = CC_P };
1044 /* compute eflags.S to reg */
1045 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
1047 switch (s->cc_op) {
1048 case CC_OP_DYNAMIC:
1049 gen_compute_eflags(s);
1050 /* FALLTHRU */
1051 case CC_OP_EFLAGS:
1052 case CC_OP_ADCX:
1053 case CC_OP_ADOX:
1054 case CC_OP_ADCOX:
1055 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1056 .mask = CC_S };
1057 case CC_OP_CLR:
1058 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
1059 default:
1061 int size = (s->cc_op - CC_OP_ADDB) & 3;
1062 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
1063 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
1068 /* compute eflags.O to reg */
1069 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
1071 switch (s->cc_op) {
1072 case CC_OP_ADOX:
1073 case CC_OP_ADCOX:
1074 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
1075 .mask = -1, .no_setcond = true };
1076 case CC_OP_CLR:
1077 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
1078 default:
1079 gen_compute_eflags(s);
1080 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1081 .mask = CC_O };
1085 /* compute eflags.Z to reg */
1086 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
1088 switch (s->cc_op) {
1089 case CC_OP_DYNAMIC:
1090 gen_compute_eflags(s);
1091 /* FALLTHRU */
1092 case CC_OP_EFLAGS:
1093 case CC_OP_ADCX:
1094 case CC_OP_ADOX:
1095 case CC_OP_ADCOX:
1096 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1097 .mask = CC_Z };
1098 case CC_OP_CLR:
1099 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
1100 default:
1102 int size = (s->cc_op - CC_OP_ADDB) & 3;
1103 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
1104 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
1109 /* perform a conditional store into register 'reg' according to jump opcode
1110 value 'b'. In the fast case, T0 is guaranted not to be used. */
1111 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
1113 int inv, jcc_op, size, cond;
1114 CCPrepare cc;
1115 TCGv t0;
1117 inv = b & 1;
1118 jcc_op = (b >> 1) & 7;
1120 switch (s->cc_op) {
1121 case CC_OP_SUBB ... CC_OP_SUBQ:
1122 /* We optimize relational operators for the cmp/jcc case. */
1123 size = s->cc_op - CC_OP_SUBB;
1124 switch (jcc_op) {
1125 case JCC_BE:
1126 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
1127 gen_extu(size, cpu_tmp4);
1128 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
1129 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
1130 .reg2 = t0, .mask = -1, .use_reg2 = true };
1131 break;
1133 case JCC_L:
1134 cond = TCG_COND_LT;
1135 goto fast_jcc_l;
1136 case JCC_LE:
1137 cond = TCG_COND_LE;
1138 fast_jcc_l:
1139 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
1140 gen_exts(size, cpu_tmp4);
1141 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
1142 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
1143 .reg2 = t0, .mask = -1, .use_reg2 = true };
1144 break;
1146 default:
1147 goto slow_jcc;
1149 break;
1151 default:
1152 slow_jcc:
1153 /* This actually generates good code for JC, JZ and JS. */
1154 switch (jcc_op) {
1155 case JCC_O:
1156 cc = gen_prepare_eflags_o(s, reg);
1157 break;
1158 case JCC_B:
1159 cc = gen_prepare_eflags_c(s, reg);
1160 break;
1161 case JCC_Z:
1162 cc = gen_prepare_eflags_z(s, reg);
1163 break;
1164 case JCC_BE:
1165 gen_compute_eflags(s);
1166 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1167 .mask = CC_Z | CC_C };
1168 break;
1169 case JCC_S:
1170 cc = gen_prepare_eflags_s(s, reg);
1171 break;
1172 case JCC_P:
1173 cc = gen_prepare_eflags_p(s, reg);
1174 break;
1175 case JCC_L:
1176 gen_compute_eflags(s);
1177 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1178 reg = cpu_tmp0;
1180 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1181 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1182 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1183 .mask = CC_S };
1184 break;
1185 default:
1186 case JCC_LE:
1187 gen_compute_eflags(s);
1188 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1189 reg = cpu_tmp0;
1191 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1192 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1193 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1194 .mask = CC_S | CC_Z };
1195 break;
1197 break;
1200 if (inv) {
1201 cc.cond = tcg_invert_cond(cc.cond);
1203 return cc;
1206 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1208 CCPrepare cc = gen_prepare_cc(s, b, reg);
1210 if (cc.no_setcond) {
1211 if (cc.cond == TCG_COND_EQ) {
1212 tcg_gen_xori_tl(reg, cc.reg, 1);
1213 } else {
1214 tcg_gen_mov_tl(reg, cc.reg);
1216 return;
1219 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1220 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1221 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1222 tcg_gen_andi_tl(reg, reg, 1);
1223 return;
1225 if (cc.mask != -1) {
1226 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1227 cc.reg = reg;
1229 if (cc.use_reg2) {
1230 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1231 } else {
1232 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1236 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1238 gen_setcc1(s, JCC_B << 1, reg);
1241 /* generate a conditional jump to label 'l1' according to jump opcode
1242 value 'b'. In the fast case, T0 is guaranted not to be used. */
1243 static inline void gen_jcc1_noeob(DisasContext *s, int b, int l1)
1245 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1247 if (cc.mask != -1) {
1248 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1249 cc.reg = cpu_T[0];
1251 if (cc.use_reg2) {
1252 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1253 } else {
1254 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1258 /* Generate a conditional jump to label 'l1' according to jump opcode
1259 value 'b'. In the fast case, T0 is guaranted not to be used.
1260 A translation block must end soon. */
1261 static inline void gen_jcc1(DisasContext *s, int b, int l1)
1263 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1265 gen_update_cc_op(s);
1266 if (cc.mask != -1) {
1267 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1268 cc.reg = cpu_T[0];
1270 set_cc_op(s, CC_OP_DYNAMIC);
1271 if (cc.use_reg2) {
1272 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1273 } else {
1274 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1278 /* XXX: does not work with gdbstub "ice" single step - not a
1279 serious problem */
1280 static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1282 int l1, l2;
1284 l1 = gen_new_label();
1285 l2 = gen_new_label();
1286 gen_op_jnz_ecx(s->aflag, l1);
1287 gen_set_label(l2);
1288 gen_jmp_tb(s, next_eip, 1);
1289 gen_set_label(l1);
1290 return l2;
1293 static inline void gen_stos(DisasContext *s, int ot)
1295 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
1296 gen_string_movl_A0_EDI(s);
1297 gen_op_st_T0_A0(ot + s->mem_index);
1298 gen_op_movl_T0_Dshift(ot);
1299 gen_op_add_reg_T0(s->aflag, R_EDI);
1302 static inline void gen_lods(DisasContext *s, int ot)
1304 gen_string_movl_A0_ESI(s);
1305 gen_op_ld_T0_A0(ot + s->mem_index);
1306 gen_op_mov_reg_T0(ot, R_EAX);
1307 gen_op_movl_T0_Dshift(ot);
1308 gen_op_add_reg_T0(s->aflag, R_ESI);
1311 static inline void gen_scas(DisasContext *s, int ot)
1313 gen_string_movl_A0_EDI(s);
1314 gen_op_ld_T1_A0(ot + s->mem_index);
1315 gen_op(s, OP_CMPL, ot, R_EAX);
1316 gen_op_movl_T0_Dshift(ot);
1317 gen_op_add_reg_T0(s->aflag, R_EDI);
1320 static inline void gen_cmps(DisasContext *s, int ot)
1322 gen_string_movl_A0_EDI(s);
1323 gen_op_ld_T1_A0(ot + s->mem_index);
1324 gen_string_movl_A0_ESI(s);
1325 gen_op(s, OP_CMPL, ot, OR_TMP0);
1326 gen_op_movl_T0_Dshift(ot);
1327 gen_op_add_reg_T0(s->aflag, R_ESI);
1328 gen_op_add_reg_T0(s->aflag, R_EDI);
1331 static inline void gen_ins(DisasContext *s, int ot)
1333 if (use_icount)
1334 gen_io_start();
1335 gen_string_movl_A0_EDI(s);
1336 /* Note: we must do this dummy write first to be restartable in
1337 case of page fault. */
1338 gen_op_movl_T0_0();
1339 gen_op_st_T0_A0(ot + s->mem_index);
1340 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
1341 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1342 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1343 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
1344 gen_op_st_T0_A0(ot + s->mem_index);
1345 gen_op_movl_T0_Dshift(ot);
1346 gen_op_add_reg_T0(s->aflag, R_EDI);
1347 if (use_icount)
1348 gen_io_end();
1351 static inline void gen_outs(DisasContext *s, int ot)
1353 if (use_icount)
1354 gen_io_start();
1355 gen_string_movl_A0_ESI(s);
1356 gen_op_ld_T0_A0(ot + s->mem_index);
1358 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
1359 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1360 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1361 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
1362 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1364 gen_op_movl_T0_Dshift(ot);
1365 gen_op_add_reg_T0(s->aflag, R_ESI);
1366 if (use_icount)
1367 gen_io_end();
1370 /* same method as Valgrind : we generate jumps to current or next
1371 instruction */
1372 #define GEN_REPZ(op) \
1373 static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1374 target_ulong cur_eip, target_ulong next_eip) \
1376 int l2;\
1377 gen_update_cc_op(s); \
1378 l2 = gen_jz_ecx_string(s, next_eip); \
1379 gen_ ## op(s, ot); \
1380 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1381 /* a loop would cause two single step exceptions if ECX = 1 \
1382 before rep string_insn */ \
1383 if (!s->jmp_opt) \
1384 gen_op_jz_ecx(s->aflag, l2); \
1385 gen_jmp(s, cur_eip); \
1388 #define GEN_REPZ2(op) \
1389 static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1390 target_ulong cur_eip, \
1391 target_ulong next_eip, \
1392 int nz) \
1394 int l2;\
1395 gen_update_cc_op(s); \
1396 l2 = gen_jz_ecx_string(s, next_eip); \
1397 gen_ ## op(s, ot); \
1398 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1399 gen_update_cc_op(s); \
1400 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1401 if (!s->jmp_opt) \
1402 gen_op_jz_ecx(s->aflag, l2); \
1403 gen_jmp(s, cur_eip); \
1406 GEN_REPZ(movs)
1407 GEN_REPZ(stos)
1408 GEN_REPZ(lods)
1409 GEN_REPZ(ins)
1410 GEN_REPZ(outs)
1411 GEN_REPZ2(scas)
1412 GEN_REPZ2(cmps)
1414 static void gen_helper_fp_arith_ST0_FT0(int op)
1416 switch (op) {
1417 case 0:
1418 gen_helper_fadd_ST0_FT0(cpu_env);
1419 break;
1420 case 1:
1421 gen_helper_fmul_ST0_FT0(cpu_env);
1422 break;
1423 case 2:
1424 gen_helper_fcom_ST0_FT0(cpu_env);
1425 break;
1426 case 3:
1427 gen_helper_fcom_ST0_FT0(cpu_env);
1428 break;
1429 case 4:
1430 gen_helper_fsub_ST0_FT0(cpu_env);
1431 break;
1432 case 5:
1433 gen_helper_fsubr_ST0_FT0(cpu_env);
1434 break;
1435 case 6:
1436 gen_helper_fdiv_ST0_FT0(cpu_env);
1437 break;
1438 case 7:
1439 gen_helper_fdivr_ST0_FT0(cpu_env);
1440 break;
1444 /* NOTE the exception in "r" op ordering */
1445 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1447 TCGv_i32 tmp = tcg_const_i32(opreg);
1448 switch (op) {
1449 case 0:
1450 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1451 break;
1452 case 1:
1453 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1454 break;
1455 case 4:
1456 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1457 break;
1458 case 5:
1459 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1460 break;
1461 case 6:
1462 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1463 break;
1464 case 7:
1465 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1466 break;
1470 /* if d == OR_TMP0, it means memory operand (address in A0) */
1471 static void gen_op(DisasContext *s1, int op, int ot, int d)
1473 if (d != OR_TMP0) {
1474 gen_op_mov_TN_reg(ot, 0, d);
1475 } else {
1476 gen_op_ld_T0_A0(ot + s1->mem_index);
1478 switch(op) {
1479 case OP_ADCL:
1480 gen_compute_eflags_c(s1, cpu_tmp4);
1481 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1482 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1483 if (d != OR_TMP0)
1484 gen_op_mov_reg_T0(ot, d);
1485 else
1486 gen_op_st_T0_A0(ot + s1->mem_index);
1487 gen_op_update3_cc(cpu_tmp4);
1488 set_cc_op(s1, CC_OP_ADCB + ot);
1489 break;
1490 case OP_SBBL:
1491 gen_compute_eflags_c(s1, cpu_tmp4);
1492 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1493 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1494 if (d != OR_TMP0)
1495 gen_op_mov_reg_T0(ot, d);
1496 else
1497 gen_op_st_T0_A0(ot + s1->mem_index);
1498 gen_op_update3_cc(cpu_tmp4);
1499 set_cc_op(s1, CC_OP_SBBB + ot);
1500 break;
1501 case OP_ADDL:
1502 gen_op_addl_T0_T1();
1503 if (d != OR_TMP0)
1504 gen_op_mov_reg_T0(ot, d);
1505 else
1506 gen_op_st_T0_A0(ot + s1->mem_index);
1507 gen_op_update2_cc();
1508 set_cc_op(s1, CC_OP_ADDB + ot);
1509 break;
1510 case OP_SUBL:
1511 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1512 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1513 if (d != OR_TMP0)
1514 gen_op_mov_reg_T0(ot, d);
1515 else
1516 gen_op_st_T0_A0(ot + s1->mem_index);
1517 gen_op_update2_cc();
1518 set_cc_op(s1, CC_OP_SUBB + ot);
1519 break;
1520 default:
1521 case OP_ANDL:
1522 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1523 if (d != OR_TMP0)
1524 gen_op_mov_reg_T0(ot, d);
1525 else
1526 gen_op_st_T0_A0(ot + s1->mem_index);
1527 gen_op_update1_cc();
1528 set_cc_op(s1, CC_OP_LOGICB + ot);
1529 break;
1530 case OP_ORL:
1531 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1532 if (d != OR_TMP0)
1533 gen_op_mov_reg_T0(ot, d);
1534 else
1535 gen_op_st_T0_A0(ot + s1->mem_index);
1536 gen_op_update1_cc();
1537 set_cc_op(s1, CC_OP_LOGICB + ot);
1538 break;
1539 case OP_XORL:
1540 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1541 if (d != OR_TMP0)
1542 gen_op_mov_reg_T0(ot, d);
1543 else
1544 gen_op_st_T0_A0(ot + s1->mem_index);
1545 gen_op_update1_cc();
1546 set_cc_op(s1, CC_OP_LOGICB + ot);
1547 break;
1548 case OP_CMPL:
1549 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
1550 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1551 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
1552 set_cc_op(s1, CC_OP_SUBB + ot);
1553 break;
1557 /* if d == OR_TMP0, it means memory operand (address in A0) */
1558 static void gen_inc(DisasContext *s1, int ot, int d, int c)
1560 if (d != OR_TMP0)
1561 gen_op_mov_TN_reg(ot, 0, d);
1562 else
1563 gen_op_ld_T0_A0(ot + s1->mem_index);
1564 gen_compute_eflags_c(s1, cpu_cc_src);
1565 if (c > 0) {
1566 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
1567 set_cc_op(s1, CC_OP_INCB + ot);
1568 } else {
1569 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
1570 set_cc_op(s1, CC_OP_DECB + ot);
1572 if (d != OR_TMP0)
1573 gen_op_mov_reg_T0(ot, d);
1574 else
1575 gen_op_st_T0_A0(ot + s1->mem_index);
1576 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1579 static void gen_shift_flags(DisasContext *s, int ot, TCGv result, TCGv shm1,
1580 TCGv count, bool is_right)
1582 TCGv_i32 z32, s32, oldop;
1583 TCGv z_tl;
1585 /* Store the results into the CC variables. If we know that the
1586 variable must be dead, store unconditionally. Otherwise we'll
1587 need to not disrupt the current contents. */
1588 z_tl = tcg_const_tl(0);
1589 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1590 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1591 result, cpu_cc_dst);
1592 } else {
1593 tcg_gen_mov_tl(cpu_cc_dst, result);
1595 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1596 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1597 shm1, cpu_cc_src);
1598 } else {
1599 tcg_gen_mov_tl(cpu_cc_src, shm1);
1601 tcg_temp_free(z_tl);
1603 /* Get the two potential CC_OP values into temporaries. */
1604 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1605 if (s->cc_op == CC_OP_DYNAMIC) {
1606 oldop = cpu_cc_op;
1607 } else {
1608 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1609 oldop = cpu_tmp3_i32;
1612 /* Conditionally store the CC_OP value. */
1613 z32 = tcg_const_i32(0);
1614 s32 = tcg_temp_new_i32();
1615 tcg_gen_trunc_tl_i32(s32, count);
1616 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1617 tcg_temp_free_i32(z32);
1618 tcg_temp_free_i32(s32);
1620 /* The CC_OP value is no longer predictable. */
1621 set_cc_op(s, CC_OP_DYNAMIC);
1624 static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
1625 int is_right, int is_arith)
1627 target_ulong mask = (ot == OT_QUAD ? 0x3f : 0x1f);
1629 /* load */
1630 if (op1 == OR_TMP0) {
1631 gen_op_ld_T0_A0(ot + s->mem_index);
1632 } else {
1633 gen_op_mov_TN_reg(ot, 0, op1);
1636 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1637 tcg_gen_subi_tl(cpu_tmp0, cpu_T[1], 1);
1639 if (is_right) {
1640 if (is_arith) {
1641 gen_exts(ot, cpu_T[0]);
1642 tcg_gen_sar_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1643 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1644 } else {
1645 gen_extu(ot, cpu_T[0]);
1646 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1647 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1649 } else {
1650 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1651 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1654 /* store */
1655 if (op1 == OR_TMP0) {
1656 gen_op_st_T0_A0(ot + s->mem_index);
1657 } else {
1658 gen_op_mov_reg_T0(ot, op1);
1661 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, cpu_T[1], is_right);
1664 static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
1665 int is_right, int is_arith)
1667 int mask = (ot == OT_QUAD ? 0x3f : 0x1f);
1669 /* load */
1670 if (op1 == OR_TMP0)
1671 gen_op_ld_T0_A0(ot + s->mem_index);
1672 else
1673 gen_op_mov_TN_reg(ot, 0, op1);
1675 op2 &= mask;
1676 if (op2 != 0) {
1677 if (is_right) {
1678 if (is_arith) {
1679 gen_exts(ot, cpu_T[0]);
1680 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1681 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
1682 } else {
1683 gen_extu(ot, cpu_T[0]);
1684 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1685 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
1687 } else {
1688 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1689 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
1693 /* store */
1694 if (op1 == OR_TMP0)
1695 gen_op_st_T0_A0(ot + s->mem_index);
1696 else
1697 gen_op_mov_reg_T0(ot, op1);
1699 /* update eflags if non zero shift */
1700 if (op2 != 0) {
1701 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1702 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1703 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1707 static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2)
1709 if (arg2 >= 0)
1710 tcg_gen_shli_tl(ret, arg1, arg2);
1711 else
1712 tcg_gen_shri_tl(ret, arg1, -arg2);
1715 static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
1717 target_ulong mask = (ot == OT_QUAD ? 0x3f : 0x1f);
1718 TCGv_i32 t0, t1;
1720 /* load */
1721 if (op1 == OR_TMP0) {
1722 gen_op_ld_T0_A0(ot + s->mem_index);
1723 } else {
1724 gen_op_mov_TN_reg(ot, 0, op1);
1727 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1729 switch (ot) {
1730 case OT_BYTE:
1731 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1732 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
1733 tcg_gen_muli_tl(cpu_T[0], cpu_T[0], 0x01010101);
1734 goto do_long;
1735 case OT_WORD:
1736 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1737 tcg_gen_deposit_tl(cpu_T[0], cpu_T[0], cpu_T[0], 16, 16);
1738 goto do_long;
1739 do_long:
1740 #ifdef TARGET_X86_64
1741 case OT_LONG:
1742 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1743 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
1744 if (is_right) {
1745 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1746 } else {
1747 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1749 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1750 break;
1751 #endif
1752 default:
1753 if (is_right) {
1754 tcg_gen_rotr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1755 } else {
1756 tcg_gen_rotl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1758 break;
1761 /* store */
1762 if (op1 == OR_TMP0) {
1763 gen_op_st_T0_A0(ot + s->mem_index);
1764 } else {
1765 gen_op_mov_reg_T0(ot, op1);
1768 /* We'll need the flags computed into CC_SRC. */
1769 gen_compute_eflags(s);
1771 /* The value that was "rotated out" is now present at the other end
1772 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1773 since we've computed the flags into CC_SRC, these variables are
1774 currently dead. */
1775 if (is_right) {
1776 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1777 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1778 } else {
1779 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1780 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
1782 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1783 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1785 /* Now conditionally store the new CC_OP value. If the shift count
1786 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1787 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1788 exactly as we computed above. */
1789 t0 = tcg_const_i32(0);
1790 t1 = tcg_temp_new_i32();
1791 tcg_gen_trunc_tl_i32(t1, cpu_T[1]);
1792 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1793 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1794 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1795 cpu_tmp2_i32, cpu_tmp3_i32);
1796 tcg_temp_free_i32(t0);
1797 tcg_temp_free_i32(t1);
1799 /* The CC_OP value is no longer predictable. */
1800 set_cc_op(s, CC_OP_DYNAMIC);
1803 static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
1804 int is_right)
1806 int mask = (ot == OT_QUAD ? 0x3f : 0x1f);
1807 int shift;
1809 /* load */
1810 if (op1 == OR_TMP0) {
1811 gen_op_ld_T0_A0(ot + s->mem_index);
1812 } else {
1813 gen_op_mov_TN_reg(ot, 0, op1);
1816 op2 &= mask;
1817 if (op2 != 0) {
1818 switch (ot) {
1819 #ifdef TARGET_X86_64
1820 case OT_LONG:
1821 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1822 if (is_right) {
1823 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1824 } else {
1825 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1827 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1828 break;
1829 #endif
1830 default:
1831 if (is_right) {
1832 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], op2);
1833 } else {
1834 tcg_gen_rotli_tl(cpu_T[0], cpu_T[0], op2);
1836 break;
1837 case OT_BYTE:
1838 mask = 7;
1839 goto do_shifts;
1840 case OT_WORD:
1841 mask = 15;
1842 do_shifts:
1843 shift = op2 & mask;
1844 if (is_right) {
1845 shift = mask + 1 - shift;
1847 gen_extu(ot, cpu_T[0]);
1848 tcg_gen_shli_tl(cpu_tmp0, cpu_T[0], shift);
1849 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], mask + 1 - shift);
1850 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
1851 break;
1855 /* store */
1856 if (op1 == OR_TMP0) {
1857 gen_op_st_T0_A0(ot + s->mem_index);
1858 } else {
1859 gen_op_mov_reg_T0(ot, op1);
1862 if (op2 != 0) {
1863 /* Compute the flags into CC_SRC. */
1864 gen_compute_eflags(s);
1866 /* The value that was "rotated out" is now present at the other end
1867 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1868 since we've computed the flags into CC_SRC, these variables are
1869 currently dead. */
1870 if (is_right) {
1871 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1872 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
1873 } else {
1874 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1875 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
1877 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1878 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1879 set_cc_op(s, CC_OP_ADCOX);
1883 /* XXX: add faster immediate = 1 case */
1884 static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
1885 int is_right)
1887 gen_compute_eflags(s);
1888 assert(s->cc_op == CC_OP_EFLAGS);
1890 /* load */
1891 if (op1 == OR_TMP0)
1892 gen_op_ld_T0_A0(ot + s->mem_index);
1893 else
1894 gen_op_mov_TN_reg(ot, 0, op1);
1896 if (is_right) {
1897 switch (ot) {
1898 case OT_BYTE:
1899 gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1900 break;
1901 case OT_WORD:
1902 gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1903 break;
1904 case OT_LONG:
1905 gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1906 break;
1907 #ifdef TARGET_X86_64
1908 case OT_QUAD:
1909 gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1910 break;
1911 #endif
1913 } else {
1914 switch (ot) {
1915 case OT_BYTE:
1916 gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1917 break;
1918 case OT_WORD:
1919 gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1920 break;
1921 case OT_LONG:
1922 gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1923 break;
1924 #ifdef TARGET_X86_64
1925 case OT_QUAD:
1926 gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1927 break;
1928 #endif
1931 /* store */
1932 if (op1 == OR_TMP0)
1933 gen_op_st_T0_A0(ot + s->mem_index);
1934 else
1935 gen_op_mov_reg_T0(ot, op1);
1938 /* XXX: add faster immediate case */
1939 static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
1940 bool is_right, TCGv count_in)
1942 target_ulong mask = (ot == OT_QUAD ? 63 : 31);
1943 TCGv count;
1945 /* load */
1946 if (op1 == OR_TMP0) {
1947 gen_op_ld_T0_A0(ot + s->mem_index);
1948 } else {
1949 gen_op_mov_TN_reg(ot, 0, op1);
1952 count = tcg_temp_new();
1953 tcg_gen_andi_tl(count, count_in, mask);
1955 switch (ot) {
1956 case OT_WORD:
1957 /* Note: we implement the Intel behaviour for shift count > 16.
1958 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1959 portion by constructing it as a 32-bit value. */
1960 if (is_right) {
1961 tcg_gen_deposit_tl(cpu_tmp0, cpu_T[0], cpu_T[1], 16, 16);
1962 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1963 tcg_gen_mov_tl(cpu_T[0], cpu_tmp0);
1964 } else {
1965 tcg_gen_deposit_tl(cpu_T[1], cpu_T[0], cpu_T[1], 16, 16);
1967 /* FALLTHRU */
1968 #ifdef TARGET_X86_64
1969 case OT_LONG:
1970 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1971 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1972 if (is_right) {
1973 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
1974 tcg_gen_shr_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1975 tcg_gen_shr_i64(cpu_T[0], cpu_T[0], count);
1976 } else {
1977 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[1], cpu_T[0]);
1978 tcg_gen_shl_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1979 tcg_gen_shl_i64(cpu_T[0], cpu_T[0], count);
1980 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1981 tcg_gen_shri_i64(cpu_T[0], cpu_T[0], 32);
1983 break;
1984 #endif
1985 default:
1986 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1987 if (is_right) {
1988 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1990 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1991 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], count);
1992 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
1993 } else {
1994 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1995 if (ot == OT_WORD) {
1996 /* Only needed if count > 16, for Intel behaviour. */
1997 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1998 tcg_gen_shr_tl(cpu_tmp4, cpu_T[1], cpu_tmp4);
1999 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
2002 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
2003 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], count);
2004 tcg_gen_shr_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
2006 tcg_gen_movi_tl(cpu_tmp4, 0);
2007 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[1], count, cpu_tmp4,
2008 cpu_tmp4, cpu_T[1]);
2009 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
2010 break;
2013 /* store */
2014 if (op1 == OR_TMP0) {
2015 gen_op_st_T0_A0(ot + s->mem_index);
2016 } else {
2017 gen_op_mov_reg_T0(ot, op1);
2020 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, count, is_right);
2021 tcg_temp_free(count);
2024 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
2026 if (s != OR_TMP1)
2027 gen_op_mov_TN_reg(ot, 1, s);
2028 switch(op) {
2029 case OP_ROL:
2030 gen_rot_rm_T1(s1, ot, d, 0);
2031 break;
2032 case OP_ROR:
2033 gen_rot_rm_T1(s1, ot, d, 1);
2034 break;
2035 case OP_SHL:
2036 case OP_SHL1:
2037 gen_shift_rm_T1(s1, ot, d, 0, 0);
2038 break;
2039 case OP_SHR:
2040 gen_shift_rm_T1(s1, ot, d, 1, 0);
2041 break;
2042 case OP_SAR:
2043 gen_shift_rm_T1(s1, ot, d, 1, 1);
2044 break;
2045 case OP_RCL:
2046 gen_rotc_rm_T1(s1, ot, d, 0);
2047 break;
2048 case OP_RCR:
2049 gen_rotc_rm_T1(s1, ot, d, 1);
2050 break;
2054 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
2056 switch(op) {
2057 case OP_ROL:
2058 gen_rot_rm_im(s1, ot, d, c, 0);
2059 break;
2060 case OP_ROR:
2061 gen_rot_rm_im(s1, ot, d, c, 1);
2062 break;
2063 case OP_SHL:
2064 case OP_SHL1:
2065 gen_shift_rm_im(s1, ot, d, c, 0, 0);
2066 break;
2067 case OP_SHR:
2068 gen_shift_rm_im(s1, ot, d, c, 1, 0);
2069 break;
2070 case OP_SAR:
2071 gen_shift_rm_im(s1, ot, d, c, 1, 1);
2072 break;
2073 default:
2074 /* currently not optimized */
2075 gen_op_movl_T1_im(c);
2076 gen_shift(s1, op, ot, d, OR_TMP1);
2077 break;
2081 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm,
2082 int *reg_ptr, int *offset_ptr)
2084 target_long disp;
2085 int havesib;
2086 int base;
2087 int index;
2088 int scale;
2089 int opreg;
2090 int mod, rm, code, override, must_add_seg;
2092 override = s->override;
2093 must_add_seg = s->addseg;
2094 if (override >= 0)
2095 must_add_seg = 1;
2096 mod = (modrm >> 6) & 3;
2097 rm = modrm & 7;
2099 if (s->aflag) {
2101 havesib = 0;
2102 base = rm;
2103 index = 0;
2104 scale = 0;
2106 if (base == 4) {
2107 havesib = 1;
2108 code = cpu_ldub_code(env, s->pc++);
2109 scale = (code >> 6) & 3;
2110 index = ((code >> 3) & 7) | REX_X(s);
2111 base = (code & 7);
2113 base |= REX_B(s);
2115 switch (mod) {
2116 case 0:
2117 if ((base & 7) == 5) {
2118 base = -1;
2119 disp = (int32_t)cpu_ldl_code(env, s->pc);
2120 s->pc += 4;
2121 if (CODE64(s) && !havesib) {
2122 disp += s->pc + s->rip_offset;
2124 } else {
2125 disp = 0;
2127 break;
2128 case 1:
2129 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2130 break;
2131 default:
2132 case 2:
2133 disp = (int32_t)cpu_ldl_code(env, s->pc);
2134 s->pc += 4;
2135 break;
2138 if (base >= 0) {
2139 /* for correct popl handling with esp */
2140 if (base == 4 && s->popl_esp_hack)
2141 disp += s->popl_esp_hack;
2142 #ifdef TARGET_X86_64
2143 if (s->aflag == 2) {
2144 gen_op_movq_A0_reg(base);
2145 if (disp != 0) {
2146 gen_op_addq_A0_im(disp);
2148 } else
2149 #endif
2151 gen_op_movl_A0_reg(base);
2152 if (disp != 0)
2153 gen_op_addl_A0_im(disp);
2155 } else {
2156 #ifdef TARGET_X86_64
2157 if (s->aflag == 2) {
2158 gen_op_movq_A0_im(disp);
2159 } else
2160 #endif
2162 gen_op_movl_A0_im(disp);
2165 /* index == 4 means no index */
2166 if (havesib && (index != 4)) {
2167 #ifdef TARGET_X86_64
2168 if (s->aflag == 2) {
2169 gen_op_addq_A0_reg_sN(scale, index);
2170 } else
2171 #endif
2173 gen_op_addl_A0_reg_sN(scale, index);
2176 if (must_add_seg) {
2177 if (override < 0) {
2178 if (base == R_EBP || base == R_ESP)
2179 override = R_SS;
2180 else
2181 override = R_DS;
2183 #ifdef TARGET_X86_64
2184 if (s->aflag == 2) {
2185 gen_op_addq_A0_seg(override);
2186 } else
2187 #endif
2189 gen_op_addl_A0_seg(s, override);
2192 } else {
2193 switch (mod) {
2194 case 0:
2195 if (rm == 6) {
2196 disp = cpu_lduw_code(env, s->pc);
2197 s->pc += 2;
2198 gen_op_movl_A0_im(disp);
2199 rm = 0; /* avoid SS override */
2200 goto no_rm;
2201 } else {
2202 disp = 0;
2204 break;
2205 case 1:
2206 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2207 break;
2208 default:
2209 case 2:
2210 disp = cpu_lduw_code(env, s->pc);
2211 s->pc += 2;
2212 break;
2214 switch(rm) {
2215 case 0:
2216 gen_op_movl_A0_reg(R_EBX);
2217 gen_op_addl_A0_reg_sN(0, R_ESI);
2218 break;
2219 case 1:
2220 gen_op_movl_A0_reg(R_EBX);
2221 gen_op_addl_A0_reg_sN(0, R_EDI);
2222 break;
2223 case 2:
2224 gen_op_movl_A0_reg(R_EBP);
2225 gen_op_addl_A0_reg_sN(0, R_ESI);
2226 break;
2227 case 3:
2228 gen_op_movl_A0_reg(R_EBP);
2229 gen_op_addl_A0_reg_sN(0, R_EDI);
2230 break;
2231 case 4:
2232 gen_op_movl_A0_reg(R_ESI);
2233 break;
2234 case 5:
2235 gen_op_movl_A0_reg(R_EDI);
2236 break;
2237 case 6:
2238 gen_op_movl_A0_reg(R_EBP);
2239 break;
2240 default:
2241 case 7:
2242 gen_op_movl_A0_reg(R_EBX);
2243 break;
2245 if (disp != 0)
2246 gen_op_addl_A0_im(disp);
2247 gen_op_andl_A0_ffff();
2248 no_rm:
2249 if (must_add_seg) {
2250 if (override < 0) {
2251 if (rm == 2 || rm == 3 || rm == 6)
2252 override = R_SS;
2253 else
2254 override = R_DS;
2256 gen_op_addl_A0_seg(s, override);
2260 opreg = OR_A0;
2261 disp = 0;
2262 *reg_ptr = opreg;
2263 *offset_ptr = disp;
2266 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2268 int mod, rm, base, code;
2270 mod = (modrm >> 6) & 3;
2271 if (mod == 3)
2272 return;
2273 rm = modrm & 7;
2275 if (s->aflag) {
2277 base = rm;
2279 if (base == 4) {
2280 code = cpu_ldub_code(env, s->pc++);
2281 base = (code & 7);
2284 switch (mod) {
2285 case 0:
2286 if (base == 5) {
2287 s->pc += 4;
2289 break;
2290 case 1:
2291 s->pc++;
2292 break;
2293 default:
2294 case 2:
2295 s->pc += 4;
2296 break;
2298 } else {
2299 switch (mod) {
2300 case 0:
2301 if (rm == 6) {
2302 s->pc += 2;
2304 break;
2305 case 1:
2306 s->pc++;
2307 break;
2308 default:
2309 case 2:
2310 s->pc += 2;
2311 break;
2316 /* used for LEA and MOV AX, mem */
2317 static void gen_add_A0_ds_seg(DisasContext *s)
2319 int override, must_add_seg;
2320 must_add_seg = s->addseg;
2321 override = R_DS;
2322 if (s->override >= 0) {
2323 override = s->override;
2324 must_add_seg = 1;
2326 if (must_add_seg) {
2327 #ifdef TARGET_X86_64
2328 if (CODE64(s)) {
2329 gen_op_addq_A0_seg(override);
2330 } else
2331 #endif
2333 gen_op_addl_A0_seg(s, override);
2338 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2339 OR_TMP0 */
2340 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2341 int ot, int reg, int is_store)
2343 int mod, rm, opreg, disp;
2345 mod = (modrm >> 6) & 3;
2346 rm = (modrm & 7) | REX_B(s);
2347 if (mod == 3) {
2348 if (is_store) {
2349 if (reg != OR_TMP0)
2350 gen_op_mov_TN_reg(ot, 0, reg);
2351 gen_op_mov_reg_T0(ot, rm);
2352 } else {
2353 gen_op_mov_TN_reg(ot, 0, rm);
2354 if (reg != OR_TMP0)
2355 gen_op_mov_reg_T0(ot, reg);
2357 } else {
2358 gen_lea_modrm(env, s, modrm, &opreg, &disp);
2359 if (is_store) {
2360 if (reg != OR_TMP0)
2361 gen_op_mov_TN_reg(ot, 0, reg);
2362 gen_op_st_T0_A0(ot + s->mem_index);
2363 } else {
2364 gen_op_ld_T0_A0(ot + s->mem_index);
2365 if (reg != OR_TMP0)
2366 gen_op_mov_reg_T0(ot, reg);
2371 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
2373 uint32_t ret;
2375 switch(ot) {
2376 case OT_BYTE:
2377 ret = cpu_ldub_code(env, s->pc);
2378 s->pc++;
2379 break;
2380 case OT_WORD:
2381 ret = cpu_lduw_code(env, s->pc);
2382 s->pc += 2;
2383 break;
2384 default:
2385 case OT_LONG:
2386 ret = cpu_ldl_code(env, s->pc);
2387 s->pc += 4;
2388 break;
2390 return ret;
2393 static inline int insn_const_size(unsigned int ot)
2395 if (ot <= OT_LONG)
2396 return 1 << ot;
2397 else
2398 return 4;
2401 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2403 TranslationBlock *tb;
2404 target_ulong pc;
2406 pc = s->cs_base + eip;
2407 tb = s->tb;
2408 /* NOTE: we handle the case where the TB spans two pages here */
2409 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2410 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2411 /* jump to same page: we can use a direct jump */
2412 tcg_gen_goto_tb(tb_num);
2413 gen_jmp_im(eip);
2414 tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
2415 } else {
2416 /* jump to another page: currently not optimized */
2417 gen_jmp_im(eip);
2418 gen_eob(s);
2422 static inline void gen_jcc(DisasContext *s, int b,
2423 target_ulong val, target_ulong next_eip)
2425 int l1, l2;
2427 if (s->jmp_opt) {
2428 l1 = gen_new_label();
2429 gen_jcc1(s, b, l1);
2431 gen_goto_tb(s, 0, next_eip);
2433 gen_set_label(l1);
2434 gen_goto_tb(s, 1, val);
2435 s->is_jmp = DISAS_TB_JUMP;
2436 } else {
2437 l1 = gen_new_label();
2438 l2 = gen_new_label();
2439 gen_jcc1(s, b, l1);
2441 gen_jmp_im(next_eip);
2442 tcg_gen_br(l2);
2444 gen_set_label(l1);
2445 gen_jmp_im(val);
2446 gen_set_label(l2);
2447 gen_eob(s);
2451 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, int ot, int b,
2452 int modrm, int reg)
2454 CCPrepare cc;
2456 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2458 cc = gen_prepare_cc(s, b, cpu_T[1]);
2459 if (cc.mask != -1) {
2460 TCGv t0 = tcg_temp_new();
2461 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2462 cc.reg = t0;
2464 if (!cc.use_reg2) {
2465 cc.reg2 = tcg_const_tl(cc.imm);
2468 tcg_gen_movcond_tl(cc.cond, cpu_T[0], cc.reg, cc.reg2,
2469 cpu_T[0], cpu_regs[reg]);
2470 gen_op_mov_reg_T0(ot, reg);
2472 if (cc.mask != -1) {
2473 tcg_temp_free(cc.reg);
2475 if (!cc.use_reg2) {
2476 tcg_temp_free(cc.reg2);
2480 static inline void gen_op_movl_T0_seg(int seg_reg)
2482 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
2483 offsetof(CPUX86State,segs[seg_reg].selector));
2486 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2488 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
2489 tcg_gen_st32_tl(cpu_T[0], cpu_env,
2490 offsetof(CPUX86State,segs[seg_reg].selector));
2491 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
2492 tcg_gen_st_tl(cpu_T[0], cpu_env,
2493 offsetof(CPUX86State,segs[seg_reg].base));
2496 /* move T0 to seg_reg and compute if the CPU state may change. Never
2497 call this function with seg_reg == R_CS */
2498 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2500 if (s->pe && !s->vm86) {
2501 /* XXX: optimize by finding processor state dynamically */
2502 gen_update_cc_op(s);
2503 gen_jmp_im(cur_eip);
2504 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2505 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
2506 /* abort translation because the addseg value may change or
2507 because ss32 may change. For R_SS, translation must always
2508 stop as a special handling must be done to disable hardware
2509 interrupts for the next instruction */
2510 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
2511 s->is_jmp = DISAS_TB_JUMP;
2512 } else {
2513 gen_op_movl_seg_T0_vm(seg_reg);
2514 if (seg_reg == R_SS)
2515 s->is_jmp = DISAS_TB_JUMP;
2519 static inline int svm_is_rep(int prefixes)
2521 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2524 static inline void
2525 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2526 uint32_t type, uint64_t param)
2528 /* no SVM activated; fast case */
2529 if (likely(!(s->flags & HF_SVMI_MASK)))
2530 return;
2531 gen_update_cc_op(s);
2532 gen_jmp_im(pc_start - s->cs_base);
2533 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2534 tcg_const_i64(param));
2537 static inline void
2538 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2540 gen_svm_check_intercept_param(s, pc_start, type, 0);
2543 static inline void gen_stack_update(DisasContext *s, int addend)
2545 #ifdef TARGET_X86_64
2546 if (CODE64(s)) {
2547 gen_op_add_reg_im(2, R_ESP, addend);
2548 } else
2549 #endif
2550 if (s->ss32) {
2551 gen_op_add_reg_im(1, R_ESP, addend);
2552 } else {
2553 gen_op_add_reg_im(0, R_ESP, addend);
2557 /* generate a push. It depends on ss32, addseg and dflag */
2558 static void gen_push_T0(DisasContext *s)
2560 #ifdef TARGET_X86_64
2561 if (CODE64(s)) {
2562 gen_op_movq_A0_reg(R_ESP);
2563 if (s->dflag) {
2564 gen_op_addq_A0_im(-8);
2565 gen_op_st_T0_A0(OT_QUAD + s->mem_index);
2566 } else {
2567 gen_op_addq_A0_im(-2);
2568 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2570 gen_op_mov_reg_A0(2, R_ESP);
2571 } else
2572 #endif
2574 gen_op_movl_A0_reg(R_ESP);
2575 if (!s->dflag)
2576 gen_op_addl_A0_im(-2);
2577 else
2578 gen_op_addl_A0_im(-4);
2579 if (s->ss32) {
2580 if (s->addseg) {
2581 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2582 gen_op_addl_A0_seg(s, R_SS);
2584 } else {
2585 gen_op_andl_A0_ffff();
2586 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2587 gen_op_addl_A0_seg(s, R_SS);
2589 gen_op_st_T0_A0(s->dflag + 1 + s->mem_index);
2590 if (s->ss32 && !s->addseg)
2591 gen_op_mov_reg_A0(1, R_ESP);
2592 else
2593 gen_op_mov_reg_T1(s->ss32 + 1, R_ESP);
2597 /* generate a push. It depends on ss32, addseg and dflag */
2598 /* slower version for T1, only used for call Ev */
2599 static void gen_push_T1(DisasContext *s)
2601 #ifdef TARGET_X86_64
2602 if (CODE64(s)) {
2603 gen_op_movq_A0_reg(R_ESP);
2604 if (s->dflag) {
2605 gen_op_addq_A0_im(-8);
2606 gen_op_st_T1_A0(OT_QUAD + s->mem_index);
2607 } else {
2608 gen_op_addq_A0_im(-2);
2609 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2611 gen_op_mov_reg_A0(2, R_ESP);
2612 } else
2613 #endif
2615 gen_op_movl_A0_reg(R_ESP);
2616 if (!s->dflag)
2617 gen_op_addl_A0_im(-2);
2618 else
2619 gen_op_addl_A0_im(-4);
2620 if (s->ss32) {
2621 if (s->addseg) {
2622 gen_op_addl_A0_seg(s, R_SS);
2624 } else {
2625 gen_op_andl_A0_ffff();
2626 gen_op_addl_A0_seg(s, R_SS);
2628 gen_op_st_T1_A0(s->dflag + 1 + s->mem_index);
2630 if (s->ss32 && !s->addseg)
2631 gen_op_mov_reg_A0(1, R_ESP);
2632 else
2633 gen_stack_update(s, (-2) << s->dflag);
2637 /* two step pop is necessary for precise exceptions */
2638 static void gen_pop_T0(DisasContext *s)
2640 #ifdef TARGET_X86_64
2641 if (CODE64(s)) {
2642 gen_op_movq_A0_reg(R_ESP);
2643 gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index);
2644 } else
2645 #endif
2647 gen_op_movl_A0_reg(R_ESP);
2648 if (s->ss32) {
2649 if (s->addseg)
2650 gen_op_addl_A0_seg(s, R_SS);
2651 } else {
2652 gen_op_andl_A0_ffff();
2653 gen_op_addl_A0_seg(s, R_SS);
2655 gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index);
2659 static void gen_pop_update(DisasContext *s)
2661 #ifdef TARGET_X86_64
2662 if (CODE64(s) && s->dflag) {
2663 gen_stack_update(s, 8);
2664 } else
2665 #endif
2667 gen_stack_update(s, 2 << s->dflag);
2671 static void gen_stack_A0(DisasContext *s)
2673 gen_op_movl_A0_reg(R_ESP);
2674 if (!s->ss32)
2675 gen_op_andl_A0_ffff();
2676 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2677 if (s->addseg)
2678 gen_op_addl_A0_seg(s, R_SS);
2681 /* NOTE: wrap around in 16 bit not fully handled */
2682 static void gen_pusha(DisasContext *s)
2684 int i;
2685 gen_op_movl_A0_reg(R_ESP);
2686 gen_op_addl_A0_im(-16 << s->dflag);
2687 if (!s->ss32)
2688 gen_op_andl_A0_ffff();
2689 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2690 if (s->addseg)
2691 gen_op_addl_A0_seg(s, R_SS);
2692 for(i = 0;i < 8; i++) {
2693 gen_op_mov_TN_reg(OT_LONG, 0, 7 - i);
2694 gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index);
2695 gen_op_addl_A0_im(2 << s->dflag);
2697 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2700 /* NOTE: wrap around in 16 bit not fully handled */
2701 static void gen_popa(DisasContext *s)
2703 int i;
2704 gen_op_movl_A0_reg(R_ESP);
2705 if (!s->ss32)
2706 gen_op_andl_A0_ffff();
2707 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2708 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 << s->dflag);
2709 if (s->addseg)
2710 gen_op_addl_A0_seg(s, R_SS);
2711 for(i = 0;i < 8; i++) {
2712 /* ESP is not reloaded */
2713 if (i != 3) {
2714 gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index);
2715 gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i);
2717 gen_op_addl_A0_im(2 << s->dflag);
2719 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2722 static void gen_enter(DisasContext *s, int esp_addend, int level)
2724 int ot, opsize;
2726 level &= 0x1f;
2727 #ifdef TARGET_X86_64
2728 if (CODE64(s)) {
2729 ot = s->dflag ? OT_QUAD : OT_WORD;
2730 opsize = 1 << ot;
2732 gen_op_movl_A0_reg(R_ESP);
2733 gen_op_addq_A0_im(-opsize);
2734 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2736 /* push bp */
2737 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2738 gen_op_st_T0_A0(ot + s->mem_index);
2739 if (level) {
2740 /* XXX: must save state */
2741 gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
2742 tcg_const_i32((ot == OT_QUAD)),
2743 cpu_T[1]);
2745 gen_op_mov_reg_T1(ot, R_EBP);
2746 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2747 gen_op_mov_reg_T1(OT_QUAD, R_ESP);
2748 } else
2749 #endif
2751 ot = s->dflag + OT_WORD;
2752 opsize = 2 << s->dflag;
2754 gen_op_movl_A0_reg(R_ESP);
2755 gen_op_addl_A0_im(-opsize);
2756 if (!s->ss32)
2757 gen_op_andl_A0_ffff();
2758 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2759 if (s->addseg)
2760 gen_op_addl_A0_seg(s, R_SS);
2761 /* push bp */
2762 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2763 gen_op_st_T0_A0(ot + s->mem_index);
2764 if (level) {
2765 /* XXX: must save state */
2766 gen_helper_enter_level(cpu_env, tcg_const_i32(level),
2767 tcg_const_i32(s->dflag),
2768 cpu_T[1]);
2770 gen_op_mov_reg_T1(ot, R_EBP);
2771 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2772 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2776 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2778 gen_update_cc_op(s);
2779 gen_jmp_im(cur_eip);
2780 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
2781 s->is_jmp = DISAS_TB_JUMP;
2784 /* an interrupt is different from an exception because of the
2785 privilege checks */
2786 static void gen_interrupt(DisasContext *s, int intno,
2787 target_ulong cur_eip, target_ulong next_eip)
2789 gen_update_cc_op(s);
2790 gen_jmp_im(cur_eip);
2791 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2792 tcg_const_i32(next_eip - cur_eip));
2793 s->is_jmp = DISAS_TB_JUMP;
2796 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2798 gen_update_cc_op(s);
2799 gen_jmp_im(cur_eip);
2800 gen_helper_debug(cpu_env);
2801 s->is_jmp = DISAS_TB_JUMP;
2804 /* generate a generic end of block. Trace exception is also generated
2805 if needed */
2806 static void gen_eob(DisasContext *s)
2808 gen_update_cc_op(s);
2809 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2810 gen_helper_reset_inhibit_irq(cpu_env);
2812 if (s->tb->flags & HF_RF_MASK) {
2813 gen_helper_reset_rf(cpu_env);
2815 if (s->singlestep_enabled) {
2816 gen_helper_debug(cpu_env);
2817 } else if (s->tf) {
2818 gen_helper_single_step(cpu_env);
2819 } else {
2820 tcg_gen_exit_tb(0);
2822 s->is_jmp = DISAS_TB_JUMP;
2825 /* generate a jump to eip. No segment change must happen before as a
2826 direct call to the next block may occur */
2827 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2829 gen_update_cc_op(s);
2830 set_cc_op(s, CC_OP_DYNAMIC);
2831 if (s->jmp_opt) {
2832 gen_goto_tb(s, tb_num, eip);
2833 s->is_jmp = DISAS_TB_JUMP;
2834 } else {
2835 gen_jmp_im(eip);
2836 gen_eob(s);
2840 static void gen_jmp(DisasContext *s, target_ulong eip)
2842 gen_jmp_tb(s, eip, 0);
2845 static inline void gen_ldq_env_A0(int idx, int offset)
2847 int mem_index = (idx >> 2) - 1;
2848 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
2849 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2852 static inline void gen_stq_env_A0(int idx, int offset)
2854 int mem_index = (idx >> 2) - 1;
2855 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2856 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
2859 static inline void gen_ldo_env_A0(int idx, int offset)
2861 int mem_index = (idx >> 2) - 1;
2862 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
2863 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2864 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2865 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_tmp0, mem_index);
2866 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2869 static inline void gen_sto_env_A0(int idx, int offset)
2871 int mem_index = (idx >> 2) - 1;
2872 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2873 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
2874 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2875 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2876 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_tmp0, mem_index);
2879 static inline void gen_op_movo(int d_offset, int s_offset)
2881 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2882 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2883 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8);
2884 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8);
2887 static inline void gen_op_movq(int d_offset, int s_offset)
2889 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2890 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2893 static inline void gen_op_movl(int d_offset, int s_offset)
2895 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2896 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2899 static inline void gen_op_movq_env_0(int d_offset)
2901 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2902 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2905 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2906 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2907 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2908 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2909 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2910 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2911 TCGv_i32 val);
2912 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2913 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2914 TCGv val);
2916 #define SSE_SPECIAL ((void *)1)
2917 #define SSE_DUMMY ((void *)2)
2919 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2920 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2921 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2923 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2924 /* 3DNow! extensions */
2925 [0x0e] = { SSE_DUMMY }, /* femms */
2926 [0x0f] = { SSE_DUMMY }, /* pf... */
2927 /* pure SSE operations */
2928 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2929 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2930 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2931 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2932 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2933 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2934 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2935 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2937 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2938 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2939 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2940 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2941 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2942 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2943 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2944 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2945 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2946 [0x51] = SSE_FOP(sqrt),
2947 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2948 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2949 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2950 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2951 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2952 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2953 [0x58] = SSE_FOP(add),
2954 [0x59] = SSE_FOP(mul),
2955 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2956 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2957 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2958 [0x5c] = SSE_FOP(sub),
2959 [0x5d] = SSE_FOP(min),
2960 [0x5e] = SSE_FOP(div),
2961 [0x5f] = SSE_FOP(max),
2963 [0xc2] = SSE_FOP(cmpeq),
2964 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2965 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2967 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2968 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2969 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2971 /* MMX ops and their SSE extensions */
2972 [0x60] = MMX_OP2(punpcklbw),
2973 [0x61] = MMX_OP2(punpcklwd),
2974 [0x62] = MMX_OP2(punpckldq),
2975 [0x63] = MMX_OP2(packsswb),
2976 [0x64] = MMX_OP2(pcmpgtb),
2977 [0x65] = MMX_OP2(pcmpgtw),
2978 [0x66] = MMX_OP2(pcmpgtl),
2979 [0x67] = MMX_OP2(packuswb),
2980 [0x68] = MMX_OP2(punpckhbw),
2981 [0x69] = MMX_OP2(punpckhwd),
2982 [0x6a] = MMX_OP2(punpckhdq),
2983 [0x6b] = MMX_OP2(packssdw),
2984 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2985 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2986 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2987 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2988 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2989 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2990 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2991 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2992 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2993 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2994 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2995 [0x74] = MMX_OP2(pcmpeqb),
2996 [0x75] = MMX_OP2(pcmpeqw),
2997 [0x76] = MMX_OP2(pcmpeql),
2998 [0x77] = { SSE_DUMMY }, /* emms */
2999 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
3000 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
3001 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
3002 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
3003 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
3004 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
3005 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
3006 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
3007 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
3008 [0xd1] = MMX_OP2(psrlw),
3009 [0xd2] = MMX_OP2(psrld),
3010 [0xd3] = MMX_OP2(psrlq),
3011 [0xd4] = MMX_OP2(paddq),
3012 [0xd5] = MMX_OP2(pmullw),
3013 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
3014 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
3015 [0xd8] = MMX_OP2(psubusb),
3016 [0xd9] = MMX_OP2(psubusw),
3017 [0xda] = MMX_OP2(pminub),
3018 [0xdb] = MMX_OP2(pand),
3019 [0xdc] = MMX_OP2(paddusb),
3020 [0xdd] = MMX_OP2(paddusw),
3021 [0xde] = MMX_OP2(pmaxub),
3022 [0xdf] = MMX_OP2(pandn),
3023 [0xe0] = MMX_OP2(pavgb),
3024 [0xe1] = MMX_OP2(psraw),
3025 [0xe2] = MMX_OP2(psrad),
3026 [0xe3] = MMX_OP2(pavgw),
3027 [0xe4] = MMX_OP2(pmulhuw),
3028 [0xe5] = MMX_OP2(pmulhw),
3029 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
3030 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
3031 [0xe8] = MMX_OP2(psubsb),
3032 [0xe9] = MMX_OP2(psubsw),
3033 [0xea] = MMX_OP2(pminsw),
3034 [0xeb] = MMX_OP2(por),
3035 [0xec] = MMX_OP2(paddsb),
3036 [0xed] = MMX_OP2(paddsw),
3037 [0xee] = MMX_OP2(pmaxsw),
3038 [0xef] = MMX_OP2(pxor),
3039 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
3040 [0xf1] = MMX_OP2(psllw),
3041 [0xf2] = MMX_OP2(pslld),
3042 [0xf3] = MMX_OP2(psllq),
3043 [0xf4] = MMX_OP2(pmuludq),
3044 [0xf5] = MMX_OP2(pmaddwd),
3045 [0xf6] = MMX_OP2(psadbw),
3046 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
3047 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
3048 [0xf8] = MMX_OP2(psubb),
3049 [0xf9] = MMX_OP2(psubw),
3050 [0xfa] = MMX_OP2(psubl),
3051 [0xfb] = MMX_OP2(psubq),
3052 [0xfc] = MMX_OP2(paddb),
3053 [0xfd] = MMX_OP2(paddw),
3054 [0xfe] = MMX_OP2(paddl),
3057 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
3058 [0 + 2] = MMX_OP2(psrlw),
3059 [0 + 4] = MMX_OP2(psraw),
3060 [0 + 6] = MMX_OP2(psllw),
3061 [8 + 2] = MMX_OP2(psrld),
3062 [8 + 4] = MMX_OP2(psrad),
3063 [8 + 6] = MMX_OP2(pslld),
3064 [16 + 2] = MMX_OP2(psrlq),
3065 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
3066 [16 + 6] = MMX_OP2(psllq),
3067 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
3070 static const SSEFunc_0_epi sse_op_table3ai[] = {
3071 gen_helper_cvtsi2ss,
3072 gen_helper_cvtsi2sd
3075 #ifdef TARGET_X86_64
3076 static const SSEFunc_0_epl sse_op_table3aq[] = {
3077 gen_helper_cvtsq2ss,
3078 gen_helper_cvtsq2sd
3080 #endif
3082 static const SSEFunc_i_ep sse_op_table3bi[] = {
3083 gen_helper_cvttss2si,
3084 gen_helper_cvtss2si,
3085 gen_helper_cvttsd2si,
3086 gen_helper_cvtsd2si
3089 #ifdef TARGET_X86_64
3090 static const SSEFunc_l_ep sse_op_table3bq[] = {
3091 gen_helper_cvttss2sq,
3092 gen_helper_cvtss2sq,
3093 gen_helper_cvttsd2sq,
3094 gen_helper_cvtsd2sq
3096 #endif
3098 static const SSEFunc_0_epp sse_op_table4[8][4] = {
3099 SSE_FOP(cmpeq),
3100 SSE_FOP(cmplt),
3101 SSE_FOP(cmple),
3102 SSE_FOP(cmpunord),
3103 SSE_FOP(cmpneq),
3104 SSE_FOP(cmpnlt),
3105 SSE_FOP(cmpnle),
3106 SSE_FOP(cmpord),
3109 static const SSEFunc_0_epp sse_op_table5[256] = {
3110 [0x0c] = gen_helper_pi2fw,
3111 [0x0d] = gen_helper_pi2fd,
3112 [0x1c] = gen_helper_pf2iw,
3113 [0x1d] = gen_helper_pf2id,
3114 [0x8a] = gen_helper_pfnacc,
3115 [0x8e] = gen_helper_pfpnacc,
3116 [0x90] = gen_helper_pfcmpge,
3117 [0x94] = gen_helper_pfmin,
3118 [0x96] = gen_helper_pfrcp,
3119 [0x97] = gen_helper_pfrsqrt,
3120 [0x9a] = gen_helper_pfsub,
3121 [0x9e] = gen_helper_pfadd,
3122 [0xa0] = gen_helper_pfcmpgt,
3123 [0xa4] = gen_helper_pfmax,
3124 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
3125 [0xa7] = gen_helper_movq, /* pfrsqit1 */
3126 [0xaa] = gen_helper_pfsubr,
3127 [0xae] = gen_helper_pfacc,
3128 [0xb0] = gen_helper_pfcmpeq,
3129 [0xb4] = gen_helper_pfmul,
3130 [0xb6] = gen_helper_movq, /* pfrcpit2 */
3131 [0xb7] = gen_helper_pmulhrw_mmx,
3132 [0xbb] = gen_helper_pswapd,
3133 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
3136 struct SSEOpHelper_epp {
3137 SSEFunc_0_epp op[2];
3138 uint32_t ext_mask;
3141 struct SSEOpHelper_eppi {
3142 SSEFunc_0_eppi op[2];
3143 uint32_t ext_mask;
3146 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
3147 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
3148 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
3149 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
3151 static const struct SSEOpHelper_epp sse_op_table6[256] = {
3152 [0x00] = SSSE3_OP(pshufb),
3153 [0x01] = SSSE3_OP(phaddw),
3154 [0x02] = SSSE3_OP(phaddd),
3155 [0x03] = SSSE3_OP(phaddsw),
3156 [0x04] = SSSE3_OP(pmaddubsw),
3157 [0x05] = SSSE3_OP(phsubw),
3158 [0x06] = SSSE3_OP(phsubd),
3159 [0x07] = SSSE3_OP(phsubsw),
3160 [0x08] = SSSE3_OP(psignb),
3161 [0x09] = SSSE3_OP(psignw),
3162 [0x0a] = SSSE3_OP(psignd),
3163 [0x0b] = SSSE3_OP(pmulhrsw),
3164 [0x10] = SSE41_OP(pblendvb),
3165 [0x14] = SSE41_OP(blendvps),
3166 [0x15] = SSE41_OP(blendvpd),
3167 [0x17] = SSE41_OP(ptest),
3168 [0x1c] = SSSE3_OP(pabsb),
3169 [0x1d] = SSSE3_OP(pabsw),
3170 [0x1e] = SSSE3_OP(pabsd),
3171 [0x20] = SSE41_OP(pmovsxbw),
3172 [0x21] = SSE41_OP(pmovsxbd),
3173 [0x22] = SSE41_OP(pmovsxbq),
3174 [0x23] = SSE41_OP(pmovsxwd),
3175 [0x24] = SSE41_OP(pmovsxwq),
3176 [0x25] = SSE41_OP(pmovsxdq),
3177 [0x28] = SSE41_OP(pmuldq),
3178 [0x29] = SSE41_OP(pcmpeqq),
3179 [0x2a] = SSE41_SPECIAL, /* movntqda */
3180 [0x2b] = SSE41_OP(packusdw),
3181 [0x30] = SSE41_OP(pmovzxbw),
3182 [0x31] = SSE41_OP(pmovzxbd),
3183 [0x32] = SSE41_OP(pmovzxbq),
3184 [0x33] = SSE41_OP(pmovzxwd),
3185 [0x34] = SSE41_OP(pmovzxwq),
3186 [0x35] = SSE41_OP(pmovzxdq),
3187 [0x37] = SSE42_OP(pcmpgtq),
3188 [0x38] = SSE41_OP(pminsb),
3189 [0x39] = SSE41_OP(pminsd),
3190 [0x3a] = SSE41_OP(pminuw),
3191 [0x3b] = SSE41_OP(pminud),
3192 [0x3c] = SSE41_OP(pmaxsb),
3193 [0x3d] = SSE41_OP(pmaxsd),
3194 [0x3e] = SSE41_OP(pmaxuw),
3195 [0x3f] = SSE41_OP(pmaxud),
3196 [0x40] = SSE41_OP(pmulld),
3197 [0x41] = SSE41_OP(phminposuw),
3200 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
3201 [0x08] = SSE41_OP(roundps),
3202 [0x09] = SSE41_OP(roundpd),
3203 [0x0a] = SSE41_OP(roundss),
3204 [0x0b] = SSE41_OP(roundsd),
3205 [0x0c] = SSE41_OP(blendps),
3206 [0x0d] = SSE41_OP(blendpd),
3207 [0x0e] = SSE41_OP(pblendw),
3208 [0x0f] = SSSE3_OP(palignr),
3209 [0x14] = SSE41_SPECIAL, /* pextrb */
3210 [0x15] = SSE41_SPECIAL, /* pextrw */
3211 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3212 [0x17] = SSE41_SPECIAL, /* extractps */
3213 [0x20] = SSE41_SPECIAL, /* pinsrb */
3214 [0x21] = SSE41_SPECIAL, /* insertps */
3215 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3216 [0x40] = SSE41_OP(dpps),
3217 [0x41] = SSE41_OP(dppd),
3218 [0x42] = SSE41_OP(mpsadbw),
3219 [0x60] = SSE42_OP(pcmpestrm),
3220 [0x61] = SSE42_OP(pcmpestri),
3221 [0x62] = SSE42_OP(pcmpistrm),
3222 [0x63] = SSE42_OP(pcmpistri),
3225 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3226 target_ulong pc_start, int rex_r)
3228 int b1, op1_offset, op2_offset, is_xmm, val, ot;
3229 int modrm, mod, rm, reg, reg_addr, offset_addr;
3230 SSEFunc_0_epp sse_fn_epp;
3231 SSEFunc_0_eppi sse_fn_eppi;
3232 SSEFunc_0_ppi sse_fn_ppi;
3233 SSEFunc_0_eppt sse_fn_eppt;
3235 b &= 0xff;
3236 if (s->prefix & PREFIX_DATA)
3237 b1 = 1;
3238 else if (s->prefix & PREFIX_REPZ)
3239 b1 = 2;
3240 else if (s->prefix & PREFIX_REPNZ)
3241 b1 = 3;
3242 else
3243 b1 = 0;
3244 sse_fn_epp = sse_op_table1[b][b1];
3245 if (!sse_fn_epp) {
3246 goto illegal_op;
3248 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3249 is_xmm = 1;
3250 } else {
3251 if (b1 == 0) {
3252 /* MMX case */
3253 is_xmm = 0;
3254 } else {
3255 is_xmm = 1;
3258 /* simple MMX/SSE operation */
3259 if (s->flags & HF_TS_MASK) {
3260 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3261 return;
3263 if (s->flags & HF_EM_MASK) {
3264 illegal_op:
3265 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
3266 return;
3268 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
3269 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
3270 goto illegal_op;
3271 if (b == 0x0e) {
3272 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3273 goto illegal_op;
3274 /* femms */
3275 gen_helper_emms(cpu_env);
3276 return;
3278 if (b == 0x77) {
3279 /* emms */
3280 gen_helper_emms(cpu_env);
3281 return;
3283 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3284 the static cpu state) */
3285 if (!is_xmm) {
3286 gen_helper_enter_mmx(cpu_env);
3289 modrm = cpu_ldub_code(env, s->pc++);
3290 reg = ((modrm >> 3) & 7);
3291 if (is_xmm)
3292 reg |= rex_r;
3293 mod = (modrm >> 6) & 3;
3294 if (sse_fn_epp == SSE_SPECIAL) {
3295 b |= (b1 << 8);
3296 switch(b) {
3297 case 0x0e7: /* movntq */
3298 if (mod == 3)
3299 goto illegal_op;
3300 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3301 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
3302 break;
3303 case 0x1e7: /* movntdq */
3304 case 0x02b: /* movntps */
3305 case 0x12b: /* movntps */
3306 if (mod == 3)
3307 goto illegal_op;
3308 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3309 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3310 break;
3311 case 0x3f0: /* lddqu */
3312 if (mod == 3)
3313 goto illegal_op;
3314 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3315 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3316 break;
3317 case 0x22b: /* movntss */
3318 case 0x32b: /* movntsd */
3319 if (mod == 3)
3320 goto illegal_op;
3321 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3322 if (b1 & 1) {
3323 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,
3324 xmm_regs[reg]));
3325 } else {
3326 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3327 xmm_regs[reg].XMM_L(0)));
3328 gen_op_st_T0_A0(OT_LONG + s->mem_index);
3330 break;
3331 case 0x6e: /* movd mm, ea */
3332 #ifdef TARGET_X86_64
3333 if (s->dflag == 2) {
3334 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
3335 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3336 } else
3337 #endif
3339 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
3340 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3341 offsetof(CPUX86State,fpregs[reg].mmx));
3342 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3343 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
3345 break;
3346 case 0x16e: /* movd xmm, ea */
3347 #ifdef TARGET_X86_64
3348 if (s->dflag == 2) {
3349 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
3350 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3351 offsetof(CPUX86State,xmm_regs[reg]));
3352 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
3353 } else
3354 #endif
3356 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
3357 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3358 offsetof(CPUX86State,xmm_regs[reg]));
3359 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3360 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
3362 break;
3363 case 0x6f: /* movq mm, ea */
3364 if (mod != 3) {
3365 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3366 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
3367 } else {
3368 rm = (modrm & 7);
3369 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3370 offsetof(CPUX86State,fpregs[rm].mmx));
3371 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3372 offsetof(CPUX86State,fpregs[reg].mmx));
3374 break;
3375 case 0x010: /* movups */
3376 case 0x110: /* movupd */
3377 case 0x028: /* movaps */
3378 case 0x128: /* movapd */
3379 case 0x16f: /* movdqa xmm, ea */
3380 case 0x26f: /* movdqu xmm, ea */
3381 if (mod != 3) {
3382 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3383 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3384 } else {
3385 rm = (modrm & 7) | REX_B(s);
3386 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3387 offsetof(CPUX86State,xmm_regs[rm]));
3389 break;
3390 case 0x210: /* movss xmm, ea */
3391 if (mod != 3) {
3392 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3393 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3394 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3395 gen_op_movl_T0_0();
3396 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3397 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3398 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3399 } else {
3400 rm = (modrm & 7) | REX_B(s);
3401 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3402 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3404 break;
3405 case 0x310: /* movsd xmm, ea */
3406 if (mod != 3) {
3407 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3408 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3409 gen_op_movl_T0_0();
3410 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3411 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3412 } else {
3413 rm = (modrm & 7) | REX_B(s);
3414 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3415 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3417 break;
3418 case 0x012: /* movlps */
3419 case 0x112: /* movlpd */
3420 if (mod != 3) {
3421 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3422 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3423 } else {
3424 /* movhlps */
3425 rm = (modrm & 7) | REX_B(s);
3426 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3427 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3429 break;
3430 case 0x212: /* movsldup */
3431 if (mod != 3) {
3432 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3433 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3434 } else {
3435 rm = (modrm & 7) | REX_B(s);
3436 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3437 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3438 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3439 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3441 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3442 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3443 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3444 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3445 break;
3446 case 0x312: /* movddup */
3447 if (mod != 3) {
3448 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3449 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3450 } else {
3451 rm = (modrm & 7) | REX_B(s);
3452 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3453 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3455 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3456 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3457 break;
3458 case 0x016: /* movhps */
3459 case 0x116: /* movhpd */
3460 if (mod != 3) {
3461 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3462 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3463 } else {
3464 /* movlhps */
3465 rm = (modrm & 7) | REX_B(s);
3466 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3467 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3469 break;
3470 case 0x216: /* movshdup */
3471 if (mod != 3) {
3472 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3473 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3474 } else {
3475 rm = (modrm & 7) | REX_B(s);
3476 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3477 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3478 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3479 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3481 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3482 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3483 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3484 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3485 break;
3486 case 0x178:
3487 case 0x378:
3489 int bit_index, field_length;
3491 if (b1 == 1 && reg != 0)
3492 goto illegal_op;
3493 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3494 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3495 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3496 offsetof(CPUX86State,xmm_regs[reg]));
3497 if (b1 == 1)
3498 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3499 tcg_const_i32(bit_index),
3500 tcg_const_i32(field_length));
3501 else
3502 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3503 tcg_const_i32(bit_index),
3504 tcg_const_i32(field_length));
3506 break;
3507 case 0x7e: /* movd ea, mm */
3508 #ifdef TARGET_X86_64
3509 if (s->dflag == 2) {
3510 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3511 offsetof(CPUX86State,fpregs[reg].mmx));
3512 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
3513 } else
3514 #endif
3516 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3517 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3518 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
3520 break;
3521 case 0x17e: /* movd ea, xmm */
3522 #ifdef TARGET_X86_64
3523 if (s->dflag == 2) {
3524 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3525 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3526 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
3527 } else
3528 #endif
3530 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3531 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3532 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
3534 break;
3535 case 0x27e: /* movq xmm, ea */
3536 if (mod != 3) {
3537 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3538 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3539 } else {
3540 rm = (modrm & 7) | REX_B(s);
3541 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3542 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3544 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3545 break;
3546 case 0x7f: /* movq ea, mm */
3547 if (mod != 3) {
3548 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3549 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
3550 } else {
3551 rm = (modrm & 7);
3552 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3553 offsetof(CPUX86State,fpregs[reg].mmx));
3555 break;
3556 case 0x011: /* movups */
3557 case 0x111: /* movupd */
3558 case 0x029: /* movaps */
3559 case 0x129: /* movapd */
3560 case 0x17f: /* movdqa ea, xmm */
3561 case 0x27f: /* movdqu ea, xmm */
3562 if (mod != 3) {
3563 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3564 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3565 } else {
3566 rm = (modrm & 7) | REX_B(s);
3567 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3568 offsetof(CPUX86State,xmm_regs[reg]));
3570 break;
3571 case 0x211: /* movss ea, xmm */
3572 if (mod != 3) {
3573 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3574 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3575 gen_op_st_T0_A0(OT_LONG + s->mem_index);
3576 } else {
3577 rm = (modrm & 7) | REX_B(s);
3578 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3579 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3581 break;
3582 case 0x311: /* movsd ea, xmm */
3583 if (mod != 3) {
3584 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3585 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3586 } else {
3587 rm = (modrm & 7) | REX_B(s);
3588 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3589 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3591 break;
3592 case 0x013: /* movlps */
3593 case 0x113: /* movlpd */
3594 if (mod != 3) {
3595 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3596 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3597 } else {
3598 goto illegal_op;
3600 break;
3601 case 0x017: /* movhps */
3602 case 0x117: /* movhpd */
3603 if (mod != 3) {
3604 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3605 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3606 } else {
3607 goto illegal_op;
3609 break;
3610 case 0x71: /* shift mm, im */
3611 case 0x72:
3612 case 0x73:
3613 case 0x171: /* shift xmm, im */
3614 case 0x172:
3615 case 0x173:
3616 if (b1 >= 2) {
3617 goto illegal_op;
3619 val = cpu_ldub_code(env, s->pc++);
3620 if (is_xmm) {
3621 gen_op_movl_T0_im(val);
3622 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3623 gen_op_movl_T0_0();
3624 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
3625 op1_offset = offsetof(CPUX86State,xmm_t0);
3626 } else {
3627 gen_op_movl_T0_im(val);
3628 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3629 gen_op_movl_T0_0();
3630 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3631 op1_offset = offsetof(CPUX86State,mmx_t0);
3633 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3634 (((modrm >> 3)) & 7)][b1];
3635 if (!sse_fn_epp) {
3636 goto illegal_op;
3638 if (is_xmm) {
3639 rm = (modrm & 7) | REX_B(s);
3640 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3641 } else {
3642 rm = (modrm & 7);
3643 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3645 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3646 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3647 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3648 break;
3649 case 0x050: /* movmskps */
3650 rm = (modrm & 7) | REX_B(s);
3651 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3652 offsetof(CPUX86State,xmm_regs[rm]));
3653 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3654 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3655 gen_op_mov_reg_T0(OT_LONG, reg);
3656 break;
3657 case 0x150: /* movmskpd */
3658 rm = (modrm & 7) | REX_B(s);
3659 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3660 offsetof(CPUX86State,xmm_regs[rm]));
3661 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3662 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3663 gen_op_mov_reg_T0(OT_LONG, reg);
3664 break;
3665 case 0x02a: /* cvtpi2ps */
3666 case 0x12a: /* cvtpi2pd */
3667 gen_helper_enter_mmx(cpu_env);
3668 if (mod != 3) {
3669 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3670 op2_offset = offsetof(CPUX86State,mmx_t0);
3671 gen_ldq_env_A0(s->mem_index, op2_offset);
3672 } else {
3673 rm = (modrm & 7);
3674 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3676 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3677 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3678 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3679 switch(b >> 8) {
3680 case 0x0:
3681 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3682 break;
3683 default:
3684 case 0x1:
3685 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3686 break;
3688 break;
3689 case 0x22a: /* cvtsi2ss */
3690 case 0x32a: /* cvtsi2sd */
3691 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3692 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3693 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3694 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3695 if (ot == OT_LONG) {
3696 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3697 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3698 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3699 } else {
3700 #ifdef TARGET_X86_64
3701 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3702 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T[0]);
3703 #else
3704 goto illegal_op;
3705 #endif
3707 break;
3708 case 0x02c: /* cvttps2pi */
3709 case 0x12c: /* cvttpd2pi */
3710 case 0x02d: /* cvtps2pi */
3711 case 0x12d: /* cvtpd2pi */
3712 gen_helper_enter_mmx(cpu_env);
3713 if (mod != 3) {
3714 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3715 op2_offset = offsetof(CPUX86State,xmm_t0);
3716 gen_ldo_env_A0(s->mem_index, op2_offset);
3717 } else {
3718 rm = (modrm & 7) | REX_B(s);
3719 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3721 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3722 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3723 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3724 switch(b) {
3725 case 0x02c:
3726 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3727 break;
3728 case 0x12c:
3729 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3730 break;
3731 case 0x02d:
3732 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3733 break;
3734 case 0x12d:
3735 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3736 break;
3738 break;
3739 case 0x22c: /* cvttss2si */
3740 case 0x32c: /* cvttsd2si */
3741 case 0x22d: /* cvtss2si */
3742 case 0x32d: /* cvtsd2si */
3743 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3744 if (mod != 3) {
3745 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3746 if ((b >> 8) & 1) {
3747 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
3748 } else {
3749 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3750 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3752 op2_offset = offsetof(CPUX86State,xmm_t0);
3753 } else {
3754 rm = (modrm & 7) | REX_B(s);
3755 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3757 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3758 if (ot == OT_LONG) {
3759 SSEFunc_i_ep sse_fn_i_ep =
3760 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3761 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3762 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3763 } else {
3764 #ifdef TARGET_X86_64
3765 SSEFunc_l_ep sse_fn_l_ep =
3766 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3767 sse_fn_l_ep(cpu_T[0], cpu_env, cpu_ptr0);
3768 #else
3769 goto illegal_op;
3770 #endif
3772 gen_op_mov_reg_T0(ot, reg);
3773 break;
3774 case 0xc4: /* pinsrw */
3775 case 0x1c4:
3776 s->rip_offset = 1;
3777 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
3778 val = cpu_ldub_code(env, s->pc++);
3779 if (b1) {
3780 val &= 7;
3781 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3782 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
3783 } else {
3784 val &= 3;
3785 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3786 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3788 break;
3789 case 0xc5: /* pextrw */
3790 case 0x1c5:
3791 if (mod != 3)
3792 goto illegal_op;
3793 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3794 val = cpu_ldub_code(env, s->pc++);
3795 if (b1) {
3796 val &= 7;
3797 rm = (modrm & 7) | REX_B(s);
3798 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3799 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
3800 } else {
3801 val &= 3;
3802 rm = (modrm & 7);
3803 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3804 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3806 reg = ((modrm >> 3) & 7) | rex_r;
3807 gen_op_mov_reg_T0(ot, reg);
3808 break;
3809 case 0x1d6: /* movq ea, xmm */
3810 if (mod != 3) {
3811 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3812 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3813 } else {
3814 rm = (modrm & 7) | REX_B(s);
3815 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3816 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3817 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3819 break;
3820 case 0x2d6: /* movq2dq */
3821 gen_helper_enter_mmx(cpu_env);
3822 rm = (modrm & 7);
3823 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3824 offsetof(CPUX86State,fpregs[rm].mmx));
3825 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3826 break;
3827 case 0x3d6: /* movdq2q */
3828 gen_helper_enter_mmx(cpu_env);
3829 rm = (modrm & 7) | REX_B(s);
3830 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3831 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3832 break;
3833 case 0xd7: /* pmovmskb */
3834 case 0x1d7:
3835 if (mod != 3)
3836 goto illegal_op;
3837 if (b1) {
3838 rm = (modrm & 7) | REX_B(s);
3839 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3840 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3841 } else {
3842 rm = (modrm & 7);
3843 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3844 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3846 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3847 reg = ((modrm >> 3) & 7) | rex_r;
3848 gen_op_mov_reg_T0(OT_LONG, reg);
3849 break;
3851 case 0x138:
3852 case 0x038:
3853 b = modrm;
3854 if ((b & 0xf0) == 0xf0) {
3855 goto do_0f_38_fx;
3857 modrm = cpu_ldub_code(env, s->pc++);
3858 rm = modrm & 7;
3859 reg = ((modrm >> 3) & 7) | rex_r;
3860 mod = (modrm >> 6) & 3;
3861 if (b1 >= 2) {
3862 goto illegal_op;
3865 sse_fn_epp = sse_op_table6[b].op[b1];
3866 if (!sse_fn_epp) {
3867 goto illegal_op;
3869 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3870 goto illegal_op;
3872 if (b1) {
3873 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3874 if (mod == 3) {
3875 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3876 } else {
3877 op2_offset = offsetof(CPUX86State,xmm_t0);
3878 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3879 switch (b) {
3880 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3881 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3882 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3883 gen_ldq_env_A0(s->mem_index, op2_offset +
3884 offsetof(XMMReg, XMM_Q(0)));
3885 break;
3886 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3887 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3888 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
3889 (s->mem_index >> 2) - 1);
3890 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
3891 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3892 offsetof(XMMReg, XMM_L(0)));
3893 break;
3894 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3895 tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0,
3896 (s->mem_index >> 2) - 1);
3897 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3898 offsetof(XMMReg, XMM_W(0)));
3899 break;
3900 case 0x2a: /* movntqda */
3901 gen_ldo_env_A0(s->mem_index, op1_offset);
3902 return;
3903 default:
3904 gen_ldo_env_A0(s->mem_index, op2_offset);
3907 } else {
3908 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3909 if (mod == 3) {
3910 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3911 } else {
3912 op2_offset = offsetof(CPUX86State,mmx_t0);
3913 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3914 gen_ldq_env_A0(s->mem_index, op2_offset);
3917 if (sse_fn_epp == SSE_SPECIAL) {
3918 goto illegal_op;
3921 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3922 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3923 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3925 if (b == 0x17) {
3926 set_cc_op(s, CC_OP_EFLAGS);
3928 break;
3930 case 0x238:
3931 case 0x338:
3932 do_0f_38_fx:
3933 /* Various integer extensions at 0f 38 f[0-f]. */
3934 b = modrm | (b1 << 8);
3935 modrm = cpu_ldub_code(env, s->pc++);
3936 reg = ((modrm >> 3) & 7) | rex_r;
3938 switch (b) {
3939 case 0x3f0: /* crc32 Gd,Eb */
3940 case 0x3f1: /* crc32 Gd,Ey */
3941 do_crc32:
3942 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3943 goto illegal_op;
3945 if ((b & 0xff) == 0xf0) {
3946 ot = OT_BYTE;
3947 } else if (s->dflag != 2) {
3948 ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
3949 } else {
3950 ot = OT_QUAD;
3953 gen_op_mov_TN_reg(OT_LONG, 0, reg);
3954 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3955 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3956 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
3957 cpu_T[0], tcg_const_i32(8 << ot));
3959 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3960 gen_op_mov_reg_T0(ot, reg);
3961 break;
3963 case 0x1f0: /* crc32 or movbe */
3964 case 0x1f1:
3965 /* For these insns, the f3 prefix is supposed to have priority
3966 over the 66 prefix, but that's not what we implement above
3967 setting b1. */
3968 if (s->prefix & PREFIX_REPNZ) {
3969 goto do_crc32;
3971 /* FALLTHRU */
3972 case 0x0f0: /* movbe Gy,My */
3973 case 0x0f1: /* movbe My,Gy */
3974 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3975 goto illegal_op;
3977 if (s->dflag != 2) {
3978 ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
3979 } else {
3980 ot = OT_QUAD;
3983 /* Load the data incoming to the bswap. Note that the TCG
3984 implementation of bswap requires the input be zero
3985 extended. In the case of the loads, we simply know that
3986 gen_op_ld_v via gen_ldst_modrm does that already. */
3987 if ((b & 1) == 0) {
3988 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3989 } else {
3990 switch (ot) {
3991 case OT_WORD:
3992 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[reg]);
3993 break;
3994 default:
3995 tcg_gen_ext32u_tl(cpu_T[0], cpu_regs[reg]);
3996 break;
3997 case OT_QUAD:
3998 tcg_gen_mov_tl(cpu_T[0], cpu_regs[reg]);
3999 break;
4003 switch (ot) {
4004 case OT_WORD:
4005 tcg_gen_bswap16_tl(cpu_T[0], cpu_T[0]);
4006 break;
4007 default:
4008 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
4009 break;
4010 #ifdef TARGET_X86_64
4011 case OT_QUAD:
4012 tcg_gen_bswap64_tl(cpu_T[0], cpu_T[0]);
4013 break;
4014 #endif
4017 if ((b & 1) == 0) {
4018 gen_op_mov_reg_T0(ot, reg);
4019 } else {
4020 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
4022 break;
4024 case 0x0f2: /* andn Gy, By, Ey */
4025 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4026 || !(s->prefix & PREFIX_VEX)
4027 || s->vex_l != 0) {
4028 goto illegal_op;
4030 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4031 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4032 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
4033 gen_op_mov_reg_T0(ot, reg);
4034 gen_op_update1_cc();
4035 set_cc_op(s, CC_OP_LOGICB + ot);
4036 break;
4038 case 0x0f7: /* bextr Gy, Ey, By */
4039 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4040 || !(s->prefix & PREFIX_VEX)
4041 || s->vex_l != 0) {
4042 goto illegal_op;
4044 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4046 TCGv bound, zero;
4048 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4049 /* Extract START, and shift the operand.
4050 Shifts larger than operand size get zeros. */
4051 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
4052 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_A0);
4054 bound = tcg_const_tl(ot == OT_QUAD ? 63 : 31);
4055 zero = tcg_const_tl(0);
4056 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T[0], cpu_A0, bound,
4057 cpu_T[0], zero);
4058 tcg_temp_free(zero);
4060 /* Extract the LEN into a mask. Lengths larger than
4061 operand size get all ones. */
4062 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
4063 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
4064 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
4065 cpu_A0, bound);
4066 tcg_temp_free(bound);
4067 tcg_gen_movi_tl(cpu_T[1], 1);
4068 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_A0);
4069 tcg_gen_subi_tl(cpu_T[1], cpu_T[1], 1);
4070 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4072 gen_op_mov_reg_T0(ot, reg);
4073 gen_op_update1_cc();
4074 set_cc_op(s, CC_OP_LOGICB + ot);
4076 break;
4078 case 0x0f5: /* bzhi Gy, Ey, By */
4079 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4080 || !(s->prefix & PREFIX_VEX)
4081 || s->vex_l != 0) {
4082 goto illegal_op;
4084 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4085 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4086 tcg_gen_ext8u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4088 TCGv bound = tcg_const_tl(ot == OT_QUAD ? 63 : 31);
4089 /* Note that since we're using BMILG (in order to get O
4090 cleared) we need to store the inverse into C. */
4091 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
4092 cpu_T[1], bound);
4093 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T[1], cpu_T[1],
4094 bound, bound, cpu_T[1]);
4095 tcg_temp_free(bound);
4097 tcg_gen_movi_tl(cpu_A0, -1);
4098 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T[1]);
4099 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_A0);
4100 gen_op_mov_reg_T0(ot, reg);
4101 gen_op_update1_cc();
4102 set_cc_op(s, CC_OP_BMILGB + ot);
4103 break;
4105 case 0x3f6: /* mulx By, Gy, rdx, Ey */
4106 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4107 || !(s->prefix & PREFIX_VEX)
4108 || s->vex_l != 0) {
4109 goto illegal_op;
4111 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4112 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4113 switch (ot) {
4114 default:
4115 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4116 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
4117 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4118 cpu_tmp2_i32, cpu_tmp3_i32);
4119 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
4120 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
4121 break;
4122 #ifdef TARGET_X86_64
4123 case OT_QUAD:
4124 tcg_gen_mulu2_i64(cpu_regs[s->vex_v], cpu_regs[reg],
4125 cpu_T[0], cpu_regs[R_EDX]);
4126 break;
4127 #endif
4129 break;
4131 case 0x3f5: /* pdep Gy, By, Ey */
4132 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4133 || !(s->prefix & PREFIX_VEX)
4134 || s->vex_l != 0) {
4135 goto illegal_op;
4137 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4138 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4139 /* Note that by zero-extending the mask operand, we
4140 automatically handle zero-extending the result. */
4141 if (s->dflag == 2) {
4142 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
4143 } else {
4144 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4146 gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]);
4147 break;
4149 case 0x2f5: /* pext Gy, By, Ey */
4150 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4151 || !(s->prefix & PREFIX_VEX)
4152 || s->vex_l != 0) {
4153 goto illegal_op;
4155 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4156 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4157 /* Note that by zero-extending the mask operand, we
4158 automatically handle zero-extending the result. */
4159 if (s->dflag == 2) {
4160 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
4161 } else {
4162 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
4164 gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]);
4165 break;
4167 case 0x1f6: /* adcx Gy, Ey */
4168 case 0x2f6: /* adox Gy, Ey */
4169 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
4170 goto illegal_op;
4171 } else {
4172 TCGv carry_in, carry_out, zero;
4173 int end_op;
4175 ot = (s->dflag == 2 ? OT_QUAD : OT_LONG);
4176 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4178 /* Re-use the carry-out from a previous round. */
4179 TCGV_UNUSED(carry_in);
4180 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
4181 switch (s->cc_op) {
4182 case CC_OP_ADCX:
4183 if (b == 0x1f6) {
4184 carry_in = cpu_cc_dst;
4185 end_op = CC_OP_ADCX;
4186 } else {
4187 end_op = CC_OP_ADCOX;
4189 break;
4190 case CC_OP_ADOX:
4191 if (b == 0x1f6) {
4192 end_op = CC_OP_ADCOX;
4193 } else {
4194 carry_in = cpu_cc_src2;
4195 end_op = CC_OP_ADOX;
4197 break;
4198 case CC_OP_ADCOX:
4199 end_op = CC_OP_ADCOX;
4200 carry_in = carry_out;
4201 break;
4202 default:
4203 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADCOX);
4204 break;
4206 /* If we can't reuse carry-out, get it out of EFLAGS. */
4207 if (TCGV_IS_UNUSED(carry_in)) {
4208 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4209 gen_compute_eflags(s);
4211 carry_in = cpu_tmp0;
4212 tcg_gen_shri_tl(carry_in, cpu_cc_src,
4213 ctz32(b == 0x1f6 ? CC_C : CC_O));
4214 tcg_gen_andi_tl(carry_in, carry_in, 1);
4217 switch (ot) {
4218 #ifdef TARGET_X86_64
4219 case OT_LONG:
4220 /* If we know TL is 64-bit, and we want a 32-bit
4221 result, just do everything in 64-bit arithmetic. */
4222 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4223 tcg_gen_ext32u_i64(cpu_T[0], cpu_T[0]);
4224 tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_regs[reg]);
4225 tcg_gen_add_i64(cpu_T[0], cpu_T[0], carry_in);
4226 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T[0]);
4227 tcg_gen_shri_i64(carry_out, cpu_T[0], 32);
4228 break;
4229 #endif
4230 default:
4231 /* Otherwise compute the carry-out in two steps. */
4232 zero = tcg_const_tl(0);
4233 tcg_gen_add2_tl(cpu_T[0], carry_out,
4234 cpu_T[0], zero,
4235 carry_in, zero);
4236 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4237 cpu_regs[reg], carry_out,
4238 cpu_T[0], zero);
4239 tcg_temp_free(zero);
4240 break;
4242 set_cc_op(s, end_op);
4244 break;
4246 case 0x1f7: /* shlx Gy, Ey, By */
4247 case 0x2f7: /* sarx Gy, Ey, By */
4248 case 0x3f7: /* shrx Gy, Ey, By */
4249 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4250 || !(s->prefix & PREFIX_VEX)
4251 || s->vex_l != 0) {
4252 goto illegal_op;
4254 ot = (s->dflag == 2 ? OT_QUAD : OT_LONG);
4255 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4256 if (ot == OT_QUAD) {
4257 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
4258 } else {
4259 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
4261 if (b == 0x1f7) {
4262 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4263 } else if (b == 0x2f7) {
4264 if (ot != OT_QUAD) {
4265 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4267 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4268 } else {
4269 if (ot != OT_QUAD) {
4270 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
4272 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4274 gen_op_mov_reg_T0(ot, reg);
4275 break;
4277 case 0x0f3:
4278 case 0x1f3:
4279 case 0x2f3:
4280 case 0x3f3: /* Group 17 */
4281 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4282 || !(s->prefix & PREFIX_VEX)
4283 || s->vex_l != 0) {
4284 goto illegal_op;
4286 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4287 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4289 switch (reg & 7) {
4290 case 1: /* blsr By,Ey */
4291 tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
4292 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4293 gen_op_mov_reg_T0(ot, s->vex_v);
4294 gen_op_update2_cc();
4295 set_cc_op(s, CC_OP_BMILGB + ot);
4296 break;
4298 case 2: /* blsmsk By,Ey */
4299 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4300 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4301 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4302 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4303 set_cc_op(s, CC_OP_BMILGB + ot);
4304 break;
4306 case 3: /* blsi By, Ey */
4307 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4308 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4309 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4310 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4311 set_cc_op(s, CC_OP_BMILGB + ot);
4312 break;
4314 default:
4315 goto illegal_op;
4317 break;
4319 default:
4320 goto illegal_op;
4322 break;
4324 case 0x03a:
4325 case 0x13a:
4326 b = modrm;
4327 modrm = cpu_ldub_code(env, s->pc++);
4328 rm = modrm & 7;
4329 reg = ((modrm >> 3) & 7) | rex_r;
4330 mod = (modrm >> 6) & 3;
4331 if (b1 >= 2) {
4332 goto illegal_op;
4335 sse_fn_eppi = sse_op_table7[b].op[b1];
4336 if (!sse_fn_eppi) {
4337 goto illegal_op;
4339 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4340 goto illegal_op;
4342 if (sse_fn_eppi == SSE_SPECIAL) {
4343 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
4344 rm = (modrm & 7) | REX_B(s);
4345 if (mod != 3)
4346 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4347 reg = ((modrm >> 3) & 7) | rex_r;
4348 val = cpu_ldub_code(env, s->pc++);
4349 switch (b) {
4350 case 0x14: /* pextrb */
4351 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4352 xmm_regs[reg].XMM_B(val & 15)));
4353 if (mod == 3)
4354 gen_op_mov_reg_T0(ot, rm);
4355 else
4356 tcg_gen_qemu_st8(cpu_T[0], cpu_A0,
4357 (s->mem_index >> 2) - 1);
4358 break;
4359 case 0x15: /* pextrw */
4360 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4361 xmm_regs[reg].XMM_W(val & 7)));
4362 if (mod == 3)
4363 gen_op_mov_reg_T0(ot, rm);
4364 else
4365 tcg_gen_qemu_st16(cpu_T[0], cpu_A0,
4366 (s->mem_index >> 2) - 1);
4367 break;
4368 case 0x16:
4369 if (ot == OT_LONG) { /* pextrd */
4370 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4371 offsetof(CPUX86State,
4372 xmm_regs[reg].XMM_L(val & 3)));
4373 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4374 if (mod == 3)
4375 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4376 else
4377 tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
4378 (s->mem_index >> 2) - 1);
4379 } else { /* pextrq */
4380 #ifdef TARGET_X86_64
4381 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4382 offsetof(CPUX86State,
4383 xmm_regs[reg].XMM_Q(val & 1)));
4384 if (mod == 3)
4385 gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
4386 else
4387 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
4388 (s->mem_index >> 2) - 1);
4389 #else
4390 goto illegal_op;
4391 #endif
4393 break;
4394 case 0x17: /* extractps */
4395 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4396 xmm_regs[reg].XMM_L(val & 3)));
4397 if (mod == 3)
4398 gen_op_mov_reg_T0(ot, rm);
4399 else
4400 tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
4401 (s->mem_index >> 2) - 1);
4402 break;
4403 case 0x20: /* pinsrb */
4404 if (mod == 3)
4405 gen_op_mov_TN_reg(OT_LONG, 0, rm);
4406 else
4407 tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0,
4408 (s->mem_index >> 2) - 1);
4409 tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State,
4410 xmm_regs[reg].XMM_B(val & 15)));
4411 break;
4412 case 0x21: /* insertps */
4413 if (mod == 3) {
4414 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4415 offsetof(CPUX86State,xmm_regs[rm]
4416 .XMM_L((val >> 6) & 3)));
4417 } else {
4418 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
4419 (s->mem_index >> 2) - 1);
4420 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
4422 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4423 offsetof(CPUX86State,xmm_regs[reg]
4424 .XMM_L((val >> 4) & 3)));
4425 if ((val >> 0) & 1)
4426 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4427 cpu_env, offsetof(CPUX86State,
4428 xmm_regs[reg].XMM_L(0)));
4429 if ((val >> 1) & 1)
4430 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4431 cpu_env, offsetof(CPUX86State,
4432 xmm_regs[reg].XMM_L(1)));
4433 if ((val >> 2) & 1)
4434 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4435 cpu_env, offsetof(CPUX86State,
4436 xmm_regs[reg].XMM_L(2)));
4437 if ((val >> 3) & 1)
4438 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4439 cpu_env, offsetof(CPUX86State,
4440 xmm_regs[reg].XMM_L(3)));
4441 break;
4442 case 0x22:
4443 if (ot == OT_LONG) { /* pinsrd */
4444 if (mod == 3)
4445 gen_op_mov_v_reg(ot, cpu_tmp0, rm);
4446 else
4447 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
4448 (s->mem_index >> 2) - 1);
4449 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
4450 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4451 offsetof(CPUX86State,
4452 xmm_regs[reg].XMM_L(val & 3)));
4453 } else { /* pinsrq */
4454 #ifdef TARGET_X86_64
4455 if (mod == 3)
4456 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4457 else
4458 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
4459 (s->mem_index >> 2) - 1);
4460 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4461 offsetof(CPUX86State,
4462 xmm_regs[reg].XMM_Q(val & 1)));
4463 #else
4464 goto illegal_op;
4465 #endif
4467 break;
4469 return;
4472 if (b1) {
4473 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4474 if (mod == 3) {
4475 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4476 } else {
4477 op2_offset = offsetof(CPUX86State,xmm_t0);
4478 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4479 gen_ldo_env_A0(s->mem_index, op2_offset);
4481 } else {
4482 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4483 if (mod == 3) {
4484 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4485 } else {
4486 op2_offset = offsetof(CPUX86State,mmx_t0);
4487 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4488 gen_ldq_env_A0(s->mem_index, op2_offset);
4491 val = cpu_ldub_code(env, s->pc++);
4493 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4494 set_cc_op(s, CC_OP_EFLAGS);
4496 if (s->dflag == 2)
4497 /* The helper must use entire 64-bit gp registers */
4498 val |= 1 << 8;
4501 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4502 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4503 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4504 break;
4506 case 0x33a:
4507 /* Various integer extensions at 0f 3a f[0-f]. */
4508 b = modrm | (b1 << 8);
4509 modrm = cpu_ldub_code(env, s->pc++);
4510 reg = ((modrm >> 3) & 7) | rex_r;
4512 switch (b) {
4513 case 0x3f0: /* rorx Gy,Ey, Ib */
4514 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4515 || !(s->prefix & PREFIX_VEX)
4516 || s->vex_l != 0) {
4517 goto illegal_op;
4519 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4520 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4521 b = cpu_ldub_code(env, s->pc++);
4522 if (ot == OT_QUAD) {
4523 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
4524 } else {
4525 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4526 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4527 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4529 gen_op_mov_reg_T0(ot, reg);
4530 break;
4532 default:
4533 goto illegal_op;
4535 break;
4537 default:
4538 goto illegal_op;
4540 } else {
4541 /* generic MMX or SSE operation */
4542 switch(b) {
4543 case 0x70: /* pshufx insn */
4544 case 0xc6: /* pshufx insn */
4545 case 0xc2: /* compare insns */
4546 s->rip_offset = 1;
4547 break;
4548 default:
4549 break;
4551 if (is_xmm) {
4552 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4553 if (mod != 3) {
4554 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4555 op2_offset = offsetof(CPUX86State,xmm_t0);
4556 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
4557 b == 0xc2)) {
4558 /* specific case for SSE single instructions */
4559 if (b1 == 2) {
4560 /* 32 bit access */
4561 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
4562 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
4563 } else {
4564 /* 64 bit access */
4565 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
4567 } else {
4568 gen_ldo_env_A0(s->mem_index, op2_offset);
4570 } else {
4571 rm = (modrm & 7) | REX_B(s);
4572 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4574 } else {
4575 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4576 if (mod != 3) {
4577 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4578 op2_offset = offsetof(CPUX86State,mmx_t0);
4579 gen_ldq_env_A0(s->mem_index, op2_offset);
4580 } else {
4581 rm = (modrm & 7);
4582 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4585 switch(b) {
4586 case 0x0f: /* 3DNow! data insns */
4587 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4588 goto illegal_op;
4589 val = cpu_ldub_code(env, s->pc++);
4590 sse_fn_epp = sse_op_table5[val];
4591 if (!sse_fn_epp) {
4592 goto illegal_op;
4594 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4595 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4596 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4597 break;
4598 case 0x70: /* pshufx insn */
4599 case 0xc6: /* pshufx insn */
4600 val = cpu_ldub_code(env, s->pc++);
4601 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4602 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4603 /* XXX: introduce a new table? */
4604 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4605 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4606 break;
4607 case 0xc2:
4608 /* compare insns */
4609 val = cpu_ldub_code(env, s->pc++);
4610 if (val >= 8)
4611 goto illegal_op;
4612 sse_fn_epp = sse_op_table4[val][b1];
4614 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4615 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4616 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4617 break;
4618 case 0xf7:
4619 /* maskmov : we must prepare A0 */
4620 if (mod != 3)
4621 goto illegal_op;
4622 #ifdef TARGET_X86_64
4623 if (s->aflag == 2) {
4624 gen_op_movq_A0_reg(R_EDI);
4625 } else
4626 #endif
4628 gen_op_movl_A0_reg(R_EDI);
4629 if (s->aflag == 0)
4630 gen_op_andl_A0_ffff();
4632 gen_add_A0_ds_seg(s);
4634 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4635 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4636 /* XXX: introduce a new table? */
4637 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4638 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4639 break;
4640 default:
4641 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4642 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4643 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4644 break;
4646 if (b == 0x2e || b == 0x2f) {
4647 set_cc_op(s, CC_OP_EFLAGS);
4652 /* convert one instruction. s->is_jmp is set if the translation must
4653 be stopped. Return the next pc value */
4654 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4655 target_ulong pc_start)
4657 int b, prefixes, aflag, dflag;
4658 int shift, ot;
4659 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
4660 target_ulong next_eip, tval;
4661 int rex_w, rex_r;
4663 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
4664 tcg_gen_debug_insn_start(pc_start);
4666 s->pc = pc_start;
4667 prefixes = 0;
4668 aflag = s->code32;
4669 dflag = s->code32;
4670 s->override = -1;
4671 rex_w = -1;
4672 rex_r = 0;
4673 #ifdef TARGET_X86_64
4674 s->rex_x = 0;
4675 s->rex_b = 0;
4676 x86_64_hregs = 0;
4677 #endif
4678 s->rip_offset = 0; /* for relative ip address */
4679 s->vex_l = 0;
4680 s->vex_v = 0;
4681 next_byte:
4682 b = cpu_ldub_code(env, s->pc);
4683 s->pc++;
4684 /* Collect prefixes. */
4685 switch (b) {
4686 case 0xf3:
4687 prefixes |= PREFIX_REPZ;
4688 goto next_byte;
4689 case 0xf2:
4690 prefixes |= PREFIX_REPNZ;
4691 goto next_byte;
4692 case 0xf0:
4693 prefixes |= PREFIX_LOCK;
4694 goto next_byte;
4695 case 0x2e:
4696 s->override = R_CS;
4697 goto next_byte;
4698 case 0x36:
4699 s->override = R_SS;
4700 goto next_byte;
4701 case 0x3e:
4702 s->override = R_DS;
4703 goto next_byte;
4704 case 0x26:
4705 s->override = R_ES;
4706 goto next_byte;
4707 case 0x64:
4708 s->override = R_FS;
4709 goto next_byte;
4710 case 0x65:
4711 s->override = R_GS;
4712 goto next_byte;
4713 case 0x66:
4714 prefixes |= PREFIX_DATA;
4715 goto next_byte;
4716 case 0x67:
4717 prefixes |= PREFIX_ADR;
4718 goto next_byte;
4719 #ifdef TARGET_X86_64
4720 case 0x40 ... 0x4f:
4721 if (CODE64(s)) {
4722 /* REX prefix */
4723 rex_w = (b >> 3) & 1;
4724 rex_r = (b & 0x4) << 1;
4725 s->rex_x = (b & 0x2) << 2;
4726 REX_B(s) = (b & 0x1) << 3;
4727 x86_64_hregs = 1; /* select uniform byte register addressing */
4728 goto next_byte;
4730 break;
4731 #endif
4732 case 0xc5: /* 2-byte VEX */
4733 case 0xc4: /* 3-byte VEX */
4734 /* VEX prefixes cannot be used except in 32-bit mode.
4735 Otherwise the instruction is LES or LDS. */
4736 if (s->code32 && !s->vm86) {
4737 static const int pp_prefix[4] = {
4738 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4740 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4742 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4743 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4744 otherwise the instruction is LES or LDS. */
4745 break;
4747 s->pc++;
4749 /* 4.1.1-4.1.3: No preceeding lock, 66, f2, f3, or rex prefixes. */
4750 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4751 | PREFIX_LOCK | PREFIX_DATA)) {
4752 goto illegal_op;
4754 #ifdef TARGET_X86_64
4755 if (x86_64_hregs) {
4756 goto illegal_op;
4758 #endif
4759 rex_r = (~vex2 >> 4) & 8;
4760 if (b == 0xc5) {
4761 vex3 = vex2;
4762 b = cpu_ldub_code(env, s->pc++);
4763 } else {
4764 #ifdef TARGET_X86_64
4765 s->rex_x = (~vex2 >> 3) & 8;
4766 s->rex_b = (~vex2 >> 2) & 8;
4767 #endif
4768 vex3 = cpu_ldub_code(env, s->pc++);
4769 rex_w = (vex3 >> 7) & 1;
4770 switch (vex2 & 0x1f) {
4771 case 0x01: /* Implied 0f leading opcode bytes. */
4772 b = cpu_ldub_code(env, s->pc++) | 0x100;
4773 break;
4774 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4775 b = 0x138;
4776 break;
4777 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4778 b = 0x13a;
4779 break;
4780 default: /* Reserved for future use. */
4781 goto illegal_op;
4784 s->vex_v = (~vex3 >> 3) & 0xf;
4785 s->vex_l = (vex3 >> 2) & 1;
4786 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4788 break;
4791 /* Post-process prefixes. */
4792 if (prefixes & PREFIX_DATA) {
4793 dflag ^= 1;
4795 if (prefixes & PREFIX_ADR) {
4796 aflag ^= 1;
4798 #ifdef TARGET_X86_64
4799 if (CODE64(s)) {
4800 if (rex_w == 1) {
4801 /* 0x66 is ignored if rex.w is set */
4802 dflag = 2;
4804 if (!(prefixes & PREFIX_ADR)) {
4805 aflag = 2;
4808 #endif
4810 s->prefix = prefixes;
4811 s->aflag = aflag;
4812 s->dflag = dflag;
4814 /* lock generation */
4815 if (prefixes & PREFIX_LOCK)
4816 gen_helper_lock();
4818 /* now check op code */
4819 reswitch:
4820 switch(b) {
4821 case 0x0f:
4822 /**************************/
4823 /* extended op code */
4824 b = cpu_ldub_code(env, s->pc++) | 0x100;
4825 goto reswitch;
4827 /**************************/
4828 /* arith & logic */
4829 case 0x00 ... 0x05:
4830 case 0x08 ... 0x0d:
4831 case 0x10 ... 0x15:
4832 case 0x18 ... 0x1d:
4833 case 0x20 ... 0x25:
4834 case 0x28 ... 0x2d:
4835 case 0x30 ... 0x35:
4836 case 0x38 ... 0x3d:
4838 int op, f, val;
4839 op = (b >> 3) & 7;
4840 f = (b >> 1) & 3;
4842 if ((b & 1) == 0)
4843 ot = OT_BYTE;
4844 else
4845 ot = dflag + OT_WORD;
4847 switch(f) {
4848 case 0: /* OP Ev, Gv */
4849 modrm = cpu_ldub_code(env, s->pc++);
4850 reg = ((modrm >> 3) & 7) | rex_r;
4851 mod = (modrm >> 6) & 3;
4852 rm = (modrm & 7) | REX_B(s);
4853 if (mod != 3) {
4854 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4855 opreg = OR_TMP0;
4856 } else if (op == OP_XORL && rm == reg) {
4857 xor_zero:
4858 /* xor reg, reg optimisation */
4859 set_cc_op(s, CC_OP_CLR);
4860 gen_op_movl_T0_0();
4861 gen_op_mov_reg_T0(ot, reg);
4862 break;
4863 } else {
4864 opreg = rm;
4866 gen_op_mov_TN_reg(ot, 1, reg);
4867 gen_op(s, op, ot, opreg);
4868 break;
4869 case 1: /* OP Gv, Ev */
4870 modrm = cpu_ldub_code(env, s->pc++);
4871 mod = (modrm >> 6) & 3;
4872 reg = ((modrm >> 3) & 7) | rex_r;
4873 rm = (modrm & 7) | REX_B(s);
4874 if (mod != 3) {
4875 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4876 gen_op_ld_T1_A0(ot + s->mem_index);
4877 } else if (op == OP_XORL && rm == reg) {
4878 goto xor_zero;
4879 } else {
4880 gen_op_mov_TN_reg(ot, 1, rm);
4882 gen_op(s, op, ot, reg);
4883 break;
4884 case 2: /* OP A, Iv */
4885 val = insn_get(env, s, ot);
4886 gen_op_movl_T1_im(val);
4887 gen_op(s, op, ot, OR_EAX);
4888 break;
4891 break;
4893 case 0x82:
4894 if (CODE64(s))
4895 goto illegal_op;
4896 case 0x80: /* GRP1 */
4897 case 0x81:
4898 case 0x83:
4900 int val;
4902 if ((b & 1) == 0)
4903 ot = OT_BYTE;
4904 else
4905 ot = dflag + OT_WORD;
4907 modrm = cpu_ldub_code(env, s->pc++);
4908 mod = (modrm >> 6) & 3;
4909 rm = (modrm & 7) | REX_B(s);
4910 op = (modrm >> 3) & 7;
4912 if (mod != 3) {
4913 if (b == 0x83)
4914 s->rip_offset = 1;
4915 else
4916 s->rip_offset = insn_const_size(ot);
4917 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4918 opreg = OR_TMP0;
4919 } else {
4920 opreg = rm;
4923 switch(b) {
4924 default:
4925 case 0x80:
4926 case 0x81:
4927 case 0x82:
4928 val = insn_get(env, s, ot);
4929 break;
4930 case 0x83:
4931 val = (int8_t)insn_get(env, s, OT_BYTE);
4932 break;
4934 gen_op_movl_T1_im(val);
4935 gen_op(s, op, ot, opreg);
4937 break;
4939 /**************************/
4940 /* inc, dec, and other misc arith */
4941 case 0x40 ... 0x47: /* inc Gv */
4942 ot = dflag ? OT_LONG : OT_WORD;
4943 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4944 break;
4945 case 0x48 ... 0x4f: /* dec Gv */
4946 ot = dflag ? OT_LONG : OT_WORD;
4947 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4948 break;
4949 case 0xf6: /* GRP3 */
4950 case 0xf7:
4951 if ((b & 1) == 0)
4952 ot = OT_BYTE;
4953 else
4954 ot = dflag + OT_WORD;
4956 modrm = cpu_ldub_code(env, s->pc++);
4957 mod = (modrm >> 6) & 3;
4958 rm = (modrm & 7) | REX_B(s);
4959 op = (modrm >> 3) & 7;
4960 if (mod != 3) {
4961 if (op == 0)
4962 s->rip_offset = insn_const_size(ot);
4963 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4964 gen_op_ld_T0_A0(ot + s->mem_index);
4965 } else {
4966 gen_op_mov_TN_reg(ot, 0, rm);
4969 switch(op) {
4970 case 0: /* test */
4971 val = insn_get(env, s, ot);
4972 gen_op_movl_T1_im(val);
4973 gen_op_testl_T0_T1_cc();
4974 set_cc_op(s, CC_OP_LOGICB + ot);
4975 break;
4976 case 2: /* not */
4977 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
4978 if (mod != 3) {
4979 gen_op_st_T0_A0(ot + s->mem_index);
4980 } else {
4981 gen_op_mov_reg_T0(ot, rm);
4983 break;
4984 case 3: /* neg */
4985 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
4986 if (mod != 3) {
4987 gen_op_st_T0_A0(ot + s->mem_index);
4988 } else {
4989 gen_op_mov_reg_T0(ot, rm);
4991 gen_op_update_neg_cc();
4992 set_cc_op(s, CC_OP_SUBB + ot);
4993 break;
4994 case 4: /* mul */
4995 switch(ot) {
4996 case OT_BYTE:
4997 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
4998 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4999 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
5000 /* XXX: use 32 bit mul which could be faster */
5001 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5002 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5003 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5004 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
5005 set_cc_op(s, CC_OP_MULB);
5006 break;
5007 case OT_WORD:
5008 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
5009 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
5010 tcg_gen_ext16u_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(OT_WORD, R_EAX);
5014 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5015 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
5016 gen_op_mov_reg_T0(OT_WORD, R_EDX);
5017 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
5018 set_cc_op(s, CC_OP_MULW);
5019 break;
5020 default:
5021 case OT_LONG:
5022 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5023 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
5024 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5025 cpu_tmp2_i32, cpu_tmp3_i32);
5026 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
5027 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
5028 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5029 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
5030 set_cc_op(s, CC_OP_MULL);
5031 break;
5032 #ifdef TARGET_X86_64
5033 case OT_QUAD:
5034 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5035 cpu_T[0], cpu_regs[R_EAX]);
5036 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5037 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
5038 set_cc_op(s, CC_OP_MULQ);
5039 break;
5040 #endif
5042 break;
5043 case 5: /* imul */
5044 switch(ot) {
5045 case OT_BYTE:
5046 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
5047 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5048 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
5049 /* XXX: use 32 bit mul which could be faster */
5050 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5051 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5052 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5053 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
5054 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5055 set_cc_op(s, CC_OP_MULB);
5056 break;
5057 case OT_WORD:
5058 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
5059 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5060 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5061 /* XXX: use 32 bit mul which could be faster */
5062 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5063 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5064 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5065 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5066 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5067 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
5068 gen_op_mov_reg_T0(OT_WORD, R_EDX);
5069 set_cc_op(s, CC_OP_MULW);
5070 break;
5071 default:
5072 case OT_LONG:
5073 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5074 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
5075 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5076 cpu_tmp2_i32, cpu_tmp3_i32);
5077 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
5078 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
5079 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5080 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5081 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5082 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5083 set_cc_op(s, CC_OP_MULL);
5084 break;
5085 #ifdef TARGET_X86_64
5086 case OT_QUAD:
5087 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5088 cpu_T[0], cpu_regs[R_EAX]);
5089 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5090 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
5091 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
5092 set_cc_op(s, CC_OP_MULQ);
5093 break;
5094 #endif
5096 break;
5097 case 6: /* div */
5098 switch(ot) {
5099 case OT_BYTE:
5100 gen_jmp_im(pc_start - s->cs_base);
5101 gen_helper_divb_AL(cpu_env, cpu_T[0]);
5102 break;
5103 case OT_WORD:
5104 gen_jmp_im(pc_start - s->cs_base);
5105 gen_helper_divw_AX(cpu_env, cpu_T[0]);
5106 break;
5107 default:
5108 case OT_LONG:
5109 gen_jmp_im(pc_start - s->cs_base);
5110 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
5111 break;
5112 #ifdef TARGET_X86_64
5113 case OT_QUAD:
5114 gen_jmp_im(pc_start - s->cs_base);
5115 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
5116 break;
5117 #endif
5119 break;
5120 case 7: /* idiv */
5121 switch(ot) {
5122 case OT_BYTE:
5123 gen_jmp_im(pc_start - s->cs_base);
5124 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
5125 break;
5126 case OT_WORD:
5127 gen_jmp_im(pc_start - s->cs_base);
5128 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
5129 break;
5130 default:
5131 case OT_LONG:
5132 gen_jmp_im(pc_start - s->cs_base);
5133 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
5134 break;
5135 #ifdef TARGET_X86_64
5136 case OT_QUAD:
5137 gen_jmp_im(pc_start - s->cs_base);
5138 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
5139 break;
5140 #endif
5142 break;
5143 default:
5144 goto illegal_op;
5146 break;
5148 case 0xfe: /* GRP4 */
5149 case 0xff: /* GRP5 */
5150 if ((b & 1) == 0)
5151 ot = OT_BYTE;
5152 else
5153 ot = dflag + OT_WORD;
5155 modrm = cpu_ldub_code(env, s->pc++);
5156 mod = (modrm >> 6) & 3;
5157 rm = (modrm & 7) | REX_B(s);
5158 op = (modrm >> 3) & 7;
5159 if (op >= 2 && b == 0xfe) {
5160 goto illegal_op;
5162 if (CODE64(s)) {
5163 if (op == 2 || op == 4) {
5164 /* operand size for jumps is 64 bit */
5165 ot = OT_QUAD;
5166 } else if (op == 3 || op == 5) {
5167 ot = dflag ? OT_LONG + (rex_w == 1) : OT_WORD;
5168 } else if (op == 6) {
5169 /* default push size is 64 bit */
5170 ot = dflag ? OT_QUAD : OT_WORD;
5173 if (mod != 3) {
5174 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5175 if (op >= 2 && op != 3 && op != 5)
5176 gen_op_ld_T0_A0(ot + s->mem_index);
5177 } else {
5178 gen_op_mov_TN_reg(ot, 0, rm);
5181 switch(op) {
5182 case 0: /* inc Ev */
5183 if (mod != 3)
5184 opreg = OR_TMP0;
5185 else
5186 opreg = rm;
5187 gen_inc(s, ot, opreg, 1);
5188 break;
5189 case 1: /* dec Ev */
5190 if (mod != 3)
5191 opreg = OR_TMP0;
5192 else
5193 opreg = rm;
5194 gen_inc(s, ot, opreg, -1);
5195 break;
5196 case 2: /* call Ev */
5197 /* XXX: optimize if memory (no 'and' is necessary) */
5198 if (s->dflag == 0)
5199 gen_op_andl_T0_ffff();
5200 next_eip = s->pc - s->cs_base;
5201 gen_movtl_T1_im(next_eip);
5202 gen_push_T1(s);
5203 gen_op_jmp_T0();
5204 gen_eob(s);
5205 break;
5206 case 3: /* lcall Ev */
5207 gen_op_ld_T1_A0(ot + s->mem_index);
5208 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
5209 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
5210 do_lcall:
5211 if (s->pe && !s->vm86) {
5212 gen_update_cc_op(s);
5213 gen_jmp_im(pc_start - s->cs_base);
5214 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5215 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
5216 tcg_const_i32(dflag),
5217 tcg_const_i32(s->pc - pc_start));
5218 } else {
5219 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5220 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
5221 tcg_const_i32(dflag),
5222 tcg_const_i32(s->pc - s->cs_base));
5224 gen_eob(s);
5225 break;
5226 case 4: /* jmp Ev */
5227 if (s->dflag == 0)
5228 gen_op_andl_T0_ffff();
5229 gen_op_jmp_T0();
5230 gen_eob(s);
5231 break;
5232 case 5: /* ljmp Ev */
5233 gen_op_ld_T1_A0(ot + s->mem_index);
5234 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
5235 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
5236 do_ljmp:
5237 if (s->pe && !s->vm86) {
5238 gen_update_cc_op(s);
5239 gen_jmp_im(pc_start - s->cs_base);
5240 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5241 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
5242 tcg_const_i32(s->pc - pc_start));
5243 } else {
5244 gen_op_movl_seg_T0_vm(R_CS);
5245 gen_op_movl_T0_T1();
5246 gen_op_jmp_T0();
5248 gen_eob(s);
5249 break;
5250 case 6: /* push Ev */
5251 gen_push_T0(s);
5252 break;
5253 default:
5254 goto illegal_op;
5256 break;
5258 case 0x84: /* test Ev, Gv */
5259 case 0x85:
5260 if ((b & 1) == 0)
5261 ot = OT_BYTE;
5262 else
5263 ot = dflag + OT_WORD;
5265 modrm = cpu_ldub_code(env, s->pc++);
5266 reg = ((modrm >> 3) & 7) | rex_r;
5268 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5269 gen_op_mov_TN_reg(ot, 1, reg);
5270 gen_op_testl_T0_T1_cc();
5271 set_cc_op(s, CC_OP_LOGICB + ot);
5272 break;
5274 case 0xa8: /* test eAX, Iv */
5275 case 0xa9:
5276 if ((b & 1) == 0)
5277 ot = OT_BYTE;
5278 else
5279 ot = dflag + OT_WORD;
5280 val = insn_get(env, s, ot);
5282 gen_op_mov_TN_reg(ot, 0, OR_EAX);
5283 gen_op_movl_T1_im(val);
5284 gen_op_testl_T0_T1_cc();
5285 set_cc_op(s, CC_OP_LOGICB + ot);
5286 break;
5288 case 0x98: /* CWDE/CBW */
5289 #ifdef TARGET_X86_64
5290 if (dflag == 2) {
5291 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5292 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5293 gen_op_mov_reg_T0(OT_QUAD, R_EAX);
5294 } else
5295 #endif
5296 if (dflag == 1) {
5297 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
5298 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5299 gen_op_mov_reg_T0(OT_LONG, R_EAX);
5300 } else {
5301 gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX);
5302 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5303 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5305 break;
5306 case 0x99: /* CDQ/CWD */
5307 #ifdef TARGET_X86_64
5308 if (dflag == 2) {
5309 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5310 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
5311 gen_op_mov_reg_T0(OT_QUAD, R_EDX);
5312 } else
5313 #endif
5314 if (dflag == 1) {
5315 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5316 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5317 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
5318 gen_op_mov_reg_T0(OT_LONG, R_EDX);
5319 } else {
5320 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
5321 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5322 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
5323 gen_op_mov_reg_T0(OT_WORD, R_EDX);
5325 break;
5326 case 0x1af: /* imul Gv, Ev */
5327 case 0x69: /* imul Gv, Ev, I */
5328 case 0x6b:
5329 ot = dflag + OT_WORD;
5330 modrm = cpu_ldub_code(env, s->pc++);
5331 reg = ((modrm >> 3) & 7) | rex_r;
5332 if (b == 0x69)
5333 s->rip_offset = insn_const_size(ot);
5334 else if (b == 0x6b)
5335 s->rip_offset = 1;
5336 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5337 if (b == 0x69) {
5338 val = insn_get(env, s, ot);
5339 gen_op_movl_T1_im(val);
5340 } else if (b == 0x6b) {
5341 val = (int8_t)insn_get(env, s, OT_BYTE);
5342 gen_op_movl_T1_im(val);
5343 } else {
5344 gen_op_mov_TN_reg(ot, 1, reg);
5346 switch (ot) {
5347 #ifdef TARGET_X86_64
5348 case OT_QUAD:
5349 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
5350 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5351 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5352 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
5353 break;
5354 #endif
5355 case OT_LONG:
5356 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5357 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5358 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5359 cpu_tmp2_i32, cpu_tmp3_i32);
5360 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5361 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5362 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5363 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5364 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5365 break;
5366 default:
5367 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5368 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5369 /* XXX: use 32 bit mul which could be faster */
5370 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5371 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5372 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5373 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5374 gen_op_mov_reg_T0(ot, reg);
5375 break;
5377 set_cc_op(s, CC_OP_MULB + ot);
5378 break;
5379 case 0x1c0:
5380 case 0x1c1: /* xadd Ev, Gv */
5381 if ((b & 1) == 0)
5382 ot = OT_BYTE;
5383 else
5384 ot = dflag + OT_WORD;
5385 modrm = cpu_ldub_code(env, s->pc++);
5386 reg = ((modrm >> 3) & 7) | rex_r;
5387 mod = (modrm >> 6) & 3;
5388 if (mod == 3) {
5389 rm = (modrm & 7) | REX_B(s);
5390 gen_op_mov_TN_reg(ot, 0, reg);
5391 gen_op_mov_TN_reg(ot, 1, rm);
5392 gen_op_addl_T0_T1();
5393 gen_op_mov_reg_T1(ot, reg);
5394 gen_op_mov_reg_T0(ot, rm);
5395 } else {
5396 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5397 gen_op_mov_TN_reg(ot, 0, reg);
5398 gen_op_ld_T1_A0(ot + s->mem_index);
5399 gen_op_addl_T0_T1();
5400 gen_op_st_T0_A0(ot + s->mem_index);
5401 gen_op_mov_reg_T1(ot, reg);
5403 gen_op_update2_cc();
5404 set_cc_op(s, CC_OP_ADDB + ot);
5405 break;
5406 case 0x1b0:
5407 case 0x1b1: /* cmpxchg Ev, Gv */
5409 int label1, label2;
5410 TCGv t0, t1, t2, a0;
5412 if ((b & 1) == 0)
5413 ot = OT_BYTE;
5414 else
5415 ot = dflag + OT_WORD;
5416 modrm = cpu_ldub_code(env, s->pc++);
5417 reg = ((modrm >> 3) & 7) | rex_r;
5418 mod = (modrm >> 6) & 3;
5419 t0 = tcg_temp_local_new();
5420 t1 = tcg_temp_local_new();
5421 t2 = tcg_temp_local_new();
5422 a0 = tcg_temp_local_new();
5423 gen_op_mov_v_reg(ot, t1, reg);
5424 if (mod == 3) {
5425 rm = (modrm & 7) | REX_B(s);
5426 gen_op_mov_v_reg(ot, t0, rm);
5427 } else {
5428 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5429 tcg_gen_mov_tl(a0, cpu_A0);
5430 gen_op_ld_v(ot + s->mem_index, t0, a0);
5431 rm = 0; /* avoid warning */
5433 label1 = gen_new_label();
5434 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5435 gen_extu(ot, t0);
5436 gen_extu(ot, t2);
5437 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
5438 label2 = gen_new_label();
5439 if (mod == 3) {
5440 gen_op_mov_reg_v(ot, R_EAX, t0);
5441 tcg_gen_br(label2);
5442 gen_set_label(label1);
5443 gen_op_mov_reg_v(ot, rm, t1);
5444 } else {
5445 /* perform no-op store cycle like physical cpu; must be
5446 before changing accumulator to ensure idempotency if
5447 the store faults and the instruction is restarted */
5448 gen_op_st_v(ot + s->mem_index, t0, a0);
5449 gen_op_mov_reg_v(ot, R_EAX, t0);
5450 tcg_gen_br(label2);
5451 gen_set_label(label1);
5452 gen_op_st_v(ot + s->mem_index, t1, a0);
5454 gen_set_label(label2);
5455 tcg_gen_mov_tl(cpu_cc_src, t0);
5456 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5457 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
5458 set_cc_op(s, CC_OP_SUBB + ot);
5459 tcg_temp_free(t0);
5460 tcg_temp_free(t1);
5461 tcg_temp_free(t2);
5462 tcg_temp_free(a0);
5464 break;
5465 case 0x1c7: /* cmpxchg8b */
5466 modrm = cpu_ldub_code(env, s->pc++);
5467 mod = (modrm >> 6) & 3;
5468 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5469 goto illegal_op;
5470 #ifdef TARGET_X86_64
5471 if (dflag == 2) {
5472 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5473 goto illegal_op;
5474 gen_jmp_im(pc_start - s->cs_base);
5475 gen_update_cc_op(s);
5476 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5477 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5478 } else
5479 #endif
5481 if (!(s->cpuid_features & CPUID_CX8))
5482 goto illegal_op;
5483 gen_jmp_im(pc_start - s->cs_base);
5484 gen_update_cc_op(s);
5485 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5486 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5488 set_cc_op(s, CC_OP_EFLAGS);
5489 break;
5491 /**************************/
5492 /* push/pop */
5493 case 0x50 ... 0x57: /* push */
5494 gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
5495 gen_push_T0(s);
5496 break;
5497 case 0x58 ... 0x5f: /* pop */
5498 if (CODE64(s)) {
5499 ot = dflag ? OT_QUAD : OT_WORD;
5500 } else {
5501 ot = dflag + OT_WORD;
5503 gen_pop_T0(s);
5504 /* NOTE: order is important for pop %sp */
5505 gen_pop_update(s);
5506 gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
5507 break;
5508 case 0x60: /* pusha */
5509 if (CODE64(s))
5510 goto illegal_op;
5511 gen_pusha(s);
5512 break;
5513 case 0x61: /* popa */
5514 if (CODE64(s))
5515 goto illegal_op;
5516 gen_popa(s);
5517 break;
5518 case 0x68: /* push Iv */
5519 case 0x6a:
5520 if (CODE64(s)) {
5521 ot = dflag ? OT_QUAD : OT_WORD;
5522 } else {
5523 ot = dflag + OT_WORD;
5525 if (b == 0x68)
5526 val = insn_get(env, s, ot);
5527 else
5528 val = (int8_t)insn_get(env, s, OT_BYTE);
5529 gen_op_movl_T0_im(val);
5530 gen_push_T0(s);
5531 break;
5532 case 0x8f: /* pop Ev */
5533 if (CODE64(s)) {
5534 ot = dflag ? OT_QUAD : OT_WORD;
5535 } else {
5536 ot = dflag + OT_WORD;
5538 modrm = cpu_ldub_code(env, s->pc++);
5539 mod = (modrm >> 6) & 3;
5540 gen_pop_T0(s);
5541 if (mod == 3) {
5542 /* NOTE: order is important for pop %sp */
5543 gen_pop_update(s);
5544 rm = (modrm & 7) | REX_B(s);
5545 gen_op_mov_reg_T0(ot, rm);
5546 } else {
5547 /* NOTE: order is important too for MMU exceptions */
5548 s->popl_esp_hack = 1 << ot;
5549 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5550 s->popl_esp_hack = 0;
5551 gen_pop_update(s);
5553 break;
5554 case 0xc8: /* enter */
5556 int level;
5557 val = cpu_lduw_code(env, s->pc);
5558 s->pc += 2;
5559 level = cpu_ldub_code(env, s->pc++);
5560 gen_enter(s, val, level);
5562 break;
5563 case 0xc9: /* leave */
5564 /* XXX: exception not precise (ESP is updated before potential exception) */
5565 if (CODE64(s)) {
5566 gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
5567 gen_op_mov_reg_T0(OT_QUAD, R_ESP);
5568 } else if (s->ss32) {
5569 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
5570 gen_op_mov_reg_T0(OT_LONG, R_ESP);
5571 } else {
5572 gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
5573 gen_op_mov_reg_T0(OT_WORD, R_ESP);
5575 gen_pop_T0(s);
5576 if (CODE64(s)) {
5577 ot = dflag ? OT_QUAD : OT_WORD;
5578 } else {
5579 ot = dflag + OT_WORD;
5581 gen_op_mov_reg_T0(ot, R_EBP);
5582 gen_pop_update(s);
5583 break;
5584 case 0x06: /* push es */
5585 case 0x0e: /* push cs */
5586 case 0x16: /* push ss */
5587 case 0x1e: /* push ds */
5588 if (CODE64(s))
5589 goto illegal_op;
5590 gen_op_movl_T0_seg(b >> 3);
5591 gen_push_T0(s);
5592 break;
5593 case 0x1a0: /* push fs */
5594 case 0x1a8: /* push gs */
5595 gen_op_movl_T0_seg((b >> 3) & 7);
5596 gen_push_T0(s);
5597 break;
5598 case 0x07: /* pop es */
5599 case 0x17: /* pop ss */
5600 case 0x1f: /* pop ds */
5601 if (CODE64(s))
5602 goto illegal_op;
5603 reg = b >> 3;
5604 gen_pop_T0(s);
5605 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5606 gen_pop_update(s);
5607 if (reg == R_SS) {
5608 /* if reg == SS, inhibit interrupts/trace. */
5609 /* If several instructions disable interrupts, only the
5610 _first_ does it */
5611 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5612 gen_helper_set_inhibit_irq(cpu_env);
5613 s->tf = 0;
5615 if (s->is_jmp) {
5616 gen_jmp_im(s->pc - s->cs_base);
5617 gen_eob(s);
5619 break;
5620 case 0x1a1: /* pop fs */
5621 case 0x1a9: /* pop gs */
5622 gen_pop_T0(s);
5623 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
5624 gen_pop_update(s);
5625 if (s->is_jmp) {
5626 gen_jmp_im(s->pc - s->cs_base);
5627 gen_eob(s);
5629 break;
5631 /**************************/
5632 /* mov */
5633 case 0x88:
5634 case 0x89: /* mov Gv, Ev */
5635 if ((b & 1) == 0)
5636 ot = OT_BYTE;
5637 else
5638 ot = dflag + OT_WORD;
5639 modrm = cpu_ldub_code(env, s->pc++);
5640 reg = ((modrm >> 3) & 7) | rex_r;
5642 /* generate a generic store */
5643 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5644 break;
5645 case 0xc6:
5646 case 0xc7: /* mov Ev, Iv */
5647 if ((b & 1) == 0)
5648 ot = OT_BYTE;
5649 else
5650 ot = dflag + OT_WORD;
5651 modrm = cpu_ldub_code(env, s->pc++);
5652 mod = (modrm >> 6) & 3;
5653 if (mod != 3) {
5654 s->rip_offset = insn_const_size(ot);
5655 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5657 val = insn_get(env, s, ot);
5658 gen_op_movl_T0_im(val);
5659 if (mod != 3)
5660 gen_op_st_T0_A0(ot + s->mem_index);
5661 else
5662 gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
5663 break;
5664 case 0x8a:
5665 case 0x8b: /* mov Ev, Gv */
5666 if ((b & 1) == 0)
5667 ot = OT_BYTE;
5668 else
5669 ot = OT_WORD + dflag;
5670 modrm = cpu_ldub_code(env, s->pc++);
5671 reg = ((modrm >> 3) & 7) | rex_r;
5673 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5674 gen_op_mov_reg_T0(ot, reg);
5675 break;
5676 case 0x8e: /* mov seg, Gv */
5677 modrm = cpu_ldub_code(env, s->pc++);
5678 reg = (modrm >> 3) & 7;
5679 if (reg >= 6 || reg == R_CS)
5680 goto illegal_op;
5681 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
5682 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5683 if (reg == R_SS) {
5684 /* if reg == SS, inhibit interrupts/trace */
5685 /* If several instructions disable interrupts, only the
5686 _first_ does it */
5687 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5688 gen_helper_set_inhibit_irq(cpu_env);
5689 s->tf = 0;
5691 if (s->is_jmp) {
5692 gen_jmp_im(s->pc - s->cs_base);
5693 gen_eob(s);
5695 break;
5696 case 0x8c: /* mov Gv, seg */
5697 modrm = cpu_ldub_code(env, s->pc++);
5698 reg = (modrm >> 3) & 7;
5699 mod = (modrm >> 6) & 3;
5700 if (reg >= 6)
5701 goto illegal_op;
5702 gen_op_movl_T0_seg(reg);
5703 if (mod == 3)
5704 ot = OT_WORD + dflag;
5705 else
5706 ot = OT_WORD;
5707 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5708 break;
5710 case 0x1b6: /* movzbS Gv, Eb */
5711 case 0x1b7: /* movzwS Gv, Eb */
5712 case 0x1be: /* movsbS Gv, Eb */
5713 case 0x1bf: /* movswS Gv, Eb */
5715 int d_ot;
5716 /* d_ot is the size of destination */
5717 d_ot = dflag + OT_WORD;
5718 /* ot is the size of source */
5719 ot = (b & 1) + OT_BYTE;
5720 modrm = cpu_ldub_code(env, s->pc++);
5721 reg = ((modrm >> 3) & 7) | rex_r;
5722 mod = (modrm >> 6) & 3;
5723 rm = (modrm & 7) | REX_B(s);
5725 if (mod == 3) {
5726 gen_op_mov_TN_reg(ot, 0, rm);
5727 switch(ot | (b & 8)) {
5728 case OT_BYTE:
5729 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
5730 break;
5731 case OT_BYTE | 8:
5732 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5733 break;
5734 case OT_WORD:
5735 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
5736 break;
5737 default:
5738 case OT_WORD | 8:
5739 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5740 break;
5742 gen_op_mov_reg_T0(d_ot, reg);
5743 } else {
5744 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5745 if (b & 8) {
5746 gen_op_lds_T0_A0(ot + s->mem_index);
5747 } else {
5748 gen_op_ldu_T0_A0(ot + s->mem_index);
5750 gen_op_mov_reg_T0(d_ot, reg);
5753 break;
5755 case 0x8d: /* lea */
5756 ot = dflag + OT_WORD;
5757 modrm = cpu_ldub_code(env, s->pc++);
5758 mod = (modrm >> 6) & 3;
5759 if (mod == 3)
5760 goto illegal_op;
5761 reg = ((modrm >> 3) & 7) | rex_r;
5762 /* we must ensure that no segment is added */
5763 s->override = -1;
5764 val = s->addseg;
5765 s->addseg = 0;
5766 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5767 s->addseg = val;
5768 gen_op_mov_reg_A0(ot - OT_WORD, reg);
5769 break;
5771 case 0xa0: /* mov EAX, Ov */
5772 case 0xa1:
5773 case 0xa2: /* mov Ov, EAX */
5774 case 0xa3:
5776 target_ulong offset_addr;
5778 if ((b & 1) == 0)
5779 ot = OT_BYTE;
5780 else
5781 ot = dflag + OT_WORD;
5782 #ifdef TARGET_X86_64
5783 if (s->aflag == 2) {
5784 offset_addr = cpu_ldq_code(env, s->pc);
5785 s->pc += 8;
5786 gen_op_movq_A0_im(offset_addr);
5787 } else
5788 #endif
5790 if (s->aflag) {
5791 offset_addr = insn_get(env, s, OT_LONG);
5792 } else {
5793 offset_addr = insn_get(env, s, OT_WORD);
5795 gen_op_movl_A0_im(offset_addr);
5797 gen_add_A0_ds_seg(s);
5798 if ((b & 2) == 0) {
5799 gen_op_ld_T0_A0(ot + s->mem_index);
5800 gen_op_mov_reg_T0(ot, R_EAX);
5801 } else {
5802 gen_op_mov_TN_reg(ot, 0, R_EAX);
5803 gen_op_st_T0_A0(ot + s->mem_index);
5806 break;
5807 case 0xd7: /* xlat */
5808 #ifdef TARGET_X86_64
5809 if (s->aflag == 2) {
5810 gen_op_movq_A0_reg(R_EBX);
5811 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5812 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5813 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5814 } else
5815 #endif
5817 gen_op_movl_A0_reg(R_EBX);
5818 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5819 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5820 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5821 if (s->aflag == 0)
5822 gen_op_andl_A0_ffff();
5823 else
5824 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
5826 gen_add_A0_ds_seg(s);
5827 gen_op_ldu_T0_A0(OT_BYTE + s->mem_index);
5828 gen_op_mov_reg_T0(OT_BYTE, R_EAX);
5829 break;
5830 case 0xb0 ... 0xb7: /* mov R, Ib */
5831 val = insn_get(env, s, OT_BYTE);
5832 gen_op_movl_T0_im(val);
5833 gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
5834 break;
5835 case 0xb8 ... 0xbf: /* mov R, Iv */
5836 #ifdef TARGET_X86_64
5837 if (dflag == 2) {
5838 uint64_t tmp;
5839 /* 64 bit case */
5840 tmp = cpu_ldq_code(env, s->pc);
5841 s->pc += 8;
5842 reg = (b & 7) | REX_B(s);
5843 gen_movtl_T0_im(tmp);
5844 gen_op_mov_reg_T0(OT_QUAD, reg);
5845 } else
5846 #endif
5848 ot = dflag ? OT_LONG : OT_WORD;
5849 val = insn_get(env, s, ot);
5850 reg = (b & 7) | REX_B(s);
5851 gen_op_movl_T0_im(val);
5852 gen_op_mov_reg_T0(ot, reg);
5854 break;
5856 case 0x91 ... 0x97: /* xchg R, EAX */
5857 do_xchg_reg_eax:
5858 ot = dflag + OT_WORD;
5859 reg = (b & 7) | REX_B(s);
5860 rm = R_EAX;
5861 goto do_xchg_reg;
5862 case 0x86:
5863 case 0x87: /* xchg Ev, Gv */
5864 if ((b & 1) == 0)
5865 ot = OT_BYTE;
5866 else
5867 ot = dflag + OT_WORD;
5868 modrm = cpu_ldub_code(env, s->pc++);
5869 reg = ((modrm >> 3) & 7) | rex_r;
5870 mod = (modrm >> 6) & 3;
5871 if (mod == 3) {
5872 rm = (modrm & 7) | REX_B(s);
5873 do_xchg_reg:
5874 gen_op_mov_TN_reg(ot, 0, reg);
5875 gen_op_mov_TN_reg(ot, 1, rm);
5876 gen_op_mov_reg_T0(ot, rm);
5877 gen_op_mov_reg_T1(ot, reg);
5878 } else {
5879 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5880 gen_op_mov_TN_reg(ot, 0, reg);
5881 /* for xchg, lock is implicit */
5882 if (!(prefixes & PREFIX_LOCK))
5883 gen_helper_lock();
5884 gen_op_ld_T1_A0(ot + s->mem_index);
5885 gen_op_st_T0_A0(ot + s->mem_index);
5886 if (!(prefixes & PREFIX_LOCK))
5887 gen_helper_unlock();
5888 gen_op_mov_reg_T1(ot, reg);
5890 break;
5891 case 0xc4: /* les Gv */
5892 /* In CODE64 this is VEX3; see above. */
5893 op = R_ES;
5894 goto do_lxx;
5895 case 0xc5: /* lds Gv */
5896 /* In CODE64 this is VEX2; see above. */
5897 op = R_DS;
5898 goto do_lxx;
5899 case 0x1b2: /* lss Gv */
5900 op = R_SS;
5901 goto do_lxx;
5902 case 0x1b4: /* lfs Gv */
5903 op = R_FS;
5904 goto do_lxx;
5905 case 0x1b5: /* lgs Gv */
5906 op = R_GS;
5907 do_lxx:
5908 ot = dflag ? OT_LONG : OT_WORD;
5909 modrm = cpu_ldub_code(env, s->pc++);
5910 reg = ((modrm >> 3) & 7) | rex_r;
5911 mod = (modrm >> 6) & 3;
5912 if (mod == 3)
5913 goto illegal_op;
5914 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5915 gen_op_ld_T1_A0(ot + s->mem_index);
5916 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
5917 /* load the segment first to handle exceptions properly */
5918 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
5919 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5920 /* then put the data */
5921 gen_op_mov_reg_T1(ot, reg);
5922 if (s->is_jmp) {
5923 gen_jmp_im(s->pc - s->cs_base);
5924 gen_eob(s);
5926 break;
5928 /************************/
5929 /* shifts */
5930 case 0xc0:
5931 case 0xc1:
5932 /* shift Ev,Ib */
5933 shift = 2;
5934 grp2:
5936 if ((b & 1) == 0)
5937 ot = OT_BYTE;
5938 else
5939 ot = dflag + OT_WORD;
5941 modrm = cpu_ldub_code(env, s->pc++);
5942 mod = (modrm >> 6) & 3;
5943 op = (modrm >> 3) & 7;
5945 if (mod != 3) {
5946 if (shift == 2) {
5947 s->rip_offset = 1;
5949 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5950 opreg = OR_TMP0;
5951 } else {
5952 opreg = (modrm & 7) | REX_B(s);
5955 /* simpler op */
5956 if (shift == 0) {
5957 gen_shift(s, op, ot, opreg, OR_ECX);
5958 } else {
5959 if (shift == 2) {
5960 shift = cpu_ldub_code(env, s->pc++);
5962 gen_shifti(s, op, ot, opreg, shift);
5965 break;
5966 case 0xd0:
5967 case 0xd1:
5968 /* shift Ev,1 */
5969 shift = 1;
5970 goto grp2;
5971 case 0xd2:
5972 case 0xd3:
5973 /* shift Ev,cl */
5974 shift = 0;
5975 goto grp2;
5977 case 0x1a4: /* shld imm */
5978 op = 0;
5979 shift = 1;
5980 goto do_shiftd;
5981 case 0x1a5: /* shld cl */
5982 op = 0;
5983 shift = 0;
5984 goto do_shiftd;
5985 case 0x1ac: /* shrd imm */
5986 op = 1;
5987 shift = 1;
5988 goto do_shiftd;
5989 case 0x1ad: /* shrd cl */
5990 op = 1;
5991 shift = 0;
5992 do_shiftd:
5993 ot = dflag + OT_WORD;
5994 modrm = cpu_ldub_code(env, s->pc++);
5995 mod = (modrm >> 6) & 3;
5996 rm = (modrm & 7) | REX_B(s);
5997 reg = ((modrm >> 3) & 7) | rex_r;
5998 if (mod != 3) {
5999 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
6000 opreg = OR_TMP0;
6001 } else {
6002 opreg = rm;
6004 gen_op_mov_TN_reg(ot, 1, reg);
6006 if (shift) {
6007 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
6008 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
6009 tcg_temp_free(imm);
6010 } else {
6011 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
6013 break;
6015 /************************/
6016 /* floats */
6017 case 0xd8 ... 0xdf:
6018 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
6019 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
6020 /* XXX: what to do if illegal op ? */
6021 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6022 break;
6024 modrm = cpu_ldub_code(env, s->pc++);
6025 mod = (modrm >> 6) & 3;
6026 rm = modrm & 7;
6027 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
6028 if (mod != 3) {
6029 /* memory op */
6030 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
6031 switch(op) {
6032 case 0x00 ... 0x07: /* fxxxs */
6033 case 0x10 ... 0x17: /* fixxxl */
6034 case 0x20 ... 0x27: /* fxxxl */
6035 case 0x30 ... 0x37: /* fixxx */
6037 int op1;
6038 op1 = op & 7;
6040 switch(op >> 4) {
6041 case 0:
6042 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
6043 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6044 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
6045 break;
6046 case 1:
6047 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
6048 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6049 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
6050 break;
6051 case 2:
6052 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
6053 (s->mem_index >> 2) - 1);
6054 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
6055 break;
6056 case 3:
6057 default:
6058 gen_op_lds_T0_A0(OT_WORD + s->mem_index);
6059 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6060 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
6061 break;
6064 gen_helper_fp_arith_ST0_FT0(op1);
6065 if (op1 == 3) {
6066 /* fcomp needs pop */
6067 gen_helper_fpop(cpu_env);
6070 break;
6071 case 0x08: /* flds */
6072 case 0x0a: /* fsts */
6073 case 0x0b: /* fstps */
6074 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
6075 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
6076 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
6077 switch(op & 7) {
6078 case 0:
6079 switch(op >> 4) {
6080 case 0:
6081 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
6082 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6083 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
6084 break;
6085 case 1:
6086 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
6087 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6088 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
6089 break;
6090 case 2:
6091 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
6092 (s->mem_index >> 2) - 1);
6093 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
6094 break;
6095 case 3:
6096 default:
6097 gen_op_lds_T0_A0(OT_WORD + s->mem_index);
6098 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6099 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
6100 break;
6102 break;
6103 case 1:
6104 /* XXX: the corresponding CPUID bit must be tested ! */
6105 switch(op >> 4) {
6106 case 1:
6107 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
6108 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6109 gen_op_st_T0_A0(OT_LONG + s->mem_index);
6110 break;
6111 case 2:
6112 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
6113 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
6114 (s->mem_index >> 2) - 1);
6115 break;
6116 case 3:
6117 default:
6118 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
6119 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6120 gen_op_st_T0_A0(OT_WORD + s->mem_index);
6121 break;
6123 gen_helper_fpop(cpu_env);
6124 break;
6125 default:
6126 switch(op >> 4) {
6127 case 0:
6128 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
6129 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6130 gen_op_st_T0_A0(OT_LONG + s->mem_index);
6131 break;
6132 case 1:
6133 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
6134 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6135 gen_op_st_T0_A0(OT_LONG + s->mem_index);
6136 break;
6137 case 2:
6138 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
6139 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
6140 (s->mem_index >> 2) - 1);
6141 break;
6142 case 3:
6143 default:
6144 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
6145 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6146 gen_op_st_T0_A0(OT_WORD + s->mem_index);
6147 break;
6149 if ((op & 7) == 3)
6150 gen_helper_fpop(cpu_env);
6151 break;
6153 break;
6154 case 0x0c: /* fldenv mem */
6155 gen_update_cc_op(s);
6156 gen_jmp_im(pc_start - s->cs_base);
6157 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
6158 break;
6159 case 0x0d: /* fldcw mem */
6160 gen_op_ld_T0_A0(OT_WORD + s->mem_index);
6161 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6162 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
6163 break;
6164 case 0x0e: /* fnstenv mem */
6165 gen_update_cc_op(s);
6166 gen_jmp_im(pc_start - s->cs_base);
6167 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
6168 break;
6169 case 0x0f: /* fnstcw mem */
6170 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
6171 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6172 gen_op_st_T0_A0(OT_WORD + s->mem_index);
6173 break;
6174 case 0x1d: /* fldt mem */
6175 gen_update_cc_op(s);
6176 gen_jmp_im(pc_start - s->cs_base);
6177 gen_helper_fldt_ST0(cpu_env, cpu_A0);
6178 break;
6179 case 0x1f: /* fstpt mem */
6180 gen_update_cc_op(s);
6181 gen_jmp_im(pc_start - s->cs_base);
6182 gen_helper_fstt_ST0(cpu_env, cpu_A0);
6183 gen_helper_fpop(cpu_env);
6184 break;
6185 case 0x2c: /* frstor mem */
6186 gen_update_cc_op(s);
6187 gen_jmp_im(pc_start - s->cs_base);
6188 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
6189 break;
6190 case 0x2e: /* fnsave mem */
6191 gen_update_cc_op(s);
6192 gen_jmp_im(pc_start - s->cs_base);
6193 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
6194 break;
6195 case 0x2f: /* fnstsw mem */
6196 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6197 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6198 gen_op_st_T0_A0(OT_WORD + s->mem_index);
6199 break;
6200 case 0x3c: /* fbld */
6201 gen_update_cc_op(s);
6202 gen_jmp_im(pc_start - s->cs_base);
6203 gen_helper_fbld_ST0(cpu_env, cpu_A0);
6204 break;
6205 case 0x3e: /* fbstp */
6206 gen_update_cc_op(s);
6207 gen_jmp_im(pc_start - s->cs_base);
6208 gen_helper_fbst_ST0(cpu_env, cpu_A0);
6209 gen_helper_fpop(cpu_env);
6210 break;
6211 case 0x3d: /* fildll */
6212 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
6213 (s->mem_index >> 2) - 1);
6214 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
6215 break;
6216 case 0x3f: /* fistpll */
6217 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
6218 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
6219 (s->mem_index >> 2) - 1);
6220 gen_helper_fpop(cpu_env);
6221 break;
6222 default:
6223 goto illegal_op;
6225 } else {
6226 /* register float ops */
6227 opreg = rm;
6229 switch(op) {
6230 case 0x08: /* fld sti */
6231 gen_helper_fpush(cpu_env);
6232 gen_helper_fmov_ST0_STN(cpu_env,
6233 tcg_const_i32((opreg + 1) & 7));
6234 break;
6235 case 0x09: /* fxchg sti */
6236 case 0x29: /* fxchg4 sti, undocumented op */
6237 case 0x39: /* fxchg7 sti, undocumented op */
6238 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
6239 break;
6240 case 0x0a: /* grp d9/2 */
6241 switch(rm) {
6242 case 0: /* fnop */
6243 /* check exceptions (FreeBSD FPU probe) */
6244 gen_update_cc_op(s);
6245 gen_jmp_im(pc_start - s->cs_base);
6246 gen_helper_fwait(cpu_env);
6247 break;
6248 default:
6249 goto illegal_op;
6251 break;
6252 case 0x0c: /* grp d9/4 */
6253 switch(rm) {
6254 case 0: /* fchs */
6255 gen_helper_fchs_ST0(cpu_env);
6256 break;
6257 case 1: /* fabs */
6258 gen_helper_fabs_ST0(cpu_env);
6259 break;
6260 case 4: /* ftst */
6261 gen_helper_fldz_FT0(cpu_env);
6262 gen_helper_fcom_ST0_FT0(cpu_env);
6263 break;
6264 case 5: /* fxam */
6265 gen_helper_fxam_ST0(cpu_env);
6266 break;
6267 default:
6268 goto illegal_op;
6270 break;
6271 case 0x0d: /* grp d9/5 */
6273 switch(rm) {
6274 case 0:
6275 gen_helper_fpush(cpu_env);
6276 gen_helper_fld1_ST0(cpu_env);
6277 break;
6278 case 1:
6279 gen_helper_fpush(cpu_env);
6280 gen_helper_fldl2t_ST0(cpu_env);
6281 break;
6282 case 2:
6283 gen_helper_fpush(cpu_env);
6284 gen_helper_fldl2e_ST0(cpu_env);
6285 break;
6286 case 3:
6287 gen_helper_fpush(cpu_env);
6288 gen_helper_fldpi_ST0(cpu_env);
6289 break;
6290 case 4:
6291 gen_helper_fpush(cpu_env);
6292 gen_helper_fldlg2_ST0(cpu_env);
6293 break;
6294 case 5:
6295 gen_helper_fpush(cpu_env);
6296 gen_helper_fldln2_ST0(cpu_env);
6297 break;
6298 case 6:
6299 gen_helper_fpush(cpu_env);
6300 gen_helper_fldz_ST0(cpu_env);
6301 break;
6302 default:
6303 goto illegal_op;
6306 break;
6307 case 0x0e: /* grp d9/6 */
6308 switch(rm) {
6309 case 0: /* f2xm1 */
6310 gen_helper_f2xm1(cpu_env);
6311 break;
6312 case 1: /* fyl2x */
6313 gen_helper_fyl2x(cpu_env);
6314 break;
6315 case 2: /* fptan */
6316 gen_helper_fptan(cpu_env);
6317 break;
6318 case 3: /* fpatan */
6319 gen_helper_fpatan(cpu_env);
6320 break;
6321 case 4: /* fxtract */
6322 gen_helper_fxtract(cpu_env);
6323 break;
6324 case 5: /* fprem1 */
6325 gen_helper_fprem1(cpu_env);
6326 break;
6327 case 6: /* fdecstp */
6328 gen_helper_fdecstp(cpu_env);
6329 break;
6330 default:
6331 case 7: /* fincstp */
6332 gen_helper_fincstp(cpu_env);
6333 break;
6335 break;
6336 case 0x0f: /* grp d9/7 */
6337 switch(rm) {
6338 case 0: /* fprem */
6339 gen_helper_fprem(cpu_env);
6340 break;
6341 case 1: /* fyl2xp1 */
6342 gen_helper_fyl2xp1(cpu_env);
6343 break;
6344 case 2: /* fsqrt */
6345 gen_helper_fsqrt(cpu_env);
6346 break;
6347 case 3: /* fsincos */
6348 gen_helper_fsincos(cpu_env);
6349 break;
6350 case 5: /* fscale */
6351 gen_helper_fscale(cpu_env);
6352 break;
6353 case 4: /* frndint */
6354 gen_helper_frndint(cpu_env);
6355 break;
6356 case 6: /* fsin */
6357 gen_helper_fsin(cpu_env);
6358 break;
6359 default:
6360 case 7: /* fcos */
6361 gen_helper_fcos(cpu_env);
6362 break;
6364 break;
6365 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6366 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6367 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6369 int op1;
6371 op1 = op & 7;
6372 if (op >= 0x20) {
6373 gen_helper_fp_arith_STN_ST0(op1, opreg);
6374 if (op >= 0x30)
6375 gen_helper_fpop(cpu_env);
6376 } else {
6377 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6378 gen_helper_fp_arith_ST0_FT0(op1);
6381 break;
6382 case 0x02: /* fcom */
6383 case 0x22: /* fcom2, undocumented op */
6384 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6385 gen_helper_fcom_ST0_FT0(cpu_env);
6386 break;
6387 case 0x03: /* fcomp */
6388 case 0x23: /* fcomp3, undocumented op */
6389 case 0x32: /* fcomp5, undocumented op */
6390 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6391 gen_helper_fcom_ST0_FT0(cpu_env);
6392 gen_helper_fpop(cpu_env);
6393 break;
6394 case 0x15: /* da/5 */
6395 switch(rm) {
6396 case 1: /* fucompp */
6397 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6398 gen_helper_fucom_ST0_FT0(cpu_env);
6399 gen_helper_fpop(cpu_env);
6400 gen_helper_fpop(cpu_env);
6401 break;
6402 default:
6403 goto illegal_op;
6405 break;
6406 case 0x1c:
6407 switch(rm) {
6408 case 0: /* feni (287 only, just do nop here) */
6409 break;
6410 case 1: /* fdisi (287 only, just do nop here) */
6411 break;
6412 case 2: /* fclex */
6413 gen_helper_fclex(cpu_env);
6414 break;
6415 case 3: /* fninit */
6416 gen_helper_fninit(cpu_env);
6417 break;
6418 case 4: /* fsetpm (287 only, just do nop here) */
6419 break;
6420 default:
6421 goto illegal_op;
6423 break;
6424 case 0x1d: /* fucomi */
6425 gen_update_cc_op(s);
6426 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6427 gen_helper_fucomi_ST0_FT0(cpu_env);
6428 set_cc_op(s, CC_OP_EFLAGS);
6429 break;
6430 case 0x1e: /* fcomi */
6431 gen_update_cc_op(s);
6432 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6433 gen_helper_fcomi_ST0_FT0(cpu_env);
6434 set_cc_op(s, CC_OP_EFLAGS);
6435 break;
6436 case 0x28: /* ffree sti */
6437 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6438 break;
6439 case 0x2a: /* fst sti */
6440 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6441 break;
6442 case 0x2b: /* fstp sti */
6443 case 0x0b: /* fstp1 sti, undocumented op */
6444 case 0x3a: /* fstp8 sti, undocumented op */
6445 case 0x3b: /* fstp9 sti, undocumented op */
6446 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6447 gen_helper_fpop(cpu_env);
6448 break;
6449 case 0x2c: /* fucom st(i) */
6450 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6451 gen_helper_fucom_ST0_FT0(cpu_env);
6452 break;
6453 case 0x2d: /* fucomp st(i) */
6454 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6455 gen_helper_fucom_ST0_FT0(cpu_env);
6456 gen_helper_fpop(cpu_env);
6457 break;
6458 case 0x33: /* de/3 */
6459 switch(rm) {
6460 case 1: /* fcompp */
6461 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6462 gen_helper_fcom_ST0_FT0(cpu_env);
6463 gen_helper_fpop(cpu_env);
6464 gen_helper_fpop(cpu_env);
6465 break;
6466 default:
6467 goto illegal_op;
6469 break;
6470 case 0x38: /* ffreep sti, undocumented op */
6471 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6472 gen_helper_fpop(cpu_env);
6473 break;
6474 case 0x3c: /* df/4 */
6475 switch(rm) {
6476 case 0:
6477 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6478 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6479 gen_op_mov_reg_T0(OT_WORD, R_EAX);
6480 break;
6481 default:
6482 goto illegal_op;
6484 break;
6485 case 0x3d: /* fucomip */
6486 gen_update_cc_op(s);
6487 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6488 gen_helper_fucomi_ST0_FT0(cpu_env);
6489 gen_helper_fpop(cpu_env);
6490 set_cc_op(s, CC_OP_EFLAGS);
6491 break;
6492 case 0x3e: /* fcomip */
6493 gen_update_cc_op(s);
6494 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6495 gen_helper_fcomi_ST0_FT0(cpu_env);
6496 gen_helper_fpop(cpu_env);
6497 set_cc_op(s, CC_OP_EFLAGS);
6498 break;
6499 case 0x10 ... 0x13: /* fcmovxx */
6500 case 0x18 ... 0x1b:
6502 int op1, l1;
6503 static const uint8_t fcmov_cc[8] = {
6504 (JCC_B << 1),
6505 (JCC_Z << 1),
6506 (JCC_BE << 1),
6507 (JCC_P << 1),
6509 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6510 l1 = gen_new_label();
6511 gen_jcc1_noeob(s, op1, l1);
6512 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6513 gen_set_label(l1);
6515 break;
6516 default:
6517 goto illegal_op;
6520 break;
6521 /************************/
6522 /* string ops */
6524 case 0xa4: /* movsS */
6525 case 0xa5:
6526 if ((b & 1) == 0)
6527 ot = OT_BYTE;
6528 else
6529 ot = dflag + OT_WORD;
6531 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6532 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6533 } else {
6534 gen_movs(s, ot);
6536 break;
6538 case 0xaa: /* stosS */
6539 case 0xab:
6540 if ((b & 1) == 0)
6541 ot = OT_BYTE;
6542 else
6543 ot = dflag + OT_WORD;
6545 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6546 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6547 } else {
6548 gen_stos(s, ot);
6550 break;
6551 case 0xac: /* lodsS */
6552 case 0xad:
6553 if ((b & 1) == 0)
6554 ot = OT_BYTE;
6555 else
6556 ot = dflag + OT_WORD;
6557 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6558 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6559 } else {
6560 gen_lods(s, ot);
6562 break;
6563 case 0xae: /* scasS */
6564 case 0xaf:
6565 if ((b & 1) == 0)
6566 ot = OT_BYTE;
6567 else
6568 ot = dflag + OT_WORD;
6569 if (prefixes & PREFIX_REPNZ) {
6570 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6571 } else if (prefixes & PREFIX_REPZ) {
6572 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6573 } else {
6574 gen_scas(s, ot);
6576 break;
6578 case 0xa6: /* cmpsS */
6579 case 0xa7:
6580 if ((b & 1) == 0)
6581 ot = OT_BYTE;
6582 else
6583 ot = dflag + OT_WORD;
6584 if (prefixes & PREFIX_REPNZ) {
6585 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6586 } else if (prefixes & PREFIX_REPZ) {
6587 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6588 } else {
6589 gen_cmps(s, ot);
6591 break;
6592 case 0x6c: /* insS */
6593 case 0x6d:
6594 if ((b & 1) == 0)
6595 ot = OT_BYTE;
6596 else
6597 ot = dflag ? OT_LONG : OT_WORD;
6598 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
6599 gen_op_andl_T0_ffff();
6600 gen_check_io(s, ot, pc_start - s->cs_base,
6601 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6602 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6603 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6604 } else {
6605 gen_ins(s, ot);
6606 if (use_icount) {
6607 gen_jmp(s, s->pc - s->cs_base);
6610 break;
6611 case 0x6e: /* outsS */
6612 case 0x6f:
6613 if ((b & 1) == 0)
6614 ot = OT_BYTE;
6615 else
6616 ot = dflag ? OT_LONG : OT_WORD;
6617 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
6618 gen_op_andl_T0_ffff();
6619 gen_check_io(s, ot, pc_start - s->cs_base,
6620 svm_is_rep(prefixes) | 4);
6621 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6622 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6623 } else {
6624 gen_outs(s, ot);
6625 if (use_icount) {
6626 gen_jmp(s, s->pc - s->cs_base);
6629 break;
6631 /************************/
6632 /* port I/O */
6634 case 0xe4:
6635 case 0xe5:
6636 if ((b & 1) == 0)
6637 ot = OT_BYTE;
6638 else
6639 ot = dflag ? OT_LONG : OT_WORD;
6640 val = cpu_ldub_code(env, s->pc++);
6641 gen_op_movl_T0_im(val);
6642 gen_check_io(s, ot, pc_start - s->cs_base,
6643 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6644 if (use_icount)
6645 gen_io_start();
6646 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6647 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6648 gen_op_mov_reg_T1(ot, R_EAX);
6649 if (use_icount) {
6650 gen_io_end();
6651 gen_jmp(s, s->pc - s->cs_base);
6653 break;
6654 case 0xe6:
6655 case 0xe7:
6656 if ((b & 1) == 0)
6657 ot = OT_BYTE;
6658 else
6659 ot = dflag ? OT_LONG : OT_WORD;
6660 val = cpu_ldub_code(env, s->pc++);
6661 gen_op_movl_T0_im(val);
6662 gen_check_io(s, ot, pc_start - s->cs_base,
6663 svm_is_rep(prefixes));
6664 gen_op_mov_TN_reg(ot, 1, R_EAX);
6666 if (use_icount)
6667 gen_io_start();
6668 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6669 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6670 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6671 if (use_icount) {
6672 gen_io_end();
6673 gen_jmp(s, s->pc - s->cs_base);
6675 break;
6676 case 0xec:
6677 case 0xed:
6678 if ((b & 1) == 0)
6679 ot = OT_BYTE;
6680 else
6681 ot = dflag ? OT_LONG : OT_WORD;
6682 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
6683 gen_op_andl_T0_ffff();
6684 gen_check_io(s, ot, pc_start - s->cs_base,
6685 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6686 if (use_icount)
6687 gen_io_start();
6688 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6689 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6690 gen_op_mov_reg_T1(ot, R_EAX);
6691 if (use_icount) {
6692 gen_io_end();
6693 gen_jmp(s, s->pc - s->cs_base);
6695 break;
6696 case 0xee:
6697 case 0xef:
6698 if ((b & 1) == 0)
6699 ot = OT_BYTE;
6700 else
6701 ot = dflag ? OT_LONG : OT_WORD;
6702 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
6703 gen_op_andl_T0_ffff();
6704 gen_check_io(s, ot, pc_start - s->cs_base,
6705 svm_is_rep(prefixes));
6706 gen_op_mov_TN_reg(ot, 1, R_EAX);
6708 if (use_icount)
6709 gen_io_start();
6710 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6711 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6712 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6713 if (use_icount) {
6714 gen_io_end();
6715 gen_jmp(s, s->pc - s->cs_base);
6717 break;
6719 /************************/
6720 /* control */
6721 case 0xc2: /* ret im */
6722 val = cpu_ldsw_code(env, s->pc);
6723 s->pc += 2;
6724 gen_pop_T0(s);
6725 if (CODE64(s) && s->dflag)
6726 s->dflag = 2;
6727 gen_stack_update(s, val + (2 << s->dflag));
6728 if (s->dflag == 0)
6729 gen_op_andl_T0_ffff();
6730 gen_op_jmp_T0();
6731 gen_eob(s);
6732 break;
6733 case 0xc3: /* ret */
6734 gen_pop_T0(s);
6735 gen_pop_update(s);
6736 if (s->dflag == 0)
6737 gen_op_andl_T0_ffff();
6738 gen_op_jmp_T0();
6739 gen_eob(s);
6740 break;
6741 case 0xca: /* lret im */
6742 val = cpu_ldsw_code(env, s->pc);
6743 s->pc += 2;
6744 do_lret:
6745 if (s->pe && !s->vm86) {
6746 gen_update_cc_op(s);
6747 gen_jmp_im(pc_start - s->cs_base);
6748 gen_helper_lret_protected(cpu_env, tcg_const_i32(s->dflag),
6749 tcg_const_i32(val));
6750 } else {
6751 gen_stack_A0(s);
6752 /* pop offset */
6753 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
6754 if (s->dflag == 0)
6755 gen_op_andl_T0_ffff();
6756 /* NOTE: keeping EIP updated is not a problem in case of
6757 exception */
6758 gen_op_jmp_T0();
6759 /* pop selector */
6760 gen_op_addl_A0_im(2 << s->dflag);
6761 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
6762 gen_op_movl_seg_T0_vm(R_CS);
6763 /* add stack offset */
6764 gen_stack_update(s, val + (4 << s->dflag));
6766 gen_eob(s);
6767 break;
6768 case 0xcb: /* lret */
6769 val = 0;
6770 goto do_lret;
6771 case 0xcf: /* iret */
6772 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6773 if (!s->pe) {
6774 /* real mode */
6775 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
6776 set_cc_op(s, CC_OP_EFLAGS);
6777 } else if (s->vm86) {
6778 if (s->iopl != 3) {
6779 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6780 } else {
6781 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
6782 set_cc_op(s, CC_OP_EFLAGS);
6784 } else {
6785 gen_update_cc_op(s);
6786 gen_jmp_im(pc_start - s->cs_base);
6787 gen_helper_iret_protected(cpu_env, tcg_const_i32(s->dflag),
6788 tcg_const_i32(s->pc - s->cs_base));
6789 set_cc_op(s, CC_OP_EFLAGS);
6791 gen_eob(s);
6792 break;
6793 case 0xe8: /* call im */
6795 if (dflag)
6796 tval = (int32_t)insn_get(env, s, OT_LONG);
6797 else
6798 tval = (int16_t)insn_get(env, s, OT_WORD);
6799 next_eip = s->pc - s->cs_base;
6800 tval += next_eip;
6801 if (s->dflag == 0)
6802 tval &= 0xffff;
6803 else if(!CODE64(s))
6804 tval &= 0xffffffff;
6805 gen_movtl_T0_im(next_eip);
6806 gen_push_T0(s);
6807 gen_jmp(s, tval);
6809 break;
6810 case 0x9a: /* lcall im */
6812 unsigned int selector, offset;
6814 if (CODE64(s))
6815 goto illegal_op;
6816 ot = dflag ? OT_LONG : OT_WORD;
6817 offset = insn_get(env, s, ot);
6818 selector = insn_get(env, s, OT_WORD);
6820 gen_op_movl_T0_im(selector);
6821 gen_op_movl_T1_imu(offset);
6823 goto do_lcall;
6824 case 0xe9: /* jmp im */
6825 if (dflag)
6826 tval = (int32_t)insn_get(env, s, OT_LONG);
6827 else
6828 tval = (int16_t)insn_get(env, s, OT_WORD);
6829 tval += s->pc - s->cs_base;
6830 if (s->dflag == 0)
6831 tval &= 0xffff;
6832 else if(!CODE64(s))
6833 tval &= 0xffffffff;
6834 gen_jmp(s, tval);
6835 break;
6836 case 0xea: /* ljmp im */
6838 unsigned int selector, offset;
6840 if (CODE64(s))
6841 goto illegal_op;
6842 ot = dflag ? OT_LONG : OT_WORD;
6843 offset = insn_get(env, s, ot);
6844 selector = insn_get(env, s, OT_WORD);
6846 gen_op_movl_T0_im(selector);
6847 gen_op_movl_T1_imu(offset);
6849 goto do_ljmp;
6850 case 0xeb: /* jmp Jb */
6851 tval = (int8_t)insn_get(env, s, OT_BYTE);
6852 tval += s->pc - s->cs_base;
6853 if (s->dflag == 0)
6854 tval &= 0xffff;
6855 gen_jmp(s, tval);
6856 break;
6857 case 0x70 ... 0x7f: /* jcc Jb */
6858 tval = (int8_t)insn_get(env, s, OT_BYTE);
6859 goto do_jcc;
6860 case 0x180 ... 0x18f: /* jcc Jv */
6861 if (dflag) {
6862 tval = (int32_t)insn_get(env, s, OT_LONG);
6863 } else {
6864 tval = (int16_t)insn_get(env, s, OT_WORD);
6866 do_jcc:
6867 next_eip = s->pc - s->cs_base;
6868 tval += next_eip;
6869 if (s->dflag == 0)
6870 tval &= 0xffff;
6871 gen_jcc(s, b, tval, next_eip);
6872 break;
6874 case 0x190 ... 0x19f: /* setcc Gv */
6875 modrm = cpu_ldub_code(env, s->pc++);
6876 gen_setcc1(s, b, cpu_T[0]);
6877 gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1);
6878 break;
6879 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6880 ot = dflag + OT_WORD;
6881 modrm = cpu_ldub_code(env, s->pc++);
6882 reg = ((modrm >> 3) & 7) | rex_r;
6883 gen_cmovcc1(env, s, ot, b, modrm, reg);
6884 break;
6886 /************************/
6887 /* flags */
6888 case 0x9c: /* pushf */
6889 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6890 if (s->vm86 && s->iopl != 3) {
6891 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6892 } else {
6893 gen_update_cc_op(s);
6894 gen_helper_read_eflags(cpu_T[0], cpu_env);
6895 gen_push_T0(s);
6897 break;
6898 case 0x9d: /* popf */
6899 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6900 if (s->vm86 && s->iopl != 3) {
6901 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6902 } else {
6903 gen_pop_T0(s);
6904 if (s->cpl == 0) {
6905 if (s->dflag) {
6906 gen_helper_write_eflags(cpu_env, cpu_T[0],
6907 tcg_const_i32((TF_MASK | AC_MASK |
6908 ID_MASK | NT_MASK |
6909 IF_MASK |
6910 IOPL_MASK)));
6911 } else {
6912 gen_helper_write_eflags(cpu_env, cpu_T[0],
6913 tcg_const_i32((TF_MASK | AC_MASK |
6914 ID_MASK | NT_MASK |
6915 IF_MASK | IOPL_MASK)
6916 & 0xffff));
6918 } else {
6919 if (s->cpl <= s->iopl) {
6920 if (s->dflag) {
6921 gen_helper_write_eflags(cpu_env, cpu_T[0],
6922 tcg_const_i32((TF_MASK |
6923 AC_MASK |
6924 ID_MASK |
6925 NT_MASK |
6926 IF_MASK)));
6927 } else {
6928 gen_helper_write_eflags(cpu_env, cpu_T[0],
6929 tcg_const_i32((TF_MASK |
6930 AC_MASK |
6931 ID_MASK |
6932 NT_MASK |
6933 IF_MASK)
6934 & 0xffff));
6936 } else {
6937 if (s->dflag) {
6938 gen_helper_write_eflags(cpu_env, cpu_T[0],
6939 tcg_const_i32((TF_MASK | AC_MASK |
6940 ID_MASK | NT_MASK)));
6941 } else {
6942 gen_helper_write_eflags(cpu_env, cpu_T[0],
6943 tcg_const_i32((TF_MASK | AC_MASK |
6944 ID_MASK | NT_MASK)
6945 & 0xffff));
6949 gen_pop_update(s);
6950 set_cc_op(s, CC_OP_EFLAGS);
6951 /* abort translation because TF/AC flag may change */
6952 gen_jmp_im(s->pc - s->cs_base);
6953 gen_eob(s);
6955 break;
6956 case 0x9e: /* sahf */
6957 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6958 goto illegal_op;
6959 gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
6960 gen_compute_eflags(s);
6961 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6962 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6963 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
6964 break;
6965 case 0x9f: /* lahf */
6966 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6967 goto illegal_op;
6968 gen_compute_eflags(s);
6969 /* Note: gen_compute_eflags() only gives the condition codes */
6970 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
6971 gen_op_mov_reg_T0(OT_BYTE, R_AH);
6972 break;
6973 case 0xf5: /* cmc */
6974 gen_compute_eflags(s);
6975 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6976 break;
6977 case 0xf8: /* clc */
6978 gen_compute_eflags(s);
6979 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6980 break;
6981 case 0xf9: /* stc */
6982 gen_compute_eflags(s);
6983 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6984 break;
6985 case 0xfc: /* cld */
6986 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6987 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6988 break;
6989 case 0xfd: /* std */
6990 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6991 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6992 break;
6994 /************************/
6995 /* bit operations */
6996 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6997 ot = dflag + OT_WORD;
6998 modrm = cpu_ldub_code(env, s->pc++);
6999 op = (modrm >> 3) & 7;
7000 mod = (modrm >> 6) & 3;
7001 rm = (modrm & 7) | REX_B(s);
7002 if (mod != 3) {
7003 s->rip_offset = 1;
7004 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7005 gen_op_ld_T0_A0(ot + s->mem_index);
7006 } else {
7007 gen_op_mov_TN_reg(ot, 0, rm);
7009 /* load shift */
7010 val = cpu_ldub_code(env, s->pc++);
7011 gen_op_movl_T1_im(val);
7012 if (op < 4)
7013 goto illegal_op;
7014 op -= 4;
7015 goto bt_op;
7016 case 0x1a3: /* bt Gv, Ev */
7017 op = 0;
7018 goto do_btx;
7019 case 0x1ab: /* bts */
7020 op = 1;
7021 goto do_btx;
7022 case 0x1b3: /* btr */
7023 op = 2;
7024 goto do_btx;
7025 case 0x1bb: /* btc */
7026 op = 3;
7027 do_btx:
7028 ot = dflag + OT_WORD;
7029 modrm = cpu_ldub_code(env, s->pc++);
7030 reg = ((modrm >> 3) & 7) | rex_r;
7031 mod = (modrm >> 6) & 3;
7032 rm = (modrm & 7) | REX_B(s);
7033 gen_op_mov_TN_reg(OT_LONG, 1, reg);
7034 if (mod != 3) {
7035 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7036 /* specific case: we need to add a displacement */
7037 gen_exts(ot, cpu_T[1]);
7038 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
7039 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
7040 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
7041 gen_op_ld_T0_A0(ot + s->mem_index);
7042 } else {
7043 gen_op_mov_TN_reg(ot, 0, rm);
7045 bt_op:
7046 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
7047 switch(op) {
7048 case 0:
7049 tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
7050 tcg_gen_movi_tl(cpu_cc_dst, 0);
7051 break;
7052 case 1:
7053 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7054 tcg_gen_movi_tl(cpu_tmp0, 1);
7055 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7056 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7057 break;
7058 case 2:
7059 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7060 tcg_gen_movi_tl(cpu_tmp0, 1);
7061 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7062 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
7063 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7064 break;
7065 default:
7066 case 3:
7067 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
7068 tcg_gen_movi_tl(cpu_tmp0, 1);
7069 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
7070 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
7071 break;
7073 set_cc_op(s, CC_OP_SARB + ot);
7074 if (op != 0) {
7075 if (mod != 3)
7076 gen_op_st_T0_A0(ot + s->mem_index);
7077 else
7078 gen_op_mov_reg_T0(ot, rm);
7079 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
7080 tcg_gen_movi_tl(cpu_cc_dst, 0);
7082 break;
7083 case 0x1bc: /* bsf / tzcnt */
7084 case 0x1bd: /* bsr / lzcnt */
7085 ot = dflag + OT_WORD;
7086 modrm = cpu_ldub_code(env, s->pc++);
7087 reg = ((modrm >> 3) & 7) | rex_r;
7088 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7089 gen_extu(ot, cpu_T[0]);
7091 /* Note that lzcnt and tzcnt are in different extensions. */
7092 if ((prefixes & PREFIX_REPZ)
7093 && (b & 1
7094 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
7095 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
7096 int size = 8 << ot;
7097 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
7098 if (b & 1) {
7099 /* For lzcnt, reduce the target_ulong result by the
7100 number of zeros that we expect to find at the top. */
7101 gen_helper_clz(cpu_T[0], cpu_T[0]);
7102 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - size);
7103 } else {
7104 /* For tzcnt, a zero input must return the operand size:
7105 force all bits outside the operand size to 1. */
7106 target_ulong mask = (target_ulong)-2 << (size - 1);
7107 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], mask);
7108 gen_helper_ctz(cpu_T[0], cpu_T[0]);
7110 /* For lzcnt/tzcnt, C and Z bits are defined and are
7111 related to the result. */
7112 gen_op_update1_cc();
7113 set_cc_op(s, CC_OP_BMILGB + ot);
7114 } else {
7115 /* For bsr/bsf, only the Z bit is defined and it is related
7116 to the input and not the result. */
7117 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
7118 set_cc_op(s, CC_OP_LOGICB + ot);
7119 if (b & 1) {
7120 /* For bsr, return the bit index of the first 1 bit,
7121 not the count of leading zeros. */
7122 gen_helper_clz(cpu_T[0], cpu_T[0]);
7123 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - 1);
7124 } else {
7125 gen_helper_ctz(cpu_T[0], cpu_T[0]);
7127 /* ??? The manual says that the output is undefined when the
7128 input is zero, but real hardware leaves it unchanged, and
7129 real programs appear to depend on that. */
7130 tcg_gen_movi_tl(cpu_tmp0, 0);
7131 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[0], cpu_cc_dst, cpu_tmp0,
7132 cpu_regs[reg], cpu_T[0]);
7134 gen_op_mov_reg_T0(ot, reg);
7135 break;
7136 /************************/
7137 /* bcd */
7138 case 0x27: /* daa */
7139 if (CODE64(s))
7140 goto illegal_op;
7141 gen_update_cc_op(s);
7142 gen_helper_daa(cpu_env);
7143 set_cc_op(s, CC_OP_EFLAGS);
7144 break;
7145 case 0x2f: /* das */
7146 if (CODE64(s))
7147 goto illegal_op;
7148 gen_update_cc_op(s);
7149 gen_helper_das(cpu_env);
7150 set_cc_op(s, CC_OP_EFLAGS);
7151 break;
7152 case 0x37: /* aaa */
7153 if (CODE64(s))
7154 goto illegal_op;
7155 gen_update_cc_op(s);
7156 gen_helper_aaa(cpu_env);
7157 set_cc_op(s, CC_OP_EFLAGS);
7158 break;
7159 case 0x3f: /* aas */
7160 if (CODE64(s))
7161 goto illegal_op;
7162 gen_update_cc_op(s);
7163 gen_helper_aas(cpu_env);
7164 set_cc_op(s, CC_OP_EFLAGS);
7165 break;
7166 case 0xd4: /* aam */
7167 if (CODE64(s))
7168 goto illegal_op;
7169 val = cpu_ldub_code(env, s->pc++);
7170 if (val == 0) {
7171 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7172 } else {
7173 gen_helper_aam(cpu_env, tcg_const_i32(val));
7174 set_cc_op(s, CC_OP_LOGICB);
7176 break;
7177 case 0xd5: /* aad */
7178 if (CODE64(s))
7179 goto illegal_op;
7180 val = cpu_ldub_code(env, s->pc++);
7181 gen_helper_aad(cpu_env, tcg_const_i32(val));
7182 set_cc_op(s, CC_OP_LOGICB);
7183 break;
7184 /************************/
7185 /* misc */
7186 case 0x90: /* nop */
7187 /* XXX: correct lock test for all insn */
7188 if (prefixes & PREFIX_LOCK) {
7189 goto illegal_op;
7191 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
7192 if (REX_B(s)) {
7193 goto do_xchg_reg_eax;
7195 if (prefixes & PREFIX_REPZ) {
7196 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
7198 break;
7199 case 0x9b: /* fwait */
7200 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7201 (HF_MP_MASK | HF_TS_MASK)) {
7202 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7203 } else {
7204 gen_update_cc_op(s);
7205 gen_jmp_im(pc_start - s->cs_base);
7206 gen_helper_fwait(cpu_env);
7208 break;
7209 case 0xcc: /* int3 */
7210 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7211 break;
7212 case 0xcd: /* int N */
7213 val = cpu_ldub_code(env, s->pc++);
7214 if (s->vm86 && s->iopl != 3) {
7215 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7216 } else {
7217 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7219 break;
7220 case 0xce: /* into */
7221 if (CODE64(s))
7222 goto illegal_op;
7223 gen_update_cc_op(s);
7224 gen_jmp_im(pc_start - s->cs_base);
7225 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
7226 break;
7227 #ifdef WANT_ICEBP
7228 case 0xf1: /* icebp (undocumented, exits to external debugger) */
7229 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
7230 #if 1
7231 gen_debug(s, pc_start - s->cs_base);
7232 #else
7233 /* start debug */
7234 tb_flush(env);
7235 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
7236 #endif
7237 break;
7238 #endif
7239 case 0xfa: /* cli */
7240 if (!s->vm86) {
7241 if (s->cpl <= s->iopl) {
7242 gen_helper_cli(cpu_env);
7243 } else {
7244 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7246 } else {
7247 if (s->iopl == 3) {
7248 gen_helper_cli(cpu_env);
7249 } else {
7250 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7253 break;
7254 case 0xfb: /* sti */
7255 if (!s->vm86) {
7256 if (s->cpl <= s->iopl) {
7257 gen_sti:
7258 gen_helper_sti(cpu_env);
7259 /* interruptions are enabled only the first insn after sti */
7260 /* If several instructions disable interrupts, only the
7261 _first_ does it */
7262 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
7263 gen_helper_set_inhibit_irq(cpu_env);
7264 /* give a chance to handle pending irqs */
7265 gen_jmp_im(s->pc - s->cs_base);
7266 gen_eob(s);
7267 } else {
7268 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7270 } else {
7271 if (s->iopl == 3) {
7272 goto gen_sti;
7273 } else {
7274 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7277 break;
7278 case 0x62: /* bound */
7279 if (CODE64(s))
7280 goto illegal_op;
7281 ot = dflag ? OT_LONG : OT_WORD;
7282 modrm = cpu_ldub_code(env, s->pc++);
7283 reg = (modrm >> 3) & 7;
7284 mod = (modrm >> 6) & 3;
7285 if (mod == 3)
7286 goto illegal_op;
7287 gen_op_mov_TN_reg(ot, 0, reg);
7288 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7289 gen_jmp_im(pc_start - s->cs_base);
7290 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7291 if (ot == OT_WORD) {
7292 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
7293 } else {
7294 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
7296 break;
7297 case 0x1c8 ... 0x1cf: /* bswap reg */
7298 reg = (b & 7) | REX_B(s);
7299 #ifdef TARGET_X86_64
7300 if (dflag == 2) {
7301 gen_op_mov_TN_reg(OT_QUAD, 0, reg);
7302 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
7303 gen_op_mov_reg_T0(OT_QUAD, reg);
7304 } else
7305 #endif
7307 gen_op_mov_TN_reg(OT_LONG, 0, reg);
7308 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
7309 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
7310 gen_op_mov_reg_T0(OT_LONG, reg);
7312 break;
7313 case 0xd6: /* salc */
7314 if (CODE64(s))
7315 goto illegal_op;
7316 gen_compute_eflags_c(s, cpu_T[0]);
7317 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
7318 gen_op_mov_reg_T0(OT_BYTE, R_EAX);
7319 break;
7320 case 0xe0: /* loopnz */
7321 case 0xe1: /* loopz */
7322 case 0xe2: /* loop */
7323 case 0xe3: /* jecxz */
7325 int l1, l2, l3;
7327 tval = (int8_t)insn_get(env, s, OT_BYTE);
7328 next_eip = s->pc - s->cs_base;
7329 tval += next_eip;
7330 if (s->dflag == 0)
7331 tval &= 0xffff;
7333 l1 = gen_new_label();
7334 l2 = gen_new_label();
7335 l3 = gen_new_label();
7336 b &= 3;
7337 switch(b) {
7338 case 0: /* loopnz */
7339 case 1: /* loopz */
7340 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7341 gen_op_jz_ecx(s->aflag, l3);
7342 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7343 break;
7344 case 2: /* loop */
7345 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7346 gen_op_jnz_ecx(s->aflag, l1);
7347 break;
7348 default:
7349 case 3: /* jcxz */
7350 gen_op_jz_ecx(s->aflag, l1);
7351 break;
7354 gen_set_label(l3);
7355 gen_jmp_im(next_eip);
7356 tcg_gen_br(l2);
7358 gen_set_label(l1);
7359 gen_jmp_im(tval);
7360 gen_set_label(l2);
7361 gen_eob(s);
7363 break;
7364 case 0x130: /* wrmsr */
7365 case 0x132: /* rdmsr */
7366 if (s->cpl != 0) {
7367 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7368 } else {
7369 gen_update_cc_op(s);
7370 gen_jmp_im(pc_start - s->cs_base);
7371 if (b & 2) {
7372 gen_helper_rdmsr(cpu_env);
7373 } else {
7374 gen_helper_wrmsr(cpu_env);
7377 break;
7378 case 0x131: /* rdtsc */
7379 gen_update_cc_op(s);
7380 gen_jmp_im(pc_start - s->cs_base);
7381 if (use_icount)
7382 gen_io_start();
7383 gen_helper_rdtsc(cpu_env);
7384 if (use_icount) {
7385 gen_io_end();
7386 gen_jmp(s, s->pc - s->cs_base);
7388 break;
7389 case 0x133: /* rdpmc */
7390 gen_update_cc_op(s);
7391 gen_jmp_im(pc_start - s->cs_base);
7392 gen_helper_rdpmc(cpu_env);
7393 break;
7394 case 0x134: /* sysenter */
7395 /* For Intel SYSENTER is valid on 64-bit */
7396 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7397 goto illegal_op;
7398 if (!s->pe) {
7399 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7400 } else {
7401 gen_update_cc_op(s);
7402 gen_jmp_im(pc_start - s->cs_base);
7403 gen_helper_sysenter(cpu_env);
7404 gen_eob(s);
7406 break;
7407 case 0x135: /* sysexit */
7408 /* For Intel SYSEXIT is valid on 64-bit */
7409 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7410 goto illegal_op;
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_sysexit(cpu_env, tcg_const_i32(dflag));
7417 gen_eob(s);
7419 break;
7420 #ifdef TARGET_X86_64
7421 case 0x105: /* syscall */
7422 /* XXX: is it usable in real mode ? */
7423 gen_update_cc_op(s);
7424 gen_jmp_im(pc_start - s->cs_base);
7425 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7426 gen_eob(s);
7427 break;
7428 case 0x107: /* sysret */
7429 if (!s->pe) {
7430 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7431 } else {
7432 gen_update_cc_op(s);
7433 gen_jmp_im(pc_start - s->cs_base);
7434 gen_helper_sysret(cpu_env, tcg_const_i32(s->dflag));
7435 /* condition codes are modified only in long mode */
7436 if (s->lma) {
7437 set_cc_op(s, CC_OP_EFLAGS);
7439 gen_eob(s);
7441 break;
7442 #endif
7443 case 0x1a2: /* cpuid */
7444 gen_update_cc_op(s);
7445 gen_jmp_im(pc_start - s->cs_base);
7446 gen_helper_cpuid(cpu_env);
7447 break;
7448 case 0xf4: /* hlt */
7449 if (s->cpl != 0) {
7450 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7451 } else {
7452 gen_update_cc_op(s);
7453 gen_jmp_im(pc_start - s->cs_base);
7454 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7455 s->is_jmp = DISAS_TB_JUMP;
7457 break;
7458 case 0x100:
7459 modrm = cpu_ldub_code(env, s->pc++);
7460 mod = (modrm >> 6) & 3;
7461 op = (modrm >> 3) & 7;
7462 switch(op) {
7463 case 0: /* sldt */
7464 if (!s->pe || s->vm86)
7465 goto illegal_op;
7466 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7467 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
7468 ot = OT_WORD;
7469 if (mod == 3)
7470 ot += s->dflag;
7471 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7472 break;
7473 case 2: /* lldt */
7474 if (!s->pe || s->vm86)
7475 goto illegal_op;
7476 if (s->cpl != 0) {
7477 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7478 } else {
7479 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7480 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7481 gen_jmp_im(pc_start - s->cs_base);
7482 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7483 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7485 break;
7486 case 1: /* str */
7487 if (!s->pe || s->vm86)
7488 goto illegal_op;
7489 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7490 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
7491 ot = OT_WORD;
7492 if (mod == 3)
7493 ot += s->dflag;
7494 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7495 break;
7496 case 3: /* ltr */
7497 if (!s->pe || s->vm86)
7498 goto illegal_op;
7499 if (s->cpl != 0) {
7500 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7501 } else {
7502 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7503 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7504 gen_jmp_im(pc_start - s->cs_base);
7505 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7506 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7508 break;
7509 case 4: /* verr */
7510 case 5: /* verw */
7511 if (!s->pe || s->vm86)
7512 goto illegal_op;
7513 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7514 gen_update_cc_op(s);
7515 if (op == 4) {
7516 gen_helper_verr(cpu_env, cpu_T[0]);
7517 } else {
7518 gen_helper_verw(cpu_env, cpu_T[0]);
7520 set_cc_op(s, CC_OP_EFLAGS);
7521 break;
7522 default:
7523 goto illegal_op;
7525 break;
7526 case 0x101:
7527 modrm = cpu_ldub_code(env, s->pc++);
7528 mod = (modrm >> 6) & 3;
7529 op = (modrm >> 3) & 7;
7530 rm = modrm & 7;
7531 switch(op) {
7532 case 0: /* sgdt */
7533 if (mod == 3)
7534 goto illegal_op;
7535 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7536 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7537 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
7538 gen_op_st_T0_A0(OT_WORD + s->mem_index);
7539 gen_add_A0_im(s, 2);
7540 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
7541 if (!s->dflag)
7542 gen_op_andl_T0_im(0xffffff);
7543 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
7544 break;
7545 case 1:
7546 if (mod == 3) {
7547 switch (rm) {
7548 case 0: /* monitor */
7549 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7550 s->cpl != 0)
7551 goto illegal_op;
7552 gen_update_cc_op(s);
7553 gen_jmp_im(pc_start - s->cs_base);
7554 #ifdef TARGET_X86_64
7555 if (s->aflag == 2) {
7556 gen_op_movq_A0_reg(R_EAX);
7557 } else
7558 #endif
7560 gen_op_movl_A0_reg(R_EAX);
7561 if (s->aflag == 0)
7562 gen_op_andl_A0_ffff();
7564 gen_add_A0_ds_seg(s);
7565 gen_helper_monitor(cpu_env, cpu_A0);
7566 break;
7567 case 1: /* mwait */
7568 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7569 s->cpl != 0)
7570 goto illegal_op;
7571 gen_update_cc_op(s);
7572 gen_jmp_im(pc_start - s->cs_base);
7573 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7574 gen_eob(s);
7575 break;
7576 case 2: /* clac */
7577 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7578 s->cpl != 0) {
7579 goto illegal_op;
7581 gen_helper_clac(cpu_env);
7582 gen_jmp_im(s->pc - s->cs_base);
7583 gen_eob(s);
7584 break;
7585 case 3: /* stac */
7586 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7587 s->cpl != 0) {
7588 goto illegal_op;
7590 gen_helper_stac(cpu_env);
7591 gen_jmp_im(s->pc - s->cs_base);
7592 gen_eob(s);
7593 break;
7594 default:
7595 goto illegal_op;
7597 } else { /* sidt */
7598 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7599 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7600 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
7601 gen_op_st_T0_A0(OT_WORD + s->mem_index);
7602 gen_add_A0_im(s, 2);
7603 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
7604 if (!s->dflag)
7605 gen_op_andl_T0_im(0xffffff);
7606 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
7608 break;
7609 case 2: /* lgdt */
7610 case 3: /* lidt */
7611 if (mod == 3) {
7612 gen_update_cc_op(s);
7613 gen_jmp_im(pc_start - s->cs_base);
7614 switch(rm) {
7615 case 0: /* VMRUN */
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_vmrun(cpu_env, tcg_const_i32(s->aflag),
7623 tcg_const_i32(s->pc - pc_start));
7624 tcg_gen_exit_tb(0);
7625 s->is_jmp = DISAS_TB_JUMP;
7627 break;
7628 case 1: /* VMMCALL */
7629 if (!(s->flags & HF_SVME_MASK))
7630 goto illegal_op;
7631 gen_helper_vmmcall(cpu_env);
7632 break;
7633 case 2: /* VMLOAD */
7634 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7635 goto illegal_op;
7636 if (s->cpl != 0) {
7637 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7638 break;
7639 } else {
7640 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag));
7642 break;
7643 case 3: /* VMSAVE */
7644 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7645 goto illegal_op;
7646 if (s->cpl != 0) {
7647 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7648 break;
7649 } else {
7650 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag));
7652 break;
7653 case 4: /* STGI */
7654 if ((!(s->flags & HF_SVME_MASK) &&
7655 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7656 !s->pe)
7657 goto illegal_op;
7658 if (s->cpl != 0) {
7659 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7660 break;
7661 } else {
7662 gen_helper_stgi(cpu_env);
7664 break;
7665 case 5: /* CLGI */
7666 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7667 goto illegal_op;
7668 if (s->cpl != 0) {
7669 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7670 break;
7671 } else {
7672 gen_helper_clgi(cpu_env);
7674 break;
7675 case 6: /* SKINIT */
7676 if ((!(s->flags & HF_SVME_MASK) &&
7677 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7678 !s->pe)
7679 goto illegal_op;
7680 gen_helper_skinit(cpu_env);
7681 break;
7682 case 7: /* INVLPGA */
7683 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7684 goto illegal_op;
7685 if (s->cpl != 0) {
7686 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7687 break;
7688 } else {
7689 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag));
7691 break;
7692 default:
7693 goto illegal_op;
7695 } else if (s->cpl != 0) {
7696 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7697 } else {
7698 gen_svm_check_intercept(s, pc_start,
7699 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
7700 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7701 gen_op_ld_T1_A0(OT_WORD + s->mem_index);
7702 gen_add_A0_im(s, 2);
7703 gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
7704 if (!s->dflag)
7705 gen_op_andl_T0_im(0xffffff);
7706 if (op == 2) {
7707 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7708 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
7709 } else {
7710 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7711 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
7714 break;
7715 case 4: /* smsw */
7716 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7717 #if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
7718 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7719 #else
7720 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
7721 #endif
7722 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 1);
7723 break;
7724 case 6: /* lmsw */
7725 if (s->cpl != 0) {
7726 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7727 } else {
7728 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7729 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7730 gen_helper_lmsw(cpu_env, cpu_T[0]);
7731 gen_jmp_im(s->pc - s->cs_base);
7732 gen_eob(s);
7734 break;
7735 case 7:
7736 if (mod != 3) { /* invlpg */
7737 if (s->cpl != 0) {
7738 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7739 } else {
7740 gen_update_cc_op(s);
7741 gen_jmp_im(pc_start - s->cs_base);
7742 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7743 gen_helper_invlpg(cpu_env, cpu_A0);
7744 gen_jmp_im(s->pc - s->cs_base);
7745 gen_eob(s);
7747 } else {
7748 switch (rm) {
7749 case 0: /* swapgs */
7750 #ifdef TARGET_X86_64
7751 if (CODE64(s)) {
7752 if (s->cpl != 0) {
7753 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7754 } else {
7755 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7756 offsetof(CPUX86State,segs[R_GS].base));
7757 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7758 offsetof(CPUX86State,kernelgsbase));
7759 tcg_gen_st_tl(cpu_T[1], cpu_env,
7760 offsetof(CPUX86State,segs[R_GS].base));
7761 tcg_gen_st_tl(cpu_T[0], cpu_env,
7762 offsetof(CPUX86State,kernelgsbase));
7764 } else
7765 #endif
7767 goto illegal_op;
7769 break;
7770 case 1: /* rdtscp */
7771 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7772 goto illegal_op;
7773 gen_update_cc_op(s);
7774 gen_jmp_im(pc_start - s->cs_base);
7775 if (use_icount)
7776 gen_io_start();
7777 gen_helper_rdtscp(cpu_env);
7778 if (use_icount) {
7779 gen_io_end();
7780 gen_jmp(s, s->pc - s->cs_base);
7782 break;
7783 default:
7784 goto illegal_op;
7787 break;
7788 default:
7789 goto illegal_op;
7791 break;
7792 case 0x108: /* invd */
7793 case 0x109: /* wbinvd */
7794 if (s->cpl != 0) {
7795 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7796 } else {
7797 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7798 /* nothing to do */
7800 break;
7801 case 0x63: /* arpl or movslS (x86_64) */
7802 #ifdef TARGET_X86_64
7803 if (CODE64(s)) {
7804 int d_ot;
7805 /* d_ot is the size of destination */
7806 d_ot = dflag + OT_WORD;
7808 modrm = cpu_ldub_code(env, s->pc++);
7809 reg = ((modrm >> 3) & 7) | rex_r;
7810 mod = (modrm >> 6) & 3;
7811 rm = (modrm & 7) | REX_B(s);
7813 if (mod == 3) {
7814 gen_op_mov_TN_reg(OT_LONG, 0, rm);
7815 /* sign extend */
7816 if (d_ot == OT_QUAD)
7817 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
7818 gen_op_mov_reg_T0(d_ot, reg);
7819 } else {
7820 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7821 if (d_ot == OT_QUAD) {
7822 gen_op_lds_T0_A0(OT_LONG + s->mem_index);
7823 } else {
7824 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
7826 gen_op_mov_reg_T0(d_ot, reg);
7828 } else
7829 #endif
7831 int label1;
7832 TCGv t0, t1, t2, a0;
7834 if (!s->pe || s->vm86)
7835 goto illegal_op;
7836 t0 = tcg_temp_local_new();
7837 t1 = tcg_temp_local_new();
7838 t2 = tcg_temp_local_new();
7839 ot = OT_WORD;
7840 modrm = cpu_ldub_code(env, s->pc++);
7841 reg = (modrm >> 3) & 7;
7842 mod = (modrm >> 6) & 3;
7843 rm = modrm & 7;
7844 if (mod != 3) {
7845 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7846 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
7847 a0 = tcg_temp_local_new();
7848 tcg_gen_mov_tl(a0, cpu_A0);
7849 } else {
7850 gen_op_mov_v_reg(ot, t0, rm);
7851 TCGV_UNUSED(a0);
7853 gen_op_mov_v_reg(ot, t1, reg);
7854 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7855 tcg_gen_andi_tl(t1, t1, 3);
7856 tcg_gen_movi_tl(t2, 0);
7857 label1 = gen_new_label();
7858 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7859 tcg_gen_andi_tl(t0, t0, ~3);
7860 tcg_gen_or_tl(t0, t0, t1);
7861 tcg_gen_movi_tl(t2, CC_Z);
7862 gen_set_label(label1);
7863 if (mod != 3) {
7864 gen_op_st_v(ot + s->mem_index, t0, a0);
7865 tcg_temp_free(a0);
7866 } else {
7867 gen_op_mov_reg_v(ot, rm, t0);
7869 gen_compute_eflags(s);
7870 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7871 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7872 tcg_temp_free(t0);
7873 tcg_temp_free(t1);
7874 tcg_temp_free(t2);
7876 break;
7877 case 0x102: /* lar */
7878 case 0x103: /* lsl */
7880 int label1;
7881 TCGv t0;
7882 if (!s->pe || s->vm86)
7883 goto illegal_op;
7884 ot = dflag ? OT_LONG : OT_WORD;
7885 modrm = cpu_ldub_code(env, s->pc++);
7886 reg = ((modrm >> 3) & 7) | rex_r;
7887 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7888 t0 = tcg_temp_local_new();
7889 gen_update_cc_op(s);
7890 if (b == 0x102) {
7891 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7892 } else {
7893 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7895 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7896 label1 = gen_new_label();
7897 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7898 gen_op_mov_reg_v(ot, reg, t0);
7899 gen_set_label(label1);
7900 set_cc_op(s, CC_OP_EFLAGS);
7901 tcg_temp_free(t0);
7903 break;
7904 case 0x118:
7905 modrm = cpu_ldub_code(env, s->pc++);
7906 mod = (modrm >> 6) & 3;
7907 op = (modrm >> 3) & 7;
7908 switch(op) {
7909 case 0: /* prefetchnta */
7910 case 1: /* prefetchnt0 */
7911 case 2: /* prefetchnt0 */
7912 case 3: /* prefetchnt0 */
7913 if (mod == 3)
7914 goto illegal_op;
7915 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7916 /* nothing more to do */
7917 break;
7918 default: /* nop (multi byte) */
7919 gen_nop_modrm(env, s, modrm);
7920 break;
7922 break;
7923 case 0x119 ... 0x11f: /* nop (multi byte) */
7924 modrm = cpu_ldub_code(env, s->pc++);
7925 gen_nop_modrm(env, s, modrm);
7926 break;
7927 case 0x120: /* mov reg, crN */
7928 case 0x122: /* mov crN, reg */
7929 if (s->cpl != 0) {
7930 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7931 } else {
7932 modrm = cpu_ldub_code(env, s->pc++);
7933 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7934 * AMD documentation (24594.pdf) and testing of
7935 * intel 386 and 486 processors all show that the mod bits
7936 * are assumed to be 1's, regardless of actual values.
7938 rm = (modrm & 7) | REX_B(s);
7939 reg = ((modrm >> 3) & 7) | rex_r;
7940 if (CODE64(s))
7941 ot = OT_QUAD;
7942 else
7943 ot = OT_LONG;
7944 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7945 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7946 reg = 8;
7948 switch(reg) {
7949 case 0:
7950 case 2:
7951 case 3:
7952 case 4:
7953 case 8:
7954 gen_update_cc_op(s);
7955 gen_jmp_im(pc_start - s->cs_base);
7956 if (b & 2) {
7957 gen_op_mov_TN_reg(ot, 0, rm);
7958 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7959 cpu_T[0]);
7960 gen_jmp_im(s->pc - s->cs_base);
7961 gen_eob(s);
7962 } else {
7963 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
7964 gen_op_mov_reg_T0(ot, rm);
7966 break;
7967 default:
7968 goto illegal_op;
7971 break;
7972 case 0x121: /* mov reg, drN */
7973 case 0x123: /* mov drN, reg */
7974 if (s->cpl != 0) {
7975 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7976 } else {
7977 modrm = cpu_ldub_code(env, s->pc++);
7978 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7979 * AMD documentation (24594.pdf) and testing of
7980 * intel 386 and 486 processors all show that the mod bits
7981 * are assumed to be 1's, regardless of actual values.
7983 rm = (modrm & 7) | REX_B(s);
7984 reg = ((modrm >> 3) & 7) | rex_r;
7985 if (CODE64(s))
7986 ot = OT_QUAD;
7987 else
7988 ot = OT_LONG;
7989 /* XXX: do it dynamically with CR4.DE bit */
7990 if (reg == 4 || reg == 5 || reg >= 8)
7991 goto illegal_op;
7992 if (b & 2) {
7993 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7994 gen_op_mov_TN_reg(ot, 0, rm);
7995 gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]);
7996 gen_jmp_im(s->pc - s->cs_base);
7997 gen_eob(s);
7998 } else {
7999 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
8000 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
8001 gen_op_mov_reg_T0(ot, rm);
8004 break;
8005 case 0x106: /* clts */
8006 if (s->cpl != 0) {
8007 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8008 } else {
8009 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
8010 gen_helper_clts(cpu_env);
8011 /* abort block because static cpu state changed */
8012 gen_jmp_im(s->pc - s->cs_base);
8013 gen_eob(s);
8015 break;
8016 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
8017 case 0x1c3: /* MOVNTI reg, mem */
8018 if (!(s->cpuid_features & CPUID_SSE2))
8019 goto illegal_op;
8020 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
8021 modrm = cpu_ldub_code(env, s->pc++);
8022 mod = (modrm >> 6) & 3;
8023 if (mod == 3)
8024 goto illegal_op;
8025 reg = ((modrm >> 3) & 7) | rex_r;
8026 /* generate a generic store */
8027 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8028 break;
8029 case 0x1ae:
8030 modrm = cpu_ldub_code(env, s->pc++);
8031 mod = (modrm >> 6) & 3;
8032 op = (modrm >> 3) & 7;
8033 switch(op) {
8034 case 0: /* fxsave */
8035 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
8036 (s->prefix & PREFIX_LOCK))
8037 goto illegal_op;
8038 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8039 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8040 break;
8042 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8043 gen_update_cc_op(s);
8044 gen_jmp_im(pc_start - s->cs_base);
8045 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32((s->dflag == 2)));
8046 break;
8047 case 1: /* fxrstor */
8048 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
8049 (s->prefix & PREFIX_LOCK))
8050 goto illegal_op;
8051 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8052 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8053 break;
8055 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8056 gen_update_cc_op(s);
8057 gen_jmp_im(pc_start - s->cs_base);
8058 gen_helper_fxrstor(cpu_env, cpu_A0,
8059 tcg_const_i32((s->dflag == 2)));
8060 break;
8061 case 2: /* ldmxcsr */
8062 case 3: /* stmxcsr */
8063 if (s->flags & HF_TS_MASK) {
8064 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8065 break;
8067 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
8068 mod == 3)
8069 goto illegal_op;
8070 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8071 if (op == 2) {
8072 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
8073 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
8074 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
8075 } else {
8076 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
8077 gen_op_st_T0_A0(OT_LONG + s->mem_index);
8079 break;
8080 case 5: /* lfence */
8081 case 6: /* mfence */
8082 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
8083 goto illegal_op;
8084 break;
8085 case 7: /* sfence / clflush */
8086 if ((modrm & 0xc7) == 0xc0) {
8087 /* sfence */
8088 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
8089 if (!(s->cpuid_features & CPUID_SSE))
8090 goto illegal_op;
8091 } else {
8092 /* clflush */
8093 if (!(s->cpuid_features & CPUID_CLFLUSH))
8094 goto illegal_op;
8095 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8097 break;
8098 default:
8099 goto illegal_op;
8101 break;
8102 case 0x10d: /* 3DNow! prefetch(w) */
8103 modrm = cpu_ldub_code(env, s->pc++);
8104 mod = (modrm >> 6) & 3;
8105 if (mod == 3)
8106 goto illegal_op;
8107 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8108 /* ignore for now */
8109 break;
8110 case 0x1aa: /* rsm */
8111 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8112 if (!(s->flags & HF_SMM_MASK))
8113 goto illegal_op;
8114 gen_update_cc_op(s);
8115 gen_jmp_im(s->pc - s->cs_base);
8116 gen_helper_rsm(cpu_env);
8117 gen_eob(s);
8118 break;
8119 case 0x1b8: /* SSE4.2 popcnt */
8120 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8121 PREFIX_REPZ)
8122 goto illegal_op;
8123 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8124 goto illegal_op;
8126 modrm = cpu_ldub_code(env, s->pc++);
8127 reg = ((modrm >> 3) & 7) | rex_r;
8129 if (s->prefix & PREFIX_DATA)
8130 ot = OT_WORD;
8131 else if (s->dflag != 2)
8132 ot = OT_LONG;
8133 else
8134 ot = OT_QUAD;
8136 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8137 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
8138 gen_op_mov_reg_T0(ot, reg);
8140 set_cc_op(s, CC_OP_EFLAGS);
8141 break;
8142 case 0x10e ... 0x10f:
8143 /* 3DNow! instructions, ignore prefixes */
8144 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8145 case 0x110 ... 0x117:
8146 case 0x128 ... 0x12f:
8147 case 0x138 ... 0x13a:
8148 case 0x150 ... 0x179:
8149 case 0x17c ... 0x17f:
8150 case 0x1c2:
8151 case 0x1c4 ... 0x1c6:
8152 case 0x1d0 ... 0x1fe:
8153 gen_sse(env, s, b, pc_start, rex_r);
8154 break;
8155 default:
8156 goto illegal_op;
8158 /* lock generation */
8159 if (s->prefix & PREFIX_LOCK)
8160 gen_helper_unlock();
8161 return s->pc;
8162 illegal_op:
8163 if (s->prefix & PREFIX_LOCK)
8164 gen_helper_unlock();
8165 /* XXX: ensure that no lock was generated */
8166 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
8167 return s->pc;
8170 void optimize_flags_init(void)
8172 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8173 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
8174 offsetof(CPUX86State, cc_op), "cc_op");
8175 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
8176 "cc_dst");
8177 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
8178 "cc_src");
8179 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
8180 "cc_src2");
8182 #ifdef TARGET_X86_64
8183 cpu_regs[R_EAX] = tcg_global_mem_new_i64(TCG_AREG0,
8184 offsetof(CPUX86State, regs[R_EAX]), "rax");
8185 cpu_regs[R_ECX] = tcg_global_mem_new_i64(TCG_AREG0,
8186 offsetof(CPUX86State, regs[R_ECX]), "rcx");
8187 cpu_regs[R_EDX] = tcg_global_mem_new_i64(TCG_AREG0,
8188 offsetof(CPUX86State, regs[R_EDX]), "rdx");
8189 cpu_regs[R_EBX] = tcg_global_mem_new_i64(TCG_AREG0,
8190 offsetof(CPUX86State, regs[R_EBX]), "rbx");
8191 cpu_regs[R_ESP] = tcg_global_mem_new_i64(TCG_AREG0,
8192 offsetof(CPUX86State, regs[R_ESP]), "rsp");
8193 cpu_regs[R_EBP] = tcg_global_mem_new_i64(TCG_AREG0,
8194 offsetof(CPUX86State, regs[R_EBP]), "rbp");
8195 cpu_regs[R_ESI] = tcg_global_mem_new_i64(TCG_AREG0,
8196 offsetof(CPUX86State, regs[R_ESI]), "rsi");
8197 cpu_regs[R_EDI] = tcg_global_mem_new_i64(TCG_AREG0,
8198 offsetof(CPUX86State, regs[R_EDI]), "rdi");
8199 cpu_regs[8] = tcg_global_mem_new_i64(TCG_AREG0,
8200 offsetof(CPUX86State, regs[8]), "r8");
8201 cpu_regs[9] = tcg_global_mem_new_i64(TCG_AREG0,
8202 offsetof(CPUX86State, regs[9]), "r9");
8203 cpu_regs[10] = tcg_global_mem_new_i64(TCG_AREG0,
8204 offsetof(CPUX86State, regs[10]), "r10");
8205 cpu_regs[11] = tcg_global_mem_new_i64(TCG_AREG0,
8206 offsetof(CPUX86State, regs[11]), "r11");
8207 cpu_regs[12] = tcg_global_mem_new_i64(TCG_AREG0,
8208 offsetof(CPUX86State, regs[12]), "r12");
8209 cpu_regs[13] = tcg_global_mem_new_i64(TCG_AREG0,
8210 offsetof(CPUX86State, regs[13]), "r13");
8211 cpu_regs[14] = tcg_global_mem_new_i64(TCG_AREG0,
8212 offsetof(CPUX86State, regs[14]), "r14");
8213 cpu_regs[15] = tcg_global_mem_new_i64(TCG_AREG0,
8214 offsetof(CPUX86State, regs[15]), "r15");
8215 #else
8216 cpu_regs[R_EAX] = tcg_global_mem_new_i32(TCG_AREG0,
8217 offsetof(CPUX86State, regs[R_EAX]), "eax");
8218 cpu_regs[R_ECX] = tcg_global_mem_new_i32(TCG_AREG0,
8219 offsetof(CPUX86State, regs[R_ECX]), "ecx");
8220 cpu_regs[R_EDX] = tcg_global_mem_new_i32(TCG_AREG0,
8221 offsetof(CPUX86State, regs[R_EDX]), "edx");
8222 cpu_regs[R_EBX] = tcg_global_mem_new_i32(TCG_AREG0,
8223 offsetof(CPUX86State, regs[R_EBX]), "ebx");
8224 cpu_regs[R_ESP] = tcg_global_mem_new_i32(TCG_AREG0,
8225 offsetof(CPUX86State, regs[R_ESP]), "esp");
8226 cpu_regs[R_EBP] = tcg_global_mem_new_i32(TCG_AREG0,
8227 offsetof(CPUX86State, regs[R_EBP]), "ebp");
8228 cpu_regs[R_ESI] = tcg_global_mem_new_i32(TCG_AREG0,
8229 offsetof(CPUX86State, regs[R_ESI]), "esi");
8230 cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
8231 offsetof(CPUX86State, regs[R_EDI]), "edi");
8232 #endif
8234 /* register helpers */
8235 #define GEN_HELPER 2
8236 #include "helper.h"
8239 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8240 basic block 'tb'. If search_pc is TRUE, also generate PC
8241 information for each intermediate instruction. */
8242 static inline void gen_intermediate_code_internal(CPUX86State *env,
8243 TranslationBlock *tb,
8244 int search_pc)
8246 DisasContext dc1, *dc = &dc1;
8247 target_ulong pc_ptr;
8248 uint16_t *gen_opc_end;
8249 CPUBreakpoint *bp;
8250 int j, lj;
8251 uint64_t flags;
8252 target_ulong pc_start;
8253 target_ulong cs_base;
8254 int num_insns;
8255 int max_insns;
8257 /* generate intermediate code */
8258 pc_start = tb->pc;
8259 cs_base = tb->cs_base;
8260 flags = tb->flags;
8262 dc->pe = (flags >> HF_PE_SHIFT) & 1;
8263 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8264 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8265 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8266 dc->f_st = 0;
8267 dc->vm86 = (flags >> VM_SHIFT) & 1;
8268 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8269 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8270 dc->tf = (flags >> TF_SHIFT) & 1;
8271 dc->singlestep_enabled = env->singlestep_enabled;
8272 dc->cc_op = CC_OP_DYNAMIC;
8273 dc->cc_op_dirty = false;
8274 dc->cs_base = cs_base;
8275 dc->tb = tb;
8276 dc->popl_esp_hack = 0;
8277 /* select memory access functions */
8278 dc->mem_index = 0;
8279 if (flags & HF_SOFTMMU_MASK) {
8280 dc->mem_index = (cpu_mmu_index(env) + 1) << 2;
8282 dc->cpuid_features = env->cpuid_features;
8283 dc->cpuid_ext_features = env->cpuid_ext_features;
8284 dc->cpuid_ext2_features = env->cpuid_ext2_features;
8285 dc->cpuid_ext3_features = env->cpuid_ext3_features;
8286 dc->cpuid_7_0_ebx_features = env->cpuid_7_0_ebx_features;
8287 #ifdef TARGET_X86_64
8288 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8289 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8290 #endif
8291 dc->flags = flags;
8292 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
8293 (flags & HF_INHIBIT_IRQ_MASK)
8294 #ifndef CONFIG_SOFTMMU
8295 || (flags & HF_SOFTMMU_MASK)
8296 #endif
8298 #if 0
8299 /* check addseg logic */
8300 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8301 printf("ERROR addseg\n");
8302 #endif
8304 cpu_T[0] = tcg_temp_new();
8305 cpu_T[1] = tcg_temp_new();
8306 cpu_A0 = tcg_temp_new();
8308 cpu_tmp0 = tcg_temp_new();
8309 cpu_tmp1_i64 = tcg_temp_new_i64();
8310 cpu_tmp2_i32 = tcg_temp_new_i32();
8311 cpu_tmp3_i32 = tcg_temp_new_i32();
8312 cpu_tmp4 = tcg_temp_new();
8313 cpu_ptr0 = tcg_temp_new_ptr();
8314 cpu_ptr1 = tcg_temp_new_ptr();
8315 cpu_cc_srcT = tcg_temp_local_new();
8317 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
8319 dc->is_jmp = DISAS_NEXT;
8320 pc_ptr = pc_start;
8321 lj = -1;
8322 num_insns = 0;
8323 max_insns = tb->cflags & CF_COUNT_MASK;
8324 if (max_insns == 0)
8325 max_insns = CF_COUNT_MASK;
8327 gen_icount_start();
8328 for(;;) {
8329 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8330 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8331 if (bp->pc == pc_ptr &&
8332 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
8333 gen_debug(dc, pc_ptr - dc->cs_base);
8334 break;
8338 if (search_pc) {
8339 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
8340 if (lj < j) {
8341 lj++;
8342 while (lj < j)
8343 tcg_ctx.gen_opc_instr_start[lj++] = 0;
8345 tcg_ctx.gen_opc_pc[lj] = pc_ptr;
8346 gen_opc_cc_op[lj] = dc->cc_op;
8347 tcg_ctx.gen_opc_instr_start[lj] = 1;
8348 tcg_ctx.gen_opc_icount[lj] = num_insns;
8350 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8351 gen_io_start();
8353 pc_ptr = disas_insn(env, dc, pc_ptr);
8354 num_insns++;
8355 /* stop translation if indicated */
8356 if (dc->is_jmp)
8357 break;
8358 /* if single step mode, we generate only one instruction and
8359 generate an exception */
8360 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8361 the flag and abort the translation to give the irqs a
8362 change to be happen */
8363 if (dc->tf || dc->singlestep_enabled ||
8364 (flags & HF_INHIBIT_IRQ_MASK)) {
8365 gen_jmp_im(pc_ptr - dc->cs_base);
8366 gen_eob(dc);
8367 break;
8369 /* if too long translation, stop generation too */
8370 if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
8371 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8372 num_insns >= max_insns) {
8373 gen_jmp_im(pc_ptr - dc->cs_base);
8374 gen_eob(dc);
8375 break;
8377 if (singlestep) {
8378 gen_jmp_im(pc_ptr - dc->cs_base);
8379 gen_eob(dc);
8380 break;
8383 if (tb->cflags & CF_LAST_IO)
8384 gen_io_end();
8385 gen_icount_end(tb, num_insns);
8386 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
8387 /* we don't forget to fill the last values */
8388 if (search_pc) {
8389 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
8390 lj++;
8391 while (lj <= j)
8392 tcg_ctx.gen_opc_instr_start[lj++] = 0;
8395 #ifdef DEBUG_DISAS
8396 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8397 int disas_flags;
8398 qemu_log("----------------\n");
8399 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8400 #ifdef TARGET_X86_64
8401 if (dc->code64)
8402 disas_flags = 2;
8403 else
8404 #endif
8405 disas_flags = !dc->code32;
8406 log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags);
8407 qemu_log("\n");
8409 #endif
8411 if (!search_pc) {
8412 tb->size = pc_ptr - pc_start;
8413 tb->icount = num_insns;
8417 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
8419 gen_intermediate_code_internal(env, tb, 0);
8422 void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
8424 gen_intermediate_code_internal(env, tb, 1);
8427 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
8429 int cc_op;
8430 #ifdef DEBUG_DISAS
8431 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
8432 int i;
8433 qemu_log("RESTORE:\n");
8434 for(i = 0;i <= pc_pos; i++) {
8435 if (tcg_ctx.gen_opc_instr_start[i]) {
8436 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
8437 tcg_ctx.gen_opc_pc[i]);
8440 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
8441 pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
8442 (uint32_t)tb->cs_base);
8444 #endif
8445 env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
8446 cc_op = gen_opc_cc_op[pc_pos];
8447 if (cc_op != CC_OP_DYNAMIC)
8448 env->cc_op = cc_op;