Merge remote-tracking branch 'remotes/cohuck-gitlab/tags/s390x-20210520-v2' into...
[qemu/ar7.git] / target / i386 / tcg / translate.c
blob834186bcae96c99786fc9759264a1befb0b836e1
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.1 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 "qemu/osdep.h"
21 #include "qemu/host-utils.h"
22 #include "cpu.h"
23 #include "disas/disas.h"
24 #include "exec/exec-all.h"
25 #include "tcg/tcg-op.h"
26 #include "exec/cpu_ldst.h"
27 #include "exec/translator.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "helper-tcg.h"
33 #include "trace-tcg.h"
34 #include "exec/log.h"
36 #define PREFIX_REPZ 0x01
37 #define PREFIX_REPNZ 0x02
38 #define PREFIX_LOCK 0x04
39 #define PREFIX_DATA 0x08
40 #define PREFIX_ADR 0x10
41 #define PREFIX_VEX 0x20
42 #define PREFIX_REX 0x40
44 #ifdef TARGET_X86_64
45 # define ctztl ctz64
46 # define clztl clz64
47 #else
48 # define ctztl ctz32
49 # define clztl clz32
50 #endif
52 /* For a switch indexed by MODRM, match all memory operands for a given OP. */
53 #define CASE_MODRM_MEM_OP(OP) \
54 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
55 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
56 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
58 #define CASE_MODRM_OP(OP) \
59 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
60 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
61 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
62 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
64 //#define MACRO_TEST 1
66 /* global register indexes */
67 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
68 static TCGv_i32 cpu_cc_op;
69 static TCGv cpu_regs[CPU_NB_REGS];
70 static TCGv cpu_seg_base[6];
71 static TCGv_i64 cpu_bndl[4];
72 static TCGv_i64 cpu_bndu[4];
74 #include "exec/gen-icount.h"
76 typedef struct DisasContext {
77 DisasContextBase base;
79 target_ulong pc; /* pc = eip + cs_base */
80 target_ulong pc_start; /* pc at TB entry */
81 target_ulong cs_base; /* base of CS segment */
83 MemOp aflag;
84 MemOp dflag;
86 int8_t override; /* -1 if no override, else R_CS, R_DS, etc */
87 uint8_t prefix;
89 #ifndef CONFIG_USER_ONLY
90 uint8_t cpl; /* code priv level */
91 uint8_t iopl; /* i/o priv level */
92 #endif
93 uint8_t vex_l; /* vex vector length */
94 uint8_t vex_v; /* vex vvvv register, without 1's complement. */
95 uint8_t popl_esp_hack; /* for correct popl with esp base handling */
96 uint8_t rip_offset; /* only used in x86_64, but left for simplicity */
98 #ifdef TARGET_X86_64
99 uint8_t rex_r;
100 uint8_t rex_x;
101 uint8_t rex_b;
102 bool rex_w;
103 #endif
104 bool jmp_opt; /* use direct block chaining for direct jumps */
105 bool repz_opt; /* optimize jumps within repz instructions */
106 bool cc_op_dirty;
108 CCOp cc_op; /* current CC operation */
109 int mem_index; /* select memory access functions */
110 uint32_t flags; /* all execution flags */
111 int cpuid_features;
112 int cpuid_ext_features;
113 int cpuid_ext2_features;
114 int cpuid_ext3_features;
115 int cpuid_7_0_ebx_features;
116 int cpuid_xsave_features;
118 /* TCG local temps */
119 TCGv cc_srcT;
120 TCGv A0;
121 TCGv T0;
122 TCGv T1;
124 /* TCG local register indexes (only used inside old micro ops) */
125 TCGv tmp0;
126 TCGv tmp4;
127 TCGv_ptr ptr0;
128 TCGv_ptr ptr1;
129 TCGv_i32 tmp2_i32;
130 TCGv_i32 tmp3_i32;
131 TCGv_i64 tmp1_i64;
133 sigjmp_buf jmpbuf;
134 } DisasContext;
136 /* The environment in which user-only runs is constrained. */
137 #ifdef CONFIG_USER_ONLY
138 #define PE(S) true
139 #define CPL(S) 3
140 #define IOPL(S) 0
141 #define SVME(S) false
142 #define GUEST(S) false
143 #else
144 #define PE(S) (((S)->flags & HF_PE_MASK) != 0)
145 #define CPL(S) ((S)->cpl)
146 #define IOPL(S) ((S)->iopl)
147 #define SVME(S) (((S)->flags & HF_SVME_MASK) != 0)
148 #define GUEST(S) (((S)->flags & HF_GUEST_MASK) != 0)
149 #endif
150 #if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
151 #define VM86(S) false
152 #define CODE32(S) true
153 #define SS32(S) true
154 #define ADDSEG(S) false
155 #else
156 #define VM86(S) (((S)->flags & HF_VM_MASK) != 0)
157 #define CODE32(S) (((S)->flags & HF_CS32_MASK) != 0)
158 #define SS32(S) (((S)->flags & HF_SS32_MASK) != 0)
159 #define ADDSEG(S) (((S)->flags & HF_ADDSEG_MASK) != 0)
160 #endif
161 #if !defined(TARGET_X86_64)
162 #define CODE64(S) false
163 #define LMA(S) false
164 #elif defined(CONFIG_USER_ONLY)
165 #define CODE64(S) true
166 #define LMA(S) true
167 #else
168 #define CODE64(S) (((S)->flags & HF_CS64_MASK) != 0)
169 #define LMA(S) (((S)->flags & HF_LMA_MASK) != 0)
170 #endif
172 #ifdef TARGET_X86_64
173 #define REX_PREFIX(S) (((S)->prefix & PREFIX_REX) != 0)
174 #define REX_W(S) ((S)->rex_w)
175 #define REX_R(S) ((S)->rex_r + 0)
176 #define REX_X(S) ((S)->rex_x + 0)
177 #define REX_B(S) ((S)->rex_b + 0)
178 #else
179 #define REX_PREFIX(S) false
180 #define REX_W(S) false
181 #define REX_R(S) 0
182 #define REX_X(S) 0
183 #define REX_B(S) 0
184 #endif
187 * Many sysemu-only helpers are not reachable for user-only.
188 * Define stub generators here, so that we need not either sprinkle
189 * ifdefs through the translator, nor provide the helper function.
191 #define STUB_HELPER(NAME, ...) \
192 static inline void gen_helper_##NAME(__VA_ARGS__) \
193 { qemu_build_not_reached(); }
195 #ifdef CONFIG_USER_ONLY
196 STUB_HELPER(clgi, TCGv_env env)
197 STUB_HELPER(flush_page, TCGv_env env, TCGv addr)
198 STUB_HELPER(hlt, TCGv_env env, TCGv_i32 pc_ofs)
199 STUB_HELPER(inb, TCGv ret, TCGv_env env, TCGv_i32 port)
200 STUB_HELPER(inw, TCGv ret, TCGv_env env, TCGv_i32 port)
201 STUB_HELPER(inl, TCGv ret, TCGv_env env, TCGv_i32 port)
202 STUB_HELPER(monitor, TCGv_env env, TCGv addr)
203 STUB_HELPER(mwait, TCGv_env env, TCGv_i32 pc_ofs)
204 STUB_HELPER(outb, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
205 STUB_HELPER(outw, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
206 STUB_HELPER(outl, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
207 STUB_HELPER(rdmsr, TCGv_env env)
208 STUB_HELPER(read_crN, TCGv ret, TCGv_env env, TCGv_i32 reg)
209 STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
210 STUB_HELPER(stgi, TCGv_env env)
211 STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
212 STUB_HELPER(vmload, TCGv_env env, TCGv_i32 aflag)
213 STUB_HELPER(vmmcall, TCGv_env env)
214 STUB_HELPER(vmrun, TCGv_env env, TCGv_i32 aflag, TCGv_i32 pc_ofs)
215 STUB_HELPER(vmsave, TCGv_env env, TCGv_i32 aflag)
216 STUB_HELPER(write_crN, TCGv_env env, TCGv_i32 reg, TCGv val)
217 STUB_HELPER(wrmsr, TCGv_env env)
218 #endif
220 static void gen_eob(DisasContext *s);
221 static void gen_jr(DisasContext *s, TCGv dest);
222 static void gen_jmp(DisasContext *s, target_ulong eip);
223 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
224 static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
225 static void gen_exception_gpf(DisasContext *s);
227 /* i386 arith/logic operations */
228 enum {
229 OP_ADDL,
230 OP_ORL,
231 OP_ADCL,
232 OP_SBBL,
233 OP_ANDL,
234 OP_SUBL,
235 OP_XORL,
236 OP_CMPL,
239 /* i386 shift ops */
240 enum {
241 OP_ROL,
242 OP_ROR,
243 OP_RCL,
244 OP_RCR,
245 OP_SHL,
246 OP_SHR,
247 OP_SHL1, /* undocumented */
248 OP_SAR = 7,
251 enum {
252 JCC_O,
253 JCC_B,
254 JCC_Z,
255 JCC_BE,
256 JCC_S,
257 JCC_P,
258 JCC_L,
259 JCC_LE,
262 enum {
263 /* I386 int registers */
264 OR_EAX, /* MUST be even numbered */
265 OR_ECX,
266 OR_EDX,
267 OR_EBX,
268 OR_ESP,
269 OR_EBP,
270 OR_ESI,
271 OR_EDI,
273 OR_TMP0 = 16, /* temporary operand register */
274 OR_TMP1,
275 OR_A0, /* temporary register used when doing address evaluation */
278 enum {
279 USES_CC_DST = 1,
280 USES_CC_SRC = 2,
281 USES_CC_SRC2 = 4,
282 USES_CC_SRCT = 8,
285 /* Bit set if the global variable is live after setting CC_OP to X. */
286 static const uint8_t cc_op_live[CC_OP_NB] = {
287 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
288 [CC_OP_EFLAGS] = USES_CC_SRC,
289 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
290 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
291 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
292 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
293 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
294 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
295 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
296 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
297 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
298 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
299 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
300 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
301 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
302 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
303 [CC_OP_CLR] = 0,
304 [CC_OP_POPCNT] = USES_CC_SRC,
307 static void set_cc_op(DisasContext *s, CCOp op)
309 int dead;
311 if (s->cc_op == op) {
312 return;
315 /* Discard CC computation that will no longer be used. */
316 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
317 if (dead & USES_CC_DST) {
318 tcg_gen_discard_tl(cpu_cc_dst);
320 if (dead & USES_CC_SRC) {
321 tcg_gen_discard_tl(cpu_cc_src);
323 if (dead & USES_CC_SRC2) {
324 tcg_gen_discard_tl(cpu_cc_src2);
326 if (dead & USES_CC_SRCT) {
327 tcg_gen_discard_tl(s->cc_srcT);
330 if (op == CC_OP_DYNAMIC) {
331 /* The DYNAMIC setting is translator only, and should never be
332 stored. Thus we always consider it clean. */
333 s->cc_op_dirty = false;
334 } else {
335 /* Discard any computed CC_OP value (see shifts). */
336 if (s->cc_op == CC_OP_DYNAMIC) {
337 tcg_gen_discard_i32(cpu_cc_op);
339 s->cc_op_dirty = true;
341 s->cc_op = op;
344 static void gen_update_cc_op(DisasContext *s)
346 if (s->cc_op_dirty) {
347 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
348 s->cc_op_dirty = false;
352 #ifdef TARGET_X86_64
354 #define NB_OP_SIZES 4
356 #else /* !TARGET_X86_64 */
358 #define NB_OP_SIZES 3
360 #endif /* !TARGET_X86_64 */
362 #if defined(HOST_WORDS_BIGENDIAN)
363 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
364 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
365 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
366 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
367 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
368 #else
369 #define REG_B_OFFSET 0
370 #define REG_H_OFFSET 1
371 #define REG_W_OFFSET 0
372 #define REG_L_OFFSET 0
373 #define REG_LH_OFFSET 4
374 #endif
376 /* In instruction encodings for byte register accesses the
377 * register number usually indicates "low 8 bits of register N";
378 * however there are some special cases where N 4..7 indicates
379 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
380 * true for this special case, false otherwise.
382 static inline bool byte_reg_is_xH(DisasContext *s, int reg)
384 /* Any time the REX prefix is present, byte registers are uniform */
385 if (reg < 4 || REX_PREFIX(s)) {
386 return false;
388 return true;
391 /* Select the size of a push/pop operation. */
392 static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
394 if (CODE64(s)) {
395 return ot == MO_16 ? MO_16 : MO_64;
396 } else {
397 return ot;
401 /* Select the size of the stack pointer. */
402 static inline MemOp mo_stacksize(DisasContext *s)
404 return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
407 /* Select only size 64 else 32. Used for SSE operand sizes. */
408 static inline MemOp mo_64_32(MemOp ot)
410 #ifdef TARGET_X86_64
411 return ot == MO_64 ? MO_64 : MO_32;
412 #else
413 return MO_32;
414 #endif
417 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
418 byte vs word opcodes. */
419 static inline MemOp mo_b_d(int b, MemOp ot)
421 return b & 1 ? ot : MO_8;
424 /* Select size 8 if lsb of B is clear, else OT capped at 32.
425 Used for decoding operand size of port opcodes. */
426 static inline MemOp mo_b_d32(int b, MemOp ot)
428 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
431 static void gen_op_mov_reg_v(DisasContext *s, MemOp ot, int reg, TCGv t0)
433 switch(ot) {
434 case MO_8:
435 if (!byte_reg_is_xH(s, reg)) {
436 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
437 } else {
438 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
440 break;
441 case MO_16:
442 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
443 break;
444 case MO_32:
445 /* For x86_64, this sets the higher half of register to zero.
446 For i386, this is equivalent to a mov. */
447 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
448 break;
449 #ifdef TARGET_X86_64
450 case MO_64:
451 tcg_gen_mov_tl(cpu_regs[reg], t0);
452 break;
453 #endif
454 default:
455 tcg_abort();
459 static inline
460 void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg)
462 if (ot == MO_8 && byte_reg_is_xH(s, reg)) {
463 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
464 } else {
465 tcg_gen_mov_tl(t0, cpu_regs[reg]);
469 static void gen_add_A0_im(DisasContext *s, int val)
471 tcg_gen_addi_tl(s->A0, s->A0, val);
472 if (!CODE64(s)) {
473 tcg_gen_ext32u_tl(s->A0, s->A0);
477 static inline void gen_op_jmp_v(TCGv dest)
479 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
482 static inline
483 void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val)
485 tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val);
486 gen_op_mov_reg_v(s, size, reg, s->tmp0);
489 static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg)
491 tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0);
492 gen_op_mov_reg_v(s, size, reg, s->tmp0);
495 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
497 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
500 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
502 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
505 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
507 if (d == OR_TMP0) {
508 gen_op_st_v(s, idx, s->T0, s->A0);
509 } else {
510 gen_op_mov_reg_v(s, idx, d, s->T0);
514 static inline void gen_jmp_im(DisasContext *s, target_ulong pc)
516 tcg_gen_movi_tl(s->tmp0, pc);
517 gen_op_jmp_v(s->tmp0);
520 /* Compute SEG:REG into A0. SEG is selected from the override segment
521 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
522 indicate no override. */
523 static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
524 int def_seg, int ovr_seg)
526 switch (aflag) {
527 #ifdef TARGET_X86_64
528 case MO_64:
529 if (ovr_seg < 0) {
530 tcg_gen_mov_tl(s->A0, a0);
531 return;
533 break;
534 #endif
535 case MO_32:
536 /* 32 bit address */
537 if (ovr_seg < 0 && ADDSEG(s)) {
538 ovr_seg = def_seg;
540 if (ovr_seg < 0) {
541 tcg_gen_ext32u_tl(s->A0, a0);
542 return;
544 break;
545 case MO_16:
546 /* 16 bit address */
547 tcg_gen_ext16u_tl(s->A0, a0);
548 a0 = s->A0;
549 if (ovr_seg < 0) {
550 if (ADDSEG(s)) {
551 ovr_seg = def_seg;
552 } else {
553 return;
556 break;
557 default:
558 tcg_abort();
561 if (ovr_seg >= 0) {
562 TCGv seg = cpu_seg_base[ovr_seg];
564 if (aflag == MO_64) {
565 tcg_gen_add_tl(s->A0, a0, seg);
566 } else if (CODE64(s)) {
567 tcg_gen_ext32u_tl(s->A0, a0);
568 tcg_gen_add_tl(s->A0, s->A0, seg);
569 } else {
570 tcg_gen_add_tl(s->A0, a0, seg);
571 tcg_gen_ext32u_tl(s->A0, s->A0);
576 static inline void gen_string_movl_A0_ESI(DisasContext *s)
578 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
581 static inline void gen_string_movl_A0_EDI(DisasContext *s)
583 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
586 static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
588 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
589 tcg_gen_shli_tl(s->T0, s->T0, ot);
592 static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
594 switch (size) {
595 case MO_8:
596 if (sign) {
597 tcg_gen_ext8s_tl(dst, src);
598 } else {
599 tcg_gen_ext8u_tl(dst, src);
601 return dst;
602 case MO_16:
603 if (sign) {
604 tcg_gen_ext16s_tl(dst, src);
605 } else {
606 tcg_gen_ext16u_tl(dst, src);
608 return dst;
609 #ifdef TARGET_X86_64
610 case MO_32:
611 if (sign) {
612 tcg_gen_ext32s_tl(dst, src);
613 } else {
614 tcg_gen_ext32u_tl(dst, src);
616 return dst;
617 #endif
618 default:
619 return src;
623 static void gen_extu(MemOp ot, TCGv reg)
625 gen_ext_tl(reg, reg, ot, false);
628 static void gen_exts(MemOp ot, TCGv reg)
630 gen_ext_tl(reg, reg, ot, true);
633 static inline
634 void gen_op_jnz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
636 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
637 gen_extu(size, s->tmp0);
638 tcg_gen_brcondi_tl(TCG_COND_NE, s->tmp0, 0, label1);
641 static inline
642 void gen_op_jz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
644 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
645 gen_extu(size, s->tmp0);
646 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
649 static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
651 switch (ot) {
652 case MO_8:
653 gen_helper_inb(v, cpu_env, n);
654 break;
655 case MO_16:
656 gen_helper_inw(v, cpu_env, n);
657 break;
658 case MO_32:
659 gen_helper_inl(v, cpu_env, n);
660 break;
661 default:
662 tcg_abort();
666 static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
668 switch (ot) {
669 case MO_8:
670 gen_helper_outb(cpu_env, v, n);
671 break;
672 case MO_16:
673 gen_helper_outw(cpu_env, v, n);
674 break;
675 case MO_32:
676 gen_helper_outl(cpu_env, v, n);
677 break;
678 default:
679 tcg_abort();
684 * Validate that access to [port, port + 1<<ot) is allowed.
685 * Raise #GP, or VMM exit if not.
687 static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
688 uint32_t svm_flags)
690 #ifdef CONFIG_USER_ONLY
692 * We do not implement the ioperm(2) syscall, so the TSS check
693 * will always fail.
695 gen_exception_gpf(s);
696 return false;
697 #else
698 if (PE(s) && (CPL(s) > IOPL(s) || VM86(s))) {
699 gen_helper_check_io(cpu_env, port, tcg_constant_i32(1 << ot));
701 if (GUEST(s)) {
702 target_ulong cur_eip = s->base.pc_next - s->cs_base;
703 target_ulong next_eip = s->pc - s->cs_base;
705 gen_update_cc_op(s);
706 gen_jmp_im(s, cur_eip);
707 if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
708 svm_flags |= SVM_IOIO_REP_MASK;
710 svm_flags |= 1 << (SVM_IOIO_SIZE_SHIFT + ot);
711 gen_helper_svm_check_io(cpu_env, port,
712 tcg_constant_i32(svm_flags),
713 tcg_constant_i32(next_eip - cur_eip));
715 return true;
716 #endif
719 static inline void gen_movs(DisasContext *s, MemOp ot)
721 gen_string_movl_A0_ESI(s);
722 gen_op_ld_v(s, ot, s->T0, s->A0);
723 gen_string_movl_A0_EDI(s);
724 gen_op_st_v(s, ot, s->T0, s->A0);
725 gen_op_movl_T0_Dshift(s, ot);
726 gen_op_add_reg_T0(s, s->aflag, R_ESI);
727 gen_op_add_reg_T0(s, s->aflag, R_EDI);
730 static void gen_op_update1_cc(DisasContext *s)
732 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
735 static void gen_op_update2_cc(DisasContext *s)
737 tcg_gen_mov_tl(cpu_cc_src, s->T1);
738 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
741 static void gen_op_update3_cc(DisasContext *s, TCGv reg)
743 tcg_gen_mov_tl(cpu_cc_src2, reg);
744 tcg_gen_mov_tl(cpu_cc_src, s->T1);
745 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
748 static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
750 tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1);
753 static void gen_op_update_neg_cc(DisasContext *s)
755 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
756 tcg_gen_neg_tl(cpu_cc_src, s->T0);
757 tcg_gen_movi_tl(s->cc_srcT, 0);
760 /* compute all eflags to cc_src */
761 static void gen_compute_eflags(DisasContext *s)
763 TCGv zero, dst, src1, src2;
764 int live, dead;
766 if (s->cc_op == CC_OP_EFLAGS) {
767 return;
769 if (s->cc_op == CC_OP_CLR) {
770 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
771 set_cc_op(s, CC_OP_EFLAGS);
772 return;
775 zero = NULL;
776 dst = cpu_cc_dst;
777 src1 = cpu_cc_src;
778 src2 = cpu_cc_src2;
780 /* Take care to not read values that are not live. */
781 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
782 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
783 if (dead) {
784 zero = tcg_const_tl(0);
785 if (dead & USES_CC_DST) {
786 dst = zero;
788 if (dead & USES_CC_SRC) {
789 src1 = zero;
791 if (dead & USES_CC_SRC2) {
792 src2 = zero;
796 gen_update_cc_op(s);
797 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
798 set_cc_op(s, CC_OP_EFLAGS);
800 if (dead) {
801 tcg_temp_free(zero);
805 typedef struct CCPrepare {
806 TCGCond cond;
807 TCGv reg;
808 TCGv reg2;
809 target_ulong imm;
810 target_ulong mask;
811 bool use_reg2;
812 bool no_setcond;
813 } CCPrepare;
815 /* compute eflags.C to reg */
816 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
818 TCGv t0, t1;
819 int size, shift;
821 switch (s->cc_op) {
822 case CC_OP_SUBB ... CC_OP_SUBQ:
823 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
824 size = s->cc_op - CC_OP_SUBB;
825 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
826 /* If no temporary was used, be careful not to alias t1 and t0. */
827 t0 = t1 == cpu_cc_src ? s->tmp0 : reg;
828 tcg_gen_mov_tl(t0, s->cc_srcT);
829 gen_extu(size, t0);
830 goto add_sub;
832 case CC_OP_ADDB ... CC_OP_ADDQ:
833 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
834 size = s->cc_op - CC_OP_ADDB;
835 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
836 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
837 add_sub:
838 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
839 .reg2 = t1, .mask = -1, .use_reg2 = true };
841 case CC_OP_LOGICB ... CC_OP_LOGICQ:
842 case CC_OP_CLR:
843 case CC_OP_POPCNT:
844 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
846 case CC_OP_INCB ... CC_OP_INCQ:
847 case CC_OP_DECB ... CC_OP_DECQ:
848 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
849 .mask = -1, .no_setcond = true };
851 case CC_OP_SHLB ... CC_OP_SHLQ:
852 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
853 size = s->cc_op - CC_OP_SHLB;
854 shift = (8 << size) - 1;
855 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
856 .mask = (target_ulong)1 << shift };
858 case CC_OP_MULB ... CC_OP_MULQ:
859 return (CCPrepare) { .cond = TCG_COND_NE,
860 .reg = cpu_cc_src, .mask = -1 };
862 case CC_OP_BMILGB ... CC_OP_BMILGQ:
863 size = s->cc_op - CC_OP_BMILGB;
864 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
865 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
867 case CC_OP_ADCX:
868 case CC_OP_ADCOX:
869 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
870 .mask = -1, .no_setcond = true };
872 case CC_OP_EFLAGS:
873 case CC_OP_SARB ... CC_OP_SARQ:
874 /* CC_SRC & 1 */
875 return (CCPrepare) { .cond = TCG_COND_NE,
876 .reg = cpu_cc_src, .mask = CC_C };
878 default:
879 /* The need to compute only C from CC_OP_DYNAMIC is important
880 in efficiently implementing e.g. INC at the start of a TB. */
881 gen_update_cc_op(s);
882 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
883 cpu_cc_src2, cpu_cc_op);
884 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
885 .mask = -1, .no_setcond = true };
889 /* compute eflags.P to reg */
890 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
892 gen_compute_eflags(s);
893 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
894 .mask = CC_P };
897 /* compute eflags.S to reg */
898 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
900 switch (s->cc_op) {
901 case CC_OP_DYNAMIC:
902 gen_compute_eflags(s);
903 /* FALLTHRU */
904 case CC_OP_EFLAGS:
905 case CC_OP_ADCX:
906 case CC_OP_ADOX:
907 case CC_OP_ADCOX:
908 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
909 .mask = CC_S };
910 case CC_OP_CLR:
911 case CC_OP_POPCNT:
912 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
913 default:
915 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
916 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
917 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
922 /* compute eflags.O to reg */
923 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
925 switch (s->cc_op) {
926 case CC_OP_ADOX:
927 case CC_OP_ADCOX:
928 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
929 .mask = -1, .no_setcond = true };
930 case CC_OP_CLR:
931 case CC_OP_POPCNT:
932 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
933 default:
934 gen_compute_eflags(s);
935 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
936 .mask = CC_O };
940 /* compute eflags.Z to reg */
941 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
943 switch (s->cc_op) {
944 case CC_OP_DYNAMIC:
945 gen_compute_eflags(s);
946 /* FALLTHRU */
947 case CC_OP_EFLAGS:
948 case CC_OP_ADCX:
949 case CC_OP_ADOX:
950 case CC_OP_ADCOX:
951 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
952 .mask = CC_Z };
953 case CC_OP_CLR:
954 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
955 case CC_OP_POPCNT:
956 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
957 .mask = -1 };
958 default:
960 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
961 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
962 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
967 /* perform a conditional store into register 'reg' according to jump opcode
968 value 'b'. In the fast case, T0 is guaranted not to be used. */
969 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
971 int inv, jcc_op, cond;
972 MemOp size;
973 CCPrepare cc;
974 TCGv t0;
976 inv = b & 1;
977 jcc_op = (b >> 1) & 7;
979 switch (s->cc_op) {
980 case CC_OP_SUBB ... CC_OP_SUBQ:
981 /* We optimize relational operators for the cmp/jcc case. */
982 size = s->cc_op - CC_OP_SUBB;
983 switch (jcc_op) {
984 case JCC_BE:
985 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
986 gen_extu(size, s->tmp4);
987 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
988 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4,
989 .reg2 = t0, .mask = -1, .use_reg2 = true };
990 break;
992 case JCC_L:
993 cond = TCG_COND_LT;
994 goto fast_jcc_l;
995 case JCC_LE:
996 cond = TCG_COND_LE;
997 fast_jcc_l:
998 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
999 gen_exts(size, s->tmp4);
1000 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true);
1001 cc = (CCPrepare) { .cond = cond, .reg = s->tmp4,
1002 .reg2 = t0, .mask = -1, .use_reg2 = true };
1003 break;
1005 default:
1006 goto slow_jcc;
1008 break;
1010 default:
1011 slow_jcc:
1012 /* This actually generates good code for JC, JZ and JS. */
1013 switch (jcc_op) {
1014 case JCC_O:
1015 cc = gen_prepare_eflags_o(s, reg);
1016 break;
1017 case JCC_B:
1018 cc = gen_prepare_eflags_c(s, reg);
1019 break;
1020 case JCC_Z:
1021 cc = gen_prepare_eflags_z(s, reg);
1022 break;
1023 case JCC_BE:
1024 gen_compute_eflags(s);
1025 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1026 .mask = CC_Z | CC_C };
1027 break;
1028 case JCC_S:
1029 cc = gen_prepare_eflags_s(s, reg);
1030 break;
1031 case JCC_P:
1032 cc = gen_prepare_eflags_p(s, reg);
1033 break;
1034 case JCC_L:
1035 gen_compute_eflags(s);
1036 if (reg == cpu_cc_src) {
1037 reg = s->tmp0;
1039 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1040 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1041 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1042 .mask = CC_S };
1043 break;
1044 default:
1045 case JCC_LE:
1046 gen_compute_eflags(s);
1047 if (reg == cpu_cc_src) {
1048 reg = s->tmp0;
1050 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1051 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1052 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1053 .mask = CC_S | CC_Z };
1054 break;
1056 break;
1059 if (inv) {
1060 cc.cond = tcg_invert_cond(cc.cond);
1062 return cc;
1065 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1067 CCPrepare cc = gen_prepare_cc(s, b, reg);
1069 if (cc.no_setcond) {
1070 if (cc.cond == TCG_COND_EQ) {
1071 tcg_gen_xori_tl(reg, cc.reg, 1);
1072 } else {
1073 tcg_gen_mov_tl(reg, cc.reg);
1075 return;
1078 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1079 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1080 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1081 tcg_gen_andi_tl(reg, reg, 1);
1082 return;
1084 if (cc.mask != -1) {
1085 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1086 cc.reg = reg;
1088 if (cc.use_reg2) {
1089 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1090 } else {
1091 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1095 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1097 gen_setcc1(s, JCC_B << 1, reg);
1100 /* generate a conditional jump to label 'l1' according to jump opcode
1101 value 'b'. In the fast case, T0 is guaranted not to be used. */
1102 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1104 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1106 if (cc.mask != -1) {
1107 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1108 cc.reg = s->T0;
1110 if (cc.use_reg2) {
1111 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1112 } else {
1113 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1117 /* Generate a conditional jump to label 'l1' according to jump opcode
1118 value 'b'. In the fast case, T0 is guaranted not to be used.
1119 A translation block must end soon. */
1120 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1122 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1124 gen_update_cc_op(s);
1125 if (cc.mask != -1) {
1126 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1127 cc.reg = s->T0;
1129 set_cc_op(s, CC_OP_DYNAMIC);
1130 if (cc.use_reg2) {
1131 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1132 } else {
1133 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1137 /* XXX: does not work with gdbstub "ice" single step - not a
1138 serious problem */
1139 static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1141 TCGLabel *l1 = gen_new_label();
1142 TCGLabel *l2 = gen_new_label();
1143 gen_op_jnz_ecx(s, s->aflag, l1);
1144 gen_set_label(l2);
1145 gen_jmp_tb(s, next_eip, 1);
1146 gen_set_label(l1);
1147 return l2;
1150 static inline void gen_stos(DisasContext *s, MemOp ot)
1152 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
1153 gen_string_movl_A0_EDI(s);
1154 gen_op_st_v(s, ot, s->T0, s->A0);
1155 gen_op_movl_T0_Dshift(s, ot);
1156 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1159 static inline void gen_lods(DisasContext *s, MemOp ot)
1161 gen_string_movl_A0_ESI(s);
1162 gen_op_ld_v(s, ot, s->T0, s->A0);
1163 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
1164 gen_op_movl_T0_Dshift(s, ot);
1165 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1168 static inline void gen_scas(DisasContext *s, MemOp ot)
1170 gen_string_movl_A0_EDI(s);
1171 gen_op_ld_v(s, ot, s->T1, s->A0);
1172 gen_op(s, OP_CMPL, ot, R_EAX);
1173 gen_op_movl_T0_Dshift(s, ot);
1174 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1177 static inline void gen_cmps(DisasContext *s, MemOp ot)
1179 gen_string_movl_A0_EDI(s);
1180 gen_op_ld_v(s, ot, s->T1, s->A0);
1181 gen_string_movl_A0_ESI(s);
1182 gen_op(s, OP_CMPL, ot, OR_TMP0);
1183 gen_op_movl_T0_Dshift(s, ot);
1184 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1185 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1188 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1190 if (s->flags & HF_IOBPT_MASK) {
1191 #ifdef CONFIG_USER_ONLY
1192 /* user-mode cpu should not be in IOBPT mode */
1193 g_assert_not_reached();
1194 #else
1195 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1196 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1198 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1199 tcg_temp_free_i32(t_size);
1200 tcg_temp_free(t_next);
1201 #endif /* CONFIG_USER_ONLY */
1205 static inline void gen_ins(DisasContext *s, MemOp ot)
1207 gen_string_movl_A0_EDI(s);
1208 /* Note: we must do this dummy write first to be restartable in
1209 case of page fault. */
1210 tcg_gen_movi_tl(s->T0, 0);
1211 gen_op_st_v(s, ot, s->T0, s->A0);
1212 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1213 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1214 gen_helper_in_func(ot, s->T0, s->tmp2_i32);
1215 gen_op_st_v(s, ot, s->T0, s->A0);
1216 gen_op_movl_T0_Dshift(s, ot);
1217 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1218 gen_bpt_io(s, s->tmp2_i32, ot);
1221 static inline void gen_outs(DisasContext *s, MemOp ot)
1223 gen_string_movl_A0_ESI(s);
1224 gen_op_ld_v(s, ot, s->T0, s->A0);
1226 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1227 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1228 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0);
1229 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
1230 gen_op_movl_T0_Dshift(s, ot);
1231 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1232 gen_bpt_io(s, s->tmp2_i32, ot);
1235 /* same method as Valgrind : we generate jumps to current or next
1236 instruction */
1237 #define GEN_REPZ(op) \
1238 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1239 target_ulong cur_eip, target_ulong next_eip) \
1241 TCGLabel *l2; \
1242 gen_update_cc_op(s); \
1243 l2 = gen_jz_ecx_string(s, next_eip); \
1244 gen_ ## op(s, ot); \
1245 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1246 /* a loop would cause two single step exceptions if ECX = 1 \
1247 before rep string_insn */ \
1248 if (s->repz_opt) \
1249 gen_op_jz_ecx(s, s->aflag, l2); \
1250 gen_jmp(s, cur_eip); \
1253 #define GEN_REPZ2(op) \
1254 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1255 target_ulong cur_eip, \
1256 target_ulong next_eip, \
1257 int nz) \
1259 TCGLabel *l2; \
1260 gen_update_cc_op(s); \
1261 l2 = gen_jz_ecx_string(s, next_eip); \
1262 gen_ ## op(s, ot); \
1263 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1264 gen_update_cc_op(s); \
1265 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1266 if (s->repz_opt) \
1267 gen_op_jz_ecx(s, s->aflag, l2); \
1268 gen_jmp(s, cur_eip); \
1271 GEN_REPZ(movs)
1272 GEN_REPZ(stos)
1273 GEN_REPZ(lods)
1274 GEN_REPZ(ins)
1275 GEN_REPZ(outs)
1276 GEN_REPZ2(scas)
1277 GEN_REPZ2(cmps)
1279 static void gen_helper_fp_arith_ST0_FT0(int op)
1281 switch (op) {
1282 case 0:
1283 gen_helper_fadd_ST0_FT0(cpu_env);
1284 break;
1285 case 1:
1286 gen_helper_fmul_ST0_FT0(cpu_env);
1287 break;
1288 case 2:
1289 gen_helper_fcom_ST0_FT0(cpu_env);
1290 break;
1291 case 3:
1292 gen_helper_fcom_ST0_FT0(cpu_env);
1293 break;
1294 case 4:
1295 gen_helper_fsub_ST0_FT0(cpu_env);
1296 break;
1297 case 5:
1298 gen_helper_fsubr_ST0_FT0(cpu_env);
1299 break;
1300 case 6:
1301 gen_helper_fdiv_ST0_FT0(cpu_env);
1302 break;
1303 case 7:
1304 gen_helper_fdivr_ST0_FT0(cpu_env);
1305 break;
1309 /* NOTE the exception in "r" op ordering */
1310 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1312 TCGv_i32 tmp = tcg_const_i32(opreg);
1313 switch (op) {
1314 case 0:
1315 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1316 break;
1317 case 1:
1318 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1319 break;
1320 case 4:
1321 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1322 break;
1323 case 5:
1324 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1325 break;
1326 case 6:
1327 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1328 break;
1329 case 7:
1330 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1331 break;
1335 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
1337 gen_update_cc_op(s);
1338 gen_jmp_im(s, cur_eip);
1339 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
1340 s->base.is_jmp = DISAS_NORETURN;
1343 /* Generate #UD for the current instruction. The assumption here is that
1344 the instruction is known, but it isn't allowed in the current cpu mode. */
1345 static void gen_illegal_opcode(DisasContext *s)
1347 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
1350 /* Generate #GP for the current instruction. */
1351 static void gen_exception_gpf(DisasContext *s)
1353 gen_exception(s, EXCP0D_GPF, s->pc_start - s->cs_base);
1356 /* Check for cpl == 0; if not, raise #GP and return false. */
1357 static bool check_cpl0(DisasContext *s)
1359 if (CPL(s) == 0) {
1360 return true;
1362 gen_exception_gpf(s);
1363 return false;
1366 /* If vm86, check for iopl == 3; if not, raise #GP and return false. */
1367 static bool check_vm86_iopl(DisasContext *s)
1369 if (!VM86(s) || IOPL(s) == 3) {
1370 return true;
1372 gen_exception_gpf(s);
1373 return false;
1376 /* Check for iopl allowing access; if not, raise #GP and return false. */
1377 static bool check_iopl(DisasContext *s)
1379 if (VM86(s) ? IOPL(s) == 3 : CPL(s) <= IOPL(s)) {
1380 return true;
1382 gen_exception_gpf(s);
1383 return false;
1386 /* if d == OR_TMP0, it means memory operand (address in A0) */
1387 static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
1389 if (d != OR_TMP0) {
1390 if (s1->prefix & PREFIX_LOCK) {
1391 /* Lock prefix when destination is not memory. */
1392 gen_illegal_opcode(s1);
1393 return;
1395 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1396 } else if (!(s1->prefix & PREFIX_LOCK)) {
1397 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1399 switch(op) {
1400 case OP_ADCL:
1401 gen_compute_eflags_c(s1, s1->tmp4);
1402 if (s1->prefix & PREFIX_LOCK) {
1403 tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1);
1404 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1405 s1->mem_index, ot | MO_LE);
1406 } else {
1407 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1408 tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4);
1409 gen_op_st_rm_T0_A0(s1, ot, d);
1411 gen_op_update3_cc(s1, s1->tmp4);
1412 set_cc_op(s1, CC_OP_ADCB + ot);
1413 break;
1414 case OP_SBBL:
1415 gen_compute_eflags_c(s1, s1->tmp4);
1416 if (s1->prefix & PREFIX_LOCK) {
1417 tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4);
1418 tcg_gen_neg_tl(s1->T0, s1->T0);
1419 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1420 s1->mem_index, ot | MO_LE);
1421 } else {
1422 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1423 tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4);
1424 gen_op_st_rm_T0_A0(s1, ot, d);
1426 gen_op_update3_cc(s1, s1->tmp4);
1427 set_cc_op(s1, CC_OP_SBBB + ot);
1428 break;
1429 case OP_ADDL:
1430 if (s1->prefix & PREFIX_LOCK) {
1431 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1,
1432 s1->mem_index, ot | MO_LE);
1433 } else {
1434 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1435 gen_op_st_rm_T0_A0(s1, ot, d);
1437 gen_op_update2_cc(s1);
1438 set_cc_op(s1, CC_OP_ADDB + ot);
1439 break;
1440 case OP_SUBL:
1441 if (s1->prefix & PREFIX_LOCK) {
1442 tcg_gen_neg_tl(s1->T0, s1->T1);
1443 tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
1444 s1->mem_index, ot | MO_LE);
1445 tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
1446 } else {
1447 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1448 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1449 gen_op_st_rm_T0_A0(s1, ot, d);
1451 gen_op_update2_cc(s1);
1452 set_cc_op(s1, CC_OP_SUBB + ot);
1453 break;
1454 default:
1455 case OP_ANDL:
1456 if (s1->prefix & PREFIX_LOCK) {
1457 tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1,
1458 s1->mem_index, ot | MO_LE);
1459 } else {
1460 tcg_gen_and_tl(s1->T0, s1->T0, s1->T1);
1461 gen_op_st_rm_T0_A0(s1, ot, d);
1463 gen_op_update1_cc(s1);
1464 set_cc_op(s1, CC_OP_LOGICB + ot);
1465 break;
1466 case OP_ORL:
1467 if (s1->prefix & PREFIX_LOCK) {
1468 tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1,
1469 s1->mem_index, ot | MO_LE);
1470 } else {
1471 tcg_gen_or_tl(s1->T0, s1->T0, s1->T1);
1472 gen_op_st_rm_T0_A0(s1, ot, d);
1474 gen_op_update1_cc(s1);
1475 set_cc_op(s1, CC_OP_LOGICB + ot);
1476 break;
1477 case OP_XORL:
1478 if (s1->prefix & PREFIX_LOCK) {
1479 tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1,
1480 s1->mem_index, ot | MO_LE);
1481 } else {
1482 tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1);
1483 gen_op_st_rm_T0_A0(s1, ot, d);
1485 gen_op_update1_cc(s1);
1486 set_cc_op(s1, CC_OP_LOGICB + ot);
1487 break;
1488 case OP_CMPL:
1489 tcg_gen_mov_tl(cpu_cc_src, s1->T1);
1490 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1491 tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
1492 set_cc_op(s1, CC_OP_SUBB + ot);
1493 break;
1497 /* if d == OR_TMP0, it means memory operand (address in A0) */
1498 static void gen_inc(DisasContext *s1, MemOp ot, int d, int c)
1500 if (s1->prefix & PREFIX_LOCK) {
1501 if (d != OR_TMP0) {
1502 /* Lock prefix when destination is not memory */
1503 gen_illegal_opcode(s1);
1504 return;
1506 tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
1507 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1508 s1->mem_index, ot | MO_LE);
1509 } else {
1510 if (d != OR_TMP0) {
1511 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1512 } else {
1513 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1515 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
1516 gen_op_st_rm_T0_A0(s1, ot, d);
1519 gen_compute_eflags_c(s1, cpu_cc_src);
1520 tcg_gen_mov_tl(cpu_cc_dst, s1->T0);
1521 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1524 static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
1525 TCGv shm1, TCGv count, bool is_right)
1527 TCGv_i32 z32, s32, oldop;
1528 TCGv z_tl;
1530 /* Store the results into the CC variables. If we know that the
1531 variable must be dead, store unconditionally. Otherwise we'll
1532 need to not disrupt the current contents. */
1533 z_tl = tcg_const_tl(0);
1534 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1535 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1536 result, cpu_cc_dst);
1537 } else {
1538 tcg_gen_mov_tl(cpu_cc_dst, result);
1540 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1541 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1542 shm1, cpu_cc_src);
1543 } else {
1544 tcg_gen_mov_tl(cpu_cc_src, shm1);
1546 tcg_temp_free(z_tl);
1548 /* Get the two potential CC_OP values into temporaries. */
1549 tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1550 if (s->cc_op == CC_OP_DYNAMIC) {
1551 oldop = cpu_cc_op;
1552 } else {
1553 tcg_gen_movi_i32(s->tmp3_i32, s->cc_op);
1554 oldop = s->tmp3_i32;
1557 /* Conditionally store the CC_OP value. */
1558 z32 = tcg_const_i32(0);
1559 s32 = tcg_temp_new_i32();
1560 tcg_gen_trunc_tl_i32(s32, count);
1561 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop);
1562 tcg_temp_free_i32(z32);
1563 tcg_temp_free_i32(s32);
1565 /* The CC_OP value is no longer predictable. */
1566 set_cc_op(s, CC_OP_DYNAMIC);
1569 static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1,
1570 int is_right, int is_arith)
1572 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1574 /* load */
1575 if (op1 == OR_TMP0) {
1576 gen_op_ld_v(s, ot, s->T0, s->A0);
1577 } else {
1578 gen_op_mov_v_reg(s, ot, s->T0, op1);
1581 tcg_gen_andi_tl(s->T1, s->T1, mask);
1582 tcg_gen_subi_tl(s->tmp0, s->T1, 1);
1584 if (is_right) {
1585 if (is_arith) {
1586 gen_exts(ot, s->T0);
1587 tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0);
1588 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
1589 } else {
1590 gen_extu(ot, s->T0);
1591 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1592 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
1594 } else {
1595 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1596 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
1599 /* store */
1600 gen_op_st_rm_T0_A0(s, ot, op1);
1602 gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right);
1605 static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1606 int is_right, int is_arith)
1608 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1610 /* load */
1611 if (op1 == OR_TMP0)
1612 gen_op_ld_v(s, ot, s->T0, s->A0);
1613 else
1614 gen_op_mov_v_reg(s, ot, s->T0, op1);
1616 op2 &= mask;
1617 if (op2 != 0) {
1618 if (is_right) {
1619 if (is_arith) {
1620 gen_exts(ot, s->T0);
1621 tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1);
1622 tcg_gen_sari_tl(s->T0, s->T0, op2);
1623 } else {
1624 gen_extu(ot, s->T0);
1625 tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1);
1626 tcg_gen_shri_tl(s->T0, s->T0, op2);
1628 } else {
1629 tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1);
1630 tcg_gen_shli_tl(s->T0, s->T0, op2);
1634 /* store */
1635 gen_op_st_rm_T0_A0(s, ot, op1);
1637 /* update eflags if non zero shift */
1638 if (op2 != 0) {
1639 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
1640 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
1641 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1645 static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right)
1647 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1648 TCGv_i32 t0, t1;
1650 /* load */
1651 if (op1 == OR_TMP0) {
1652 gen_op_ld_v(s, ot, s->T0, s->A0);
1653 } else {
1654 gen_op_mov_v_reg(s, ot, s->T0, op1);
1657 tcg_gen_andi_tl(s->T1, s->T1, mask);
1659 switch (ot) {
1660 case MO_8:
1661 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1662 tcg_gen_ext8u_tl(s->T0, s->T0);
1663 tcg_gen_muli_tl(s->T0, s->T0, 0x01010101);
1664 goto do_long;
1665 case MO_16:
1666 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1667 tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16);
1668 goto do_long;
1669 do_long:
1670 #ifdef TARGET_X86_64
1671 case MO_32:
1672 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1673 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
1674 if (is_right) {
1675 tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1676 } else {
1677 tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1679 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1680 break;
1681 #endif
1682 default:
1683 if (is_right) {
1684 tcg_gen_rotr_tl(s->T0, s->T0, s->T1);
1685 } else {
1686 tcg_gen_rotl_tl(s->T0, s->T0, s->T1);
1688 break;
1691 /* store */
1692 gen_op_st_rm_T0_A0(s, ot, op1);
1694 /* We'll need the flags computed into CC_SRC. */
1695 gen_compute_eflags(s);
1697 /* The value that was "rotated out" is now present at the other end
1698 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1699 since we've computed the flags into CC_SRC, these variables are
1700 currently dead. */
1701 if (is_right) {
1702 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1703 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1704 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1705 } else {
1706 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1707 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1709 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1710 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1712 /* Now conditionally store the new CC_OP value. If the shift count
1713 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1714 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1715 exactly as we computed above. */
1716 t0 = tcg_const_i32(0);
1717 t1 = tcg_temp_new_i32();
1718 tcg_gen_trunc_tl_i32(t1, s->T1);
1719 tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX);
1720 tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS);
1721 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1722 s->tmp2_i32, s->tmp3_i32);
1723 tcg_temp_free_i32(t0);
1724 tcg_temp_free_i32(t1);
1726 /* The CC_OP value is no longer predictable. */
1727 set_cc_op(s, CC_OP_DYNAMIC);
1730 static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1731 int is_right)
1733 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1734 int shift;
1736 /* load */
1737 if (op1 == OR_TMP0) {
1738 gen_op_ld_v(s, ot, s->T0, s->A0);
1739 } else {
1740 gen_op_mov_v_reg(s, ot, s->T0, op1);
1743 op2 &= mask;
1744 if (op2 != 0) {
1745 switch (ot) {
1746 #ifdef TARGET_X86_64
1747 case MO_32:
1748 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1749 if (is_right) {
1750 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2);
1751 } else {
1752 tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2);
1754 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1755 break;
1756 #endif
1757 default:
1758 if (is_right) {
1759 tcg_gen_rotri_tl(s->T0, s->T0, op2);
1760 } else {
1761 tcg_gen_rotli_tl(s->T0, s->T0, op2);
1763 break;
1764 case MO_8:
1765 mask = 7;
1766 goto do_shifts;
1767 case MO_16:
1768 mask = 15;
1769 do_shifts:
1770 shift = op2 & mask;
1771 if (is_right) {
1772 shift = mask + 1 - shift;
1774 gen_extu(ot, s->T0);
1775 tcg_gen_shli_tl(s->tmp0, s->T0, shift);
1776 tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift);
1777 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
1778 break;
1782 /* store */
1783 gen_op_st_rm_T0_A0(s, ot, op1);
1785 if (op2 != 0) {
1786 /* Compute the flags into CC_SRC. */
1787 gen_compute_eflags(s);
1789 /* The value that was "rotated out" is now present at the other end
1790 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1791 since we've computed the flags into CC_SRC, these variables are
1792 currently dead. */
1793 if (is_right) {
1794 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1795 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1796 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1797 } else {
1798 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1799 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1801 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1802 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1803 set_cc_op(s, CC_OP_ADCOX);
1807 /* XXX: add faster immediate = 1 case */
1808 static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
1809 int is_right)
1811 gen_compute_eflags(s);
1812 assert(s->cc_op == CC_OP_EFLAGS);
1814 /* load */
1815 if (op1 == OR_TMP0)
1816 gen_op_ld_v(s, ot, s->T0, s->A0);
1817 else
1818 gen_op_mov_v_reg(s, ot, s->T0, op1);
1820 if (is_right) {
1821 switch (ot) {
1822 case MO_8:
1823 gen_helper_rcrb(s->T0, cpu_env, s->T0, s->T1);
1824 break;
1825 case MO_16:
1826 gen_helper_rcrw(s->T0, cpu_env, s->T0, s->T1);
1827 break;
1828 case MO_32:
1829 gen_helper_rcrl(s->T0, cpu_env, s->T0, s->T1);
1830 break;
1831 #ifdef TARGET_X86_64
1832 case MO_64:
1833 gen_helper_rcrq(s->T0, cpu_env, s->T0, s->T1);
1834 break;
1835 #endif
1836 default:
1837 tcg_abort();
1839 } else {
1840 switch (ot) {
1841 case MO_8:
1842 gen_helper_rclb(s->T0, cpu_env, s->T0, s->T1);
1843 break;
1844 case MO_16:
1845 gen_helper_rclw(s->T0, cpu_env, s->T0, s->T1);
1846 break;
1847 case MO_32:
1848 gen_helper_rcll(s->T0, cpu_env, s->T0, s->T1);
1849 break;
1850 #ifdef TARGET_X86_64
1851 case MO_64:
1852 gen_helper_rclq(s->T0, cpu_env, s->T0, s->T1);
1853 break;
1854 #endif
1855 default:
1856 tcg_abort();
1859 /* store */
1860 gen_op_st_rm_T0_A0(s, ot, op1);
1863 /* XXX: add faster immediate case */
1864 static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
1865 bool is_right, TCGv count_in)
1867 target_ulong mask = (ot == MO_64 ? 63 : 31);
1868 TCGv count;
1870 /* load */
1871 if (op1 == OR_TMP0) {
1872 gen_op_ld_v(s, ot, s->T0, s->A0);
1873 } else {
1874 gen_op_mov_v_reg(s, ot, s->T0, op1);
1877 count = tcg_temp_new();
1878 tcg_gen_andi_tl(count, count_in, mask);
1880 switch (ot) {
1881 case MO_16:
1882 /* Note: we implement the Intel behaviour for shift count > 16.
1883 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1884 portion by constructing it as a 32-bit value. */
1885 if (is_right) {
1886 tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16);
1887 tcg_gen_mov_tl(s->T1, s->T0);
1888 tcg_gen_mov_tl(s->T0, s->tmp0);
1889 } else {
1890 tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
1893 * If TARGET_X86_64 defined then fall through into MO_32 case,
1894 * otherwise fall through default case.
1896 case MO_32:
1897 #ifdef TARGET_X86_64
1898 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1899 tcg_gen_subi_tl(s->tmp0, count, 1);
1900 if (is_right) {
1901 tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1);
1902 tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0);
1903 tcg_gen_shr_i64(s->T0, s->T0, count);
1904 } else {
1905 tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0);
1906 tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0);
1907 tcg_gen_shl_i64(s->T0, s->T0, count);
1908 tcg_gen_shri_i64(s->tmp0, s->tmp0, 32);
1909 tcg_gen_shri_i64(s->T0, s->T0, 32);
1911 break;
1912 #endif
1913 default:
1914 tcg_gen_subi_tl(s->tmp0, count, 1);
1915 if (is_right) {
1916 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1918 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1919 tcg_gen_shr_tl(s->T0, s->T0, count);
1920 tcg_gen_shl_tl(s->T1, s->T1, s->tmp4);
1921 } else {
1922 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1923 if (ot == MO_16) {
1924 /* Only needed if count > 16, for Intel behaviour. */
1925 tcg_gen_subfi_tl(s->tmp4, 33, count);
1926 tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4);
1927 tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4);
1930 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1931 tcg_gen_shl_tl(s->T0, s->T0, count);
1932 tcg_gen_shr_tl(s->T1, s->T1, s->tmp4);
1934 tcg_gen_movi_tl(s->tmp4, 0);
1935 tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4,
1936 s->tmp4, s->T1);
1937 tcg_gen_or_tl(s->T0, s->T0, s->T1);
1938 break;
1941 /* store */
1942 gen_op_st_rm_T0_A0(s, ot, op1);
1944 gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
1945 tcg_temp_free(count);
1948 static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s)
1950 if (s != OR_TMP1)
1951 gen_op_mov_v_reg(s1, ot, s1->T1, s);
1952 switch(op) {
1953 case OP_ROL:
1954 gen_rot_rm_T1(s1, ot, d, 0);
1955 break;
1956 case OP_ROR:
1957 gen_rot_rm_T1(s1, ot, d, 1);
1958 break;
1959 case OP_SHL:
1960 case OP_SHL1:
1961 gen_shift_rm_T1(s1, ot, d, 0, 0);
1962 break;
1963 case OP_SHR:
1964 gen_shift_rm_T1(s1, ot, d, 1, 0);
1965 break;
1966 case OP_SAR:
1967 gen_shift_rm_T1(s1, ot, d, 1, 1);
1968 break;
1969 case OP_RCL:
1970 gen_rotc_rm_T1(s1, ot, d, 0);
1971 break;
1972 case OP_RCR:
1973 gen_rotc_rm_T1(s1, ot, d, 1);
1974 break;
1978 static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c)
1980 switch(op) {
1981 case OP_ROL:
1982 gen_rot_rm_im(s1, ot, d, c, 0);
1983 break;
1984 case OP_ROR:
1985 gen_rot_rm_im(s1, ot, d, c, 1);
1986 break;
1987 case OP_SHL:
1988 case OP_SHL1:
1989 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1990 break;
1991 case OP_SHR:
1992 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1993 break;
1994 case OP_SAR:
1995 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1996 break;
1997 default:
1998 /* currently not optimized */
1999 tcg_gen_movi_tl(s1->T1, c);
2000 gen_shift(s1, op, ot, d, OR_TMP1);
2001 break;
2005 #define X86_MAX_INSN_LENGTH 15
2007 static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
2009 uint64_t pc = s->pc;
2011 s->pc += num_bytes;
2012 if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
2013 /* If the instruction's 16th byte is on a different page than the 1st, a
2014 * page fault on the second page wins over the general protection fault
2015 * caused by the instruction being too long.
2016 * This can happen even if the operand is only one byte long!
2018 if (((s->pc - 1) ^ (pc - 1)) & TARGET_PAGE_MASK) {
2019 volatile uint8_t unused =
2020 cpu_ldub_code(env, (s->pc - 1) & TARGET_PAGE_MASK);
2021 (void) unused;
2023 siglongjmp(s->jmpbuf, 1);
2026 return pc;
2029 static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
2031 return translator_ldub(env, advance_pc(env, s, 1));
2034 static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
2036 return translator_ldsw(env, advance_pc(env, s, 2));
2039 static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
2041 return translator_lduw(env, advance_pc(env, s, 2));
2044 static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
2046 return translator_ldl(env, advance_pc(env, s, 4));
2049 #ifdef TARGET_X86_64
2050 static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
2052 return translator_ldq(env, advance_pc(env, s, 8));
2054 #endif
2056 /* Decompose an address. */
2058 typedef struct AddressParts {
2059 int def_seg;
2060 int base;
2061 int index;
2062 int scale;
2063 target_long disp;
2064 } AddressParts;
2066 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
2067 int modrm)
2069 int def_seg, base, index, scale, mod, rm;
2070 target_long disp;
2071 bool havesib;
2073 def_seg = R_DS;
2074 index = -1;
2075 scale = 0;
2076 disp = 0;
2078 mod = (modrm >> 6) & 3;
2079 rm = modrm & 7;
2080 base = rm | REX_B(s);
2082 if (mod == 3) {
2083 /* Normally filtered out earlier, but including this path
2084 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
2085 goto done;
2088 switch (s->aflag) {
2089 case MO_64:
2090 case MO_32:
2091 havesib = 0;
2092 if (rm == 4) {
2093 int code = x86_ldub_code(env, s);
2094 scale = (code >> 6) & 3;
2095 index = ((code >> 3) & 7) | REX_X(s);
2096 if (index == 4) {
2097 index = -1; /* no index */
2099 base = (code & 7) | REX_B(s);
2100 havesib = 1;
2103 switch (mod) {
2104 case 0:
2105 if ((base & 7) == 5) {
2106 base = -1;
2107 disp = (int32_t)x86_ldl_code(env, s);
2108 if (CODE64(s) && !havesib) {
2109 base = -2;
2110 disp += s->pc + s->rip_offset;
2113 break;
2114 case 1:
2115 disp = (int8_t)x86_ldub_code(env, s);
2116 break;
2117 default:
2118 case 2:
2119 disp = (int32_t)x86_ldl_code(env, s);
2120 break;
2123 /* For correct popl handling with esp. */
2124 if (base == R_ESP && s->popl_esp_hack) {
2125 disp += s->popl_esp_hack;
2127 if (base == R_EBP || base == R_ESP) {
2128 def_seg = R_SS;
2130 break;
2132 case MO_16:
2133 if (mod == 0) {
2134 if (rm == 6) {
2135 base = -1;
2136 disp = x86_lduw_code(env, s);
2137 break;
2139 } else if (mod == 1) {
2140 disp = (int8_t)x86_ldub_code(env, s);
2141 } else {
2142 disp = (int16_t)x86_lduw_code(env, s);
2145 switch (rm) {
2146 case 0:
2147 base = R_EBX;
2148 index = R_ESI;
2149 break;
2150 case 1:
2151 base = R_EBX;
2152 index = R_EDI;
2153 break;
2154 case 2:
2155 base = R_EBP;
2156 index = R_ESI;
2157 def_seg = R_SS;
2158 break;
2159 case 3:
2160 base = R_EBP;
2161 index = R_EDI;
2162 def_seg = R_SS;
2163 break;
2164 case 4:
2165 base = R_ESI;
2166 break;
2167 case 5:
2168 base = R_EDI;
2169 break;
2170 case 6:
2171 base = R_EBP;
2172 def_seg = R_SS;
2173 break;
2174 default:
2175 case 7:
2176 base = R_EBX;
2177 break;
2179 break;
2181 default:
2182 tcg_abort();
2185 done:
2186 return (AddressParts){ def_seg, base, index, scale, disp };
2189 /* Compute the address, with a minimum number of TCG ops. */
2190 static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a)
2192 TCGv ea = NULL;
2194 if (a.index >= 0) {
2195 if (a.scale == 0) {
2196 ea = cpu_regs[a.index];
2197 } else {
2198 tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale);
2199 ea = s->A0;
2201 if (a.base >= 0) {
2202 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2203 ea = s->A0;
2205 } else if (a.base >= 0) {
2206 ea = cpu_regs[a.base];
2208 if (!ea) {
2209 tcg_gen_movi_tl(s->A0, a.disp);
2210 ea = s->A0;
2211 } else if (a.disp != 0) {
2212 tcg_gen_addi_tl(s->A0, ea, a.disp);
2213 ea = s->A0;
2216 return ea;
2219 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2221 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2222 TCGv ea = gen_lea_modrm_1(s, a);
2223 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2226 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2228 (void)gen_lea_modrm_0(env, s, modrm);
2231 /* Used for BNDCL, BNDCU, BNDCN. */
2232 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2233 TCGCond cond, TCGv_i64 bndv)
2235 TCGv ea = gen_lea_modrm_1(s, gen_lea_modrm_0(env, s, modrm));
2237 tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
2238 if (!CODE64(s)) {
2239 tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64);
2241 tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv);
2242 tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64);
2243 gen_helper_bndck(cpu_env, s->tmp2_i32);
2246 /* used for LEA and MOV AX, mem */
2247 static void gen_add_A0_ds_seg(DisasContext *s)
2249 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
2252 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2253 OR_TMP0 */
2254 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2255 MemOp ot, int reg, int is_store)
2257 int mod, rm;
2259 mod = (modrm >> 6) & 3;
2260 rm = (modrm & 7) | REX_B(s);
2261 if (mod == 3) {
2262 if (is_store) {
2263 if (reg != OR_TMP0)
2264 gen_op_mov_v_reg(s, ot, s->T0, reg);
2265 gen_op_mov_reg_v(s, ot, rm, s->T0);
2266 } else {
2267 gen_op_mov_v_reg(s, ot, s->T0, rm);
2268 if (reg != OR_TMP0)
2269 gen_op_mov_reg_v(s, ot, reg, s->T0);
2271 } else {
2272 gen_lea_modrm(env, s, modrm);
2273 if (is_store) {
2274 if (reg != OR_TMP0)
2275 gen_op_mov_v_reg(s, ot, s->T0, reg);
2276 gen_op_st_v(s, ot, s->T0, s->A0);
2277 } else {
2278 gen_op_ld_v(s, ot, s->T0, s->A0);
2279 if (reg != OR_TMP0)
2280 gen_op_mov_reg_v(s, ot, reg, s->T0);
2285 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
2287 uint32_t ret;
2289 switch (ot) {
2290 case MO_8:
2291 ret = x86_ldub_code(env, s);
2292 break;
2293 case MO_16:
2294 ret = x86_lduw_code(env, s);
2295 break;
2296 case MO_32:
2297 #ifdef TARGET_X86_64
2298 case MO_64:
2299 #endif
2300 ret = x86_ldl_code(env, s);
2301 break;
2302 default:
2303 tcg_abort();
2305 return ret;
2308 static inline int insn_const_size(MemOp ot)
2310 if (ot <= MO_32) {
2311 return 1 << ot;
2312 } else {
2313 return 4;
2317 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2319 #ifndef CONFIG_USER_ONLY
2320 return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
2321 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2322 #else
2323 return true;
2324 #endif
2327 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2329 target_ulong pc = s->cs_base + eip;
2331 if (use_goto_tb(s, pc)) {
2332 /* jump to same page: we can use a direct jump */
2333 tcg_gen_goto_tb(tb_num);
2334 gen_jmp_im(s, eip);
2335 tcg_gen_exit_tb(s->base.tb, tb_num);
2336 s->base.is_jmp = DISAS_NORETURN;
2337 } else {
2338 /* jump to another page */
2339 gen_jmp_im(s, eip);
2340 gen_jr(s, s->tmp0);
2344 static inline void gen_jcc(DisasContext *s, int b,
2345 target_ulong val, target_ulong next_eip)
2347 TCGLabel *l1, *l2;
2349 if (s->jmp_opt) {
2350 l1 = gen_new_label();
2351 gen_jcc1(s, b, l1);
2353 gen_goto_tb(s, 0, next_eip);
2355 gen_set_label(l1);
2356 gen_goto_tb(s, 1, val);
2357 } else {
2358 l1 = gen_new_label();
2359 l2 = gen_new_label();
2360 gen_jcc1(s, b, l1);
2362 gen_jmp_im(s, next_eip);
2363 tcg_gen_br(l2);
2365 gen_set_label(l1);
2366 gen_jmp_im(s, val);
2367 gen_set_label(l2);
2368 gen_eob(s);
2372 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
2373 int modrm, int reg)
2375 CCPrepare cc;
2377 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2379 cc = gen_prepare_cc(s, b, s->T1);
2380 if (cc.mask != -1) {
2381 TCGv t0 = tcg_temp_new();
2382 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2383 cc.reg = t0;
2385 if (!cc.use_reg2) {
2386 cc.reg2 = tcg_const_tl(cc.imm);
2389 tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2,
2390 s->T0, cpu_regs[reg]);
2391 gen_op_mov_reg_v(s, ot, reg, s->T0);
2393 if (cc.mask != -1) {
2394 tcg_temp_free(cc.reg);
2396 if (!cc.use_reg2) {
2397 tcg_temp_free(cc.reg2);
2401 static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg)
2403 tcg_gen_ld32u_tl(s->T0, cpu_env,
2404 offsetof(CPUX86State,segs[seg_reg].selector));
2407 static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg)
2409 tcg_gen_ext16u_tl(s->T0, s->T0);
2410 tcg_gen_st32_tl(s->T0, cpu_env,
2411 offsetof(CPUX86State,segs[seg_reg].selector));
2412 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
2415 /* move T0 to seg_reg and compute if the CPU state may change. Never
2416 call this function with seg_reg == R_CS */
2417 static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg)
2419 if (PE(s) && !VM86(s)) {
2420 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
2421 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), s->tmp2_i32);
2422 /* abort translation because the addseg value may change or
2423 because ss32 may change. For R_SS, translation must always
2424 stop as a special handling must be done to disable hardware
2425 interrupts for the next instruction */
2426 if (seg_reg == R_SS || (CODE32(s) && seg_reg < R_FS)) {
2427 s->base.is_jmp = DISAS_TOO_MANY;
2429 } else {
2430 gen_op_movl_seg_T0_vm(s, seg_reg);
2431 if (seg_reg == R_SS) {
2432 s->base.is_jmp = DISAS_TOO_MANY;
2437 static void gen_svm_check_intercept(DisasContext *s, uint32_t type)
2439 /* no SVM activated; fast case */
2440 if (likely(!GUEST(s))) {
2441 return;
2443 gen_helper_svm_check_intercept(cpu_env, tcg_constant_i32(type));
2446 static inline void gen_stack_update(DisasContext *s, int addend)
2448 gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend);
2451 /* Generate a push. It depends on ss32, addseg and dflag. */
2452 static void gen_push_v(DisasContext *s, TCGv val)
2454 MemOp d_ot = mo_pushpop(s, s->dflag);
2455 MemOp a_ot = mo_stacksize(s);
2456 int size = 1 << d_ot;
2457 TCGv new_esp = s->A0;
2459 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2461 if (!CODE64(s)) {
2462 if (ADDSEG(s)) {
2463 new_esp = s->tmp4;
2464 tcg_gen_mov_tl(new_esp, s->A0);
2466 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2469 gen_op_st_v(s, d_ot, val, s->A0);
2470 gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp);
2473 /* two step pop is necessary for precise exceptions */
2474 static MemOp gen_pop_T0(DisasContext *s)
2476 MemOp d_ot = mo_pushpop(s, s->dflag);
2478 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2479 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2481 return d_ot;
2484 static inline void gen_pop_update(DisasContext *s, MemOp ot)
2486 gen_stack_update(s, 1 << ot);
2489 static inline void gen_stack_A0(DisasContext *s)
2491 gen_lea_v_seg(s, SS32(s) ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2494 static void gen_pusha(DisasContext *s)
2496 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2497 MemOp d_ot = s->dflag;
2498 int size = 1 << d_ot;
2499 int i;
2501 for (i = 0; i < 8; i++) {
2502 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size);
2503 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2504 gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0);
2507 gen_stack_update(s, -8 * size);
2510 static void gen_popa(DisasContext *s)
2512 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2513 MemOp d_ot = s->dflag;
2514 int size = 1 << d_ot;
2515 int i;
2517 for (i = 0; i < 8; i++) {
2518 /* ESP is not reloaded */
2519 if (7 - i == R_ESP) {
2520 continue;
2522 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size);
2523 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2524 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2525 gen_op_mov_reg_v(s, d_ot, 7 - i, s->T0);
2528 gen_stack_update(s, 8 * size);
2531 static void gen_enter(DisasContext *s, int esp_addend, int level)
2533 MemOp d_ot = mo_pushpop(s, s->dflag);
2534 MemOp a_ot = CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
2535 int size = 1 << d_ot;
2537 /* Push BP; compute FrameTemp into T1. */
2538 tcg_gen_subi_tl(s->T1, cpu_regs[R_ESP], size);
2539 gen_lea_v_seg(s, a_ot, s->T1, R_SS, -1);
2540 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0);
2542 level &= 31;
2543 if (level != 0) {
2544 int i;
2546 /* Copy level-1 pointers from the previous frame. */
2547 for (i = 1; i < level; ++i) {
2548 tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i);
2549 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2550 gen_op_ld_v(s, d_ot, s->tmp0, s->A0);
2552 tcg_gen_subi_tl(s->A0, s->T1, size * i);
2553 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2554 gen_op_st_v(s, d_ot, s->tmp0, s->A0);
2557 /* Push the current FrameTemp as the last level. */
2558 tcg_gen_subi_tl(s->A0, s->T1, size * level);
2559 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2560 gen_op_st_v(s, d_ot, s->T1, s->A0);
2563 /* Copy the FrameTemp value to EBP. */
2564 gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
2566 /* Compute the final value of ESP. */
2567 tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
2568 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2571 static void gen_leave(DisasContext *s)
2573 MemOp d_ot = mo_pushpop(s, s->dflag);
2574 MemOp a_ot = mo_stacksize(s);
2576 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2577 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2579 tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot);
2581 gen_op_mov_reg_v(s, d_ot, R_EBP, s->T0);
2582 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2585 /* Similarly, except that the assumption here is that we don't decode
2586 the instruction at all -- either a missing opcode, an unimplemented
2587 feature, or just a bogus instruction stream. */
2588 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2590 gen_illegal_opcode(s);
2592 if (qemu_loglevel_mask(LOG_UNIMP)) {
2593 FILE *logfile = qemu_log_lock();
2594 target_ulong pc = s->pc_start, end = s->pc;
2596 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2597 for (; pc < end; ++pc) {
2598 qemu_log(" %02x", cpu_ldub_code(env, pc));
2600 qemu_log("\n");
2601 qemu_log_unlock(logfile);
2605 /* an interrupt is different from an exception because of the
2606 privilege checks */
2607 static void gen_interrupt(DisasContext *s, int intno,
2608 target_ulong cur_eip, target_ulong next_eip)
2610 gen_update_cc_op(s);
2611 gen_jmp_im(s, cur_eip);
2612 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2613 tcg_const_i32(next_eip - cur_eip));
2614 s->base.is_jmp = DISAS_NORETURN;
2617 static void gen_debug(DisasContext *s)
2619 gen_update_cc_op(s);
2620 gen_jmp_im(s, s->base.pc_next - s->cs_base);
2621 gen_helper_debug(cpu_env);
2622 s->base.is_jmp = DISAS_NORETURN;
2625 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2627 if ((s->flags & mask) == 0) {
2628 TCGv_i32 t = tcg_temp_new_i32();
2629 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2630 tcg_gen_ori_i32(t, t, mask);
2631 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2632 tcg_temp_free_i32(t);
2633 s->flags |= mask;
2637 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2639 if (s->flags & mask) {
2640 TCGv_i32 t = tcg_temp_new_i32();
2641 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2642 tcg_gen_andi_i32(t, t, ~mask);
2643 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2644 tcg_temp_free_i32(t);
2645 s->flags &= ~mask;
2649 /* Clear BND registers during legacy branches. */
2650 static void gen_bnd_jmp(DisasContext *s)
2652 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2653 and if the BNDREGs are known to be in use (non-zero) already.
2654 The helper itself will check BNDPRESERVE at runtime. */
2655 if ((s->prefix & PREFIX_REPNZ) == 0
2656 && (s->flags & HF_MPX_EN_MASK) != 0
2657 && (s->flags & HF_MPX_IU_MASK) != 0) {
2658 gen_helper_bnd_jmp(cpu_env);
2662 /* Generate an end of block. Trace exception is also generated if needed.
2663 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.
2664 If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
2665 S->TF. This is used by the syscall/sysret insns. */
2666 static void
2667 do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2669 gen_update_cc_op(s);
2671 /* If several instructions disable interrupts, only the first does it. */
2672 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2673 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2674 } else {
2675 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2678 if (s->base.tb->flags & HF_RF_MASK) {
2679 gen_helper_reset_rf(cpu_env);
2681 if (s->base.singlestep_enabled) {
2682 gen_helper_debug(cpu_env);
2683 } else if (recheck_tf) {
2684 gen_helper_rechecking_single_step(cpu_env);
2685 tcg_gen_exit_tb(NULL, 0);
2686 } else if (s->flags & HF_TF_MASK) {
2687 gen_helper_single_step(cpu_env);
2688 } else if (jr) {
2689 tcg_gen_lookup_and_goto_ptr();
2690 } else {
2691 tcg_gen_exit_tb(NULL, 0);
2693 s->base.is_jmp = DISAS_NORETURN;
2696 static inline void
2697 gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2699 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2702 /* End of block.
2703 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2704 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2706 gen_eob_worker(s, inhibit, false);
2709 /* End of block, resetting the inhibit irq flag. */
2710 static void gen_eob(DisasContext *s)
2712 gen_eob_worker(s, false, false);
2715 /* Jump to register */
2716 static void gen_jr(DisasContext *s, TCGv dest)
2718 do_gen_eob_worker(s, false, false, true);
2721 /* generate a jump to eip. No segment change must happen before as a
2722 direct call to the next block may occur */
2723 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2725 gen_update_cc_op(s);
2726 set_cc_op(s, CC_OP_DYNAMIC);
2727 if (s->jmp_opt) {
2728 gen_goto_tb(s, tb_num, eip);
2729 } else {
2730 gen_jmp_im(s, eip);
2731 gen_eob(s);
2735 static void gen_jmp(DisasContext *s, target_ulong eip)
2737 gen_jmp_tb(s, eip, 0);
2740 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2742 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2743 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset);
2746 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2748 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset);
2749 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2752 static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2754 int mem_index = s->mem_index;
2755 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2756 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2757 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2758 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2759 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2762 static inline void gen_sto_env_A0(DisasContext *s, int offset)
2764 int mem_index = s->mem_index;
2765 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2766 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2767 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2768 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2769 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2772 static inline void gen_op_movo(DisasContext *s, int d_offset, int s_offset)
2774 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2775 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2776 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2777 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2780 static inline void gen_op_movq(DisasContext *s, int d_offset, int s_offset)
2782 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset);
2783 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2786 static inline void gen_op_movl(DisasContext *s, int d_offset, int s_offset)
2788 tcg_gen_ld_i32(s->tmp2_i32, cpu_env, s_offset);
2789 tcg_gen_st_i32(s->tmp2_i32, cpu_env, d_offset);
2792 static inline void gen_op_movq_env_0(DisasContext *s, int d_offset)
2794 tcg_gen_movi_i64(s->tmp1_i64, 0);
2795 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2798 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2799 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2800 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2801 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2802 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2803 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2804 TCGv_i32 val);
2805 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2806 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2807 TCGv val);
2809 #define SSE_SPECIAL ((void *)1)
2810 #define SSE_DUMMY ((void *)2)
2812 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2813 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2814 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2816 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2817 /* 3DNow! extensions */
2818 [0x0e] = { SSE_DUMMY }, /* femms */
2819 [0x0f] = { SSE_DUMMY }, /* pf... */
2820 /* pure SSE operations */
2821 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2822 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2823 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2824 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2825 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2826 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2827 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2828 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2830 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2831 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2832 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2833 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2834 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2835 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2836 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2837 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2838 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2839 [0x51] = SSE_FOP(sqrt),
2840 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2841 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2842 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2843 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2844 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2845 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2846 [0x58] = SSE_FOP(add),
2847 [0x59] = SSE_FOP(mul),
2848 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2849 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2850 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2851 [0x5c] = SSE_FOP(sub),
2852 [0x5d] = SSE_FOP(min),
2853 [0x5e] = SSE_FOP(div),
2854 [0x5f] = SSE_FOP(max),
2856 [0xc2] = SSE_FOP(cmpeq),
2857 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2858 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2860 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2861 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2862 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2864 /* MMX ops and their SSE extensions */
2865 [0x60] = MMX_OP2(punpcklbw),
2866 [0x61] = MMX_OP2(punpcklwd),
2867 [0x62] = MMX_OP2(punpckldq),
2868 [0x63] = MMX_OP2(packsswb),
2869 [0x64] = MMX_OP2(pcmpgtb),
2870 [0x65] = MMX_OP2(pcmpgtw),
2871 [0x66] = MMX_OP2(pcmpgtl),
2872 [0x67] = MMX_OP2(packuswb),
2873 [0x68] = MMX_OP2(punpckhbw),
2874 [0x69] = MMX_OP2(punpckhwd),
2875 [0x6a] = MMX_OP2(punpckhdq),
2876 [0x6b] = MMX_OP2(packssdw),
2877 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2878 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2879 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2880 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2881 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2882 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2883 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2884 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2885 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2886 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2887 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2888 [0x74] = MMX_OP2(pcmpeqb),
2889 [0x75] = MMX_OP2(pcmpeqw),
2890 [0x76] = MMX_OP2(pcmpeql),
2891 [0x77] = { SSE_DUMMY }, /* emms */
2892 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2893 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2894 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2895 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2896 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2897 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2898 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2899 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2900 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2901 [0xd1] = MMX_OP2(psrlw),
2902 [0xd2] = MMX_OP2(psrld),
2903 [0xd3] = MMX_OP2(psrlq),
2904 [0xd4] = MMX_OP2(paddq),
2905 [0xd5] = MMX_OP2(pmullw),
2906 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2907 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2908 [0xd8] = MMX_OP2(psubusb),
2909 [0xd9] = MMX_OP2(psubusw),
2910 [0xda] = MMX_OP2(pminub),
2911 [0xdb] = MMX_OP2(pand),
2912 [0xdc] = MMX_OP2(paddusb),
2913 [0xdd] = MMX_OP2(paddusw),
2914 [0xde] = MMX_OP2(pmaxub),
2915 [0xdf] = MMX_OP2(pandn),
2916 [0xe0] = MMX_OP2(pavgb),
2917 [0xe1] = MMX_OP2(psraw),
2918 [0xe2] = MMX_OP2(psrad),
2919 [0xe3] = MMX_OP2(pavgw),
2920 [0xe4] = MMX_OP2(pmulhuw),
2921 [0xe5] = MMX_OP2(pmulhw),
2922 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2923 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2924 [0xe8] = MMX_OP2(psubsb),
2925 [0xe9] = MMX_OP2(psubsw),
2926 [0xea] = MMX_OP2(pminsw),
2927 [0xeb] = MMX_OP2(por),
2928 [0xec] = MMX_OP2(paddsb),
2929 [0xed] = MMX_OP2(paddsw),
2930 [0xee] = MMX_OP2(pmaxsw),
2931 [0xef] = MMX_OP2(pxor),
2932 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2933 [0xf1] = MMX_OP2(psllw),
2934 [0xf2] = MMX_OP2(pslld),
2935 [0xf3] = MMX_OP2(psllq),
2936 [0xf4] = MMX_OP2(pmuludq),
2937 [0xf5] = MMX_OP2(pmaddwd),
2938 [0xf6] = MMX_OP2(psadbw),
2939 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2940 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
2941 [0xf8] = MMX_OP2(psubb),
2942 [0xf9] = MMX_OP2(psubw),
2943 [0xfa] = MMX_OP2(psubl),
2944 [0xfb] = MMX_OP2(psubq),
2945 [0xfc] = MMX_OP2(paddb),
2946 [0xfd] = MMX_OP2(paddw),
2947 [0xfe] = MMX_OP2(paddl),
2950 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2951 [0 + 2] = MMX_OP2(psrlw),
2952 [0 + 4] = MMX_OP2(psraw),
2953 [0 + 6] = MMX_OP2(psllw),
2954 [8 + 2] = MMX_OP2(psrld),
2955 [8 + 4] = MMX_OP2(psrad),
2956 [8 + 6] = MMX_OP2(pslld),
2957 [16 + 2] = MMX_OP2(psrlq),
2958 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2959 [16 + 6] = MMX_OP2(psllq),
2960 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2963 static const SSEFunc_0_epi sse_op_table3ai[] = {
2964 gen_helper_cvtsi2ss,
2965 gen_helper_cvtsi2sd
2968 #ifdef TARGET_X86_64
2969 static const SSEFunc_0_epl sse_op_table3aq[] = {
2970 gen_helper_cvtsq2ss,
2971 gen_helper_cvtsq2sd
2973 #endif
2975 static const SSEFunc_i_ep sse_op_table3bi[] = {
2976 gen_helper_cvttss2si,
2977 gen_helper_cvtss2si,
2978 gen_helper_cvttsd2si,
2979 gen_helper_cvtsd2si
2982 #ifdef TARGET_X86_64
2983 static const SSEFunc_l_ep sse_op_table3bq[] = {
2984 gen_helper_cvttss2sq,
2985 gen_helper_cvtss2sq,
2986 gen_helper_cvttsd2sq,
2987 gen_helper_cvtsd2sq
2989 #endif
2991 static const SSEFunc_0_epp sse_op_table4[8][4] = {
2992 SSE_FOP(cmpeq),
2993 SSE_FOP(cmplt),
2994 SSE_FOP(cmple),
2995 SSE_FOP(cmpunord),
2996 SSE_FOP(cmpneq),
2997 SSE_FOP(cmpnlt),
2998 SSE_FOP(cmpnle),
2999 SSE_FOP(cmpord),
3002 static const SSEFunc_0_epp sse_op_table5[256] = {
3003 [0x0c] = gen_helper_pi2fw,
3004 [0x0d] = gen_helper_pi2fd,
3005 [0x1c] = gen_helper_pf2iw,
3006 [0x1d] = gen_helper_pf2id,
3007 [0x8a] = gen_helper_pfnacc,
3008 [0x8e] = gen_helper_pfpnacc,
3009 [0x90] = gen_helper_pfcmpge,
3010 [0x94] = gen_helper_pfmin,
3011 [0x96] = gen_helper_pfrcp,
3012 [0x97] = gen_helper_pfrsqrt,
3013 [0x9a] = gen_helper_pfsub,
3014 [0x9e] = gen_helper_pfadd,
3015 [0xa0] = gen_helper_pfcmpgt,
3016 [0xa4] = gen_helper_pfmax,
3017 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
3018 [0xa7] = gen_helper_movq, /* pfrsqit1 */
3019 [0xaa] = gen_helper_pfsubr,
3020 [0xae] = gen_helper_pfacc,
3021 [0xb0] = gen_helper_pfcmpeq,
3022 [0xb4] = gen_helper_pfmul,
3023 [0xb6] = gen_helper_movq, /* pfrcpit2 */
3024 [0xb7] = gen_helper_pmulhrw_mmx,
3025 [0xbb] = gen_helper_pswapd,
3026 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
3029 struct SSEOpHelper_epp {
3030 SSEFunc_0_epp op[2];
3031 uint32_t ext_mask;
3034 struct SSEOpHelper_eppi {
3035 SSEFunc_0_eppi op[2];
3036 uint32_t ext_mask;
3039 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
3040 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
3041 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
3042 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
3043 #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
3044 CPUID_EXT_PCLMULQDQ }
3045 #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
3047 static const struct SSEOpHelper_epp sse_op_table6[256] = {
3048 [0x00] = SSSE3_OP(pshufb),
3049 [0x01] = SSSE3_OP(phaddw),
3050 [0x02] = SSSE3_OP(phaddd),
3051 [0x03] = SSSE3_OP(phaddsw),
3052 [0x04] = SSSE3_OP(pmaddubsw),
3053 [0x05] = SSSE3_OP(phsubw),
3054 [0x06] = SSSE3_OP(phsubd),
3055 [0x07] = SSSE3_OP(phsubsw),
3056 [0x08] = SSSE3_OP(psignb),
3057 [0x09] = SSSE3_OP(psignw),
3058 [0x0a] = SSSE3_OP(psignd),
3059 [0x0b] = SSSE3_OP(pmulhrsw),
3060 [0x10] = SSE41_OP(pblendvb),
3061 [0x14] = SSE41_OP(blendvps),
3062 [0x15] = SSE41_OP(blendvpd),
3063 [0x17] = SSE41_OP(ptest),
3064 [0x1c] = SSSE3_OP(pabsb),
3065 [0x1d] = SSSE3_OP(pabsw),
3066 [0x1e] = SSSE3_OP(pabsd),
3067 [0x20] = SSE41_OP(pmovsxbw),
3068 [0x21] = SSE41_OP(pmovsxbd),
3069 [0x22] = SSE41_OP(pmovsxbq),
3070 [0x23] = SSE41_OP(pmovsxwd),
3071 [0x24] = SSE41_OP(pmovsxwq),
3072 [0x25] = SSE41_OP(pmovsxdq),
3073 [0x28] = SSE41_OP(pmuldq),
3074 [0x29] = SSE41_OP(pcmpeqq),
3075 [0x2a] = SSE41_SPECIAL, /* movntqda */
3076 [0x2b] = SSE41_OP(packusdw),
3077 [0x30] = SSE41_OP(pmovzxbw),
3078 [0x31] = SSE41_OP(pmovzxbd),
3079 [0x32] = SSE41_OP(pmovzxbq),
3080 [0x33] = SSE41_OP(pmovzxwd),
3081 [0x34] = SSE41_OP(pmovzxwq),
3082 [0x35] = SSE41_OP(pmovzxdq),
3083 [0x37] = SSE42_OP(pcmpgtq),
3084 [0x38] = SSE41_OP(pminsb),
3085 [0x39] = SSE41_OP(pminsd),
3086 [0x3a] = SSE41_OP(pminuw),
3087 [0x3b] = SSE41_OP(pminud),
3088 [0x3c] = SSE41_OP(pmaxsb),
3089 [0x3d] = SSE41_OP(pmaxsd),
3090 [0x3e] = SSE41_OP(pmaxuw),
3091 [0x3f] = SSE41_OP(pmaxud),
3092 [0x40] = SSE41_OP(pmulld),
3093 [0x41] = SSE41_OP(phminposuw),
3094 [0xdb] = AESNI_OP(aesimc),
3095 [0xdc] = AESNI_OP(aesenc),
3096 [0xdd] = AESNI_OP(aesenclast),
3097 [0xde] = AESNI_OP(aesdec),
3098 [0xdf] = AESNI_OP(aesdeclast),
3101 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
3102 [0x08] = SSE41_OP(roundps),
3103 [0x09] = SSE41_OP(roundpd),
3104 [0x0a] = SSE41_OP(roundss),
3105 [0x0b] = SSE41_OP(roundsd),
3106 [0x0c] = SSE41_OP(blendps),
3107 [0x0d] = SSE41_OP(blendpd),
3108 [0x0e] = SSE41_OP(pblendw),
3109 [0x0f] = SSSE3_OP(palignr),
3110 [0x14] = SSE41_SPECIAL, /* pextrb */
3111 [0x15] = SSE41_SPECIAL, /* pextrw */
3112 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3113 [0x17] = SSE41_SPECIAL, /* extractps */
3114 [0x20] = SSE41_SPECIAL, /* pinsrb */
3115 [0x21] = SSE41_SPECIAL, /* insertps */
3116 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3117 [0x40] = SSE41_OP(dpps),
3118 [0x41] = SSE41_OP(dppd),
3119 [0x42] = SSE41_OP(mpsadbw),
3120 [0x44] = PCLMULQDQ_OP(pclmulqdq),
3121 [0x60] = SSE42_OP(pcmpestrm),
3122 [0x61] = SSE42_OP(pcmpestri),
3123 [0x62] = SSE42_OP(pcmpistrm),
3124 [0x63] = SSE42_OP(pcmpistri),
3125 [0xdf] = AESNI_OP(aeskeygenassist),
3128 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3129 target_ulong pc_start)
3131 int b1, op1_offset, op2_offset, is_xmm, val;
3132 int modrm, mod, rm, reg;
3133 SSEFunc_0_epp sse_fn_epp;
3134 SSEFunc_0_eppi sse_fn_eppi;
3135 SSEFunc_0_ppi sse_fn_ppi;
3136 SSEFunc_0_eppt sse_fn_eppt;
3137 MemOp ot;
3139 b &= 0xff;
3140 if (s->prefix & PREFIX_DATA)
3141 b1 = 1;
3142 else if (s->prefix & PREFIX_REPZ)
3143 b1 = 2;
3144 else if (s->prefix & PREFIX_REPNZ)
3145 b1 = 3;
3146 else
3147 b1 = 0;
3148 sse_fn_epp = sse_op_table1[b][b1];
3149 if (!sse_fn_epp) {
3150 goto unknown_op;
3152 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3153 is_xmm = 1;
3154 } else {
3155 if (b1 == 0) {
3156 /* MMX case */
3157 is_xmm = 0;
3158 } else {
3159 is_xmm = 1;
3162 /* simple MMX/SSE operation */
3163 if (s->flags & HF_TS_MASK) {
3164 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3165 return;
3167 if (s->flags & HF_EM_MASK) {
3168 illegal_op:
3169 gen_illegal_opcode(s);
3170 return;
3172 if (is_xmm
3173 && !(s->flags & HF_OSFXSR_MASK)
3174 && (b != 0x38 && b != 0x3a)) {
3175 goto unknown_op;
3177 if (b == 0x0e) {
3178 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3179 /* If we were fully decoding this we might use illegal_op. */
3180 goto unknown_op;
3182 /* femms */
3183 gen_helper_emms(cpu_env);
3184 return;
3186 if (b == 0x77) {
3187 /* emms */
3188 gen_helper_emms(cpu_env);
3189 return;
3191 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3192 the static cpu state) */
3193 if (!is_xmm) {
3194 gen_helper_enter_mmx(cpu_env);
3197 modrm = x86_ldub_code(env, s);
3198 reg = ((modrm >> 3) & 7);
3199 if (is_xmm) {
3200 reg |= REX_R(s);
3202 mod = (modrm >> 6) & 3;
3203 if (sse_fn_epp == SSE_SPECIAL) {
3204 b |= (b1 << 8);
3205 switch(b) {
3206 case 0x0e7: /* movntq */
3207 if (mod == 3) {
3208 goto illegal_op;
3210 gen_lea_modrm(env, s, modrm);
3211 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3212 break;
3213 case 0x1e7: /* movntdq */
3214 case 0x02b: /* movntps */
3215 case 0x12b: /* movntps */
3216 if (mod == 3)
3217 goto illegal_op;
3218 gen_lea_modrm(env, s, modrm);
3219 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3220 break;
3221 case 0x3f0: /* lddqu */
3222 if (mod == 3)
3223 goto illegal_op;
3224 gen_lea_modrm(env, s, modrm);
3225 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3226 break;
3227 case 0x22b: /* movntss */
3228 case 0x32b: /* movntsd */
3229 if (mod == 3)
3230 goto illegal_op;
3231 gen_lea_modrm(env, s, modrm);
3232 if (b1 & 1) {
3233 gen_stq_env_A0(s, offsetof(CPUX86State,
3234 xmm_regs[reg].ZMM_Q(0)));
3235 } else {
3236 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
3237 xmm_regs[reg].ZMM_L(0)));
3238 gen_op_st_v(s, MO_32, s->T0, s->A0);
3240 break;
3241 case 0x6e: /* movd mm, ea */
3242 #ifdef TARGET_X86_64
3243 if (s->dflag == MO_64) {
3244 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3245 tcg_gen_st_tl(s->T0, cpu_env,
3246 offsetof(CPUX86State, fpregs[reg].mmx));
3247 } else
3248 #endif
3250 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3251 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3252 offsetof(CPUX86State,fpregs[reg].mmx));
3253 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3254 gen_helper_movl_mm_T0_mmx(s->ptr0, s->tmp2_i32);
3256 break;
3257 case 0x16e: /* movd xmm, ea */
3258 #ifdef TARGET_X86_64
3259 if (s->dflag == MO_64) {
3260 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3261 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3262 offsetof(CPUX86State,xmm_regs[reg]));
3263 gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0);
3264 } else
3265 #endif
3267 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3268 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3269 offsetof(CPUX86State,xmm_regs[reg]));
3270 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3271 gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32);
3273 break;
3274 case 0x6f: /* movq mm, ea */
3275 if (mod != 3) {
3276 gen_lea_modrm(env, s, modrm);
3277 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3278 } else {
3279 rm = (modrm & 7);
3280 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
3281 offsetof(CPUX86State,fpregs[rm].mmx));
3282 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
3283 offsetof(CPUX86State,fpregs[reg].mmx));
3285 break;
3286 case 0x010: /* movups */
3287 case 0x110: /* movupd */
3288 case 0x028: /* movaps */
3289 case 0x128: /* movapd */
3290 case 0x16f: /* movdqa xmm, ea */
3291 case 0x26f: /* movdqu xmm, ea */
3292 if (mod != 3) {
3293 gen_lea_modrm(env, s, modrm);
3294 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3295 } else {
3296 rm = (modrm & 7) | REX_B(s);
3297 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[reg]),
3298 offsetof(CPUX86State,xmm_regs[rm]));
3300 break;
3301 case 0x210: /* movss xmm, ea */
3302 if (mod != 3) {
3303 gen_lea_modrm(env, s, modrm);
3304 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3305 tcg_gen_st32_tl(s->T0, cpu_env,
3306 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3307 tcg_gen_movi_tl(s->T0, 0);
3308 tcg_gen_st32_tl(s->T0, cpu_env,
3309 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)));
3310 tcg_gen_st32_tl(s->T0, cpu_env,
3311 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3312 tcg_gen_st32_tl(s->T0, cpu_env,
3313 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3314 } else {
3315 rm = (modrm & 7) | REX_B(s);
3316 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3317 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3319 break;
3320 case 0x310: /* movsd xmm, ea */
3321 if (mod != 3) {
3322 gen_lea_modrm(env, s, modrm);
3323 gen_ldq_env_A0(s, offsetof(CPUX86State,
3324 xmm_regs[reg].ZMM_Q(0)));
3325 tcg_gen_movi_tl(s->T0, 0);
3326 tcg_gen_st32_tl(s->T0, cpu_env,
3327 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3328 tcg_gen_st32_tl(s->T0, cpu_env,
3329 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3330 } else {
3331 rm = (modrm & 7) | REX_B(s);
3332 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3333 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3335 break;
3336 case 0x012: /* movlps */
3337 case 0x112: /* movlpd */
3338 if (mod != 3) {
3339 gen_lea_modrm(env, s, modrm);
3340 gen_ldq_env_A0(s, offsetof(CPUX86State,
3341 xmm_regs[reg].ZMM_Q(0)));
3342 } else {
3343 /* movhlps */
3344 rm = (modrm & 7) | REX_B(s);
3345 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3346 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3348 break;
3349 case 0x212: /* movsldup */
3350 if (mod != 3) {
3351 gen_lea_modrm(env, s, modrm);
3352 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3353 } else {
3354 rm = (modrm & 7) | REX_B(s);
3355 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3356 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3357 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3358 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3360 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3361 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3362 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3363 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3364 break;
3365 case 0x312: /* movddup */
3366 if (mod != 3) {
3367 gen_lea_modrm(env, s, modrm);
3368 gen_ldq_env_A0(s, offsetof(CPUX86State,
3369 xmm_regs[reg].ZMM_Q(0)));
3370 } else {
3371 rm = (modrm & 7) | REX_B(s);
3372 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3373 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3375 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3376 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3377 break;
3378 case 0x016: /* movhps */
3379 case 0x116: /* movhpd */
3380 if (mod != 3) {
3381 gen_lea_modrm(env, s, modrm);
3382 gen_ldq_env_A0(s, offsetof(CPUX86State,
3383 xmm_regs[reg].ZMM_Q(1)));
3384 } else {
3385 /* movlhps */
3386 rm = (modrm & 7) | REX_B(s);
3387 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3388 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3390 break;
3391 case 0x216: /* movshdup */
3392 if (mod != 3) {
3393 gen_lea_modrm(env, s, modrm);
3394 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3395 } else {
3396 rm = (modrm & 7) | REX_B(s);
3397 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3398 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3399 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3400 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3402 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3403 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3404 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3405 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3406 break;
3407 case 0x178:
3408 case 0x378:
3410 int bit_index, field_length;
3412 if (b1 == 1 && reg != 0)
3413 goto illegal_op;
3414 field_length = x86_ldub_code(env, s) & 0x3F;
3415 bit_index = x86_ldub_code(env, s) & 0x3F;
3416 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3417 offsetof(CPUX86State,xmm_regs[reg]));
3418 if (b1 == 1)
3419 gen_helper_extrq_i(cpu_env, s->ptr0,
3420 tcg_const_i32(bit_index),
3421 tcg_const_i32(field_length));
3422 else
3423 gen_helper_insertq_i(cpu_env, s->ptr0,
3424 tcg_const_i32(bit_index),
3425 tcg_const_i32(field_length));
3427 break;
3428 case 0x7e: /* movd ea, mm */
3429 #ifdef TARGET_X86_64
3430 if (s->dflag == MO_64) {
3431 tcg_gen_ld_i64(s->T0, cpu_env,
3432 offsetof(CPUX86State,fpregs[reg].mmx));
3433 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3434 } else
3435 #endif
3437 tcg_gen_ld32u_tl(s->T0, cpu_env,
3438 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3439 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3441 break;
3442 case 0x17e: /* movd ea, xmm */
3443 #ifdef TARGET_X86_64
3444 if (s->dflag == MO_64) {
3445 tcg_gen_ld_i64(s->T0, cpu_env,
3446 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3447 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3448 } else
3449 #endif
3451 tcg_gen_ld32u_tl(s->T0, cpu_env,
3452 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3453 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3455 break;
3456 case 0x27e: /* movq xmm, ea */
3457 if (mod != 3) {
3458 gen_lea_modrm(env, s, modrm);
3459 gen_ldq_env_A0(s, offsetof(CPUX86State,
3460 xmm_regs[reg].ZMM_Q(0)));
3461 } else {
3462 rm = (modrm & 7) | REX_B(s);
3463 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3464 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3466 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3467 break;
3468 case 0x7f: /* movq ea, mm */
3469 if (mod != 3) {
3470 gen_lea_modrm(env, s, modrm);
3471 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3472 } else {
3473 rm = (modrm & 7);
3474 gen_op_movq(s, offsetof(CPUX86State, fpregs[rm].mmx),
3475 offsetof(CPUX86State,fpregs[reg].mmx));
3477 break;
3478 case 0x011: /* movups */
3479 case 0x111: /* movupd */
3480 case 0x029: /* movaps */
3481 case 0x129: /* movapd */
3482 case 0x17f: /* movdqa ea, xmm */
3483 case 0x27f: /* movdqu ea, xmm */
3484 if (mod != 3) {
3485 gen_lea_modrm(env, s, modrm);
3486 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3487 } else {
3488 rm = (modrm & 7) | REX_B(s);
3489 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[rm]),
3490 offsetof(CPUX86State,xmm_regs[reg]));
3492 break;
3493 case 0x211: /* movss ea, xmm */
3494 if (mod != 3) {
3495 gen_lea_modrm(env, s, modrm);
3496 tcg_gen_ld32u_tl(s->T0, cpu_env,
3497 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3498 gen_op_st_v(s, MO_32, s->T0, s->A0);
3499 } else {
3500 rm = (modrm & 7) | REX_B(s);
3501 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0)),
3502 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3504 break;
3505 case 0x311: /* movsd ea, xmm */
3506 if (mod != 3) {
3507 gen_lea_modrm(env, s, modrm);
3508 gen_stq_env_A0(s, offsetof(CPUX86State,
3509 xmm_regs[reg].ZMM_Q(0)));
3510 } else {
3511 rm = (modrm & 7) | REX_B(s);
3512 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3513 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3515 break;
3516 case 0x013: /* movlps */
3517 case 0x113: /* movlpd */
3518 if (mod != 3) {
3519 gen_lea_modrm(env, s, modrm);
3520 gen_stq_env_A0(s, offsetof(CPUX86State,
3521 xmm_regs[reg].ZMM_Q(0)));
3522 } else {
3523 goto illegal_op;
3525 break;
3526 case 0x017: /* movhps */
3527 case 0x117: /* movhpd */
3528 if (mod != 3) {
3529 gen_lea_modrm(env, s, modrm);
3530 gen_stq_env_A0(s, offsetof(CPUX86State,
3531 xmm_regs[reg].ZMM_Q(1)));
3532 } else {
3533 goto illegal_op;
3535 break;
3536 case 0x71: /* shift mm, im */
3537 case 0x72:
3538 case 0x73:
3539 case 0x171: /* shift xmm, im */
3540 case 0x172:
3541 case 0x173:
3542 if (b1 >= 2) {
3543 goto unknown_op;
3545 val = x86_ldub_code(env, s);
3546 if (is_xmm) {
3547 tcg_gen_movi_tl(s->T0, val);
3548 tcg_gen_st32_tl(s->T0, cpu_env,
3549 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3550 tcg_gen_movi_tl(s->T0, 0);
3551 tcg_gen_st32_tl(s->T0, cpu_env,
3552 offsetof(CPUX86State, xmm_t0.ZMM_L(1)));
3553 op1_offset = offsetof(CPUX86State,xmm_t0);
3554 } else {
3555 tcg_gen_movi_tl(s->T0, val);
3556 tcg_gen_st32_tl(s->T0, cpu_env,
3557 offsetof(CPUX86State, mmx_t0.MMX_L(0)));
3558 tcg_gen_movi_tl(s->T0, 0);
3559 tcg_gen_st32_tl(s->T0, cpu_env,
3560 offsetof(CPUX86State, mmx_t0.MMX_L(1)));
3561 op1_offset = offsetof(CPUX86State,mmx_t0);
3563 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3564 (((modrm >> 3)) & 7)][b1];
3565 if (!sse_fn_epp) {
3566 goto unknown_op;
3568 if (is_xmm) {
3569 rm = (modrm & 7) | REX_B(s);
3570 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3571 } else {
3572 rm = (modrm & 7);
3573 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3575 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3576 tcg_gen_addi_ptr(s->ptr1, cpu_env, op1_offset);
3577 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3578 break;
3579 case 0x050: /* movmskps */
3580 rm = (modrm & 7) | REX_B(s);
3581 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3582 offsetof(CPUX86State,xmm_regs[rm]));
3583 gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0);
3584 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3585 break;
3586 case 0x150: /* movmskpd */
3587 rm = (modrm & 7) | REX_B(s);
3588 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3589 offsetof(CPUX86State,xmm_regs[rm]));
3590 gen_helper_movmskpd(s->tmp2_i32, cpu_env, s->ptr0);
3591 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3592 break;
3593 case 0x02a: /* cvtpi2ps */
3594 case 0x12a: /* cvtpi2pd */
3595 gen_helper_enter_mmx(cpu_env);
3596 if (mod != 3) {
3597 gen_lea_modrm(env, s, modrm);
3598 op2_offset = offsetof(CPUX86State,mmx_t0);
3599 gen_ldq_env_A0(s, op2_offset);
3600 } else {
3601 rm = (modrm & 7);
3602 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3604 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3605 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3606 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3607 switch(b >> 8) {
3608 case 0x0:
3609 gen_helper_cvtpi2ps(cpu_env, s->ptr0, s->ptr1);
3610 break;
3611 default:
3612 case 0x1:
3613 gen_helper_cvtpi2pd(cpu_env, s->ptr0, s->ptr1);
3614 break;
3616 break;
3617 case 0x22a: /* cvtsi2ss */
3618 case 0x32a: /* cvtsi2sd */
3619 ot = mo_64_32(s->dflag);
3620 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3621 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3622 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3623 if (ot == MO_32) {
3624 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3625 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3626 sse_fn_epi(cpu_env, s->ptr0, s->tmp2_i32);
3627 } else {
3628 #ifdef TARGET_X86_64
3629 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3630 sse_fn_epl(cpu_env, s->ptr0, s->T0);
3631 #else
3632 goto illegal_op;
3633 #endif
3635 break;
3636 case 0x02c: /* cvttps2pi */
3637 case 0x12c: /* cvttpd2pi */
3638 case 0x02d: /* cvtps2pi */
3639 case 0x12d: /* cvtpd2pi */
3640 gen_helper_enter_mmx(cpu_env);
3641 if (mod != 3) {
3642 gen_lea_modrm(env, s, modrm);
3643 op2_offset = offsetof(CPUX86State,xmm_t0);
3644 gen_ldo_env_A0(s, op2_offset);
3645 } else {
3646 rm = (modrm & 7) | REX_B(s);
3647 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3649 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3650 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3651 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3652 switch(b) {
3653 case 0x02c:
3654 gen_helper_cvttps2pi(cpu_env, s->ptr0, s->ptr1);
3655 break;
3656 case 0x12c:
3657 gen_helper_cvttpd2pi(cpu_env, s->ptr0, s->ptr1);
3658 break;
3659 case 0x02d:
3660 gen_helper_cvtps2pi(cpu_env, s->ptr0, s->ptr1);
3661 break;
3662 case 0x12d:
3663 gen_helper_cvtpd2pi(cpu_env, s->ptr0, s->ptr1);
3664 break;
3666 break;
3667 case 0x22c: /* cvttss2si */
3668 case 0x32c: /* cvttsd2si */
3669 case 0x22d: /* cvtss2si */
3670 case 0x32d: /* cvtsd2si */
3671 ot = mo_64_32(s->dflag);
3672 if (mod != 3) {
3673 gen_lea_modrm(env, s, modrm);
3674 if ((b >> 8) & 1) {
3675 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3676 } else {
3677 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3678 tcg_gen_st32_tl(s->T0, cpu_env,
3679 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3681 op2_offset = offsetof(CPUX86State,xmm_t0);
3682 } else {
3683 rm = (modrm & 7) | REX_B(s);
3684 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3686 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3687 if (ot == MO_32) {
3688 SSEFunc_i_ep sse_fn_i_ep =
3689 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3690 sse_fn_i_ep(s->tmp2_i32, cpu_env, s->ptr0);
3691 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
3692 } else {
3693 #ifdef TARGET_X86_64
3694 SSEFunc_l_ep sse_fn_l_ep =
3695 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3696 sse_fn_l_ep(s->T0, cpu_env, s->ptr0);
3697 #else
3698 goto illegal_op;
3699 #endif
3701 gen_op_mov_reg_v(s, ot, reg, s->T0);
3702 break;
3703 case 0xc4: /* pinsrw */
3704 case 0x1c4:
3705 s->rip_offset = 1;
3706 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3707 val = x86_ldub_code(env, s);
3708 if (b1) {
3709 val &= 7;
3710 tcg_gen_st16_tl(s->T0, cpu_env,
3711 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3712 } else {
3713 val &= 3;
3714 tcg_gen_st16_tl(s->T0, cpu_env,
3715 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3717 break;
3718 case 0xc5: /* pextrw */
3719 case 0x1c5:
3720 if (mod != 3)
3721 goto illegal_op;
3722 ot = mo_64_32(s->dflag);
3723 val = x86_ldub_code(env, s);
3724 if (b1) {
3725 val &= 7;
3726 rm = (modrm & 7) | REX_B(s);
3727 tcg_gen_ld16u_tl(s->T0, cpu_env,
3728 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3729 } else {
3730 val &= 3;
3731 rm = (modrm & 7);
3732 tcg_gen_ld16u_tl(s->T0, cpu_env,
3733 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3735 reg = ((modrm >> 3) & 7) | REX_R(s);
3736 gen_op_mov_reg_v(s, ot, reg, s->T0);
3737 break;
3738 case 0x1d6: /* movq ea, xmm */
3739 if (mod != 3) {
3740 gen_lea_modrm(env, s, modrm);
3741 gen_stq_env_A0(s, offsetof(CPUX86State,
3742 xmm_regs[reg].ZMM_Q(0)));
3743 } else {
3744 rm = (modrm & 7) | REX_B(s);
3745 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3746 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3747 gen_op_movq_env_0(s,
3748 offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(1)));
3750 break;
3751 case 0x2d6: /* movq2dq */
3752 gen_helper_enter_mmx(cpu_env);
3753 rm = (modrm & 7);
3754 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3755 offsetof(CPUX86State,fpregs[rm].mmx));
3756 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3757 break;
3758 case 0x3d6: /* movdq2q */
3759 gen_helper_enter_mmx(cpu_env);
3760 rm = (modrm & 7) | REX_B(s);
3761 gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx),
3762 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3763 break;
3764 case 0xd7: /* pmovmskb */
3765 case 0x1d7:
3766 if (mod != 3)
3767 goto illegal_op;
3768 if (b1) {
3769 rm = (modrm & 7) | REX_B(s);
3770 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3771 offsetof(CPUX86State, xmm_regs[rm]));
3772 gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0);
3773 } else {
3774 rm = (modrm & 7);
3775 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3776 offsetof(CPUX86State, fpregs[rm].mmx));
3777 gen_helper_pmovmskb_mmx(s->tmp2_i32, cpu_env, s->ptr0);
3779 reg = ((modrm >> 3) & 7) | REX_R(s);
3780 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3781 break;
3783 case 0x138:
3784 case 0x038:
3785 b = modrm;
3786 if ((b & 0xf0) == 0xf0) {
3787 goto do_0f_38_fx;
3789 modrm = x86_ldub_code(env, s);
3790 rm = modrm & 7;
3791 reg = ((modrm >> 3) & 7) | REX_R(s);
3792 mod = (modrm >> 6) & 3;
3793 if (b1 >= 2) {
3794 goto unknown_op;
3797 sse_fn_epp = sse_op_table6[b].op[b1];
3798 if (!sse_fn_epp) {
3799 goto unknown_op;
3801 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3802 goto illegal_op;
3804 if (b1) {
3805 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3806 if (mod == 3) {
3807 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3808 } else {
3809 op2_offset = offsetof(CPUX86State,xmm_t0);
3810 gen_lea_modrm(env, s, modrm);
3811 switch (b) {
3812 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3813 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3814 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3815 gen_ldq_env_A0(s, op2_offset +
3816 offsetof(ZMMReg, ZMM_Q(0)));
3817 break;
3818 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3819 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3820 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
3821 s->mem_index, MO_LEUL);
3822 tcg_gen_st_i32(s->tmp2_i32, cpu_env, op2_offset +
3823 offsetof(ZMMReg, ZMM_L(0)));
3824 break;
3825 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3826 tcg_gen_qemu_ld_tl(s->tmp0, s->A0,
3827 s->mem_index, MO_LEUW);
3828 tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset +
3829 offsetof(ZMMReg, ZMM_W(0)));
3830 break;
3831 case 0x2a: /* movntqda */
3832 gen_ldo_env_A0(s, op1_offset);
3833 return;
3834 default:
3835 gen_ldo_env_A0(s, op2_offset);
3838 } else {
3839 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3840 if (mod == 3) {
3841 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3842 } else {
3843 op2_offset = offsetof(CPUX86State,mmx_t0);
3844 gen_lea_modrm(env, s, modrm);
3845 gen_ldq_env_A0(s, op2_offset);
3848 if (sse_fn_epp == SSE_SPECIAL) {
3849 goto unknown_op;
3852 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3853 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3854 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3856 if (b == 0x17) {
3857 set_cc_op(s, CC_OP_EFLAGS);
3859 break;
3861 case 0x238:
3862 case 0x338:
3863 do_0f_38_fx:
3864 /* Various integer extensions at 0f 38 f[0-f]. */
3865 b = modrm | (b1 << 8);
3866 modrm = x86_ldub_code(env, s);
3867 reg = ((modrm >> 3) & 7) | REX_R(s);
3869 switch (b) {
3870 case 0x3f0: /* crc32 Gd,Eb */
3871 case 0x3f1: /* crc32 Gd,Ey */
3872 do_crc32:
3873 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3874 goto illegal_op;
3876 if ((b & 0xff) == 0xf0) {
3877 ot = MO_8;
3878 } else if (s->dflag != MO_64) {
3879 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3880 } else {
3881 ot = MO_64;
3884 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[reg]);
3885 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3886 gen_helper_crc32(s->T0, s->tmp2_i32,
3887 s->T0, tcg_const_i32(8 << ot));
3889 ot = mo_64_32(s->dflag);
3890 gen_op_mov_reg_v(s, ot, reg, s->T0);
3891 break;
3893 case 0x1f0: /* crc32 or movbe */
3894 case 0x1f1:
3895 /* For these insns, the f3 prefix is supposed to have priority
3896 over the 66 prefix, but that's not what we implement above
3897 setting b1. */
3898 if (s->prefix & PREFIX_REPNZ) {
3899 goto do_crc32;
3901 /* FALLTHRU */
3902 case 0x0f0: /* movbe Gy,My */
3903 case 0x0f1: /* movbe My,Gy */
3904 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3905 goto illegal_op;
3907 if (s->dflag != MO_64) {
3908 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3909 } else {
3910 ot = MO_64;
3913 gen_lea_modrm(env, s, modrm);
3914 if ((b & 1) == 0) {
3915 tcg_gen_qemu_ld_tl(s->T0, s->A0,
3916 s->mem_index, ot | MO_BE);
3917 gen_op_mov_reg_v(s, ot, reg, s->T0);
3918 } else {
3919 tcg_gen_qemu_st_tl(cpu_regs[reg], s->A0,
3920 s->mem_index, ot | MO_BE);
3922 break;
3924 case 0x0f2: /* andn Gy, By, Ey */
3925 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3926 || !(s->prefix & PREFIX_VEX)
3927 || s->vex_l != 0) {
3928 goto illegal_op;
3930 ot = mo_64_32(s->dflag);
3931 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3932 tcg_gen_andc_tl(s->T0, s->T0, cpu_regs[s->vex_v]);
3933 gen_op_mov_reg_v(s, ot, reg, s->T0);
3934 gen_op_update1_cc(s);
3935 set_cc_op(s, CC_OP_LOGICB + ot);
3936 break;
3938 case 0x0f7: /* bextr Gy, Ey, By */
3939 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3940 || !(s->prefix & PREFIX_VEX)
3941 || s->vex_l != 0) {
3942 goto illegal_op;
3944 ot = mo_64_32(s->dflag);
3946 TCGv bound, zero;
3948 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3949 /* Extract START, and shift the operand.
3950 Shifts larger than operand size get zeros. */
3951 tcg_gen_ext8u_tl(s->A0, cpu_regs[s->vex_v]);
3952 tcg_gen_shr_tl(s->T0, s->T0, s->A0);
3954 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3955 zero = tcg_const_tl(0);
3956 tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound,
3957 s->T0, zero);
3958 tcg_temp_free(zero);
3960 /* Extract the LEN into a mask. Lengths larger than
3961 operand size get all ones. */
3962 tcg_gen_extract_tl(s->A0, cpu_regs[s->vex_v], 8, 8);
3963 tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound,
3964 s->A0, bound);
3965 tcg_temp_free(bound);
3966 tcg_gen_movi_tl(s->T1, 1);
3967 tcg_gen_shl_tl(s->T1, s->T1, s->A0);
3968 tcg_gen_subi_tl(s->T1, s->T1, 1);
3969 tcg_gen_and_tl(s->T0, s->T0, s->T1);
3971 gen_op_mov_reg_v(s, ot, reg, s->T0);
3972 gen_op_update1_cc(s);
3973 set_cc_op(s, CC_OP_LOGICB + ot);
3975 break;
3977 case 0x0f5: /* bzhi Gy, Ey, By */
3978 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3979 || !(s->prefix & PREFIX_VEX)
3980 || s->vex_l != 0) {
3981 goto illegal_op;
3983 ot = mo_64_32(s->dflag);
3984 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3985 tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]);
3987 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3988 /* Note that since we're using BMILG (in order to get O
3989 cleared) we need to store the inverse into C. */
3990 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3991 s->T1, bound);
3992 tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1,
3993 bound, bound, s->T1);
3994 tcg_temp_free(bound);
3996 tcg_gen_movi_tl(s->A0, -1);
3997 tcg_gen_shl_tl(s->A0, s->A0, s->T1);
3998 tcg_gen_andc_tl(s->T0, s->T0, s->A0);
3999 gen_op_mov_reg_v(s, ot, reg, s->T0);
4000 gen_op_update1_cc(s);
4001 set_cc_op(s, CC_OP_BMILGB + ot);
4002 break;
4004 case 0x3f6: /* mulx By, Gy, rdx, Ey */
4005 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4006 || !(s->prefix & PREFIX_VEX)
4007 || s->vex_l != 0) {
4008 goto illegal_op;
4010 ot = mo_64_32(s->dflag);
4011 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4012 switch (ot) {
4013 default:
4014 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4015 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EDX]);
4016 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
4017 s->tmp2_i32, s->tmp3_i32);
4018 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32);
4019 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp3_i32);
4020 break;
4021 #ifdef TARGET_X86_64
4022 case MO_64:
4023 tcg_gen_mulu2_i64(s->T0, s->T1,
4024 s->T0, cpu_regs[R_EDX]);
4025 tcg_gen_mov_i64(cpu_regs[s->vex_v], s->T0);
4026 tcg_gen_mov_i64(cpu_regs[reg], s->T1);
4027 break;
4028 #endif
4030 break;
4032 case 0x3f5: /* pdep Gy, By, Ey */
4033 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4034 || !(s->prefix & PREFIX_VEX)
4035 || s->vex_l != 0) {
4036 goto illegal_op;
4038 ot = mo_64_32(s->dflag);
4039 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4040 /* Note that by zero-extending the source operand, we
4041 automatically handle zero-extending the result. */
4042 if (ot == MO_64) {
4043 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
4044 } else {
4045 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
4047 gen_helper_pdep(cpu_regs[reg], s->T1, s->T0);
4048 break;
4050 case 0x2f5: /* pext Gy, By, Ey */
4051 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4052 || !(s->prefix & PREFIX_VEX)
4053 || s->vex_l != 0) {
4054 goto illegal_op;
4056 ot = mo_64_32(s->dflag);
4057 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4058 /* Note that by zero-extending the source operand, we
4059 automatically handle zero-extending the result. */
4060 if (ot == MO_64) {
4061 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
4062 } else {
4063 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
4065 gen_helper_pext(cpu_regs[reg], s->T1, s->T0);
4066 break;
4068 case 0x1f6: /* adcx Gy, Ey */
4069 case 0x2f6: /* adox Gy, Ey */
4070 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
4071 goto illegal_op;
4072 } else {
4073 TCGv carry_in, carry_out, zero;
4074 int end_op;
4076 ot = mo_64_32(s->dflag);
4077 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4079 /* Re-use the carry-out from a previous round. */
4080 carry_in = NULL;
4081 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
4082 switch (s->cc_op) {
4083 case CC_OP_ADCX:
4084 if (b == 0x1f6) {
4085 carry_in = cpu_cc_dst;
4086 end_op = CC_OP_ADCX;
4087 } else {
4088 end_op = CC_OP_ADCOX;
4090 break;
4091 case CC_OP_ADOX:
4092 if (b == 0x1f6) {
4093 end_op = CC_OP_ADCOX;
4094 } else {
4095 carry_in = cpu_cc_src2;
4096 end_op = CC_OP_ADOX;
4098 break;
4099 case CC_OP_ADCOX:
4100 end_op = CC_OP_ADCOX;
4101 carry_in = carry_out;
4102 break;
4103 default:
4104 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
4105 break;
4107 /* If we can't reuse carry-out, get it out of EFLAGS. */
4108 if (!carry_in) {
4109 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4110 gen_compute_eflags(s);
4112 carry_in = s->tmp0;
4113 tcg_gen_extract_tl(carry_in, cpu_cc_src,
4114 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
4117 switch (ot) {
4118 #ifdef TARGET_X86_64
4119 case MO_32:
4120 /* If we know TL is 64-bit, and we want a 32-bit
4121 result, just do everything in 64-bit arithmetic. */
4122 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4123 tcg_gen_ext32u_i64(s->T0, s->T0);
4124 tcg_gen_add_i64(s->T0, s->T0, cpu_regs[reg]);
4125 tcg_gen_add_i64(s->T0, s->T0, carry_in);
4126 tcg_gen_ext32u_i64(cpu_regs[reg], s->T0);
4127 tcg_gen_shri_i64(carry_out, s->T0, 32);
4128 break;
4129 #endif
4130 default:
4131 /* Otherwise compute the carry-out in two steps. */
4132 zero = tcg_const_tl(0);
4133 tcg_gen_add2_tl(s->T0, carry_out,
4134 s->T0, zero,
4135 carry_in, zero);
4136 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4137 cpu_regs[reg], carry_out,
4138 s->T0, zero);
4139 tcg_temp_free(zero);
4140 break;
4142 set_cc_op(s, end_op);
4144 break;
4146 case 0x1f7: /* shlx Gy, Ey, By */
4147 case 0x2f7: /* sarx Gy, Ey, By */
4148 case 0x3f7: /* shrx Gy, Ey, By */
4149 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4150 || !(s->prefix & PREFIX_VEX)
4151 || s->vex_l != 0) {
4152 goto illegal_op;
4154 ot = mo_64_32(s->dflag);
4155 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4156 if (ot == MO_64) {
4157 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 63);
4158 } else {
4159 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 31);
4161 if (b == 0x1f7) {
4162 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
4163 } else if (b == 0x2f7) {
4164 if (ot != MO_64) {
4165 tcg_gen_ext32s_tl(s->T0, s->T0);
4167 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
4168 } else {
4169 if (ot != MO_64) {
4170 tcg_gen_ext32u_tl(s->T0, s->T0);
4172 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
4174 gen_op_mov_reg_v(s, ot, reg, s->T0);
4175 break;
4177 case 0x0f3:
4178 case 0x1f3:
4179 case 0x2f3:
4180 case 0x3f3: /* Group 17 */
4181 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4182 || !(s->prefix & PREFIX_VEX)
4183 || s->vex_l != 0) {
4184 goto illegal_op;
4186 ot = mo_64_32(s->dflag);
4187 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4189 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4190 switch (reg & 7) {
4191 case 1: /* blsr By,Ey */
4192 tcg_gen_subi_tl(s->T1, s->T0, 1);
4193 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4194 break;
4195 case 2: /* blsmsk By,Ey */
4196 tcg_gen_subi_tl(s->T1, s->T0, 1);
4197 tcg_gen_xor_tl(s->T0, s->T0, s->T1);
4198 break;
4199 case 3: /* blsi By, Ey */
4200 tcg_gen_neg_tl(s->T1, s->T0);
4201 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4202 break;
4203 default:
4204 goto unknown_op;
4206 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4207 gen_op_mov_reg_v(s, ot, s->vex_v, s->T0);
4208 set_cc_op(s, CC_OP_BMILGB + ot);
4209 break;
4211 default:
4212 goto unknown_op;
4214 break;
4216 case 0x03a:
4217 case 0x13a:
4218 b = modrm;
4219 modrm = x86_ldub_code(env, s);
4220 rm = modrm & 7;
4221 reg = ((modrm >> 3) & 7) | REX_R(s);
4222 mod = (modrm >> 6) & 3;
4223 if (b1 >= 2) {
4224 goto unknown_op;
4227 sse_fn_eppi = sse_op_table7[b].op[b1];
4228 if (!sse_fn_eppi) {
4229 goto unknown_op;
4231 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4232 goto illegal_op;
4234 s->rip_offset = 1;
4236 if (sse_fn_eppi == SSE_SPECIAL) {
4237 ot = mo_64_32(s->dflag);
4238 rm = (modrm & 7) | REX_B(s);
4239 if (mod != 3)
4240 gen_lea_modrm(env, s, modrm);
4241 reg = ((modrm >> 3) & 7) | REX_R(s);
4242 val = x86_ldub_code(env, s);
4243 switch (b) {
4244 case 0x14: /* pextrb */
4245 tcg_gen_ld8u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4246 xmm_regs[reg].ZMM_B(val & 15)));
4247 if (mod == 3) {
4248 gen_op_mov_reg_v(s, ot, rm, s->T0);
4249 } else {
4250 tcg_gen_qemu_st_tl(s->T0, s->A0,
4251 s->mem_index, MO_UB);
4253 break;
4254 case 0x15: /* pextrw */
4255 tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4256 xmm_regs[reg].ZMM_W(val & 7)));
4257 if (mod == 3) {
4258 gen_op_mov_reg_v(s, ot, rm, s->T0);
4259 } else {
4260 tcg_gen_qemu_st_tl(s->T0, s->A0,
4261 s->mem_index, MO_LEUW);
4263 break;
4264 case 0x16:
4265 if (ot == MO_32) { /* pextrd */
4266 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4267 offsetof(CPUX86State,
4268 xmm_regs[reg].ZMM_L(val & 3)));
4269 if (mod == 3) {
4270 tcg_gen_extu_i32_tl(cpu_regs[rm], s->tmp2_i32);
4271 } else {
4272 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4273 s->mem_index, MO_LEUL);
4275 } else { /* pextrq */
4276 #ifdef TARGET_X86_64
4277 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
4278 offsetof(CPUX86State,
4279 xmm_regs[reg].ZMM_Q(val & 1)));
4280 if (mod == 3) {
4281 tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64);
4282 } else {
4283 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4284 s->mem_index, MO_LEQ);
4286 #else
4287 goto illegal_op;
4288 #endif
4290 break;
4291 case 0x17: /* extractps */
4292 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4293 xmm_regs[reg].ZMM_L(val & 3)));
4294 if (mod == 3) {
4295 gen_op_mov_reg_v(s, ot, rm, s->T0);
4296 } else {
4297 tcg_gen_qemu_st_tl(s->T0, s->A0,
4298 s->mem_index, MO_LEUL);
4300 break;
4301 case 0x20: /* pinsrb */
4302 if (mod == 3) {
4303 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
4304 } else {
4305 tcg_gen_qemu_ld_tl(s->T0, s->A0,
4306 s->mem_index, MO_UB);
4308 tcg_gen_st8_tl(s->T0, cpu_env, offsetof(CPUX86State,
4309 xmm_regs[reg].ZMM_B(val & 15)));
4310 break;
4311 case 0x21: /* insertps */
4312 if (mod == 3) {
4313 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4314 offsetof(CPUX86State,xmm_regs[rm]
4315 .ZMM_L((val >> 6) & 3)));
4316 } else {
4317 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4318 s->mem_index, MO_LEUL);
4320 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4321 offsetof(CPUX86State,xmm_regs[reg]
4322 .ZMM_L((val >> 4) & 3)));
4323 if ((val >> 0) & 1)
4324 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4325 cpu_env, offsetof(CPUX86State,
4326 xmm_regs[reg].ZMM_L(0)));
4327 if ((val >> 1) & 1)
4328 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4329 cpu_env, offsetof(CPUX86State,
4330 xmm_regs[reg].ZMM_L(1)));
4331 if ((val >> 2) & 1)
4332 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4333 cpu_env, offsetof(CPUX86State,
4334 xmm_regs[reg].ZMM_L(2)));
4335 if ((val >> 3) & 1)
4336 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4337 cpu_env, offsetof(CPUX86State,
4338 xmm_regs[reg].ZMM_L(3)));
4339 break;
4340 case 0x22:
4341 if (ot == MO_32) { /* pinsrd */
4342 if (mod == 3) {
4343 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[rm]);
4344 } else {
4345 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4346 s->mem_index, MO_LEUL);
4348 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4349 offsetof(CPUX86State,
4350 xmm_regs[reg].ZMM_L(val & 3)));
4351 } else { /* pinsrq */
4352 #ifdef TARGET_X86_64
4353 if (mod == 3) {
4354 gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm);
4355 } else {
4356 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4357 s->mem_index, MO_LEQ);
4359 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
4360 offsetof(CPUX86State,
4361 xmm_regs[reg].ZMM_Q(val & 1)));
4362 #else
4363 goto illegal_op;
4364 #endif
4366 break;
4368 return;
4371 if (b1) {
4372 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4373 if (mod == 3) {
4374 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4375 } else {
4376 op2_offset = offsetof(CPUX86State,xmm_t0);
4377 gen_lea_modrm(env, s, modrm);
4378 gen_ldo_env_A0(s, op2_offset);
4380 } else {
4381 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4382 if (mod == 3) {
4383 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4384 } else {
4385 op2_offset = offsetof(CPUX86State,mmx_t0);
4386 gen_lea_modrm(env, s, modrm);
4387 gen_ldq_env_A0(s, op2_offset);
4390 val = x86_ldub_code(env, s);
4392 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4393 set_cc_op(s, CC_OP_EFLAGS);
4395 if (s->dflag == MO_64) {
4396 /* The helper must use entire 64-bit gp registers */
4397 val |= 1 << 8;
4401 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4402 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4403 sse_fn_eppi(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val));
4404 break;
4406 case 0x33a:
4407 /* Various integer extensions at 0f 3a f[0-f]. */
4408 b = modrm | (b1 << 8);
4409 modrm = x86_ldub_code(env, s);
4410 reg = ((modrm >> 3) & 7) | REX_R(s);
4412 switch (b) {
4413 case 0x3f0: /* rorx Gy,Ey, Ib */
4414 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4415 || !(s->prefix & PREFIX_VEX)
4416 || s->vex_l != 0) {
4417 goto illegal_op;
4419 ot = mo_64_32(s->dflag);
4420 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4421 b = x86_ldub_code(env, s);
4422 if (ot == MO_64) {
4423 tcg_gen_rotri_tl(s->T0, s->T0, b & 63);
4424 } else {
4425 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4426 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b & 31);
4427 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
4429 gen_op_mov_reg_v(s, ot, reg, s->T0);
4430 break;
4432 default:
4433 goto unknown_op;
4435 break;
4437 default:
4438 unknown_op:
4439 gen_unknown_opcode(env, s);
4440 return;
4442 } else {
4443 /* generic MMX or SSE operation */
4444 switch(b) {
4445 case 0x70: /* pshufx insn */
4446 case 0xc6: /* pshufx insn */
4447 case 0xc2: /* compare insns */
4448 s->rip_offset = 1;
4449 break;
4450 default:
4451 break;
4453 if (is_xmm) {
4454 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4455 if (mod != 3) {
4456 int sz = 4;
4458 gen_lea_modrm(env, s, modrm);
4459 op2_offset = offsetof(CPUX86State,xmm_t0);
4461 switch (b) {
4462 case 0x50 ... 0x5a:
4463 case 0x5c ... 0x5f:
4464 case 0xc2:
4465 /* Most sse scalar operations. */
4466 if (b1 == 2) {
4467 sz = 2;
4468 } else if (b1 == 3) {
4469 sz = 3;
4471 break;
4473 case 0x2e: /* ucomis[sd] */
4474 case 0x2f: /* comis[sd] */
4475 if (b1 == 0) {
4476 sz = 2;
4477 } else {
4478 sz = 3;
4480 break;
4483 switch (sz) {
4484 case 2:
4485 /* 32 bit access */
4486 gen_op_ld_v(s, MO_32, s->T0, s->A0);
4487 tcg_gen_st32_tl(s->T0, cpu_env,
4488 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4489 break;
4490 case 3:
4491 /* 64 bit access */
4492 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4493 break;
4494 default:
4495 /* 128 bit access */
4496 gen_ldo_env_A0(s, op2_offset);
4497 break;
4499 } else {
4500 rm = (modrm & 7) | REX_B(s);
4501 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4503 } else {
4504 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4505 if (mod != 3) {
4506 gen_lea_modrm(env, s, modrm);
4507 op2_offset = offsetof(CPUX86State,mmx_t0);
4508 gen_ldq_env_A0(s, op2_offset);
4509 } else {
4510 rm = (modrm & 7);
4511 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4514 switch(b) {
4515 case 0x0f: /* 3DNow! data insns */
4516 val = x86_ldub_code(env, s);
4517 sse_fn_epp = sse_op_table5[val];
4518 if (!sse_fn_epp) {
4519 goto unknown_op;
4521 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4522 goto illegal_op;
4524 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4525 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4526 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4527 break;
4528 case 0x70: /* pshufx insn */
4529 case 0xc6: /* pshufx insn */
4530 val = x86_ldub_code(env, s);
4531 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4532 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4533 /* XXX: introduce a new table? */
4534 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4535 sse_fn_ppi(s->ptr0, s->ptr1, tcg_const_i32(val));
4536 break;
4537 case 0xc2:
4538 /* compare insns */
4539 val = x86_ldub_code(env, s);
4540 if (val >= 8)
4541 goto unknown_op;
4542 sse_fn_epp = sse_op_table4[val][b1];
4544 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4545 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4546 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4547 break;
4548 case 0xf7:
4549 /* maskmov : we must prepare A0 */
4550 if (mod != 3)
4551 goto illegal_op;
4552 tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]);
4553 gen_extu(s->aflag, s->A0);
4554 gen_add_A0_ds_seg(s);
4556 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4557 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4558 /* XXX: introduce a new table? */
4559 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4560 sse_fn_eppt(cpu_env, s->ptr0, s->ptr1, s->A0);
4561 break;
4562 default:
4563 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4564 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4565 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4566 break;
4568 if (b == 0x2e || b == 0x2f) {
4569 set_cc_op(s, CC_OP_EFLAGS);
4574 /* convert one instruction. s->base.is_jmp is set if the translation must
4575 be stopped. Return the next pc value */
4576 static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
4578 CPUX86State *env = cpu->env_ptr;
4579 int b, prefixes;
4580 int shift;
4581 MemOp ot, aflag, dflag;
4582 int modrm, reg, rm, mod, op, opreg, val;
4583 target_ulong next_eip, tval;
4584 target_ulong pc_start = s->base.pc_next;
4586 s->pc_start = s->pc = pc_start;
4587 s->override = -1;
4588 #ifdef TARGET_X86_64
4589 s->rex_w = false;
4590 s->rex_r = 0;
4591 s->rex_x = 0;
4592 s->rex_b = 0;
4593 #endif
4594 s->rip_offset = 0; /* for relative ip address */
4595 s->vex_l = 0;
4596 s->vex_v = 0;
4597 if (sigsetjmp(s->jmpbuf, 0) != 0) {
4598 gen_exception_gpf(s);
4599 return s->pc;
4602 prefixes = 0;
4604 next_byte:
4605 b = x86_ldub_code(env, s);
4606 /* Collect prefixes. */
4607 switch (b) {
4608 case 0xf3:
4609 prefixes |= PREFIX_REPZ;
4610 goto next_byte;
4611 case 0xf2:
4612 prefixes |= PREFIX_REPNZ;
4613 goto next_byte;
4614 case 0xf0:
4615 prefixes |= PREFIX_LOCK;
4616 goto next_byte;
4617 case 0x2e:
4618 s->override = R_CS;
4619 goto next_byte;
4620 case 0x36:
4621 s->override = R_SS;
4622 goto next_byte;
4623 case 0x3e:
4624 s->override = R_DS;
4625 goto next_byte;
4626 case 0x26:
4627 s->override = R_ES;
4628 goto next_byte;
4629 case 0x64:
4630 s->override = R_FS;
4631 goto next_byte;
4632 case 0x65:
4633 s->override = R_GS;
4634 goto next_byte;
4635 case 0x66:
4636 prefixes |= PREFIX_DATA;
4637 goto next_byte;
4638 case 0x67:
4639 prefixes |= PREFIX_ADR;
4640 goto next_byte;
4641 #ifdef TARGET_X86_64
4642 case 0x40 ... 0x4f:
4643 if (CODE64(s)) {
4644 /* REX prefix */
4645 prefixes |= PREFIX_REX;
4646 s->rex_w = (b >> 3) & 1;
4647 s->rex_r = (b & 0x4) << 1;
4648 s->rex_x = (b & 0x2) << 2;
4649 s->rex_b = (b & 0x1) << 3;
4650 goto next_byte;
4652 break;
4653 #endif
4654 case 0xc5: /* 2-byte VEX */
4655 case 0xc4: /* 3-byte VEX */
4656 /* VEX prefixes cannot be used except in 32-bit mode.
4657 Otherwise the instruction is LES or LDS. */
4658 if (CODE32(s) && !VM86(s)) {
4659 static const int pp_prefix[4] = {
4660 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4662 int vex3, vex2 = x86_ldub_code(env, s);
4664 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4665 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4666 otherwise the instruction is LES or LDS. */
4667 s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
4668 break;
4671 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
4672 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4673 | PREFIX_LOCK | PREFIX_DATA | PREFIX_REX)) {
4674 goto illegal_op;
4676 #ifdef TARGET_X86_64
4677 s->rex_r = (~vex2 >> 4) & 8;
4678 #endif
4679 if (b == 0xc5) {
4680 /* 2-byte VEX prefix: RVVVVlpp, implied 0f leading opcode byte */
4681 vex3 = vex2;
4682 b = x86_ldub_code(env, s) | 0x100;
4683 } else {
4684 /* 3-byte VEX prefix: RXBmmmmm wVVVVlpp */
4685 vex3 = x86_ldub_code(env, s);
4686 #ifdef TARGET_X86_64
4687 s->rex_x = (~vex2 >> 3) & 8;
4688 s->rex_b = (~vex2 >> 2) & 8;
4689 s->rex_w = (vex3 >> 7) & 1;
4690 #endif
4691 switch (vex2 & 0x1f) {
4692 case 0x01: /* Implied 0f leading opcode bytes. */
4693 b = x86_ldub_code(env, s) | 0x100;
4694 break;
4695 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4696 b = 0x138;
4697 break;
4698 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4699 b = 0x13a;
4700 break;
4701 default: /* Reserved for future use. */
4702 goto unknown_op;
4705 s->vex_v = (~vex3 >> 3) & 0xf;
4706 s->vex_l = (vex3 >> 2) & 1;
4707 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4709 break;
4712 /* Post-process prefixes. */
4713 if (CODE64(s)) {
4714 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4715 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4716 over 0x66 if both are present. */
4717 dflag = (REX_W(s) ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4718 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
4719 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4720 } else {
4721 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
4722 if (CODE32(s) ^ ((prefixes & PREFIX_DATA) != 0)) {
4723 dflag = MO_32;
4724 } else {
4725 dflag = MO_16;
4727 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
4728 if (CODE32(s) ^ ((prefixes & PREFIX_ADR) != 0)) {
4729 aflag = MO_32;
4730 } else {
4731 aflag = MO_16;
4735 s->prefix = prefixes;
4736 s->aflag = aflag;
4737 s->dflag = dflag;
4739 /* now check op code */
4740 reswitch:
4741 switch(b) {
4742 case 0x0f:
4743 /**************************/
4744 /* extended op code */
4745 b = x86_ldub_code(env, s) | 0x100;
4746 goto reswitch;
4748 /**************************/
4749 /* arith & logic */
4750 case 0x00 ... 0x05:
4751 case 0x08 ... 0x0d:
4752 case 0x10 ... 0x15:
4753 case 0x18 ... 0x1d:
4754 case 0x20 ... 0x25:
4755 case 0x28 ... 0x2d:
4756 case 0x30 ... 0x35:
4757 case 0x38 ... 0x3d:
4759 int op, f, val;
4760 op = (b >> 3) & 7;
4761 f = (b >> 1) & 3;
4763 ot = mo_b_d(b, dflag);
4765 switch(f) {
4766 case 0: /* OP Ev, Gv */
4767 modrm = x86_ldub_code(env, s);
4768 reg = ((modrm >> 3) & 7) | REX_R(s);
4769 mod = (modrm >> 6) & 3;
4770 rm = (modrm & 7) | REX_B(s);
4771 if (mod != 3) {
4772 gen_lea_modrm(env, s, modrm);
4773 opreg = OR_TMP0;
4774 } else if (op == OP_XORL && rm == reg) {
4775 xor_zero:
4776 /* xor reg, reg optimisation */
4777 set_cc_op(s, CC_OP_CLR);
4778 tcg_gen_movi_tl(s->T0, 0);
4779 gen_op_mov_reg_v(s, ot, reg, s->T0);
4780 break;
4781 } else {
4782 opreg = rm;
4784 gen_op_mov_v_reg(s, ot, s->T1, reg);
4785 gen_op(s, op, ot, opreg);
4786 break;
4787 case 1: /* OP Gv, Ev */
4788 modrm = x86_ldub_code(env, s);
4789 mod = (modrm >> 6) & 3;
4790 reg = ((modrm >> 3) & 7) | REX_R(s);
4791 rm = (modrm & 7) | REX_B(s);
4792 if (mod != 3) {
4793 gen_lea_modrm(env, s, modrm);
4794 gen_op_ld_v(s, ot, s->T1, s->A0);
4795 } else if (op == OP_XORL && rm == reg) {
4796 goto xor_zero;
4797 } else {
4798 gen_op_mov_v_reg(s, ot, s->T1, rm);
4800 gen_op(s, op, ot, reg);
4801 break;
4802 case 2: /* OP A, Iv */
4803 val = insn_get(env, s, ot);
4804 tcg_gen_movi_tl(s->T1, val);
4805 gen_op(s, op, ot, OR_EAX);
4806 break;
4809 break;
4811 case 0x82:
4812 if (CODE64(s))
4813 goto illegal_op;
4814 /* fall through */
4815 case 0x80: /* GRP1 */
4816 case 0x81:
4817 case 0x83:
4819 int val;
4821 ot = mo_b_d(b, dflag);
4823 modrm = x86_ldub_code(env, s);
4824 mod = (modrm >> 6) & 3;
4825 rm = (modrm & 7) | REX_B(s);
4826 op = (modrm >> 3) & 7;
4828 if (mod != 3) {
4829 if (b == 0x83)
4830 s->rip_offset = 1;
4831 else
4832 s->rip_offset = insn_const_size(ot);
4833 gen_lea_modrm(env, s, modrm);
4834 opreg = OR_TMP0;
4835 } else {
4836 opreg = rm;
4839 switch(b) {
4840 default:
4841 case 0x80:
4842 case 0x81:
4843 case 0x82:
4844 val = insn_get(env, s, ot);
4845 break;
4846 case 0x83:
4847 val = (int8_t)insn_get(env, s, MO_8);
4848 break;
4850 tcg_gen_movi_tl(s->T1, val);
4851 gen_op(s, op, ot, opreg);
4853 break;
4855 /**************************/
4856 /* inc, dec, and other misc arith */
4857 case 0x40 ... 0x47: /* inc Gv */
4858 ot = dflag;
4859 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4860 break;
4861 case 0x48 ... 0x4f: /* dec Gv */
4862 ot = dflag;
4863 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4864 break;
4865 case 0xf6: /* GRP3 */
4866 case 0xf7:
4867 ot = mo_b_d(b, dflag);
4869 modrm = x86_ldub_code(env, s);
4870 mod = (modrm >> 6) & 3;
4871 rm = (modrm & 7) | REX_B(s);
4872 op = (modrm >> 3) & 7;
4873 if (mod != 3) {
4874 if (op == 0) {
4875 s->rip_offset = insn_const_size(ot);
4877 gen_lea_modrm(env, s, modrm);
4878 /* For those below that handle locked memory, don't load here. */
4879 if (!(s->prefix & PREFIX_LOCK)
4880 || op != 2) {
4881 gen_op_ld_v(s, ot, s->T0, s->A0);
4883 } else {
4884 gen_op_mov_v_reg(s, ot, s->T0, rm);
4887 switch(op) {
4888 case 0: /* test */
4889 val = insn_get(env, s, ot);
4890 tcg_gen_movi_tl(s->T1, val);
4891 gen_op_testl_T0_T1_cc(s);
4892 set_cc_op(s, CC_OP_LOGICB + ot);
4893 break;
4894 case 2: /* not */
4895 if (s->prefix & PREFIX_LOCK) {
4896 if (mod == 3) {
4897 goto illegal_op;
4899 tcg_gen_movi_tl(s->T0, ~0);
4900 tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0,
4901 s->mem_index, ot | MO_LE);
4902 } else {
4903 tcg_gen_not_tl(s->T0, s->T0);
4904 if (mod != 3) {
4905 gen_op_st_v(s, ot, s->T0, s->A0);
4906 } else {
4907 gen_op_mov_reg_v(s, ot, rm, s->T0);
4910 break;
4911 case 3: /* neg */
4912 if (s->prefix & PREFIX_LOCK) {
4913 TCGLabel *label1;
4914 TCGv a0, t0, t1, t2;
4916 if (mod == 3) {
4917 goto illegal_op;
4919 a0 = tcg_temp_local_new();
4920 t0 = tcg_temp_local_new();
4921 label1 = gen_new_label();
4923 tcg_gen_mov_tl(a0, s->A0);
4924 tcg_gen_mov_tl(t0, s->T0);
4926 gen_set_label(label1);
4927 t1 = tcg_temp_new();
4928 t2 = tcg_temp_new();
4929 tcg_gen_mov_tl(t2, t0);
4930 tcg_gen_neg_tl(t1, t0);
4931 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4932 s->mem_index, ot | MO_LE);
4933 tcg_temp_free(t1);
4934 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4936 tcg_temp_free(t2);
4937 tcg_temp_free(a0);
4938 tcg_gen_mov_tl(s->T0, t0);
4939 tcg_temp_free(t0);
4940 } else {
4941 tcg_gen_neg_tl(s->T0, s->T0);
4942 if (mod != 3) {
4943 gen_op_st_v(s, ot, s->T0, s->A0);
4944 } else {
4945 gen_op_mov_reg_v(s, ot, rm, s->T0);
4948 gen_op_update_neg_cc(s);
4949 set_cc_op(s, CC_OP_SUBB + ot);
4950 break;
4951 case 4: /* mul */
4952 switch(ot) {
4953 case MO_8:
4954 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4955 tcg_gen_ext8u_tl(s->T0, s->T0);
4956 tcg_gen_ext8u_tl(s->T1, s->T1);
4957 /* XXX: use 32 bit mul which could be faster */
4958 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4959 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4960 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4961 tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00);
4962 set_cc_op(s, CC_OP_MULB);
4963 break;
4964 case MO_16:
4965 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
4966 tcg_gen_ext16u_tl(s->T0, s->T0);
4967 tcg_gen_ext16u_tl(s->T1, s->T1);
4968 /* XXX: use 32 bit mul which could be faster */
4969 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4970 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4971 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4972 tcg_gen_shri_tl(s->T0, s->T0, 16);
4973 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
4974 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4975 set_cc_op(s, CC_OP_MULW);
4976 break;
4977 default:
4978 case MO_32:
4979 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4980 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
4981 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
4982 s->tmp2_i32, s->tmp3_i32);
4983 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
4984 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
4985 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4986 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4987 set_cc_op(s, CC_OP_MULL);
4988 break;
4989 #ifdef TARGET_X86_64
4990 case MO_64:
4991 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4992 s->T0, cpu_regs[R_EAX]);
4993 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4994 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4995 set_cc_op(s, CC_OP_MULQ);
4996 break;
4997 #endif
4999 break;
5000 case 5: /* imul */
5001 switch(ot) {
5002 case MO_8:
5003 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
5004 tcg_gen_ext8s_tl(s->T0, s->T0);
5005 tcg_gen_ext8s_tl(s->T1, s->T1);
5006 /* XXX: use 32 bit mul which could be faster */
5007 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5008 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5009 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5010 tcg_gen_ext8s_tl(s->tmp0, s->T0);
5011 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5012 set_cc_op(s, CC_OP_MULB);
5013 break;
5014 case MO_16:
5015 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
5016 tcg_gen_ext16s_tl(s->T0, s->T0);
5017 tcg_gen_ext16s_tl(s->T1, s->T1);
5018 /* XXX: use 32 bit mul which could be faster */
5019 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5020 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5021 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5022 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5023 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5024 tcg_gen_shri_tl(s->T0, s->T0, 16);
5025 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5026 set_cc_op(s, CC_OP_MULW);
5027 break;
5028 default:
5029 case MO_32:
5030 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5031 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
5032 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5033 s->tmp2_i32, s->tmp3_i32);
5034 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
5035 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
5036 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5037 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5038 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5039 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5040 set_cc_op(s, CC_OP_MULL);
5041 break;
5042 #ifdef TARGET_X86_64
5043 case MO_64:
5044 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
5045 s->T0, cpu_regs[R_EAX]);
5046 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
5047 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
5048 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
5049 set_cc_op(s, CC_OP_MULQ);
5050 break;
5051 #endif
5053 break;
5054 case 6: /* div */
5055 switch(ot) {
5056 case MO_8:
5057 gen_helper_divb_AL(cpu_env, s->T0);
5058 break;
5059 case MO_16:
5060 gen_helper_divw_AX(cpu_env, s->T0);
5061 break;
5062 default:
5063 case MO_32:
5064 gen_helper_divl_EAX(cpu_env, s->T0);
5065 break;
5066 #ifdef TARGET_X86_64
5067 case MO_64:
5068 gen_helper_divq_EAX(cpu_env, s->T0);
5069 break;
5070 #endif
5072 break;
5073 case 7: /* idiv */
5074 switch(ot) {
5075 case MO_8:
5076 gen_helper_idivb_AL(cpu_env, s->T0);
5077 break;
5078 case MO_16:
5079 gen_helper_idivw_AX(cpu_env, s->T0);
5080 break;
5081 default:
5082 case MO_32:
5083 gen_helper_idivl_EAX(cpu_env, s->T0);
5084 break;
5085 #ifdef TARGET_X86_64
5086 case MO_64:
5087 gen_helper_idivq_EAX(cpu_env, s->T0);
5088 break;
5089 #endif
5091 break;
5092 default:
5093 goto unknown_op;
5095 break;
5097 case 0xfe: /* GRP4 */
5098 case 0xff: /* GRP5 */
5099 ot = mo_b_d(b, dflag);
5101 modrm = x86_ldub_code(env, s);
5102 mod = (modrm >> 6) & 3;
5103 rm = (modrm & 7) | REX_B(s);
5104 op = (modrm >> 3) & 7;
5105 if (op >= 2 && b == 0xfe) {
5106 goto unknown_op;
5108 if (CODE64(s)) {
5109 if (op == 2 || op == 4) {
5110 /* operand size for jumps is 64 bit */
5111 ot = MO_64;
5112 } else if (op == 3 || op == 5) {
5113 ot = dflag != MO_16 ? MO_32 + REX_W(s) : MO_16;
5114 } else if (op == 6) {
5115 /* default push size is 64 bit */
5116 ot = mo_pushpop(s, dflag);
5119 if (mod != 3) {
5120 gen_lea_modrm(env, s, modrm);
5121 if (op >= 2 && op != 3 && op != 5)
5122 gen_op_ld_v(s, ot, s->T0, s->A0);
5123 } else {
5124 gen_op_mov_v_reg(s, ot, s->T0, rm);
5127 switch(op) {
5128 case 0: /* inc Ev */
5129 if (mod != 3)
5130 opreg = OR_TMP0;
5131 else
5132 opreg = rm;
5133 gen_inc(s, ot, opreg, 1);
5134 break;
5135 case 1: /* dec Ev */
5136 if (mod != 3)
5137 opreg = OR_TMP0;
5138 else
5139 opreg = rm;
5140 gen_inc(s, ot, opreg, -1);
5141 break;
5142 case 2: /* call Ev */
5143 /* XXX: optimize if memory (no 'and' is necessary) */
5144 if (dflag == MO_16) {
5145 tcg_gen_ext16u_tl(s->T0, s->T0);
5147 next_eip = s->pc - s->cs_base;
5148 tcg_gen_movi_tl(s->T1, next_eip);
5149 gen_push_v(s, s->T1);
5150 gen_op_jmp_v(s->T0);
5151 gen_bnd_jmp(s);
5152 gen_jr(s, s->T0);
5153 break;
5154 case 3: /* lcall Ev */
5155 if (mod == 3) {
5156 goto illegal_op;
5158 gen_op_ld_v(s, ot, s->T1, s->A0);
5159 gen_add_A0_im(s, 1 << ot);
5160 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5161 do_lcall:
5162 if (PE(s) && !VM86(s)) {
5163 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5164 gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
5165 tcg_const_i32(dflag - 1),
5166 tcg_const_tl(s->pc - s->cs_base));
5167 } else {
5168 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5169 gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1,
5170 tcg_const_i32(dflag - 1),
5171 tcg_const_i32(s->pc - s->cs_base));
5173 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5174 gen_jr(s, s->tmp4);
5175 break;
5176 case 4: /* jmp Ev */
5177 if (dflag == MO_16) {
5178 tcg_gen_ext16u_tl(s->T0, s->T0);
5180 gen_op_jmp_v(s->T0);
5181 gen_bnd_jmp(s);
5182 gen_jr(s, s->T0);
5183 break;
5184 case 5: /* ljmp Ev */
5185 if (mod == 3) {
5186 goto illegal_op;
5188 gen_op_ld_v(s, ot, s->T1, s->A0);
5189 gen_add_A0_im(s, 1 << ot);
5190 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5191 do_ljmp:
5192 if (PE(s) && !VM86(s)) {
5193 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5194 gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1,
5195 tcg_const_tl(s->pc - s->cs_base));
5196 } else {
5197 gen_op_movl_seg_T0_vm(s, R_CS);
5198 gen_op_jmp_v(s->T1);
5200 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5201 gen_jr(s, s->tmp4);
5202 break;
5203 case 6: /* push Ev */
5204 gen_push_v(s, s->T0);
5205 break;
5206 default:
5207 goto unknown_op;
5209 break;
5211 case 0x84: /* test Ev, Gv */
5212 case 0x85:
5213 ot = mo_b_d(b, dflag);
5215 modrm = x86_ldub_code(env, s);
5216 reg = ((modrm >> 3) & 7) | REX_R(s);
5218 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5219 gen_op_mov_v_reg(s, ot, s->T1, reg);
5220 gen_op_testl_T0_T1_cc(s);
5221 set_cc_op(s, CC_OP_LOGICB + ot);
5222 break;
5224 case 0xa8: /* test eAX, Iv */
5225 case 0xa9:
5226 ot = mo_b_d(b, dflag);
5227 val = insn_get(env, s, ot);
5229 gen_op_mov_v_reg(s, ot, s->T0, OR_EAX);
5230 tcg_gen_movi_tl(s->T1, val);
5231 gen_op_testl_T0_T1_cc(s);
5232 set_cc_op(s, CC_OP_LOGICB + ot);
5233 break;
5235 case 0x98: /* CWDE/CBW */
5236 switch (dflag) {
5237 #ifdef TARGET_X86_64
5238 case MO_64:
5239 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5240 tcg_gen_ext32s_tl(s->T0, s->T0);
5241 gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0);
5242 break;
5243 #endif
5244 case MO_32:
5245 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5246 tcg_gen_ext16s_tl(s->T0, s->T0);
5247 gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0);
5248 break;
5249 case MO_16:
5250 gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX);
5251 tcg_gen_ext8s_tl(s->T0, s->T0);
5252 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5253 break;
5254 default:
5255 tcg_abort();
5257 break;
5258 case 0x99: /* CDQ/CWD */
5259 switch (dflag) {
5260 #ifdef TARGET_X86_64
5261 case MO_64:
5262 gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX);
5263 tcg_gen_sari_tl(s->T0, s->T0, 63);
5264 gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0);
5265 break;
5266 #endif
5267 case MO_32:
5268 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5269 tcg_gen_ext32s_tl(s->T0, s->T0);
5270 tcg_gen_sari_tl(s->T0, s->T0, 31);
5271 gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0);
5272 break;
5273 case MO_16:
5274 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5275 tcg_gen_ext16s_tl(s->T0, s->T0);
5276 tcg_gen_sari_tl(s->T0, s->T0, 15);
5277 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5278 break;
5279 default:
5280 tcg_abort();
5282 break;
5283 case 0x1af: /* imul Gv, Ev */
5284 case 0x69: /* imul Gv, Ev, I */
5285 case 0x6b:
5286 ot = dflag;
5287 modrm = x86_ldub_code(env, s);
5288 reg = ((modrm >> 3) & 7) | REX_R(s);
5289 if (b == 0x69)
5290 s->rip_offset = insn_const_size(ot);
5291 else if (b == 0x6b)
5292 s->rip_offset = 1;
5293 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5294 if (b == 0x69) {
5295 val = insn_get(env, s, ot);
5296 tcg_gen_movi_tl(s->T1, val);
5297 } else if (b == 0x6b) {
5298 val = (int8_t)insn_get(env, s, MO_8);
5299 tcg_gen_movi_tl(s->T1, val);
5300 } else {
5301 gen_op_mov_v_reg(s, ot, s->T1, reg);
5303 switch (ot) {
5304 #ifdef TARGET_X86_64
5305 case MO_64:
5306 tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1);
5307 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5308 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5309 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1);
5310 break;
5311 #endif
5312 case MO_32:
5313 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5314 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
5315 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5316 s->tmp2_i32, s->tmp3_i32);
5317 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
5318 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5319 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5320 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5321 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5322 break;
5323 default:
5324 tcg_gen_ext16s_tl(s->T0, s->T0);
5325 tcg_gen_ext16s_tl(s->T1, s->T1);
5326 /* XXX: use 32 bit mul which could be faster */
5327 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5328 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5329 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5330 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5331 gen_op_mov_reg_v(s, ot, reg, s->T0);
5332 break;
5334 set_cc_op(s, CC_OP_MULB + ot);
5335 break;
5336 case 0x1c0:
5337 case 0x1c1: /* xadd Ev, Gv */
5338 ot = mo_b_d(b, dflag);
5339 modrm = x86_ldub_code(env, s);
5340 reg = ((modrm >> 3) & 7) | REX_R(s);
5341 mod = (modrm >> 6) & 3;
5342 gen_op_mov_v_reg(s, ot, s->T0, reg);
5343 if (mod == 3) {
5344 rm = (modrm & 7) | REX_B(s);
5345 gen_op_mov_v_reg(s, ot, s->T1, rm);
5346 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5347 gen_op_mov_reg_v(s, ot, reg, s->T1);
5348 gen_op_mov_reg_v(s, ot, rm, s->T0);
5349 } else {
5350 gen_lea_modrm(env, s, modrm);
5351 if (s->prefix & PREFIX_LOCK) {
5352 tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0,
5353 s->mem_index, ot | MO_LE);
5354 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5355 } else {
5356 gen_op_ld_v(s, ot, s->T1, s->A0);
5357 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5358 gen_op_st_v(s, ot, s->T0, s->A0);
5360 gen_op_mov_reg_v(s, ot, reg, s->T1);
5362 gen_op_update2_cc(s);
5363 set_cc_op(s, CC_OP_ADDB + ot);
5364 break;
5365 case 0x1b0:
5366 case 0x1b1: /* cmpxchg Ev, Gv */
5368 TCGv oldv, newv, cmpv;
5370 ot = mo_b_d(b, dflag);
5371 modrm = x86_ldub_code(env, s);
5372 reg = ((modrm >> 3) & 7) | REX_R(s);
5373 mod = (modrm >> 6) & 3;
5374 oldv = tcg_temp_new();
5375 newv = tcg_temp_new();
5376 cmpv = tcg_temp_new();
5377 gen_op_mov_v_reg(s, ot, newv, reg);
5378 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5380 if (s->prefix & PREFIX_LOCK) {
5381 if (mod == 3) {
5382 goto illegal_op;
5384 gen_lea_modrm(env, s, modrm);
5385 tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
5386 s->mem_index, ot | MO_LE);
5387 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5388 } else {
5389 if (mod == 3) {
5390 rm = (modrm & 7) | REX_B(s);
5391 gen_op_mov_v_reg(s, ot, oldv, rm);
5392 } else {
5393 gen_lea_modrm(env, s, modrm);
5394 gen_op_ld_v(s, ot, oldv, s->A0);
5395 rm = 0; /* avoid warning */
5397 gen_extu(ot, oldv);
5398 gen_extu(ot, cmpv);
5399 /* store value = (old == cmp ? new : old); */
5400 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5401 if (mod == 3) {
5402 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5403 gen_op_mov_reg_v(s, ot, rm, newv);
5404 } else {
5405 /* Perform an unconditional store cycle like physical cpu;
5406 must be before changing accumulator to ensure
5407 idempotency if the store faults and the instruction
5408 is restarted */
5409 gen_op_st_v(s, ot, newv, s->A0);
5410 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5413 tcg_gen_mov_tl(cpu_cc_src, oldv);
5414 tcg_gen_mov_tl(s->cc_srcT, cmpv);
5415 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5416 set_cc_op(s, CC_OP_SUBB + ot);
5417 tcg_temp_free(oldv);
5418 tcg_temp_free(newv);
5419 tcg_temp_free(cmpv);
5421 break;
5422 case 0x1c7: /* cmpxchg8b */
5423 modrm = x86_ldub_code(env, s);
5424 mod = (modrm >> 6) & 3;
5425 switch ((modrm >> 3) & 7) {
5426 case 1: /* CMPXCHG8, CMPXCHG16 */
5427 if (mod == 3) {
5428 goto illegal_op;
5430 #ifdef TARGET_X86_64
5431 if (dflag == MO_64) {
5432 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) {
5433 goto illegal_op;
5435 gen_lea_modrm(env, s, modrm);
5436 if ((s->prefix & PREFIX_LOCK) &&
5437 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5438 gen_helper_cmpxchg16b(cpu_env, s->A0);
5439 } else {
5440 gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0);
5442 set_cc_op(s, CC_OP_EFLAGS);
5443 break;
5445 #endif
5446 if (!(s->cpuid_features & CPUID_CX8)) {
5447 goto illegal_op;
5449 gen_lea_modrm(env, s, modrm);
5450 if ((s->prefix & PREFIX_LOCK) &&
5451 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5452 gen_helper_cmpxchg8b(cpu_env, s->A0);
5453 } else {
5454 gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0);
5456 set_cc_op(s, CC_OP_EFLAGS);
5457 break;
5459 case 7: /* RDSEED */
5460 case 6: /* RDRAND */
5461 if (mod != 3 ||
5462 (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
5463 !(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
5464 goto illegal_op;
5466 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5467 gen_io_start();
5469 gen_helper_rdrand(s->T0, cpu_env);
5470 rm = (modrm & 7) | REX_B(s);
5471 gen_op_mov_reg_v(s, dflag, rm, s->T0);
5472 set_cc_op(s, CC_OP_EFLAGS);
5473 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5474 gen_jmp(s, s->pc - s->cs_base);
5476 break;
5478 default:
5479 goto illegal_op;
5481 break;
5483 /**************************/
5484 /* push/pop */
5485 case 0x50 ... 0x57: /* push */
5486 gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s));
5487 gen_push_v(s, s->T0);
5488 break;
5489 case 0x58 ... 0x5f: /* pop */
5490 ot = gen_pop_T0(s);
5491 /* NOTE: order is important for pop %sp */
5492 gen_pop_update(s, ot);
5493 gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0);
5494 break;
5495 case 0x60: /* pusha */
5496 if (CODE64(s))
5497 goto illegal_op;
5498 gen_pusha(s);
5499 break;
5500 case 0x61: /* popa */
5501 if (CODE64(s))
5502 goto illegal_op;
5503 gen_popa(s);
5504 break;
5505 case 0x68: /* push Iv */
5506 case 0x6a:
5507 ot = mo_pushpop(s, dflag);
5508 if (b == 0x68)
5509 val = insn_get(env, s, ot);
5510 else
5511 val = (int8_t)insn_get(env, s, MO_8);
5512 tcg_gen_movi_tl(s->T0, val);
5513 gen_push_v(s, s->T0);
5514 break;
5515 case 0x8f: /* pop Ev */
5516 modrm = x86_ldub_code(env, s);
5517 mod = (modrm >> 6) & 3;
5518 ot = gen_pop_T0(s);
5519 if (mod == 3) {
5520 /* NOTE: order is important for pop %sp */
5521 gen_pop_update(s, ot);
5522 rm = (modrm & 7) | REX_B(s);
5523 gen_op_mov_reg_v(s, ot, rm, s->T0);
5524 } else {
5525 /* NOTE: order is important too for MMU exceptions */
5526 s->popl_esp_hack = 1 << ot;
5527 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5528 s->popl_esp_hack = 0;
5529 gen_pop_update(s, ot);
5531 break;
5532 case 0xc8: /* enter */
5534 int level;
5535 val = x86_lduw_code(env, s);
5536 level = x86_ldub_code(env, s);
5537 gen_enter(s, val, level);
5539 break;
5540 case 0xc9: /* leave */
5541 gen_leave(s);
5542 break;
5543 case 0x06: /* push es */
5544 case 0x0e: /* push cs */
5545 case 0x16: /* push ss */
5546 case 0x1e: /* push ds */
5547 if (CODE64(s))
5548 goto illegal_op;
5549 gen_op_movl_T0_seg(s, b >> 3);
5550 gen_push_v(s, s->T0);
5551 break;
5552 case 0x1a0: /* push fs */
5553 case 0x1a8: /* push gs */
5554 gen_op_movl_T0_seg(s, (b >> 3) & 7);
5555 gen_push_v(s, s->T0);
5556 break;
5557 case 0x07: /* pop es */
5558 case 0x17: /* pop ss */
5559 case 0x1f: /* pop ds */
5560 if (CODE64(s))
5561 goto illegal_op;
5562 reg = b >> 3;
5563 ot = gen_pop_T0(s);
5564 gen_movl_seg_T0(s, reg);
5565 gen_pop_update(s, ot);
5566 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5567 if (s->base.is_jmp) {
5568 gen_jmp_im(s, s->pc - s->cs_base);
5569 if (reg == R_SS) {
5570 s->flags &= ~HF_TF_MASK;
5571 gen_eob_inhibit_irq(s, true);
5572 } else {
5573 gen_eob(s);
5576 break;
5577 case 0x1a1: /* pop fs */
5578 case 0x1a9: /* pop gs */
5579 ot = gen_pop_T0(s);
5580 gen_movl_seg_T0(s, (b >> 3) & 7);
5581 gen_pop_update(s, ot);
5582 if (s->base.is_jmp) {
5583 gen_jmp_im(s, s->pc - s->cs_base);
5584 gen_eob(s);
5586 break;
5588 /**************************/
5589 /* mov */
5590 case 0x88:
5591 case 0x89: /* mov Gv, Ev */
5592 ot = mo_b_d(b, dflag);
5593 modrm = x86_ldub_code(env, s);
5594 reg = ((modrm >> 3) & 7) | REX_R(s);
5596 /* generate a generic store */
5597 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5598 break;
5599 case 0xc6:
5600 case 0xc7: /* mov Ev, Iv */
5601 ot = mo_b_d(b, dflag);
5602 modrm = x86_ldub_code(env, s);
5603 mod = (modrm >> 6) & 3;
5604 if (mod != 3) {
5605 s->rip_offset = insn_const_size(ot);
5606 gen_lea_modrm(env, s, modrm);
5608 val = insn_get(env, s, ot);
5609 tcg_gen_movi_tl(s->T0, val);
5610 if (mod != 3) {
5611 gen_op_st_v(s, ot, s->T0, s->A0);
5612 } else {
5613 gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0);
5615 break;
5616 case 0x8a:
5617 case 0x8b: /* mov Ev, Gv */
5618 ot = mo_b_d(b, dflag);
5619 modrm = x86_ldub_code(env, s);
5620 reg = ((modrm >> 3) & 7) | REX_R(s);
5622 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5623 gen_op_mov_reg_v(s, ot, reg, s->T0);
5624 break;
5625 case 0x8e: /* mov seg, Gv */
5626 modrm = x86_ldub_code(env, s);
5627 reg = (modrm >> 3) & 7;
5628 if (reg >= 6 || reg == R_CS)
5629 goto illegal_op;
5630 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5631 gen_movl_seg_T0(s, reg);
5632 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
5633 if (s->base.is_jmp) {
5634 gen_jmp_im(s, s->pc - s->cs_base);
5635 if (reg == R_SS) {
5636 s->flags &= ~HF_TF_MASK;
5637 gen_eob_inhibit_irq(s, true);
5638 } else {
5639 gen_eob(s);
5642 break;
5643 case 0x8c: /* mov Gv, seg */
5644 modrm = x86_ldub_code(env, s);
5645 reg = (modrm >> 3) & 7;
5646 mod = (modrm >> 6) & 3;
5647 if (reg >= 6)
5648 goto illegal_op;
5649 gen_op_movl_T0_seg(s, reg);
5650 ot = mod == 3 ? dflag : MO_16;
5651 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5652 break;
5654 case 0x1b6: /* movzbS Gv, Eb */
5655 case 0x1b7: /* movzwS Gv, Eb */
5656 case 0x1be: /* movsbS Gv, Eb */
5657 case 0x1bf: /* movswS Gv, Eb */
5659 MemOp d_ot;
5660 MemOp s_ot;
5662 /* d_ot is the size of destination */
5663 d_ot = dflag;
5664 /* ot is the size of source */
5665 ot = (b & 1) + MO_8;
5666 /* s_ot is the sign+size of source */
5667 s_ot = b & 8 ? MO_SIGN | ot : ot;
5669 modrm = x86_ldub_code(env, s);
5670 reg = ((modrm >> 3) & 7) | REX_R(s);
5671 mod = (modrm >> 6) & 3;
5672 rm = (modrm & 7) | REX_B(s);
5674 if (mod == 3) {
5675 if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) {
5676 tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8);
5677 } else {
5678 gen_op_mov_v_reg(s, ot, s->T0, rm);
5679 switch (s_ot) {
5680 case MO_UB:
5681 tcg_gen_ext8u_tl(s->T0, s->T0);
5682 break;
5683 case MO_SB:
5684 tcg_gen_ext8s_tl(s->T0, s->T0);
5685 break;
5686 case MO_UW:
5687 tcg_gen_ext16u_tl(s->T0, s->T0);
5688 break;
5689 default:
5690 case MO_SW:
5691 tcg_gen_ext16s_tl(s->T0, s->T0);
5692 break;
5695 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5696 } else {
5697 gen_lea_modrm(env, s, modrm);
5698 gen_op_ld_v(s, s_ot, s->T0, s->A0);
5699 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5702 break;
5704 case 0x8d: /* lea */
5705 modrm = x86_ldub_code(env, s);
5706 mod = (modrm >> 6) & 3;
5707 if (mod == 3)
5708 goto illegal_op;
5709 reg = ((modrm >> 3) & 7) | REX_R(s);
5711 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5712 TCGv ea = gen_lea_modrm_1(s, a);
5713 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5714 gen_op_mov_reg_v(s, dflag, reg, s->A0);
5716 break;
5718 case 0xa0: /* mov EAX, Ov */
5719 case 0xa1:
5720 case 0xa2: /* mov Ov, EAX */
5721 case 0xa3:
5723 target_ulong offset_addr;
5725 ot = mo_b_d(b, dflag);
5726 switch (s->aflag) {
5727 #ifdef TARGET_X86_64
5728 case MO_64:
5729 offset_addr = x86_ldq_code(env, s);
5730 break;
5731 #endif
5732 default:
5733 offset_addr = insn_get(env, s, s->aflag);
5734 break;
5736 tcg_gen_movi_tl(s->A0, offset_addr);
5737 gen_add_A0_ds_seg(s);
5738 if ((b & 2) == 0) {
5739 gen_op_ld_v(s, ot, s->T0, s->A0);
5740 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
5741 } else {
5742 gen_op_mov_v_reg(s, ot, s->T0, R_EAX);
5743 gen_op_st_v(s, ot, s->T0, s->A0);
5746 break;
5747 case 0xd7: /* xlat */
5748 tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]);
5749 tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]);
5750 tcg_gen_add_tl(s->A0, s->A0, s->T0);
5751 gen_extu(s->aflag, s->A0);
5752 gen_add_A0_ds_seg(s);
5753 gen_op_ld_v(s, MO_8, s->T0, s->A0);
5754 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
5755 break;
5756 case 0xb0 ... 0xb7: /* mov R, Ib */
5757 val = insn_get(env, s, MO_8);
5758 tcg_gen_movi_tl(s->T0, val);
5759 gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0);
5760 break;
5761 case 0xb8 ... 0xbf: /* mov R, Iv */
5762 #ifdef TARGET_X86_64
5763 if (dflag == MO_64) {
5764 uint64_t tmp;
5765 /* 64 bit case */
5766 tmp = x86_ldq_code(env, s);
5767 reg = (b & 7) | REX_B(s);
5768 tcg_gen_movi_tl(s->T0, tmp);
5769 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
5770 } else
5771 #endif
5773 ot = dflag;
5774 val = insn_get(env, s, ot);
5775 reg = (b & 7) | REX_B(s);
5776 tcg_gen_movi_tl(s->T0, val);
5777 gen_op_mov_reg_v(s, ot, reg, s->T0);
5779 break;
5781 case 0x91 ... 0x97: /* xchg R, EAX */
5782 do_xchg_reg_eax:
5783 ot = dflag;
5784 reg = (b & 7) | REX_B(s);
5785 rm = R_EAX;
5786 goto do_xchg_reg;
5787 case 0x86:
5788 case 0x87: /* xchg Ev, Gv */
5789 ot = mo_b_d(b, dflag);
5790 modrm = x86_ldub_code(env, s);
5791 reg = ((modrm >> 3) & 7) | REX_R(s);
5792 mod = (modrm >> 6) & 3;
5793 if (mod == 3) {
5794 rm = (modrm & 7) | REX_B(s);
5795 do_xchg_reg:
5796 gen_op_mov_v_reg(s, ot, s->T0, reg);
5797 gen_op_mov_v_reg(s, ot, s->T1, rm);
5798 gen_op_mov_reg_v(s, ot, rm, s->T0);
5799 gen_op_mov_reg_v(s, ot, reg, s->T1);
5800 } else {
5801 gen_lea_modrm(env, s, modrm);
5802 gen_op_mov_v_reg(s, ot, s->T0, reg);
5803 /* for xchg, lock is implicit */
5804 tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0,
5805 s->mem_index, ot | MO_LE);
5806 gen_op_mov_reg_v(s, ot, reg, s->T1);
5808 break;
5809 case 0xc4: /* les Gv */
5810 /* In CODE64 this is VEX3; see above. */
5811 op = R_ES;
5812 goto do_lxx;
5813 case 0xc5: /* lds Gv */
5814 /* In CODE64 this is VEX2; see above. */
5815 op = R_DS;
5816 goto do_lxx;
5817 case 0x1b2: /* lss Gv */
5818 op = R_SS;
5819 goto do_lxx;
5820 case 0x1b4: /* lfs Gv */
5821 op = R_FS;
5822 goto do_lxx;
5823 case 0x1b5: /* lgs Gv */
5824 op = R_GS;
5825 do_lxx:
5826 ot = dflag != MO_16 ? MO_32 : MO_16;
5827 modrm = x86_ldub_code(env, s);
5828 reg = ((modrm >> 3) & 7) | REX_R(s);
5829 mod = (modrm >> 6) & 3;
5830 if (mod == 3)
5831 goto illegal_op;
5832 gen_lea_modrm(env, s, modrm);
5833 gen_op_ld_v(s, ot, s->T1, s->A0);
5834 gen_add_A0_im(s, 1 << ot);
5835 /* load the segment first to handle exceptions properly */
5836 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5837 gen_movl_seg_T0(s, op);
5838 /* then put the data */
5839 gen_op_mov_reg_v(s, ot, reg, s->T1);
5840 if (s->base.is_jmp) {
5841 gen_jmp_im(s, s->pc - s->cs_base);
5842 gen_eob(s);
5844 break;
5846 /************************/
5847 /* shifts */
5848 case 0xc0:
5849 case 0xc1:
5850 /* shift Ev,Ib */
5851 shift = 2;
5852 grp2:
5854 ot = mo_b_d(b, dflag);
5855 modrm = x86_ldub_code(env, s);
5856 mod = (modrm >> 6) & 3;
5857 op = (modrm >> 3) & 7;
5859 if (mod != 3) {
5860 if (shift == 2) {
5861 s->rip_offset = 1;
5863 gen_lea_modrm(env, s, modrm);
5864 opreg = OR_TMP0;
5865 } else {
5866 opreg = (modrm & 7) | REX_B(s);
5869 /* simpler op */
5870 if (shift == 0) {
5871 gen_shift(s, op, ot, opreg, OR_ECX);
5872 } else {
5873 if (shift == 2) {
5874 shift = x86_ldub_code(env, s);
5876 gen_shifti(s, op, ot, opreg, shift);
5879 break;
5880 case 0xd0:
5881 case 0xd1:
5882 /* shift Ev,1 */
5883 shift = 1;
5884 goto grp2;
5885 case 0xd2:
5886 case 0xd3:
5887 /* shift Ev,cl */
5888 shift = 0;
5889 goto grp2;
5891 case 0x1a4: /* shld imm */
5892 op = 0;
5893 shift = 1;
5894 goto do_shiftd;
5895 case 0x1a5: /* shld cl */
5896 op = 0;
5897 shift = 0;
5898 goto do_shiftd;
5899 case 0x1ac: /* shrd imm */
5900 op = 1;
5901 shift = 1;
5902 goto do_shiftd;
5903 case 0x1ad: /* shrd cl */
5904 op = 1;
5905 shift = 0;
5906 do_shiftd:
5907 ot = dflag;
5908 modrm = x86_ldub_code(env, s);
5909 mod = (modrm >> 6) & 3;
5910 rm = (modrm & 7) | REX_B(s);
5911 reg = ((modrm >> 3) & 7) | REX_R(s);
5912 if (mod != 3) {
5913 gen_lea_modrm(env, s, modrm);
5914 opreg = OR_TMP0;
5915 } else {
5916 opreg = rm;
5918 gen_op_mov_v_reg(s, ot, s->T1, reg);
5920 if (shift) {
5921 TCGv imm = tcg_const_tl(x86_ldub_code(env, s));
5922 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5923 tcg_temp_free(imm);
5924 } else {
5925 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5927 break;
5929 /************************/
5930 /* floats */
5931 case 0xd8 ... 0xdf:
5932 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5933 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5934 /* XXX: what to do if illegal op ? */
5935 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5936 break;
5938 modrm = x86_ldub_code(env, s);
5939 mod = (modrm >> 6) & 3;
5940 rm = modrm & 7;
5941 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5942 if (mod != 3) {
5943 /* memory op */
5944 gen_lea_modrm(env, s, modrm);
5945 switch(op) {
5946 case 0x00 ... 0x07: /* fxxxs */
5947 case 0x10 ... 0x17: /* fixxxl */
5948 case 0x20 ... 0x27: /* fxxxl */
5949 case 0x30 ... 0x37: /* fixxx */
5951 int op1;
5952 op1 = op & 7;
5954 switch(op >> 4) {
5955 case 0:
5956 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5957 s->mem_index, MO_LEUL);
5958 gen_helper_flds_FT0(cpu_env, s->tmp2_i32);
5959 break;
5960 case 1:
5961 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5962 s->mem_index, MO_LEUL);
5963 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5964 break;
5965 case 2:
5966 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5967 s->mem_index, MO_LEQ);
5968 gen_helper_fldl_FT0(cpu_env, s->tmp1_i64);
5969 break;
5970 case 3:
5971 default:
5972 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5973 s->mem_index, MO_LESW);
5974 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5975 break;
5978 gen_helper_fp_arith_ST0_FT0(op1);
5979 if (op1 == 3) {
5980 /* fcomp needs pop */
5981 gen_helper_fpop(cpu_env);
5984 break;
5985 case 0x08: /* flds */
5986 case 0x0a: /* fsts */
5987 case 0x0b: /* fstps */
5988 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5989 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5990 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5991 switch(op & 7) {
5992 case 0:
5993 switch(op >> 4) {
5994 case 0:
5995 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5996 s->mem_index, MO_LEUL);
5997 gen_helper_flds_ST0(cpu_env, s->tmp2_i32);
5998 break;
5999 case 1:
6000 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6001 s->mem_index, MO_LEUL);
6002 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
6003 break;
6004 case 2:
6005 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
6006 s->mem_index, MO_LEQ);
6007 gen_helper_fldl_ST0(cpu_env, s->tmp1_i64);
6008 break;
6009 case 3:
6010 default:
6011 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6012 s->mem_index, MO_LESW);
6013 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
6014 break;
6016 break;
6017 case 1:
6018 /* XXX: the corresponding CPUID bit must be tested ! */
6019 switch(op >> 4) {
6020 case 1:
6021 gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env);
6022 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6023 s->mem_index, MO_LEUL);
6024 break;
6025 case 2:
6026 gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env);
6027 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6028 s->mem_index, MO_LEQ);
6029 break;
6030 case 3:
6031 default:
6032 gen_helper_fistt_ST0(s->tmp2_i32, cpu_env);
6033 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6034 s->mem_index, MO_LEUW);
6035 break;
6037 gen_helper_fpop(cpu_env);
6038 break;
6039 default:
6040 switch(op >> 4) {
6041 case 0:
6042 gen_helper_fsts_ST0(s->tmp2_i32, cpu_env);
6043 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6044 s->mem_index, MO_LEUL);
6045 break;
6046 case 1:
6047 gen_helper_fistl_ST0(s->tmp2_i32, cpu_env);
6048 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6049 s->mem_index, MO_LEUL);
6050 break;
6051 case 2:
6052 gen_helper_fstl_ST0(s->tmp1_i64, cpu_env);
6053 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
6054 s->mem_index, MO_LEQ);
6055 break;
6056 case 3:
6057 default:
6058 gen_helper_fist_ST0(s->tmp2_i32, cpu_env);
6059 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6060 s->mem_index, MO_LEUW);
6061 break;
6063 if ((op & 7) == 3)
6064 gen_helper_fpop(cpu_env);
6065 break;
6067 break;
6068 case 0x0c: /* fldenv mem */
6069 gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6070 break;
6071 case 0x0d: /* fldcw mem */
6072 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
6073 s->mem_index, MO_LEUW);
6074 gen_helper_fldcw(cpu_env, s->tmp2_i32);
6075 break;
6076 case 0x0e: /* fnstenv mem */
6077 gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6078 break;
6079 case 0x0f: /* fnstcw mem */
6080 gen_helper_fnstcw(s->tmp2_i32, cpu_env);
6081 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6082 s->mem_index, MO_LEUW);
6083 break;
6084 case 0x1d: /* fldt mem */
6085 gen_helper_fldt_ST0(cpu_env, s->A0);
6086 break;
6087 case 0x1f: /* fstpt mem */
6088 gen_helper_fstt_ST0(cpu_env, s->A0);
6089 gen_helper_fpop(cpu_env);
6090 break;
6091 case 0x2c: /* frstor mem */
6092 gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6093 break;
6094 case 0x2e: /* fnsave mem */
6095 gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6096 break;
6097 case 0x2f: /* fnstsw mem */
6098 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6099 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6100 s->mem_index, MO_LEUW);
6101 break;
6102 case 0x3c: /* fbld */
6103 gen_helper_fbld_ST0(cpu_env, s->A0);
6104 break;
6105 case 0x3e: /* fbstp */
6106 gen_helper_fbst_ST0(cpu_env, s->A0);
6107 gen_helper_fpop(cpu_env);
6108 break;
6109 case 0x3d: /* fildll */
6110 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6111 gen_helper_fildll_ST0(cpu_env, s->tmp1_i64);
6112 break;
6113 case 0x3f: /* fistpll */
6114 gen_helper_fistll_ST0(s->tmp1_i64, cpu_env);
6115 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6116 gen_helper_fpop(cpu_env);
6117 break;
6118 default:
6119 goto unknown_op;
6121 } else {
6122 /* register float ops */
6123 opreg = rm;
6125 switch(op) {
6126 case 0x08: /* fld sti */
6127 gen_helper_fpush(cpu_env);
6128 gen_helper_fmov_ST0_STN(cpu_env,
6129 tcg_const_i32((opreg + 1) & 7));
6130 break;
6131 case 0x09: /* fxchg sti */
6132 case 0x29: /* fxchg4 sti, undocumented op */
6133 case 0x39: /* fxchg7 sti, undocumented op */
6134 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
6135 break;
6136 case 0x0a: /* grp d9/2 */
6137 switch(rm) {
6138 case 0: /* fnop */
6139 /* check exceptions (FreeBSD FPU probe) */
6140 gen_helper_fwait(cpu_env);
6141 break;
6142 default:
6143 goto unknown_op;
6145 break;
6146 case 0x0c: /* grp d9/4 */
6147 switch(rm) {
6148 case 0: /* fchs */
6149 gen_helper_fchs_ST0(cpu_env);
6150 break;
6151 case 1: /* fabs */
6152 gen_helper_fabs_ST0(cpu_env);
6153 break;
6154 case 4: /* ftst */
6155 gen_helper_fldz_FT0(cpu_env);
6156 gen_helper_fcom_ST0_FT0(cpu_env);
6157 break;
6158 case 5: /* fxam */
6159 gen_helper_fxam_ST0(cpu_env);
6160 break;
6161 default:
6162 goto unknown_op;
6164 break;
6165 case 0x0d: /* grp d9/5 */
6167 switch(rm) {
6168 case 0:
6169 gen_helper_fpush(cpu_env);
6170 gen_helper_fld1_ST0(cpu_env);
6171 break;
6172 case 1:
6173 gen_helper_fpush(cpu_env);
6174 gen_helper_fldl2t_ST0(cpu_env);
6175 break;
6176 case 2:
6177 gen_helper_fpush(cpu_env);
6178 gen_helper_fldl2e_ST0(cpu_env);
6179 break;
6180 case 3:
6181 gen_helper_fpush(cpu_env);
6182 gen_helper_fldpi_ST0(cpu_env);
6183 break;
6184 case 4:
6185 gen_helper_fpush(cpu_env);
6186 gen_helper_fldlg2_ST0(cpu_env);
6187 break;
6188 case 5:
6189 gen_helper_fpush(cpu_env);
6190 gen_helper_fldln2_ST0(cpu_env);
6191 break;
6192 case 6:
6193 gen_helper_fpush(cpu_env);
6194 gen_helper_fldz_ST0(cpu_env);
6195 break;
6196 default:
6197 goto unknown_op;
6200 break;
6201 case 0x0e: /* grp d9/6 */
6202 switch(rm) {
6203 case 0: /* f2xm1 */
6204 gen_helper_f2xm1(cpu_env);
6205 break;
6206 case 1: /* fyl2x */
6207 gen_helper_fyl2x(cpu_env);
6208 break;
6209 case 2: /* fptan */
6210 gen_helper_fptan(cpu_env);
6211 break;
6212 case 3: /* fpatan */
6213 gen_helper_fpatan(cpu_env);
6214 break;
6215 case 4: /* fxtract */
6216 gen_helper_fxtract(cpu_env);
6217 break;
6218 case 5: /* fprem1 */
6219 gen_helper_fprem1(cpu_env);
6220 break;
6221 case 6: /* fdecstp */
6222 gen_helper_fdecstp(cpu_env);
6223 break;
6224 default:
6225 case 7: /* fincstp */
6226 gen_helper_fincstp(cpu_env);
6227 break;
6229 break;
6230 case 0x0f: /* grp d9/7 */
6231 switch(rm) {
6232 case 0: /* fprem */
6233 gen_helper_fprem(cpu_env);
6234 break;
6235 case 1: /* fyl2xp1 */
6236 gen_helper_fyl2xp1(cpu_env);
6237 break;
6238 case 2: /* fsqrt */
6239 gen_helper_fsqrt(cpu_env);
6240 break;
6241 case 3: /* fsincos */
6242 gen_helper_fsincos(cpu_env);
6243 break;
6244 case 5: /* fscale */
6245 gen_helper_fscale(cpu_env);
6246 break;
6247 case 4: /* frndint */
6248 gen_helper_frndint(cpu_env);
6249 break;
6250 case 6: /* fsin */
6251 gen_helper_fsin(cpu_env);
6252 break;
6253 default:
6254 case 7: /* fcos */
6255 gen_helper_fcos(cpu_env);
6256 break;
6258 break;
6259 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6260 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6261 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6263 int op1;
6265 op1 = op & 7;
6266 if (op >= 0x20) {
6267 gen_helper_fp_arith_STN_ST0(op1, opreg);
6268 if (op >= 0x30)
6269 gen_helper_fpop(cpu_env);
6270 } else {
6271 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6272 gen_helper_fp_arith_ST0_FT0(op1);
6275 break;
6276 case 0x02: /* fcom */
6277 case 0x22: /* fcom2, undocumented op */
6278 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6279 gen_helper_fcom_ST0_FT0(cpu_env);
6280 break;
6281 case 0x03: /* fcomp */
6282 case 0x23: /* fcomp3, undocumented op */
6283 case 0x32: /* fcomp5, undocumented op */
6284 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6285 gen_helper_fcom_ST0_FT0(cpu_env);
6286 gen_helper_fpop(cpu_env);
6287 break;
6288 case 0x15: /* da/5 */
6289 switch(rm) {
6290 case 1: /* fucompp */
6291 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6292 gen_helper_fucom_ST0_FT0(cpu_env);
6293 gen_helper_fpop(cpu_env);
6294 gen_helper_fpop(cpu_env);
6295 break;
6296 default:
6297 goto unknown_op;
6299 break;
6300 case 0x1c:
6301 switch(rm) {
6302 case 0: /* feni (287 only, just do nop here) */
6303 break;
6304 case 1: /* fdisi (287 only, just do nop here) */
6305 break;
6306 case 2: /* fclex */
6307 gen_helper_fclex(cpu_env);
6308 break;
6309 case 3: /* fninit */
6310 gen_helper_fninit(cpu_env);
6311 break;
6312 case 4: /* fsetpm (287 only, just do nop here) */
6313 break;
6314 default:
6315 goto unknown_op;
6317 break;
6318 case 0x1d: /* fucomi */
6319 if (!(s->cpuid_features & CPUID_CMOV)) {
6320 goto illegal_op;
6322 gen_update_cc_op(s);
6323 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6324 gen_helper_fucomi_ST0_FT0(cpu_env);
6325 set_cc_op(s, CC_OP_EFLAGS);
6326 break;
6327 case 0x1e: /* fcomi */
6328 if (!(s->cpuid_features & CPUID_CMOV)) {
6329 goto illegal_op;
6331 gen_update_cc_op(s);
6332 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6333 gen_helper_fcomi_ST0_FT0(cpu_env);
6334 set_cc_op(s, CC_OP_EFLAGS);
6335 break;
6336 case 0x28: /* ffree sti */
6337 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6338 break;
6339 case 0x2a: /* fst sti */
6340 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6341 break;
6342 case 0x2b: /* fstp sti */
6343 case 0x0b: /* fstp1 sti, undocumented op */
6344 case 0x3a: /* fstp8 sti, undocumented op */
6345 case 0x3b: /* fstp9 sti, undocumented op */
6346 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6347 gen_helper_fpop(cpu_env);
6348 break;
6349 case 0x2c: /* fucom st(i) */
6350 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6351 gen_helper_fucom_ST0_FT0(cpu_env);
6352 break;
6353 case 0x2d: /* fucomp st(i) */
6354 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6355 gen_helper_fucom_ST0_FT0(cpu_env);
6356 gen_helper_fpop(cpu_env);
6357 break;
6358 case 0x33: /* de/3 */
6359 switch(rm) {
6360 case 1: /* fcompp */
6361 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6362 gen_helper_fcom_ST0_FT0(cpu_env);
6363 gen_helper_fpop(cpu_env);
6364 gen_helper_fpop(cpu_env);
6365 break;
6366 default:
6367 goto unknown_op;
6369 break;
6370 case 0x38: /* ffreep sti, undocumented op */
6371 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6372 gen_helper_fpop(cpu_env);
6373 break;
6374 case 0x3c: /* df/4 */
6375 switch(rm) {
6376 case 0:
6377 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6378 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
6379 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
6380 break;
6381 default:
6382 goto unknown_op;
6384 break;
6385 case 0x3d: /* fucomip */
6386 if (!(s->cpuid_features & CPUID_CMOV)) {
6387 goto illegal_op;
6389 gen_update_cc_op(s);
6390 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6391 gen_helper_fucomi_ST0_FT0(cpu_env);
6392 gen_helper_fpop(cpu_env);
6393 set_cc_op(s, CC_OP_EFLAGS);
6394 break;
6395 case 0x3e: /* fcomip */
6396 if (!(s->cpuid_features & CPUID_CMOV)) {
6397 goto illegal_op;
6399 gen_update_cc_op(s);
6400 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6401 gen_helper_fcomi_ST0_FT0(cpu_env);
6402 gen_helper_fpop(cpu_env);
6403 set_cc_op(s, CC_OP_EFLAGS);
6404 break;
6405 case 0x10 ... 0x13: /* fcmovxx */
6406 case 0x18 ... 0x1b:
6408 int op1;
6409 TCGLabel *l1;
6410 static const uint8_t fcmov_cc[8] = {
6411 (JCC_B << 1),
6412 (JCC_Z << 1),
6413 (JCC_BE << 1),
6414 (JCC_P << 1),
6417 if (!(s->cpuid_features & CPUID_CMOV)) {
6418 goto illegal_op;
6420 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6421 l1 = gen_new_label();
6422 gen_jcc1_noeob(s, op1, l1);
6423 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6424 gen_set_label(l1);
6426 break;
6427 default:
6428 goto unknown_op;
6431 break;
6432 /************************/
6433 /* string ops */
6435 case 0xa4: /* movsS */
6436 case 0xa5:
6437 ot = mo_b_d(b, dflag);
6438 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6439 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6440 } else {
6441 gen_movs(s, ot);
6443 break;
6445 case 0xaa: /* stosS */
6446 case 0xab:
6447 ot = mo_b_d(b, dflag);
6448 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6449 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6450 } else {
6451 gen_stos(s, ot);
6453 break;
6454 case 0xac: /* lodsS */
6455 case 0xad:
6456 ot = mo_b_d(b, dflag);
6457 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6458 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6459 } else {
6460 gen_lods(s, ot);
6462 break;
6463 case 0xae: /* scasS */
6464 case 0xaf:
6465 ot = mo_b_d(b, dflag);
6466 if (prefixes & PREFIX_REPNZ) {
6467 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6468 } else if (prefixes & PREFIX_REPZ) {
6469 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6470 } else {
6471 gen_scas(s, ot);
6473 break;
6475 case 0xa6: /* cmpsS */
6476 case 0xa7:
6477 ot = mo_b_d(b, dflag);
6478 if (prefixes & PREFIX_REPNZ) {
6479 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6480 } else if (prefixes & PREFIX_REPZ) {
6481 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6482 } else {
6483 gen_cmps(s, ot);
6485 break;
6486 case 0x6c: /* insS */
6487 case 0x6d:
6488 ot = mo_b_d32(b, dflag);
6489 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
6490 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
6491 if (!gen_check_io(s, ot, s->tmp2_i32,
6492 SVM_IOIO_TYPE_MASK | SVM_IOIO_STR_MASK)) {
6493 break;
6495 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6496 gen_io_start();
6498 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6499 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6500 /* jump generated by gen_repz_ins */
6501 } else {
6502 gen_ins(s, ot);
6503 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6504 gen_jmp(s, s->pc - s->cs_base);
6507 break;
6508 case 0x6e: /* outsS */
6509 case 0x6f:
6510 ot = mo_b_d32(b, dflag);
6511 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
6512 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
6513 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_STR_MASK)) {
6514 break;
6516 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6517 gen_io_start();
6519 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6520 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6521 /* jump generated by gen_repz_outs */
6522 } else {
6523 gen_outs(s, ot);
6524 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6525 gen_jmp(s, s->pc - s->cs_base);
6528 break;
6530 /************************/
6531 /* port I/O */
6533 case 0xe4:
6534 case 0xe5:
6535 ot = mo_b_d32(b, dflag);
6536 val = x86_ldub_code(env, s);
6537 tcg_gen_movi_i32(s->tmp2_i32, val);
6538 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) {
6539 break;
6541 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6542 gen_io_start();
6544 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6545 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6546 gen_bpt_io(s, s->tmp2_i32, ot);
6547 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6548 gen_jmp(s, s->pc - s->cs_base);
6550 break;
6551 case 0xe6:
6552 case 0xe7:
6553 ot = mo_b_d32(b, dflag);
6554 val = x86_ldub_code(env, s);
6555 tcg_gen_movi_i32(s->tmp2_i32, val);
6556 if (!gen_check_io(s, ot, s->tmp2_i32, 0)) {
6557 break;
6559 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6560 gen_io_start();
6562 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6563 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6564 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6565 gen_bpt_io(s, s->tmp2_i32, ot);
6566 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6567 gen_jmp(s, s->pc - s->cs_base);
6569 break;
6570 case 0xec:
6571 case 0xed:
6572 ot = mo_b_d32(b, dflag);
6573 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
6574 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
6575 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) {
6576 break;
6578 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6579 gen_io_start();
6581 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6582 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6583 gen_bpt_io(s, s->tmp2_i32, ot);
6584 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6585 gen_jmp(s, s->pc - s->cs_base);
6587 break;
6588 case 0xee:
6589 case 0xef:
6590 ot = mo_b_d32(b, dflag);
6591 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
6592 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
6593 if (!gen_check_io(s, ot, s->tmp2_i32, 0)) {
6594 break;
6596 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6597 gen_io_start();
6599 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6600 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6601 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6602 gen_bpt_io(s, s->tmp2_i32, ot);
6603 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6604 gen_jmp(s, s->pc - s->cs_base);
6606 break;
6608 /************************/
6609 /* control */
6610 case 0xc2: /* ret im */
6611 val = x86_ldsw_code(env, s);
6612 ot = gen_pop_T0(s);
6613 gen_stack_update(s, val + (1 << ot));
6614 /* Note that gen_pop_T0 uses a zero-extending load. */
6615 gen_op_jmp_v(s->T0);
6616 gen_bnd_jmp(s);
6617 gen_jr(s, s->T0);
6618 break;
6619 case 0xc3: /* ret */
6620 ot = gen_pop_T0(s);
6621 gen_pop_update(s, ot);
6622 /* Note that gen_pop_T0 uses a zero-extending load. */
6623 gen_op_jmp_v(s->T0);
6624 gen_bnd_jmp(s);
6625 gen_jr(s, s->T0);
6626 break;
6627 case 0xca: /* lret im */
6628 val = x86_ldsw_code(env, s);
6629 do_lret:
6630 if (PE(s) && !VM86(s)) {
6631 gen_update_cc_op(s);
6632 gen_jmp_im(s, pc_start - s->cs_base);
6633 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6634 tcg_const_i32(val));
6635 } else {
6636 gen_stack_A0(s);
6637 /* pop offset */
6638 gen_op_ld_v(s, dflag, s->T0, s->A0);
6639 /* NOTE: keeping EIP updated is not a problem in case of
6640 exception */
6641 gen_op_jmp_v(s->T0);
6642 /* pop selector */
6643 gen_add_A0_im(s, 1 << dflag);
6644 gen_op_ld_v(s, dflag, s->T0, s->A0);
6645 gen_op_movl_seg_T0_vm(s, R_CS);
6646 /* add stack offset */
6647 gen_stack_update(s, val + (2 << dflag));
6649 gen_eob(s);
6650 break;
6651 case 0xcb: /* lret */
6652 val = 0;
6653 goto do_lret;
6654 case 0xcf: /* iret */
6655 gen_svm_check_intercept(s, SVM_EXIT_IRET);
6656 if (!PE(s) || VM86(s)) {
6657 /* real mode or vm86 mode */
6658 if (!check_vm86_iopl(s)) {
6659 break;
6661 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6662 } else {
6663 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6664 tcg_const_i32(s->pc - s->cs_base));
6666 set_cc_op(s, CC_OP_EFLAGS);
6667 gen_eob(s);
6668 break;
6669 case 0xe8: /* call im */
6671 if (dflag != MO_16) {
6672 tval = (int32_t)insn_get(env, s, MO_32);
6673 } else {
6674 tval = (int16_t)insn_get(env, s, MO_16);
6676 next_eip = s->pc - s->cs_base;
6677 tval += next_eip;
6678 if (dflag == MO_16) {
6679 tval &= 0xffff;
6680 } else if (!CODE64(s)) {
6681 tval &= 0xffffffff;
6683 tcg_gen_movi_tl(s->T0, next_eip);
6684 gen_push_v(s, s->T0);
6685 gen_bnd_jmp(s);
6686 gen_jmp(s, tval);
6688 break;
6689 case 0x9a: /* lcall im */
6691 unsigned int selector, offset;
6693 if (CODE64(s))
6694 goto illegal_op;
6695 ot = dflag;
6696 offset = insn_get(env, s, ot);
6697 selector = insn_get(env, s, MO_16);
6699 tcg_gen_movi_tl(s->T0, selector);
6700 tcg_gen_movi_tl(s->T1, offset);
6702 goto do_lcall;
6703 case 0xe9: /* jmp im */
6704 if (dflag != MO_16) {
6705 tval = (int32_t)insn_get(env, s, MO_32);
6706 } else {
6707 tval = (int16_t)insn_get(env, s, MO_16);
6709 tval += s->pc - s->cs_base;
6710 if (dflag == MO_16) {
6711 tval &= 0xffff;
6712 } else if (!CODE64(s)) {
6713 tval &= 0xffffffff;
6715 gen_bnd_jmp(s);
6716 gen_jmp(s, tval);
6717 break;
6718 case 0xea: /* ljmp im */
6720 unsigned int selector, offset;
6722 if (CODE64(s))
6723 goto illegal_op;
6724 ot = dflag;
6725 offset = insn_get(env, s, ot);
6726 selector = insn_get(env, s, MO_16);
6728 tcg_gen_movi_tl(s->T0, selector);
6729 tcg_gen_movi_tl(s->T1, offset);
6731 goto do_ljmp;
6732 case 0xeb: /* jmp Jb */
6733 tval = (int8_t)insn_get(env, s, MO_8);
6734 tval += s->pc - s->cs_base;
6735 if (dflag == MO_16) {
6736 tval &= 0xffff;
6738 gen_jmp(s, tval);
6739 break;
6740 case 0x70 ... 0x7f: /* jcc Jb */
6741 tval = (int8_t)insn_get(env, s, MO_8);
6742 goto do_jcc;
6743 case 0x180 ... 0x18f: /* jcc Jv */
6744 if (dflag != MO_16) {
6745 tval = (int32_t)insn_get(env, s, MO_32);
6746 } else {
6747 tval = (int16_t)insn_get(env, s, MO_16);
6749 do_jcc:
6750 next_eip = s->pc - s->cs_base;
6751 tval += next_eip;
6752 if (dflag == MO_16) {
6753 tval &= 0xffff;
6755 gen_bnd_jmp(s);
6756 gen_jcc(s, b, tval, next_eip);
6757 break;
6759 case 0x190 ... 0x19f: /* setcc Gv */
6760 modrm = x86_ldub_code(env, s);
6761 gen_setcc1(s, b, s->T0);
6762 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6763 break;
6764 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6765 if (!(s->cpuid_features & CPUID_CMOV)) {
6766 goto illegal_op;
6768 ot = dflag;
6769 modrm = x86_ldub_code(env, s);
6770 reg = ((modrm >> 3) & 7) | REX_R(s);
6771 gen_cmovcc1(env, s, ot, b, modrm, reg);
6772 break;
6774 /************************/
6775 /* flags */
6776 case 0x9c: /* pushf */
6777 gen_svm_check_intercept(s, SVM_EXIT_PUSHF);
6778 if (check_vm86_iopl(s)) {
6779 gen_update_cc_op(s);
6780 gen_helper_read_eflags(s->T0, cpu_env);
6781 gen_push_v(s, s->T0);
6783 break;
6784 case 0x9d: /* popf */
6785 gen_svm_check_intercept(s, SVM_EXIT_POPF);
6786 if (check_vm86_iopl(s)) {
6787 ot = gen_pop_T0(s);
6788 if (CPL(s) == 0) {
6789 if (dflag != MO_16) {
6790 gen_helper_write_eflags(cpu_env, s->T0,
6791 tcg_const_i32((TF_MASK | AC_MASK |
6792 ID_MASK | NT_MASK |
6793 IF_MASK |
6794 IOPL_MASK)));
6795 } else {
6796 gen_helper_write_eflags(cpu_env, s->T0,
6797 tcg_const_i32((TF_MASK | AC_MASK |
6798 ID_MASK | NT_MASK |
6799 IF_MASK | IOPL_MASK)
6800 & 0xffff));
6802 } else {
6803 if (CPL(s) <= IOPL(s)) {
6804 if (dflag != MO_16) {
6805 gen_helper_write_eflags(cpu_env, s->T0,
6806 tcg_const_i32((TF_MASK |
6807 AC_MASK |
6808 ID_MASK |
6809 NT_MASK |
6810 IF_MASK)));
6811 } else {
6812 gen_helper_write_eflags(cpu_env, s->T0,
6813 tcg_const_i32((TF_MASK |
6814 AC_MASK |
6815 ID_MASK |
6816 NT_MASK |
6817 IF_MASK)
6818 & 0xffff));
6820 } else {
6821 if (dflag != MO_16) {
6822 gen_helper_write_eflags(cpu_env, s->T0,
6823 tcg_const_i32((TF_MASK | AC_MASK |
6824 ID_MASK | NT_MASK)));
6825 } else {
6826 gen_helper_write_eflags(cpu_env, s->T0,
6827 tcg_const_i32((TF_MASK | AC_MASK |
6828 ID_MASK | NT_MASK)
6829 & 0xffff));
6833 gen_pop_update(s, ot);
6834 set_cc_op(s, CC_OP_EFLAGS);
6835 /* abort translation because TF/AC flag may change */
6836 gen_jmp_im(s, s->pc - s->cs_base);
6837 gen_eob(s);
6839 break;
6840 case 0x9e: /* sahf */
6841 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6842 goto illegal_op;
6843 gen_op_mov_v_reg(s, MO_8, s->T0, R_AH);
6844 gen_compute_eflags(s);
6845 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6846 tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6847 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
6848 break;
6849 case 0x9f: /* lahf */
6850 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6851 goto illegal_op;
6852 gen_compute_eflags(s);
6853 /* Note: gen_compute_eflags() only gives the condition codes */
6854 tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02);
6855 gen_op_mov_reg_v(s, MO_8, R_AH, s->T0);
6856 break;
6857 case 0xf5: /* cmc */
6858 gen_compute_eflags(s);
6859 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6860 break;
6861 case 0xf8: /* clc */
6862 gen_compute_eflags(s);
6863 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6864 break;
6865 case 0xf9: /* stc */
6866 gen_compute_eflags(s);
6867 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6868 break;
6869 case 0xfc: /* cld */
6870 tcg_gen_movi_i32(s->tmp2_i32, 1);
6871 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6872 break;
6873 case 0xfd: /* std */
6874 tcg_gen_movi_i32(s->tmp2_i32, -1);
6875 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6876 break;
6878 /************************/
6879 /* bit operations */
6880 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6881 ot = dflag;
6882 modrm = x86_ldub_code(env, s);
6883 op = (modrm >> 3) & 7;
6884 mod = (modrm >> 6) & 3;
6885 rm = (modrm & 7) | REX_B(s);
6886 if (mod != 3) {
6887 s->rip_offset = 1;
6888 gen_lea_modrm(env, s, modrm);
6889 if (!(s->prefix & PREFIX_LOCK)) {
6890 gen_op_ld_v(s, ot, s->T0, s->A0);
6892 } else {
6893 gen_op_mov_v_reg(s, ot, s->T0, rm);
6895 /* load shift */
6896 val = x86_ldub_code(env, s);
6897 tcg_gen_movi_tl(s->T1, val);
6898 if (op < 4)
6899 goto unknown_op;
6900 op -= 4;
6901 goto bt_op;
6902 case 0x1a3: /* bt Gv, Ev */
6903 op = 0;
6904 goto do_btx;
6905 case 0x1ab: /* bts */
6906 op = 1;
6907 goto do_btx;
6908 case 0x1b3: /* btr */
6909 op = 2;
6910 goto do_btx;
6911 case 0x1bb: /* btc */
6912 op = 3;
6913 do_btx:
6914 ot = dflag;
6915 modrm = x86_ldub_code(env, s);
6916 reg = ((modrm >> 3) & 7) | REX_R(s);
6917 mod = (modrm >> 6) & 3;
6918 rm = (modrm & 7) | REX_B(s);
6919 gen_op_mov_v_reg(s, MO_32, s->T1, reg);
6920 if (mod != 3) {
6921 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6922 /* specific case: we need to add a displacement */
6923 gen_exts(ot, s->T1);
6924 tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
6925 tcg_gen_shli_tl(s->tmp0, s->tmp0, ot);
6926 tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a), s->tmp0);
6927 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
6928 if (!(s->prefix & PREFIX_LOCK)) {
6929 gen_op_ld_v(s, ot, s->T0, s->A0);
6931 } else {
6932 gen_op_mov_v_reg(s, ot, s->T0, rm);
6934 bt_op:
6935 tcg_gen_andi_tl(s->T1, s->T1, (1 << (3 + ot)) - 1);
6936 tcg_gen_movi_tl(s->tmp0, 1);
6937 tcg_gen_shl_tl(s->tmp0, s->tmp0, s->T1);
6938 if (s->prefix & PREFIX_LOCK) {
6939 switch (op) {
6940 case 0: /* bt */
6941 /* Needs no atomic ops; we surpressed the normal
6942 memory load for LOCK above so do it now. */
6943 gen_op_ld_v(s, ot, s->T0, s->A0);
6944 break;
6945 case 1: /* bts */
6946 tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, s->tmp0,
6947 s->mem_index, ot | MO_LE);
6948 break;
6949 case 2: /* btr */
6950 tcg_gen_not_tl(s->tmp0, s->tmp0);
6951 tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, s->tmp0,
6952 s->mem_index, ot | MO_LE);
6953 break;
6954 default:
6955 case 3: /* btc */
6956 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0,
6957 s->mem_index, ot | MO_LE);
6958 break;
6960 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6961 } else {
6962 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6963 switch (op) {
6964 case 0: /* bt */
6965 /* Data already loaded; nothing to do. */
6966 break;
6967 case 1: /* bts */
6968 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
6969 break;
6970 case 2: /* btr */
6971 tcg_gen_andc_tl(s->T0, s->T0, s->tmp0);
6972 break;
6973 default:
6974 case 3: /* btc */
6975 tcg_gen_xor_tl(s->T0, s->T0, s->tmp0);
6976 break;
6978 if (op != 0) {
6979 if (mod != 3) {
6980 gen_op_st_v(s, ot, s->T0, s->A0);
6981 } else {
6982 gen_op_mov_reg_v(s, ot, rm, s->T0);
6987 /* Delay all CC updates until after the store above. Note that
6988 C is the result of the test, Z is unchanged, and the others
6989 are all undefined. */
6990 switch (s->cc_op) {
6991 case CC_OP_MULB ... CC_OP_MULQ:
6992 case CC_OP_ADDB ... CC_OP_ADDQ:
6993 case CC_OP_ADCB ... CC_OP_ADCQ:
6994 case CC_OP_SUBB ... CC_OP_SUBQ:
6995 case CC_OP_SBBB ... CC_OP_SBBQ:
6996 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6997 case CC_OP_INCB ... CC_OP_INCQ:
6998 case CC_OP_DECB ... CC_OP_DECQ:
6999 case CC_OP_SHLB ... CC_OP_SHLQ:
7000 case CC_OP_SARB ... CC_OP_SARQ:
7001 case CC_OP_BMILGB ... CC_OP_BMILGQ:
7002 /* Z was going to be computed from the non-zero status of CC_DST.
7003 We can get that same Z value (and the new C value) by leaving
7004 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
7005 same width. */
7006 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
7007 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
7008 break;
7009 default:
7010 /* Otherwise, generate EFLAGS and replace the C bit. */
7011 gen_compute_eflags(s);
7012 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, s->tmp4,
7013 ctz32(CC_C), 1);
7014 break;
7016 break;
7017 case 0x1bc: /* bsf / tzcnt */
7018 case 0x1bd: /* bsr / lzcnt */
7019 ot = dflag;
7020 modrm = x86_ldub_code(env, s);
7021 reg = ((modrm >> 3) & 7) | REX_R(s);
7022 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7023 gen_extu(ot, s->T0);
7025 /* Note that lzcnt and tzcnt are in different extensions. */
7026 if ((prefixes & PREFIX_REPZ)
7027 && (b & 1
7028 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
7029 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
7030 int size = 8 << ot;
7031 /* For lzcnt/tzcnt, C bit is defined related to the input. */
7032 tcg_gen_mov_tl(cpu_cc_src, s->T0);
7033 if (b & 1) {
7034 /* For lzcnt, reduce the target_ulong result by the
7035 number of zeros that we expect to find at the top. */
7036 tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
7037 tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
7038 } else {
7039 /* For tzcnt, a zero input must return the operand size. */
7040 tcg_gen_ctzi_tl(s->T0, s->T0, size);
7042 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
7043 gen_op_update1_cc(s);
7044 set_cc_op(s, CC_OP_BMILGB + ot);
7045 } else {
7046 /* For bsr/bsf, only the Z bit is defined and it is related
7047 to the input and not the result. */
7048 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
7049 set_cc_op(s, CC_OP_LOGICB + ot);
7051 /* ??? The manual says that the output is undefined when the
7052 input is zero, but real hardware leaves it unchanged, and
7053 real programs appear to depend on that. Accomplish this
7054 by passing the output as the value to return upon zero. */
7055 if (b & 1) {
7056 /* For bsr, return the bit index of the first 1 bit,
7057 not the count of leading zeros. */
7058 tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
7059 tcg_gen_clz_tl(s->T0, s->T0, s->T1);
7060 tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
7061 } else {
7062 tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
7065 gen_op_mov_reg_v(s, ot, reg, s->T0);
7066 break;
7067 /************************/
7068 /* bcd */
7069 case 0x27: /* daa */
7070 if (CODE64(s))
7071 goto illegal_op;
7072 gen_update_cc_op(s);
7073 gen_helper_daa(cpu_env);
7074 set_cc_op(s, CC_OP_EFLAGS);
7075 break;
7076 case 0x2f: /* das */
7077 if (CODE64(s))
7078 goto illegal_op;
7079 gen_update_cc_op(s);
7080 gen_helper_das(cpu_env);
7081 set_cc_op(s, CC_OP_EFLAGS);
7082 break;
7083 case 0x37: /* aaa */
7084 if (CODE64(s))
7085 goto illegal_op;
7086 gen_update_cc_op(s);
7087 gen_helper_aaa(cpu_env);
7088 set_cc_op(s, CC_OP_EFLAGS);
7089 break;
7090 case 0x3f: /* aas */
7091 if (CODE64(s))
7092 goto illegal_op;
7093 gen_update_cc_op(s);
7094 gen_helper_aas(cpu_env);
7095 set_cc_op(s, CC_OP_EFLAGS);
7096 break;
7097 case 0xd4: /* aam */
7098 if (CODE64(s))
7099 goto illegal_op;
7100 val = x86_ldub_code(env, s);
7101 if (val == 0) {
7102 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7103 } else {
7104 gen_helper_aam(cpu_env, tcg_const_i32(val));
7105 set_cc_op(s, CC_OP_LOGICB);
7107 break;
7108 case 0xd5: /* aad */
7109 if (CODE64(s))
7110 goto illegal_op;
7111 val = x86_ldub_code(env, s);
7112 gen_helper_aad(cpu_env, tcg_const_i32(val));
7113 set_cc_op(s, CC_OP_LOGICB);
7114 break;
7115 /************************/
7116 /* misc */
7117 case 0x90: /* nop */
7118 /* XXX: correct lock test for all insn */
7119 if (prefixes & PREFIX_LOCK) {
7120 goto illegal_op;
7122 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
7123 if (REX_B(s)) {
7124 goto do_xchg_reg_eax;
7126 if (prefixes & PREFIX_REPZ) {
7127 gen_update_cc_op(s);
7128 gen_jmp_im(s, pc_start - s->cs_base);
7129 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
7130 s->base.is_jmp = DISAS_NORETURN;
7132 break;
7133 case 0x9b: /* fwait */
7134 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7135 (HF_MP_MASK | HF_TS_MASK)) {
7136 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7137 } else {
7138 gen_helper_fwait(cpu_env);
7140 break;
7141 case 0xcc: /* int3 */
7142 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7143 break;
7144 case 0xcd: /* int N */
7145 val = x86_ldub_code(env, s);
7146 if (check_vm86_iopl(s)) {
7147 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7149 break;
7150 case 0xce: /* into */
7151 if (CODE64(s))
7152 goto illegal_op;
7153 gen_update_cc_op(s);
7154 gen_jmp_im(s, pc_start - s->cs_base);
7155 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
7156 break;
7157 #ifdef WANT_ICEBP
7158 case 0xf1: /* icebp (undocumented, exits to external debugger) */
7159 gen_svm_check_intercept(s, SVM_EXIT_ICEBP);
7160 gen_debug(s);
7161 break;
7162 #endif
7163 case 0xfa: /* cli */
7164 if (check_iopl(s)) {
7165 gen_helper_cli(cpu_env);
7167 break;
7168 case 0xfb: /* sti */
7169 if (check_iopl(s)) {
7170 gen_helper_sti(cpu_env);
7171 /* interruptions are enabled only the first insn after sti */
7172 gen_jmp_im(s, s->pc - s->cs_base);
7173 gen_eob_inhibit_irq(s, true);
7175 break;
7176 case 0x62: /* bound */
7177 if (CODE64(s))
7178 goto illegal_op;
7179 ot = dflag;
7180 modrm = x86_ldub_code(env, s);
7181 reg = (modrm >> 3) & 7;
7182 mod = (modrm >> 6) & 3;
7183 if (mod == 3)
7184 goto illegal_op;
7185 gen_op_mov_v_reg(s, ot, s->T0, reg);
7186 gen_lea_modrm(env, s, modrm);
7187 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7188 if (ot == MO_16) {
7189 gen_helper_boundw(cpu_env, s->A0, s->tmp2_i32);
7190 } else {
7191 gen_helper_boundl(cpu_env, s->A0, s->tmp2_i32);
7193 break;
7194 case 0x1c8 ... 0x1cf: /* bswap reg */
7195 reg = (b & 7) | REX_B(s);
7196 #ifdef TARGET_X86_64
7197 if (dflag == MO_64) {
7198 gen_op_mov_v_reg(s, MO_64, s->T0, reg);
7199 tcg_gen_bswap64_i64(s->T0, s->T0);
7200 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
7201 } else
7202 #endif
7204 gen_op_mov_v_reg(s, MO_32, s->T0, reg);
7205 tcg_gen_ext32u_tl(s->T0, s->T0);
7206 tcg_gen_bswap32_tl(s->T0, s->T0);
7207 gen_op_mov_reg_v(s, MO_32, reg, s->T0);
7209 break;
7210 case 0xd6: /* salc */
7211 if (CODE64(s))
7212 goto illegal_op;
7213 gen_compute_eflags_c(s, s->T0);
7214 tcg_gen_neg_tl(s->T0, s->T0);
7215 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
7216 break;
7217 case 0xe0: /* loopnz */
7218 case 0xe1: /* loopz */
7219 case 0xe2: /* loop */
7220 case 0xe3: /* jecxz */
7222 TCGLabel *l1, *l2, *l3;
7224 tval = (int8_t)insn_get(env, s, MO_8);
7225 next_eip = s->pc - s->cs_base;
7226 tval += next_eip;
7227 if (dflag == MO_16) {
7228 tval &= 0xffff;
7231 l1 = gen_new_label();
7232 l2 = gen_new_label();
7233 l3 = gen_new_label();
7234 gen_update_cc_op(s);
7235 b &= 3;
7236 switch(b) {
7237 case 0: /* loopnz */
7238 case 1: /* loopz */
7239 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7240 gen_op_jz_ecx(s, s->aflag, l3);
7241 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7242 break;
7243 case 2: /* loop */
7244 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7245 gen_op_jnz_ecx(s, s->aflag, l1);
7246 break;
7247 default:
7248 case 3: /* jcxz */
7249 gen_op_jz_ecx(s, s->aflag, l1);
7250 break;
7253 gen_set_label(l3);
7254 gen_jmp_im(s, next_eip);
7255 tcg_gen_br(l2);
7257 gen_set_label(l1);
7258 gen_jmp_im(s, tval);
7259 gen_set_label(l2);
7260 gen_eob(s);
7262 break;
7263 case 0x130: /* wrmsr */
7264 case 0x132: /* rdmsr */
7265 if (check_cpl0(s)) {
7266 gen_update_cc_op(s);
7267 gen_jmp_im(s, pc_start - s->cs_base);
7268 if (b & 2) {
7269 gen_helper_rdmsr(cpu_env);
7270 } else {
7271 gen_helper_wrmsr(cpu_env);
7272 gen_jmp_im(s, s->pc - s->cs_base);
7273 gen_eob(s);
7276 break;
7277 case 0x131: /* rdtsc */
7278 gen_update_cc_op(s);
7279 gen_jmp_im(s, pc_start - s->cs_base);
7280 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7281 gen_io_start();
7283 gen_helper_rdtsc(cpu_env);
7284 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7285 gen_jmp(s, s->pc - s->cs_base);
7287 break;
7288 case 0x133: /* rdpmc */
7289 gen_update_cc_op(s);
7290 gen_jmp_im(s, pc_start - s->cs_base);
7291 gen_helper_rdpmc(cpu_env);
7292 s->base.is_jmp = DISAS_NORETURN;
7293 break;
7294 case 0x134: /* sysenter */
7295 /* For Intel SYSENTER is valid on 64-bit */
7296 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7297 goto illegal_op;
7298 if (!PE(s)) {
7299 gen_exception_gpf(s);
7300 } else {
7301 gen_helper_sysenter(cpu_env);
7302 gen_eob(s);
7304 break;
7305 case 0x135: /* sysexit */
7306 /* For Intel SYSEXIT is valid on 64-bit */
7307 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7308 goto illegal_op;
7309 if (!PE(s)) {
7310 gen_exception_gpf(s);
7311 } else {
7312 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7313 gen_eob(s);
7315 break;
7316 #ifdef TARGET_X86_64
7317 case 0x105: /* syscall */
7318 /* XXX: is it usable in real mode ? */
7319 gen_update_cc_op(s);
7320 gen_jmp_im(s, pc_start - s->cs_base);
7321 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7322 /* TF handling for the syscall insn is different. The TF bit is checked
7323 after the syscall insn completes. This allows #DB to not be
7324 generated after one has entered CPL0 if TF is set in FMASK. */
7325 gen_eob_worker(s, false, true);
7326 break;
7327 case 0x107: /* sysret */
7328 if (!PE(s)) {
7329 gen_exception_gpf(s);
7330 } else {
7331 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7332 /* condition codes are modified only in long mode */
7333 if (LMA(s)) {
7334 set_cc_op(s, CC_OP_EFLAGS);
7336 /* TF handling for the sysret insn is different. The TF bit is
7337 checked after the sysret insn completes. This allows #DB to be
7338 generated "as if" the syscall insn in userspace has just
7339 completed. */
7340 gen_eob_worker(s, false, true);
7342 break;
7343 #endif
7344 case 0x1a2: /* cpuid */
7345 gen_update_cc_op(s);
7346 gen_jmp_im(s, pc_start - s->cs_base);
7347 gen_helper_cpuid(cpu_env);
7348 break;
7349 case 0xf4: /* hlt */
7350 if (check_cpl0(s)) {
7351 gen_update_cc_op(s);
7352 gen_jmp_im(s, pc_start - s->cs_base);
7353 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7354 s->base.is_jmp = DISAS_NORETURN;
7356 break;
7357 case 0x100:
7358 modrm = x86_ldub_code(env, s);
7359 mod = (modrm >> 6) & 3;
7360 op = (modrm >> 3) & 7;
7361 switch(op) {
7362 case 0: /* sldt */
7363 if (!PE(s) || VM86(s))
7364 goto illegal_op;
7365 gen_svm_check_intercept(s, SVM_EXIT_LDTR_READ);
7366 tcg_gen_ld32u_tl(s->T0, cpu_env,
7367 offsetof(CPUX86State, ldt.selector));
7368 ot = mod == 3 ? dflag : MO_16;
7369 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7370 break;
7371 case 2: /* lldt */
7372 if (!PE(s) || VM86(s))
7373 goto illegal_op;
7374 if (check_cpl0(s)) {
7375 gen_svm_check_intercept(s, SVM_EXIT_LDTR_WRITE);
7376 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7377 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7378 gen_helper_lldt(cpu_env, s->tmp2_i32);
7380 break;
7381 case 1: /* str */
7382 if (!PE(s) || VM86(s))
7383 goto illegal_op;
7384 gen_svm_check_intercept(s, SVM_EXIT_TR_READ);
7385 tcg_gen_ld32u_tl(s->T0, cpu_env,
7386 offsetof(CPUX86State, tr.selector));
7387 ot = mod == 3 ? dflag : MO_16;
7388 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7389 break;
7390 case 3: /* ltr */
7391 if (!PE(s) || VM86(s))
7392 goto illegal_op;
7393 if (check_cpl0(s)) {
7394 gen_svm_check_intercept(s, SVM_EXIT_TR_WRITE);
7395 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7396 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7397 gen_helper_ltr(cpu_env, s->tmp2_i32);
7399 break;
7400 case 4: /* verr */
7401 case 5: /* verw */
7402 if (!PE(s) || VM86(s))
7403 goto illegal_op;
7404 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7405 gen_update_cc_op(s);
7406 if (op == 4) {
7407 gen_helper_verr(cpu_env, s->T0);
7408 } else {
7409 gen_helper_verw(cpu_env, s->T0);
7411 set_cc_op(s, CC_OP_EFLAGS);
7412 break;
7413 default:
7414 goto unknown_op;
7416 break;
7418 case 0x101:
7419 modrm = x86_ldub_code(env, s);
7420 switch (modrm) {
7421 CASE_MODRM_MEM_OP(0): /* sgdt */
7422 gen_svm_check_intercept(s, SVM_EXIT_GDTR_READ);
7423 gen_lea_modrm(env, s, modrm);
7424 tcg_gen_ld32u_tl(s->T0,
7425 cpu_env, offsetof(CPUX86State, gdt.limit));
7426 gen_op_st_v(s, MO_16, s->T0, s->A0);
7427 gen_add_A0_im(s, 2);
7428 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7429 if (dflag == MO_16) {
7430 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7432 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7433 break;
7435 case 0xc8: /* monitor */
7436 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
7437 goto illegal_op;
7439 gen_update_cc_op(s);
7440 gen_jmp_im(s, pc_start - s->cs_base);
7441 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7442 gen_extu(s->aflag, s->A0);
7443 gen_add_A0_ds_seg(s);
7444 gen_helper_monitor(cpu_env, s->A0);
7445 break;
7447 case 0xc9: /* mwait */
7448 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
7449 goto illegal_op;
7451 gen_update_cc_op(s);
7452 gen_jmp_im(s, pc_start - s->cs_base);
7453 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7454 s->base.is_jmp = DISAS_NORETURN;
7455 break;
7457 case 0xca: /* clac */
7458 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7459 || CPL(s) != 0) {
7460 goto illegal_op;
7462 gen_helper_clac(cpu_env);
7463 gen_jmp_im(s, s->pc - s->cs_base);
7464 gen_eob(s);
7465 break;
7467 case 0xcb: /* stac */
7468 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7469 || CPL(s) != 0) {
7470 goto illegal_op;
7472 gen_helper_stac(cpu_env);
7473 gen_jmp_im(s, s->pc - s->cs_base);
7474 gen_eob(s);
7475 break;
7477 CASE_MODRM_MEM_OP(1): /* sidt */
7478 gen_svm_check_intercept(s, SVM_EXIT_IDTR_READ);
7479 gen_lea_modrm(env, s, modrm);
7480 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit));
7481 gen_op_st_v(s, MO_16, s->T0, s->A0);
7482 gen_add_A0_im(s, 2);
7483 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7484 if (dflag == MO_16) {
7485 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7487 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7488 break;
7490 case 0xd0: /* xgetbv */
7491 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7492 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7493 | PREFIX_REPZ | PREFIX_REPNZ))) {
7494 goto illegal_op;
7496 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7497 gen_helper_xgetbv(s->tmp1_i64, cpu_env, s->tmp2_i32);
7498 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7499 break;
7501 case 0xd1: /* xsetbv */
7502 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7503 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7504 | PREFIX_REPZ | PREFIX_REPNZ))) {
7505 goto illegal_op;
7507 if (!check_cpl0(s)) {
7508 break;
7510 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7511 cpu_regs[R_EDX]);
7512 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7513 gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
7514 /* End TB because translation flags may change. */
7515 gen_jmp_im(s, s->pc - s->cs_base);
7516 gen_eob(s);
7517 break;
7519 case 0xd8: /* VMRUN */
7520 if (!SVME(s) || !PE(s)) {
7521 goto illegal_op;
7523 if (!check_cpl0(s)) {
7524 break;
7526 gen_update_cc_op(s);
7527 gen_jmp_im(s, pc_start - s->cs_base);
7528 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7529 tcg_const_i32(s->pc - pc_start));
7530 tcg_gen_exit_tb(NULL, 0);
7531 s->base.is_jmp = DISAS_NORETURN;
7532 break;
7534 case 0xd9: /* VMMCALL */
7535 if (!SVME(s)) {
7536 goto illegal_op;
7538 gen_update_cc_op(s);
7539 gen_jmp_im(s, pc_start - s->cs_base);
7540 gen_helper_vmmcall(cpu_env);
7541 break;
7543 case 0xda: /* VMLOAD */
7544 if (!SVME(s) || !PE(s)) {
7545 goto illegal_op;
7547 if (!check_cpl0(s)) {
7548 break;
7550 gen_update_cc_op(s);
7551 gen_jmp_im(s, pc_start - s->cs_base);
7552 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7553 break;
7555 case 0xdb: /* VMSAVE */
7556 if (!SVME(s) || !PE(s)) {
7557 goto illegal_op;
7559 if (!check_cpl0(s)) {
7560 break;
7562 gen_update_cc_op(s);
7563 gen_jmp_im(s, pc_start - s->cs_base);
7564 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7565 break;
7567 case 0xdc: /* STGI */
7568 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7569 || !PE(s)) {
7570 goto illegal_op;
7572 if (!check_cpl0(s)) {
7573 break;
7575 gen_update_cc_op(s);
7576 gen_helper_stgi(cpu_env);
7577 gen_jmp_im(s, s->pc - s->cs_base);
7578 gen_eob(s);
7579 break;
7581 case 0xdd: /* CLGI */
7582 if (!SVME(s) || !PE(s)) {
7583 goto illegal_op;
7585 if (!check_cpl0(s)) {
7586 break;
7588 gen_update_cc_op(s);
7589 gen_jmp_im(s, pc_start - s->cs_base);
7590 gen_helper_clgi(cpu_env);
7591 break;
7593 case 0xde: /* SKINIT */
7594 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7595 || !PE(s)) {
7596 goto illegal_op;
7598 gen_svm_check_intercept(s, SVM_EXIT_SKINIT);
7599 /* If not intercepted, not implemented -- raise #UD. */
7600 goto illegal_op;
7602 case 0xdf: /* INVLPGA */
7603 if (!SVME(s) || !PE(s)) {
7604 goto illegal_op;
7606 if (!check_cpl0(s)) {
7607 break;
7609 gen_svm_check_intercept(s, SVM_EXIT_INVLPGA);
7610 if (s->aflag == MO_64) {
7611 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7612 } else {
7613 tcg_gen_ext32u_tl(s->A0, cpu_regs[R_EAX]);
7615 gen_helper_flush_page(cpu_env, s->A0);
7616 gen_jmp_im(s, s->pc - s->cs_base);
7617 gen_eob(s);
7618 break;
7620 CASE_MODRM_MEM_OP(2): /* lgdt */
7621 if (!check_cpl0(s)) {
7622 break;
7624 gen_svm_check_intercept(s, SVM_EXIT_GDTR_WRITE);
7625 gen_lea_modrm(env, s, modrm);
7626 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7627 gen_add_A0_im(s, 2);
7628 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7629 if (dflag == MO_16) {
7630 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7632 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7633 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7634 break;
7636 CASE_MODRM_MEM_OP(3): /* lidt */
7637 if (!check_cpl0(s)) {
7638 break;
7640 gen_svm_check_intercept(s, SVM_EXIT_IDTR_WRITE);
7641 gen_lea_modrm(env, s, modrm);
7642 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7643 gen_add_A0_im(s, 2);
7644 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7645 if (dflag == MO_16) {
7646 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7648 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7649 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, idt.limit));
7650 break;
7652 CASE_MODRM_OP(4): /* smsw */
7653 gen_svm_check_intercept(s, SVM_EXIT_READ_CR0);
7654 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
7656 * In 32-bit mode, the higher 16 bits of the destination
7657 * register are undefined. In practice CR0[31:0] is stored
7658 * just like in 64-bit mode.
7660 mod = (modrm >> 6) & 3;
7661 ot = (mod != 3 ? MO_16 : s->dflag);
7662 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7663 break;
7664 case 0xee: /* rdpkru */
7665 if (prefixes & PREFIX_LOCK) {
7666 goto illegal_op;
7668 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7669 gen_helper_rdpkru(s->tmp1_i64, cpu_env, s->tmp2_i32);
7670 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7671 break;
7672 case 0xef: /* wrpkru */
7673 if (prefixes & PREFIX_LOCK) {
7674 goto illegal_op;
7676 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7677 cpu_regs[R_EDX]);
7678 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7679 gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64);
7680 break;
7682 CASE_MODRM_OP(6): /* lmsw */
7683 if (!check_cpl0(s)) {
7684 break;
7686 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
7687 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7689 * Only the 4 lower bits of CR0 are modified.
7690 * PE cannot be set to zero if already set to one.
7692 tcg_gen_ld_tl(s->T1, cpu_env, offsetof(CPUX86State, cr[0]));
7693 tcg_gen_andi_tl(s->T0, s->T0, 0xf);
7694 tcg_gen_andi_tl(s->T1, s->T1, ~0xe);
7695 tcg_gen_or_tl(s->T0, s->T0, s->T1);
7696 gen_helper_write_crN(cpu_env, tcg_constant_i32(0), s->T0);
7697 gen_jmp_im(s, s->pc - s->cs_base);
7698 gen_eob(s);
7699 break;
7701 CASE_MODRM_MEM_OP(7): /* invlpg */
7702 if (!check_cpl0(s)) {
7703 break;
7705 gen_svm_check_intercept(s, SVM_EXIT_INVLPG);
7706 gen_lea_modrm(env, s, modrm);
7707 gen_helper_flush_page(cpu_env, s->A0);
7708 gen_jmp_im(s, s->pc - s->cs_base);
7709 gen_eob(s);
7710 break;
7712 case 0xf8: /* swapgs */
7713 #ifdef TARGET_X86_64
7714 if (CODE64(s)) {
7715 if (check_cpl0(s)) {
7716 tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]);
7717 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7718 offsetof(CPUX86State, kernelgsbase));
7719 tcg_gen_st_tl(s->T0, cpu_env,
7720 offsetof(CPUX86State, kernelgsbase));
7722 break;
7724 #endif
7725 goto illegal_op;
7727 case 0xf9: /* rdtscp */
7728 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7729 goto illegal_op;
7731 gen_update_cc_op(s);
7732 gen_jmp_im(s, pc_start - s->cs_base);
7733 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7734 gen_io_start();
7736 gen_helper_rdtscp(cpu_env);
7737 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7738 gen_jmp(s, s->pc - s->cs_base);
7740 break;
7742 default:
7743 goto unknown_op;
7745 break;
7747 case 0x108: /* invd */
7748 case 0x109: /* wbinvd */
7749 if (check_cpl0(s)) {
7750 gen_svm_check_intercept(s, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7751 /* nothing to do */
7753 break;
7754 case 0x63: /* arpl or movslS (x86_64) */
7755 #ifdef TARGET_X86_64
7756 if (CODE64(s)) {
7757 int d_ot;
7758 /* d_ot is the size of destination */
7759 d_ot = dflag;
7761 modrm = x86_ldub_code(env, s);
7762 reg = ((modrm >> 3) & 7) | REX_R(s);
7763 mod = (modrm >> 6) & 3;
7764 rm = (modrm & 7) | REX_B(s);
7766 if (mod == 3) {
7767 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
7768 /* sign extend */
7769 if (d_ot == MO_64) {
7770 tcg_gen_ext32s_tl(s->T0, s->T0);
7772 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7773 } else {
7774 gen_lea_modrm(env, s, modrm);
7775 gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0);
7776 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7778 } else
7779 #endif
7781 TCGLabel *label1;
7782 TCGv t0, t1, t2, a0;
7784 if (!PE(s) || VM86(s))
7785 goto illegal_op;
7786 t0 = tcg_temp_local_new();
7787 t1 = tcg_temp_local_new();
7788 t2 = tcg_temp_local_new();
7789 ot = MO_16;
7790 modrm = x86_ldub_code(env, s);
7791 reg = (modrm >> 3) & 7;
7792 mod = (modrm >> 6) & 3;
7793 rm = modrm & 7;
7794 if (mod != 3) {
7795 gen_lea_modrm(env, s, modrm);
7796 gen_op_ld_v(s, ot, t0, s->A0);
7797 a0 = tcg_temp_local_new();
7798 tcg_gen_mov_tl(a0, s->A0);
7799 } else {
7800 gen_op_mov_v_reg(s, ot, t0, rm);
7801 a0 = NULL;
7803 gen_op_mov_v_reg(s, ot, t1, reg);
7804 tcg_gen_andi_tl(s->tmp0, t0, 3);
7805 tcg_gen_andi_tl(t1, t1, 3);
7806 tcg_gen_movi_tl(t2, 0);
7807 label1 = gen_new_label();
7808 tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1);
7809 tcg_gen_andi_tl(t0, t0, ~3);
7810 tcg_gen_or_tl(t0, t0, t1);
7811 tcg_gen_movi_tl(t2, CC_Z);
7812 gen_set_label(label1);
7813 if (mod != 3) {
7814 gen_op_st_v(s, ot, t0, a0);
7815 tcg_temp_free(a0);
7816 } else {
7817 gen_op_mov_reg_v(s, ot, rm, t0);
7819 gen_compute_eflags(s);
7820 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7821 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7822 tcg_temp_free(t0);
7823 tcg_temp_free(t1);
7824 tcg_temp_free(t2);
7826 break;
7827 case 0x102: /* lar */
7828 case 0x103: /* lsl */
7830 TCGLabel *label1;
7831 TCGv t0;
7832 if (!PE(s) || VM86(s))
7833 goto illegal_op;
7834 ot = dflag != MO_16 ? MO_32 : MO_16;
7835 modrm = x86_ldub_code(env, s);
7836 reg = ((modrm >> 3) & 7) | REX_R(s);
7837 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7838 t0 = tcg_temp_local_new();
7839 gen_update_cc_op(s);
7840 if (b == 0x102) {
7841 gen_helper_lar(t0, cpu_env, s->T0);
7842 } else {
7843 gen_helper_lsl(t0, cpu_env, s->T0);
7845 tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z);
7846 label1 = gen_new_label();
7847 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
7848 gen_op_mov_reg_v(s, ot, reg, t0);
7849 gen_set_label(label1);
7850 set_cc_op(s, CC_OP_EFLAGS);
7851 tcg_temp_free(t0);
7853 break;
7854 case 0x118:
7855 modrm = x86_ldub_code(env, s);
7856 mod = (modrm >> 6) & 3;
7857 op = (modrm >> 3) & 7;
7858 switch(op) {
7859 case 0: /* prefetchnta */
7860 case 1: /* prefetchnt0 */
7861 case 2: /* prefetchnt0 */
7862 case 3: /* prefetchnt0 */
7863 if (mod == 3)
7864 goto illegal_op;
7865 gen_nop_modrm(env, s, modrm);
7866 /* nothing more to do */
7867 break;
7868 default: /* nop (multi byte) */
7869 gen_nop_modrm(env, s, modrm);
7870 break;
7872 break;
7873 case 0x11a:
7874 modrm = x86_ldub_code(env, s);
7875 if (s->flags & HF_MPX_EN_MASK) {
7876 mod = (modrm >> 6) & 3;
7877 reg = ((modrm >> 3) & 7) | REX_R(s);
7878 if (prefixes & PREFIX_REPZ) {
7879 /* bndcl */
7880 if (reg >= 4
7881 || (prefixes & PREFIX_LOCK)
7882 || s->aflag == MO_16) {
7883 goto illegal_op;
7885 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7886 } else if (prefixes & PREFIX_REPNZ) {
7887 /* bndcu */
7888 if (reg >= 4
7889 || (prefixes & PREFIX_LOCK)
7890 || s->aflag == MO_16) {
7891 goto illegal_op;
7893 TCGv_i64 notu = tcg_temp_new_i64();
7894 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7895 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7896 tcg_temp_free_i64(notu);
7897 } else if (prefixes & PREFIX_DATA) {
7898 /* bndmov -- from reg/mem */
7899 if (reg >= 4 || s->aflag == MO_16) {
7900 goto illegal_op;
7902 if (mod == 3) {
7903 int reg2 = (modrm & 7) | REX_B(s);
7904 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7905 goto illegal_op;
7907 if (s->flags & HF_MPX_IU_MASK) {
7908 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7909 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7911 } else {
7912 gen_lea_modrm(env, s, modrm);
7913 if (CODE64(s)) {
7914 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7915 s->mem_index, MO_LEQ);
7916 tcg_gen_addi_tl(s->A0, s->A0, 8);
7917 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7918 s->mem_index, MO_LEQ);
7919 } else {
7920 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7921 s->mem_index, MO_LEUL);
7922 tcg_gen_addi_tl(s->A0, s->A0, 4);
7923 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7924 s->mem_index, MO_LEUL);
7926 /* bnd registers are now in-use */
7927 gen_set_hflag(s, HF_MPX_IU_MASK);
7929 } else if (mod != 3) {
7930 /* bndldx */
7931 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7932 if (reg >= 4
7933 || (prefixes & PREFIX_LOCK)
7934 || s->aflag == MO_16
7935 || a.base < -1) {
7936 goto illegal_op;
7938 if (a.base >= 0) {
7939 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
7940 } else {
7941 tcg_gen_movi_tl(s->A0, 0);
7943 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
7944 if (a.index >= 0) {
7945 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
7946 } else {
7947 tcg_gen_movi_tl(s->T0, 0);
7949 if (CODE64(s)) {
7950 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0);
7951 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7952 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7953 } else {
7954 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0);
7955 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7956 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7958 gen_set_hflag(s, HF_MPX_IU_MASK);
7961 gen_nop_modrm(env, s, modrm);
7962 break;
7963 case 0x11b:
7964 modrm = x86_ldub_code(env, s);
7965 if (s->flags & HF_MPX_EN_MASK) {
7966 mod = (modrm >> 6) & 3;
7967 reg = ((modrm >> 3) & 7) | REX_R(s);
7968 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7969 /* bndmk */
7970 if (reg >= 4
7971 || (prefixes & PREFIX_LOCK)
7972 || s->aflag == MO_16) {
7973 goto illegal_op;
7975 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7976 if (a.base >= 0) {
7977 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7978 if (!CODE64(s)) {
7979 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7981 } else if (a.base == -1) {
7982 /* no base register has lower bound of 0 */
7983 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7984 } else {
7985 /* rip-relative generates #ud */
7986 goto illegal_op;
7988 tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a));
7989 if (!CODE64(s)) {
7990 tcg_gen_ext32u_tl(s->A0, s->A0);
7992 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
7993 /* bnd registers are now in-use */
7994 gen_set_hflag(s, HF_MPX_IU_MASK);
7995 break;
7996 } else if (prefixes & PREFIX_REPNZ) {
7997 /* bndcn */
7998 if (reg >= 4
7999 || (prefixes & PREFIX_LOCK)
8000 || s->aflag == MO_16) {
8001 goto illegal_op;
8003 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
8004 } else if (prefixes & PREFIX_DATA) {
8005 /* bndmov -- to reg/mem */
8006 if (reg >= 4 || s->aflag == MO_16) {
8007 goto illegal_op;
8009 if (mod == 3) {
8010 int reg2 = (modrm & 7) | REX_B(s);
8011 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
8012 goto illegal_op;
8014 if (s->flags & HF_MPX_IU_MASK) {
8015 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
8016 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
8018 } else {
8019 gen_lea_modrm(env, s, modrm);
8020 if (CODE64(s)) {
8021 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
8022 s->mem_index, MO_LEQ);
8023 tcg_gen_addi_tl(s->A0, s->A0, 8);
8024 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
8025 s->mem_index, MO_LEQ);
8026 } else {
8027 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
8028 s->mem_index, MO_LEUL);
8029 tcg_gen_addi_tl(s->A0, s->A0, 4);
8030 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
8031 s->mem_index, MO_LEUL);
8034 } else if (mod != 3) {
8035 /* bndstx */
8036 AddressParts a = gen_lea_modrm_0(env, s, modrm);
8037 if (reg >= 4
8038 || (prefixes & PREFIX_LOCK)
8039 || s->aflag == MO_16
8040 || a.base < -1) {
8041 goto illegal_op;
8043 if (a.base >= 0) {
8044 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
8045 } else {
8046 tcg_gen_movi_tl(s->A0, 0);
8048 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
8049 if (a.index >= 0) {
8050 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
8051 } else {
8052 tcg_gen_movi_tl(s->T0, 0);
8054 if (CODE64(s)) {
8055 gen_helper_bndstx64(cpu_env, s->A0, s->T0,
8056 cpu_bndl[reg], cpu_bndu[reg]);
8057 } else {
8058 gen_helper_bndstx32(cpu_env, s->A0, s->T0,
8059 cpu_bndl[reg], cpu_bndu[reg]);
8063 gen_nop_modrm(env, s, modrm);
8064 break;
8065 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
8066 modrm = x86_ldub_code(env, s);
8067 gen_nop_modrm(env, s, modrm);
8068 break;
8070 case 0x120: /* mov reg, crN */
8071 case 0x122: /* mov crN, reg */
8072 if (!check_cpl0(s)) {
8073 break;
8075 modrm = x86_ldub_code(env, s);
8077 * Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8078 * AMD documentation (24594.pdf) and testing of Intel 386 and 486
8079 * processors all show that the mod bits are assumed to be 1's,
8080 * regardless of actual values.
8082 rm = (modrm & 7) | REX_B(s);
8083 reg = ((modrm >> 3) & 7) | REX_R(s);
8084 switch (reg) {
8085 case 0:
8086 if ((prefixes & PREFIX_LOCK) &&
8087 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
8088 reg = 8;
8090 break;
8091 case 2:
8092 case 3:
8093 case 4:
8094 break;
8095 default:
8096 goto unknown_op;
8098 ot = (CODE64(s) ? MO_64 : MO_32);
8100 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8101 gen_io_start();
8103 if (b & 2) {
8104 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
8105 gen_op_mov_v_reg(s, ot, s->T0, rm);
8106 gen_helper_write_crN(cpu_env, tcg_constant_i32(reg), s->T0);
8107 gen_jmp_im(s, s->pc - s->cs_base);
8108 gen_eob(s);
8109 } else {
8110 gen_svm_check_intercept(s, SVM_EXIT_READ_CR0 + reg);
8111 gen_helper_read_crN(s->T0, cpu_env, tcg_constant_i32(reg));
8112 gen_op_mov_reg_v(s, ot, rm, s->T0);
8113 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8114 gen_jmp(s, s->pc - s->cs_base);
8117 break;
8119 case 0x121: /* mov reg, drN */
8120 case 0x123: /* mov drN, reg */
8121 if (check_cpl0(s)) {
8122 modrm = x86_ldub_code(env, s);
8123 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8124 * AMD documentation (24594.pdf) and testing of
8125 * intel 386 and 486 processors all show that the mod bits
8126 * are assumed to be 1's, regardless of actual values.
8128 rm = (modrm & 7) | REX_B(s);
8129 reg = ((modrm >> 3) & 7) | REX_R(s);
8130 if (CODE64(s))
8131 ot = MO_64;
8132 else
8133 ot = MO_32;
8134 if (reg >= 8) {
8135 goto illegal_op;
8137 if (b & 2) {
8138 gen_svm_check_intercept(s, SVM_EXIT_WRITE_DR0 + reg);
8139 gen_op_mov_v_reg(s, ot, s->T0, rm);
8140 tcg_gen_movi_i32(s->tmp2_i32, reg);
8141 gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
8142 gen_jmp_im(s, s->pc - s->cs_base);
8143 gen_eob(s);
8144 } else {
8145 gen_svm_check_intercept(s, SVM_EXIT_READ_DR0 + reg);
8146 tcg_gen_movi_i32(s->tmp2_i32, reg);
8147 gen_helper_get_dr(s->T0, cpu_env, s->tmp2_i32);
8148 gen_op_mov_reg_v(s, ot, rm, s->T0);
8151 break;
8152 case 0x106: /* clts */
8153 if (check_cpl0(s)) {
8154 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
8155 gen_helper_clts(cpu_env);
8156 /* abort block because static cpu state changed */
8157 gen_jmp_im(s, s->pc - s->cs_base);
8158 gen_eob(s);
8160 break;
8161 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
8162 case 0x1c3: /* MOVNTI reg, mem */
8163 if (!(s->cpuid_features & CPUID_SSE2))
8164 goto illegal_op;
8165 ot = mo_64_32(dflag);
8166 modrm = x86_ldub_code(env, s);
8167 mod = (modrm >> 6) & 3;
8168 if (mod == 3)
8169 goto illegal_op;
8170 reg = ((modrm >> 3) & 7) | REX_R(s);
8171 /* generate a generic store */
8172 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8173 break;
8174 case 0x1ae:
8175 modrm = x86_ldub_code(env, s);
8176 switch (modrm) {
8177 CASE_MODRM_MEM_OP(0): /* fxsave */
8178 if (!(s->cpuid_features & CPUID_FXSR)
8179 || (prefixes & PREFIX_LOCK)) {
8180 goto illegal_op;
8182 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8183 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8184 break;
8186 gen_lea_modrm(env, s, modrm);
8187 gen_helper_fxsave(cpu_env, s->A0);
8188 break;
8190 CASE_MODRM_MEM_OP(1): /* fxrstor */
8191 if (!(s->cpuid_features & CPUID_FXSR)
8192 || (prefixes & PREFIX_LOCK)) {
8193 goto illegal_op;
8195 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8196 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8197 break;
8199 gen_lea_modrm(env, s, modrm);
8200 gen_helper_fxrstor(cpu_env, s->A0);
8201 break;
8203 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
8204 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8205 goto illegal_op;
8207 if (s->flags & HF_TS_MASK) {
8208 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8209 break;
8211 gen_lea_modrm(env, s, modrm);
8212 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
8213 gen_helper_ldmxcsr(cpu_env, s->tmp2_i32);
8214 break;
8216 CASE_MODRM_MEM_OP(3): /* stmxcsr */
8217 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8218 goto illegal_op;
8220 if (s->flags & HF_TS_MASK) {
8221 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8222 break;
8224 gen_helper_update_mxcsr(cpu_env);
8225 gen_lea_modrm(env, s, modrm);
8226 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr));
8227 gen_op_st_v(s, MO_32, s->T0, s->A0);
8228 break;
8230 CASE_MODRM_MEM_OP(4): /* xsave */
8231 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8232 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8233 | PREFIX_REPZ | PREFIX_REPNZ))) {
8234 goto illegal_op;
8236 gen_lea_modrm(env, s, modrm);
8237 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8238 cpu_regs[R_EDX]);
8239 gen_helper_xsave(cpu_env, s->A0, s->tmp1_i64);
8240 break;
8242 CASE_MODRM_MEM_OP(5): /* xrstor */
8243 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8244 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8245 | PREFIX_REPZ | PREFIX_REPNZ))) {
8246 goto illegal_op;
8248 gen_lea_modrm(env, s, modrm);
8249 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8250 cpu_regs[R_EDX]);
8251 gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64);
8252 /* XRSTOR is how MPX is enabled, which changes how
8253 we translate. Thus we need to end the TB. */
8254 gen_update_cc_op(s);
8255 gen_jmp_im(s, s->pc - s->cs_base);
8256 gen_eob(s);
8257 break;
8259 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
8260 if (prefixes & PREFIX_LOCK) {
8261 goto illegal_op;
8263 if (prefixes & PREFIX_DATA) {
8264 /* clwb */
8265 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8266 goto illegal_op;
8268 gen_nop_modrm(env, s, modrm);
8269 } else {
8270 /* xsaveopt */
8271 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8272 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8273 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8274 goto illegal_op;
8276 gen_lea_modrm(env, s, modrm);
8277 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8278 cpu_regs[R_EDX]);
8279 gen_helper_xsaveopt(cpu_env, s->A0, s->tmp1_i64);
8281 break;
8283 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
8284 if (prefixes & PREFIX_LOCK) {
8285 goto illegal_op;
8287 if (prefixes & PREFIX_DATA) {
8288 /* clflushopt */
8289 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8290 goto illegal_op;
8292 } else {
8293 /* clflush */
8294 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8295 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8296 goto illegal_op;
8299 gen_nop_modrm(env, s, modrm);
8300 break;
8302 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
8303 case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
8304 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
8305 case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
8306 if (CODE64(s)
8307 && (prefixes & PREFIX_REPZ)
8308 && !(prefixes & PREFIX_LOCK)
8309 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8310 TCGv base, treg, src, dst;
8312 /* Preserve hflags bits by testing CR4 at runtime. */
8313 tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
8314 gen_helper_cr4_testbit(cpu_env, s->tmp2_i32);
8316 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8317 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8319 if (modrm & 0x10) {
8320 /* wr*base */
8321 dst = base, src = treg;
8322 } else {
8323 /* rd*base */
8324 dst = treg, src = base;
8327 if (s->dflag == MO_32) {
8328 tcg_gen_ext32u_tl(dst, src);
8329 } else {
8330 tcg_gen_mov_tl(dst, src);
8332 break;
8334 goto unknown_op;
8336 case 0xf8: /* sfence / pcommit */
8337 if (prefixes & PREFIX_DATA) {
8338 /* pcommit */
8339 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8340 || (prefixes & PREFIX_LOCK)) {
8341 goto illegal_op;
8343 break;
8345 /* fallthru */
8346 case 0xf9 ... 0xff: /* sfence */
8347 if (!(s->cpuid_features & CPUID_SSE)
8348 || (prefixes & PREFIX_LOCK)) {
8349 goto illegal_op;
8351 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8352 break;
8353 case 0xe8 ... 0xef: /* lfence */
8354 if (!(s->cpuid_features & CPUID_SSE)
8355 || (prefixes & PREFIX_LOCK)) {
8356 goto illegal_op;
8358 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8359 break;
8360 case 0xf0 ... 0xf7: /* mfence */
8361 if (!(s->cpuid_features & CPUID_SSE2)
8362 || (prefixes & PREFIX_LOCK)) {
8363 goto illegal_op;
8365 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8366 break;
8368 default:
8369 goto unknown_op;
8371 break;
8373 case 0x10d: /* 3DNow! prefetch(w) */
8374 modrm = x86_ldub_code(env, s);
8375 mod = (modrm >> 6) & 3;
8376 if (mod == 3)
8377 goto illegal_op;
8378 gen_nop_modrm(env, s, modrm);
8379 break;
8380 case 0x1aa: /* rsm */
8381 gen_svm_check_intercept(s, SVM_EXIT_RSM);
8382 if (!(s->flags & HF_SMM_MASK))
8383 goto illegal_op;
8384 #ifdef CONFIG_USER_ONLY
8385 /* we should not be in SMM mode */
8386 g_assert_not_reached();
8387 #else
8388 gen_update_cc_op(s);
8389 gen_jmp_im(s, s->pc - s->cs_base);
8390 gen_helper_rsm(cpu_env);
8391 #endif /* CONFIG_USER_ONLY */
8392 gen_eob(s);
8393 break;
8394 case 0x1b8: /* SSE4.2 popcnt */
8395 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8396 PREFIX_REPZ)
8397 goto illegal_op;
8398 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8399 goto illegal_op;
8401 modrm = x86_ldub_code(env, s);
8402 reg = ((modrm >> 3) & 7) | REX_R(s);
8404 if (s->prefix & PREFIX_DATA) {
8405 ot = MO_16;
8406 } else {
8407 ot = mo_64_32(dflag);
8410 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8411 gen_extu(ot, s->T0);
8412 tcg_gen_mov_tl(cpu_cc_src, s->T0);
8413 tcg_gen_ctpop_tl(s->T0, s->T0);
8414 gen_op_mov_reg_v(s, ot, reg, s->T0);
8416 set_cc_op(s, CC_OP_POPCNT);
8417 break;
8418 case 0x10e ... 0x10f:
8419 /* 3DNow! instructions, ignore prefixes */
8420 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8421 /* fall through */
8422 case 0x110 ... 0x117:
8423 case 0x128 ... 0x12f:
8424 case 0x138 ... 0x13a:
8425 case 0x150 ... 0x179:
8426 case 0x17c ... 0x17f:
8427 case 0x1c2:
8428 case 0x1c4 ... 0x1c6:
8429 case 0x1d0 ... 0x1fe:
8430 gen_sse(env, s, b, pc_start);
8431 break;
8432 default:
8433 goto unknown_op;
8435 return s->pc;
8436 illegal_op:
8437 gen_illegal_opcode(s);
8438 return s->pc;
8439 unknown_op:
8440 gen_unknown_opcode(env, s);
8441 return s->pc;
8444 void tcg_x86_init(void)
8446 static const char reg_names[CPU_NB_REGS][4] = {
8447 #ifdef TARGET_X86_64
8448 [R_EAX] = "rax",
8449 [R_EBX] = "rbx",
8450 [R_ECX] = "rcx",
8451 [R_EDX] = "rdx",
8452 [R_ESI] = "rsi",
8453 [R_EDI] = "rdi",
8454 [R_EBP] = "rbp",
8455 [R_ESP] = "rsp",
8456 [8] = "r8",
8457 [9] = "r9",
8458 [10] = "r10",
8459 [11] = "r11",
8460 [12] = "r12",
8461 [13] = "r13",
8462 [14] = "r14",
8463 [15] = "r15",
8464 #else
8465 [R_EAX] = "eax",
8466 [R_EBX] = "ebx",
8467 [R_ECX] = "ecx",
8468 [R_EDX] = "edx",
8469 [R_ESI] = "esi",
8470 [R_EDI] = "edi",
8471 [R_EBP] = "ebp",
8472 [R_ESP] = "esp",
8473 #endif
8475 static const char seg_base_names[6][8] = {
8476 [R_CS] = "cs_base",
8477 [R_DS] = "ds_base",
8478 [R_ES] = "es_base",
8479 [R_FS] = "fs_base",
8480 [R_GS] = "gs_base",
8481 [R_SS] = "ss_base",
8483 static const char bnd_regl_names[4][8] = {
8484 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8486 static const char bnd_regu_names[4][8] = {
8487 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8489 int i;
8491 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8492 offsetof(CPUX86State, cc_op), "cc_op");
8493 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8494 "cc_dst");
8495 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8496 "cc_src");
8497 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8498 "cc_src2");
8500 for (i = 0; i < CPU_NB_REGS; ++i) {
8501 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8502 offsetof(CPUX86State, regs[i]),
8503 reg_names[i]);
8506 for (i = 0; i < 6; ++i) {
8507 cpu_seg_base[i]
8508 = tcg_global_mem_new(cpu_env,
8509 offsetof(CPUX86State, segs[i].base),
8510 seg_base_names[i]);
8513 for (i = 0; i < 4; ++i) {
8514 cpu_bndl[i]
8515 = tcg_global_mem_new_i64(cpu_env,
8516 offsetof(CPUX86State, bnd_regs[i].lb),
8517 bnd_regl_names[i]);
8518 cpu_bndu[i]
8519 = tcg_global_mem_new_i64(cpu_env,
8520 offsetof(CPUX86State, bnd_regs[i].ub),
8521 bnd_regu_names[i]);
8525 static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
8527 DisasContext *dc = container_of(dcbase, DisasContext, base);
8528 CPUX86State *env = cpu->env_ptr;
8529 uint32_t flags = dc->base.tb->flags;
8530 int cpl = (flags >> HF_CPL_SHIFT) & 3;
8531 int iopl = (flags >> IOPL_SHIFT) & 3;
8533 dc->cs_base = dc->base.tb->cs_base;
8534 dc->flags = flags;
8535 #ifndef CONFIG_USER_ONLY
8536 dc->cpl = cpl;
8537 dc->iopl = iopl;
8538 #endif
8540 /* We make some simplifying assumptions; validate they're correct. */
8541 g_assert(PE(dc) == ((flags & HF_PE_MASK) != 0));
8542 g_assert(CPL(dc) == cpl);
8543 g_assert(IOPL(dc) == iopl);
8544 g_assert(VM86(dc) == ((flags & HF_VM_MASK) != 0));
8545 g_assert(CODE32(dc) == ((flags & HF_CS32_MASK) != 0));
8546 g_assert(CODE64(dc) == ((flags & HF_CS64_MASK) != 0));
8547 g_assert(SS32(dc) == ((flags & HF_SS32_MASK) != 0));
8548 g_assert(LMA(dc) == ((flags & HF_LMA_MASK) != 0));
8549 g_assert(ADDSEG(dc) == ((flags & HF_ADDSEG_MASK) != 0));
8550 g_assert(SVME(dc) == ((flags & HF_SVME_MASK) != 0));
8551 g_assert(GUEST(dc) == ((flags & HF_GUEST_MASK) != 0));
8553 dc->cc_op = CC_OP_DYNAMIC;
8554 dc->cc_op_dirty = false;
8555 dc->popl_esp_hack = 0;
8556 /* select memory access functions */
8557 dc->mem_index = 0;
8558 #ifdef CONFIG_SOFTMMU
8559 dc->mem_index = cpu_mmu_index(env, false);
8560 #endif
8561 dc->cpuid_features = env->features[FEAT_1_EDX];
8562 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8563 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8564 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8565 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8566 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8567 dc->jmp_opt = !(dc->base.singlestep_enabled ||
8568 (flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)));
8570 * If jmp_opt, we want to handle each string instruction individually.
8571 * For icount also disable repz optimization so that each iteration
8572 * is accounted separately.
8574 dc->repz_opt = !dc->jmp_opt && !(tb_cflags(dc->base.tb) & CF_USE_ICOUNT);
8576 dc->T0 = tcg_temp_new();
8577 dc->T1 = tcg_temp_new();
8578 dc->A0 = tcg_temp_new();
8580 dc->tmp0 = tcg_temp_new();
8581 dc->tmp1_i64 = tcg_temp_new_i64();
8582 dc->tmp2_i32 = tcg_temp_new_i32();
8583 dc->tmp3_i32 = tcg_temp_new_i32();
8584 dc->tmp4 = tcg_temp_new();
8585 dc->ptr0 = tcg_temp_new_ptr();
8586 dc->ptr1 = tcg_temp_new_ptr();
8587 dc->cc_srcT = tcg_temp_local_new();
8590 static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
8594 static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8596 DisasContext *dc = container_of(dcbase, DisasContext, base);
8598 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
8601 static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8602 const CPUBreakpoint *bp)
8604 DisasContext *dc = container_of(dcbase, DisasContext, base);
8605 /* If RF is set, suppress an internally generated breakpoint. */
8606 int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
8607 if (bp->flags & flags) {
8608 gen_debug(dc);
8609 /* The address covered by the breakpoint must be included in
8610 [tb->pc, tb->pc + tb->size) in order to for it to be
8611 properly cleared -- thus we increment the PC here so that
8612 the generic logic setting tb->size later does the right thing. */
8613 dc->base.pc_next += 1;
8614 return true;
8615 } else {
8616 return false;
8620 static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8622 DisasContext *dc = container_of(dcbase, DisasContext, base);
8623 target_ulong pc_next;
8625 #ifdef TARGET_VSYSCALL_PAGE
8627 * Detect entry into the vsyscall page and invoke the syscall.
8629 if ((dc->base.pc_next & TARGET_PAGE_MASK) == TARGET_VSYSCALL_PAGE) {
8630 gen_exception(dc, EXCP_VSYSCALL, dc->base.pc_next);
8631 dc->base.pc_next = dc->pc + 1;
8632 return;
8634 #endif
8636 pc_next = disas_insn(dc, cpu);
8638 if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
8639 /* if single step mode, we generate only one instruction and
8640 generate an exception */
8641 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8642 the flag and abort the translation to give the irqs a
8643 chance to happen */
8644 dc->base.is_jmp = DISAS_TOO_MANY;
8645 } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
8646 && ((pc_next & TARGET_PAGE_MASK)
8647 != ((pc_next + TARGET_MAX_INSN_SIZE - 1)
8648 & TARGET_PAGE_MASK)
8649 || (pc_next & ~TARGET_PAGE_MASK) == 0)) {
8650 /* Do not cross the boundary of the pages in icount mode,
8651 it can cause an exception. Do it only when boundary is
8652 crossed by the first instruction in the block.
8653 If current instruction already crossed the bound - it's ok,
8654 because an exception hasn't stopped this code.
8656 dc->base.is_jmp = DISAS_TOO_MANY;
8657 } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
8658 dc->base.is_jmp = DISAS_TOO_MANY;
8661 dc->base.pc_next = pc_next;
8664 static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8666 DisasContext *dc = container_of(dcbase, DisasContext, base);
8668 if (dc->base.is_jmp == DISAS_TOO_MANY) {
8669 gen_jmp_im(dc, dc->base.pc_next - dc->cs_base);
8670 gen_eob(dc);
8674 static void i386_tr_disas_log(const DisasContextBase *dcbase,
8675 CPUState *cpu)
8677 DisasContext *dc = container_of(dcbase, DisasContext, base);
8679 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
8680 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
8683 static const TranslatorOps i386_tr_ops = {
8684 .init_disas_context = i386_tr_init_disas_context,
8685 .tb_start = i386_tr_tb_start,
8686 .insn_start = i386_tr_insn_start,
8687 .breakpoint_check = i386_tr_breakpoint_check,
8688 .translate_insn = i386_tr_translate_insn,
8689 .tb_stop = i386_tr_tb_stop,
8690 .disas_log = i386_tr_disas_log,
8693 /* generate intermediate code for basic block 'tb'. */
8694 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
8696 DisasContext dc;
8698 translator_loop(&i386_tr_ops, &dc.base, cpu, tb, max_insns);
8701 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8702 target_ulong *data)
8704 int cc_op = data[1];
8705 env->eip = data[0] - tb->cs_base;
8706 if (cc_op != CC_OP_DYNAMIC) {
8707 env->cc_op = cc_op;