target/i386: hardcode R_EAX as destination register for LAHF/SAHF
[qemu.git] / target / i386 / tcg / translate.c
blob7e0b2a709ae1b2771bdd85902ce84db0af4a6727
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 "tcg/tcg-op-gvec.h"
27 #include "exec/cpu_ldst.h"
28 #include "exec/translator.h"
29 #include "fpu/softfloat.h"
31 #include "exec/helper-proto.h"
32 #include "exec/helper-gen.h"
33 #include "helper-tcg.h"
35 #include "exec/log.h"
37 #define PREFIX_REPZ 0x01
38 #define PREFIX_REPNZ 0x02
39 #define PREFIX_LOCK 0x04
40 #define PREFIX_DATA 0x08
41 #define PREFIX_ADR 0x10
42 #define PREFIX_VEX 0x20
43 #define PREFIX_REX 0x40
45 #ifdef TARGET_X86_64
46 # define ctztl ctz64
47 # define clztl clz64
48 #else
49 # define ctztl ctz32
50 # define clztl clz32
51 #endif
53 /* For a switch indexed by MODRM, match all memory operands for a given OP. */
54 #define CASE_MODRM_MEM_OP(OP) \
55 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
56 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
57 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
59 #define CASE_MODRM_OP(OP) \
60 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
61 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
62 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
63 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
65 //#define MACRO_TEST 1
67 /* global register indexes */
68 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
69 static TCGv cpu_eip;
70 static TCGv_i32 cpu_cc_op;
71 static TCGv cpu_regs[CPU_NB_REGS];
72 static TCGv cpu_seg_base[6];
73 static TCGv_i64 cpu_bndl[4];
74 static TCGv_i64 cpu_bndu[4];
76 #include "exec/gen-icount.h"
78 typedef struct DisasContext {
79 DisasContextBase base;
81 target_ulong pc; /* pc = eip + cs_base */
82 target_ulong cs_base; /* base of CS segment */
83 target_ulong pc_save;
85 MemOp aflag;
86 MemOp dflag;
88 int8_t override; /* -1 if no override, else R_CS, R_DS, etc */
89 uint8_t prefix;
91 bool has_modrm;
92 uint8_t modrm;
94 #ifndef CONFIG_USER_ONLY
95 uint8_t cpl; /* code priv level */
96 uint8_t iopl; /* i/o priv level */
97 #endif
98 uint8_t vex_l; /* vex vector length */
99 uint8_t vex_v; /* vex vvvv register, without 1's complement. */
100 uint8_t popl_esp_hack; /* for correct popl with esp base handling */
101 uint8_t rip_offset; /* only used in x86_64, but left for simplicity */
103 #ifdef TARGET_X86_64
104 uint8_t rex_r;
105 uint8_t rex_x;
106 uint8_t rex_b;
107 #endif
108 bool vex_w; /* used by AVX even on 32-bit processors */
109 bool jmp_opt; /* use direct block chaining for direct jumps */
110 bool repz_opt; /* optimize jumps within repz instructions */
111 bool cc_op_dirty;
113 CCOp cc_op; /* current CC operation */
114 int mem_index; /* select memory access functions */
115 uint32_t flags; /* all execution flags */
116 int cpuid_features;
117 int cpuid_ext_features;
118 int cpuid_ext2_features;
119 int cpuid_ext3_features;
120 int cpuid_7_0_ebx_features;
121 int cpuid_7_0_ecx_features;
122 int cpuid_xsave_features;
124 /* TCG local temps */
125 TCGv cc_srcT;
126 TCGv A0;
127 TCGv T0;
128 TCGv T1;
130 /* TCG local register indexes (only used inside old micro ops) */
131 TCGv tmp0;
132 TCGv tmp4;
133 TCGv_i32 tmp2_i32;
134 TCGv_i32 tmp3_i32;
135 TCGv_i64 tmp1_i64;
137 sigjmp_buf jmpbuf;
138 TCGOp *prev_insn_end;
139 } DisasContext;
141 #define DISAS_EOB_ONLY DISAS_TARGET_0
142 #define DISAS_EOB_NEXT DISAS_TARGET_1
143 #define DISAS_EOB_INHIBIT_IRQ DISAS_TARGET_2
144 #define DISAS_JUMP DISAS_TARGET_3
146 /* The environment in which user-only runs is constrained. */
147 #ifdef CONFIG_USER_ONLY
148 #define PE(S) true
149 #define CPL(S) 3
150 #define IOPL(S) 0
151 #define SVME(S) false
152 #define GUEST(S) false
153 #else
154 #define PE(S) (((S)->flags & HF_PE_MASK) != 0)
155 #define CPL(S) ((S)->cpl)
156 #define IOPL(S) ((S)->iopl)
157 #define SVME(S) (((S)->flags & HF_SVME_MASK) != 0)
158 #define GUEST(S) (((S)->flags & HF_GUEST_MASK) != 0)
159 #endif
160 #if defined(CONFIG_USER_ONLY) && defined(TARGET_X86_64)
161 #define VM86(S) false
162 #define CODE32(S) true
163 #define SS32(S) true
164 #define ADDSEG(S) false
165 #else
166 #define VM86(S) (((S)->flags & HF_VM_MASK) != 0)
167 #define CODE32(S) (((S)->flags & HF_CS32_MASK) != 0)
168 #define SS32(S) (((S)->flags & HF_SS32_MASK) != 0)
169 #define ADDSEG(S) (((S)->flags & HF_ADDSEG_MASK) != 0)
170 #endif
171 #if !defined(TARGET_X86_64)
172 #define CODE64(S) false
173 #define LMA(S) false
174 #elif defined(CONFIG_USER_ONLY)
175 #define CODE64(S) true
176 #define LMA(S) true
177 #else
178 #define CODE64(S) (((S)->flags & HF_CS64_MASK) != 0)
179 #define LMA(S) (((S)->flags & HF_LMA_MASK) != 0)
180 #endif
182 #ifdef TARGET_X86_64
183 #define REX_PREFIX(S) (((S)->prefix & PREFIX_REX) != 0)
184 #define REX_W(S) ((S)->vex_w)
185 #define REX_R(S) ((S)->rex_r + 0)
186 #define REX_X(S) ((S)->rex_x + 0)
187 #define REX_B(S) ((S)->rex_b + 0)
188 #else
189 #define REX_PREFIX(S) false
190 #define REX_W(S) false
191 #define REX_R(S) 0
192 #define REX_X(S) 0
193 #define REX_B(S) 0
194 #endif
197 * Many sysemu-only helpers are not reachable for user-only.
198 * Define stub generators here, so that we need not either sprinkle
199 * ifdefs through the translator, nor provide the helper function.
201 #define STUB_HELPER(NAME, ...) \
202 static inline void gen_helper_##NAME(__VA_ARGS__) \
203 { qemu_build_not_reached(); }
205 #ifdef CONFIG_USER_ONLY
206 STUB_HELPER(clgi, TCGv_env env)
207 STUB_HELPER(flush_page, TCGv_env env, TCGv addr)
208 STUB_HELPER(hlt, TCGv_env env, TCGv_i32 pc_ofs)
209 STUB_HELPER(inb, TCGv ret, TCGv_env env, TCGv_i32 port)
210 STUB_HELPER(inw, TCGv ret, TCGv_env env, TCGv_i32 port)
211 STUB_HELPER(inl, TCGv ret, TCGv_env env, TCGv_i32 port)
212 STUB_HELPER(monitor, TCGv_env env, TCGv addr)
213 STUB_HELPER(mwait, TCGv_env env, TCGv_i32 pc_ofs)
214 STUB_HELPER(outb, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
215 STUB_HELPER(outw, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
216 STUB_HELPER(outl, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
217 STUB_HELPER(rdmsr, TCGv_env env)
218 STUB_HELPER(read_crN, TCGv ret, TCGv_env env, TCGv_i32 reg)
219 STUB_HELPER(get_dr, TCGv ret, TCGv_env env, TCGv_i32 reg)
220 STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
221 STUB_HELPER(stgi, TCGv_env env)
222 STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
223 STUB_HELPER(vmload, TCGv_env env, TCGv_i32 aflag)
224 STUB_HELPER(vmmcall, TCGv_env env)
225 STUB_HELPER(vmrun, TCGv_env env, TCGv_i32 aflag, TCGv_i32 pc_ofs)
226 STUB_HELPER(vmsave, TCGv_env env, TCGv_i32 aflag)
227 STUB_HELPER(write_crN, TCGv_env env, TCGv_i32 reg, TCGv val)
228 STUB_HELPER(wrmsr, TCGv_env env)
229 #endif
231 static void gen_eob(DisasContext *s);
232 static void gen_jr(DisasContext *s);
233 static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num);
234 static void gen_jmp_rel_csize(DisasContext *s, int diff, int tb_num);
235 static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
236 static void gen_exception_gpf(DisasContext *s);
238 /* i386 arith/logic operations */
239 enum {
240 OP_ADDL,
241 OP_ORL,
242 OP_ADCL,
243 OP_SBBL,
244 OP_ANDL,
245 OP_SUBL,
246 OP_XORL,
247 OP_CMPL,
250 /* i386 shift ops */
251 enum {
252 OP_ROL,
253 OP_ROR,
254 OP_RCL,
255 OP_RCR,
256 OP_SHL,
257 OP_SHR,
258 OP_SHL1, /* undocumented */
259 OP_SAR = 7,
262 enum {
263 JCC_O,
264 JCC_B,
265 JCC_Z,
266 JCC_BE,
267 JCC_S,
268 JCC_P,
269 JCC_L,
270 JCC_LE,
273 enum {
274 /* I386 int registers */
275 OR_EAX, /* MUST be even numbered */
276 OR_ECX,
277 OR_EDX,
278 OR_EBX,
279 OR_ESP,
280 OR_EBP,
281 OR_ESI,
282 OR_EDI,
284 OR_TMP0 = 16, /* temporary operand register */
285 OR_TMP1,
286 OR_A0, /* temporary register used when doing address evaluation */
289 enum {
290 USES_CC_DST = 1,
291 USES_CC_SRC = 2,
292 USES_CC_SRC2 = 4,
293 USES_CC_SRCT = 8,
296 /* Bit set if the global variable is live after setting CC_OP to X. */
297 static const uint8_t cc_op_live[CC_OP_NB] = {
298 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
299 [CC_OP_EFLAGS] = USES_CC_SRC,
300 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
301 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
302 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
303 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
304 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
305 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
306 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
307 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
308 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
309 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
310 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
311 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
312 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
313 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
314 [CC_OP_CLR] = 0,
315 [CC_OP_POPCNT] = USES_CC_SRC,
318 static void set_cc_op(DisasContext *s, CCOp op)
320 int dead;
322 if (s->cc_op == op) {
323 return;
326 /* Discard CC computation that will no longer be used. */
327 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
328 if (dead & USES_CC_DST) {
329 tcg_gen_discard_tl(cpu_cc_dst);
331 if (dead & USES_CC_SRC) {
332 tcg_gen_discard_tl(cpu_cc_src);
334 if (dead & USES_CC_SRC2) {
335 tcg_gen_discard_tl(cpu_cc_src2);
337 if (dead & USES_CC_SRCT) {
338 tcg_gen_discard_tl(s->cc_srcT);
341 if (op == CC_OP_DYNAMIC) {
342 /* The DYNAMIC setting is translator only, and should never be
343 stored. Thus we always consider it clean. */
344 s->cc_op_dirty = false;
345 } else {
346 /* Discard any computed CC_OP value (see shifts). */
347 if (s->cc_op == CC_OP_DYNAMIC) {
348 tcg_gen_discard_i32(cpu_cc_op);
350 s->cc_op_dirty = true;
352 s->cc_op = op;
355 static void gen_update_cc_op(DisasContext *s)
357 if (s->cc_op_dirty) {
358 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
359 s->cc_op_dirty = false;
363 #ifdef TARGET_X86_64
365 #define NB_OP_SIZES 4
367 #else /* !TARGET_X86_64 */
369 #define NB_OP_SIZES 3
371 #endif /* !TARGET_X86_64 */
373 #if HOST_BIG_ENDIAN
374 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
375 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
376 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
377 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
378 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
379 #else
380 #define REG_B_OFFSET 0
381 #define REG_H_OFFSET 1
382 #define REG_W_OFFSET 0
383 #define REG_L_OFFSET 0
384 #define REG_LH_OFFSET 4
385 #endif
387 /* In instruction encodings for byte register accesses the
388 * register number usually indicates "low 8 bits of register N";
389 * however there are some special cases where N 4..7 indicates
390 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
391 * true for this special case, false otherwise.
393 static inline bool byte_reg_is_xH(DisasContext *s, int reg)
395 /* Any time the REX prefix is present, byte registers are uniform */
396 if (reg < 4 || REX_PREFIX(s)) {
397 return false;
399 return true;
402 /* Select the size of a push/pop operation. */
403 static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
405 if (CODE64(s)) {
406 return ot == MO_16 ? MO_16 : MO_64;
407 } else {
408 return ot;
412 /* Select the size of the stack pointer. */
413 static inline MemOp mo_stacksize(DisasContext *s)
415 return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
418 /* Select only size 64 else 32. Used for SSE operand sizes. */
419 static inline MemOp mo_64_32(MemOp ot)
421 #ifdef TARGET_X86_64
422 return ot == MO_64 ? MO_64 : MO_32;
423 #else
424 return MO_32;
425 #endif
428 /* Select size 8 if lsb of B is clear, else OT. Used for decoding
429 byte vs word opcodes. */
430 static inline MemOp mo_b_d(int b, MemOp ot)
432 return b & 1 ? ot : MO_8;
435 /* Select size 8 if lsb of B is clear, else OT capped at 32.
436 Used for decoding operand size of port opcodes. */
437 static inline MemOp mo_b_d32(int b, MemOp ot)
439 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
442 /* Compute the result of writing t0 to the OT-sized register REG.
444 * If DEST is NULL, store the result into the register and return the
445 * register's TCGv.
447 * If DEST is not NULL, store the result into DEST and return the
448 * register's TCGv.
450 static TCGv gen_op_deposit_reg_v(DisasContext *s, MemOp ot, int reg, TCGv dest, TCGv t0)
452 switch(ot) {
453 case MO_8:
454 if (byte_reg_is_xH(s, reg)) {
455 dest = dest ? dest : cpu_regs[reg - 4];
456 tcg_gen_deposit_tl(dest, cpu_regs[reg - 4], t0, 8, 8);
457 return cpu_regs[reg - 4];
459 dest = dest ? dest : cpu_regs[reg];
460 tcg_gen_deposit_tl(dest, cpu_regs[reg], t0, 0, 8);
461 break;
462 case MO_16:
463 dest = dest ? dest : cpu_regs[reg];
464 tcg_gen_deposit_tl(dest, cpu_regs[reg], t0, 0, 16);
465 break;
466 case MO_32:
467 /* For x86_64, this sets the higher half of register to zero.
468 For i386, this is equivalent to a mov. */
469 dest = dest ? dest : cpu_regs[reg];
470 tcg_gen_ext32u_tl(dest, t0);
471 break;
472 #ifdef TARGET_X86_64
473 case MO_64:
474 dest = dest ? dest : cpu_regs[reg];
475 tcg_gen_mov_tl(dest, t0);
476 break;
477 #endif
478 default:
479 tcg_abort();
481 return cpu_regs[reg];
484 static void gen_op_mov_reg_v(DisasContext *s, MemOp ot, int reg, TCGv t0)
486 gen_op_deposit_reg_v(s, ot, reg, NULL, t0);
489 static inline
490 void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg)
492 if (ot == MO_8 && byte_reg_is_xH(s, reg)) {
493 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
494 } else {
495 tcg_gen_mov_tl(t0, cpu_regs[reg]);
499 static void gen_add_A0_im(DisasContext *s, int val)
501 tcg_gen_addi_tl(s->A0, s->A0, val);
502 if (!CODE64(s)) {
503 tcg_gen_ext32u_tl(s->A0, s->A0);
507 static inline void gen_op_jmp_v(DisasContext *s, TCGv dest)
509 tcg_gen_mov_tl(cpu_eip, dest);
510 s->pc_save = -1;
513 static inline
514 void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val)
516 tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val);
517 gen_op_mov_reg_v(s, size, reg, s->tmp0);
520 static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg)
522 tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0);
523 gen_op_mov_reg_v(s, size, reg, s->tmp0);
526 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
528 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
531 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
533 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
536 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
538 if (d == OR_TMP0) {
539 gen_op_st_v(s, idx, s->T0, s->A0);
540 } else {
541 gen_op_mov_reg_v(s, idx, d, s->T0);
545 static void gen_update_eip_cur(DisasContext *s)
547 assert(s->pc_save != -1);
548 if (TARGET_TB_PCREL) {
549 tcg_gen_addi_tl(cpu_eip, cpu_eip, s->base.pc_next - s->pc_save);
550 } else {
551 tcg_gen_movi_tl(cpu_eip, s->base.pc_next - s->cs_base);
553 s->pc_save = s->base.pc_next;
556 static void gen_update_eip_next(DisasContext *s)
558 assert(s->pc_save != -1);
559 if (TARGET_TB_PCREL) {
560 tcg_gen_addi_tl(cpu_eip, cpu_eip, s->pc - s->pc_save);
561 } else {
562 tcg_gen_movi_tl(cpu_eip, s->pc - s->cs_base);
564 s->pc_save = s->pc;
567 static int cur_insn_len(DisasContext *s)
569 return s->pc - s->base.pc_next;
572 static TCGv_i32 cur_insn_len_i32(DisasContext *s)
574 return tcg_constant_i32(cur_insn_len(s));
577 static TCGv_i32 eip_next_i32(DisasContext *s)
579 assert(s->pc_save != -1);
581 * This function has two users: lcall_real (always 16-bit mode), and
582 * iret_protected (16, 32, or 64-bit mode). IRET only uses the value
583 * when EFLAGS.NT is set, which is illegal in 64-bit mode, which is
584 * why passing a 32-bit value isn't broken. To avoid using this where
585 * we shouldn't, return -1 in 64-bit mode so that execution goes into
586 * the weeds quickly.
588 if (CODE64(s)) {
589 return tcg_constant_i32(-1);
591 if (TARGET_TB_PCREL) {
592 TCGv_i32 ret = tcg_temp_new_i32();
593 tcg_gen_trunc_tl_i32(ret, cpu_eip);
594 tcg_gen_addi_i32(ret, ret, s->pc - s->pc_save);
595 return ret;
596 } else {
597 return tcg_constant_i32(s->pc - s->cs_base);
601 static TCGv eip_next_tl(DisasContext *s)
603 assert(s->pc_save != -1);
604 if (TARGET_TB_PCREL) {
605 TCGv ret = tcg_temp_new();
606 tcg_gen_addi_tl(ret, cpu_eip, s->pc - s->pc_save);
607 return ret;
608 } else {
609 return tcg_constant_tl(s->pc - s->cs_base);
613 static TCGv eip_cur_tl(DisasContext *s)
615 assert(s->pc_save != -1);
616 if (TARGET_TB_PCREL) {
617 TCGv ret = tcg_temp_new();
618 tcg_gen_addi_tl(ret, cpu_eip, s->base.pc_next - s->pc_save);
619 return ret;
620 } else {
621 return tcg_constant_tl(s->base.pc_next - s->cs_base);
625 /* Compute SEG:REG into A0. SEG is selected from the override segment
626 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
627 indicate no override. */
628 static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
629 int def_seg, int ovr_seg)
631 switch (aflag) {
632 #ifdef TARGET_X86_64
633 case MO_64:
634 if (ovr_seg < 0) {
635 tcg_gen_mov_tl(s->A0, a0);
636 return;
638 break;
639 #endif
640 case MO_32:
641 /* 32 bit address */
642 if (ovr_seg < 0 && ADDSEG(s)) {
643 ovr_seg = def_seg;
645 if (ovr_seg < 0) {
646 tcg_gen_ext32u_tl(s->A0, a0);
647 return;
649 break;
650 case MO_16:
651 /* 16 bit address */
652 tcg_gen_ext16u_tl(s->A0, a0);
653 a0 = s->A0;
654 if (ovr_seg < 0) {
655 if (ADDSEG(s)) {
656 ovr_seg = def_seg;
657 } else {
658 return;
661 break;
662 default:
663 tcg_abort();
666 if (ovr_seg >= 0) {
667 TCGv seg = cpu_seg_base[ovr_seg];
669 if (aflag == MO_64) {
670 tcg_gen_add_tl(s->A0, a0, seg);
671 } else if (CODE64(s)) {
672 tcg_gen_ext32u_tl(s->A0, a0);
673 tcg_gen_add_tl(s->A0, s->A0, seg);
674 } else {
675 tcg_gen_add_tl(s->A0, a0, seg);
676 tcg_gen_ext32u_tl(s->A0, s->A0);
681 static inline void gen_string_movl_A0_ESI(DisasContext *s)
683 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
686 static inline void gen_string_movl_A0_EDI(DisasContext *s)
688 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
691 static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
693 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
694 tcg_gen_shli_tl(s->T0, s->T0, ot);
697 static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
699 switch (size) {
700 case MO_8:
701 if (sign) {
702 tcg_gen_ext8s_tl(dst, src);
703 } else {
704 tcg_gen_ext8u_tl(dst, src);
706 return dst;
707 case MO_16:
708 if (sign) {
709 tcg_gen_ext16s_tl(dst, src);
710 } else {
711 tcg_gen_ext16u_tl(dst, src);
713 return dst;
714 #ifdef TARGET_X86_64
715 case MO_32:
716 if (sign) {
717 tcg_gen_ext32s_tl(dst, src);
718 } else {
719 tcg_gen_ext32u_tl(dst, src);
721 return dst;
722 #endif
723 default:
724 return src;
728 static void gen_extu(MemOp ot, TCGv reg)
730 gen_ext_tl(reg, reg, ot, false);
733 static void gen_exts(MemOp ot, TCGv reg)
735 gen_ext_tl(reg, reg, ot, true);
738 static void gen_op_j_ecx(DisasContext *s, TCGCond cond, TCGLabel *label1)
740 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
741 gen_extu(s->aflag, s->tmp0);
742 tcg_gen_brcondi_tl(cond, s->tmp0, 0, label1);
745 static inline void gen_op_jz_ecx(DisasContext *s, TCGLabel *label1)
747 gen_op_j_ecx(s, TCG_COND_EQ, label1);
750 static inline void gen_op_jnz_ecx(DisasContext *s, TCGLabel *label1)
752 gen_op_j_ecx(s, TCG_COND_NE, label1);
755 static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
757 switch (ot) {
758 case MO_8:
759 gen_helper_inb(v, cpu_env, n);
760 break;
761 case MO_16:
762 gen_helper_inw(v, cpu_env, n);
763 break;
764 case MO_32:
765 gen_helper_inl(v, cpu_env, n);
766 break;
767 default:
768 tcg_abort();
772 static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
774 switch (ot) {
775 case MO_8:
776 gen_helper_outb(cpu_env, v, n);
777 break;
778 case MO_16:
779 gen_helper_outw(cpu_env, v, n);
780 break;
781 case MO_32:
782 gen_helper_outl(cpu_env, v, n);
783 break;
784 default:
785 tcg_abort();
790 * Validate that access to [port, port + 1<<ot) is allowed.
791 * Raise #GP, or VMM exit if not.
793 static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
794 uint32_t svm_flags)
796 #ifdef CONFIG_USER_ONLY
798 * We do not implement the ioperm(2) syscall, so the TSS check
799 * will always fail.
801 gen_exception_gpf(s);
802 return false;
803 #else
804 if (PE(s) && (CPL(s) > IOPL(s) || VM86(s))) {
805 gen_helper_check_io(cpu_env, port, tcg_constant_i32(1 << ot));
807 if (GUEST(s)) {
808 gen_update_cc_op(s);
809 gen_update_eip_cur(s);
810 if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
811 svm_flags |= SVM_IOIO_REP_MASK;
813 svm_flags |= 1 << (SVM_IOIO_SIZE_SHIFT + ot);
814 gen_helper_svm_check_io(cpu_env, port,
815 tcg_constant_i32(svm_flags),
816 cur_insn_len_i32(s));
818 return true;
819 #endif
822 static void gen_movs(DisasContext *s, MemOp ot)
824 gen_string_movl_A0_ESI(s);
825 gen_op_ld_v(s, ot, s->T0, s->A0);
826 gen_string_movl_A0_EDI(s);
827 gen_op_st_v(s, ot, s->T0, s->A0);
828 gen_op_movl_T0_Dshift(s, ot);
829 gen_op_add_reg_T0(s, s->aflag, R_ESI);
830 gen_op_add_reg_T0(s, s->aflag, R_EDI);
833 static void gen_op_update1_cc(DisasContext *s)
835 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
838 static void gen_op_update2_cc(DisasContext *s)
840 tcg_gen_mov_tl(cpu_cc_src, s->T1);
841 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
844 static void gen_op_update3_cc(DisasContext *s, TCGv reg)
846 tcg_gen_mov_tl(cpu_cc_src2, reg);
847 tcg_gen_mov_tl(cpu_cc_src, s->T1);
848 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
851 static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
853 tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1);
856 static void gen_op_update_neg_cc(DisasContext *s)
858 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
859 tcg_gen_neg_tl(cpu_cc_src, s->T0);
860 tcg_gen_movi_tl(s->cc_srcT, 0);
863 /* compute all eflags to cc_src */
864 static void gen_compute_eflags(DisasContext *s)
866 TCGv zero, dst, src1, src2;
867 int live, dead;
869 if (s->cc_op == CC_OP_EFLAGS) {
870 return;
872 if (s->cc_op == CC_OP_CLR) {
873 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
874 set_cc_op(s, CC_OP_EFLAGS);
875 return;
878 zero = NULL;
879 dst = cpu_cc_dst;
880 src1 = cpu_cc_src;
881 src2 = cpu_cc_src2;
883 /* Take care to not read values that are not live. */
884 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
885 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
886 if (dead) {
887 zero = tcg_const_tl(0);
888 if (dead & USES_CC_DST) {
889 dst = zero;
891 if (dead & USES_CC_SRC) {
892 src1 = zero;
894 if (dead & USES_CC_SRC2) {
895 src2 = zero;
899 gen_update_cc_op(s);
900 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
901 set_cc_op(s, CC_OP_EFLAGS);
903 if (dead) {
904 tcg_temp_free(zero);
908 typedef struct CCPrepare {
909 TCGCond cond;
910 TCGv reg;
911 TCGv reg2;
912 target_ulong imm;
913 target_ulong mask;
914 bool use_reg2;
915 bool no_setcond;
916 } CCPrepare;
918 /* compute eflags.C to reg */
919 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
921 TCGv t0, t1;
922 int size, shift;
924 switch (s->cc_op) {
925 case CC_OP_SUBB ... CC_OP_SUBQ:
926 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
927 size = s->cc_op - CC_OP_SUBB;
928 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
929 /* If no temporary was used, be careful not to alias t1 and t0. */
930 t0 = t1 == cpu_cc_src ? s->tmp0 : reg;
931 tcg_gen_mov_tl(t0, s->cc_srcT);
932 gen_extu(size, t0);
933 goto add_sub;
935 case CC_OP_ADDB ... CC_OP_ADDQ:
936 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
937 size = s->cc_op - CC_OP_ADDB;
938 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
939 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
940 add_sub:
941 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
942 .reg2 = t1, .mask = -1, .use_reg2 = true };
944 case CC_OP_LOGICB ... CC_OP_LOGICQ:
945 case CC_OP_CLR:
946 case CC_OP_POPCNT:
947 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
949 case CC_OP_INCB ... CC_OP_INCQ:
950 case CC_OP_DECB ... CC_OP_DECQ:
951 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
952 .mask = -1, .no_setcond = true };
954 case CC_OP_SHLB ... CC_OP_SHLQ:
955 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
956 size = s->cc_op - CC_OP_SHLB;
957 shift = (8 << size) - 1;
958 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
959 .mask = (target_ulong)1 << shift };
961 case CC_OP_MULB ... CC_OP_MULQ:
962 return (CCPrepare) { .cond = TCG_COND_NE,
963 .reg = cpu_cc_src, .mask = -1 };
965 case CC_OP_BMILGB ... CC_OP_BMILGQ:
966 size = s->cc_op - CC_OP_BMILGB;
967 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
968 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
970 case CC_OP_ADCX:
971 case CC_OP_ADCOX:
972 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
973 .mask = -1, .no_setcond = true };
975 case CC_OP_EFLAGS:
976 case CC_OP_SARB ... CC_OP_SARQ:
977 /* CC_SRC & 1 */
978 return (CCPrepare) { .cond = TCG_COND_NE,
979 .reg = cpu_cc_src, .mask = CC_C };
981 default:
982 /* The need to compute only C from CC_OP_DYNAMIC is important
983 in efficiently implementing e.g. INC at the start of a TB. */
984 gen_update_cc_op(s);
985 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
986 cpu_cc_src2, cpu_cc_op);
987 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
988 .mask = -1, .no_setcond = true };
992 /* compute eflags.P to reg */
993 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
995 gen_compute_eflags(s);
996 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
997 .mask = CC_P };
1000 /* compute eflags.S to reg */
1001 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
1003 switch (s->cc_op) {
1004 case CC_OP_DYNAMIC:
1005 gen_compute_eflags(s);
1006 /* FALLTHRU */
1007 case CC_OP_EFLAGS:
1008 case CC_OP_ADCX:
1009 case CC_OP_ADOX:
1010 case CC_OP_ADCOX:
1011 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1012 .mask = CC_S };
1013 case CC_OP_CLR:
1014 case CC_OP_POPCNT:
1015 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
1016 default:
1018 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
1019 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
1020 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
1025 /* compute eflags.O to reg */
1026 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
1028 switch (s->cc_op) {
1029 case CC_OP_ADOX:
1030 case CC_OP_ADCOX:
1031 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
1032 .mask = -1, .no_setcond = true };
1033 case CC_OP_CLR:
1034 case CC_OP_POPCNT:
1035 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
1036 default:
1037 gen_compute_eflags(s);
1038 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1039 .mask = CC_O };
1043 /* compute eflags.Z to reg */
1044 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
1046 switch (s->cc_op) {
1047 case CC_OP_DYNAMIC:
1048 gen_compute_eflags(s);
1049 /* FALLTHRU */
1050 case CC_OP_EFLAGS:
1051 case CC_OP_ADCX:
1052 case CC_OP_ADOX:
1053 case CC_OP_ADCOX:
1054 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1055 .mask = CC_Z };
1056 case CC_OP_CLR:
1057 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
1058 case CC_OP_POPCNT:
1059 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
1060 .mask = -1 };
1061 default:
1063 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
1064 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
1065 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
1070 /* perform a conditional store into register 'reg' according to jump opcode
1071 value 'b'. In the fast case, T0 is guaranted not to be used. */
1072 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
1074 int inv, jcc_op, cond;
1075 MemOp size;
1076 CCPrepare cc;
1077 TCGv t0;
1079 inv = b & 1;
1080 jcc_op = (b >> 1) & 7;
1082 switch (s->cc_op) {
1083 case CC_OP_SUBB ... CC_OP_SUBQ:
1084 /* We optimize relational operators for the cmp/jcc case. */
1085 size = s->cc_op - CC_OP_SUBB;
1086 switch (jcc_op) {
1087 case JCC_BE:
1088 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
1089 gen_extu(size, s->tmp4);
1090 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
1091 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4,
1092 .reg2 = t0, .mask = -1, .use_reg2 = true };
1093 break;
1095 case JCC_L:
1096 cond = TCG_COND_LT;
1097 goto fast_jcc_l;
1098 case JCC_LE:
1099 cond = TCG_COND_LE;
1100 fast_jcc_l:
1101 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
1102 gen_exts(size, s->tmp4);
1103 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true);
1104 cc = (CCPrepare) { .cond = cond, .reg = s->tmp4,
1105 .reg2 = t0, .mask = -1, .use_reg2 = true };
1106 break;
1108 default:
1109 goto slow_jcc;
1111 break;
1113 default:
1114 slow_jcc:
1115 /* This actually generates good code for JC, JZ and JS. */
1116 switch (jcc_op) {
1117 case JCC_O:
1118 cc = gen_prepare_eflags_o(s, reg);
1119 break;
1120 case JCC_B:
1121 cc = gen_prepare_eflags_c(s, reg);
1122 break;
1123 case JCC_Z:
1124 cc = gen_prepare_eflags_z(s, reg);
1125 break;
1126 case JCC_BE:
1127 gen_compute_eflags(s);
1128 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1129 .mask = CC_Z | CC_C };
1130 break;
1131 case JCC_S:
1132 cc = gen_prepare_eflags_s(s, reg);
1133 break;
1134 case JCC_P:
1135 cc = gen_prepare_eflags_p(s, reg);
1136 break;
1137 case JCC_L:
1138 gen_compute_eflags(s);
1139 if (reg == cpu_cc_src) {
1140 reg = s->tmp0;
1142 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1143 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1144 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1145 .mask = CC_S };
1146 break;
1147 default:
1148 case JCC_LE:
1149 gen_compute_eflags(s);
1150 if (reg == cpu_cc_src) {
1151 reg = s->tmp0;
1153 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1154 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1155 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1156 .mask = CC_S | CC_Z };
1157 break;
1159 break;
1162 if (inv) {
1163 cc.cond = tcg_invert_cond(cc.cond);
1165 return cc;
1168 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1170 CCPrepare cc = gen_prepare_cc(s, b, reg);
1172 if (cc.no_setcond) {
1173 if (cc.cond == TCG_COND_EQ) {
1174 tcg_gen_xori_tl(reg, cc.reg, 1);
1175 } else {
1176 tcg_gen_mov_tl(reg, cc.reg);
1178 return;
1181 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1182 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1183 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1184 tcg_gen_andi_tl(reg, reg, 1);
1185 return;
1187 if (cc.mask != -1) {
1188 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1189 cc.reg = reg;
1191 if (cc.use_reg2) {
1192 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1193 } else {
1194 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1198 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1200 gen_setcc1(s, JCC_B << 1, reg);
1203 /* generate a conditional jump to label 'l1' according to jump opcode
1204 value 'b'. In the fast case, T0 is guaranted not to be used. */
1205 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1207 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1209 if (cc.mask != -1) {
1210 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1211 cc.reg = s->T0;
1213 if (cc.use_reg2) {
1214 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1215 } else {
1216 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1220 /* Generate a conditional jump to label 'l1' according to jump opcode
1221 value 'b'. In the fast case, T0 is guaranted not to be used.
1222 A translation block must end soon. */
1223 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1225 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1227 gen_update_cc_op(s);
1228 if (cc.mask != -1) {
1229 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1230 cc.reg = s->T0;
1232 set_cc_op(s, CC_OP_DYNAMIC);
1233 if (cc.use_reg2) {
1234 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1235 } else {
1236 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1240 /* XXX: does not work with gdbstub "ice" single step - not a
1241 serious problem */
1242 static TCGLabel *gen_jz_ecx_string(DisasContext *s)
1244 TCGLabel *l1 = gen_new_label();
1245 TCGLabel *l2 = gen_new_label();
1246 gen_op_jnz_ecx(s, l1);
1247 gen_set_label(l2);
1248 gen_jmp_rel_csize(s, 0, 1);
1249 gen_set_label(l1);
1250 return l2;
1253 static void gen_stos(DisasContext *s, MemOp ot)
1255 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
1256 gen_string_movl_A0_EDI(s);
1257 gen_op_st_v(s, ot, s->T0, s->A0);
1258 gen_op_movl_T0_Dshift(s, ot);
1259 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1262 static void gen_lods(DisasContext *s, MemOp ot)
1264 gen_string_movl_A0_ESI(s);
1265 gen_op_ld_v(s, ot, s->T0, s->A0);
1266 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
1267 gen_op_movl_T0_Dshift(s, ot);
1268 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1271 static void gen_scas(DisasContext *s, MemOp ot)
1273 gen_string_movl_A0_EDI(s);
1274 gen_op_ld_v(s, ot, s->T1, s->A0);
1275 gen_op(s, OP_CMPL, ot, R_EAX);
1276 gen_op_movl_T0_Dshift(s, ot);
1277 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1280 static void gen_cmps(DisasContext *s, MemOp ot)
1282 gen_string_movl_A0_EDI(s);
1283 gen_op_ld_v(s, ot, s->T1, s->A0);
1284 gen_string_movl_A0_ESI(s);
1285 gen_op(s, OP_CMPL, ot, OR_TMP0);
1286 gen_op_movl_T0_Dshift(s, ot);
1287 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1288 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1291 static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1293 if (s->flags & HF_IOBPT_MASK) {
1294 #ifdef CONFIG_USER_ONLY
1295 /* user-mode cpu should not be in IOBPT mode */
1296 g_assert_not_reached();
1297 #else
1298 TCGv_i32 t_size = tcg_constant_i32(1 << ot);
1299 TCGv t_next = eip_next_tl(s);
1300 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1301 #endif /* CONFIG_USER_ONLY */
1305 static void gen_ins(DisasContext *s, MemOp ot)
1307 gen_string_movl_A0_EDI(s);
1308 /* Note: we must do this dummy write first to be restartable in
1309 case of page fault. */
1310 tcg_gen_movi_tl(s->T0, 0);
1311 gen_op_st_v(s, ot, s->T0, s->A0);
1312 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1313 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1314 gen_helper_in_func(ot, s->T0, s->tmp2_i32);
1315 gen_op_st_v(s, ot, s->T0, s->A0);
1316 gen_op_movl_T0_Dshift(s, ot);
1317 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1318 gen_bpt_io(s, s->tmp2_i32, ot);
1321 static void gen_outs(DisasContext *s, MemOp ot)
1323 gen_string_movl_A0_ESI(s);
1324 gen_op_ld_v(s, ot, s->T0, s->A0);
1326 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1327 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1328 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0);
1329 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
1330 gen_op_movl_T0_Dshift(s, ot);
1331 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1332 gen_bpt_io(s, s->tmp2_i32, ot);
1335 /* Generate jumps to current or next instruction */
1336 static void gen_repz(DisasContext *s, MemOp ot,
1337 void (*fn)(DisasContext *s, MemOp ot))
1339 TCGLabel *l2;
1340 gen_update_cc_op(s);
1341 l2 = gen_jz_ecx_string(s);
1342 fn(s, ot);
1343 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
1345 * A loop would cause two single step exceptions if ECX = 1
1346 * before rep string_insn
1348 if (s->repz_opt) {
1349 gen_op_jz_ecx(s, l2);
1351 gen_jmp_rel_csize(s, -cur_insn_len(s), 0);
1354 #define GEN_REPZ(op) \
1355 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot) \
1356 { gen_repz(s, ot, gen_##op); }
1358 static void gen_repz2(DisasContext *s, MemOp ot, int nz,
1359 void (*fn)(DisasContext *s, MemOp ot))
1361 TCGLabel *l2;
1362 gen_update_cc_op(s);
1363 l2 = gen_jz_ecx_string(s);
1364 fn(s, ot);
1365 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
1366 gen_update_cc_op(s);
1367 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2);
1368 if (s->repz_opt) {
1369 gen_op_jz_ecx(s, l2);
1371 gen_jmp_rel_csize(s, -cur_insn_len(s), 0);
1374 #define GEN_REPZ2(op) \
1375 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, int nz) \
1376 { gen_repz2(s, ot, nz, gen_##op); }
1378 GEN_REPZ(movs)
1379 GEN_REPZ(stos)
1380 GEN_REPZ(lods)
1381 GEN_REPZ(ins)
1382 GEN_REPZ(outs)
1383 GEN_REPZ2(scas)
1384 GEN_REPZ2(cmps)
1386 static void gen_helper_fp_arith_ST0_FT0(int op)
1388 switch (op) {
1389 case 0:
1390 gen_helper_fadd_ST0_FT0(cpu_env);
1391 break;
1392 case 1:
1393 gen_helper_fmul_ST0_FT0(cpu_env);
1394 break;
1395 case 2:
1396 gen_helper_fcom_ST0_FT0(cpu_env);
1397 break;
1398 case 3:
1399 gen_helper_fcom_ST0_FT0(cpu_env);
1400 break;
1401 case 4:
1402 gen_helper_fsub_ST0_FT0(cpu_env);
1403 break;
1404 case 5:
1405 gen_helper_fsubr_ST0_FT0(cpu_env);
1406 break;
1407 case 6:
1408 gen_helper_fdiv_ST0_FT0(cpu_env);
1409 break;
1410 case 7:
1411 gen_helper_fdivr_ST0_FT0(cpu_env);
1412 break;
1416 /* NOTE the exception in "r" op ordering */
1417 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1419 TCGv_i32 tmp = tcg_const_i32(opreg);
1420 switch (op) {
1421 case 0:
1422 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1423 break;
1424 case 1:
1425 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1426 break;
1427 case 4:
1428 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1429 break;
1430 case 5:
1431 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1432 break;
1433 case 6:
1434 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1435 break;
1436 case 7:
1437 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1438 break;
1442 static void gen_exception(DisasContext *s, int trapno)
1444 gen_update_cc_op(s);
1445 gen_update_eip_cur(s);
1446 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
1447 s->base.is_jmp = DISAS_NORETURN;
1450 /* Generate #UD for the current instruction. The assumption here is that
1451 the instruction is known, but it isn't allowed in the current cpu mode. */
1452 static void gen_illegal_opcode(DisasContext *s)
1454 gen_exception(s, EXCP06_ILLOP);
1457 /* Generate #GP for the current instruction. */
1458 static void gen_exception_gpf(DisasContext *s)
1460 gen_exception(s, EXCP0D_GPF);
1463 /* Check for cpl == 0; if not, raise #GP and return false. */
1464 static bool check_cpl0(DisasContext *s)
1466 if (CPL(s) == 0) {
1467 return true;
1469 gen_exception_gpf(s);
1470 return false;
1473 /* If vm86, check for iopl == 3; if not, raise #GP and return false. */
1474 static bool check_vm86_iopl(DisasContext *s)
1476 if (!VM86(s) || IOPL(s) == 3) {
1477 return true;
1479 gen_exception_gpf(s);
1480 return false;
1483 /* Check for iopl allowing access; if not, raise #GP and return false. */
1484 static bool check_iopl(DisasContext *s)
1486 if (VM86(s) ? IOPL(s) == 3 : CPL(s) <= IOPL(s)) {
1487 return true;
1489 gen_exception_gpf(s);
1490 return false;
1493 /* if d == OR_TMP0, it means memory operand (address in A0) */
1494 static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
1496 if (d != OR_TMP0) {
1497 if (s1->prefix & PREFIX_LOCK) {
1498 /* Lock prefix when destination is not memory. */
1499 gen_illegal_opcode(s1);
1500 return;
1502 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1503 } else if (!(s1->prefix & PREFIX_LOCK)) {
1504 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1506 switch(op) {
1507 case OP_ADCL:
1508 gen_compute_eflags_c(s1, s1->tmp4);
1509 if (s1->prefix & PREFIX_LOCK) {
1510 tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1);
1511 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1512 s1->mem_index, ot | MO_LE);
1513 } else {
1514 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1515 tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4);
1516 gen_op_st_rm_T0_A0(s1, ot, d);
1518 gen_op_update3_cc(s1, s1->tmp4);
1519 set_cc_op(s1, CC_OP_ADCB + ot);
1520 break;
1521 case OP_SBBL:
1522 gen_compute_eflags_c(s1, s1->tmp4);
1523 if (s1->prefix & PREFIX_LOCK) {
1524 tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4);
1525 tcg_gen_neg_tl(s1->T0, s1->T0);
1526 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1527 s1->mem_index, ot | MO_LE);
1528 } else {
1529 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1530 tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4);
1531 gen_op_st_rm_T0_A0(s1, ot, d);
1533 gen_op_update3_cc(s1, s1->tmp4);
1534 set_cc_op(s1, CC_OP_SBBB + ot);
1535 break;
1536 case OP_ADDL:
1537 if (s1->prefix & PREFIX_LOCK) {
1538 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1,
1539 s1->mem_index, ot | MO_LE);
1540 } else {
1541 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1542 gen_op_st_rm_T0_A0(s1, ot, d);
1544 gen_op_update2_cc(s1);
1545 set_cc_op(s1, CC_OP_ADDB + ot);
1546 break;
1547 case OP_SUBL:
1548 if (s1->prefix & PREFIX_LOCK) {
1549 tcg_gen_neg_tl(s1->T0, s1->T1);
1550 tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
1551 s1->mem_index, ot | MO_LE);
1552 tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
1553 } else {
1554 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1555 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1556 gen_op_st_rm_T0_A0(s1, ot, d);
1558 gen_op_update2_cc(s1);
1559 set_cc_op(s1, CC_OP_SUBB + ot);
1560 break;
1561 default:
1562 case OP_ANDL:
1563 if (s1->prefix & PREFIX_LOCK) {
1564 tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1,
1565 s1->mem_index, ot | MO_LE);
1566 } else {
1567 tcg_gen_and_tl(s1->T0, s1->T0, s1->T1);
1568 gen_op_st_rm_T0_A0(s1, ot, d);
1570 gen_op_update1_cc(s1);
1571 set_cc_op(s1, CC_OP_LOGICB + ot);
1572 break;
1573 case OP_ORL:
1574 if (s1->prefix & PREFIX_LOCK) {
1575 tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1,
1576 s1->mem_index, ot | MO_LE);
1577 } else {
1578 tcg_gen_or_tl(s1->T0, s1->T0, s1->T1);
1579 gen_op_st_rm_T0_A0(s1, ot, d);
1581 gen_op_update1_cc(s1);
1582 set_cc_op(s1, CC_OP_LOGICB + ot);
1583 break;
1584 case OP_XORL:
1585 if (s1->prefix & PREFIX_LOCK) {
1586 tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1,
1587 s1->mem_index, ot | MO_LE);
1588 } else {
1589 tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1);
1590 gen_op_st_rm_T0_A0(s1, ot, d);
1592 gen_op_update1_cc(s1);
1593 set_cc_op(s1, CC_OP_LOGICB + ot);
1594 break;
1595 case OP_CMPL:
1596 tcg_gen_mov_tl(cpu_cc_src, s1->T1);
1597 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1598 tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
1599 set_cc_op(s1, CC_OP_SUBB + ot);
1600 break;
1604 /* if d == OR_TMP0, it means memory operand (address in A0) */
1605 static void gen_inc(DisasContext *s1, MemOp ot, int d, int c)
1607 if (s1->prefix & PREFIX_LOCK) {
1608 if (d != OR_TMP0) {
1609 /* Lock prefix when destination is not memory */
1610 gen_illegal_opcode(s1);
1611 return;
1613 tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
1614 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1615 s1->mem_index, ot | MO_LE);
1616 } else {
1617 if (d != OR_TMP0) {
1618 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1619 } else {
1620 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1622 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
1623 gen_op_st_rm_T0_A0(s1, ot, d);
1626 gen_compute_eflags_c(s1, cpu_cc_src);
1627 tcg_gen_mov_tl(cpu_cc_dst, s1->T0);
1628 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1631 static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
1632 TCGv shm1, TCGv count, bool is_right)
1634 TCGv_i32 z32, s32, oldop;
1635 TCGv z_tl;
1637 /* Store the results into the CC variables. If we know that the
1638 variable must be dead, store unconditionally. Otherwise we'll
1639 need to not disrupt the current contents. */
1640 z_tl = tcg_const_tl(0);
1641 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1642 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1643 result, cpu_cc_dst);
1644 } else {
1645 tcg_gen_mov_tl(cpu_cc_dst, result);
1647 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1648 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1649 shm1, cpu_cc_src);
1650 } else {
1651 tcg_gen_mov_tl(cpu_cc_src, shm1);
1653 tcg_temp_free(z_tl);
1655 /* Get the two potential CC_OP values into temporaries. */
1656 tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1657 if (s->cc_op == CC_OP_DYNAMIC) {
1658 oldop = cpu_cc_op;
1659 } else {
1660 tcg_gen_movi_i32(s->tmp3_i32, s->cc_op);
1661 oldop = s->tmp3_i32;
1664 /* Conditionally store the CC_OP value. */
1665 z32 = tcg_const_i32(0);
1666 s32 = tcg_temp_new_i32();
1667 tcg_gen_trunc_tl_i32(s32, count);
1668 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop);
1669 tcg_temp_free_i32(z32);
1670 tcg_temp_free_i32(s32);
1672 /* The CC_OP value is no longer predictable. */
1673 set_cc_op(s, CC_OP_DYNAMIC);
1676 static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1,
1677 int is_right, int is_arith)
1679 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1681 /* load */
1682 if (op1 == OR_TMP0) {
1683 gen_op_ld_v(s, ot, s->T0, s->A0);
1684 } else {
1685 gen_op_mov_v_reg(s, ot, s->T0, op1);
1688 tcg_gen_andi_tl(s->T1, s->T1, mask);
1689 tcg_gen_subi_tl(s->tmp0, s->T1, 1);
1691 if (is_right) {
1692 if (is_arith) {
1693 gen_exts(ot, s->T0);
1694 tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0);
1695 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
1696 } else {
1697 gen_extu(ot, s->T0);
1698 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1699 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
1701 } else {
1702 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1703 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
1706 /* store */
1707 gen_op_st_rm_T0_A0(s, ot, op1);
1709 gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right);
1712 static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1713 int is_right, int is_arith)
1715 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1717 /* load */
1718 if (op1 == OR_TMP0)
1719 gen_op_ld_v(s, ot, s->T0, s->A0);
1720 else
1721 gen_op_mov_v_reg(s, ot, s->T0, op1);
1723 op2 &= mask;
1724 if (op2 != 0) {
1725 if (is_right) {
1726 if (is_arith) {
1727 gen_exts(ot, s->T0);
1728 tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1);
1729 tcg_gen_sari_tl(s->T0, s->T0, op2);
1730 } else {
1731 gen_extu(ot, s->T0);
1732 tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1);
1733 tcg_gen_shri_tl(s->T0, s->T0, op2);
1735 } else {
1736 tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1);
1737 tcg_gen_shli_tl(s->T0, s->T0, op2);
1741 /* store */
1742 gen_op_st_rm_T0_A0(s, ot, op1);
1744 /* update eflags if non zero shift */
1745 if (op2 != 0) {
1746 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
1747 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
1748 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1752 static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right)
1754 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1755 TCGv_i32 t0, t1;
1757 /* load */
1758 if (op1 == OR_TMP0) {
1759 gen_op_ld_v(s, ot, s->T0, s->A0);
1760 } else {
1761 gen_op_mov_v_reg(s, ot, s->T0, op1);
1764 tcg_gen_andi_tl(s->T1, s->T1, mask);
1766 switch (ot) {
1767 case MO_8:
1768 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1769 tcg_gen_ext8u_tl(s->T0, s->T0);
1770 tcg_gen_muli_tl(s->T0, s->T0, 0x01010101);
1771 goto do_long;
1772 case MO_16:
1773 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1774 tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16);
1775 goto do_long;
1776 do_long:
1777 #ifdef TARGET_X86_64
1778 case MO_32:
1779 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1780 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
1781 if (is_right) {
1782 tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1783 } else {
1784 tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1786 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1787 break;
1788 #endif
1789 default:
1790 if (is_right) {
1791 tcg_gen_rotr_tl(s->T0, s->T0, s->T1);
1792 } else {
1793 tcg_gen_rotl_tl(s->T0, s->T0, s->T1);
1795 break;
1798 /* store */
1799 gen_op_st_rm_T0_A0(s, ot, op1);
1801 /* We'll need the flags computed into CC_SRC. */
1802 gen_compute_eflags(s);
1804 /* The value that was "rotated out" is now present at the other end
1805 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1806 since we've computed the flags into CC_SRC, these variables are
1807 currently dead. */
1808 if (is_right) {
1809 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1810 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1811 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1812 } else {
1813 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1814 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1816 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1817 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1819 /* Now conditionally store the new CC_OP value. If the shift count
1820 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1821 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1822 exactly as we computed above. */
1823 t0 = tcg_const_i32(0);
1824 t1 = tcg_temp_new_i32();
1825 tcg_gen_trunc_tl_i32(t1, s->T1);
1826 tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX);
1827 tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS);
1828 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1829 s->tmp2_i32, s->tmp3_i32);
1830 tcg_temp_free_i32(t0);
1831 tcg_temp_free_i32(t1);
1833 /* The CC_OP value is no longer predictable. */
1834 set_cc_op(s, CC_OP_DYNAMIC);
1837 static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1838 int is_right)
1840 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1841 int shift;
1843 /* load */
1844 if (op1 == OR_TMP0) {
1845 gen_op_ld_v(s, ot, s->T0, s->A0);
1846 } else {
1847 gen_op_mov_v_reg(s, ot, s->T0, op1);
1850 op2 &= mask;
1851 if (op2 != 0) {
1852 switch (ot) {
1853 #ifdef TARGET_X86_64
1854 case MO_32:
1855 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1856 if (is_right) {
1857 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2);
1858 } else {
1859 tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2);
1861 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1862 break;
1863 #endif
1864 default:
1865 if (is_right) {
1866 tcg_gen_rotri_tl(s->T0, s->T0, op2);
1867 } else {
1868 tcg_gen_rotli_tl(s->T0, s->T0, op2);
1870 break;
1871 case MO_8:
1872 mask = 7;
1873 goto do_shifts;
1874 case MO_16:
1875 mask = 15;
1876 do_shifts:
1877 shift = op2 & mask;
1878 if (is_right) {
1879 shift = mask + 1 - shift;
1881 gen_extu(ot, s->T0);
1882 tcg_gen_shli_tl(s->tmp0, s->T0, shift);
1883 tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift);
1884 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
1885 break;
1889 /* store */
1890 gen_op_st_rm_T0_A0(s, ot, op1);
1892 if (op2 != 0) {
1893 /* Compute the flags into CC_SRC. */
1894 gen_compute_eflags(s);
1896 /* The value that was "rotated out" is now present at the other end
1897 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1898 since we've computed the flags into CC_SRC, these variables are
1899 currently dead. */
1900 if (is_right) {
1901 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1902 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1903 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1904 } else {
1905 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1906 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1908 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1909 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1910 set_cc_op(s, CC_OP_ADCOX);
1914 /* XXX: add faster immediate = 1 case */
1915 static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
1916 int is_right)
1918 gen_compute_eflags(s);
1919 assert(s->cc_op == CC_OP_EFLAGS);
1921 /* load */
1922 if (op1 == OR_TMP0)
1923 gen_op_ld_v(s, ot, s->T0, s->A0);
1924 else
1925 gen_op_mov_v_reg(s, ot, s->T0, op1);
1927 if (is_right) {
1928 switch (ot) {
1929 case MO_8:
1930 gen_helper_rcrb(s->T0, cpu_env, s->T0, s->T1);
1931 break;
1932 case MO_16:
1933 gen_helper_rcrw(s->T0, cpu_env, s->T0, s->T1);
1934 break;
1935 case MO_32:
1936 gen_helper_rcrl(s->T0, cpu_env, s->T0, s->T1);
1937 break;
1938 #ifdef TARGET_X86_64
1939 case MO_64:
1940 gen_helper_rcrq(s->T0, cpu_env, s->T0, s->T1);
1941 break;
1942 #endif
1943 default:
1944 tcg_abort();
1946 } else {
1947 switch (ot) {
1948 case MO_8:
1949 gen_helper_rclb(s->T0, cpu_env, s->T0, s->T1);
1950 break;
1951 case MO_16:
1952 gen_helper_rclw(s->T0, cpu_env, s->T0, s->T1);
1953 break;
1954 case MO_32:
1955 gen_helper_rcll(s->T0, cpu_env, s->T0, s->T1);
1956 break;
1957 #ifdef TARGET_X86_64
1958 case MO_64:
1959 gen_helper_rclq(s->T0, cpu_env, s->T0, s->T1);
1960 break;
1961 #endif
1962 default:
1963 tcg_abort();
1966 /* store */
1967 gen_op_st_rm_T0_A0(s, ot, op1);
1970 /* XXX: add faster immediate case */
1971 static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
1972 bool is_right, TCGv count_in)
1974 target_ulong mask = (ot == MO_64 ? 63 : 31);
1975 TCGv count;
1977 /* load */
1978 if (op1 == OR_TMP0) {
1979 gen_op_ld_v(s, ot, s->T0, s->A0);
1980 } else {
1981 gen_op_mov_v_reg(s, ot, s->T0, op1);
1984 count = tcg_temp_new();
1985 tcg_gen_andi_tl(count, count_in, mask);
1987 switch (ot) {
1988 case MO_16:
1989 /* Note: we implement the Intel behaviour for shift count > 16.
1990 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1991 portion by constructing it as a 32-bit value. */
1992 if (is_right) {
1993 tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16);
1994 tcg_gen_mov_tl(s->T1, s->T0);
1995 tcg_gen_mov_tl(s->T0, s->tmp0);
1996 } else {
1997 tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
2000 * If TARGET_X86_64 defined then fall through into MO_32 case,
2001 * otherwise fall through default case.
2003 case MO_32:
2004 #ifdef TARGET_X86_64
2005 /* Concatenate the two 32-bit values and use a 64-bit shift. */
2006 tcg_gen_subi_tl(s->tmp0, count, 1);
2007 if (is_right) {
2008 tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1);
2009 tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0);
2010 tcg_gen_shr_i64(s->T0, s->T0, count);
2011 } else {
2012 tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0);
2013 tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0);
2014 tcg_gen_shl_i64(s->T0, s->T0, count);
2015 tcg_gen_shri_i64(s->tmp0, s->tmp0, 32);
2016 tcg_gen_shri_i64(s->T0, s->T0, 32);
2018 break;
2019 #endif
2020 default:
2021 tcg_gen_subi_tl(s->tmp0, count, 1);
2022 if (is_right) {
2023 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
2025 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
2026 tcg_gen_shr_tl(s->T0, s->T0, count);
2027 tcg_gen_shl_tl(s->T1, s->T1, s->tmp4);
2028 } else {
2029 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
2030 if (ot == MO_16) {
2031 /* Only needed if count > 16, for Intel behaviour. */
2032 tcg_gen_subfi_tl(s->tmp4, 33, count);
2033 tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4);
2034 tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4);
2037 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
2038 tcg_gen_shl_tl(s->T0, s->T0, count);
2039 tcg_gen_shr_tl(s->T1, s->T1, s->tmp4);
2041 tcg_gen_movi_tl(s->tmp4, 0);
2042 tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4,
2043 s->tmp4, s->T1);
2044 tcg_gen_or_tl(s->T0, s->T0, s->T1);
2045 break;
2048 /* store */
2049 gen_op_st_rm_T0_A0(s, ot, op1);
2051 gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
2052 tcg_temp_free(count);
2055 static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s)
2057 if (s != OR_TMP1)
2058 gen_op_mov_v_reg(s1, ot, s1->T1, s);
2059 switch(op) {
2060 case OP_ROL:
2061 gen_rot_rm_T1(s1, ot, d, 0);
2062 break;
2063 case OP_ROR:
2064 gen_rot_rm_T1(s1, ot, d, 1);
2065 break;
2066 case OP_SHL:
2067 case OP_SHL1:
2068 gen_shift_rm_T1(s1, ot, d, 0, 0);
2069 break;
2070 case OP_SHR:
2071 gen_shift_rm_T1(s1, ot, d, 1, 0);
2072 break;
2073 case OP_SAR:
2074 gen_shift_rm_T1(s1, ot, d, 1, 1);
2075 break;
2076 case OP_RCL:
2077 gen_rotc_rm_T1(s1, ot, d, 0);
2078 break;
2079 case OP_RCR:
2080 gen_rotc_rm_T1(s1, ot, d, 1);
2081 break;
2085 static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c)
2087 switch(op) {
2088 case OP_ROL:
2089 gen_rot_rm_im(s1, ot, d, c, 0);
2090 break;
2091 case OP_ROR:
2092 gen_rot_rm_im(s1, ot, d, c, 1);
2093 break;
2094 case OP_SHL:
2095 case OP_SHL1:
2096 gen_shift_rm_im(s1, ot, d, c, 0, 0);
2097 break;
2098 case OP_SHR:
2099 gen_shift_rm_im(s1, ot, d, c, 1, 0);
2100 break;
2101 case OP_SAR:
2102 gen_shift_rm_im(s1, ot, d, c, 1, 1);
2103 break;
2104 default:
2105 /* currently not optimized */
2106 tcg_gen_movi_tl(s1->T1, c);
2107 gen_shift(s1, op, ot, d, OR_TMP1);
2108 break;
2112 #define X86_MAX_INSN_LENGTH 15
2114 static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
2116 uint64_t pc = s->pc;
2118 /* This is a subsequent insn that crosses a page boundary. */
2119 if (s->base.num_insns > 1 &&
2120 !is_same_page(&s->base, s->pc + num_bytes - 1)) {
2121 siglongjmp(s->jmpbuf, 2);
2124 s->pc += num_bytes;
2125 if (unlikely(cur_insn_len(s) > X86_MAX_INSN_LENGTH)) {
2126 /* If the instruction's 16th byte is on a different page than the 1st, a
2127 * page fault on the second page wins over the general protection fault
2128 * caused by the instruction being too long.
2129 * This can happen even if the operand is only one byte long!
2131 if (((s->pc - 1) ^ (pc - 1)) & TARGET_PAGE_MASK) {
2132 volatile uint8_t unused =
2133 cpu_ldub_code(env, (s->pc - 1) & TARGET_PAGE_MASK);
2134 (void) unused;
2136 siglongjmp(s->jmpbuf, 1);
2139 return pc;
2142 static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
2144 return translator_ldub(env, &s->base, advance_pc(env, s, 1));
2147 static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
2149 return translator_lduw(env, &s->base, advance_pc(env, s, 2));
2152 static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
2154 return translator_lduw(env, &s->base, advance_pc(env, s, 2));
2157 static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
2159 return translator_ldl(env, &s->base, advance_pc(env, s, 4));
2162 #ifdef TARGET_X86_64
2163 static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
2165 return translator_ldq(env, &s->base, advance_pc(env, s, 8));
2167 #endif
2169 /* Decompose an address. */
2171 typedef struct AddressParts {
2172 int def_seg;
2173 int base;
2174 int index;
2175 int scale;
2176 target_long disp;
2177 } AddressParts;
2179 static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
2180 int modrm)
2182 int def_seg, base, index, scale, mod, rm;
2183 target_long disp;
2184 bool havesib;
2186 def_seg = R_DS;
2187 index = -1;
2188 scale = 0;
2189 disp = 0;
2191 mod = (modrm >> 6) & 3;
2192 rm = modrm & 7;
2193 base = rm | REX_B(s);
2195 if (mod == 3) {
2196 /* Normally filtered out earlier, but including this path
2197 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
2198 goto done;
2201 switch (s->aflag) {
2202 case MO_64:
2203 case MO_32:
2204 havesib = 0;
2205 if (rm == 4) {
2206 int code = x86_ldub_code(env, s);
2207 scale = (code >> 6) & 3;
2208 index = ((code >> 3) & 7) | REX_X(s);
2209 if (index == 4) {
2210 index = -1; /* no index */
2212 base = (code & 7) | REX_B(s);
2213 havesib = 1;
2216 switch (mod) {
2217 case 0:
2218 if ((base & 7) == 5) {
2219 base = -1;
2220 disp = (int32_t)x86_ldl_code(env, s);
2221 if (CODE64(s) && !havesib) {
2222 base = -2;
2223 disp += s->pc + s->rip_offset;
2226 break;
2227 case 1:
2228 disp = (int8_t)x86_ldub_code(env, s);
2229 break;
2230 default:
2231 case 2:
2232 disp = (int32_t)x86_ldl_code(env, s);
2233 break;
2236 /* For correct popl handling with esp. */
2237 if (base == R_ESP && s->popl_esp_hack) {
2238 disp += s->popl_esp_hack;
2240 if (base == R_EBP || base == R_ESP) {
2241 def_seg = R_SS;
2243 break;
2245 case MO_16:
2246 if (mod == 0) {
2247 if (rm == 6) {
2248 base = -1;
2249 disp = x86_lduw_code(env, s);
2250 break;
2252 } else if (mod == 1) {
2253 disp = (int8_t)x86_ldub_code(env, s);
2254 } else {
2255 disp = (int16_t)x86_lduw_code(env, s);
2258 switch (rm) {
2259 case 0:
2260 base = R_EBX;
2261 index = R_ESI;
2262 break;
2263 case 1:
2264 base = R_EBX;
2265 index = R_EDI;
2266 break;
2267 case 2:
2268 base = R_EBP;
2269 index = R_ESI;
2270 def_seg = R_SS;
2271 break;
2272 case 3:
2273 base = R_EBP;
2274 index = R_EDI;
2275 def_seg = R_SS;
2276 break;
2277 case 4:
2278 base = R_ESI;
2279 break;
2280 case 5:
2281 base = R_EDI;
2282 break;
2283 case 6:
2284 base = R_EBP;
2285 def_seg = R_SS;
2286 break;
2287 default:
2288 case 7:
2289 base = R_EBX;
2290 break;
2292 break;
2294 default:
2295 tcg_abort();
2298 done:
2299 return (AddressParts){ def_seg, base, index, scale, disp };
2302 /* Compute the address, with a minimum number of TCG ops. */
2303 static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a, bool is_vsib)
2305 TCGv ea = NULL;
2307 if (a.index >= 0 && !is_vsib) {
2308 if (a.scale == 0) {
2309 ea = cpu_regs[a.index];
2310 } else {
2311 tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale);
2312 ea = s->A0;
2314 if (a.base >= 0) {
2315 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2316 ea = s->A0;
2318 } else if (a.base >= 0) {
2319 ea = cpu_regs[a.base];
2321 if (!ea) {
2322 if (TARGET_TB_PCREL && a.base == -2) {
2323 /* With cpu_eip ~= pc_save, the expression is pc-relative. */
2324 tcg_gen_addi_tl(s->A0, cpu_eip, a.disp - s->pc_save);
2325 } else {
2326 tcg_gen_movi_tl(s->A0, a.disp);
2328 ea = s->A0;
2329 } else if (a.disp != 0) {
2330 tcg_gen_addi_tl(s->A0, ea, a.disp);
2331 ea = s->A0;
2334 return ea;
2337 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2339 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2340 TCGv ea = gen_lea_modrm_1(s, a, false);
2341 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2344 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2346 (void)gen_lea_modrm_0(env, s, modrm);
2349 /* Used for BNDCL, BNDCU, BNDCN. */
2350 static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2351 TCGCond cond, TCGv_i64 bndv)
2353 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2354 TCGv ea = gen_lea_modrm_1(s, a, false);
2356 tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
2357 if (!CODE64(s)) {
2358 tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64);
2360 tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv);
2361 tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64);
2362 gen_helper_bndck(cpu_env, s->tmp2_i32);
2365 /* used for LEA and MOV AX, mem */
2366 static void gen_add_A0_ds_seg(DisasContext *s)
2368 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
2371 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2372 OR_TMP0 */
2373 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2374 MemOp ot, int reg, int is_store)
2376 int mod, rm;
2378 mod = (modrm >> 6) & 3;
2379 rm = (modrm & 7) | REX_B(s);
2380 if (mod == 3) {
2381 if (is_store) {
2382 if (reg != OR_TMP0)
2383 gen_op_mov_v_reg(s, ot, s->T0, reg);
2384 gen_op_mov_reg_v(s, ot, rm, s->T0);
2385 } else {
2386 gen_op_mov_v_reg(s, ot, s->T0, rm);
2387 if (reg != OR_TMP0)
2388 gen_op_mov_reg_v(s, ot, reg, s->T0);
2390 } else {
2391 gen_lea_modrm(env, s, modrm);
2392 if (is_store) {
2393 if (reg != OR_TMP0)
2394 gen_op_mov_v_reg(s, ot, s->T0, reg);
2395 gen_op_st_v(s, ot, s->T0, s->A0);
2396 } else {
2397 gen_op_ld_v(s, ot, s->T0, s->A0);
2398 if (reg != OR_TMP0)
2399 gen_op_mov_reg_v(s, ot, reg, s->T0);
2404 static target_ulong insn_get_addr(CPUX86State *env, DisasContext *s, MemOp ot)
2406 target_ulong ret;
2408 switch (ot) {
2409 case MO_8:
2410 ret = x86_ldub_code(env, s);
2411 break;
2412 case MO_16:
2413 ret = x86_lduw_code(env, s);
2414 break;
2415 case MO_32:
2416 ret = x86_ldl_code(env, s);
2417 break;
2418 #ifdef TARGET_X86_64
2419 case MO_64:
2420 ret = x86_ldq_code(env, s);
2421 break;
2422 #endif
2423 default:
2424 g_assert_not_reached();
2426 return ret;
2429 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
2431 uint32_t ret;
2433 switch (ot) {
2434 case MO_8:
2435 ret = x86_ldub_code(env, s);
2436 break;
2437 case MO_16:
2438 ret = x86_lduw_code(env, s);
2439 break;
2440 case MO_32:
2441 #ifdef TARGET_X86_64
2442 case MO_64:
2443 #endif
2444 ret = x86_ldl_code(env, s);
2445 break;
2446 default:
2447 tcg_abort();
2449 return ret;
2452 static target_long insn_get_signed(CPUX86State *env, DisasContext *s, MemOp ot)
2454 target_long ret;
2456 switch (ot) {
2457 case MO_8:
2458 ret = (int8_t) x86_ldub_code(env, s);
2459 break;
2460 case MO_16:
2461 ret = (int16_t) x86_lduw_code(env, s);
2462 break;
2463 case MO_32:
2464 ret = (int32_t) x86_ldl_code(env, s);
2465 break;
2466 #ifdef TARGET_X86_64
2467 case MO_64:
2468 ret = x86_ldq_code(env, s);
2469 break;
2470 #endif
2471 default:
2472 g_assert_not_reached();
2474 return ret;
2477 static inline int insn_const_size(MemOp ot)
2479 if (ot <= MO_32) {
2480 return 1 << ot;
2481 } else {
2482 return 4;
2486 static void gen_jcc(DisasContext *s, int b, int diff)
2488 TCGLabel *l1 = gen_new_label();
2490 gen_jcc1(s, b, l1);
2491 gen_jmp_rel_csize(s, 0, 1);
2492 gen_set_label(l1);
2493 gen_jmp_rel(s, s->dflag, diff, 0);
2496 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
2497 int modrm, int reg)
2499 CCPrepare cc;
2501 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2503 cc = gen_prepare_cc(s, b, s->T1);
2504 if (cc.mask != -1) {
2505 TCGv t0 = tcg_temp_new();
2506 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2507 cc.reg = t0;
2509 if (!cc.use_reg2) {
2510 cc.reg2 = tcg_const_tl(cc.imm);
2513 tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2,
2514 s->T0, cpu_regs[reg]);
2515 gen_op_mov_reg_v(s, ot, reg, s->T0);
2517 if (cc.mask != -1) {
2518 tcg_temp_free(cc.reg);
2520 if (!cc.use_reg2) {
2521 tcg_temp_free(cc.reg2);
2525 static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg)
2527 tcg_gen_ld32u_tl(s->T0, cpu_env,
2528 offsetof(CPUX86State,segs[seg_reg].selector));
2531 static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg)
2533 tcg_gen_ext16u_tl(s->T0, s->T0);
2534 tcg_gen_st32_tl(s->T0, cpu_env,
2535 offsetof(CPUX86State,segs[seg_reg].selector));
2536 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
2539 /* move T0 to seg_reg and compute if the CPU state may change. Never
2540 call this function with seg_reg == R_CS */
2541 static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg)
2543 if (PE(s) && !VM86(s)) {
2544 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
2545 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), s->tmp2_i32);
2546 /* abort translation because the addseg value may change or
2547 because ss32 may change. For R_SS, translation must always
2548 stop as a special handling must be done to disable hardware
2549 interrupts for the next instruction */
2550 if (seg_reg == R_SS) {
2551 s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
2552 } else if (CODE32(s) && seg_reg < R_FS) {
2553 s->base.is_jmp = DISAS_EOB_NEXT;
2555 } else {
2556 gen_op_movl_seg_T0_vm(s, seg_reg);
2557 if (seg_reg == R_SS) {
2558 s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
2563 static void gen_svm_check_intercept(DisasContext *s, uint32_t type)
2565 /* no SVM activated; fast case */
2566 if (likely(!GUEST(s))) {
2567 return;
2569 gen_helper_svm_check_intercept(cpu_env, tcg_constant_i32(type));
2572 static inline void gen_stack_update(DisasContext *s, int addend)
2574 gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend);
2577 /* Generate a push. It depends on ss32, addseg and dflag. */
2578 static void gen_push_v(DisasContext *s, TCGv val)
2580 MemOp d_ot = mo_pushpop(s, s->dflag);
2581 MemOp a_ot = mo_stacksize(s);
2582 int size = 1 << d_ot;
2583 TCGv new_esp = s->A0;
2585 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2587 if (!CODE64(s)) {
2588 if (ADDSEG(s)) {
2589 new_esp = s->tmp4;
2590 tcg_gen_mov_tl(new_esp, s->A0);
2592 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2595 gen_op_st_v(s, d_ot, val, s->A0);
2596 gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp);
2599 /* two step pop is necessary for precise exceptions */
2600 static MemOp gen_pop_T0(DisasContext *s)
2602 MemOp d_ot = mo_pushpop(s, s->dflag);
2604 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2605 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2607 return d_ot;
2610 static inline void gen_pop_update(DisasContext *s, MemOp ot)
2612 gen_stack_update(s, 1 << ot);
2615 static inline void gen_stack_A0(DisasContext *s)
2617 gen_lea_v_seg(s, SS32(s) ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2620 static void gen_pusha(DisasContext *s)
2622 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2623 MemOp d_ot = s->dflag;
2624 int size = 1 << d_ot;
2625 int i;
2627 for (i = 0; i < 8; i++) {
2628 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size);
2629 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2630 gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0);
2633 gen_stack_update(s, -8 * size);
2636 static void gen_popa(DisasContext *s)
2638 MemOp s_ot = SS32(s) ? MO_32 : MO_16;
2639 MemOp d_ot = s->dflag;
2640 int size = 1 << d_ot;
2641 int i;
2643 for (i = 0; i < 8; i++) {
2644 /* ESP is not reloaded */
2645 if (7 - i == R_ESP) {
2646 continue;
2648 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size);
2649 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2650 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2651 gen_op_mov_reg_v(s, d_ot, 7 - i, s->T0);
2654 gen_stack_update(s, 8 * size);
2657 static void gen_enter(DisasContext *s, int esp_addend, int level)
2659 MemOp d_ot = mo_pushpop(s, s->dflag);
2660 MemOp a_ot = CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
2661 int size = 1 << d_ot;
2663 /* Push BP; compute FrameTemp into T1. */
2664 tcg_gen_subi_tl(s->T1, cpu_regs[R_ESP], size);
2665 gen_lea_v_seg(s, a_ot, s->T1, R_SS, -1);
2666 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0);
2668 level &= 31;
2669 if (level != 0) {
2670 int i;
2672 /* Copy level-1 pointers from the previous frame. */
2673 for (i = 1; i < level; ++i) {
2674 tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i);
2675 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2676 gen_op_ld_v(s, d_ot, s->tmp0, s->A0);
2678 tcg_gen_subi_tl(s->A0, s->T1, size * i);
2679 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2680 gen_op_st_v(s, d_ot, s->tmp0, s->A0);
2683 /* Push the current FrameTemp as the last level. */
2684 tcg_gen_subi_tl(s->A0, s->T1, size * level);
2685 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2686 gen_op_st_v(s, d_ot, s->T1, s->A0);
2689 /* Copy the FrameTemp value to EBP. */
2690 gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
2692 /* Compute the final value of ESP. */
2693 tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
2694 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2697 static void gen_leave(DisasContext *s)
2699 MemOp d_ot = mo_pushpop(s, s->dflag);
2700 MemOp a_ot = mo_stacksize(s);
2702 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2703 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2705 tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot);
2707 gen_op_mov_reg_v(s, d_ot, R_EBP, s->T0);
2708 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2711 /* Similarly, except that the assumption here is that we don't decode
2712 the instruction at all -- either a missing opcode, an unimplemented
2713 feature, or just a bogus instruction stream. */
2714 static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2716 gen_illegal_opcode(s);
2718 if (qemu_loglevel_mask(LOG_UNIMP)) {
2719 FILE *logfile = qemu_log_trylock();
2720 if (logfile) {
2721 target_ulong pc = s->base.pc_next, end = s->pc;
2723 fprintf(logfile, "ILLOPC: " TARGET_FMT_lx ":", pc);
2724 for (; pc < end; ++pc) {
2725 fprintf(logfile, " %02x", cpu_ldub_code(env, pc));
2727 fprintf(logfile, "\n");
2728 qemu_log_unlock(logfile);
2733 /* an interrupt is different from an exception because of the
2734 privilege checks */
2735 static void gen_interrupt(DisasContext *s, int intno)
2737 gen_update_cc_op(s);
2738 gen_update_eip_cur(s);
2739 gen_helper_raise_interrupt(cpu_env, tcg_constant_i32(intno),
2740 cur_insn_len_i32(s));
2741 s->base.is_jmp = DISAS_NORETURN;
2744 static void gen_set_hflag(DisasContext *s, uint32_t mask)
2746 if ((s->flags & mask) == 0) {
2747 TCGv_i32 t = tcg_temp_new_i32();
2748 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2749 tcg_gen_ori_i32(t, t, mask);
2750 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2751 tcg_temp_free_i32(t);
2752 s->flags |= mask;
2756 static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2758 if (s->flags & mask) {
2759 TCGv_i32 t = tcg_temp_new_i32();
2760 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2761 tcg_gen_andi_i32(t, t, ~mask);
2762 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2763 tcg_temp_free_i32(t);
2764 s->flags &= ~mask;
2768 static void gen_set_eflags(DisasContext *s, target_ulong mask)
2770 TCGv t = tcg_temp_new();
2772 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUX86State, eflags));
2773 tcg_gen_ori_tl(t, t, mask);
2774 tcg_gen_st_tl(t, cpu_env, offsetof(CPUX86State, eflags));
2775 tcg_temp_free(t);
2778 static void gen_reset_eflags(DisasContext *s, target_ulong mask)
2780 TCGv t = tcg_temp_new();
2782 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUX86State, eflags));
2783 tcg_gen_andi_tl(t, t, ~mask);
2784 tcg_gen_st_tl(t, cpu_env, offsetof(CPUX86State, eflags));
2785 tcg_temp_free(t);
2788 /* Clear BND registers during legacy branches. */
2789 static void gen_bnd_jmp(DisasContext *s)
2791 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2792 and if the BNDREGs are known to be in use (non-zero) already.
2793 The helper itself will check BNDPRESERVE at runtime. */
2794 if ((s->prefix & PREFIX_REPNZ) == 0
2795 && (s->flags & HF_MPX_EN_MASK) != 0
2796 && (s->flags & HF_MPX_IU_MASK) != 0) {
2797 gen_helper_bnd_jmp(cpu_env);
2801 /* Generate an end of block. Trace exception is also generated if needed.
2802 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.
2803 If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
2804 S->TF. This is used by the syscall/sysret insns. */
2805 static void
2806 do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2808 gen_update_cc_op(s);
2810 /* If several instructions disable interrupts, only the first does it. */
2811 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2812 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2813 } else {
2814 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2817 if (s->base.tb->flags & HF_RF_MASK) {
2818 gen_reset_eflags(s, RF_MASK);
2820 if (recheck_tf) {
2821 gen_helper_rechecking_single_step(cpu_env);
2822 tcg_gen_exit_tb(NULL, 0);
2823 } else if (s->flags & HF_TF_MASK) {
2824 gen_helper_single_step(cpu_env);
2825 } else if (jr) {
2826 tcg_gen_lookup_and_goto_ptr();
2827 } else {
2828 tcg_gen_exit_tb(NULL, 0);
2830 s->base.is_jmp = DISAS_NORETURN;
2833 static inline void
2834 gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2836 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2839 /* End of block.
2840 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2841 static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2843 gen_eob_worker(s, inhibit, false);
2846 /* End of block, resetting the inhibit irq flag. */
2847 static void gen_eob(DisasContext *s)
2849 gen_eob_worker(s, false, false);
2852 /* Jump to register */
2853 static void gen_jr(DisasContext *s)
2855 do_gen_eob_worker(s, false, false, true);
2858 /* Jump to eip+diff, truncating the result to OT. */
2859 static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num)
2861 bool use_goto_tb = s->jmp_opt;
2862 target_ulong mask = -1;
2863 target_ulong new_pc = s->pc + diff;
2864 target_ulong new_eip = new_pc - s->cs_base;
2866 /* In 64-bit mode, operand size is fixed at 64 bits. */
2867 if (!CODE64(s)) {
2868 if (ot == MO_16) {
2869 mask = 0xffff;
2870 if (TARGET_TB_PCREL && CODE32(s)) {
2871 use_goto_tb = false;
2873 } else {
2874 mask = 0xffffffff;
2877 new_eip &= mask;
2879 gen_update_cc_op(s);
2880 set_cc_op(s, CC_OP_DYNAMIC);
2882 if (TARGET_TB_PCREL) {
2883 tcg_gen_addi_tl(cpu_eip, cpu_eip, new_pc - s->pc_save);
2885 * If we can prove the branch does not leave the page and we have
2886 * no extra masking to apply (data16 branch in code32, see above),
2887 * then we have also proven that the addition does not wrap.
2889 if (!use_goto_tb || !is_same_page(&s->base, new_pc)) {
2890 tcg_gen_andi_tl(cpu_eip, cpu_eip, mask);
2891 use_goto_tb = false;
2895 if (use_goto_tb &&
2896 translator_use_goto_tb(&s->base, new_eip + s->cs_base)) {
2897 /* jump to same page: we can use a direct jump */
2898 tcg_gen_goto_tb(tb_num);
2899 if (!TARGET_TB_PCREL) {
2900 tcg_gen_movi_tl(cpu_eip, new_eip);
2902 tcg_gen_exit_tb(s->base.tb, tb_num);
2903 s->base.is_jmp = DISAS_NORETURN;
2904 } else {
2905 if (!TARGET_TB_PCREL) {
2906 tcg_gen_movi_tl(cpu_eip, new_eip);
2908 if (s->jmp_opt) {
2909 gen_jr(s); /* jump to another page */
2910 } else {
2911 gen_eob(s); /* exit to main loop */
2916 /* Jump to eip+diff, truncating to the current code size. */
2917 static void gen_jmp_rel_csize(DisasContext *s, int diff, int tb_num)
2919 /* CODE64 ignores the OT argument, so we need not consider it. */
2920 gen_jmp_rel(s, CODE32(s) ? MO_32 : MO_16, diff, tb_num);
2923 static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2925 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
2926 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset);
2929 static inline void gen_stq_env_A0(DisasContext *s, int offset)
2931 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset);
2932 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
2935 static inline void gen_ldo_env_A0(DisasContext *s, int offset, bool align)
2937 int mem_index = s->mem_index;
2938 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index,
2939 MO_LEUQ | (align ? MO_ALIGN_16 : 0));
2940 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2941 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2942 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2943 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2946 static inline void gen_sto_env_A0(DisasContext *s, int offset, bool align)
2948 int mem_index = s->mem_index;
2949 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2950 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index,
2951 MO_LEUQ | (align ? MO_ALIGN_16 : 0));
2952 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2953 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2954 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2957 static void gen_ldy_env_A0(DisasContext *s, int offset, bool align)
2959 int mem_index = s->mem_index;
2960 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index,
2961 MO_LEUQ | (align ? MO_ALIGN_32 : 0));
2962 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(YMMReg, YMM_Q(0)));
2963 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2964 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2965 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(YMMReg, YMM_Q(1)));
2967 tcg_gen_addi_tl(s->tmp0, s->A0, 16);
2968 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2969 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(YMMReg, YMM_Q(2)));
2970 tcg_gen_addi_tl(s->tmp0, s->A0, 24);
2971 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2972 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(YMMReg, YMM_Q(3)));
2975 static void gen_sty_env_A0(DisasContext *s, int offset, bool align)
2977 int mem_index = s->mem_index;
2978 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(YMMReg, YMM_Q(0)));
2979 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index,
2980 MO_LEUQ | (align ? MO_ALIGN_32 : 0));
2981 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2982 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(YMMReg, YMM_Q(1)));
2983 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2984 tcg_gen_addi_tl(s->tmp0, s->A0, 16);
2985 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(YMMReg, YMM_Q(2)));
2986 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2987 tcg_gen_addi_tl(s->tmp0, s->A0, 24);
2988 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(YMMReg, YMM_Q(3)));
2989 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
2992 #include "decode-new.h"
2993 #include "emit.c.inc"
2994 #include "decode-new.c.inc"
2996 /* convert one instruction. s->base.is_jmp is set if the translation must
2997 be stopped. Return the next pc value */
2998 static bool disas_insn(DisasContext *s, CPUState *cpu)
3000 CPUX86State *env = cpu->env_ptr;
3001 int b, prefixes;
3002 int shift;
3003 MemOp ot, aflag, dflag;
3004 int modrm, reg, rm, mod, op, opreg, val;
3005 bool orig_cc_op_dirty = s->cc_op_dirty;
3006 CCOp orig_cc_op = s->cc_op;
3007 target_ulong orig_pc_save = s->pc_save;
3009 s->pc = s->base.pc_next;
3010 s->override = -1;
3011 #ifdef TARGET_X86_64
3012 s->rex_r = 0;
3013 s->rex_x = 0;
3014 s->rex_b = 0;
3015 #endif
3016 s->rip_offset = 0; /* for relative ip address */
3017 s->vex_l = 0;
3018 s->vex_v = 0;
3019 s->vex_w = false;
3020 switch (sigsetjmp(s->jmpbuf, 0)) {
3021 case 0:
3022 break;
3023 case 1:
3024 gen_exception_gpf(s);
3025 return true;
3026 case 2:
3027 /* Restore state that may affect the next instruction. */
3028 s->pc = s->base.pc_next;
3030 * TODO: These save/restore can be removed after the table-based
3031 * decoder is complete; we will be decoding the insn completely
3032 * before any code generation that might affect these variables.
3034 s->cc_op_dirty = orig_cc_op_dirty;
3035 s->cc_op = orig_cc_op;
3036 s->pc_save = orig_pc_save;
3037 /* END TODO */
3038 s->base.num_insns--;
3039 tcg_remove_ops_after(s->prev_insn_end);
3040 s->base.is_jmp = DISAS_TOO_MANY;
3041 return false;
3042 default:
3043 g_assert_not_reached();
3046 prefixes = 0;
3048 next_byte:
3049 s->prefix = prefixes;
3050 b = x86_ldub_code(env, s);
3051 /* Collect prefixes. */
3052 switch (b) {
3053 default:
3054 break;
3055 case 0x0f:
3056 b = x86_ldub_code(env, s) + 0x100;
3057 break;
3058 case 0xf3:
3059 prefixes |= PREFIX_REPZ;
3060 prefixes &= ~PREFIX_REPNZ;
3061 goto next_byte;
3062 case 0xf2:
3063 prefixes |= PREFIX_REPNZ;
3064 prefixes &= ~PREFIX_REPZ;
3065 goto next_byte;
3066 case 0xf0:
3067 prefixes |= PREFIX_LOCK;
3068 goto next_byte;
3069 case 0x2e:
3070 s->override = R_CS;
3071 goto next_byte;
3072 case 0x36:
3073 s->override = R_SS;
3074 goto next_byte;
3075 case 0x3e:
3076 s->override = R_DS;
3077 goto next_byte;
3078 case 0x26:
3079 s->override = R_ES;
3080 goto next_byte;
3081 case 0x64:
3082 s->override = R_FS;
3083 goto next_byte;
3084 case 0x65:
3085 s->override = R_GS;
3086 goto next_byte;
3087 case 0x66:
3088 prefixes |= PREFIX_DATA;
3089 goto next_byte;
3090 case 0x67:
3091 prefixes |= PREFIX_ADR;
3092 goto next_byte;
3093 #ifdef TARGET_X86_64
3094 case 0x40 ... 0x4f:
3095 if (CODE64(s)) {
3096 /* REX prefix */
3097 prefixes |= PREFIX_REX;
3098 s->vex_w = (b >> 3) & 1;
3099 s->rex_r = (b & 0x4) << 1;
3100 s->rex_x = (b & 0x2) << 2;
3101 s->rex_b = (b & 0x1) << 3;
3102 goto next_byte;
3104 break;
3105 #endif
3106 case 0xc5: /* 2-byte VEX */
3107 case 0xc4: /* 3-byte VEX */
3108 if (CODE32(s) && !VM86(s)) {
3109 int vex2 = x86_ldub_code(env, s);
3110 s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
3112 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
3113 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
3114 otherwise the instruction is LES or LDS. */
3115 break;
3117 disas_insn_new(s, cpu, b);
3118 return s->pc;
3120 break;
3123 /* Post-process prefixes. */
3124 if (CODE64(s)) {
3125 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
3126 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
3127 over 0x66 if both are present. */
3128 dflag = (REX_W(s) ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
3129 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
3130 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
3131 } else {
3132 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
3133 if (CODE32(s) ^ ((prefixes & PREFIX_DATA) != 0)) {
3134 dflag = MO_32;
3135 } else {
3136 dflag = MO_16;
3138 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
3139 if (CODE32(s) ^ ((prefixes & PREFIX_ADR) != 0)) {
3140 aflag = MO_32;
3141 } else {
3142 aflag = MO_16;
3146 s->prefix = prefixes;
3147 s->aflag = aflag;
3148 s->dflag = dflag;
3150 /* now check op code */
3151 switch (b) {
3152 /**************************/
3153 /* arith & logic */
3154 case 0x00 ... 0x05:
3155 case 0x08 ... 0x0d:
3156 case 0x10 ... 0x15:
3157 case 0x18 ... 0x1d:
3158 case 0x20 ... 0x25:
3159 case 0x28 ... 0x2d:
3160 case 0x30 ... 0x35:
3161 case 0x38 ... 0x3d:
3163 int op, f, val;
3164 op = (b >> 3) & 7;
3165 f = (b >> 1) & 3;
3167 ot = mo_b_d(b, dflag);
3169 switch(f) {
3170 case 0: /* OP Ev, Gv */
3171 modrm = x86_ldub_code(env, s);
3172 reg = ((modrm >> 3) & 7) | REX_R(s);
3173 mod = (modrm >> 6) & 3;
3174 rm = (modrm & 7) | REX_B(s);
3175 if (mod != 3) {
3176 gen_lea_modrm(env, s, modrm);
3177 opreg = OR_TMP0;
3178 } else if (op == OP_XORL && rm == reg) {
3179 xor_zero:
3180 /* xor reg, reg optimisation */
3181 set_cc_op(s, CC_OP_CLR);
3182 tcg_gen_movi_tl(s->T0, 0);
3183 gen_op_mov_reg_v(s, ot, reg, s->T0);
3184 break;
3185 } else {
3186 opreg = rm;
3188 gen_op_mov_v_reg(s, ot, s->T1, reg);
3189 gen_op(s, op, ot, opreg);
3190 break;
3191 case 1: /* OP Gv, Ev */
3192 modrm = x86_ldub_code(env, s);
3193 mod = (modrm >> 6) & 3;
3194 reg = ((modrm >> 3) & 7) | REX_R(s);
3195 rm = (modrm & 7) | REX_B(s);
3196 if (mod != 3) {
3197 gen_lea_modrm(env, s, modrm);
3198 gen_op_ld_v(s, ot, s->T1, s->A0);
3199 } else if (op == OP_XORL && rm == reg) {
3200 goto xor_zero;
3201 } else {
3202 gen_op_mov_v_reg(s, ot, s->T1, rm);
3204 gen_op(s, op, ot, reg);
3205 break;
3206 case 2: /* OP A, Iv */
3207 val = insn_get(env, s, ot);
3208 tcg_gen_movi_tl(s->T1, val);
3209 gen_op(s, op, ot, OR_EAX);
3210 break;
3213 break;
3215 case 0x82:
3216 if (CODE64(s))
3217 goto illegal_op;
3218 /* fall through */
3219 case 0x80: /* GRP1 */
3220 case 0x81:
3221 case 0x83:
3223 int val;
3225 ot = mo_b_d(b, dflag);
3227 modrm = x86_ldub_code(env, s);
3228 mod = (modrm >> 6) & 3;
3229 rm = (modrm & 7) | REX_B(s);
3230 op = (modrm >> 3) & 7;
3232 if (mod != 3) {
3233 if (b == 0x83)
3234 s->rip_offset = 1;
3235 else
3236 s->rip_offset = insn_const_size(ot);
3237 gen_lea_modrm(env, s, modrm);
3238 opreg = OR_TMP0;
3239 } else {
3240 opreg = rm;
3243 switch(b) {
3244 default:
3245 case 0x80:
3246 case 0x81:
3247 case 0x82:
3248 val = insn_get(env, s, ot);
3249 break;
3250 case 0x83:
3251 val = (int8_t)insn_get(env, s, MO_8);
3252 break;
3254 tcg_gen_movi_tl(s->T1, val);
3255 gen_op(s, op, ot, opreg);
3257 break;
3259 /**************************/
3260 /* inc, dec, and other misc arith */
3261 case 0x40 ... 0x47: /* inc Gv */
3262 ot = dflag;
3263 gen_inc(s, ot, OR_EAX + (b & 7), 1);
3264 break;
3265 case 0x48 ... 0x4f: /* dec Gv */
3266 ot = dflag;
3267 gen_inc(s, ot, OR_EAX + (b & 7), -1);
3268 break;
3269 case 0xf6: /* GRP3 */
3270 case 0xf7:
3271 ot = mo_b_d(b, dflag);
3273 modrm = x86_ldub_code(env, s);
3274 mod = (modrm >> 6) & 3;
3275 rm = (modrm & 7) | REX_B(s);
3276 op = (modrm >> 3) & 7;
3277 if (mod != 3) {
3278 if (op == 0) {
3279 s->rip_offset = insn_const_size(ot);
3281 gen_lea_modrm(env, s, modrm);
3282 /* For those below that handle locked memory, don't load here. */
3283 if (!(s->prefix & PREFIX_LOCK)
3284 || op != 2) {
3285 gen_op_ld_v(s, ot, s->T0, s->A0);
3287 } else {
3288 gen_op_mov_v_reg(s, ot, s->T0, rm);
3291 switch(op) {
3292 case 0: /* test */
3293 val = insn_get(env, s, ot);
3294 tcg_gen_movi_tl(s->T1, val);
3295 gen_op_testl_T0_T1_cc(s);
3296 set_cc_op(s, CC_OP_LOGICB + ot);
3297 break;
3298 case 2: /* not */
3299 if (s->prefix & PREFIX_LOCK) {
3300 if (mod == 3) {
3301 goto illegal_op;
3303 tcg_gen_movi_tl(s->T0, ~0);
3304 tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0,
3305 s->mem_index, ot | MO_LE);
3306 } else {
3307 tcg_gen_not_tl(s->T0, s->T0);
3308 if (mod != 3) {
3309 gen_op_st_v(s, ot, s->T0, s->A0);
3310 } else {
3311 gen_op_mov_reg_v(s, ot, rm, s->T0);
3314 break;
3315 case 3: /* neg */
3316 if (s->prefix & PREFIX_LOCK) {
3317 TCGLabel *label1;
3318 TCGv a0, t0, t1, t2;
3320 if (mod == 3) {
3321 goto illegal_op;
3323 a0 = tcg_temp_local_new();
3324 t0 = tcg_temp_local_new();
3325 label1 = gen_new_label();
3327 tcg_gen_mov_tl(a0, s->A0);
3328 tcg_gen_mov_tl(t0, s->T0);
3330 gen_set_label(label1);
3331 t1 = tcg_temp_new();
3332 t2 = tcg_temp_new();
3333 tcg_gen_mov_tl(t2, t0);
3334 tcg_gen_neg_tl(t1, t0);
3335 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
3336 s->mem_index, ot | MO_LE);
3337 tcg_temp_free(t1);
3338 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
3340 tcg_temp_free(t2);
3341 tcg_temp_free(a0);
3342 tcg_gen_neg_tl(s->T0, t0);
3343 tcg_temp_free(t0);
3344 } else {
3345 tcg_gen_neg_tl(s->T0, s->T0);
3346 if (mod != 3) {
3347 gen_op_st_v(s, ot, s->T0, s->A0);
3348 } else {
3349 gen_op_mov_reg_v(s, ot, rm, s->T0);
3352 gen_op_update_neg_cc(s);
3353 set_cc_op(s, CC_OP_SUBB + ot);
3354 break;
3355 case 4: /* mul */
3356 switch(ot) {
3357 case MO_8:
3358 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
3359 tcg_gen_ext8u_tl(s->T0, s->T0);
3360 tcg_gen_ext8u_tl(s->T1, s->T1);
3361 /* XXX: use 32 bit mul which could be faster */
3362 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
3363 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
3364 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
3365 tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00);
3366 set_cc_op(s, CC_OP_MULB);
3367 break;
3368 case MO_16:
3369 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
3370 tcg_gen_ext16u_tl(s->T0, s->T0);
3371 tcg_gen_ext16u_tl(s->T1, s->T1);
3372 /* XXX: use 32 bit mul which could be faster */
3373 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
3374 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
3375 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
3376 tcg_gen_shri_tl(s->T0, s->T0, 16);
3377 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
3378 tcg_gen_mov_tl(cpu_cc_src, s->T0);
3379 set_cc_op(s, CC_OP_MULW);
3380 break;
3381 default:
3382 case MO_32:
3383 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3384 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
3385 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
3386 s->tmp2_i32, s->tmp3_i32);
3387 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
3388 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
3389 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
3390 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3391 set_cc_op(s, CC_OP_MULL);
3392 break;
3393 #ifdef TARGET_X86_64
3394 case MO_64:
3395 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
3396 s->T0, cpu_regs[R_EAX]);
3397 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
3398 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3399 set_cc_op(s, CC_OP_MULQ);
3400 break;
3401 #endif
3403 break;
3404 case 5: /* imul */
3405 switch(ot) {
3406 case MO_8:
3407 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
3408 tcg_gen_ext8s_tl(s->T0, s->T0);
3409 tcg_gen_ext8s_tl(s->T1, s->T1);
3410 /* XXX: use 32 bit mul which could be faster */
3411 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
3412 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
3413 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
3414 tcg_gen_ext8s_tl(s->tmp0, s->T0);
3415 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
3416 set_cc_op(s, CC_OP_MULB);
3417 break;
3418 case MO_16:
3419 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
3420 tcg_gen_ext16s_tl(s->T0, s->T0);
3421 tcg_gen_ext16s_tl(s->T1, s->T1);
3422 /* XXX: use 32 bit mul which could be faster */
3423 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
3424 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
3425 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
3426 tcg_gen_ext16s_tl(s->tmp0, s->T0);
3427 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
3428 tcg_gen_shri_tl(s->T0, s->T0, 16);
3429 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
3430 set_cc_op(s, CC_OP_MULW);
3431 break;
3432 default:
3433 case MO_32:
3434 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3435 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
3436 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
3437 s->tmp2_i32, s->tmp3_i32);
3438 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
3439 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
3440 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
3441 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
3442 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
3443 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
3444 set_cc_op(s, CC_OP_MULL);
3445 break;
3446 #ifdef TARGET_X86_64
3447 case MO_64:
3448 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
3449 s->T0, cpu_regs[R_EAX]);
3450 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
3451 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
3452 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
3453 set_cc_op(s, CC_OP_MULQ);
3454 break;
3455 #endif
3457 break;
3458 case 6: /* div */
3459 switch(ot) {
3460 case MO_8:
3461 gen_helper_divb_AL(cpu_env, s->T0);
3462 break;
3463 case MO_16:
3464 gen_helper_divw_AX(cpu_env, s->T0);
3465 break;
3466 default:
3467 case MO_32:
3468 gen_helper_divl_EAX(cpu_env, s->T0);
3469 break;
3470 #ifdef TARGET_X86_64
3471 case MO_64:
3472 gen_helper_divq_EAX(cpu_env, s->T0);
3473 break;
3474 #endif
3476 break;
3477 case 7: /* idiv */
3478 switch(ot) {
3479 case MO_8:
3480 gen_helper_idivb_AL(cpu_env, s->T0);
3481 break;
3482 case MO_16:
3483 gen_helper_idivw_AX(cpu_env, s->T0);
3484 break;
3485 default:
3486 case MO_32:
3487 gen_helper_idivl_EAX(cpu_env, s->T0);
3488 break;
3489 #ifdef TARGET_X86_64
3490 case MO_64:
3491 gen_helper_idivq_EAX(cpu_env, s->T0);
3492 break;
3493 #endif
3495 break;
3496 default:
3497 goto unknown_op;
3499 break;
3501 case 0xfe: /* GRP4 */
3502 case 0xff: /* GRP5 */
3503 ot = mo_b_d(b, dflag);
3505 modrm = x86_ldub_code(env, s);
3506 mod = (modrm >> 6) & 3;
3507 rm = (modrm & 7) | REX_B(s);
3508 op = (modrm >> 3) & 7;
3509 if (op >= 2 && b == 0xfe) {
3510 goto unknown_op;
3512 if (CODE64(s)) {
3513 if (op == 2 || op == 4) {
3514 /* operand size for jumps is 64 bit */
3515 ot = MO_64;
3516 } else if (op == 3 || op == 5) {
3517 ot = dflag != MO_16 ? MO_32 + REX_W(s) : MO_16;
3518 } else if (op == 6) {
3519 /* default push size is 64 bit */
3520 ot = mo_pushpop(s, dflag);
3523 if (mod != 3) {
3524 gen_lea_modrm(env, s, modrm);
3525 if (op >= 2 && op != 3 && op != 5)
3526 gen_op_ld_v(s, ot, s->T0, s->A0);
3527 } else {
3528 gen_op_mov_v_reg(s, ot, s->T0, rm);
3531 switch(op) {
3532 case 0: /* inc Ev */
3533 if (mod != 3)
3534 opreg = OR_TMP0;
3535 else
3536 opreg = rm;
3537 gen_inc(s, ot, opreg, 1);
3538 break;
3539 case 1: /* dec Ev */
3540 if (mod != 3)
3541 opreg = OR_TMP0;
3542 else
3543 opreg = rm;
3544 gen_inc(s, ot, opreg, -1);
3545 break;
3546 case 2: /* call Ev */
3547 /* XXX: optimize if memory (no 'and' is necessary) */
3548 if (dflag == MO_16) {
3549 tcg_gen_ext16u_tl(s->T0, s->T0);
3551 gen_push_v(s, eip_next_tl(s));
3552 gen_op_jmp_v(s, s->T0);
3553 gen_bnd_jmp(s);
3554 s->base.is_jmp = DISAS_JUMP;
3555 break;
3556 case 3: /* lcall Ev */
3557 if (mod == 3) {
3558 goto illegal_op;
3560 gen_op_ld_v(s, ot, s->T1, s->A0);
3561 gen_add_A0_im(s, 1 << ot);
3562 gen_op_ld_v(s, MO_16, s->T0, s->A0);
3563 do_lcall:
3564 if (PE(s) && !VM86(s)) {
3565 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3566 gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
3567 tcg_constant_i32(dflag - 1),
3568 eip_next_tl(s));
3569 } else {
3570 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3571 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
3572 gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->tmp3_i32,
3573 tcg_constant_i32(dflag - 1),
3574 eip_next_i32(s));
3576 s->base.is_jmp = DISAS_JUMP;
3577 break;
3578 case 4: /* jmp Ev */
3579 if (dflag == MO_16) {
3580 tcg_gen_ext16u_tl(s->T0, s->T0);
3582 gen_op_jmp_v(s, s->T0);
3583 gen_bnd_jmp(s);
3584 s->base.is_jmp = DISAS_JUMP;
3585 break;
3586 case 5: /* ljmp Ev */
3587 if (mod == 3) {
3588 goto illegal_op;
3590 gen_op_ld_v(s, ot, s->T1, s->A0);
3591 gen_add_A0_im(s, 1 << ot);
3592 gen_op_ld_v(s, MO_16, s->T0, s->A0);
3593 do_ljmp:
3594 if (PE(s) && !VM86(s)) {
3595 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3596 gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1,
3597 eip_next_tl(s));
3598 } else {
3599 gen_op_movl_seg_T0_vm(s, R_CS);
3600 gen_op_jmp_v(s, s->T1);
3602 s->base.is_jmp = DISAS_JUMP;
3603 break;
3604 case 6: /* push Ev */
3605 gen_push_v(s, s->T0);
3606 break;
3607 default:
3608 goto unknown_op;
3610 break;
3612 case 0x84: /* test Ev, Gv */
3613 case 0x85:
3614 ot = mo_b_d(b, dflag);
3616 modrm = x86_ldub_code(env, s);
3617 reg = ((modrm >> 3) & 7) | REX_R(s);
3619 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3620 gen_op_mov_v_reg(s, ot, s->T1, reg);
3621 gen_op_testl_T0_T1_cc(s);
3622 set_cc_op(s, CC_OP_LOGICB + ot);
3623 break;
3625 case 0xa8: /* test eAX, Iv */
3626 case 0xa9:
3627 ot = mo_b_d(b, dflag);
3628 val = insn_get(env, s, ot);
3630 gen_op_mov_v_reg(s, ot, s->T0, OR_EAX);
3631 tcg_gen_movi_tl(s->T1, val);
3632 gen_op_testl_T0_T1_cc(s);
3633 set_cc_op(s, CC_OP_LOGICB + ot);
3634 break;
3636 case 0x98: /* CWDE/CBW */
3637 switch (dflag) {
3638 #ifdef TARGET_X86_64
3639 case MO_64:
3640 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
3641 tcg_gen_ext32s_tl(s->T0, s->T0);
3642 gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0);
3643 break;
3644 #endif
3645 case MO_32:
3646 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
3647 tcg_gen_ext16s_tl(s->T0, s->T0);
3648 gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0);
3649 break;
3650 case MO_16:
3651 gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX);
3652 tcg_gen_ext8s_tl(s->T0, s->T0);
3653 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
3654 break;
3655 default:
3656 tcg_abort();
3658 break;
3659 case 0x99: /* CDQ/CWD */
3660 switch (dflag) {
3661 #ifdef TARGET_X86_64
3662 case MO_64:
3663 gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX);
3664 tcg_gen_sari_tl(s->T0, s->T0, 63);
3665 gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0);
3666 break;
3667 #endif
3668 case MO_32:
3669 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
3670 tcg_gen_ext32s_tl(s->T0, s->T0);
3671 tcg_gen_sari_tl(s->T0, s->T0, 31);
3672 gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0);
3673 break;
3674 case MO_16:
3675 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
3676 tcg_gen_ext16s_tl(s->T0, s->T0);
3677 tcg_gen_sari_tl(s->T0, s->T0, 15);
3678 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
3679 break;
3680 default:
3681 tcg_abort();
3683 break;
3684 case 0x1af: /* imul Gv, Ev */
3685 case 0x69: /* imul Gv, Ev, I */
3686 case 0x6b:
3687 ot = dflag;
3688 modrm = x86_ldub_code(env, s);
3689 reg = ((modrm >> 3) & 7) | REX_R(s);
3690 if (b == 0x69)
3691 s->rip_offset = insn_const_size(ot);
3692 else if (b == 0x6b)
3693 s->rip_offset = 1;
3694 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3695 if (b == 0x69) {
3696 val = insn_get(env, s, ot);
3697 tcg_gen_movi_tl(s->T1, val);
3698 } else if (b == 0x6b) {
3699 val = (int8_t)insn_get(env, s, MO_8);
3700 tcg_gen_movi_tl(s->T1, val);
3701 } else {
3702 gen_op_mov_v_reg(s, ot, s->T1, reg);
3704 switch (ot) {
3705 #ifdef TARGET_X86_64
3706 case MO_64:
3707 tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1);
3708 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
3709 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
3710 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1);
3711 break;
3712 #endif
3713 case MO_32:
3714 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3715 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
3716 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
3717 s->tmp2_i32, s->tmp3_i32);
3718 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3719 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
3720 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
3721 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
3722 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
3723 break;
3724 default:
3725 tcg_gen_ext16s_tl(s->T0, s->T0);
3726 tcg_gen_ext16s_tl(s->T1, s->T1);
3727 /* XXX: use 32 bit mul which could be faster */
3728 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
3729 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
3730 tcg_gen_ext16s_tl(s->tmp0, s->T0);
3731 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
3732 gen_op_mov_reg_v(s, ot, reg, s->T0);
3733 break;
3735 set_cc_op(s, CC_OP_MULB + ot);
3736 break;
3737 case 0x1c0:
3738 case 0x1c1: /* xadd Ev, Gv */
3739 ot = mo_b_d(b, dflag);
3740 modrm = x86_ldub_code(env, s);
3741 reg = ((modrm >> 3) & 7) | REX_R(s);
3742 mod = (modrm >> 6) & 3;
3743 gen_op_mov_v_reg(s, ot, s->T0, reg);
3744 if (mod == 3) {
3745 rm = (modrm & 7) | REX_B(s);
3746 gen_op_mov_v_reg(s, ot, s->T1, rm);
3747 tcg_gen_add_tl(s->T0, s->T0, s->T1);
3748 gen_op_mov_reg_v(s, ot, reg, s->T1);
3749 gen_op_mov_reg_v(s, ot, rm, s->T0);
3750 } else {
3751 gen_lea_modrm(env, s, modrm);
3752 if (s->prefix & PREFIX_LOCK) {
3753 tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0,
3754 s->mem_index, ot | MO_LE);
3755 tcg_gen_add_tl(s->T0, s->T0, s->T1);
3756 } else {
3757 gen_op_ld_v(s, ot, s->T1, s->A0);
3758 tcg_gen_add_tl(s->T0, s->T0, s->T1);
3759 gen_op_st_v(s, ot, s->T0, s->A0);
3761 gen_op_mov_reg_v(s, ot, reg, s->T1);
3763 gen_op_update2_cc(s);
3764 set_cc_op(s, CC_OP_ADDB + ot);
3765 break;
3766 case 0x1b0:
3767 case 0x1b1: /* cmpxchg Ev, Gv */
3769 TCGv oldv, newv, cmpv, dest;
3771 ot = mo_b_d(b, dflag);
3772 modrm = x86_ldub_code(env, s);
3773 reg = ((modrm >> 3) & 7) | REX_R(s);
3774 mod = (modrm >> 6) & 3;
3775 oldv = tcg_temp_new();
3776 newv = tcg_temp_new();
3777 cmpv = tcg_temp_new();
3778 gen_op_mov_v_reg(s, ot, newv, reg);
3779 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
3780 gen_extu(ot, cmpv);
3781 if (s->prefix & PREFIX_LOCK) {
3782 if (mod == 3) {
3783 goto illegal_op;
3785 gen_lea_modrm(env, s, modrm);
3786 tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
3787 s->mem_index, ot | MO_LE);
3788 } else {
3789 if (mod == 3) {
3790 rm = (modrm & 7) | REX_B(s);
3791 gen_op_mov_v_reg(s, ot, oldv, rm);
3792 gen_extu(ot, oldv);
3795 * Unlike the memory case, where "the destination operand receives
3796 * a write cycle without regard to the result of the comparison",
3797 * rm must not be touched altogether if the write fails, including
3798 * not zero-extending it on 64-bit processors. So, precompute
3799 * the result of a successful writeback and perform the movcond
3800 * directly on cpu_regs. Also need to write accumulator first, in
3801 * case rm is part of RAX too.
3803 dest = gen_op_deposit_reg_v(s, ot, rm, newv, newv);
3804 tcg_gen_movcond_tl(TCG_COND_EQ, dest, oldv, cmpv, newv, dest);
3805 } else {
3806 gen_lea_modrm(env, s, modrm);
3807 gen_op_ld_v(s, ot, oldv, s->A0);
3810 * Perform an unconditional store cycle like physical cpu;
3811 * must be before changing accumulator to ensure
3812 * idempotency if the store faults and the instruction
3813 * is restarted
3815 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
3816 gen_op_st_v(s, ot, newv, s->A0);
3820 * Write EAX only if the cmpxchg fails; reuse newv as the destination,
3821 * since it's dead here.
3823 dest = gen_op_deposit_reg_v(s, ot, R_EAX, newv, oldv);
3824 tcg_gen_movcond_tl(TCG_COND_EQ, dest, oldv, cmpv, dest, newv);
3825 tcg_gen_mov_tl(cpu_cc_src, oldv);
3826 tcg_gen_mov_tl(s->cc_srcT, cmpv);
3827 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
3828 set_cc_op(s, CC_OP_SUBB + ot);
3829 tcg_temp_free(oldv);
3830 tcg_temp_free(newv);
3831 tcg_temp_free(cmpv);
3833 break;
3834 case 0x1c7: /* cmpxchg8b */
3835 modrm = x86_ldub_code(env, s);
3836 mod = (modrm >> 6) & 3;
3837 switch ((modrm >> 3) & 7) {
3838 case 1: /* CMPXCHG8, CMPXCHG16 */
3839 if (mod == 3) {
3840 goto illegal_op;
3842 #ifdef TARGET_X86_64
3843 if (dflag == MO_64) {
3844 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) {
3845 goto illegal_op;
3847 gen_lea_modrm(env, s, modrm);
3848 if ((s->prefix & PREFIX_LOCK) &&
3849 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
3850 gen_helper_cmpxchg16b(cpu_env, s->A0);
3851 } else {
3852 gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0);
3854 set_cc_op(s, CC_OP_EFLAGS);
3855 break;
3857 #endif
3858 if (!(s->cpuid_features & CPUID_CX8)) {
3859 goto illegal_op;
3861 gen_lea_modrm(env, s, modrm);
3862 if ((s->prefix & PREFIX_LOCK) &&
3863 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
3864 gen_helper_cmpxchg8b(cpu_env, s->A0);
3865 } else {
3866 gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0);
3868 set_cc_op(s, CC_OP_EFLAGS);
3869 break;
3871 case 7: /* RDSEED */
3872 case 6: /* RDRAND */
3873 if (mod != 3 ||
3874 (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
3875 !(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
3876 goto illegal_op;
3878 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3879 gen_io_start();
3880 s->base.is_jmp = DISAS_TOO_MANY;
3882 gen_helper_rdrand(s->T0, cpu_env);
3883 rm = (modrm & 7) | REX_B(s);
3884 gen_op_mov_reg_v(s, dflag, rm, s->T0);
3885 set_cc_op(s, CC_OP_EFLAGS);
3886 break;
3888 default:
3889 goto illegal_op;
3891 break;
3893 /**************************/
3894 /* push/pop */
3895 case 0x50 ... 0x57: /* push */
3896 gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s));
3897 gen_push_v(s, s->T0);
3898 break;
3899 case 0x58 ... 0x5f: /* pop */
3900 ot = gen_pop_T0(s);
3901 /* NOTE: order is important for pop %sp */
3902 gen_pop_update(s, ot);
3903 gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0);
3904 break;
3905 case 0x60: /* pusha */
3906 if (CODE64(s))
3907 goto illegal_op;
3908 gen_pusha(s);
3909 break;
3910 case 0x61: /* popa */
3911 if (CODE64(s))
3912 goto illegal_op;
3913 gen_popa(s);
3914 break;
3915 case 0x68: /* push Iv */
3916 case 0x6a:
3917 ot = mo_pushpop(s, dflag);
3918 if (b == 0x68)
3919 val = insn_get(env, s, ot);
3920 else
3921 val = (int8_t)insn_get(env, s, MO_8);
3922 tcg_gen_movi_tl(s->T0, val);
3923 gen_push_v(s, s->T0);
3924 break;
3925 case 0x8f: /* pop Ev */
3926 modrm = x86_ldub_code(env, s);
3927 mod = (modrm >> 6) & 3;
3928 ot = gen_pop_T0(s);
3929 if (mod == 3) {
3930 /* NOTE: order is important for pop %sp */
3931 gen_pop_update(s, ot);
3932 rm = (modrm & 7) | REX_B(s);
3933 gen_op_mov_reg_v(s, ot, rm, s->T0);
3934 } else {
3935 /* NOTE: order is important too for MMU exceptions */
3936 s->popl_esp_hack = 1 << ot;
3937 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
3938 s->popl_esp_hack = 0;
3939 gen_pop_update(s, ot);
3941 break;
3942 case 0xc8: /* enter */
3944 int level;
3945 val = x86_lduw_code(env, s);
3946 level = x86_ldub_code(env, s);
3947 gen_enter(s, val, level);
3949 break;
3950 case 0xc9: /* leave */
3951 gen_leave(s);
3952 break;
3953 case 0x06: /* push es */
3954 case 0x0e: /* push cs */
3955 case 0x16: /* push ss */
3956 case 0x1e: /* push ds */
3957 if (CODE64(s))
3958 goto illegal_op;
3959 gen_op_movl_T0_seg(s, b >> 3);
3960 gen_push_v(s, s->T0);
3961 break;
3962 case 0x1a0: /* push fs */
3963 case 0x1a8: /* push gs */
3964 gen_op_movl_T0_seg(s, (b >> 3) & 7);
3965 gen_push_v(s, s->T0);
3966 break;
3967 case 0x07: /* pop es */
3968 case 0x17: /* pop ss */
3969 case 0x1f: /* pop ds */
3970 if (CODE64(s))
3971 goto illegal_op;
3972 reg = b >> 3;
3973 ot = gen_pop_T0(s);
3974 gen_movl_seg_T0(s, reg);
3975 gen_pop_update(s, ot);
3976 break;
3977 case 0x1a1: /* pop fs */
3978 case 0x1a9: /* pop gs */
3979 ot = gen_pop_T0(s);
3980 gen_movl_seg_T0(s, (b >> 3) & 7);
3981 gen_pop_update(s, ot);
3982 break;
3984 /**************************/
3985 /* mov */
3986 case 0x88:
3987 case 0x89: /* mov Gv, Ev */
3988 ot = mo_b_d(b, dflag);
3989 modrm = x86_ldub_code(env, s);
3990 reg = ((modrm >> 3) & 7) | REX_R(s);
3992 /* generate a generic store */
3993 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
3994 break;
3995 case 0xc6:
3996 case 0xc7: /* mov Ev, Iv */
3997 ot = mo_b_d(b, dflag);
3998 modrm = x86_ldub_code(env, s);
3999 mod = (modrm >> 6) & 3;
4000 if (mod != 3) {
4001 s->rip_offset = insn_const_size(ot);
4002 gen_lea_modrm(env, s, modrm);
4004 val = insn_get(env, s, ot);
4005 tcg_gen_movi_tl(s->T0, val);
4006 if (mod != 3) {
4007 gen_op_st_v(s, ot, s->T0, s->A0);
4008 } else {
4009 gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0);
4011 break;
4012 case 0x8a:
4013 case 0x8b: /* mov Ev, Gv */
4014 ot = mo_b_d(b, dflag);
4015 modrm = x86_ldub_code(env, s);
4016 reg = ((modrm >> 3) & 7) | REX_R(s);
4018 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4019 gen_op_mov_reg_v(s, ot, reg, s->T0);
4020 break;
4021 case 0x8e: /* mov seg, Gv */
4022 modrm = x86_ldub_code(env, s);
4023 reg = (modrm >> 3) & 7;
4024 if (reg >= 6 || reg == R_CS)
4025 goto illegal_op;
4026 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
4027 gen_movl_seg_T0(s, reg);
4028 break;
4029 case 0x8c: /* mov Gv, seg */
4030 modrm = x86_ldub_code(env, s);
4031 reg = (modrm >> 3) & 7;
4032 mod = (modrm >> 6) & 3;
4033 if (reg >= 6)
4034 goto illegal_op;
4035 gen_op_movl_T0_seg(s, reg);
4036 ot = mod == 3 ? dflag : MO_16;
4037 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
4038 break;
4040 case 0x1b6: /* movzbS Gv, Eb */
4041 case 0x1b7: /* movzwS Gv, Eb */
4042 case 0x1be: /* movsbS Gv, Eb */
4043 case 0x1bf: /* movswS Gv, Eb */
4045 MemOp d_ot;
4046 MemOp s_ot;
4048 /* d_ot is the size of destination */
4049 d_ot = dflag;
4050 /* ot is the size of source */
4051 ot = (b & 1) + MO_8;
4052 /* s_ot is the sign+size of source */
4053 s_ot = b & 8 ? MO_SIGN | ot : ot;
4055 modrm = x86_ldub_code(env, s);
4056 reg = ((modrm >> 3) & 7) | REX_R(s);
4057 mod = (modrm >> 6) & 3;
4058 rm = (modrm & 7) | REX_B(s);
4060 if (mod == 3) {
4061 if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) {
4062 tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8);
4063 } else {
4064 gen_op_mov_v_reg(s, ot, s->T0, rm);
4065 switch (s_ot) {
4066 case MO_UB:
4067 tcg_gen_ext8u_tl(s->T0, s->T0);
4068 break;
4069 case MO_SB:
4070 tcg_gen_ext8s_tl(s->T0, s->T0);
4071 break;
4072 case MO_UW:
4073 tcg_gen_ext16u_tl(s->T0, s->T0);
4074 break;
4075 default:
4076 case MO_SW:
4077 tcg_gen_ext16s_tl(s->T0, s->T0);
4078 break;
4081 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
4082 } else {
4083 gen_lea_modrm(env, s, modrm);
4084 gen_op_ld_v(s, s_ot, s->T0, s->A0);
4085 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
4088 break;
4090 case 0x8d: /* lea */
4091 modrm = x86_ldub_code(env, s);
4092 mod = (modrm >> 6) & 3;
4093 if (mod == 3)
4094 goto illegal_op;
4095 reg = ((modrm >> 3) & 7) | REX_R(s);
4097 AddressParts a = gen_lea_modrm_0(env, s, modrm);
4098 TCGv ea = gen_lea_modrm_1(s, a, false);
4099 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
4100 gen_op_mov_reg_v(s, dflag, reg, s->A0);
4102 break;
4104 case 0xa0: /* mov EAX, Ov */
4105 case 0xa1:
4106 case 0xa2: /* mov Ov, EAX */
4107 case 0xa3:
4109 target_ulong offset_addr;
4111 ot = mo_b_d(b, dflag);
4112 offset_addr = insn_get_addr(env, s, s->aflag);
4113 tcg_gen_movi_tl(s->A0, offset_addr);
4114 gen_add_A0_ds_seg(s);
4115 if ((b & 2) == 0) {
4116 gen_op_ld_v(s, ot, s->T0, s->A0);
4117 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
4118 } else {
4119 gen_op_mov_v_reg(s, ot, s->T0, R_EAX);
4120 gen_op_st_v(s, ot, s->T0, s->A0);
4123 break;
4124 case 0xd7: /* xlat */
4125 tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]);
4126 tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]);
4127 tcg_gen_add_tl(s->A0, s->A0, s->T0);
4128 gen_extu(s->aflag, s->A0);
4129 gen_add_A0_ds_seg(s);
4130 gen_op_ld_v(s, MO_8, s->T0, s->A0);
4131 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
4132 break;
4133 case 0xb0 ... 0xb7: /* mov R, Ib */
4134 val = insn_get(env, s, MO_8);
4135 tcg_gen_movi_tl(s->T0, val);
4136 gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0);
4137 break;
4138 case 0xb8 ... 0xbf: /* mov R, Iv */
4139 #ifdef TARGET_X86_64
4140 if (dflag == MO_64) {
4141 uint64_t tmp;
4142 /* 64 bit case */
4143 tmp = x86_ldq_code(env, s);
4144 reg = (b & 7) | REX_B(s);
4145 tcg_gen_movi_tl(s->T0, tmp);
4146 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
4147 } else
4148 #endif
4150 ot = dflag;
4151 val = insn_get(env, s, ot);
4152 reg = (b & 7) | REX_B(s);
4153 tcg_gen_movi_tl(s->T0, val);
4154 gen_op_mov_reg_v(s, ot, reg, s->T0);
4156 break;
4158 case 0x91 ... 0x97: /* xchg R, EAX */
4159 do_xchg_reg_eax:
4160 ot = dflag;
4161 reg = (b & 7) | REX_B(s);
4162 rm = R_EAX;
4163 goto do_xchg_reg;
4164 case 0x86:
4165 case 0x87: /* xchg Ev, Gv */
4166 ot = mo_b_d(b, dflag);
4167 modrm = x86_ldub_code(env, s);
4168 reg = ((modrm >> 3) & 7) | REX_R(s);
4169 mod = (modrm >> 6) & 3;
4170 if (mod == 3) {
4171 rm = (modrm & 7) | REX_B(s);
4172 do_xchg_reg:
4173 gen_op_mov_v_reg(s, ot, s->T0, reg);
4174 gen_op_mov_v_reg(s, ot, s->T1, rm);
4175 gen_op_mov_reg_v(s, ot, rm, s->T0);
4176 gen_op_mov_reg_v(s, ot, reg, s->T1);
4177 } else {
4178 gen_lea_modrm(env, s, modrm);
4179 gen_op_mov_v_reg(s, ot, s->T0, reg);
4180 /* for xchg, lock is implicit */
4181 tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0,
4182 s->mem_index, ot | MO_LE);
4183 gen_op_mov_reg_v(s, ot, reg, s->T1);
4185 break;
4186 case 0xc4: /* les Gv */
4187 /* In CODE64 this is VEX3; see above. */
4188 op = R_ES;
4189 goto do_lxx;
4190 case 0xc5: /* lds Gv */
4191 /* In CODE64 this is VEX2; see above. */
4192 op = R_DS;
4193 goto do_lxx;
4194 case 0x1b2: /* lss Gv */
4195 op = R_SS;
4196 goto do_lxx;
4197 case 0x1b4: /* lfs Gv */
4198 op = R_FS;
4199 goto do_lxx;
4200 case 0x1b5: /* lgs Gv */
4201 op = R_GS;
4202 do_lxx:
4203 ot = dflag != MO_16 ? MO_32 : MO_16;
4204 modrm = x86_ldub_code(env, s);
4205 reg = ((modrm >> 3) & 7) | REX_R(s);
4206 mod = (modrm >> 6) & 3;
4207 if (mod == 3)
4208 goto illegal_op;
4209 gen_lea_modrm(env, s, modrm);
4210 gen_op_ld_v(s, ot, s->T1, s->A0);
4211 gen_add_A0_im(s, 1 << ot);
4212 /* load the segment first to handle exceptions properly */
4213 gen_op_ld_v(s, MO_16, s->T0, s->A0);
4214 gen_movl_seg_T0(s, op);
4215 /* then put the data */
4216 gen_op_mov_reg_v(s, ot, reg, s->T1);
4217 break;
4219 /************************/
4220 /* shifts */
4221 case 0xc0:
4222 case 0xc1:
4223 /* shift Ev,Ib */
4224 shift = 2;
4225 grp2:
4227 ot = mo_b_d(b, dflag);
4228 modrm = x86_ldub_code(env, s);
4229 mod = (modrm >> 6) & 3;
4230 op = (modrm >> 3) & 7;
4232 if (mod != 3) {
4233 if (shift == 2) {
4234 s->rip_offset = 1;
4236 gen_lea_modrm(env, s, modrm);
4237 opreg = OR_TMP0;
4238 } else {
4239 opreg = (modrm & 7) | REX_B(s);
4242 /* simpler op */
4243 if (shift == 0) {
4244 gen_shift(s, op, ot, opreg, OR_ECX);
4245 } else {
4246 if (shift == 2) {
4247 shift = x86_ldub_code(env, s);
4249 gen_shifti(s, op, ot, opreg, shift);
4252 break;
4253 case 0xd0:
4254 case 0xd1:
4255 /* shift Ev,1 */
4256 shift = 1;
4257 goto grp2;
4258 case 0xd2:
4259 case 0xd3:
4260 /* shift Ev,cl */
4261 shift = 0;
4262 goto grp2;
4264 case 0x1a4: /* shld imm */
4265 op = 0;
4266 shift = 1;
4267 goto do_shiftd;
4268 case 0x1a5: /* shld cl */
4269 op = 0;
4270 shift = 0;
4271 goto do_shiftd;
4272 case 0x1ac: /* shrd imm */
4273 op = 1;
4274 shift = 1;
4275 goto do_shiftd;
4276 case 0x1ad: /* shrd cl */
4277 op = 1;
4278 shift = 0;
4279 do_shiftd:
4280 ot = dflag;
4281 modrm = x86_ldub_code(env, s);
4282 mod = (modrm >> 6) & 3;
4283 rm = (modrm & 7) | REX_B(s);
4284 reg = ((modrm >> 3) & 7) | REX_R(s);
4285 if (mod != 3) {
4286 gen_lea_modrm(env, s, modrm);
4287 opreg = OR_TMP0;
4288 } else {
4289 opreg = rm;
4291 gen_op_mov_v_reg(s, ot, s->T1, reg);
4293 if (shift) {
4294 TCGv imm = tcg_const_tl(x86_ldub_code(env, s));
4295 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
4296 tcg_temp_free(imm);
4297 } else {
4298 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
4300 break;
4302 /************************/
4303 /* floats */
4304 case 0xd8 ... 0xdf:
4306 bool update_fip = true;
4308 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4309 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4310 /* XXX: what to do if illegal op ? */
4311 gen_exception(s, EXCP07_PREX);
4312 break;
4314 modrm = x86_ldub_code(env, s);
4315 mod = (modrm >> 6) & 3;
4316 rm = modrm & 7;
4317 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
4318 if (mod != 3) {
4319 /* memory op */
4320 AddressParts a = gen_lea_modrm_0(env, s, modrm);
4321 TCGv ea = gen_lea_modrm_1(s, a, false);
4322 TCGv last_addr = tcg_temp_new();
4323 bool update_fdp = true;
4325 tcg_gen_mov_tl(last_addr, ea);
4326 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
4328 switch (op) {
4329 case 0x00 ... 0x07: /* fxxxs */
4330 case 0x10 ... 0x17: /* fixxxl */
4331 case 0x20 ... 0x27: /* fxxxl */
4332 case 0x30 ... 0x37: /* fixxx */
4334 int op1;
4335 op1 = op & 7;
4337 switch (op >> 4) {
4338 case 0:
4339 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4340 s->mem_index, MO_LEUL);
4341 gen_helper_flds_FT0(cpu_env, s->tmp2_i32);
4342 break;
4343 case 1:
4344 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4345 s->mem_index, MO_LEUL);
4346 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
4347 break;
4348 case 2:
4349 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4350 s->mem_index, MO_LEUQ);
4351 gen_helper_fldl_FT0(cpu_env, s->tmp1_i64);
4352 break;
4353 case 3:
4354 default:
4355 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4356 s->mem_index, MO_LESW);
4357 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
4358 break;
4361 gen_helper_fp_arith_ST0_FT0(op1);
4362 if (op1 == 3) {
4363 /* fcomp needs pop */
4364 gen_helper_fpop(cpu_env);
4367 break;
4368 case 0x08: /* flds */
4369 case 0x0a: /* fsts */
4370 case 0x0b: /* fstps */
4371 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
4372 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
4373 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
4374 switch (op & 7) {
4375 case 0:
4376 switch (op >> 4) {
4377 case 0:
4378 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4379 s->mem_index, MO_LEUL);
4380 gen_helper_flds_ST0(cpu_env, s->tmp2_i32);
4381 break;
4382 case 1:
4383 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4384 s->mem_index, MO_LEUL);
4385 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
4386 break;
4387 case 2:
4388 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4389 s->mem_index, MO_LEUQ);
4390 gen_helper_fldl_ST0(cpu_env, s->tmp1_i64);
4391 break;
4392 case 3:
4393 default:
4394 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4395 s->mem_index, MO_LESW);
4396 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
4397 break;
4399 break;
4400 case 1:
4401 /* XXX: the corresponding CPUID bit must be tested ! */
4402 switch (op >> 4) {
4403 case 1:
4404 gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env);
4405 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4406 s->mem_index, MO_LEUL);
4407 break;
4408 case 2:
4409 gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env);
4410 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4411 s->mem_index, MO_LEUQ);
4412 break;
4413 case 3:
4414 default:
4415 gen_helper_fistt_ST0(s->tmp2_i32, cpu_env);
4416 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4417 s->mem_index, MO_LEUW);
4418 break;
4420 gen_helper_fpop(cpu_env);
4421 break;
4422 default:
4423 switch (op >> 4) {
4424 case 0:
4425 gen_helper_fsts_ST0(s->tmp2_i32, cpu_env);
4426 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4427 s->mem_index, MO_LEUL);
4428 break;
4429 case 1:
4430 gen_helper_fistl_ST0(s->tmp2_i32, cpu_env);
4431 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4432 s->mem_index, MO_LEUL);
4433 break;
4434 case 2:
4435 gen_helper_fstl_ST0(s->tmp1_i64, cpu_env);
4436 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4437 s->mem_index, MO_LEUQ);
4438 break;
4439 case 3:
4440 default:
4441 gen_helper_fist_ST0(s->tmp2_i32, cpu_env);
4442 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4443 s->mem_index, MO_LEUW);
4444 break;
4446 if ((op & 7) == 3) {
4447 gen_helper_fpop(cpu_env);
4449 break;
4451 break;
4452 case 0x0c: /* fldenv mem */
4453 gen_helper_fldenv(cpu_env, s->A0,
4454 tcg_const_i32(dflag - 1));
4455 update_fip = update_fdp = false;
4456 break;
4457 case 0x0d: /* fldcw mem */
4458 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4459 s->mem_index, MO_LEUW);
4460 gen_helper_fldcw(cpu_env, s->tmp2_i32);
4461 update_fip = update_fdp = false;
4462 break;
4463 case 0x0e: /* fnstenv mem */
4464 gen_helper_fstenv(cpu_env, s->A0,
4465 tcg_const_i32(dflag - 1));
4466 update_fip = update_fdp = false;
4467 break;
4468 case 0x0f: /* fnstcw mem */
4469 gen_helper_fnstcw(s->tmp2_i32, cpu_env);
4470 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4471 s->mem_index, MO_LEUW);
4472 update_fip = update_fdp = false;
4473 break;
4474 case 0x1d: /* fldt mem */
4475 gen_helper_fldt_ST0(cpu_env, s->A0);
4476 break;
4477 case 0x1f: /* fstpt mem */
4478 gen_helper_fstt_ST0(cpu_env, s->A0);
4479 gen_helper_fpop(cpu_env);
4480 break;
4481 case 0x2c: /* frstor mem */
4482 gen_helper_frstor(cpu_env, s->A0,
4483 tcg_const_i32(dflag - 1));
4484 update_fip = update_fdp = false;
4485 break;
4486 case 0x2e: /* fnsave mem */
4487 gen_helper_fsave(cpu_env, s->A0,
4488 tcg_const_i32(dflag - 1));
4489 update_fip = update_fdp = false;
4490 break;
4491 case 0x2f: /* fnstsw mem */
4492 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
4493 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4494 s->mem_index, MO_LEUW);
4495 update_fip = update_fdp = false;
4496 break;
4497 case 0x3c: /* fbld */
4498 gen_helper_fbld_ST0(cpu_env, s->A0);
4499 break;
4500 case 0x3e: /* fbstp */
4501 gen_helper_fbst_ST0(cpu_env, s->A0);
4502 gen_helper_fpop(cpu_env);
4503 break;
4504 case 0x3d: /* fildll */
4505 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4506 s->mem_index, MO_LEUQ);
4507 gen_helper_fildll_ST0(cpu_env, s->tmp1_i64);
4508 break;
4509 case 0x3f: /* fistpll */
4510 gen_helper_fistll_ST0(s->tmp1_i64, cpu_env);
4511 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4512 s->mem_index, MO_LEUQ);
4513 gen_helper_fpop(cpu_env);
4514 break;
4515 default:
4516 goto unknown_op;
4519 if (update_fdp) {
4520 int last_seg = s->override >= 0 ? s->override : a.def_seg;
4522 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4523 offsetof(CPUX86State,
4524 segs[last_seg].selector));
4525 tcg_gen_st16_i32(s->tmp2_i32, cpu_env,
4526 offsetof(CPUX86State, fpds));
4527 tcg_gen_st_tl(last_addr, cpu_env,
4528 offsetof(CPUX86State, fpdp));
4530 tcg_temp_free(last_addr);
4531 } else {
4532 /* register float ops */
4533 opreg = rm;
4535 switch (op) {
4536 case 0x08: /* fld sti */
4537 gen_helper_fpush(cpu_env);
4538 gen_helper_fmov_ST0_STN(cpu_env,
4539 tcg_const_i32((opreg + 1) & 7));
4540 break;
4541 case 0x09: /* fxchg sti */
4542 case 0x29: /* fxchg4 sti, undocumented op */
4543 case 0x39: /* fxchg7 sti, undocumented op */
4544 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
4545 break;
4546 case 0x0a: /* grp d9/2 */
4547 switch (rm) {
4548 case 0: /* fnop */
4549 /* check exceptions (FreeBSD FPU probe) */
4550 gen_helper_fwait(cpu_env);
4551 update_fip = false;
4552 break;
4553 default:
4554 goto unknown_op;
4556 break;
4557 case 0x0c: /* grp d9/4 */
4558 switch (rm) {
4559 case 0: /* fchs */
4560 gen_helper_fchs_ST0(cpu_env);
4561 break;
4562 case 1: /* fabs */
4563 gen_helper_fabs_ST0(cpu_env);
4564 break;
4565 case 4: /* ftst */
4566 gen_helper_fldz_FT0(cpu_env);
4567 gen_helper_fcom_ST0_FT0(cpu_env);
4568 break;
4569 case 5: /* fxam */
4570 gen_helper_fxam_ST0(cpu_env);
4571 break;
4572 default:
4573 goto unknown_op;
4575 break;
4576 case 0x0d: /* grp d9/5 */
4578 switch (rm) {
4579 case 0:
4580 gen_helper_fpush(cpu_env);
4581 gen_helper_fld1_ST0(cpu_env);
4582 break;
4583 case 1:
4584 gen_helper_fpush(cpu_env);
4585 gen_helper_fldl2t_ST0(cpu_env);
4586 break;
4587 case 2:
4588 gen_helper_fpush(cpu_env);
4589 gen_helper_fldl2e_ST0(cpu_env);
4590 break;
4591 case 3:
4592 gen_helper_fpush(cpu_env);
4593 gen_helper_fldpi_ST0(cpu_env);
4594 break;
4595 case 4:
4596 gen_helper_fpush(cpu_env);
4597 gen_helper_fldlg2_ST0(cpu_env);
4598 break;
4599 case 5:
4600 gen_helper_fpush(cpu_env);
4601 gen_helper_fldln2_ST0(cpu_env);
4602 break;
4603 case 6:
4604 gen_helper_fpush(cpu_env);
4605 gen_helper_fldz_ST0(cpu_env);
4606 break;
4607 default:
4608 goto unknown_op;
4611 break;
4612 case 0x0e: /* grp d9/6 */
4613 switch (rm) {
4614 case 0: /* f2xm1 */
4615 gen_helper_f2xm1(cpu_env);
4616 break;
4617 case 1: /* fyl2x */
4618 gen_helper_fyl2x(cpu_env);
4619 break;
4620 case 2: /* fptan */
4621 gen_helper_fptan(cpu_env);
4622 break;
4623 case 3: /* fpatan */
4624 gen_helper_fpatan(cpu_env);
4625 break;
4626 case 4: /* fxtract */
4627 gen_helper_fxtract(cpu_env);
4628 break;
4629 case 5: /* fprem1 */
4630 gen_helper_fprem1(cpu_env);
4631 break;
4632 case 6: /* fdecstp */
4633 gen_helper_fdecstp(cpu_env);
4634 break;
4635 default:
4636 case 7: /* fincstp */
4637 gen_helper_fincstp(cpu_env);
4638 break;
4640 break;
4641 case 0x0f: /* grp d9/7 */
4642 switch (rm) {
4643 case 0: /* fprem */
4644 gen_helper_fprem(cpu_env);
4645 break;
4646 case 1: /* fyl2xp1 */
4647 gen_helper_fyl2xp1(cpu_env);
4648 break;
4649 case 2: /* fsqrt */
4650 gen_helper_fsqrt(cpu_env);
4651 break;
4652 case 3: /* fsincos */
4653 gen_helper_fsincos(cpu_env);
4654 break;
4655 case 5: /* fscale */
4656 gen_helper_fscale(cpu_env);
4657 break;
4658 case 4: /* frndint */
4659 gen_helper_frndint(cpu_env);
4660 break;
4661 case 6: /* fsin */
4662 gen_helper_fsin(cpu_env);
4663 break;
4664 default:
4665 case 7: /* fcos */
4666 gen_helper_fcos(cpu_env);
4667 break;
4669 break;
4670 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4671 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4672 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4674 int op1;
4676 op1 = op & 7;
4677 if (op >= 0x20) {
4678 gen_helper_fp_arith_STN_ST0(op1, opreg);
4679 if (op >= 0x30) {
4680 gen_helper_fpop(cpu_env);
4682 } else {
4683 gen_helper_fmov_FT0_STN(cpu_env,
4684 tcg_const_i32(opreg));
4685 gen_helper_fp_arith_ST0_FT0(op1);
4688 break;
4689 case 0x02: /* fcom */
4690 case 0x22: /* fcom2, undocumented op */
4691 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
4692 gen_helper_fcom_ST0_FT0(cpu_env);
4693 break;
4694 case 0x03: /* fcomp */
4695 case 0x23: /* fcomp3, undocumented op */
4696 case 0x32: /* fcomp5, undocumented op */
4697 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
4698 gen_helper_fcom_ST0_FT0(cpu_env);
4699 gen_helper_fpop(cpu_env);
4700 break;
4701 case 0x15: /* da/5 */
4702 switch (rm) {
4703 case 1: /* fucompp */
4704 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
4705 gen_helper_fucom_ST0_FT0(cpu_env);
4706 gen_helper_fpop(cpu_env);
4707 gen_helper_fpop(cpu_env);
4708 break;
4709 default:
4710 goto unknown_op;
4712 break;
4713 case 0x1c:
4714 switch (rm) {
4715 case 0: /* feni (287 only, just do nop here) */
4716 break;
4717 case 1: /* fdisi (287 only, just do nop here) */
4718 break;
4719 case 2: /* fclex */
4720 gen_helper_fclex(cpu_env);
4721 update_fip = false;
4722 break;
4723 case 3: /* fninit */
4724 gen_helper_fninit(cpu_env);
4725 update_fip = false;
4726 break;
4727 case 4: /* fsetpm (287 only, just do nop here) */
4728 break;
4729 default:
4730 goto unknown_op;
4732 break;
4733 case 0x1d: /* fucomi */
4734 if (!(s->cpuid_features & CPUID_CMOV)) {
4735 goto illegal_op;
4737 gen_update_cc_op(s);
4738 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
4739 gen_helper_fucomi_ST0_FT0(cpu_env);
4740 set_cc_op(s, CC_OP_EFLAGS);
4741 break;
4742 case 0x1e: /* fcomi */
4743 if (!(s->cpuid_features & CPUID_CMOV)) {
4744 goto illegal_op;
4746 gen_update_cc_op(s);
4747 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
4748 gen_helper_fcomi_ST0_FT0(cpu_env);
4749 set_cc_op(s, CC_OP_EFLAGS);
4750 break;
4751 case 0x28: /* ffree sti */
4752 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
4753 break;
4754 case 0x2a: /* fst sti */
4755 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
4756 break;
4757 case 0x2b: /* fstp sti */
4758 case 0x0b: /* fstp1 sti, undocumented op */
4759 case 0x3a: /* fstp8 sti, undocumented op */
4760 case 0x3b: /* fstp9 sti, undocumented op */
4761 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
4762 gen_helper_fpop(cpu_env);
4763 break;
4764 case 0x2c: /* fucom st(i) */
4765 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
4766 gen_helper_fucom_ST0_FT0(cpu_env);
4767 break;
4768 case 0x2d: /* fucomp st(i) */
4769 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
4770 gen_helper_fucom_ST0_FT0(cpu_env);
4771 gen_helper_fpop(cpu_env);
4772 break;
4773 case 0x33: /* de/3 */
4774 switch (rm) {
4775 case 1: /* fcompp */
4776 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
4777 gen_helper_fcom_ST0_FT0(cpu_env);
4778 gen_helper_fpop(cpu_env);
4779 gen_helper_fpop(cpu_env);
4780 break;
4781 default:
4782 goto unknown_op;
4784 break;
4785 case 0x38: /* ffreep sti, undocumented op */
4786 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
4787 gen_helper_fpop(cpu_env);
4788 break;
4789 case 0x3c: /* df/4 */
4790 switch (rm) {
4791 case 0:
4792 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
4793 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
4794 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4795 break;
4796 default:
4797 goto unknown_op;
4799 break;
4800 case 0x3d: /* fucomip */
4801 if (!(s->cpuid_features & CPUID_CMOV)) {
4802 goto illegal_op;
4804 gen_update_cc_op(s);
4805 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
4806 gen_helper_fucomi_ST0_FT0(cpu_env);
4807 gen_helper_fpop(cpu_env);
4808 set_cc_op(s, CC_OP_EFLAGS);
4809 break;
4810 case 0x3e: /* fcomip */
4811 if (!(s->cpuid_features & CPUID_CMOV)) {
4812 goto illegal_op;
4814 gen_update_cc_op(s);
4815 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
4816 gen_helper_fcomi_ST0_FT0(cpu_env);
4817 gen_helper_fpop(cpu_env);
4818 set_cc_op(s, CC_OP_EFLAGS);
4819 break;
4820 case 0x10 ... 0x13: /* fcmovxx */
4821 case 0x18 ... 0x1b:
4823 int op1;
4824 TCGLabel *l1;
4825 static const uint8_t fcmov_cc[8] = {
4826 (JCC_B << 1),
4827 (JCC_Z << 1),
4828 (JCC_BE << 1),
4829 (JCC_P << 1),
4832 if (!(s->cpuid_features & CPUID_CMOV)) {
4833 goto illegal_op;
4835 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
4836 l1 = gen_new_label();
4837 gen_jcc1_noeob(s, op1, l1);
4838 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
4839 gen_set_label(l1);
4841 break;
4842 default:
4843 goto unknown_op;
4847 if (update_fip) {
4848 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4849 offsetof(CPUX86State, segs[R_CS].selector));
4850 tcg_gen_st16_i32(s->tmp2_i32, cpu_env,
4851 offsetof(CPUX86State, fpcs));
4852 tcg_gen_st_tl(eip_cur_tl(s),
4853 cpu_env, offsetof(CPUX86State, fpip));
4856 break;
4857 /************************/
4858 /* string ops */
4860 case 0xa4: /* movsS */
4861 case 0xa5:
4862 ot = mo_b_d(b, dflag);
4863 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4864 gen_repz_movs(s, ot);
4865 } else {
4866 gen_movs(s, ot);
4868 break;
4870 case 0xaa: /* stosS */
4871 case 0xab:
4872 ot = mo_b_d(b, dflag);
4873 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4874 gen_repz_stos(s, ot);
4875 } else {
4876 gen_stos(s, ot);
4878 break;
4879 case 0xac: /* lodsS */
4880 case 0xad:
4881 ot = mo_b_d(b, dflag);
4882 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4883 gen_repz_lods(s, ot);
4884 } else {
4885 gen_lods(s, ot);
4887 break;
4888 case 0xae: /* scasS */
4889 case 0xaf:
4890 ot = mo_b_d(b, dflag);
4891 if (prefixes & PREFIX_REPNZ) {
4892 gen_repz_scas(s, ot, 1);
4893 } else if (prefixes & PREFIX_REPZ) {
4894 gen_repz_scas(s, ot, 0);
4895 } else {
4896 gen_scas(s, ot);
4898 break;
4900 case 0xa6: /* cmpsS */
4901 case 0xa7:
4902 ot = mo_b_d(b, dflag);
4903 if (prefixes & PREFIX_REPNZ) {
4904 gen_repz_cmps(s, ot, 1);
4905 } else if (prefixes & PREFIX_REPZ) {
4906 gen_repz_cmps(s, ot, 0);
4907 } else {
4908 gen_cmps(s, ot);
4910 break;
4911 case 0x6c: /* insS */
4912 case 0x6d:
4913 ot = mo_b_d32(b, dflag);
4914 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
4915 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
4916 if (!gen_check_io(s, ot, s->tmp2_i32,
4917 SVM_IOIO_TYPE_MASK | SVM_IOIO_STR_MASK)) {
4918 break;
4920 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4921 gen_io_start();
4922 s->base.is_jmp = DISAS_TOO_MANY;
4924 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4925 gen_repz_ins(s, ot);
4926 } else {
4927 gen_ins(s, ot);
4929 break;
4930 case 0x6e: /* outsS */
4931 case 0x6f:
4932 ot = mo_b_d32(b, dflag);
4933 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
4934 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
4935 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_STR_MASK)) {
4936 break;
4938 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4939 gen_io_start();
4940 s->base.is_jmp = DISAS_TOO_MANY;
4942 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4943 gen_repz_outs(s, ot);
4944 } else {
4945 gen_outs(s, ot);
4947 break;
4949 /************************/
4950 /* port I/O */
4952 case 0xe4:
4953 case 0xe5:
4954 ot = mo_b_d32(b, dflag);
4955 val = x86_ldub_code(env, s);
4956 tcg_gen_movi_i32(s->tmp2_i32, val);
4957 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) {
4958 break;
4960 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4961 gen_io_start();
4962 s->base.is_jmp = DISAS_TOO_MANY;
4964 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
4965 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
4966 gen_bpt_io(s, s->tmp2_i32, ot);
4967 break;
4968 case 0xe6:
4969 case 0xe7:
4970 ot = mo_b_d32(b, dflag);
4971 val = x86_ldub_code(env, s);
4972 tcg_gen_movi_i32(s->tmp2_i32, val);
4973 if (!gen_check_io(s, ot, s->tmp2_i32, 0)) {
4974 break;
4976 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4977 gen_io_start();
4978 s->base.is_jmp = DISAS_TOO_MANY;
4980 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
4981 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
4982 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
4983 gen_bpt_io(s, s->tmp2_i32, ot);
4984 break;
4985 case 0xec:
4986 case 0xed:
4987 ot = mo_b_d32(b, dflag);
4988 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
4989 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
4990 if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) {
4991 break;
4993 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4994 gen_io_start();
4995 s->base.is_jmp = DISAS_TOO_MANY;
4997 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
4998 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
4999 gen_bpt_io(s, s->tmp2_i32, ot);
5000 break;
5001 case 0xee:
5002 case 0xef:
5003 ot = mo_b_d32(b, dflag);
5004 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
5005 tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32);
5006 if (!gen_check_io(s, ot, s->tmp2_i32, 0)) {
5007 break;
5009 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5010 gen_io_start();
5011 s->base.is_jmp = DISAS_TOO_MANY;
5013 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
5014 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
5015 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
5016 gen_bpt_io(s, s->tmp2_i32, ot);
5017 break;
5019 /************************/
5020 /* control */
5021 case 0xc2: /* ret im */
5022 val = x86_ldsw_code(env, s);
5023 ot = gen_pop_T0(s);
5024 gen_stack_update(s, val + (1 << ot));
5025 /* Note that gen_pop_T0 uses a zero-extending load. */
5026 gen_op_jmp_v(s, s->T0);
5027 gen_bnd_jmp(s);
5028 s->base.is_jmp = DISAS_JUMP;
5029 break;
5030 case 0xc3: /* ret */
5031 ot = gen_pop_T0(s);
5032 gen_pop_update(s, ot);
5033 /* Note that gen_pop_T0 uses a zero-extending load. */
5034 gen_op_jmp_v(s, s->T0);
5035 gen_bnd_jmp(s);
5036 s->base.is_jmp = DISAS_JUMP;
5037 break;
5038 case 0xca: /* lret im */
5039 val = x86_ldsw_code(env, s);
5040 do_lret:
5041 if (PE(s) && !VM86(s)) {
5042 gen_update_cc_op(s);
5043 gen_update_eip_cur(s);
5044 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
5045 tcg_const_i32(val));
5046 } else {
5047 gen_stack_A0(s);
5048 /* pop offset */
5049 gen_op_ld_v(s, dflag, s->T0, s->A0);
5050 /* NOTE: keeping EIP updated is not a problem in case of
5051 exception */
5052 gen_op_jmp_v(s, s->T0);
5053 /* pop selector */
5054 gen_add_A0_im(s, 1 << dflag);
5055 gen_op_ld_v(s, dflag, s->T0, s->A0);
5056 gen_op_movl_seg_T0_vm(s, R_CS);
5057 /* add stack offset */
5058 gen_stack_update(s, val + (2 << dflag));
5060 s->base.is_jmp = DISAS_EOB_ONLY;
5061 break;
5062 case 0xcb: /* lret */
5063 val = 0;
5064 goto do_lret;
5065 case 0xcf: /* iret */
5066 gen_svm_check_intercept(s, SVM_EXIT_IRET);
5067 if (!PE(s) || VM86(s)) {
5068 /* real mode or vm86 mode */
5069 if (!check_vm86_iopl(s)) {
5070 break;
5072 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
5073 } else {
5074 gen_helper_iret_protected(cpu_env, tcg_constant_i32(dflag - 1),
5075 eip_next_i32(s));
5077 set_cc_op(s, CC_OP_EFLAGS);
5078 s->base.is_jmp = DISAS_EOB_ONLY;
5079 break;
5080 case 0xe8: /* call im */
5082 int diff = (dflag != MO_16
5083 ? (int32_t)insn_get(env, s, MO_32)
5084 : (int16_t)insn_get(env, s, MO_16));
5085 gen_push_v(s, eip_next_tl(s));
5086 gen_bnd_jmp(s);
5087 gen_jmp_rel(s, dflag, diff, 0);
5089 break;
5090 case 0x9a: /* lcall im */
5092 unsigned int selector, offset;
5094 if (CODE64(s))
5095 goto illegal_op;
5096 ot = dflag;
5097 offset = insn_get(env, s, ot);
5098 selector = insn_get(env, s, MO_16);
5100 tcg_gen_movi_tl(s->T0, selector);
5101 tcg_gen_movi_tl(s->T1, offset);
5103 goto do_lcall;
5104 case 0xe9: /* jmp im */
5106 int diff = (dflag != MO_16
5107 ? (int32_t)insn_get(env, s, MO_32)
5108 : (int16_t)insn_get(env, s, MO_16));
5109 gen_bnd_jmp(s);
5110 gen_jmp_rel(s, dflag, diff, 0);
5112 break;
5113 case 0xea: /* ljmp im */
5115 unsigned int selector, offset;
5117 if (CODE64(s))
5118 goto illegal_op;
5119 ot = dflag;
5120 offset = insn_get(env, s, ot);
5121 selector = insn_get(env, s, MO_16);
5123 tcg_gen_movi_tl(s->T0, selector);
5124 tcg_gen_movi_tl(s->T1, offset);
5126 goto do_ljmp;
5127 case 0xeb: /* jmp Jb */
5129 int diff = (int8_t)insn_get(env, s, MO_8);
5130 gen_jmp_rel(s, dflag, diff, 0);
5132 break;
5133 case 0x70 ... 0x7f: /* jcc Jb */
5135 int diff = (int8_t)insn_get(env, s, MO_8);
5136 gen_bnd_jmp(s);
5137 gen_jcc(s, b, diff);
5139 break;
5140 case 0x180 ... 0x18f: /* jcc Jv */
5142 int diff = (dflag != MO_16
5143 ? (int32_t)insn_get(env, s, MO_32)
5144 : (int16_t)insn_get(env, s, MO_16));
5145 gen_bnd_jmp(s);
5146 gen_jcc(s, b, diff);
5148 break;
5150 case 0x190 ... 0x19f: /* setcc Gv */
5151 modrm = x86_ldub_code(env, s);
5152 gen_setcc1(s, b, s->T0);
5153 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
5154 break;
5155 case 0x140 ... 0x14f: /* cmov Gv, Ev */
5156 if (!(s->cpuid_features & CPUID_CMOV)) {
5157 goto illegal_op;
5159 ot = dflag;
5160 modrm = x86_ldub_code(env, s);
5161 reg = ((modrm >> 3) & 7) | REX_R(s);
5162 gen_cmovcc1(env, s, ot, b, modrm, reg);
5163 break;
5165 /************************/
5166 /* flags */
5167 case 0x9c: /* pushf */
5168 gen_svm_check_intercept(s, SVM_EXIT_PUSHF);
5169 if (check_vm86_iopl(s)) {
5170 gen_update_cc_op(s);
5171 gen_helper_read_eflags(s->T0, cpu_env);
5172 gen_push_v(s, s->T0);
5174 break;
5175 case 0x9d: /* popf */
5176 gen_svm_check_intercept(s, SVM_EXIT_POPF);
5177 if (check_vm86_iopl(s)) {
5178 ot = gen_pop_T0(s);
5179 if (CPL(s) == 0) {
5180 if (dflag != MO_16) {
5181 gen_helper_write_eflags(cpu_env, s->T0,
5182 tcg_const_i32((TF_MASK | AC_MASK |
5183 ID_MASK | NT_MASK |
5184 IF_MASK |
5185 IOPL_MASK)));
5186 } else {
5187 gen_helper_write_eflags(cpu_env, s->T0,
5188 tcg_const_i32((TF_MASK | AC_MASK |
5189 ID_MASK | NT_MASK |
5190 IF_MASK | IOPL_MASK)
5191 & 0xffff));
5193 } else {
5194 if (CPL(s) <= IOPL(s)) {
5195 if (dflag != MO_16) {
5196 gen_helper_write_eflags(cpu_env, s->T0,
5197 tcg_const_i32((TF_MASK |
5198 AC_MASK |
5199 ID_MASK |
5200 NT_MASK |
5201 IF_MASK)));
5202 } else {
5203 gen_helper_write_eflags(cpu_env, s->T0,
5204 tcg_const_i32((TF_MASK |
5205 AC_MASK |
5206 ID_MASK |
5207 NT_MASK |
5208 IF_MASK)
5209 & 0xffff));
5211 } else {
5212 if (dflag != MO_16) {
5213 gen_helper_write_eflags(cpu_env, s->T0,
5214 tcg_const_i32((TF_MASK | AC_MASK |
5215 ID_MASK | NT_MASK)));
5216 } else {
5217 gen_helper_write_eflags(cpu_env, s->T0,
5218 tcg_const_i32((TF_MASK | AC_MASK |
5219 ID_MASK | NT_MASK)
5220 & 0xffff));
5224 gen_pop_update(s, ot);
5225 set_cc_op(s, CC_OP_EFLAGS);
5226 /* abort translation because TF/AC flag may change */
5227 s->base.is_jmp = DISAS_EOB_NEXT;
5229 break;
5230 case 0x9e: /* sahf */
5231 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
5232 goto illegal_op;
5233 tcg_gen_shri_tl(s->T0, cpu_regs[R_EAX], 8);
5234 gen_compute_eflags(s);
5235 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
5236 tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
5237 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
5238 break;
5239 case 0x9f: /* lahf */
5240 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
5241 goto illegal_op;
5242 gen_compute_eflags(s);
5243 /* Note: gen_compute_eflags() only gives the condition codes */
5244 tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02);
5245 tcg_gen_deposit_tl(cpu_regs[R_EAX], cpu_regs[R_EAX], s->T0, 8, 8);
5246 break;
5247 case 0xf5: /* cmc */
5248 gen_compute_eflags(s);
5249 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
5250 break;
5251 case 0xf8: /* clc */
5252 gen_compute_eflags(s);
5253 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
5254 break;
5255 case 0xf9: /* stc */
5256 gen_compute_eflags(s);
5257 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
5258 break;
5259 case 0xfc: /* cld */
5260 tcg_gen_movi_i32(s->tmp2_i32, 1);
5261 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
5262 break;
5263 case 0xfd: /* std */
5264 tcg_gen_movi_i32(s->tmp2_i32, -1);
5265 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
5266 break;
5268 /************************/
5269 /* bit operations */
5270 case 0x1ba: /* bt/bts/btr/btc Gv, im */
5271 ot = dflag;
5272 modrm = x86_ldub_code(env, s);
5273 op = (modrm >> 3) & 7;
5274 mod = (modrm >> 6) & 3;
5275 rm = (modrm & 7) | REX_B(s);
5276 if (mod != 3) {
5277 s->rip_offset = 1;
5278 gen_lea_modrm(env, s, modrm);
5279 if (!(s->prefix & PREFIX_LOCK)) {
5280 gen_op_ld_v(s, ot, s->T0, s->A0);
5282 } else {
5283 gen_op_mov_v_reg(s, ot, s->T0, rm);
5285 /* load shift */
5286 val = x86_ldub_code(env, s);
5287 tcg_gen_movi_tl(s->T1, val);
5288 if (op < 4)
5289 goto unknown_op;
5290 op -= 4;
5291 goto bt_op;
5292 case 0x1a3: /* bt Gv, Ev */
5293 op = 0;
5294 goto do_btx;
5295 case 0x1ab: /* bts */
5296 op = 1;
5297 goto do_btx;
5298 case 0x1b3: /* btr */
5299 op = 2;
5300 goto do_btx;
5301 case 0x1bb: /* btc */
5302 op = 3;
5303 do_btx:
5304 ot = dflag;
5305 modrm = x86_ldub_code(env, s);
5306 reg = ((modrm >> 3) & 7) | REX_R(s);
5307 mod = (modrm >> 6) & 3;
5308 rm = (modrm & 7) | REX_B(s);
5309 gen_op_mov_v_reg(s, MO_32, s->T1, reg);
5310 if (mod != 3) {
5311 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5312 /* specific case: we need to add a displacement */
5313 gen_exts(ot, s->T1);
5314 tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
5315 tcg_gen_shli_tl(s->tmp0, s->tmp0, ot);
5316 tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a, false), s->tmp0);
5317 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
5318 if (!(s->prefix & PREFIX_LOCK)) {
5319 gen_op_ld_v(s, ot, s->T0, s->A0);
5321 } else {
5322 gen_op_mov_v_reg(s, ot, s->T0, rm);
5324 bt_op:
5325 tcg_gen_andi_tl(s->T1, s->T1, (1 << (3 + ot)) - 1);
5326 tcg_gen_movi_tl(s->tmp0, 1);
5327 tcg_gen_shl_tl(s->tmp0, s->tmp0, s->T1);
5328 if (s->prefix & PREFIX_LOCK) {
5329 switch (op) {
5330 case 0: /* bt */
5331 /* Needs no atomic ops; we surpressed the normal
5332 memory load for LOCK above so do it now. */
5333 gen_op_ld_v(s, ot, s->T0, s->A0);
5334 break;
5335 case 1: /* bts */
5336 tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, s->tmp0,
5337 s->mem_index, ot | MO_LE);
5338 break;
5339 case 2: /* btr */
5340 tcg_gen_not_tl(s->tmp0, s->tmp0);
5341 tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, s->tmp0,
5342 s->mem_index, ot | MO_LE);
5343 break;
5344 default:
5345 case 3: /* btc */
5346 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0,
5347 s->mem_index, ot | MO_LE);
5348 break;
5350 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
5351 } else {
5352 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
5353 switch (op) {
5354 case 0: /* bt */
5355 /* Data already loaded; nothing to do. */
5356 break;
5357 case 1: /* bts */
5358 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
5359 break;
5360 case 2: /* btr */
5361 tcg_gen_andc_tl(s->T0, s->T0, s->tmp0);
5362 break;
5363 default:
5364 case 3: /* btc */
5365 tcg_gen_xor_tl(s->T0, s->T0, s->tmp0);
5366 break;
5368 if (op != 0) {
5369 if (mod != 3) {
5370 gen_op_st_v(s, ot, s->T0, s->A0);
5371 } else {
5372 gen_op_mov_reg_v(s, ot, rm, s->T0);
5377 /* Delay all CC updates until after the store above. Note that
5378 C is the result of the test, Z is unchanged, and the others
5379 are all undefined. */
5380 switch (s->cc_op) {
5381 case CC_OP_MULB ... CC_OP_MULQ:
5382 case CC_OP_ADDB ... CC_OP_ADDQ:
5383 case CC_OP_ADCB ... CC_OP_ADCQ:
5384 case CC_OP_SUBB ... CC_OP_SUBQ:
5385 case CC_OP_SBBB ... CC_OP_SBBQ:
5386 case CC_OP_LOGICB ... CC_OP_LOGICQ:
5387 case CC_OP_INCB ... CC_OP_INCQ:
5388 case CC_OP_DECB ... CC_OP_DECQ:
5389 case CC_OP_SHLB ... CC_OP_SHLQ:
5390 case CC_OP_SARB ... CC_OP_SARQ:
5391 case CC_OP_BMILGB ... CC_OP_BMILGQ:
5392 /* Z was going to be computed from the non-zero status of CC_DST.
5393 We can get that same Z value (and the new C value) by leaving
5394 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
5395 same width. */
5396 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
5397 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
5398 break;
5399 default:
5400 /* Otherwise, generate EFLAGS and replace the C bit. */
5401 gen_compute_eflags(s);
5402 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, s->tmp4,
5403 ctz32(CC_C), 1);
5404 break;
5406 break;
5407 case 0x1bc: /* bsf / tzcnt */
5408 case 0x1bd: /* bsr / lzcnt */
5409 ot = dflag;
5410 modrm = x86_ldub_code(env, s);
5411 reg = ((modrm >> 3) & 7) | REX_R(s);
5412 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5413 gen_extu(ot, s->T0);
5415 /* Note that lzcnt and tzcnt are in different extensions. */
5416 if ((prefixes & PREFIX_REPZ)
5417 && (b & 1
5418 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
5419 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
5420 int size = 8 << ot;
5421 /* For lzcnt/tzcnt, C bit is defined related to the input. */
5422 tcg_gen_mov_tl(cpu_cc_src, s->T0);
5423 if (b & 1) {
5424 /* For lzcnt, reduce the target_ulong result by the
5425 number of zeros that we expect to find at the top. */
5426 tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
5427 tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
5428 } else {
5429 /* For tzcnt, a zero input must return the operand size. */
5430 tcg_gen_ctzi_tl(s->T0, s->T0, size);
5432 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
5433 gen_op_update1_cc(s);
5434 set_cc_op(s, CC_OP_BMILGB + ot);
5435 } else {
5436 /* For bsr/bsf, only the Z bit is defined and it is related
5437 to the input and not the result. */
5438 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5439 set_cc_op(s, CC_OP_LOGICB + ot);
5441 /* ??? The manual says that the output is undefined when the
5442 input is zero, but real hardware leaves it unchanged, and
5443 real programs appear to depend on that. Accomplish this
5444 by passing the output as the value to return upon zero. */
5445 if (b & 1) {
5446 /* For bsr, return the bit index of the first 1 bit,
5447 not the count of leading zeros. */
5448 tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
5449 tcg_gen_clz_tl(s->T0, s->T0, s->T1);
5450 tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
5451 } else {
5452 tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
5455 gen_op_mov_reg_v(s, ot, reg, s->T0);
5456 break;
5457 /************************/
5458 /* bcd */
5459 case 0x27: /* daa */
5460 if (CODE64(s))
5461 goto illegal_op;
5462 gen_update_cc_op(s);
5463 gen_helper_daa(cpu_env);
5464 set_cc_op(s, CC_OP_EFLAGS);
5465 break;
5466 case 0x2f: /* das */
5467 if (CODE64(s))
5468 goto illegal_op;
5469 gen_update_cc_op(s);
5470 gen_helper_das(cpu_env);
5471 set_cc_op(s, CC_OP_EFLAGS);
5472 break;
5473 case 0x37: /* aaa */
5474 if (CODE64(s))
5475 goto illegal_op;
5476 gen_update_cc_op(s);
5477 gen_helper_aaa(cpu_env);
5478 set_cc_op(s, CC_OP_EFLAGS);
5479 break;
5480 case 0x3f: /* aas */
5481 if (CODE64(s))
5482 goto illegal_op;
5483 gen_update_cc_op(s);
5484 gen_helper_aas(cpu_env);
5485 set_cc_op(s, CC_OP_EFLAGS);
5486 break;
5487 case 0xd4: /* aam */
5488 if (CODE64(s))
5489 goto illegal_op;
5490 val = x86_ldub_code(env, s);
5491 if (val == 0) {
5492 gen_exception(s, EXCP00_DIVZ);
5493 } else {
5494 gen_helper_aam(cpu_env, tcg_const_i32(val));
5495 set_cc_op(s, CC_OP_LOGICB);
5497 break;
5498 case 0xd5: /* aad */
5499 if (CODE64(s))
5500 goto illegal_op;
5501 val = x86_ldub_code(env, s);
5502 gen_helper_aad(cpu_env, tcg_const_i32(val));
5503 set_cc_op(s, CC_OP_LOGICB);
5504 break;
5505 /************************/
5506 /* misc */
5507 case 0x90: /* nop */
5508 /* XXX: correct lock test for all insn */
5509 if (prefixes & PREFIX_LOCK) {
5510 goto illegal_op;
5512 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
5513 if (REX_B(s)) {
5514 goto do_xchg_reg_eax;
5516 if (prefixes & PREFIX_REPZ) {
5517 gen_update_cc_op(s);
5518 gen_update_eip_cur(s);
5519 gen_helper_pause(cpu_env, cur_insn_len_i32(s));
5520 s->base.is_jmp = DISAS_NORETURN;
5522 break;
5523 case 0x9b: /* fwait */
5524 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
5525 (HF_MP_MASK | HF_TS_MASK)) {
5526 gen_exception(s, EXCP07_PREX);
5527 } else {
5528 gen_helper_fwait(cpu_env);
5530 break;
5531 case 0xcc: /* int3 */
5532 gen_interrupt(s, EXCP03_INT3);
5533 break;
5534 case 0xcd: /* int N */
5535 val = x86_ldub_code(env, s);
5536 if (check_vm86_iopl(s)) {
5537 gen_interrupt(s, val);
5539 break;
5540 case 0xce: /* into */
5541 if (CODE64(s))
5542 goto illegal_op;
5543 gen_update_cc_op(s);
5544 gen_update_eip_cur(s);
5545 gen_helper_into(cpu_env, cur_insn_len_i32(s));
5546 break;
5547 #ifdef WANT_ICEBP
5548 case 0xf1: /* icebp (undocumented, exits to external debugger) */
5549 gen_svm_check_intercept(s, SVM_EXIT_ICEBP);
5550 gen_debug(s);
5551 break;
5552 #endif
5553 case 0xfa: /* cli */
5554 if (check_iopl(s)) {
5555 gen_reset_eflags(s, IF_MASK);
5557 break;
5558 case 0xfb: /* sti */
5559 if (check_iopl(s)) {
5560 gen_set_eflags(s, IF_MASK);
5561 /* interruptions are enabled only the first insn after sti */
5562 gen_update_eip_next(s);
5563 gen_eob_inhibit_irq(s, true);
5565 break;
5566 case 0x62: /* bound */
5567 if (CODE64(s))
5568 goto illegal_op;
5569 ot = dflag;
5570 modrm = x86_ldub_code(env, s);
5571 reg = (modrm >> 3) & 7;
5572 mod = (modrm >> 6) & 3;
5573 if (mod == 3)
5574 goto illegal_op;
5575 gen_op_mov_v_reg(s, ot, s->T0, reg);
5576 gen_lea_modrm(env, s, modrm);
5577 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5578 if (ot == MO_16) {
5579 gen_helper_boundw(cpu_env, s->A0, s->tmp2_i32);
5580 } else {
5581 gen_helper_boundl(cpu_env, s->A0, s->tmp2_i32);
5583 break;
5584 case 0x1c8 ... 0x1cf: /* bswap reg */
5585 reg = (b & 7) | REX_B(s);
5586 #ifdef TARGET_X86_64
5587 if (dflag == MO_64) {
5588 tcg_gen_bswap64_i64(cpu_regs[reg], cpu_regs[reg]);
5589 break;
5591 #endif
5592 tcg_gen_bswap32_tl(cpu_regs[reg], cpu_regs[reg], TCG_BSWAP_OZ);
5593 break;
5594 case 0xd6: /* salc */
5595 if (CODE64(s))
5596 goto illegal_op;
5597 gen_compute_eflags_c(s, s->T0);
5598 tcg_gen_neg_tl(s->T0, s->T0);
5599 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
5600 break;
5601 case 0xe0: /* loopnz */
5602 case 0xe1: /* loopz */
5603 case 0xe2: /* loop */
5604 case 0xe3: /* jecxz */
5606 TCGLabel *l1, *l2;
5607 int diff = (int8_t)insn_get(env, s, MO_8);
5609 l1 = gen_new_label();
5610 l2 = gen_new_label();
5611 gen_update_cc_op(s);
5612 b &= 3;
5613 switch(b) {
5614 case 0: /* loopnz */
5615 case 1: /* loopz */
5616 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
5617 gen_op_jz_ecx(s, l2);
5618 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
5619 break;
5620 case 2: /* loop */
5621 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
5622 gen_op_jnz_ecx(s, l1);
5623 break;
5624 default:
5625 case 3: /* jcxz */
5626 gen_op_jz_ecx(s, l1);
5627 break;
5630 gen_set_label(l2);
5631 gen_jmp_rel_csize(s, 0, 1);
5633 gen_set_label(l1);
5634 gen_jmp_rel(s, dflag, diff, 0);
5636 break;
5637 case 0x130: /* wrmsr */
5638 case 0x132: /* rdmsr */
5639 if (check_cpl0(s)) {
5640 gen_update_cc_op(s);
5641 gen_update_eip_cur(s);
5642 if (b & 2) {
5643 gen_helper_rdmsr(cpu_env);
5644 } else {
5645 gen_helper_wrmsr(cpu_env);
5646 s->base.is_jmp = DISAS_EOB_NEXT;
5649 break;
5650 case 0x131: /* rdtsc */
5651 gen_update_cc_op(s);
5652 gen_update_eip_cur(s);
5653 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5654 gen_io_start();
5655 s->base.is_jmp = DISAS_TOO_MANY;
5657 gen_helper_rdtsc(cpu_env);
5658 break;
5659 case 0x133: /* rdpmc */
5660 gen_update_cc_op(s);
5661 gen_update_eip_cur(s);
5662 gen_helper_rdpmc(cpu_env);
5663 s->base.is_jmp = DISAS_NORETURN;
5664 break;
5665 case 0x134: /* sysenter */
5666 /* For Intel SYSENTER is valid on 64-bit */
5667 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
5668 goto illegal_op;
5669 if (!PE(s)) {
5670 gen_exception_gpf(s);
5671 } else {
5672 gen_helper_sysenter(cpu_env);
5673 s->base.is_jmp = DISAS_EOB_ONLY;
5675 break;
5676 case 0x135: /* sysexit */
5677 /* For Intel SYSEXIT is valid on 64-bit */
5678 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
5679 goto illegal_op;
5680 if (!PE(s)) {
5681 gen_exception_gpf(s);
5682 } else {
5683 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
5684 s->base.is_jmp = DISAS_EOB_ONLY;
5686 break;
5687 #ifdef TARGET_X86_64
5688 case 0x105: /* syscall */
5689 /* XXX: is it usable in real mode ? */
5690 gen_update_cc_op(s);
5691 gen_update_eip_cur(s);
5692 gen_helper_syscall(cpu_env, cur_insn_len_i32(s));
5693 /* TF handling for the syscall insn is different. The TF bit is checked
5694 after the syscall insn completes. This allows #DB to not be
5695 generated after one has entered CPL0 if TF is set in FMASK. */
5696 gen_eob_worker(s, false, true);
5697 break;
5698 case 0x107: /* sysret */
5699 if (!PE(s)) {
5700 gen_exception_gpf(s);
5701 } else {
5702 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
5703 /* condition codes are modified only in long mode */
5704 if (LMA(s)) {
5705 set_cc_op(s, CC_OP_EFLAGS);
5707 /* TF handling for the sysret insn is different. The TF bit is
5708 checked after the sysret insn completes. This allows #DB to be
5709 generated "as if" the syscall insn in userspace has just
5710 completed. */
5711 gen_eob_worker(s, false, true);
5713 break;
5714 #endif
5715 case 0x1a2: /* cpuid */
5716 gen_update_cc_op(s);
5717 gen_update_eip_cur(s);
5718 gen_helper_cpuid(cpu_env);
5719 break;
5720 case 0xf4: /* hlt */
5721 if (check_cpl0(s)) {
5722 gen_update_cc_op(s);
5723 gen_update_eip_cur(s);
5724 gen_helper_hlt(cpu_env, cur_insn_len_i32(s));
5725 s->base.is_jmp = DISAS_NORETURN;
5727 break;
5728 case 0x100:
5729 modrm = x86_ldub_code(env, s);
5730 mod = (modrm >> 6) & 3;
5731 op = (modrm >> 3) & 7;
5732 switch(op) {
5733 case 0: /* sldt */
5734 if (!PE(s) || VM86(s))
5735 goto illegal_op;
5736 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
5737 break;
5739 gen_svm_check_intercept(s, SVM_EXIT_LDTR_READ);
5740 tcg_gen_ld32u_tl(s->T0, cpu_env,
5741 offsetof(CPUX86State, ldt.selector));
5742 ot = mod == 3 ? dflag : MO_16;
5743 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5744 break;
5745 case 2: /* lldt */
5746 if (!PE(s) || VM86(s))
5747 goto illegal_op;
5748 if (check_cpl0(s)) {
5749 gen_svm_check_intercept(s, SVM_EXIT_LDTR_WRITE);
5750 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5751 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5752 gen_helper_lldt(cpu_env, s->tmp2_i32);
5754 break;
5755 case 1: /* str */
5756 if (!PE(s) || VM86(s))
5757 goto illegal_op;
5758 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
5759 break;
5761 gen_svm_check_intercept(s, SVM_EXIT_TR_READ);
5762 tcg_gen_ld32u_tl(s->T0, cpu_env,
5763 offsetof(CPUX86State, tr.selector));
5764 ot = mod == 3 ? dflag : MO_16;
5765 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5766 break;
5767 case 3: /* ltr */
5768 if (!PE(s) || VM86(s))
5769 goto illegal_op;
5770 if (check_cpl0(s)) {
5771 gen_svm_check_intercept(s, SVM_EXIT_TR_WRITE);
5772 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5773 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5774 gen_helper_ltr(cpu_env, s->tmp2_i32);
5776 break;
5777 case 4: /* verr */
5778 case 5: /* verw */
5779 if (!PE(s) || VM86(s))
5780 goto illegal_op;
5781 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5782 gen_update_cc_op(s);
5783 if (op == 4) {
5784 gen_helper_verr(cpu_env, s->T0);
5785 } else {
5786 gen_helper_verw(cpu_env, s->T0);
5788 set_cc_op(s, CC_OP_EFLAGS);
5789 break;
5790 default:
5791 goto unknown_op;
5793 break;
5795 case 0x101:
5796 modrm = x86_ldub_code(env, s);
5797 switch (modrm) {
5798 CASE_MODRM_MEM_OP(0): /* sgdt */
5799 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
5800 break;
5802 gen_svm_check_intercept(s, SVM_EXIT_GDTR_READ);
5803 gen_lea_modrm(env, s, modrm);
5804 tcg_gen_ld32u_tl(s->T0,
5805 cpu_env, offsetof(CPUX86State, gdt.limit));
5806 gen_op_st_v(s, MO_16, s->T0, s->A0);
5807 gen_add_A0_im(s, 2);
5808 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
5809 if (dflag == MO_16) {
5810 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
5812 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
5813 break;
5815 case 0xc8: /* monitor */
5816 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
5817 goto illegal_op;
5819 gen_update_cc_op(s);
5820 gen_update_eip_cur(s);
5821 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
5822 gen_extu(s->aflag, s->A0);
5823 gen_add_A0_ds_seg(s);
5824 gen_helper_monitor(cpu_env, s->A0);
5825 break;
5827 case 0xc9: /* mwait */
5828 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
5829 goto illegal_op;
5831 gen_update_cc_op(s);
5832 gen_update_eip_cur(s);
5833 gen_helper_mwait(cpu_env, cur_insn_len_i32(s));
5834 s->base.is_jmp = DISAS_NORETURN;
5835 break;
5837 case 0xca: /* clac */
5838 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
5839 || CPL(s) != 0) {
5840 goto illegal_op;
5842 gen_reset_eflags(s, AC_MASK);
5843 s->base.is_jmp = DISAS_EOB_NEXT;
5844 break;
5846 case 0xcb: /* stac */
5847 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
5848 || CPL(s) != 0) {
5849 goto illegal_op;
5851 gen_set_eflags(s, AC_MASK);
5852 s->base.is_jmp = DISAS_EOB_NEXT;
5853 break;
5855 CASE_MODRM_MEM_OP(1): /* sidt */
5856 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
5857 break;
5859 gen_svm_check_intercept(s, SVM_EXIT_IDTR_READ);
5860 gen_lea_modrm(env, s, modrm);
5861 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit));
5862 gen_op_st_v(s, MO_16, s->T0, s->A0);
5863 gen_add_A0_im(s, 2);
5864 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
5865 if (dflag == MO_16) {
5866 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
5868 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
5869 break;
5871 case 0xd0: /* xgetbv */
5872 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
5873 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
5874 | PREFIX_REPZ | PREFIX_REPNZ))) {
5875 goto illegal_op;
5877 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
5878 gen_helper_xgetbv(s->tmp1_i64, cpu_env, s->tmp2_i32);
5879 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
5880 break;
5882 case 0xd1: /* xsetbv */
5883 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
5884 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
5885 | PREFIX_REPZ | PREFIX_REPNZ))) {
5886 goto illegal_op;
5888 if (!check_cpl0(s)) {
5889 break;
5891 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
5892 cpu_regs[R_EDX]);
5893 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
5894 gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
5895 /* End TB because translation flags may change. */
5896 s->base.is_jmp = DISAS_EOB_NEXT;
5897 break;
5899 case 0xd8: /* VMRUN */
5900 if (!SVME(s) || !PE(s)) {
5901 goto illegal_op;
5903 if (!check_cpl0(s)) {
5904 break;
5906 gen_update_cc_op(s);
5907 gen_update_eip_cur(s);
5908 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
5909 cur_insn_len_i32(s));
5910 tcg_gen_exit_tb(NULL, 0);
5911 s->base.is_jmp = DISAS_NORETURN;
5912 break;
5914 case 0xd9: /* VMMCALL */
5915 if (!SVME(s)) {
5916 goto illegal_op;
5918 gen_update_cc_op(s);
5919 gen_update_eip_cur(s);
5920 gen_helper_vmmcall(cpu_env);
5921 break;
5923 case 0xda: /* VMLOAD */
5924 if (!SVME(s) || !PE(s)) {
5925 goto illegal_op;
5927 if (!check_cpl0(s)) {
5928 break;
5930 gen_update_cc_op(s);
5931 gen_update_eip_cur(s);
5932 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
5933 break;
5935 case 0xdb: /* VMSAVE */
5936 if (!SVME(s) || !PE(s)) {
5937 goto illegal_op;
5939 if (!check_cpl0(s)) {
5940 break;
5942 gen_update_cc_op(s);
5943 gen_update_eip_cur(s);
5944 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
5945 break;
5947 case 0xdc: /* STGI */
5948 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
5949 || !PE(s)) {
5950 goto illegal_op;
5952 if (!check_cpl0(s)) {
5953 break;
5955 gen_update_cc_op(s);
5956 gen_helper_stgi(cpu_env);
5957 s->base.is_jmp = DISAS_EOB_NEXT;
5958 break;
5960 case 0xdd: /* CLGI */
5961 if (!SVME(s) || !PE(s)) {
5962 goto illegal_op;
5964 if (!check_cpl0(s)) {
5965 break;
5967 gen_update_cc_op(s);
5968 gen_update_eip_cur(s);
5969 gen_helper_clgi(cpu_env);
5970 break;
5972 case 0xde: /* SKINIT */
5973 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
5974 || !PE(s)) {
5975 goto illegal_op;
5977 gen_svm_check_intercept(s, SVM_EXIT_SKINIT);
5978 /* If not intercepted, not implemented -- raise #UD. */
5979 goto illegal_op;
5981 case 0xdf: /* INVLPGA */
5982 if (!SVME(s) || !PE(s)) {
5983 goto illegal_op;
5985 if (!check_cpl0(s)) {
5986 break;
5988 gen_svm_check_intercept(s, SVM_EXIT_INVLPGA);
5989 if (s->aflag == MO_64) {
5990 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
5991 } else {
5992 tcg_gen_ext32u_tl(s->A0, cpu_regs[R_EAX]);
5994 gen_helper_flush_page(cpu_env, s->A0);
5995 s->base.is_jmp = DISAS_EOB_NEXT;
5996 break;
5998 CASE_MODRM_MEM_OP(2): /* lgdt */
5999 if (!check_cpl0(s)) {
6000 break;
6002 gen_svm_check_intercept(s, SVM_EXIT_GDTR_WRITE);
6003 gen_lea_modrm(env, s, modrm);
6004 gen_op_ld_v(s, MO_16, s->T1, s->A0);
6005 gen_add_A0_im(s, 2);
6006 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
6007 if (dflag == MO_16) {
6008 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
6010 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
6011 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, gdt.limit));
6012 break;
6014 CASE_MODRM_MEM_OP(3): /* lidt */
6015 if (!check_cpl0(s)) {
6016 break;
6018 gen_svm_check_intercept(s, SVM_EXIT_IDTR_WRITE);
6019 gen_lea_modrm(env, s, modrm);
6020 gen_op_ld_v(s, MO_16, s->T1, s->A0);
6021 gen_add_A0_im(s, 2);
6022 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
6023 if (dflag == MO_16) {
6024 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
6026 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
6027 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, idt.limit));
6028 break;
6030 CASE_MODRM_OP(4): /* smsw */
6031 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
6032 break;
6034 gen_svm_check_intercept(s, SVM_EXIT_READ_CR0);
6035 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
6037 * In 32-bit mode, the higher 16 bits of the destination
6038 * register are undefined. In practice CR0[31:0] is stored
6039 * just like in 64-bit mode.
6041 mod = (modrm >> 6) & 3;
6042 ot = (mod != 3 ? MO_16 : s->dflag);
6043 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
6044 break;
6045 case 0xee: /* rdpkru */
6046 if (prefixes & PREFIX_LOCK) {
6047 goto illegal_op;
6049 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
6050 gen_helper_rdpkru(s->tmp1_i64, cpu_env, s->tmp2_i32);
6051 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
6052 break;
6053 case 0xef: /* wrpkru */
6054 if (prefixes & PREFIX_LOCK) {
6055 goto illegal_op;
6057 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
6058 cpu_regs[R_EDX]);
6059 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
6060 gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64);
6061 break;
6063 CASE_MODRM_OP(6): /* lmsw */
6064 if (!check_cpl0(s)) {
6065 break;
6067 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
6068 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
6070 * Only the 4 lower bits of CR0 are modified.
6071 * PE cannot be set to zero if already set to one.
6073 tcg_gen_ld_tl(s->T1, cpu_env, offsetof(CPUX86State, cr[0]));
6074 tcg_gen_andi_tl(s->T0, s->T0, 0xf);
6075 tcg_gen_andi_tl(s->T1, s->T1, ~0xe);
6076 tcg_gen_or_tl(s->T0, s->T0, s->T1);
6077 gen_helper_write_crN(cpu_env, tcg_constant_i32(0), s->T0);
6078 s->base.is_jmp = DISAS_EOB_NEXT;
6079 break;
6081 CASE_MODRM_MEM_OP(7): /* invlpg */
6082 if (!check_cpl0(s)) {
6083 break;
6085 gen_svm_check_intercept(s, SVM_EXIT_INVLPG);
6086 gen_lea_modrm(env, s, modrm);
6087 gen_helper_flush_page(cpu_env, s->A0);
6088 s->base.is_jmp = DISAS_EOB_NEXT;
6089 break;
6091 case 0xf8: /* swapgs */
6092 #ifdef TARGET_X86_64
6093 if (CODE64(s)) {
6094 if (check_cpl0(s)) {
6095 tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]);
6096 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
6097 offsetof(CPUX86State, kernelgsbase));
6098 tcg_gen_st_tl(s->T0, cpu_env,
6099 offsetof(CPUX86State, kernelgsbase));
6101 break;
6103 #endif
6104 goto illegal_op;
6106 case 0xf9: /* rdtscp */
6107 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
6108 goto illegal_op;
6110 gen_update_cc_op(s);
6111 gen_update_eip_cur(s);
6112 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6113 gen_io_start();
6114 s->base.is_jmp = DISAS_TOO_MANY;
6116 gen_helper_rdtscp(cpu_env);
6117 break;
6119 default:
6120 goto unknown_op;
6122 break;
6124 case 0x108: /* invd */
6125 case 0x109: /* wbinvd */
6126 if (check_cpl0(s)) {
6127 gen_svm_check_intercept(s, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
6128 /* nothing to do */
6130 break;
6131 case 0x63: /* arpl or movslS (x86_64) */
6132 #ifdef TARGET_X86_64
6133 if (CODE64(s)) {
6134 int d_ot;
6135 /* d_ot is the size of destination */
6136 d_ot = dflag;
6138 modrm = x86_ldub_code(env, s);
6139 reg = ((modrm >> 3) & 7) | REX_R(s);
6140 mod = (modrm >> 6) & 3;
6141 rm = (modrm & 7) | REX_B(s);
6143 if (mod == 3) {
6144 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
6145 /* sign extend */
6146 if (d_ot == MO_64) {
6147 tcg_gen_ext32s_tl(s->T0, s->T0);
6149 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
6150 } else {
6151 gen_lea_modrm(env, s, modrm);
6152 gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0);
6153 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
6155 } else
6156 #endif
6158 TCGLabel *label1;
6159 TCGv t0, t1, t2, a0;
6161 if (!PE(s) || VM86(s))
6162 goto illegal_op;
6163 t0 = tcg_temp_local_new();
6164 t1 = tcg_temp_local_new();
6165 t2 = tcg_temp_local_new();
6166 ot = MO_16;
6167 modrm = x86_ldub_code(env, s);
6168 reg = (modrm >> 3) & 7;
6169 mod = (modrm >> 6) & 3;
6170 rm = modrm & 7;
6171 if (mod != 3) {
6172 gen_lea_modrm(env, s, modrm);
6173 gen_op_ld_v(s, ot, t0, s->A0);
6174 a0 = tcg_temp_local_new();
6175 tcg_gen_mov_tl(a0, s->A0);
6176 } else {
6177 gen_op_mov_v_reg(s, ot, t0, rm);
6178 a0 = NULL;
6180 gen_op_mov_v_reg(s, ot, t1, reg);
6181 tcg_gen_andi_tl(s->tmp0, t0, 3);
6182 tcg_gen_andi_tl(t1, t1, 3);
6183 tcg_gen_movi_tl(t2, 0);
6184 label1 = gen_new_label();
6185 tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1);
6186 tcg_gen_andi_tl(t0, t0, ~3);
6187 tcg_gen_or_tl(t0, t0, t1);
6188 tcg_gen_movi_tl(t2, CC_Z);
6189 gen_set_label(label1);
6190 if (mod != 3) {
6191 gen_op_st_v(s, ot, t0, a0);
6192 tcg_temp_free(a0);
6193 } else {
6194 gen_op_mov_reg_v(s, ot, rm, t0);
6196 gen_compute_eflags(s);
6197 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
6198 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
6199 tcg_temp_free(t0);
6200 tcg_temp_free(t1);
6201 tcg_temp_free(t2);
6203 break;
6204 case 0x102: /* lar */
6205 case 0x103: /* lsl */
6207 TCGLabel *label1;
6208 TCGv t0;
6209 if (!PE(s) || VM86(s))
6210 goto illegal_op;
6211 ot = dflag != MO_16 ? MO_32 : MO_16;
6212 modrm = x86_ldub_code(env, s);
6213 reg = ((modrm >> 3) & 7) | REX_R(s);
6214 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
6215 t0 = tcg_temp_local_new();
6216 gen_update_cc_op(s);
6217 if (b == 0x102) {
6218 gen_helper_lar(t0, cpu_env, s->T0);
6219 } else {
6220 gen_helper_lsl(t0, cpu_env, s->T0);
6222 tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z);
6223 label1 = gen_new_label();
6224 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
6225 gen_op_mov_reg_v(s, ot, reg, t0);
6226 gen_set_label(label1);
6227 set_cc_op(s, CC_OP_EFLAGS);
6228 tcg_temp_free(t0);
6230 break;
6231 case 0x118:
6232 modrm = x86_ldub_code(env, s);
6233 mod = (modrm >> 6) & 3;
6234 op = (modrm >> 3) & 7;
6235 switch(op) {
6236 case 0: /* prefetchnta */
6237 case 1: /* prefetchnt0 */
6238 case 2: /* prefetchnt0 */
6239 case 3: /* prefetchnt0 */
6240 if (mod == 3)
6241 goto illegal_op;
6242 gen_nop_modrm(env, s, modrm);
6243 /* nothing more to do */
6244 break;
6245 default: /* nop (multi byte) */
6246 gen_nop_modrm(env, s, modrm);
6247 break;
6249 break;
6250 case 0x11a:
6251 modrm = x86_ldub_code(env, s);
6252 if (s->flags & HF_MPX_EN_MASK) {
6253 mod = (modrm >> 6) & 3;
6254 reg = ((modrm >> 3) & 7) | REX_R(s);
6255 if (prefixes & PREFIX_REPZ) {
6256 /* bndcl */
6257 if (reg >= 4
6258 || (prefixes & PREFIX_LOCK)
6259 || s->aflag == MO_16) {
6260 goto illegal_op;
6262 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
6263 } else if (prefixes & PREFIX_REPNZ) {
6264 /* bndcu */
6265 if (reg >= 4
6266 || (prefixes & PREFIX_LOCK)
6267 || s->aflag == MO_16) {
6268 goto illegal_op;
6270 TCGv_i64 notu = tcg_temp_new_i64();
6271 tcg_gen_not_i64(notu, cpu_bndu[reg]);
6272 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
6273 tcg_temp_free_i64(notu);
6274 } else if (prefixes & PREFIX_DATA) {
6275 /* bndmov -- from reg/mem */
6276 if (reg >= 4 || s->aflag == MO_16) {
6277 goto illegal_op;
6279 if (mod == 3) {
6280 int reg2 = (modrm & 7) | REX_B(s);
6281 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
6282 goto illegal_op;
6284 if (s->flags & HF_MPX_IU_MASK) {
6285 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
6286 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
6288 } else {
6289 gen_lea_modrm(env, s, modrm);
6290 if (CODE64(s)) {
6291 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
6292 s->mem_index, MO_LEUQ);
6293 tcg_gen_addi_tl(s->A0, s->A0, 8);
6294 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
6295 s->mem_index, MO_LEUQ);
6296 } else {
6297 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
6298 s->mem_index, MO_LEUL);
6299 tcg_gen_addi_tl(s->A0, s->A0, 4);
6300 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
6301 s->mem_index, MO_LEUL);
6303 /* bnd registers are now in-use */
6304 gen_set_hflag(s, HF_MPX_IU_MASK);
6306 } else if (mod != 3) {
6307 /* bndldx */
6308 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6309 if (reg >= 4
6310 || (prefixes & PREFIX_LOCK)
6311 || s->aflag == MO_16
6312 || a.base < -1) {
6313 goto illegal_op;
6315 if (a.base >= 0) {
6316 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
6317 } else {
6318 tcg_gen_movi_tl(s->A0, 0);
6320 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
6321 if (a.index >= 0) {
6322 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
6323 } else {
6324 tcg_gen_movi_tl(s->T0, 0);
6326 if (CODE64(s)) {
6327 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0);
6328 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
6329 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
6330 } else {
6331 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0);
6332 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
6333 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
6335 gen_set_hflag(s, HF_MPX_IU_MASK);
6338 gen_nop_modrm(env, s, modrm);
6339 break;
6340 case 0x11b:
6341 modrm = x86_ldub_code(env, s);
6342 if (s->flags & HF_MPX_EN_MASK) {
6343 mod = (modrm >> 6) & 3;
6344 reg = ((modrm >> 3) & 7) | REX_R(s);
6345 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
6346 /* bndmk */
6347 if (reg >= 4
6348 || (prefixes & PREFIX_LOCK)
6349 || s->aflag == MO_16) {
6350 goto illegal_op;
6352 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6353 if (a.base >= 0) {
6354 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
6355 if (!CODE64(s)) {
6356 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
6358 } else if (a.base == -1) {
6359 /* no base register has lower bound of 0 */
6360 tcg_gen_movi_i64(cpu_bndl[reg], 0);
6361 } else {
6362 /* rip-relative generates #ud */
6363 goto illegal_op;
6365 tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a, false));
6366 if (!CODE64(s)) {
6367 tcg_gen_ext32u_tl(s->A0, s->A0);
6369 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
6370 /* bnd registers are now in-use */
6371 gen_set_hflag(s, HF_MPX_IU_MASK);
6372 break;
6373 } else if (prefixes & PREFIX_REPNZ) {
6374 /* bndcn */
6375 if (reg >= 4
6376 || (prefixes & PREFIX_LOCK)
6377 || s->aflag == MO_16) {
6378 goto illegal_op;
6380 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
6381 } else if (prefixes & PREFIX_DATA) {
6382 /* bndmov -- to reg/mem */
6383 if (reg >= 4 || s->aflag == MO_16) {
6384 goto illegal_op;
6386 if (mod == 3) {
6387 int reg2 = (modrm & 7) | REX_B(s);
6388 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
6389 goto illegal_op;
6391 if (s->flags & HF_MPX_IU_MASK) {
6392 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
6393 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
6395 } else {
6396 gen_lea_modrm(env, s, modrm);
6397 if (CODE64(s)) {
6398 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
6399 s->mem_index, MO_LEUQ);
6400 tcg_gen_addi_tl(s->A0, s->A0, 8);
6401 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
6402 s->mem_index, MO_LEUQ);
6403 } else {
6404 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
6405 s->mem_index, MO_LEUL);
6406 tcg_gen_addi_tl(s->A0, s->A0, 4);
6407 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
6408 s->mem_index, MO_LEUL);
6411 } else if (mod != 3) {
6412 /* bndstx */
6413 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6414 if (reg >= 4
6415 || (prefixes & PREFIX_LOCK)
6416 || s->aflag == MO_16
6417 || a.base < -1) {
6418 goto illegal_op;
6420 if (a.base >= 0) {
6421 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
6422 } else {
6423 tcg_gen_movi_tl(s->A0, 0);
6425 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
6426 if (a.index >= 0) {
6427 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
6428 } else {
6429 tcg_gen_movi_tl(s->T0, 0);
6431 if (CODE64(s)) {
6432 gen_helper_bndstx64(cpu_env, s->A0, s->T0,
6433 cpu_bndl[reg], cpu_bndu[reg]);
6434 } else {
6435 gen_helper_bndstx32(cpu_env, s->A0, s->T0,
6436 cpu_bndl[reg], cpu_bndu[reg]);
6440 gen_nop_modrm(env, s, modrm);
6441 break;
6442 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
6443 modrm = x86_ldub_code(env, s);
6444 gen_nop_modrm(env, s, modrm);
6445 break;
6447 case 0x120: /* mov reg, crN */
6448 case 0x122: /* mov crN, reg */
6449 if (!check_cpl0(s)) {
6450 break;
6452 modrm = x86_ldub_code(env, s);
6454 * Ignore the mod bits (assume (modrm&0xc0)==0xc0).
6455 * AMD documentation (24594.pdf) and testing of Intel 386 and 486
6456 * processors all show that the mod bits are assumed to be 1's,
6457 * regardless of actual values.
6459 rm = (modrm & 7) | REX_B(s);
6460 reg = ((modrm >> 3) & 7) | REX_R(s);
6461 switch (reg) {
6462 case 0:
6463 if ((prefixes & PREFIX_LOCK) &&
6464 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
6465 reg = 8;
6467 break;
6468 case 2:
6469 case 3:
6470 case 4:
6471 case 8:
6472 break;
6473 default:
6474 goto unknown_op;
6476 ot = (CODE64(s) ? MO_64 : MO_32);
6478 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6479 gen_io_start();
6480 s->base.is_jmp = DISAS_TOO_MANY;
6482 if (b & 2) {
6483 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
6484 gen_op_mov_v_reg(s, ot, s->T0, rm);
6485 gen_helper_write_crN(cpu_env, tcg_constant_i32(reg), s->T0);
6486 s->base.is_jmp = DISAS_EOB_NEXT;
6487 } else {
6488 gen_svm_check_intercept(s, SVM_EXIT_READ_CR0 + reg);
6489 gen_helper_read_crN(s->T0, cpu_env, tcg_constant_i32(reg));
6490 gen_op_mov_reg_v(s, ot, rm, s->T0);
6492 break;
6494 case 0x121: /* mov reg, drN */
6495 case 0x123: /* mov drN, reg */
6496 if (check_cpl0(s)) {
6497 modrm = x86_ldub_code(env, s);
6498 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
6499 * AMD documentation (24594.pdf) and testing of
6500 * intel 386 and 486 processors all show that the mod bits
6501 * are assumed to be 1's, regardless of actual values.
6503 rm = (modrm & 7) | REX_B(s);
6504 reg = ((modrm >> 3) & 7) | REX_R(s);
6505 if (CODE64(s))
6506 ot = MO_64;
6507 else
6508 ot = MO_32;
6509 if (reg >= 8) {
6510 goto illegal_op;
6512 if (b & 2) {
6513 gen_svm_check_intercept(s, SVM_EXIT_WRITE_DR0 + reg);
6514 gen_op_mov_v_reg(s, ot, s->T0, rm);
6515 tcg_gen_movi_i32(s->tmp2_i32, reg);
6516 gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
6517 s->base.is_jmp = DISAS_EOB_NEXT;
6518 } else {
6519 gen_svm_check_intercept(s, SVM_EXIT_READ_DR0 + reg);
6520 tcg_gen_movi_i32(s->tmp2_i32, reg);
6521 gen_helper_get_dr(s->T0, cpu_env, s->tmp2_i32);
6522 gen_op_mov_reg_v(s, ot, rm, s->T0);
6525 break;
6526 case 0x106: /* clts */
6527 if (check_cpl0(s)) {
6528 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
6529 gen_helper_clts(cpu_env);
6530 /* abort block because static cpu state changed */
6531 s->base.is_jmp = DISAS_EOB_NEXT;
6533 break;
6534 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
6535 case 0x1c3: /* MOVNTI reg, mem */
6536 if (!(s->cpuid_features & CPUID_SSE2))
6537 goto illegal_op;
6538 ot = mo_64_32(dflag);
6539 modrm = x86_ldub_code(env, s);
6540 mod = (modrm >> 6) & 3;
6541 if (mod == 3)
6542 goto illegal_op;
6543 reg = ((modrm >> 3) & 7) | REX_R(s);
6544 /* generate a generic store */
6545 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
6546 break;
6547 case 0x1ae:
6548 modrm = x86_ldub_code(env, s);
6549 switch (modrm) {
6550 CASE_MODRM_MEM_OP(0): /* fxsave */
6551 if (!(s->cpuid_features & CPUID_FXSR)
6552 || (prefixes & PREFIX_LOCK)) {
6553 goto illegal_op;
6555 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
6556 gen_exception(s, EXCP07_PREX);
6557 break;
6559 gen_lea_modrm(env, s, modrm);
6560 gen_helper_fxsave(cpu_env, s->A0);
6561 break;
6563 CASE_MODRM_MEM_OP(1): /* fxrstor */
6564 if (!(s->cpuid_features & CPUID_FXSR)
6565 || (prefixes & PREFIX_LOCK)) {
6566 goto illegal_op;
6568 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
6569 gen_exception(s, EXCP07_PREX);
6570 break;
6572 gen_lea_modrm(env, s, modrm);
6573 gen_helper_fxrstor(cpu_env, s->A0);
6574 break;
6576 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
6577 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
6578 goto illegal_op;
6580 if (s->flags & HF_TS_MASK) {
6581 gen_exception(s, EXCP07_PREX);
6582 break;
6584 gen_lea_modrm(env, s, modrm);
6585 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
6586 gen_helper_ldmxcsr(cpu_env, s->tmp2_i32);
6587 break;
6589 CASE_MODRM_MEM_OP(3): /* stmxcsr */
6590 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
6591 goto illegal_op;
6593 if (s->flags & HF_TS_MASK) {
6594 gen_exception(s, EXCP07_PREX);
6595 break;
6597 gen_helper_update_mxcsr(cpu_env);
6598 gen_lea_modrm(env, s, modrm);
6599 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr));
6600 gen_op_st_v(s, MO_32, s->T0, s->A0);
6601 break;
6603 CASE_MODRM_MEM_OP(4): /* xsave */
6604 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
6605 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
6606 | PREFIX_REPZ | PREFIX_REPNZ))) {
6607 goto illegal_op;
6609 gen_lea_modrm(env, s, modrm);
6610 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
6611 cpu_regs[R_EDX]);
6612 gen_helper_xsave(cpu_env, s->A0, s->tmp1_i64);
6613 break;
6615 CASE_MODRM_MEM_OP(5): /* xrstor */
6616 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
6617 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
6618 | PREFIX_REPZ | PREFIX_REPNZ))) {
6619 goto illegal_op;
6621 gen_lea_modrm(env, s, modrm);
6622 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
6623 cpu_regs[R_EDX]);
6624 gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64);
6625 /* XRSTOR is how MPX is enabled, which changes how
6626 we translate. Thus we need to end the TB. */
6627 s->base.is_jmp = DISAS_EOB_NEXT;
6628 break;
6630 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
6631 if (prefixes & PREFIX_LOCK) {
6632 goto illegal_op;
6634 if (prefixes & PREFIX_DATA) {
6635 /* clwb */
6636 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
6637 goto illegal_op;
6639 gen_nop_modrm(env, s, modrm);
6640 } else {
6641 /* xsaveopt */
6642 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
6643 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
6644 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
6645 goto illegal_op;
6647 gen_lea_modrm(env, s, modrm);
6648 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
6649 cpu_regs[R_EDX]);
6650 gen_helper_xsaveopt(cpu_env, s->A0, s->tmp1_i64);
6652 break;
6654 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
6655 if (prefixes & PREFIX_LOCK) {
6656 goto illegal_op;
6658 if (prefixes & PREFIX_DATA) {
6659 /* clflushopt */
6660 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
6661 goto illegal_op;
6663 } else {
6664 /* clflush */
6665 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
6666 || !(s->cpuid_features & CPUID_CLFLUSH)) {
6667 goto illegal_op;
6670 gen_nop_modrm(env, s, modrm);
6671 break;
6673 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
6674 case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
6675 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
6676 case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
6677 if (CODE64(s)
6678 && (prefixes & PREFIX_REPZ)
6679 && !(prefixes & PREFIX_LOCK)
6680 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
6681 TCGv base, treg, src, dst;
6683 /* Preserve hflags bits by testing CR4 at runtime. */
6684 tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
6685 gen_helper_cr4_testbit(cpu_env, s->tmp2_i32);
6687 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
6688 treg = cpu_regs[(modrm & 7) | REX_B(s)];
6690 if (modrm & 0x10) {
6691 /* wr*base */
6692 dst = base, src = treg;
6693 } else {
6694 /* rd*base */
6695 dst = treg, src = base;
6698 if (s->dflag == MO_32) {
6699 tcg_gen_ext32u_tl(dst, src);
6700 } else {
6701 tcg_gen_mov_tl(dst, src);
6703 break;
6705 goto unknown_op;
6707 case 0xf8: /* sfence / pcommit */
6708 if (prefixes & PREFIX_DATA) {
6709 /* pcommit */
6710 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
6711 || (prefixes & PREFIX_LOCK)) {
6712 goto illegal_op;
6714 break;
6716 /* fallthru */
6717 case 0xf9 ... 0xff: /* sfence */
6718 if (!(s->cpuid_features & CPUID_SSE)
6719 || (prefixes & PREFIX_LOCK)) {
6720 goto illegal_op;
6722 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
6723 break;
6724 case 0xe8 ... 0xef: /* lfence */
6725 if (!(s->cpuid_features & CPUID_SSE)
6726 || (prefixes & PREFIX_LOCK)) {
6727 goto illegal_op;
6729 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
6730 break;
6731 case 0xf0 ... 0xf7: /* mfence */
6732 if (!(s->cpuid_features & CPUID_SSE2)
6733 || (prefixes & PREFIX_LOCK)) {
6734 goto illegal_op;
6736 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
6737 break;
6739 default:
6740 goto unknown_op;
6742 break;
6744 case 0x10d: /* 3DNow! prefetch(w) */
6745 modrm = x86_ldub_code(env, s);
6746 mod = (modrm >> 6) & 3;
6747 if (mod == 3)
6748 goto illegal_op;
6749 gen_nop_modrm(env, s, modrm);
6750 break;
6751 case 0x1aa: /* rsm */
6752 gen_svm_check_intercept(s, SVM_EXIT_RSM);
6753 if (!(s->flags & HF_SMM_MASK))
6754 goto illegal_op;
6755 #ifdef CONFIG_USER_ONLY
6756 /* we should not be in SMM mode */
6757 g_assert_not_reached();
6758 #else
6759 gen_update_cc_op(s);
6760 gen_update_eip_next(s);
6761 gen_helper_rsm(cpu_env);
6762 #endif /* CONFIG_USER_ONLY */
6763 s->base.is_jmp = DISAS_EOB_ONLY;
6764 break;
6765 case 0x1b8: /* SSE4.2 popcnt */
6766 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
6767 PREFIX_REPZ)
6768 goto illegal_op;
6769 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
6770 goto illegal_op;
6772 modrm = x86_ldub_code(env, s);
6773 reg = ((modrm >> 3) & 7) | REX_R(s);
6775 if (s->prefix & PREFIX_DATA) {
6776 ot = MO_16;
6777 } else {
6778 ot = mo_64_32(dflag);
6781 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6782 gen_extu(ot, s->T0);
6783 tcg_gen_mov_tl(cpu_cc_src, s->T0);
6784 tcg_gen_ctpop_tl(s->T0, s->T0);
6785 gen_op_mov_reg_v(s, ot, reg, s->T0);
6787 set_cc_op(s, CC_OP_POPCNT);
6788 break;
6789 case 0x10e ... 0x117:
6790 case 0x128 ... 0x12f:
6791 case 0x138 ... 0x13a:
6792 case 0x150 ... 0x179:
6793 case 0x17c ... 0x17f:
6794 case 0x1c2:
6795 case 0x1c4 ... 0x1c6:
6796 case 0x1d0 ... 0x1fe:
6797 disas_insn_new(s, cpu, b);
6798 break;
6799 default:
6800 goto unknown_op;
6802 return true;
6803 illegal_op:
6804 gen_illegal_opcode(s);
6805 return true;
6806 unknown_op:
6807 gen_unknown_opcode(env, s);
6808 return true;
6811 void tcg_x86_init(void)
6813 static const char reg_names[CPU_NB_REGS][4] = {
6814 #ifdef TARGET_X86_64
6815 [R_EAX] = "rax",
6816 [R_EBX] = "rbx",
6817 [R_ECX] = "rcx",
6818 [R_EDX] = "rdx",
6819 [R_ESI] = "rsi",
6820 [R_EDI] = "rdi",
6821 [R_EBP] = "rbp",
6822 [R_ESP] = "rsp",
6823 [8] = "r8",
6824 [9] = "r9",
6825 [10] = "r10",
6826 [11] = "r11",
6827 [12] = "r12",
6828 [13] = "r13",
6829 [14] = "r14",
6830 [15] = "r15",
6831 #else
6832 [R_EAX] = "eax",
6833 [R_EBX] = "ebx",
6834 [R_ECX] = "ecx",
6835 [R_EDX] = "edx",
6836 [R_ESI] = "esi",
6837 [R_EDI] = "edi",
6838 [R_EBP] = "ebp",
6839 [R_ESP] = "esp",
6840 #endif
6842 static const char eip_name[] = {
6843 #ifdef TARGET_X86_64
6844 "rip"
6845 #else
6846 "eip"
6847 #endif
6849 static const char seg_base_names[6][8] = {
6850 [R_CS] = "cs_base",
6851 [R_DS] = "ds_base",
6852 [R_ES] = "es_base",
6853 [R_FS] = "fs_base",
6854 [R_GS] = "gs_base",
6855 [R_SS] = "ss_base",
6857 static const char bnd_regl_names[4][8] = {
6858 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
6860 static const char bnd_regu_names[4][8] = {
6861 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
6863 int i;
6865 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
6866 offsetof(CPUX86State, cc_op), "cc_op");
6867 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
6868 "cc_dst");
6869 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
6870 "cc_src");
6871 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
6872 "cc_src2");
6873 cpu_eip = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, eip), eip_name);
6875 for (i = 0; i < CPU_NB_REGS; ++i) {
6876 cpu_regs[i] = tcg_global_mem_new(cpu_env,
6877 offsetof(CPUX86State, regs[i]),
6878 reg_names[i]);
6881 for (i = 0; i < 6; ++i) {
6882 cpu_seg_base[i]
6883 = tcg_global_mem_new(cpu_env,
6884 offsetof(CPUX86State, segs[i].base),
6885 seg_base_names[i]);
6888 for (i = 0; i < 4; ++i) {
6889 cpu_bndl[i]
6890 = tcg_global_mem_new_i64(cpu_env,
6891 offsetof(CPUX86State, bnd_regs[i].lb),
6892 bnd_regl_names[i]);
6893 cpu_bndu[i]
6894 = tcg_global_mem_new_i64(cpu_env,
6895 offsetof(CPUX86State, bnd_regs[i].ub),
6896 bnd_regu_names[i]);
6900 static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
6902 DisasContext *dc = container_of(dcbase, DisasContext, base);
6903 CPUX86State *env = cpu->env_ptr;
6904 uint32_t flags = dc->base.tb->flags;
6905 uint32_t cflags = tb_cflags(dc->base.tb);
6906 int cpl = (flags >> HF_CPL_SHIFT) & 3;
6907 int iopl = (flags >> IOPL_SHIFT) & 3;
6909 dc->cs_base = dc->base.tb->cs_base;
6910 dc->pc_save = dc->base.pc_next;
6911 dc->flags = flags;
6912 #ifndef CONFIG_USER_ONLY
6913 dc->cpl = cpl;
6914 dc->iopl = iopl;
6915 #endif
6917 /* We make some simplifying assumptions; validate they're correct. */
6918 g_assert(PE(dc) == ((flags & HF_PE_MASK) != 0));
6919 g_assert(CPL(dc) == cpl);
6920 g_assert(IOPL(dc) == iopl);
6921 g_assert(VM86(dc) == ((flags & HF_VM_MASK) != 0));
6922 g_assert(CODE32(dc) == ((flags & HF_CS32_MASK) != 0));
6923 g_assert(CODE64(dc) == ((flags & HF_CS64_MASK) != 0));
6924 g_assert(SS32(dc) == ((flags & HF_SS32_MASK) != 0));
6925 g_assert(LMA(dc) == ((flags & HF_LMA_MASK) != 0));
6926 g_assert(ADDSEG(dc) == ((flags & HF_ADDSEG_MASK) != 0));
6927 g_assert(SVME(dc) == ((flags & HF_SVME_MASK) != 0));
6928 g_assert(GUEST(dc) == ((flags & HF_GUEST_MASK) != 0));
6930 dc->cc_op = CC_OP_DYNAMIC;
6931 dc->cc_op_dirty = false;
6932 dc->popl_esp_hack = 0;
6933 /* select memory access functions */
6934 dc->mem_index = 0;
6935 #ifdef CONFIG_SOFTMMU
6936 dc->mem_index = cpu_mmu_index(env, false);
6937 #endif
6938 dc->cpuid_features = env->features[FEAT_1_EDX];
6939 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
6940 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
6941 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
6942 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
6943 dc->cpuid_7_0_ecx_features = env->features[FEAT_7_0_ECX];
6944 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
6945 dc->jmp_opt = !((cflags & CF_NO_GOTO_TB) ||
6946 (flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)));
6948 * If jmp_opt, we want to handle each string instruction individually.
6949 * For icount also disable repz optimization so that each iteration
6950 * is accounted separately.
6952 dc->repz_opt = !dc->jmp_opt && !(cflags & CF_USE_ICOUNT);
6954 dc->T0 = tcg_temp_new();
6955 dc->T1 = tcg_temp_new();
6956 dc->A0 = tcg_temp_new();
6958 dc->tmp0 = tcg_temp_new();
6959 dc->tmp1_i64 = tcg_temp_new_i64();
6960 dc->tmp2_i32 = tcg_temp_new_i32();
6961 dc->tmp3_i32 = tcg_temp_new_i32();
6962 dc->tmp4 = tcg_temp_new();
6963 dc->cc_srcT = tcg_temp_local_new();
6966 static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
6970 static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
6972 DisasContext *dc = container_of(dcbase, DisasContext, base);
6973 target_ulong pc_arg = dc->base.pc_next;
6975 dc->prev_insn_end = tcg_last_op();
6976 if (TARGET_TB_PCREL) {
6977 pc_arg -= dc->cs_base;
6978 pc_arg &= ~TARGET_PAGE_MASK;
6980 tcg_gen_insn_start(pc_arg, dc->cc_op);
6983 static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
6985 DisasContext *dc = container_of(dcbase, DisasContext, base);
6987 #ifdef TARGET_VSYSCALL_PAGE
6989 * Detect entry into the vsyscall page and invoke the syscall.
6991 if ((dc->base.pc_next & TARGET_PAGE_MASK) == TARGET_VSYSCALL_PAGE) {
6992 gen_exception(dc, EXCP_VSYSCALL);
6993 dc->base.pc_next = dc->pc + 1;
6994 return;
6996 #endif
6998 if (disas_insn(dc, cpu)) {
6999 target_ulong pc_next = dc->pc;
7000 dc->base.pc_next = pc_next;
7002 if (dc->base.is_jmp == DISAS_NEXT) {
7003 if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
7005 * If single step mode, we generate only one instruction and
7006 * generate an exception.
7007 * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
7008 * the flag and abort the translation to give the irqs a
7009 * chance to happen.
7011 dc->base.is_jmp = DISAS_EOB_NEXT;
7012 } else if (!is_same_page(&dc->base, pc_next)) {
7013 dc->base.is_jmp = DISAS_TOO_MANY;
7019 static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
7021 DisasContext *dc = container_of(dcbase, DisasContext, base);
7023 switch (dc->base.is_jmp) {
7024 case DISAS_NORETURN:
7025 break;
7026 case DISAS_TOO_MANY:
7027 gen_update_cc_op(dc);
7028 gen_jmp_rel_csize(dc, 0, 0);
7029 break;
7030 case DISAS_EOB_NEXT:
7031 gen_update_cc_op(dc);
7032 gen_update_eip_cur(dc);
7033 /* fall through */
7034 case DISAS_EOB_ONLY:
7035 gen_eob(dc);
7036 break;
7037 case DISAS_EOB_INHIBIT_IRQ:
7038 gen_update_cc_op(dc);
7039 gen_update_eip_cur(dc);
7040 gen_eob_inhibit_irq(dc, true);
7041 break;
7042 case DISAS_JUMP:
7043 gen_jr(dc);
7044 break;
7045 default:
7046 g_assert_not_reached();
7050 static void i386_tr_disas_log(const DisasContextBase *dcbase,
7051 CPUState *cpu, FILE *logfile)
7053 DisasContext *dc = container_of(dcbase, DisasContext, base);
7055 fprintf(logfile, "IN: %s\n", lookup_symbol(dc->base.pc_first));
7056 target_disas(logfile, cpu, dc->base.pc_first, dc->base.tb->size);
7059 static const TranslatorOps i386_tr_ops = {
7060 .init_disas_context = i386_tr_init_disas_context,
7061 .tb_start = i386_tr_tb_start,
7062 .insn_start = i386_tr_insn_start,
7063 .translate_insn = i386_tr_translate_insn,
7064 .tb_stop = i386_tr_tb_stop,
7065 .disas_log = i386_tr_disas_log,
7068 /* generate intermediate code for basic block 'tb'. */
7069 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
7070 target_ulong pc, void *host_pc)
7072 DisasContext dc;
7074 translator_loop(cpu, tb, max_insns, pc, host_pc, &i386_tr_ops, &dc.base);