1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "qemu/osdep.h"
20
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"
30
31#include "exec/helper-proto.h"
32#include "exec/helper-gen.h"
33#include "helper-tcg.h"
34
35#include "exec/log.h"
36
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
44
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
52
53
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
58
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
64
65
66
67
68static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
69static TCGv cpu_eip;
70static TCGv_i32 cpu_cc_op;
71static TCGv cpu_regs[CPU_NB_REGS];
72static TCGv cpu_seg_base[6];
73static TCGv_i64 cpu_bndl[4];
74static TCGv_i64 cpu_bndu[4];
75
76#include "exec/gen-icount.h"
77
78typedef struct DisasContext {
79 DisasContextBase base;
80
81 target_ulong pc;
82 target_ulong cs_base;
83 target_ulong pc_save;
84
85 MemOp aflag;
86 MemOp dflag;
87
88 int8_t override;
89 uint8_t prefix;
90
91 bool has_modrm;
92 uint8_t modrm;
93
94#ifndef CONFIG_USER_ONLY
95 uint8_t cpl;
96 uint8_t iopl;
97#endif
98 uint8_t vex_l;
99 uint8_t vex_v;
100 uint8_t popl_esp_hack;
101 uint8_t rip_offset;
102
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;
109 bool jmp_opt;
110 bool repz_opt;
111 bool cc_op_dirty;
112
113 CCOp cc_op;
114 int mem_index;
115 uint32_t 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;
123
124
125 TCGv cc_srcT;
126 TCGv A0;
127 TCGv T0;
128 TCGv T1;
129
130
131 TCGv tmp0;
132 TCGv tmp4;
133 TCGv_i32 tmp2_i32;
134 TCGv_i32 tmp3_i32;
135 TCGv_i64 tmp1_i64;
136
137 sigjmp_buf jmpbuf;
138 TCGOp *prev_insn_end;
139} DisasContext;
140
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
145
146
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
181
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
195
196
197
198
199
200
201#define STUB_HELPER(NAME, ...) \
202 static inline void gen_helper_##NAME(__VA_ARGS__) \
203 { qemu_build_not_reached(); }
204
205#ifdef CONFIG_USER_ONLY
206STUB_HELPER(clgi, TCGv_env env)
207STUB_HELPER(flush_page, TCGv_env env, TCGv addr)
208STUB_HELPER(hlt, TCGv_env env, TCGv_i32 pc_ofs)
209STUB_HELPER(inb, TCGv ret, TCGv_env env, TCGv_i32 port)
210STUB_HELPER(inw, TCGv ret, TCGv_env env, TCGv_i32 port)
211STUB_HELPER(inl, TCGv ret, TCGv_env env, TCGv_i32 port)
212STUB_HELPER(monitor, TCGv_env env, TCGv addr)
213STUB_HELPER(mwait, TCGv_env env, TCGv_i32 pc_ofs)
214STUB_HELPER(outb, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
215STUB_HELPER(outw, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
216STUB_HELPER(outl, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
217STUB_HELPER(rdmsr, TCGv_env env)
218STUB_HELPER(read_crN, TCGv ret, TCGv_env env, TCGv_i32 reg)
219STUB_HELPER(get_dr, TCGv ret, TCGv_env env, TCGv_i32 reg)
220STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
221STUB_HELPER(stgi, TCGv_env env)
222STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
223STUB_HELPER(vmload, TCGv_env env, TCGv_i32 aflag)
224STUB_HELPER(vmmcall, TCGv_env env)
225STUB_HELPER(vmrun, TCGv_env env, TCGv_i32 aflag, TCGv_i32 pc_ofs)
226STUB_HELPER(vmsave, TCGv_env env, TCGv_i32 aflag)
227STUB_HELPER(write_crN, TCGv_env env, TCGv_i32 reg, TCGv val)
228STUB_HELPER(wrmsr, TCGv_env env)
229#endif
230
231static void gen_eob(DisasContext *s);
232static void gen_jr(DisasContext *s);
233static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num);
234static void gen_jmp_rel_csize(DisasContext *s, int diff, int tb_num);
235static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
236static void gen_exception_gpf(DisasContext *s);
237
238
239enum {
240 OP_ADDL,
241 OP_ORL,
242 OP_ADCL,
243 OP_SBBL,
244 OP_ANDL,
245 OP_SUBL,
246 OP_XORL,
247 OP_CMPL,
248};
249
250
251enum {
252 OP_ROL,
253 OP_ROR,
254 OP_RCL,
255 OP_RCR,
256 OP_SHL,
257 OP_SHR,
258 OP_SHL1,
259 OP_SAR = 7,
260};
261
262enum {
263 JCC_O,
264 JCC_B,
265 JCC_Z,
266 JCC_BE,
267 JCC_S,
268 JCC_P,
269 JCC_L,
270 JCC_LE,
271};
272
273enum {
274
275 OR_EAX,
276 OR_ECX,
277 OR_EDX,
278 OR_EBX,
279 OR_ESP,
280 OR_EBP,
281 OR_ESI,
282 OR_EDI,
283
284 OR_TMP0 = 16,
285 OR_TMP1,
286 OR_A0,
287};
288
289enum {
290 USES_CC_DST = 1,
291 USES_CC_SRC = 2,
292 USES_CC_SRC2 = 4,
293 USES_CC_SRCT = 8,
294};
295
296
297static 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,
316};
317
318static void set_cc_op(DisasContext *s, CCOp op)
319{
320 int dead;
321
322 if (s->cc_op == op) {
323 return;
324 }
325
326
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);
330 }
331 if (dead & USES_CC_SRC) {
332 tcg_gen_discard_tl(cpu_cc_src);
333 }
334 if (dead & USES_CC_SRC2) {
335 tcg_gen_discard_tl(cpu_cc_src2);
336 }
337 if (dead & USES_CC_SRCT) {
338 tcg_gen_discard_tl(s->cc_srcT);
339 }
340
341 if (op == CC_OP_DYNAMIC) {
342
343
344 s->cc_op_dirty = false;
345 } else {
346
347 if (s->cc_op == CC_OP_DYNAMIC) {
348 tcg_gen_discard_i32(cpu_cc_op);
349 }
350 s->cc_op_dirty = true;
351 }
352 s->cc_op = op;
353}
354
355static void gen_update_cc_op(DisasContext *s)
356{
357 if (s->cc_op_dirty) {
358 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
359 s->cc_op_dirty = false;
360 }
361}
362
363#ifdef TARGET_X86_64
364
365#define NB_OP_SIZES 4
366
367#else
368
369#define NB_OP_SIZES 3
370
371#endif
372
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
386
387
388
389
390
391
392
393static inline bool byte_reg_is_xH(DisasContext *s, int reg)
394{
395
396 if (reg < 4 || REX_PREFIX(s)) {
397 return false;
398 }
399 return true;
400}
401
402
403static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
404{
405 if (CODE64(s)) {
406 return ot == MO_16 ? MO_16 : MO_64;
407 } else {
408 return ot;
409 }
410}
411
412
413static inline MemOp mo_stacksize(DisasContext *s)
414{
415 return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
416}
417
418
419static inline MemOp mo_64_32(MemOp ot)
420{
421#ifdef TARGET_X86_64
422 return ot == MO_64 ? MO_64 : MO_32;
423#else
424 return MO_32;
425#endif
426}
427
428
429
430static inline MemOp mo_b_d(int b, MemOp ot)
431{
432 return b & 1 ? ot : MO_8;
433}
434
435
436
437static inline MemOp mo_b_d32(int b, MemOp ot)
438{
439 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
440}
441
442
443
444
445
446
447
448
449
450static TCGv gen_op_deposit_reg_v(DisasContext *s, MemOp ot, int reg, TCGv dest, TCGv t0)
451{
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];
458 }
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
468
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();
480 }
481 return cpu_regs[reg];
482}
483
484static void gen_op_mov_reg_v(DisasContext *s, MemOp ot, int reg, TCGv t0)
485{
486 gen_op_deposit_reg_v(s, ot, reg, NULL, t0);
487}
488
489static inline
490void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg)
491{
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]);
496 }
497}
498
499static void gen_add_A0_im(DisasContext *s, int val)
500{
501 tcg_gen_addi_tl(s->A0, s->A0, val);
502 if (!CODE64(s)) {
503 tcg_gen_ext32u_tl(s->A0, s->A0);
504 }
505}
506
507static inline void gen_op_jmp_v(DisasContext *s, TCGv dest)
508{
509 tcg_gen_mov_tl(cpu_eip, dest);
510 s->pc_save = -1;
511}
512
513static inline
514void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val)
515{
516 tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val);
517 gen_op_mov_reg_v(s, size, reg, s->tmp0);
518}
519
520static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg)
521{
522 tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0);
523 gen_op_mov_reg_v(s, size, reg, s->tmp0);
524}
525
526static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
527{
528 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
529}
530
531static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
532{
533 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
534}
535
536static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
537{
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);
542 }
543}
544
545static void gen_update_eip_cur(DisasContext *s)
546{
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);
552 }
553 s->pc_save = s->base.pc_next;
554}
555
556static void gen_update_eip_next(DisasContext *s)
557{
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);
563 }
564 s->pc_save = s->pc;
565}
566
567static int cur_insn_len(DisasContext *s)
568{
569 return s->pc - s->base.pc_next;
570}
571
572static TCGv_i32 cur_insn_len_i32(DisasContext *s)
573{
574 return tcg_constant_i32(cur_insn_len(s));
575}
576
577static TCGv_i32 eip_next_i32(DisasContext *s)
578{
579 assert(s->pc_save != -1);
580
581
582
583
584
585
586
587
588 if (CODE64(s)) {
589 return tcg_constant_i32(-1);
590 }
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);
598 }
599}
600
601static TCGv eip_next_tl(DisasContext *s)
602{
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);
610 }
611}
612
613static TCGv eip_cur_tl(DisasContext *s)
614{
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);
622 }
623}
624
625
626
627
628static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
629 int def_seg, int ovr_seg)
630{
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;
637 }
638 break;
639#endif
640 case MO_32:
641
642 if (ovr_seg < 0 && ADDSEG(s)) {
643 ovr_seg = def_seg;
644 }
645 if (ovr_seg < 0) {
646 tcg_gen_ext32u_tl(s->A0, a0);
647 return;
648 }
649 break;
650 case MO_16:
651
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;
659 }
660 }
661 break;
662 default:
663 tcg_abort();
664 }
665
666 if (ovr_seg >= 0) {
667 TCGv seg = cpu_seg_base[ovr_seg];
668
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);
677 }
678 }
679}
680
681static inline void gen_string_movl_A0_ESI(DisasContext *s)
682{
683 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
684}
685
686static inline void gen_string_movl_A0_EDI(DisasContext *s)
687{
688 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
689}
690
691static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
692{
693 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
694 tcg_gen_shli_tl(s->T0, s->T0, ot);
695};
696
697static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
698{
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);
705 }
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);
712 }
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);
720 }
721 return dst;
722#endif
723 default:
724 return src;
725 }
726}
727
728static void gen_extu(MemOp ot, TCGv reg)
729{
730 gen_ext_tl(reg, reg, ot, false);
731}
732
733static void gen_exts(MemOp ot, TCGv reg)
734{
735 gen_ext_tl(reg, reg, ot, true);
736}
737
738static void gen_op_j_ecx(DisasContext *s, TCGCond cond, TCGLabel *label1)
739{
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);
743}
744
745static inline void gen_op_jz_ecx(DisasContext *s, TCGLabel *label1)
746{
747 gen_op_j_ecx(s, TCG_COND_EQ, label1);
748}
749
750static inline void gen_op_jnz_ecx(DisasContext *s, TCGLabel *label1)
751{
752 gen_op_j_ecx(s, TCG_COND_NE, label1);
753}
754
755static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
756{
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();
769 }
770}
771
772static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
773{
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();
786 }
787}
788
789
790
791
792
793static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
794 uint32_t svm_flags)
795{
796#ifdef CONFIG_USER_ONLY
797
798
799
800
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));
806 }
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;
812 }
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));
817 }
818 return true;
819#endif
820}
821
822static void gen_movs(DisasContext *s, MemOp ot)
823{
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);
831}
832
833static void gen_op_update1_cc(DisasContext *s)
834{
835 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
836}
837
838static void gen_op_update2_cc(DisasContext *s)
839{
840 tcg_gen_mov_tl(cpu_cc_src, s->T1);
841 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
842}
843
844static void gen_op_update3_cc(DisasContext *s, TCGv reg)
845{
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);
849}
850
851static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
852{
853 tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1);
854}
855
856static void gen_op_update_neg_cc(DisasContext *s)
857{
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);
861}
862
863
864static void gen_compute_eflags(DisasContext *s)
865{
866 TCGv zero, dst, src1, src2;
867 int live, dead;
868
869 if (s->cc_op == CC_OP_EFLAGS) {
870 return;
871 }
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;
876 }
877
878 zero = NULL;
879 dst = cpu_cc_dst;
880 src1 = cpu_cc_src;
881 src2 = cpu_cc_src2;
882
883
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;
890 }
891 if (dead & USES_CC_SRC) {
892 src1 = zero;
893 }
894 if (dead & USES_CC_SRC2) {
895 src2 = zero;
896 }
897 }
898
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);
902
903 if (dead) {
904 tcg_temp_free(zero);
905 }
906}
907
908typedef 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;
917
918
919static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
920{
921 TCGv t0, t1;
922 int size, shift;
923
924 switch (s->cc_op) {
925 case CC_OP_SUBB ... CC_OP_SUBQ:
926
927 size = s->cc_op - CC_OP_SUBB;
928 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
929
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;
934
935 case CC_OP_ADDB ... CC_OP_ADDQ:
936
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 };
943
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 };
948
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 };
953
954 case CC_OP_SHLB ... CC_OP_SHLQ:
955
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 };
960
961 case CC_OP_MULB ... CC_OP_MULQ:
962 return (CCPrepare) { .cond = TCG_COND_NE,
963 .reg = cpu_cc_src, .mask = -1 };
964
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 };
969
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 };
974
975 case CC_OP_EFLAGS:
976 case CC_OP_SARB ... CC_OP_SARQ:
977
978 return (CCPrepare) { .cond = TCG_COND_NE,
979 .reg = cpu_cc_src, .mask = CC_C };
980
981 default:
982
983
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 };
989 }
990}
991
992
993static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
994{
995 gen_compute_eflags(s);
996 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
997 .mask = CC_P };
998}
999
1000
1001static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
1002{
1003 switch (s->cc_op) {
1004 case CC_OP_DYNAMIC:
1005 gen_compute_eflags(s);
1006
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:
1017 {
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 };
1021 }
1022 }
1023}
1024
1025
1026static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
1027{
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 };
1040 }
1041}
1042
1043
1044static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
1045{
1046 switch (s->cc_op) {
1047 case CC_OP_DYNAMIC:
1048 gen_compute_eflags(s);
1049
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:
1062 {
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 };
1066 }
1067 }
1068}
1069
1070
1071
1072static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
1073{
1074 int inv, jcc_op, cond;
1075 MemOp size;
1076 CCPrepare cc;
1077 TCGv t0;
1078
1079 inv = b & 1;
1080 jcc_op = (b >> 1) & 7;
1081
1082 switch (s->cc_op) {
1083 case CC_OP_SUBB ... CC_OP_SUBQ:
1084
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;
1094
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;
1107
1108 default:
1109 goto slow_jcc;
1110 }
1111 break;
1112
1113 default:
1114 slow_jcc:
1115
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;
1141 }
1142 tcg_gen_shri_tl(reg, cpu_cc_src, 4);
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;
1152 }
1153 tcg_gen_shri_tl(reg, cpu_cc_src, 4);
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;
1158 }
1159 break;
1160 }
1161
1162 if (inv) {
1163 cc.cond = tcg_invert_cond(cc.cond);
1164 }
1165 return cc;
1166}
1167
1168static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1169{
1170 CCPrepare cc = gen_prepare_cc(s, b, reg);
1171
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);
1177 }
1178 return;
1179 }
1180
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;
1186 }
1187 if (cc.mask != -1) {
1188 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1189 cc.reg = reg;
1190 }
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);
1195 }
1196}
1197
1198static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1199{
1200 gen_setcc1(s, JCC_B << 1, reg);
1201}
1202
1203
1204
1205static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1206{
1207 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1208
1209 if (cc.mask != -1) {
1210 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1211 cc.reg = s->T0;
1212 }
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);
1217 }
1218}
1219
1220
1221
1222
1223static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1224{
1225 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1226
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;
1231 }
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);
1237 }
1238}
1239
1240
1241
1242static TCGLabel *gen_jz_ecx_string(DisasContext *s)
1243{
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;
1251}
1252
1253static void gen_stos(DisasContext *s, MemOp ot)
1254{
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);
1260}
1261
1262static void gen_lods(DisasContext *s, MemOp ot)
1263{
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);
1269}
1270
1271static void gen_scas(DisasContext *s, MemOp ot)
1272{
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);
1278}
1279
1280static void gen_cmps(DisasContext *s, MemOp ot)
1281{
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);
1289}
1290
1291static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1292{
1293 if (s->flags & HF_IOBPT_MASK) {
1294#ifdef CONFIG_USER_ONLY
1295
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
1302 }
1303}
1304
1305static void gen_ins(DisasContext *s, MemOp ot)
1306{
1307 gen_string_movl_A0_EDI(s);
1308
1309
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);
1319}
1320
1321static void gen_outs(DisasContext *s, MemOp ot)
1322{
1323 gen_string_movl_A0_ESI(s);
1324 gen_op_ld_v(s, ot, s->T0, s->A0);
1325
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);
1333}
1334
1335
1336static void gen_repz(DisasContext *s, MemOp ot,
1337 void (*fn)(DisasContext *s, MemOp ot))
1338{
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);
1344
1345
1346
1347
1348 if (s->repz_opt) {
1349 gen_op_jz_ecx(s, l2);
1350 }
1351 gen_jmp_rel_csize(s, -cur_insn_len(s), 0);
1352}
1353
1354#define GEN_REPZ(op) \
1355 static inline void gen_repz_ ## op(DisasContext *s, MemOp ot) \
1356 { gen_repz(s, ot, gen_##op); }
1357
1358static void gen_repz2(DisasContext *s, MemOp ot, int nz,
1359 void (*fn)(DisasContext *s, MemOp ot))
1360{
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);
1370 }
1371 gen_jmp_rel_csize(s, -cur_insn_len(s), 0);
1372}
1373
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); }
1377
1378GEN_REPZ(movs)
1379GEN_REPZ(stos)
1380GEN_REPZ(lods)
1381GEN_REPZ(ins)
1382GEN_REPZ(outs)
1383GEN_REPZ2(scas)
1384GEN_REPZ2(cmps)
1385
1386static void gen_helper_fp_arith_ST0_FT0(int op)
1387{
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;
1413 }
1414}
1415
1416
1417static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1418{
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;
1439 }
1440}
1441
1442static void gen_exception(DisasContext *s, int trapno)
1443{
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;
1448}
1449
1450
1451
1452static void gen_illegal_opcode(DisasContext *s)
1453{
1454 gen_exception(s, EXCP06_ILLOP);
1455}
1456
1457
1458static void gen_exception_gpf(DisasContext *s)
1459{
1460 gen_exception(s, EXCP0D_GPF);
1461}
1462
1463
1464static bool check_cpl0(DisasContext *s)
1465{
1466 if (CPL(s) == 0) {
1467 return true;
1468 }
1469 gen_exception_gpf(s);
1470 return false;
1471}
1472
1473
1474static bool check_vm86_iopl(DisasContext *s)
1475{
1476 if (!VM86(s) || IOPL(s) == 3) {
1477 return true;
1478 }
1479 gen_exception_gpf(s);
1480 return false;
1481}
1482
1483
1484static bool check_iopl(DisasContext *s)
1485{
1486 if (VM86(s) ? IOPL(s) == 3 : CPL(s) <= IOPL(s)) {
1487 return true;
1488 }
1489 gen_exception_gpf(s);
1490 return false;
1491}
1492
1493
1494static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
1495{
1496 if (d != OR_TMP0) {
1497 if (s1->prefix & PREFIX_LOCK) {
1498
1499 gen_illegal_opcode(s1);
1500 return;
1501 }
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);
1505 }
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);
1517 }
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);
1532 }
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);
1543 }
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);
1557 }
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);
1569 }
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);
1580 }
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);
1591 }
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;
1601 }
1602}
1603
1604
1605static void gen_inc(DisasContext *s1, MemOp ot, int d, int c)
1606{
1607 if (s1->prefix & PREFIX_LOCK) {
1608 if (d != OR_TMP0) {
1609
1610 gen_illegal_opcode(s1);
1611 return;
1612 }
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);
1621 }
1622 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
1623 gen_op_st_rm_T0_A0(s1, ot, d);
1624 }
1625
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);
1629}
1630
1631static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
1632 TCGv shm1, TCGv count, bool is_right)
1633{
1634 TCGv_i32 z32, s32, oldop;
1635 TCGv z_tl;
1636
1637
1638
1639
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);
1646 }
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);
1652 }
1653 tcg_temp_free(z_tl);
1654
1655
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;
1662 }
1663
1664
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);
1671
1672
1673 set_cc_op(s, CC_OP_DYNAMIC);
1674}
1675
1676static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1,
1677 int is_right, int is_arith)
1678{
1679 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1680
1681
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);
1686 }
1687
1688 tcg_gen_andi_tl(s->T1, s->T1, mask);
1689 tcg_gen_subi_tl(s->tmp0, s->T1, 1);
1690
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);
1700 }
1701 } else {
1702 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1703 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
1704 }
1705
1706
1707 gen_op_st_rm_T0_A0(s, ot, op1);
1708
1709 gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right);
1710}
1711
1712static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1713 int is_right, int is_arith)
1714{
1715 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1716
1717
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);
1722
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);
1734 }
1735 } else {
1736 tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1);
1737 tcg_gen_shli_tl(s->T0, s->T0, op2);
1738 }
1739 }
1740
1741
1742 gen_op_st_rm_T0_A0(s, ot, op1);
1743
1744
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);
1749 }
1750}
1751
1752static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right)
1753{
1754 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1755 TCGv_i32 t0, t1;
1756
1757
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);
1762 }
1763
1764 tcg_gen_andi_tl(s->T1, s->T1, mask);
1765
1766 switch (ot) {
1767 case MO_8:
1768
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
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);
1785 }
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);
1794 }
1795 break;
1796 }
1797
1798
1799 gen_op_st_rm_T0_A0(s, ot, op1);
1800
1801
1802 gen_compute_eflags(s);
1803
1804
1805
1806
1807
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);
1815 }
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);
1818
1819
1820
1821
1822
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);
1832
1833
1834 set_cc_op(s, CC_OP_DYNAMIC);
1835}
1836
1837static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1838 int is_right)
1839{
1840 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1841 int shift;
1842
1843
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);
1848 }
1849
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);
1860 }
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);
1869 }
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;
1880 }
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;
1886 }
1887 }
1888
1889
1890 gen_op_st_rm_T0_A0(s, ot, op1);
1891
1892 if (op2 != 0) {
1893
1894 gen_compute_eflags(s);
1895
1896
1897
1898
1899
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);
1907 }
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);
1911 }
1912}
1913
1914
1915static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
1916 int is_right)
1917{
1918 gen_compute_eflags(s);
1919 assert(s->cc_op == CC_OP_EFLAGS);
1920
1921
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);
1926
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();
1945 }
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();
1964 }
1965 }
1966
1967 gen_op_st_rm_T0_A0(s, ot, op1);
1968}
1969
1970
1971static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
1972 bool is_right, TCGv count_in)
1973{
1974 target_ulong mask = (ot == MO_64 ? 63 : 31);
1975 TCGv count;
1976
1977
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);
1982 }
1983
1984 count = tcg_temp_new();
1985 tcg_gen_andi_tl(count, count_in, mask);
1986
1987 switch (ot) {
1988 case MO_16:
1989
1990
1991
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);
1998 }
1999
2000
2001
2002
2003 case MO_32:
2004#ifdef TARGET_X86_64
2005
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);
2017 }
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);
2024
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
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);
2035 }
2036
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);
2040 }
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;
2046 }
2047
2048
2049 gen_op_st_rm_T0_A0(s, ot, op1);
2050
2051 gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
2052 tcg_temp_free(count);
2053}
2054
2055static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s)
2056{
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;
2082 }
2083}
2084
2085static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c)
2086{
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
2106 tcg_gen_movi_tl(s1->T1, c);
2107 gen_shift(s1, op, ot, d, OR_TMP1);
2108 break;
2109 }
2110}
2111
2112#define X86_MAX_INSN_LENGTH 15
2113
2114static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
2115{
2116 uint64_t pc = s->pc;
2117
2118
2119 if (s->base.num_insns > 1 &&
2120 !is_same_page(&s->base, s->pc + num_bytes - 1)) {
2121 siglongjmp(s->jmpbuf, 2);
2122 }
2123
2124 s->pc += num_bytes;
2125 if (unlikely(cur_insn_len(s) > X86_MAX_INSN_LENGTH)) {
2126
2127
2128
2129
2130
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;
2135 }
2136 siglongjmp(s->jmpbuf, 1);
2137 }
2138
2139 return pc;
2140}
2141
2142static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
2143{
2144 return translator_ldub(env, &s->base, advance_pc(env, s, 1));
2145}
2146
2147static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
2148{
2149 return translator_lduw(env, &s->base, advance_pc(env, s, 2));
2150}
2151
2152static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
2153{
2154 return translator_lduw(env, &s->base, advance_pc(env, s, 2));
2155}
2156
2157static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
2158{
2159 return translator_ldl(env, &s->base, advance_pc(env, s, 4));
2160}
2161
2162#ifdef TARGET_X86_64
2163static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
2164{
2165 return translator_ldq(env, &s->base, advance_pc(env, s, 8));
2166}
2167#endif
2168
2169
2170
2171typedef struct AddressParts {
2172 int def_seg;
2173 int base;
2174 int index;
2175 int scale;
2176 target_long disp;
2177} AddressParts;
2178
2179static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
2180 int modrm)
2181{
2182 int def_seg, base, index, scale, mod, rm;
2183 target_long disp;
2184 bool havesib;
2185
2186 def_seg = R_DS;
2187 index = -1;
2188 scale = 0;
2189 disp = 0;
2190
2191 mod = (modrm >> 6) & 3;
2192 rm = modrm & 7;
2193 base = rm | REX_B(s);
2194
2195 if (mod == 3) {
2196
2197
2198 goto done;
2199 }
2200
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;
2211 }
2212 base = (code & 7) | REX_B(s);
2213 havesib = 1;
2214 }
2215
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;
2224 }
2225 }
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;
2234 }
2235
2236
2237 if (base == R_ESP && s->popl_esp_hack) {
2238 disp += s->popl_esp_hack;
2239 }
2240 if (base == R_EBP || base == R_ESP) {
2241 def_seg = R_SS;
2242 }
2243 break;
2244
2245 case MO_16:
2246 if (mod == 0) {
2247 if (rm == 6) {
2248 base = -1;
2249 disp = x86_lduw_code(env, s);
2250 break;
2251 }
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);
2256 }
2257
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;
2291 }
2292 break;
2293
2294 default:
2295 tcg_abort();
2296 }
2297
2298 done:
2299 return (AddressParts){ def_seg, base, index, scale, disp };
2300}
2301
2302
2303static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a, bool is_vsib)
2304{
2305 TCGv ea = NULL;
2306
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;
2313 }
2314 if (a.base >= 0) {
2315 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2316 ea = s->A0;
2317 }
2318 } else if (a.base >= 0) {
2319 ea = cpu_regs[a.base];
2320 }
2321 if (!ea) {
2322 if (TARGET_TB_PCREL && a.base == -2) {
2323
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);
2327 }
2328 ea = s->A0;
2329 } else if (a.disp != 0) {
2330 tcg_gen_addi_tl(s->A0, ea, a.disp);
2331 ea = s->A0;
2332 }
2333
2334 return ea;
2335}
2336
2337static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2338{
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);
2342}
2343
2344static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2345{
2346 (void)gen_lea_modrm_0(env, s, modrm);
2347}
2348
2349
2350static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2351 TCGCond cond, TCGv_i64 bndv)
2352{
2353 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2354 TCGv ea = gen_lea_modrm_1(s, a, false);
2355
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);
2359 }
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);
2363}
2364
2365
2366static void gen_add_A0_ds_seg(DisasContext *s)
2367{
2368 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
2369}
2370
2371
2372
2373static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2374 MemOp ot, int reg, int is_store)
2375{
2376 int mod, rm;
2377
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);
2389 }
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);
2400 }
2401 }
2402}
2403
2404static target_ulong insn_get_addr(CPUX86State *env, DisasContext *s, MemOp ot)
2405{
2406 target_ulong ret;
2407
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();
2425 }
2426 return ret;
2427}
2428
2429static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
2430{
2431 uint32_t ret;
2432
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();
2448 }
2449 return ret;
2450}
2451
2452static target_long insn_get_signed(CPUX86State *env, DisasContext *s, MemOp ot)
2453{
2454 target_long ret;
2455
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();
2473 }
2474 return ret;
2475}
2476
2477static inline int insn_const_size(MemOp ot)
2478{
2479 if (ot <= MO_32) {
2480 return 1 << ot;
2481 } else {
2482 return 4;
2483 }
2484}
2485
2486static void gen_jcc(DisasContext *s, int b, int diff)
2487{
2488 TCGLabel *l1 = gen_new_label();
2489
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);
2494}
2495
2496static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
2497 int modrm, int reg)
2498{
2499 CCPrepare cc;
2500
2501 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2502
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;
2508 }
2509 if (!cc.use_reg2) {
2510 cc.reg2 = tcg_const_tl(cc.imm);
2511 }
2512
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);
2516
2517 if (cc.mask != -1) {
2518 tcg_temp_free(cc.reg);
2519 }
2520 if (!cc.use_reg2) {
2521 tcg_temp_free(cc.reg2);
2522 }
2523}
2524
2525static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg)
2526{
2527 tcg_gen_ld32u_tl(s->T0, cpu_env,
2528 offsetof(CPUX86State,segs[seg_reg].selector));
2529}
2530
2531static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg)
2532{
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);
2537}
2538
2539
2540
2541static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg)
2542{
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
2547
2548
2549
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;
2554 }
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;
2559 }
2560 }
2561}
2562
2563static void gen_svm_check_intercept(DisasContext *s, uint32_t type)
2564{
2565
2566 if (likely(!GUEST(s))) {
2567 return;
2568 }
2569 gen_helper_svm_check_intercept(cpu_env, tcg_constant_i32(type));
2570}
2571
2572static inline void gen_stack_update(DisasContext *s, int addend)
2573{
2574 gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend);
2575}
2576
2577
2578static void gen_push_v(DisasContext *s, TCGv val)
2579{
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;
2584
2585 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2586
2587 if (!CODE64(s)) {
2588 if (ADDSEG(s)) {
2589 new_esp = s->tmp4;
2590 tcg_gen_mov_tl(new_esp, s->A0);
2591 }
2592 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2593 }
2594
2595 gen_op_st_v(s, d_ot, val, s->A0);
2596 gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp);
2597}
2598
2599
2600static MemOp gen_pop_T0(DisasContext *s)
2601{
2602 MemOp d_ot = mo_pushpop(s, s->dflag);
2603
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);
2606
2607 return d_ot;
2608}
2609
2610static inline void gen_pop_update(DisasContext *s, MemOp ot)
2611{
2612 gen_stack_update(s, 1 << ot);
2613}
2614
2615static inline void gen_stack_A0(DisasContext *s)
2616{
2617 gen_lea_v_seg(s, SS32(s) ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2618}
2619
2620static void gen_pusha(DisasContext *s)
2621{
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;
2626
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);
2631 }
2632
2633 gen_stack_update(s, -8 * size);
2634}
2635
2636static void gen_popa(DisasContext *s)
2637{
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;
2642
2643 for (i = 0; i < 8; i++) {
2644
2645 if (7 - i == R_ESP) {
2646 continue;
2647 }
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);
2652 }
2653
2654 gen_stack_update(s, 8 * size);
2655}
2656
2657static void gen_enter(DisasContext *s, int esp_addend, int level)
2658{
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;
2662
2663
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);
2667
2668 level &= 31;
2669 if (level != 0) {
2670 int i;
2671
2672
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);
2677
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);
2681 }
2682
2683
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);
2687 }
2688
2689
2690 gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
2691
2692
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);
2695}
2696
2697static void gen_leave(DisasContext *s)
2698{
2699 MemOp d_ot = mo_pushpop(s, s->dflag);
2700 MemOp a_ot = mo_stacksize(s);
2701
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);
2704
2705 tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot);
2706
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);
2709}
2710
2711
2712
2713
2714static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2715{
2716 gen_illegal_opcode(s);
2717
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;
2722
2723 fprintf(logfile, "ILLOPC: " TARGET_FMT_lx ":", pc);
2724 for (; pc < end; ++pc) {
2725 fprintf(logfile, " %02x", cpu_ldub_code(env, pc));
2726 }
2727 fprintf(logfile, "\n");
2728 qemu_log_unlock(logfile);
2729 }
2730 }
2731}
2732
2733
2734
2735static void gen_interrupt(DisasContext *s, int intno)
2736{
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;
2742}
2743
2744static void gen_set_hflag(DisasContext *s, uint32_t mask)
2745{
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;
2753 }
2754}
2755
2756static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2757{
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;
2765 }
2766}
2767
2768static void gen_set_eflags(DisasContext *s, target_ulong mask)
2769{
2770 TCGv t = tcg_temp_new();
2771
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);
2776}
2777
2778static void gen_reset_eflags(DisasContext *s, target_ulong mask)
2779{
2780 TCGv t = tcg_temp_new();
2781
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);
2786}
2787
2788
2789static void gen_bnd_jmp(DisasContext *s)
2790{
2791
2792
2793
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);
2798 }
2799}
2800
2801
2802
2803
2804
2805static void
2806do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2807{
2808 gen_update_cc_op(s);
2809
2810
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);
2815 }
2816
2817 if (s->base.tb->flags & HF_RF_MASK) {
2818 gen_reset_eflags(s, RF_MASK);
2819 }
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);
2829 }
2830 s->base.is_jmp = DISAS_NORETURN;
2831}
2832
2833static inline void
2834gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2835{
2836 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2837}
2838
2839
2840
2841static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2842{
2843 gen_eob_worker(s, inhibit, false);
2844}
2845
2846
2847static void gen_eob(DisasContext *s)
2848{
2849 gen_eob_worker(s, false, false);
2850}
2851
2852
2853static void gen_jr(DisasContext *s)
2854{
2855 do_gen_eob_worker(s, false, false, true);
2856}
2857
2858
2859static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num)
2860{
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;
2865
2866
2867 if (!CODE64(s)) {
2868 if (ot == MO_16) {
2869 mask = 0xffff;
2870 if (TARGET_TB_PCREL && CODE32(s)) {
2871 use_goto_tb = false;
2872 }
2873 } else {
2874 mask = 0xffffffff;
2875 }
2876 }
2877 new_eip &= mask;
2878
2879 gen_update_cc_op(s);
2880 set_cc_op(s, CC_OP_DYNAMIC);
2881
2882 if (TARGET_TB_PCREL) {
2883 tcg_gen_addi_tl(cpu_eip, cpu_eip, new_pc - s->pc_save);
2884
2885
2886
2887
2888
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;
2892 }
2893 }
2894
2895 if (use_goto_tb &&
2896 translator_use_goto_tb(&s->base, new_eip + s->cs_base)) {
2897
2898 tcg_gen_goto_tb(tb_num);
2899 if (!TARGET_TB_PCREL) {
2900 tcg_gen_movi_tl(cpu_eip, new_eip);
2901 }
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);
2907 }
2908 if (s->jmp_opt) {
2909 gen_jr(s);
2910 } else {
2911 gen_eob(s);
2912 }
2913 }
2914}
2915
2916
2917static void gen_jmp_rel_csize(DisasContext *s, int diff, int tb_num)
2918{
2919
2920 gen_jmp_rel(s, CODE32(s) ? MO_32 : MO_16, diff, tb_num);
2921}
2922
2923static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2924{
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);
2927}
2928
2929static inline void gen_stq_env_A0(DisasContext *s, int offset)
2930{
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);
2933}
2934
2935static inline void gen_ldo_env_A0(DisasContext *s, int offset, bool align)
2936{
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)));
2944}
2945
2946static inline void gen_sto_env_A0(DisasContext *s, int offset, bool align)
2947{
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);
2955}
2956
2957static void gen_ldy_env_A0(DisasContext *s, int offset, bool align)
2958{
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)));
2966
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)));
2973}
2974
2975static void gen_sty_env_A0(DisasContext *s, int offset, bool align)
2976{
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);
2990}
2991
2992#include "decode-new.h"
2993#include "emit.c.inc"
2994#include "decode-new.c.inc"
2995
2996
2997
2998static bool disas_insn(DisasContext *s, CPUState *cpu)
2999{
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;
3008
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;
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
3028 s->pc = s->base.pc_next;
3029
3030
3031
3032
3033
3034 s->cc_op_dirty = orig_cc_op_dirty;
3035 s->cc_op = orig_cc_op;
3036 s->pc_save = orig_pc_save;
3037
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();
3044 }
3045
3046 prefixes = 0;
3047
3048 next_byte:
3049 s->prefix = prefixes;
3050 b = x86_ldub_code(env, s);
3051
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
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;
3103 }
3104 break;
3105#endif
3106 case 0xc5:
3107 case 0xc4:
3108 if (CODE32(s) && !VM86(s)) {
3109 int vex2 = x86_ldub_code(env, s);
3110 s->pc--;
3111
3112 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
3113
3114
3115 break;
3116 }
3117 disas_insn_new(s, cpu, b);
3118 return s->pc;
3119 }
3120 break;
3121 }
3122
3123
3124 if (CODE64(s)) {
3125
3126
3127
3128 dflag = (REX_W(s) ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
3129
3130 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
3131 } else {
3132
3133 if (CODE32(s) ^ ((prefixes & PREFIX_DATA) != 0)) {
3134 dflag = MO_32;
3135 } else {
3136 dflag = MO_16;
3137 }
3138
3139 if (CODE32(s) ^ ((prefixes & PREFIX_ADR) != 0)) {
3140 aflag = MO_32;
3141 } else {
3142 aflag = MO_16;
3143 }
3144 }
3145
3146 s->prefix = prefixes;
3147 s->aflag = aflag;
3148 s->dflag = dflag;
3149
3150
3151 switch (b) {
3152
3153
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:
3162 {
3163 int op, f, val;
3164 op = (b >> 3) & 7;
3165 f = (b >> 1) & 3;
3166
3167 ot = mo_b_d(b, dflag);
3168
3169 switch(f) {
3170 case 0:
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
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;
3187 }
3188 gen_op_mov_v_reg(s, ot, s->T1, reg);
3189 gen_op(s, op, ot, opreg);
3190 break;
3191 case 1:
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);
3203 }
3204 gen_op(s, op, ot, reg);
3205 break;
3206 case 2:
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;
3211 }
3212 }
3213 break;
3214
3215 case 0x82:
3216 if (CODE64(s))
3217 goto illegal_op;
3218
3219 case 0x80:
3220 case 0x81:
3221 case 0x83:
3222 {
3223 int val;
3224
3225 ot = mo_b_d(b, dflag);
3226
3227 modrm = x86_ldub_code(env, s);
3228 mod = (modrm >> 6) & 3;
3229 rm = (modrm & 7) | REX_B(s);
3230 op = (modrm >> 3) & 7;
3231
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;
3241 }
3242
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;
3253 }
3254 tcg_gen_movi_tl(s->T1, val);
3255 gen_op(s, op, ot, opreg);
3256 }
3257 break;
3258
3259
3260
3261 case 0x40 ... 0x47:
3262 ot = dflag;
3263 gen_inc(s, ot, OR_EAX + (b & 7), 1);
3264 break;
3265 case 0x48 ... 0x4f:
3266 ot = dflag;
3267 gen_inc(s, ot, OR_EAX + (b & 7), -1);
3268 break;
3269 case 0xf6:
3270 case 0xf7:
3271 ot = mo_b_d(b, dflag);
3272
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);
3280 }
3281 gen_lea_modrm(env, s, modrm);
3282
3283 if (!(s->prefix & PREFIX_LOCK)
3284 || op != 2) {
3285 gen_op_ld_v(s, ot, s->T0, s->A0);
3286 }
3287 } else {
3288 gen_op_mov_v_reg(s, ot, s->T0, rm);
3289 }
3290
3291 switch(op) {
3292 case 0:
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:
3299 if (s->prefix & PREFIX_LOCK) {
3300 if (mod == 3) {
3301 goto illegal_op;
3302 }
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);
3312 }
3313 }
3314 break;
3315 case 3:
3316 if (s->prefix & PREFIX_LOCK) {
3317 TCGLabel *label1;
3318 TCGv a0, t0, t1, t2;
3319
3320 if (mod == 3) {
3321 goto illegal_op;
3322 }
3323 a0 = tcg_temp_local_new();
3324 t0 = tcg_temp_local_new();
3325 label1 = gen_new_label();
3326
3327 tcg_gen_mov_tl(a0, s->A0);
3328 tcg_gen_mov_tl(t0, s->T0);
3329
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);
3339
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);
3350 }
3351 }
3352 gen_op_update_neg_cc(s);
3353 set_cc_op(s, CC_OP_SUBB + ot);
3354 break;
3355 case 4:
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
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
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
3402 }
3403 break;
3404 case 5:
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
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
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
3456 }
3457 break;
3458 case 6:
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
3475 }
3476 break;
3477 case 7:
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
3494 }
3495 break;
3496 default:
3497 goto unknown_op;
3498 }
3499 break;
3500
3501 case 0xfe:
3502 case 0xff:
3503 ot = mo_b_d(b, dflag);
3504
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;
3511 }
3512 if (CODE64(s)) {
3513 if (op == 2 || op == 4) {
3514
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
3520 ot = mo_pushpop(s, dflag);
3521 }
3522 }
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);
3529 }
3530
3531 switch(op) {
3532 case 0:
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:
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:
3547
3548 if (dflag == MO_16) {
3549 tcg_gen_ext16u_tl(s->T0, s->T0);
3550 }
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:
3557 if (mod == 3) {
3558 goto illegal_op;
3559 }
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));
3575 }
3576 s->base.is_jmp = DISAS_JUMP;
3577 break;
3578 case 4:
3579 if (dflag == MO_16) {
3580 tcg_gen_ext16u_tl(s->T0, s->T0);
3581 }
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:
3587 if (mod == 3) {
3588 goto illegal_op;
3589 }
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);
3601 }
3602 s->base.is_jmp = DISAS_JUMP;
3603 break;
3604 case 6:
3605 gen_push_v(s, s->T0);
3606 break;
3607 default:
3608 goto unknown_op;
3609 }
3610 break;
3611
3612 case 0x84:
3613 case 0x85:
3614 ot = mo_b_d(b, dflag);
3615
3616 modrm = x86_ldub_code(env, s);
3617 reg = ((modrm >> 3) & 7) | REX_R(s);
3618
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;
3624
3625 case 0xa8:
3626 case 0xa9:
3627 ot = mo_b_d(b, dflag);
3628 val = insn_get(env, s, ot);
3629
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;
3635
3636 case 0x98:
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();
3657 }
3658 break;
3659 case 0x99:
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();
3682 }
3683 break;
3684 case 0x1af:
3685 case 0x69:
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);
3703 }
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
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;
3734 }
3735 set_cc_op(s, CC_OP_MULB + ot);
3736 break;
3737 case 0x1c0:
3738 case 0x1c1:
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);
3760 }
3761 gen_op_mov_reg_v(s, ot, reg, s->T1);
3762 }
3763 gen_op_update2_cc(s);
3764 set_cc_op(s, CC_OP_ADDB + ot);
3765 break;
3766 case 0x1b0:
3767 case 0x1b1:
3768 {
3769 TCGv oldv, newv, cmpv, dest;
3770
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;
3784 }
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);
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
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);
3808
3809
3810
3811
3812
3813
3814
3815 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
3816 gen_op_st_v(s, ot, newv, s->A0);
3817 }
3818 }
3819
3820
3821
3822
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);
3832 }
3833 break;
3834 case 0x1c7:
3835 modrm = x86_ldub_code(env, s);
3836 mod = (modrm >> 6) & 3;
3837 switch ((modrm >> 3) & 7) {
3838 case 1:
3839 if (mod == 3) {
3840 goto illegal_op;
3841 }
3842#ifdef TARGET_X86_64
3843 if (dflag == MO_64) {
3844 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) {
3845 goto illegal_op;
3846 }
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);
3853 }
3854 set_cc_op(s, CC_OP_EFLAGS);
3855 break;
3856 }
3857#endif
3858 if (!(s->cpuid_features & CPUID_CX8)) {
3859 goto illegal_op;
3860 }
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);
3867 }
3868 set_cc_op(s, CC_OP_EFLAGS);
3869 break;
3870
3871 case 7:
3872 case 6:
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;
3877 }
3878 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3879 gen_io_start();
3880 s->base.is_jmp = DISAS_TOO_MANY;
3881 }
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;
3887
3888 default:
3889 goto illegal_op;
3890 }
3891 break;
3892
3893
3894
3895 case 0x50 ... 0x57:
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:
3900 ot = gen_pop_T0(s);
3901
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:
3906 if (CODE64(s))
3907 goto illegal_op;
3908 gen_pusha(s);
3909 break;
3910 case 0x61:
3911 if (CODE64(s))
3912 goto illegal_op;
3913 gen_popa(s);
3914 break;
3915 case 0x68:
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:
3926 modrm = x86_ldub_code(env, s);
3927 mod = (modrm >> 6) & 3;
3928 ot = gen_pop_T0(s);
3929 if (mod == 3) {
3930
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
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);
3940 }
3941 break;
3942 case 0xc8:
3943 {
3944 int level;
3945 val = x86_lduw_code(env, s);
3946 level = x86_ldub_code(env, s);
3947 gen_enter(s, val, level);
3948 }
3949 break;
3950 case 0xc9:
3951 gen_leave(s);
3952 break;
3953 case 0x06:
3954 case 0x0e:
3955 case 0x16:
3956 case 0x1e:
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:
3963 case 0x1a8:
3964 gen_op_movl_T0_seg(s, (b >> 3) & 7);
3965 gen_push_v(s, s->T0);
3966 break;
3967 case 0x07:
3968 case 0x17:
3969 case 0x1f:
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:
3978 case 0x1a9:
3979 ot = gen_pop_T0(s);
3980 gen_movl_seg_T0(s, (b >> 3) & 7);
3981 gen_pop_update(s, ot);
3982 break;
3983
3984
3985
3986 case 0x88:
3987 case 0x89:
3988 ot = mo_b_d(b, dflag);
3989 modrm = x86_ldub_code(env, s);
3990 reg = ((modrm >> 3) & 7) | REX_R(s);
3991
3992
3993 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
3994 break;
3995 case 0xc6:
3996 case 0xc7:
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);
4003 }
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);
4010 }
4011 break;
4012 case 0x8a:
4013 case 0x8b:
4014 ot = mo_b_d(b, dflag);
4015 modrm = x86_ldub_code(env, s);
4016 reg = ((modrm >> 3) & 7) | REX_R(s);
4017
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:
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:
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;
4039
4040 case 0x1b6:
4041 case 0x1b7:
4042 case 0x1be:
4043 case 0x1bf:
4044 {
4045 MemOp d_ot;
4046 MemOp s_ot;
4047
4048
4049 d_ot = dflag;
4050
4051 ot = (b & 1) + MO_8;
4052
4053 s_ot = b & 8 ? MO_SIGN | ot : ot;
4054
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);
4059
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;
4079 }
4080 }
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);
4086 }
4087 }
4088 break;
4089
4090 case 0x8d:
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);
4096 {
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);
4101 }
4102 break;
4103
4104 case 0xa0:
4105 case 0xa1:
4106 case 0xa2:
4107 case 0xa3:
4108 {
4109 target_ulong offset_addr;
4110
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);
4121 }
4122 }
4123 break;
4124 case 0xd7:
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:
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:
4139#ifdef TARGET_X86_64
4140 if (dflag == MO_64) {
4141 uint64_t tmp;
4142
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
4149 {
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);
4155 }
4156 break;
4157
4158 case 0x91 ... 0x97:
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:
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
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);
4184 }
4185 break;
4186 case 0xc4:
4187
4188 op = R_ES;
4189 goto do_lxx;
4190 case 0xc5:
4191
4192 op = R_DS;
4193 goto do_lxx;
4194 case 0x1b2:
4195 op = R_SS;
4196 goto do_lxx;
4197 case 0x1b4:
4198 op = R_FS;
4199 goto do_lxx;
4200 case 0x1b5:
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
4213 gen_op_ld_v(s, MO_16, s->T0, s->A0);
4214 gen_movl_seg_T0(s, op);
4215
4216 gen_op_mov_reg_v(s, ot, reg, s->T1);
4217 break;
4218
4219
4220
4221 case 0xc0:
4222 case 0xc1:
4223
4224 shift = 2;
4225 grp2:
4226 {
4227 ot = mo_b_d(b, dflag);
4228 modrm = x86_ldub_code(env, s);
4229 mod = (modrm >> 6) & 3;
4230 op = (modrm >> 3) & 7;
4231
4232 if (mod != 3) {
4233 if (shift == 2) {
4234 s->rip_offset = 1;
4235 }
4236 gen_lea_modrm(env, s, modrm);
4237 opreg = OR_TMP0;
4238 } else {
4239 opreg = (modrm & 7) | REX_B(s);
4240 }
4241
4242
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);
4248 }
4249 gen_shifti(s, op, ot, opreg, shift);
4250 }
4251 }
4252 break;
4253 case 0xd0:
4254 case 0xd1:
4255
4256 shift = 1;
4257 goto grp2;
4258 case 0xd2:
4259 case 0xd3:
4260
4261 shift = 0;
4262 goto grp2;
4263
4264 case 0x1a4:
4265 op = 0;
4266 shift = 1;
4267 goto do_shiftd;
4268 case 0x1a5:
4269 op = 0;
4270 shift = 0;
4271 goto do_shiftd;
4272 case 0x1ac:
4273 op = 1;
4274 shift = 1;
4275 goto do_shiftd;
4276 case 0x1ad:
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;
4290 }
4291 gen_op_mov_v_reg(s, ot, s->T1, reg);
4292
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]);
4299 }
4300 break;
4301
4302
4303
4304 case 0xd8 ... 0xdf:
4305 {
4306 bool update_fip = true;
4307
4308 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4309
4310
4311 gen_exception(s, EXCP07_PREX);
4312 break;
4313 }
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
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;
4324
4325 tcg_gen_mov_tl(last_addr, ea);
4326 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
4327
4328 switch (op) {
4329 case 0x00 ... 0x07:
4330 case 0x10 ... 0x17:
4331 case 0x20 ... 0x27:
4332 case 0x30 ... 0x37:
4333 {
4334 int op1;
4335 op1 = op & 7;
4336
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;
4359 }
4360
4361 gen_helper_fp_arith_ST0_FT0(op1);
4362 if (op1 == 3) {
4363
4364 gen_helper_fpop(cpu_env);
4365 }
4366 }
4367 break;
4368 case 0x08:
4369 case 0x0a:
4370 case 0x0b:
4371 case 0x18 ... 0x1b:
4372 case 0x28 ... 0x2b:
4373 case 0x38 ... 0x3b:
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;
4398 }
4399 break;
4400 case 1:
4401
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;
4419 }
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;
4445 }
4446 if ((op & 7) == 3) {
4447 gen_helper_fpop(cpu_env);
4448 }
4449 break;
4450 }
4451 break;
4452 case 0x0c:
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:
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:
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:
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:
4475 gen_helper_fldt_ST0(cpu_env, s->A0);
4476 break;
4477 case 0x1f:
4478 gen_helper_fstt_ST0(cpu_env, s->A0);
4479 gen_helper_fpop(cpu_env);
4480 break;
4481 case 0x2c:
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:
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:
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:
4498 gen_helper_fbld_ST0(cpu_env, s->A0);
4499 break;
4500 case 0x3e:
4501 gen_helper_fbst_ST0(cpu_env, s->A0);
4502 gen_helper_fpop(cpu_env);
4503 break;
4504 case 0x3d:
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:
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;
4517 }
4518
4519 if (update_fdp) {
4520 int last_seg = s->override >= 0 ? s->override : a.def_seg;
4521
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));
4529 }
4530 tcg_temp_free(last_addr);
4531 } else {
4532
4533 opreg = rm;
4534
4535 switch (op) {
4536 case 0x08:
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:
4542 case 0x29:
4543 case 0x39:
4544 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
4545 break;
4546 case 0x0a:
4547 switch (rm) {
4548 case 0:
4549
4550 gen_helper_fwait(cpu_env);
4551 update_fip = false;
4552 break;
4553 default:
4554 goto unknown_op;
4555 }
4556 break;
4557 case 0x0c:
4558 switch (rm) {
4559 case 0:
4560 gen_helper_fchs_ST0(cpu_env);
4561 break;
4562 case 1:
4563 gen_helper_fabs_ST0(cpu_env);
4564 break;
4565 case 4:
4566 gen_helper_fldz_FT0(cpu_env);
4567 gen_helper_fcom_ST0_FT0(cpu_env);
4568 break;
4569 case 5:
4570 gen_helper_fxam_ST0(cpu_env);
4571 break;
4572 default:
4573 goto unknown_op;
4574 }
4575 break;
4576 case 0x0d:
4577 {
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;
4609 }
4610 }
4611 break;
4612 case 0x0e:
4613 switch (rm) {
4614 case 0:
4615 gen_helper_f2xm1(cpu_env);
4616 break;
4617 case 1:
4618 gen_helper_fyl2x(cpu_env);
4619 break;
4620 case 2:
4621 gen_helper_fptan(cpu_env);
4622 break;
4623 case 3:
4624 gen_helper_fpatan(cpu_env);
4625 break;
4626 case 4:
4627 gen_helper_fxtract(cpu_env);
4628 break;
4629 case 5:
4630 gen_helper_fprem1(cpu_env);
4631 break;
4632 case 6:
4633 gen_helper_fdecstp(cpu_env);
4634 break;
4635 default:
4636 case 7:
4637 gen_helper_fincstp(cpu_env);
4638 break;
4639 }
4640 break;
4641 case 0x0f:
4642 switch (rm) {
4643 case 0:
4644 gen_helper_fprem(cpu_env);
4645 break;
4646 case 1:
4647 gen_helper_fyl2xp1(cpu_env);
4648 break;
4649 case 2:
4650 gen_helper_fsqrt(cpu_env);
4651 break;
4652 case 3:
4653 gen_helper_fsincos(cpu_env);
4654 break;
4655 case 5:
4656 gen_helper_fscale(cpu_env);
4657 break;
4658 case 4:
4659 gen_helper_frndint(cpu_env);
4660 break;
4661 case 6:
4662 gen_helper_fsin(cpu_env);
4663 break;
4664 default:
4665 case 7:
4666 gen_helper_fcos(cpu_env);
4667 break;
4668 }
4669 break;
4670 case 0x00: case 0x01: case 0x04 ... 0x07:
4671 case 0x20: case 0x21: case 0x24 ... 0x27:
4672 case 0x30: case 0x31: case 0x34 ... 0x37:
4673 {
4674 int op1;
4675
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);
4681 }
4682 } else {
4683 gen_helper_fmov_FT0_STN(cpu_env,
4684 tcg_const_i32(opreg));
4685 gen_helper_fp_arith_ST0_FT0(op1);
4686 }
4687 }
4688 break;
4689 case 0x02:
4690 case 0x22:
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:
4695 case 0x23:
4696 case 0x32:
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:
4702 switch (rm) {
4703 case 1:
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;
4711 }
4712 break;
4713 case 0x1c:
4714 switch (rm) {
4715 case 0:
4716 break;
4717 case 1:
4718 break;
4719 case 2:
4720 gen_helper_fclex(cpu_env);
4721 update_fip = false;
4722 break;
4723 case 3:
4724 gen_helper_fninit(cpu_env);
4725 update_fip = false;
4726 break;
4727 case 4:
4728 break;
4729 default:
4730 goto unknown_op;
4731 }
4732 break;
4733 case 0x1d:
4734 if (!(s->cpuid_features & CPUID_CMOV)) {
4735 goto illegal_op;
4736 }
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:
4743 if (!(s->cpuid_features & CPUID_CMOV)) {
4744 goto illegal_op;
4745 }
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:
4752 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
4753 break;
4754 case 0x2a:
4755 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
4756 break;
4757 case 0x2b:
4758 case 0x0b:
4759 case 0x3a:
4760 case 0x3b:
4761 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
4762 gen_helper_fpop(cpu_env);
4763 break;
4764 case 0x2c:
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:
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:
4774 switch (rm) {
4775 case 1:
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;
4783 }
4784 break;
4785 case 0x38:
4786 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
4787 gen_helper_fpop(cpu_env);
4788 break;
4789 case 0x3c:
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;
4798 }
4799 break;
4800 case 0x3d:
4801 if (!(s->cpuid_features & CPUID_CMOV)) {
4802 goto illegal_op;
4803 }
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:
4811 if (!(s->cpuid_features & CPUID_CMOV)) {
4812 goto illegal_op;
4813 }
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:
4821 case 0x18 ... 0x1b:
4822 {
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),
4830 };
4831
4832 if (!(s->cpuid_features & CPUID_CMOV)) {
4833 goto illegal_op;
4834 }
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);
4840 }
4841 break;
4842 default:
4843 goto unknown_op;
4844 }
4845 }
4846
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));
4854 }
4855 }
4856 break;
4857
4858
4859
4860 case 0xa4:
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);
4867 }
4868 break;
4869
4870 case 0xaa:
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);
4877 }
4878 break;
4879 case 0xac:
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);
4886 }
4887 break;
4888 case 0xae:
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);
4897 }
4898 break;
4899
4900 case 0xa6:
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);
4909 }
4910 break;
4911 case 0x6c:
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;
4919 }
4920 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4921 gen_io_start();
4922 s->base.is_jmp = DISAS_TOO_MANY;
4923 }
4924 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4925 gen_repz_ins(s, ot);
4926 } else {
4927 gen_ins(s, ot);
4928 }
4929 break;
4930 case 0x6e:
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;
4937 }
4938 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4939 gen_io_start();
4940 s->base.is_jmp = DISAS_TOO_MANY;
4941 }
4942 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4943 gen_repz_outs(s, ot);
4944 } else {
4945 gen_outs(s, ot);
4946 }
4947 break;
4948
4949
4950
4951
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;
4959 }
4960 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4961 gen_io_start();
4962 s->base.is_jmp = DISAS_TOO_MANY;
4963 }
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;
4975 }
4976 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4977 gen_io_start();
4978 s->base.is_jmp = DISAS_TOO_MANY;
4979 }
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;
4992 }
4993 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4994 gen_io_start();
4995 s->base.is_jmp = DISAS_TOO_MANY;
4996 }
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;
5008 }
5009 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5010 gen_io_start();
5011 s->base.is_jmp = DISAS_TOO_MANY;
5012 }
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;
5018
5019
5020
5021 case 0xc2:
5022 val = x86_ldsw_code(env, s);
5023 ot = gen_pop_T0(s);
5024 gen_stack_update(s, val + (1 << ot));
5025
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:
5031 ot = gen_pop_T0(s);
5032 gen_pop_update(s, ot);
5033
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:
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
5049 gen_op_ld_v(s, dflag, s->T0, s->A0);
5050
5051
5052 gen_op_jmp_v(s, s->T0);
5053
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
5058 gen_stack_update(s, val + (2 << dflag));
5059 }
5060 s->base.is_jmp = DISAS_EOB_ONLY;
5061 break;
5062 case 0xcb:
5063 val = 0;
5064 goto do_lret;
5065 case 0xcf:
5066 gen_svm_check_intercept(s, SVM_EXIT_IRET);
5067 if (!PE(s) || VM86(s)) {
5068
5069 if (!check_vm86_iopl(s)) {
5070 break;
5071 }
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));
5076 }
5077 set_cc_op(s, CC_OP_EFLAGS);
5078 s->base.is_jmp = DISAS_EOB_ONLY;
5079 break;
5080 case 0xe8:
5081 {
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);
5088 }
5089 break;
5090 case 0x9a:
5091 {
5092 unsigned int selector, offset;
5093
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);
5099
5100 tcg_gen_movi_tl(s->T0, selector);
5101 tcg_gen_movi_tl(s->T1, offset);
5102 }
5103 goto do_lcall;
5104 case 0xe9:
5105 {
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);
5111 }
5112 break;
5113 case 0xea:
5114 {
5115 unsigned int selector, offset;
5116
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);
5122
5123 tcg_gen_movi_tl(s->T0, selector);
5124 tcg_gen_movi_tl(s->T1, offset);
5125 }
5126 goto do_ljmp;
5127 case 0xeb:
5128 {
5129 int diff = (int8_t)insn_get(env, s, MO_8);
5130 gen_jmp_rel(s, dflag, diff, 0);
5131 }
5132 break;
5133 case 0x70 ... 0x7f:
5134 {
5135 int diff = (int8_t)insn_get(env, s, MO_8);
5136 gen_bnd_jmp(s);
5137 gen_jcc(s, b, diff);
5138 }
5139 break;
5140 case 0x180 ... 0x18f:
5141 {
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);
5147 }
5148 break;
5149
5150 case 0x190 ... 0x19f:
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:
5156 if (!(s->cpuid_features & CPUID_CMOV)) {
5157 goto illegal_op;
5158 }
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;
5164
5165
5166
5167 case 0x9c:
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);
5173 }
5174 break;
5175 case 0x9d:
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));
5192 }
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));
5210 }
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));
5221 }
5222 }
5223 }
5224 gen_pop_update(s, ot);
5225 set_cc_op(s, CC_OP_EFLAGS);
5226
5227 s->base.is_jmp = DISAS_EOB_NEXT;
5228 }
5229 break;
5230 case 0x9e:
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:
5240 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
5241 goto illegal_op;
5242 gen_compute_eflags(s);
5243
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:
5248 gen_compute_eflags(s);
5249 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
5250 break;
5251 case 0xf8:
5252 gen_compute_eflags(s);
5253 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
5254 break;
5255 case 0xf9:
5256 gen_compute_eflags(s);
5257 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
5258 break;
5259 case 0xfc:
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:
5264 tcg_gen_movi_i32(s->tmp2_i32, -1);
5265 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
5266 break;
5267
5268
5269
5270 case 0x1ba:
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);
5281 }
5282 } else {
5283 gen_op_mov_v_reg(s, ot, s->T0, rm);
5284 }
5285
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:
5293 op = 0;
5294 goto do_btx;
5295 case 0x1ab:
5296 op = 1;
5297 goto do_btx;
5298 case 0x1b3:
5299 op = 2;
5300 goto do_btx;
5301 case 0x1bb:
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
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);
5320 }
5321 } else {
5322 gen_op_mov_v_reg(s, ot, s->T0, rm);
5323 }
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:
5331
5332
5333 gen_op_ld_v(s, ot, s->T0, s->A0);
5334 break;
5335 case 1:
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:
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:
5346 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0,
5347 s->mem_index, ot | MO_LE);
5348 break;
5349 }
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:
5355
5356 break;
5357 case 1:
5358 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
5359 break;
5360 case 2:
5361 tcg_gen_andc_tl(s->T0, s->T0, s->tmp0);
5362 break;
5363 default:
5364 case 3:
5365 tcg_gen_xor_tl(s->T0, s->T0, s->tmp0);
5366 break;
5367 }
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);
5373 }
5374 }
5375 }
5376
5377
5378
5379
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
5393
5394
5395
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
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;
5405 }
5406 break;
5407 case 0x1bc:
5408 case 0x1bd:
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);
5414
5415
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
5422 tcg_gen_mov_tl(cpu_cc_src, s->T0);
5423 if (b & 1) {
5424
5425
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
5430 tcg_gen_ctzi_tl(s->T0, s->T0, size);
5431 }
5432
5433 gen_op_update1_cc(s);
5434 set_cc_op(s, CC_OP_BMILGB + ot);
5435 } else {
5436
5437
5438 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5439 set_cc_op(s, CC_OP_LOGICB + ot);
5440
5441
5442
5443
5444
5445 if (b & 1) {
5446
5447
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]);
5453 }
5454 }
5455 gen_op_mov_reg_v(s, ot, reg, s->T0);
5456 break;
5457
5458
5459 case 0x27:
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:
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:
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:
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:
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);
5496 }
5497 break;
5498 case 0xd5:
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
5507 case 0x90:
5508
5509 if (prefixes & PREFIX_LOCK) {
5510 goto illegal_op;
5511 }
5512
5513 if (REX_B(s)) {
5514 goto do_xchg_reg_eax;
5515 }
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;
5521 }
5522 break;
5523 case 0x9b:
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);
5529 }
5530 break;
5531 case 0xcc:
5532 gen_interrupt(s, EXCP03_INT3);
5533 break;
5534 case 0xcd:
5535 val = x86_ldub_code(env, s);
5536 if (check_vm86_iopl(s)) {
5537 gen_interrupt(s, val);
5538 }
5539 break;
5540 case 0xce:
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:
5549 gen_svm_check_intercept(s, SVM_EXIT_ICEBP);
5550 gen_debug(s);
5551 break;
5552#endif
5553 case 0xfa:
5554 if (check_iopl(s)) {
5555 gen_reset_eflags(s, IF_MASK);
5556 }
5557 break;
5558 case 0xfb:
5559 if (check_iopl(s)) {
5560 gen_set_eflags(s, IF_MASK);
5561
5562 gen_update_eip_next(s);
5563 gen_eob_inhibit_irq(s, true);
5564 }
5565 break;
5566 case 0x62:
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);
5582 }
5583 break;
5584 case 0x1c8 ... 0x1cf:
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;
5590 }
5591#endif
5592 tcg_gen_bswap32_tl(cpu_regs[reg], cpu_regs[reg], TCG_BSWAP_OZ);
5593 break;
5594 case 0xd6:
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:
5602 case 0xe1:
5603 case 0xe2:
5604 case 0xe3:
5605 {
5606 TCGLabel *l1, *l2;
5607 int diff = (int8_t)insn_get(env, s, MO_8);
5608
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:
5615 case 1:
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:
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:
5626 gen_op_jz_ecx(s, l1);
5627 break;
5628 }
5629
5630 gen_set_label(l2);
5631 gen_jmp_rel_csize(s, 0, 1);
5632
5633 gen_set_label(l1);
5634 gen_jmp_rel(s, dflag, diff, 0);
5635 }
5636 break;
5637 case 0x130:
5638 case 0x132:
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;
5647 }
5648 }
5649 break;
5650 case 0x131:
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;
5656 }
5657 gen_helper_rdtsc(cpu_env);
5658 break;
5659 case 0x133:
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:
5666
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;
5674 }
5675 break;
5676 case 0x135:
5677
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;
5685 }
5686 break;
5687#ifdef TARGET_X86_64
5688 case 0x105:
5689
5690 gen_update_cc_op(s);
5691 gen_update_eip_cur(s);
5692 gen_helper_syscall(cpu_env, cur_insn_len_i32(s));
5693
5694
5695
5696 gen_eob_worker(s, false, true);
5697 break;
5698 case 0x107:
5699 if (!PE(s)) {
5700 gen_exception_gpf(s);
5701 } else {
5702 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
5703
5704 if (LMA(s)) {
5705 set_cc_op(s, CC_OP_EFLAGS);
5706 }
5707
5708
5709
5710
5711 gen_eob_worker(s, false, true);
5712 }
5713 break;
5714#endif
5715 case 0x1a2:
5716 gen_update_cc_op(s);
5717 gen_update_eip_cur(s);
5718 gen_helper_cpuid(cpu_env);
5719 break;
5720 case 0xf4:
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;
5726 }
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:
5734 if (!PE(s) || VM86(s))
5735 goto illegal_op;
5736 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
5737 break;
5738 }
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:
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);
5753 }
5754 break;
5755 case 1:
5756 if (!PE(s) || VM86(s))
5757 goto illegal_op;
5758 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
5759 break;
5760 }
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:
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);
5775 }
5776 break;
5777 case 4:
5778 case 5:
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);
5787 }
5788 set_cc_op(s, CC_OP_EFLAGS);
5789 break;
5790 default:
5791 goto unknown_op;
5792 }
5793 break;
5794
5795 case 0x101:
5796 modrm = x86_ldub_code(env, s);
5797 switch (modrm) {
5798 CASE_MODRM_MEM_OP(0):
5799 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
5800 break;
5801 }
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);
5811 }
5812 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
5813 break;
5814
5815 case 0xc8:
5816 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
5817 goto illegal_op;
5818 }
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;
5826
5827 case 0xc9:
5828 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) {
5829 goto illegal_op;
5830 }
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;
5836
5837 case 0xca:
5838 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
5839 || CPL(s) != 0) {
5840 goto illegal_op;
5841 }
5842 gen_reset_eflags(s, AC_MASK);
5843 s->base.is_jmp = DISAS_EOB_NEXT;
5844 break;
5845
5846 case 0xcb:
5847 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
5848 || CPL(s) != 0) {
5849 goto illegal_op;
5850 }
5851 gen_set_eflags(s, AC_MASK);
5852 s->base.is_jmp = DISAS_EOB_NEXT;
5853 break;
5854
5855 CASE_MODRM_MEM_OP(1):
5856 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
5857 break;
5858 }
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);
5867 }
5868 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
5869 break;
5870
5871 case 0xd0:
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;
5876 }
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;
5881
5882 case 0xd1:
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;
5887 }
5888 if (!check_cpl0(s)) {
5889 break;
5890 }
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
5896 s->base.is_jmp = DISAS_EOB_NEXT;
5897 break;
5898
5899 case 0xd8:
5900 if (!SVME(s) || !PE(s)) {
5901 goto illegal_op;
5902 }
5903 if (!check_cpl0(s)) {
5904 break;
5905 }
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;
5913
5914 case 0xd9:
5915 if (!SVME(s)) {
5916 goto illegal_op;
5917 }
5918 gen_update_cc_op(s);
5919 gen_update_eip_cur(s);
5920 gen_helper_vmmcall(cpu_env);
5921 break;
5922
5923 case 0xda:
5924 if (!SVME(s) || !PE(s)) {
5925 goto illegal_op;
5926 }
5927 if (!check_cpl0(s)) {
5928 break;
5929 }
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;
5934
5935 case 0xdb:
5936 if (!SVME(s) || !PE(s)) {
5937 goto illegal_op;
5938 }
5939 if (!check_cpl0(s)) {
5940 break;
5941 }
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;
5946
5947 case 0xdc:
5948 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
5949 || !PE(s)) {
5950 goto illegal_op;
5951 }
5952 if (!check_cpl0(s)) {
5953 break;
5954 }
5955 gen_update_cc_op(s);
5956 gen_helper_stgi(cpu_env);
5957 s->base.is_jmp = DISAS_EOB_NEXT;
5958 break;
5959
5960 case 0xdd:
5961 if (!SVME(s) || !PE(s)) {
5962 goto illegal_op;
5963 }
5964 if (!check_cpl0(s)) {
5965 break;
5966 }
5967 gen_update_cc_op(s);
5968 gen_update_eip_cur(s);
5969 gen_helper_clgi(cpu_env);
5970 break;
5971
5972 case 0xde:
5973 if ((!SVME(s) && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
5974 || !PE(s)) {
5975 goto illegal_op;
5976 }
5977 gen_svm_check_intercept(s, SVM_EXIT_SKINIT);
5978
5979 goto illegal_op;
5980
5981 case 0xdf:
5982 if (!SVME(s) || !PE(s)) {
5983 goto illegal_op;
5984 }
5985 if (!check_cpl0(s)) {
5986 break;
5987 }
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]);
5993 }
5994 gen_helper_flush_page(cpu_env, s->A0);
5995 s->base.is_jmp = DISAS_EOB_NEXT;
5996 break;
5997
5998 CASE_MODRM_MEM_OP(2):
5999 if (!check_cpl0(s)) {
6000 break;
6001 }
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);
6009 }
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;
6013
6014 CASE_MODRM_MEM_OP(3):
6015 if (!check_cpl0(s)) {
6016 break;
6017 }
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);
6025 }
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;
6029
6030 CASE_MODRM_OP(4):
6031 if (s->flags & HF_UMIP_MASK && !check_cpl0(s)) {
6032 break;
6033 }
6034 gen_svm_check_intercept(s, SVM_EXIT_READ_CR0);
6035 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
6036
6037
6038
6039
6040
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:
6046 if (prefixes & PREFIX_LOCK) {
6047 goto illegal_op;
6048 }
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:
6054 if (prefixes & PREFIX_LOCK) {
6055 goto illegal_op;
6056 }
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;
6062
6063 CASE_MODRM_OP(6):
6064 if (!check_cpl0(s)) {
6065 break;
6066 }
6067 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
6068 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
6069
6070
6071
6072
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;
6080
6081 CASE_MODRM_MEM_OP(7):
6082 if (!check_cpl0(s)) {
6083 break;
6084 }
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;
6090
6091 case 0xf8:
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));
6100 }
6101 break;
6102 }
6103#endif
6104 goto illegal_op;
6105
6106 case 0xf9:
6107 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
6108 goto illegal_op;
6109 }
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;
6115 }
6116 gen_helper_rdtscp(cpu_env);
6117 break;
6118
6119 default:
6120 goto unknown_op;
6121 }
6122 break;
6123
6124 case 0x108:
6125 case 0x109:
6126 if (check_cpl0(s)) {
6127 gen_svm_check_intercept(s, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
6128
6129 }
6130 break;
6131 case 0x63:
6132#ifdef TARGET_X86_64
6133 if (CODE64(s)) {
6134 int d_ot;
6135
6136 d_ot = dflag;
6137
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);
6142
6143 if (mod == 3) {
6144 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
6145
6146 if (d_ot == MO_64) {
6147 tcg_gen_ext32s_tl(s->T0, s->T0);
6148 }
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);
6154 }
6155 } else
6156#endif
6157 {
6158 TCGLabel *label1;
6159 TCGv t0, t1, t2, a0;
6160
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;
6179 }
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);
6195 }
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);
6202 }
6203 break;
6204 case 0x102:
6205 case 0x103:
6206 {
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);
6221 }
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);
6229 }
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:
6237 case 1:
6238 case 2:
6239 case 3:
6240 if (mod == 3)
6241 goto illegal_op;
6242 gen_nop_modrm(env, s, modrm);
6243
6244 break;
6245 default:
6246 gen_nop_modrm(env, s, modrm);
6247 break;
6248 }
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
6257 if (reg >= 4
6258 || (prefixes & PREFIX_LOCK)
6259 || s->aflag == MO_16) {
6260 goto illegal_op;
6261 }
6262 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
6263 } else if (prefixes & PREFIX_REPNZ) {
6264
6265 if (reg >= 4
6266 || (prefixes & PREFIX_LOCK)
6267 || s->aflag == MO_16) {
6268 goto illegal_op;
6269 }
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
6276 if (reg >= 4 || s->aflag == MO_16) {
6277 goto illegal_op;
6278 }
6279 if (mod == 3) {
6280 int reg2 = (modrm & 7) | REX_B(s);
6281 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
6282 goto illegal_op;
6283 }
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]);
6287 }
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);
6302 }
6303
6304 gen_set_hflag(s, HF_MPX_IU_MASK);
6305 }
6306 } else if (mod != 3) {
6307
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;
6314 }
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);
6319 }
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);
6325 }
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);
6334 }
6335 gen_set_hflag(s, HF_MPX_IU_MASK);
6336 }
6337 }
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
6347 if (reg >= 4
6348 || (prefixes & PREFIX_LOCK)
6349 || s->aflag == MO_16) {
6350 goto illegal_op;
6351 }
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]);
6357 }
6358 } else if (a.base == -1) {
6359
6360 tcg_gen_movi_i64(cpu_bndl[reg], 0);
6361 } else {
6362
6363 goto illegal_op;
6364 }
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);
6368 }
6369 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
6370
6371 gen_set_hflag(s, HF_MPX_IU_MASK);
6372 break;
6373 } else if (prefixes & PREFIX_REPNZ) {
6374
6375 if (reg >= 4
6376 || (prefixes & PREFIX_LOCK)
6377 || s->aflag == MO_16) {
6378 goto illegal_op;
6379 }
6380 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
6381 } else if (prefixes & PREFIX_DATA) {
6382
6383 if (reg >= 4 || s->aflag == MO_16) {
6384 goto illegal_op;
6385 }
6386 if (mod == 3) {
6387 int reg2 = (modrm & 7) | REX_B(s);
6388 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
6389 goto illegal_op;
6390 }
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]);
6394 }
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);
6409 }
6410 }
6411 } else if (mod != 3) {
6412
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;
6419 }
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);
6424 }
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);
6430 }
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]);
6437 }
6438 }
6439 }
6440 gen_nop_modrm(env, s, modrm);
6441 break;
6442 case 0x119: case 0x11c ... 0x11f:
6443 modrm = x86_ldub_code(env, s);
6444 gen_nop_modrm(env, s, modrm);
6445 break;
6446
6447 case 0x120:
6448 case 0x122:
6449 if (!check_cpl0(s)) {
6450 break;
6451 }
6452 modrm = x86_ldub_code(env, s);
6453
6454
6455
6456
6457
6458
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;
6466 }
6467 break;
6468 case 2:
6469 case 3:
6470 case 4:
6471 case 8:
6472 break;
6473 default:
6474 goto unknown_op;
6475 }
6476 ot = (CODE64(s) ? MO_64 : MO_32);
6477
6478 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6479 gen_io_start();
6480 s->base.is_jmp = DISAS_TOO_MANY;
6481 }
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);
6491 }
6492 break;
6493
6494 case 0x121:
6495 case 0x123:
6496 if (check_cpl0(s)) {
6497 modrm = x86_ldub_code(env, s);
6498
6499
6500
6501
6502
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;
6511 }
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);
6523 }
6524 }
6525 break;
6526 case 0x106:
6527 if (check_cpl0(s)) {
6528 gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
6529 gen_helper_clts(cpu_env);
6530
6531 s->base.is_jmp = DISAS_EOB_NEXT;
6532 }
6533 break;
6534
6535 case 0x1c3:
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
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):
6551 if (!(s->cpuid_features & CPUID_FXSR)
6552 || (prefixes & PREFIX_LOCK)) {
6553 goto illegal_op;
6554 }
6555 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
6556 gen_exception(s, EXCP07_PREX);
6557 break;
6558 }
6559 gen_lea_modrm(env, s, modrm);
6560 gen_helper_fxsave(cpu_env, s->A0);
6561 break;
6562
6563 CASE_MODRM_MEM_OP(1):
6564 if (!(s->cpuid_features & CPUID_FXSR)
6565 || (prefixes & PREFIX_LOCK)) {
6566 goto illegal_op;
6567 }
6568 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
6569 gen_exception(s, EXCP07_PREX);
6570 break;
6571 }
6572 gen_lea_modrm(env, s, modrm);
6573 gen_helper_fxrstor(cpu_env, s->A0);
6574 break;
6575
6576 CASE_MODRM_MEM_OP(2):
6577 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
6578 goto illegal_op;
6579 }
6580 if (s->flags & HF_TS_MASK) {
6581 gen_exception(s, EXCP07_PREX);
6582 break;
6583 }
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;
6588
6589 CASE_MODRM_MEM_OP(3):
6590 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
6591 goto illegal_op;
6592 }
6593 if (s->flags & HF_TS_MASK) {
6594 gen_exception(s, EXCP07_PREX);
6595 break;
6596 }
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;
6602
6603 CASE_MODRM_MEM_OP(4):
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;
6608 }
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;
6614
6615 CASE_MODRM_MEM_OP(5):
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;
6620 }
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
6626
6627 s->base.is_jmp = DISAS_EOB_NEXT;
6628 break;
6629
6630 CASE_MODRM_MEM_OP(6):
6631 if (prefixes & PREFIX_LOCK) {
6632 goto illegal_op;
6633 }
6634 if (prefixes & PREFIX_DATA) {
6635
6636 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
6637 goto illegal_op;
6638 }
6639 gen_nop_modrm(env, s, modrm);
6640 } else {
6641
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;
6646 }
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);
6651 }
6652 break;
6653
6654 CASE_MODRM_MEM_OP(7):
6655 if (prefixes & PREFIX_LOCK) {
6656 goto illegal_op;
6657 }
6658 if (prefixes & PREFIX_DATA) {
6659
6660 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
6661 goto illegal_op;
6662 }
6663 } else {
6664
6665 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
6666 || !(s->cpuid_features & CPUID_CLFLUSH)) {
6667 goto illegal_op;
6668 }
6669 }
6670 gen_nop_modrm(env, s, modrm);
6671 break;
6672
6673 case 0xc0 ... 0xc7:
6674 case 0xc8 ... 0xcf:
6675 case 0xd0 ... 0xd7:
6676 case 0xd8 ... 0xdf:
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;
6682
6683
6684 tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
6685 gen_helper_cr4_testbit(cpu_env, s->tmp2_i32);
6686
6687 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
6688 treg = cpu_regs[(modrm & 7) | REX_B(s)];
6689
6690 if (modrm & 0x10) {
6691
6692 dst = base, src = treg;
6693 } else {
6694
6695 dst = treg, src = base;
6696 }
6697
6698 if (s->dflag == MO_32) {
6699 tcg_gen_ext32u_tl(dst, src);
6700 } else {
6701 tcg_gen_mov_tl(dst, src);
6702 }
6703 break;
6704 }
6705 goto unknown_op;
6706
6707 case 0xf8:
6708 if (prefixes & PREFIX_DATA) {
6709
6710 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
6711 || (prefixes & PREFIX_LOCK)) {
6712 goto illegal_op;
6713 }
6714 break;
6715 }
6716
6717 case 0xf9 ... 0xff:
6718 if (!(s->cpuid_features & CPUID_SSE)
6719 || (prefixes & PREFIX_LOCK)) {
6720 goto illegal_op;
6721 }
6722 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
6723 break;
6724 case 0xe8 ... 0xef:
6725 if (!(s->cpuid_features & CPUID_SSE)
6726 || (prefixes & PREFIX_LOCK)) {
6727 goto illegal_op;
6728 }
6729 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
6730 break;
6731 case 0xf0 ... 0xf7:
6732 if (!(s->cpuid_features & CPUID_SSE2)
6733 || (prefixes & PREFIX_LOCK)) {
6734 goto illegal_op;
6735 }
6736 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
6737 break;
6738
6739 default:
6740 goto unknown_op;
6741 }
6742 break;
6743
6744 case 0x10d:
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:
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
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
6763 s->base.is_jmp = DISAS_EOB_ONLY;
6764 break;
6765 case 0x1b8:
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;
6771
6772 modrm = x86_ldub_code(env, s);
6773 reg = ((modrm >> 3) & 7) | REX_R(s);
6774
6775 if (s->prefix & PREFIX_DATA) {
6776 ot = MO_16;
6777 } else {
6778 ot = mo_64_32(dflag);
6779 }
6780
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);
6786
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;
6801 }
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;
6809}
6810
6811void tcg_x86_init(void)
6812{
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
6841 };
6842 static const char eip_name[] = {
6843#ifdef TARGET_X86_64
6844 "rip"
6845#else
6846 "eip"
6847#endif
6848 };
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",
6856 };
6857 static const char bnd_regl_names[4][8] = {
6858 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
6859 };
6860 static const char bnd_regu_names[4][8] = {
6861 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
6862 };
6863 int i;
6864
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);
6874
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]);
6879 }
6880
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]);
6886 }
6887
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]);
6897 }
6898}
6899
6900static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
6901{
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;
6908
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
6916
6917
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));
6929
6930 dc->cc_op = CC_OP_DYNAMIC;
6931 dc->cc_op_dirty = false;
6932 dc->popl_esp_hack = 0;
6933
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)));
6947
6948
6949
6950
6951
6952 dc->repz_opt = !dc->jmp_opt && !(cflags & CF_USE_ICOUNT);
6953
6954 dc->T0 = tcg_temp_new();
6955 dc->T1 = tcg_temp_new();
6956 dc->A0 = tcg_temp_new();
6957
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();
6964}
6965
6966static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
6967{
6968}
6969
6970static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
6971{
6972 DisasContext *dc = container_of(dcbase, DisasContext, base);
6973 target_ulong pc_arg = dc->base.pc_next;
6974
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;
6979 }
6980 tcg_gen_insn_start(pc_arg, dc->cc_op);
6981}
6982
6983static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
6984{
6985 DisasContext *dc = container_of(dcbase, DisasContext, base);
6986
6987#ifdef TARGET_VSYSCALL_PAGE
6988
6989
6990
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;
6995 }
6996#endif
6997
6998 if (disas_insn(dc, cpu)) {
6999 target_ulong pc_next = dc->pc;
7000 dc->base.pc_next = pc_next;
7001
7002 if (dc->base.is_jmp == DISAS_NEXT) {
7003 if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
7004
7005
7006
7007
7008
7009
7010
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;
7014 }
7015 }
7016 }
7017}
7018
7019static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
7020{
7021 DisasContext *dc = container_of(dcbase, DisasContext, base);
7022
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
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();
7047 }
7048}
7049
7050static void i386_tr_disas_log(const DisasContextBase *dcbase,
7051 CPUState *cpu, FILE *logfile)
7052{
7053 DisasContext *dc = container_of(dcbase, DisasContext, base);
7054
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);
7057}
7058
7059static 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,
7066};
7067
7068
7069void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
7070 target_ulong pc, void *host_pc)
7071{
7072 DisasContext dc;
7073
7074 translator_loop(cpu, tb, max_insns, pc, host_pc, &i386_tr_ops, &dc.base);
7075}
7076