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-op.h"
26#include "exec/cpu_ldst.h"
27#include "exec/translator.h"
28
29#include "exec/helper-proto.h"
30#include "exec/helper-gen.h"
31
32#include "trace-tcg.h"
33#include "exec/log.h"
34
35#define PREFIX_REPZ 0x01
36#define PREFIX_REPNZ 0x02
37#define PREFIX_LOCK 0x04
38#define PREFIX_DATA 0x08
39#define PREFIX_ADR 0x10
40#define PREFIX_VEX 0x20
41
42#ifdef TARGET_X86_64
43#define CODE64(s) ((s)->code64)
44#define REX_X(s) ((s)->rex_x)
45#define REX_B(s) ((s)->rex_b)
46#else
47#define CODE64(s) 0
48#define REX_X(s) 0
49#define REX_B(s) 0
50#endif
51
52#ifdef TARGET_X86_64
53# define ctztl ctz64
54# define clztl clz64
55#else
56# define ctztl ctz32
57# define clztl clz32
58#endif
59
60
61#define CASE_MODRM_MEM_OP(OP) \
62 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
63 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
64 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
65
66#define CASE_MODRM_OP(OP) \
67 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
68 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
69 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
70 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
71
72
73
74
75static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
76static TCGv_i32 cpu_cc_op;
77static TCGv cpu_regs[CPU_NB_REGS];
78static TCGv cpu_seg_base[6];
79static TCGv_i64 cpu_bndl[4];
80static TCGv_i64 cpu_bndu[4];
81
82#include "exec/gen-icount.h"
83
84typedef struct DisasContext {
85 DisasContextBase base;
86
87
88 int override;
89 int prefix;
90 MemOp aflag;
91 MemOp dflag;
92 target_ulong pc_start;
93 target_ulong pc;
94
95 target_ulong cs_base;
96 int pe;
97 int code32;
98#ifdef TARGET_X86_64
99 int lma;
100 int code64;
101 int rex_x, rex_b;
102#endif
103 int vex_l;
104 int vex_v;
105 int ss32;
106 CCOp cc_op;
107 bool cc_op_dirty;
108#ifdef TARGET_X86_64
109 bool x86_64_hregs;
110#endif
111 int addseg;
112 int f_st;
113 int vm86;
114 int cpl;
115 int iopl;
116 int tf;
117 int jmp_opt;
118 int repz_opt;
119 int mem_index;
120 uint64_t flags;
121 int popl_esp_hack;
122 int rip_offset;
123 int cpuid_features;
124 int cpuid_ext_features;
125 int cpuid_ext2_features;
126 int cpuid_ext3_features;
127 int cpuid_7_0_ebx_features;
128 int cpuid_xsave_features;
129
130
131 TCGv cc_srcT;
132 TCGv A0;
133 TCGv T0;
134 TCGv T1;
135
136
137 TCGv tmp0;
138 TCGv tmp4;
139 TCGv_ptr ptr0;
140 TCGv_ptr ptr1;
141 TCGv_i32 tmp2_i32;
142 TCGv_i32 tmp3_i32;
143 TCGv_i64 tmp1_i64;
144
145 sigjmp_buf jmpbuf;
146} DisasContext;
147
148static void gen_eob(DisasContext *s);
149static void gen_jr(DisasContext *s, TCGv dest);
150static void gen_jmp(DisasContext *s, target_ulong eip);
151static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
152static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
153
154
155enum {
156 OP_ADDL,
157 OP_ORL,
158 OP_ADCL,
159 OP_SBBL,
160 OP_ANDL,
161 OP_SUBL,
162 OP_XORL,
163 OP_CMPL,
164};
165
166
167enum {
168 OP_ROL,
169 OP_ROR,
170 OP_RCL,
171 OP_RCR,
172 OP_SHL,
173 OP_SHR,
174 OP_SHL1,
175 OP_SAR = 7,
176};
177
178enum {
179 JCC_O,
180 JCC_B,
181 JCC_Z,
182 JCC_BE,
183 JCC_S,
184 JCC_P,
185 JCC_L,
186 JCC_LE,
187};
188
189enum {
190
191 OR_EAX,
192 OR_ECX,
193 OR_EDX,
194 OR_EBX,
195 OR_ESP,
196 OR_EBP,
197 OR_ESI,
198 OR_EDI,
199
200 OR_TMP0 = 16,
201 OR_TMP1,
202 OR_A0,
203};
204
205enum {
206 USES_CC_DST = 1,
207 USES_CC_SRC = 2,
208 USES_CC_SRC2 = 4,
209 USES_CC_SRCT = 8,
210};
211
212
213static const uint8_t cc_op_live[CC_OP_NB] = {
214 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
215 [CC_OP_EFLAGS] = USES_CC_SRC,
216 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
217 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
218 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
219 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
220 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
221 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
222 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
223 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
224 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
225 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
226 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
227 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
228 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
229 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
230 [CC_OP_CLR] = 0,
231 [CC_OP_POPCNT] = USES_CC_SRC,
232};
233
234static void set_cc_op(DisasContext *s, CCOp op)
235{
236 int dead;
237
238 if (s->cc_op == op) {
239 return;
240 }
241
242
243 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
244 if (dead & USES_CC_DST) {
245 tcg_gen_discard_tl(cpu_cc_dst);
246 }
247 if (dead & USES_CC_SRC) {
248 tcg_gen_discard_tl(cpu_cc_src);
249 }
250 if (dead & USES_CC_SRC2) {
251 tcg_gen_discard_tl(cpu_cc_src2);
252 }
253 if (dead & USES_CC_SRCT) {
254 tcg_gen_discard_tl(s->cc_srcT);
255 }
256
257 if (op == CC_OP_DYNAMIC) {
258
259
260 s->cc_op_dirty = false;
261 } else {
262
263 if (s->cc_op == CC_OP_DYNAMIC) {
264 tcg_gen_discard_i32(cpu_cc_op);
265 }
266 s->cc_op_dirty = true;
267 }
268 s->cc_op = op;
269}
270
271static void gen_update_cc_op(DisasContext *s)
272{
273 if (s->cc_op_dirty) {
274 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
275 s->cc_op_dirty = false;
276 }
277}
278
279#ifdef TARGET_X86_64
280
281#define NB_OP_SIZES 4
282
283#else
284
285#define NB_OP_SIZES 3
286
287#endif
288
289#if defined(HOST_WORDS_BIGENDIAN)
290#define REG_B_OFFSET (sizeof(target_ulong) - 1)
291#define REG_H_OFFSET (sizeof(target_ulong) - 2)
292#define REG_W_OFFSET (sizeof(target_ulong) - 2)
293#define REG_L_OFFSET (sizeof(target_ulong) - 4)
294#define REG_LH_OFFSET (sizeof(target_ulong) - 8)
295#else
296#define REG_B_OFFSET 0
297#define REG_H_OFFSET 1
298#define REG_W_OFFSET 0
299#define REG_L_OFFSET 0
300#define REG_LH_OFFSET 4
301#endif
302
303
304
305
306
307
308
309static inline bool byte_reg_is_xH(DisasContext *s, int reg)
310{
311 if (reg < 4) {
312 return false;
313 }
314#ifdef TARGET_X86_64
315 if (reg >= 8 || s->x86_64_hregs) {
316 return false;
317 }
318#endif
319 return true;
320}
321
322
323static inline MemOp mo_pushpop(DisasContext *s, MemOp ot)
324{
325 if (CODE64(s)) {
326 return ot == MO_16 ? MO_16 : MO_64;
327 } else {
328 return ot;
329 }
330}
331
332
333static inline MemOp mo_stacksize(DisasContext *s)
334{
335 return CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
336}
337
338
339static inline MemOp mo_64_32(MemOp ot)
340{
341#ifdef TARGET_X86_64
342 return ot == MO_64 ? MO_64 : MO_32;
343#else
344 return MO_32;
345#endif
346}
347
348
349
350static inline MemOp mo_b_d(int b, MemOp ot)
351{
352 return b & 1 ? ot : MO_8;
353}
354
355
356
357static inline MemOp mo_b_d32(int b, MemOp ot)
358{
359 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
360}
361
362static void gen_op_mov_reg_v(DisasContext *s, MemOp ot, int reg, TCGv t0)
363{
364 switch(ot) {
365 case MO_8:
366 if (!byte_reg_is_xH(s, reg)) {
367 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
368 } else {
369 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
370 }
371 break;
372 case MO_16:
373 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
374 break;
375 case MO_32:
376
377
378 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
379 break;
380#ifdef TARGET_X86_64
381 case MO_64:
382 tcg_gen_mov_tl(cpu_regs[reg], t0);
383 break;
384#endif
385 default:
386 tcg_abort();
387 }
388}
389
390static inline
391void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg)
392{
393 if (ot == MO_8 && byte_reg_is_xH(s, reg)) {
394 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
395 } else {
396 tcg_gen_mov_tl(t0, cpu_regs[reg]);
397 }
398}
399
400static void gen_add_A0_im(DisasContext *s, int val)
401{
402 tcg_gen_addi_tl(s->A0, s->A0, val);
403 if (!CODE64(s)) {
404 tcg_gen_ext32u_tl(s->A0, s->A0);
405 }
406}
407
408static inline void gen_op_jmp_v(TCGv dest)
409{
410 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
411}
412
413static inline
414void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val)
415{
416 tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val);
417 gen_op_mov_reg_v(s, size, reg, s->tmp0);
418}
419
420static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg)
421{
422 tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0);
423 gen_op_mov_reg_v(s, size, reg, s->tmp0);
424}
425
426static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
427{
428 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
429}
430
431static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
432{
433 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
434}
435
436static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
437{
438 if (d == OR_TMP0) {
439 gen_op_st_v(s, idx, s->T0, s->A0);
440 } else {
441 gen_op_mov_reg_v(s, idx, d, s->T0);
442 }
443}
444
445static inline void gen_jmp_im(DisasContext *s, target_ulong pc)
446{
447 tcg_gen_movi_tl(s->tmp0, pc);
448 gen_op_jmp_v(s->tmp0);
449}
450
451
452
453
454static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
455 int def_seg, int ovr_seg)
456{
457 switch (aflag) {
458#ifdef TARGET_X86_64
459 case MO_64:
460 if (ovr_seg < 0) {
461 tcg_gen_mov_tl(s->A0, a0);
462 return;
463 }
464 break;
465#endif
466 case MO_32:
467
468 if (ovr_seg < 0 && s->addseg) {
469 ovr_seg = def_seg;
470 }
471 if (ovr_seg < 0) {
472 tcg_gen_ext32u_tl(s->A0, a0);
473 return;
474 }
475 break;
476 case MO_16:
477
478 tcg_gen_ext16u_tl(s->A0, a0);
479 a0 = s->A0;
480 if (ovr_seg < 0) {
481 if (s->addseg) {
482 ovr_seg = def_seg;
483 } else {
484 return;
485 }
486 }
487 break;
488 default:
489 tcg_abort();
490 }
491
492 if (ovr_seg >= 0) {
493 TCGv seg = cpu_seg_base[ovr_seg];
494
495 if (aflag == MO_64) {
496 tcg_gen_add_tl(s->A0, a0, seg);
497 } else if (CODE64(s)) {
498 tcg_gen_ext32u_tl(s->A0, a0);
499 tcg_gen_add_tl(s->A0, s->A0, seg);
500 } else {
501 tcg_gen_add_tl(s->A0, a0, seg);
502 tcg_gen_ext32u_tl(s->A0, s->A0);
503 }
504 }
505}
506
507static inline void gen_string_movl_A0_ESI(DisasContext *s)
508{
509 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
510}
511
512static inline void gen_string_movl_A0_EDI(DisasContext *s)
513{
514 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
515}
516
517static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
518{
519 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
520 tcg_gen_shli_tl(s->T0, s->T0, ot);
521};
522
523static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
524{
525 switch (size) {
526 case MO_8:
527 if (sign) {
528 tcg_gen_ext8s_tl(dst, src);
529 } else {
530 tcg_gen_ext8u_tl(dst, src);
531 }
532 return dst;
533 case MO_16:
534 if (sign) {
535 tcg_gen_ext16s_tl(dst, src);
536 } else {
537 tcg_gen_ext16u_tl(dst, src);
538 }
539 return dst;
540#ifdef TARGET_X86_64
541 case MO_32:
542 if (sign) {
543 tcg_gen_ext32s_tl(dst, src);
544 } else {
545 tcg_gen_ext32u_tl(dst, src);
546 }
547 return dst;
548#endif
549 default:
550 return src;
551 }
552}
553
554static void gen_extu(MemOp ot, TCGv reg)
555{
556 gen_ext_tl(reg, reg, ot, false);
557}
558
559static void gen_exts(MemOp ot, TCGv reg)
560{
561 gen_ext_tl(reg, reg, ot, true);
562}
563
564static inline
565void gen_op_jnz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
566{
567 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
568 gen_extu(size, s->tmp0);
569 tcg_gen_brcondi_tl(TCG_COND_NE, s->tmp0, 0, label1);
570}
571
572static inline
573void gen_op_jz_ecx(DisasContext *s, MemOp size, TCGLabel *label1)
574{
575 tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]);
576 gen_extu(size, s->tmp0);
577 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
578}
579
580static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
581{
582 switch (ot) {
583 case MO_8:
584 gen_helper_inb(v, cpu_env, n);
585 break;
586 case MO_16:
587 gen_helper_inw(v, cpu_env, n);
588 break;
589 case MO_32:
590 gen_helper_inl(v, cpu_env, n);
591 break;
592 default:
593 tcg_abort();
594 }
595}
596
597static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
598{
599 switch (ot) {
600 case MO_8:
601 gen_helper_outb(cpu_env, v, n);
602 break;
603 case MO_16:
604 gen_helper_outw(cpu_env, v, n);
605 break;
606 case MO_32:
607 gen_helper_outl(cpu_env, v, n);
608 break;
609 default:
610 tcg_abort();
611 }
612}
613
614static void gen_check_io(DisasContext *s, MemOp ot, target_ulong cur_eip,
615 uint32_t svm_flags)
616{
617 target_ulong next_eip;
618
619 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
620 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
621 switch (ot) {
622 case MO_8:
623 gen_helper_check_iob(cpu_env, s->tmp2_i32);
624 break;
625 case MO_16:
626 gen_helper_check_iow(cpu_env, s->tmp2_i32);
627 break;
628 case MO_32:
629 gen_helper_check_iol(cpu_env, s->tmp2_i32);
630 break;
631 default:
632 tcg_abort();
633 }
634 }
635 if(s->flags & HF_GUEST_MASK) {
636 gen_update_cc_op(s);
637 gen_jmp_im(s, cur_eip);
638 svm_flags |= (1 << (4 + ot));
639 next_eip = s->pc - s->cs_base;
640 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
641 gen_helper_svm_check_io(cpu_env, s->tmp2_i32,
642 tcg_const_i32(svm_flags),
643 tcg_const_i32(next_eip - cur_eip));
644 }
645}
646
647static inline void gen_movs(DisasContext *s, MemOp ot)
648{
649 gen_string_movl_A0_ESI(s);
650 gen_op_ld_v(s, ot, s->T0, s->A0);
651 gen_string_movl_A0_EDI(s);
652 gen_op_st_v(s, ot, s->T0, s->A0);
653 gen_op_movl_T0_Dshift(s, ot);
654 gen_op_add_reg_T0(s, s->aflag, R_ESI);
655 gen_op_add_reg_T0(s, s->aflag, R_EDI);
656}
657
658static void gen_op_update1_cc(DisasContext *s)
659{
660 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
661}
662
663static void gen_op_update2_cc(DisasContext *s)
664{
665 tcg_gen_mov_tl(cpu_cc_src, s->T1);
666 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
667}
668
669static void gen_op_update3_cc(DisasContext *s, TCGv reg)
670{
671 tcg_gen_mov_tl(cpu_cc_src2, reg);
672 tcg_gen_mov_tl(cpu_cc_src, s->T1);
673 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
674}
675
676static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
677{
678 tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1);
679}
680
681static void gen_op_update_neg_cc(DisasContext *s)
682{
683 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
684 tcg_gen_neg_tl(cpu_cc_src, s->T0);
685 tcg_gen_movi_tl(s->cc_srcT, 0);
686}
687
688
689static void gen_compute_eflags(DisasContext *s)
690{
691 TCGv zero, dst, src1, src2;
692 int live, dead;
693
694 if (s->cc_op == CC_OP_EFLAGS) {
695 return;
696 }
697 if (s->cc_op == CC_OP_CLR) {
698 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
699 set_cc_op(s, CC_OP_EFLAGS);
700 return;
701 }
702
703 zero = NULL;
704 dst = cpu_cc_dst;
705 src1 = cpu_cc_src;
706 src2 = cpu_cc_src2;
707
708
709 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
710 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
711 if (dead) {
712 zero = tcg_const_tl(0);
713 if (dead & USES_CC_DST) {
714 dst = zero;
715 }
716 if (dead & USES_CC_SRC) {
717 src1 = zero;
718 }
719 if (dead & USES_CC_SRC2) {
720 src2 = zero;
721 }
722 }
723
724 gen_update_cc_op(s);
725 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
726 set_cc_op(s, CC_OP_EFLAGS);
727
728 if (dead) {
729 tcg_temp_free(zero);
730 }
731}
732
733typedef struct CCPrepare {
734 TCGCond cond;
735 TCGv reg;
736 TCGv reg2;
737 target_ulong imm;
738 target_ulong mask;
739 bool use_reg2;
740 bool no_setcond;
741} CCPrepare;
742
743
744static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
745{
746 TCGv t0, t1;
747 int size, shift;
748
749 switch (s->cc_op) {
750 case CC_OP_SUBB ... CC_OP_SUBQ:
751
752 size = s->cc_op - CC_OP_SUBB;
753 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
754
755 t0 = t1 == cpu_cc_src ? s->tmp0 : reg;
756 tcg_gen_mov_tl(t0, s->cc_srcT);
757 gen_extu(size, t0);
758 goto add_sub;
759
760 case CC_OP_ADDB ... CC_OP_ADDQ:
761
762 size = s->cc_op - CC_OP_ADDB;
763 t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
764 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
765 add_sub:
766 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
767 .reg2 = t1, .mask = -1, .use_reg2 = true };
768
769 case CC_OP_LOGICB ... CC_OP_LOGICQ:
770 case CC_OP_CLR:
771 case CC_OP_POPCNT:
772 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
773
774 case CC_OP_INCB ... CC_OP_INCQ:
775 case CC_OP_DECB ... CC_OP_DECQ:
776 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
777 .mask = -1, .no_setcond = true };
778
779 case CC_OP_SHLB ... CC_OP_SHLQ:
780
781 size = s->cc_op - CC_OP_SHLB;
782 shift = (8 << size) - 1;
783 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
784 .mask = (target_ulong)1 << shift };
785
786 case CC_OP_MULB ... CC_OP_MULQ:
787 return (CCPrepare) { .cond = TCG_COND_NE,
788 .reg = cpu_cc_src, .mask = -1 };
789
790 case CC_OP_BMILGB ... CC_OP_BMILGQ:
791 size = s->cc_op - CC_OP_BMILGB;
792 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
793 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
794
795 case CC_OP_ADCX:
796 case CC_OP_ADCOX:
797 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
798 .mask = -1, .no_setcond = true };
799
800 case CC_OP_EFLAGS:
801 case CC_OP_SARB ... CC_OP_SARQ:
802
803 return (CCPrepare) { .cond = TCG_COND_NE,
804 .reg = cpu_cc_src, .mask = CC_C };
805
806 default:
807
808
809 gen_update_cc_op(s);
810 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
811 cpu_cc_src2, cpu_cc_op);
812 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
813 .mask = -1, .no_setcond = true };
814 }
815}
816
817
818static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
819{
820 gen_compute_eflags(s);
821 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
822 .mask = CC_P };
823}
824
825
826static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
827{
828 switch (s->cc_op) {
829 case CC_OP_DYNAMIC:
830 gen_compute_eflags(s);
831
832 case CC_OP_EFLAGS:
833 case CC_OP_ADCX:
834 case CC_OP_ADOX:
835 case CC_OP_ADCOX:
836 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
837 .mask = CC_S };
838 case CC_OP_CLR:
839 case CC_OP_POPCNT:
840 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
841 default:
842 {
843 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
844 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
845 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
846 }
847 }
848}
849
850
851static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
852{
853 switch (s->cc_op) {
854 case CC_OP_ADOX:
855 case CC_OP_ADCOX:
856 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
857 .mask = -1, .no_setcond = true };
858 case CC_OP_CLR:
859 case CC_OP_POPCNT:
860 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
861 default:
862 gen_compute_eflags(s);
863 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
864 .mask = CC_O };
865 }
866}
867
868
869static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
870{
871 switch (s->cc_op) {
872 case CC_OP_DYNAMIC:
873 gen_compute_eflags(s);
874
875 case CC_OP_EFLAGS:
876 case CC_OP_ADCX:
877 case CC_OP_ADOX:
878 case CC_OP_ADCOX:
879 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
880 .mask = CC_Z };
881 case CC_OP_CLR:
882 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
883 case CC_OP_POPCNT:
884 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
885 .mask = -1 };
886 default:
887 {
888 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
889 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
890 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
891 }
892 }
893}
894
895
896
897static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
898{
899 int inv, jcc_op, cond;
900 MemOp size;
901 CCPrepare cc;
902 TCGv t0;
903
904 inv = b & 1;
905 jcc_op = (b >> 1) & 7;
906
907 switch (s->cc_op) {
908 case CC_OP_SUBB ... CC_OP_SUBQ:
909
910 size = s->cc_op - CC_OP_SUBB;
911 switch (jcc_op) {
912 case JCC_BE:
913 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
914 gen_extu(size, s->tmp4);
915 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
916 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4,
917 .reg2 = t0, .mask = -1, .use_reg2 = true };
918 break;
919
920 case JCC_L:
921 cond = TCG_COND_LT;
922 goto fast_jcc_l;
923 case JCC_LE:
924 cond = TCG_COND_LE;
925 fast_jcc_l:
926 tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
927 gen_exts(size, s->tmp4);
928 t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true);
929 cc = (CCPrepare) { .cond = cond, .reg = s->tmp4,
930 .reg2 = t0, .mask = -1, .use_reg2 = true };
931 break;
932
933 default:
934 goto slow_jcc;
935 }
936 break;
937
938 default:
939 slow_jcc:
940
941 switch (jcc_op) {
942 case JCC_O:
943 cc = gen_prepare_eflags_o(s, reg);
944 break;
945 case JCC_B:
946 cc = gen_prepare_eflags_c(s, reg);
947 break;
948 case JCC_Z:
949 cc = gen_prepare_eflags_z(s, reg);
950 break;
951 case JCC_BE:
952 gen_compute_eflags(s);
953 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
954 .mask = CC_Z | CC_C };
955 break;
956 case JCC_S:
957 cc = gen_prepare_eflags_s(s, reg);
958 break;
959 case JCC_P:
960 cc = gen_prepare_eflags_p(s, reg);
961 break;
962 case JCC_L:
963 gen_compute_eflags(s);
964 if (reg == cpu_cc_src) {
965 reg = s->tmp0;
966 }
967 tcg_gen_shri_tl(reg, cpu_cc_src, 4);
968 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
969 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
970 .mask = CC_S };
971 break;
972 default:
973 case JCC_LE:
974 gen_compute_eflags(s);
975 if (reg == cpu_cc_src) {
976 reg = s->tmp0;
977 }
978 tcg_gen_shri_tl(reg, cpu_cc_src, 4);
979 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
980 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
981 .mask = CC_S | CC_Z };
982 break;
983 }
984 break;
985 }
986
987 if (inv) {
988 cc.cond = tcg_invert_cond(cc.cond);
989 }
990 return cc;
991}
992
993static void gen_setcc1(DisasContext *s, int b, TCGv reg)
994{
995 CCPrepare cc = gen_prepare_cc(s, b, reg);
996
997 if (cc.no_setcond) {
998 if (cc.cond == TCG_COND_EQ) {
999 tcg_gen_xori_tl(reg, cc.reg, 1);
1000 } else {
1001 tcg_gen_mov_tl(reg, cc.reg);
1002 }
1003 return;
1004 }
1005
1006 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1007 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1008 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1009 tcg_gen_andi_tl(reg, reg, 1);
1010 return;
1011 }
1012 if (cc.mask != -1) {
1013 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1014 cc.reg = reg;
1015 }
1016 if (cc.use_reg2) {
1017 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1018 } else {
1019 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1020 }
1021}
1022
1023static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1024{
1025 gen_setcc1(s, JCC_B << 1, reg);
1026}
1027
1028
1029
1030static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
1031{
1032 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1033
1034 if (cc.mask != -1) {
1035 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1036 cc.reg = s->T0;
1037 }
1038 if (cc.use_reg2) {
1039 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1040 } else {
1041 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1042 }
1043}
1044
1045
1046
1047
1048static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
1049{
1050 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
1051
1052 gen_update_cc_op(s);
1053 if (cc.mask != -1) {
1054 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1055 cc.reg = s->T0;
1056 }
1057 set_cc_op(s, CC_OP_DYNAMIC);
1058 if (cc.use_reg2) {
1059 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1060 } else {
1061 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1062 }
1063}
1064
1065
1066
1067static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1068{
1069 TCGLabel *l1 = gen_new_label();
1070 TCGLabel *l2 = gen_new_label();
1071 gen_op_jnz_ecx(s, s->aflag, l1);
1072 gen_set_label(l2);
1073 gen_jmp_tb(s, next_eip, 1);
1074 gen_set_label(l1);
1075 return l2;
1076}
1077
1078static inline void gen_stos(DisasContext *s, MemOp ot)
1079{
1080 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
1081 gen_string_movl_A0_EDI(s);
1082 gen_op_st_v(s, ot, s->T0, s->A0);
1083 gen_op_movl_T0_Dshift(s, ot);
1084 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1085}
1086
1087static inline void gen_lods(DisasContext *s, MemOp ot)
1088{
1089 gen_string_movl_A0_ESI(s);
1090 gen_op_ld_v(s, ot, s->T0, s->A0);
1091 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
1092 gen_op_movl_T0_Dshift(s, ot);
1093 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1094}
1095
1096static inline void gen_scas(DisasContext *s, MemOp ot)
1097{
1098 gen_string_movl_A0_EDI(s);
1099 gen_op_ld_v(s, ot, s->T1, s->A0);
1100 gen_op(s, OP_CMPL, ot, R_EAX);
1101 gen_op_movl_T0_Dshift(s, ot);
1102 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1103}
1104
1105static inline void gen_cmps(DisasContext *s, MemOp ot)
1106{
1107 gen_string_movl_A0_EDI(s);
1108 gen_op_ld_v(s, ot, s->T1, s->A0);
1109 gen_string_movl_A0_ESI(s);
1110 gen_op(s, OP_CMPL, ot, OR_TMP0);
1111 gen_op_movl_T0_Dshift(s, ot);
1112 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1113 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1114}
1115
1116static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1117{
1118 if (s->flags & HF_IOBPT_MASK) {
1119 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1120 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1121
1122 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1123 tcg_temp_free_i32(t_size);
1124 tcg_temp_free(t_next);
1125 }
1126}
1127
1128
1129static inline void gen_ins(DisasContext *s, MemOp ot)
1130{
1131 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1132 gen_io_start();
1133 }
1134 gen_string_movl_A0_EDI(s);
1135
1136
1137 tcg_gen_movi_tl(s->T0, 0);
1138 gen_op_st_v(s, ot, s->T0, s->A0);
1139 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1140 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1141 gen_helper_in_func(ot, s->T0, s->tmp2_i32);
1142 gen_op_st_v(s, ot, s->T0, s->A0);
1143 gen_op_movl_T0_Dshift(s, ot);
1144 gen_op_add_reg_T0(s, s->aflag, R_EDI);
1145 gen_bpt_io(s, s->tmp2_i32, ot);
1146 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1147 gen_io_end();
1148 }
1149}
1150
1151static inline void gen_outs(DisasContext *s, MemOp ot)
1152{
1153 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1154 gen_io_start();
1155 }
1156 gen_string_movl_A0_ESI(s);
1157 gen_op_ld_v(s, ot, s->T0, s->A0);
1158
1159 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]);
1160 tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff);
1161 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0);
1162 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
1163 gen_op_movl_T0_Dshift(s, ot);
1164 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1165 gen_bpt_io(s, s->tmp2_i32, ot);
1166 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1167 gen_io_end();
1168 }
1169}
1170
1171
1172
1173#define GEN_REPZ(op) \
1174static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1175 target_ulong cur_eip, target_ulong next_eip) \
1176{ \
1177 TCGLabel *l2; \
1178 gen_update_cc_op(s); \
1179 l2 = gen_jz_ecx_string(s, next_eip); \
1180 gen_ ## op(s, ot); \
1181 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1182
1183 \
1184 if (s->repz_opt) \
1185 gen_op_jz_ecx(s, s->aflag, l2); \
1186 gen_jmp(s, cur_eip); \
1187}
1188
1189#define GEN_REPZ2(op) \
1190static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
1191 target_ulong cur_eip, \
1192 target_ulong next_eip, \
1193 int nz) \
1194{ \
1195 TCGLabel *l2; \
1196 gen_update_cc_op(s); \
1197 l2 = gen_jz_ecx_string(s, next_eip); \
1198 gen_ ## op(s, ot); \
1199 gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
1200 gen_update_cc_op(s); \
1201 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1202 if (s->repz_opt) \
1203 gen_op_jz_ecx(s, s->aflag, l2); \
1204 gen_jmp(s, cur_eip); \
1205}
1206
1207GEN_REPZ(movs)
1208GEN_REPZ(stos)
1209GEN_REPZ(lods)
1210GEN_REPZ(ins)
1211GEN_REPZ(outs)
1212GEN_REPZ2(scas)
1213GEN_REPZ2(cmps)
1214
1215static void gen_helper_fp_arith_ST0_FT0(int op)
1216{
1217 switch (op) {
1218 case 0:
1219 gen_helper_fadd_ST0_FT0(cpu_env);
1220 break;
1221 case 1:
1222 gen_helper_fmul_ST0_FT0(cpu_env);
1223 break;
1224 case 2:
1225 gen_helper_fcom_ST0_FT0(cpu_env);
1226 break;
1227 case 3:
1228 gen_helper_fcom_ST0_FT0(cpu_env);
1229 break;
1230 case 4:
1231 gen_helper_fsub_ST0_FT0(cpu_env);
1232 break;
1233 case 5:
1234 gen_helper_fsubr_ST0_FT0(cpu_env);
1235 break;
1236 case 6:
1237 gen_helper_fdiv_ST0_FT0(cpu_env);
1238 break;
1239 case 7:
1240 gen_helper_fdivr_ST0_FT0(cpu_env);
1241 break;
1242 }
1243}
1244
1245
1246static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1247{
1248 TCGv_i32 tmp = tcg_const_i32(opreg);
1249 switch (op) {
1250 case 0:
1251 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1252 break;
1253 case 1:
1254 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1255 break;
1256 case 4:
1257 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1258 break;
1259 case 5:
1260 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1261 break;
1262 case 6:
1263 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1264 break;
1265 case 7:
1266 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1267 break;
1268 }
1269}
1270
1271static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
1272{
1273 gen_update_cc_op(s);
1274 gen_jmp_im(s, cur_eip);
1275 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
1276 s->base.is_jmp = DISAS_NORETURN;
1277}
1278
1279
1280
1281static void gen_illegal_opcode(DisasContext *s)
1282{
1283 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
1284}
1285
1286
1287static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
1288{
1289 if (d != OR_TMP0) {
1290 if (s1->prefix & PREFIX_LOCK) {
1291
1292 gen_illegal_opcode(s1);
1293 return;
1294 }
1295 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1296 } else if (!(s1->prefix & PREFIX_LOCK)) {
1297 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1298 }
1299 switch(op) {
1300 case OP_ADCL:
1301 gen_compute_eflags_c(s1, s1->tmp4);
1302 if (s1->prefix & PREFIX_LOCK) {
1303 tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1);
1304 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1305 s1->mem_index, ot | MO_LE);
1306 } else {
1307 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1308 tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4);
1309 gen_op_st_rm_T0_A0(s1, ot, d);
1310 }
1311 gen_op_update3_cc(s1, s1->tmp4);
1312 set_cc_op(s1, CC_OP_ADCB + ot);
1313 break;
1314 case OP_SBBL:
1315 gen_compute_eflags_c(s1, s1->tmp4);
1316 if (s1->prefix & PREFIX_LOCK) {
1317 tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4);
1318 tcg_gen_neg_tl(s1->T0, s1->T0);
1319 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1320 s1->mem_index, ot | MO_LE);
1321 } else {
1322 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1323 tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4);
1324 gen_op_st_rm_T0_A0(s1, ot, d);
1325 }
1326 gen_op_update3_cc(s1, s1->tmp4);
1327 set_cc_op(s1, CC_OP_SBBB + ot);
1328 break;
1329 case OP_ADDL:
1330 if (s1->prefix & PREFIX_LOCK) {
1331 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1,
1332 s1->mem_index, ot | MO_LE);
1333 } else {
1334 tcg_gen_add_tl(s1->T0, s1->T0, s1->T1);
1335 gen_op_st_rm_T0_A0(s1, ot, d);
1336 }
1337 gen_op_update2_cc(s1);
1338 set_cc_op(s1, CC_OP_ADDB + ot);
1339 break;
1340 case OP_SUBL:
1341 if (s1->prefix & PREFIX_LOCK) {
1342 tcg_gen_neg_tl(s1->T0, s1->T1);
1343 tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
1344 s1->mem_index, ot | MO_LE);
1345 tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
1346 } else {
1347 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1348 tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
1349 gen_op_st_rm_T0_A0(s1, ot, d);
1350 }
1351 gen_op_update2_cc(s1);
1352 set_cc_op(s1, CC_OP_SUBB + ot);
1353 break;
1354 default:
1355 case OP_ANDL:
1356 if (s1->prefix & PREFIX_LOCK) {
1357 tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1,
1358 s1->mem_index, ot | MO_LE);
1359 } else {
1360 tcg_gen_and_tl(s1->T0, s1->T0, s1->T1);
1361 gen_op_st_rm_T0_A0(s1, ot, d);
1362 }
1363 gen_op_update1_cc(s1);
1364 set_cc_op(s1, CC_OP_LOGICB + ot);
1365 break;
1366 case OP_ORL:
1367 if (s1->prefix & PREFIX_LOCK) {
1368 tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1,
1369 s1->mem_index, ot | MO_LE);
1370 } else {
1371 tcg_gen_or_tl(s1->T0, s1->T0, s1->T1);
1372 gen_op_st_rm_T0_A0(s1, ot, d);
1373 }
1374 gen_op_update1_cc(s1);
1375 set_cc_op(s1, CC_OP_LOGICB + ot);
1376 break;
1377 case OP_XORL:
1378 if (s1->prefix & PREFIX_LOCK) {
1379 tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1,
1380 s1->mem_index, ot | MO_LE);
1381 } else {
1382 tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1);
1383 gen_op_st_rm_T0_A0(s1, ot, d);
1384 }
1385 gen_op_update1_cc(s1);
1386 set_cc_op(s1, CC_OP_LOGICB + ot);
1387 break;
1388 case OP_CMPL:
1389 tcg_gen_mov_tl(cpu_cc_src, s1->T1);
1390 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1391 tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
1392 set_cc_op(s1, CC_OP_SUBB + ot);
1393 break;
1394 }
1395}
1396
1397
1398static void gen_inc(DisasContext *s1, MemOp ot, int d, int c)
1399{
1400 if (s1->prefix & PREFIX_LOCK) {
1401 if (d != OR_TMP0) {
1402
1403 gen_illegal_opcode(s1);
1404 return;
1405 }
1406 tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
1407 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
1408 s1->mem_index, ot | MO_LE);
1409 } else {
1410 if (d != OR_TMP0) {
1411 gen_op_mov_v_reg(s1, ot, s1->T0, d);
1412 } else {
1413 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
1414 }
1415 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
1416 gen_op_st_rm_T0_A0(s1, ot, d);
1417 }
1418
1419 gen_compute_eflags_c(s1, cpu_cc_src);
1420 tcg_gen_mov_tl(cpu_cc_dst, s1->T0);
1421 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
1422}
1423
1424static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
1425 TCGv shm1, TCGv count, bool is_right)
1426{
1427 TCGv_i32 z32, s32, oldop;
1428 TCGv z_tl;
1429
1430
1431
1432
1433 z_tl = tcg_const_tl(0);
1434 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1435 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1436 result, cpu_cc_dst);
1437 } else {
1438 tcg_gen_mov_tl(cpu_cc_dst, result);
1439 }
1440 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1441 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1442 shm1, cpu_cc_src);
1443 } else {
1444 tcg_gen_mov_tl(cpu_cc_src, shm1);
1445 }
1446 tcg_temp_free(z_tl);
1447
1448
1449 tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1450 if (s->cc_op == CC_OP_DYNAMIC) {
1451 oldop = cpu_cc_op;
1452 } else {
1453 tcg_gen_movi_i32(s->tmp3_i32, s->cc_op);
1454 oldop = s->tmp3_i32;
1455 }
1456
1457
1458 z32 = tcg_const_i32(0);
1459 s32 = tcg_temp_new_i32();
1460 tcg_gen_trunc_tl_i32(s32, count);
1461 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop);
1462 tcg_temp_free_i32(z32);
1463 tcg_temp_free_i32(s32);
1464
1465
1466 set_cc_op(s, CC_OP_DYNAMIC);
1467}
1468
1469static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1,
1470 int is_right, int is_arith)
1471{
1472 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1473
1474
1475 if (op1 == OR_TMP0) {
1476 gen_op_ld_v(s, ot, s->T0, s->A0);
1477 } else {
1478 gen_op_mov_v_reg(s, ot, s->T0, op1);
1479 }
1480
1481 tcg_gen_andi_tl(s->T1, s->T1, mask);
1482 tcg_gen_subi_tl(s->tmp0, s->T1, 1);
1483
1484 if (is_right) {
1485 if (is_arith) {
1486 gen_exts(ot, s->T0);
1487 tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0);
1488 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
1489 } else {
1490 gen_extu(ot, s->T0);
1491 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1492 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
1493 }
1494 } else {
1495 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1496 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
1497 }
1498
1499
1500 gen_op_st_rm_T0_A0(s, ot, op1);
1501
1502 gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right);
1503}
1504
1505static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1506 int is_right, int is_arith)
1507{
1508 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1509
1510
1511 if (op1 == OR_TMP0)
1512 gen_op_ld_v(s, ot, s->T0, s->A0);
1513 else
1514 gen_op_mov_v_reg(s, ot, s->T0, op1);
1515
1516 op2 &= mask;
1517 if (op2 != 0) {
1518 if (is_right) {
1519 if (is_arith) {
1520 gen_exts(ot, s->T0);
1521 tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1);
1522 tcg_gen_sari_tl(s->T0, s->T0, op2);
1523 } else {
1524 gen_extu(ot, s->T0);
1525 tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1);
1526 tcg_gen_shri_tl(s->T0, s->T0, op2);
1527 }
1528 } else {
1529 tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1);
1530 tcg_gen_shli_tl(s->T0, s->T0, op2);
1531 }
1532 }
1533
1534
1535 gen_op_st_rm_T0_A0(s, ot, op1);
1536
1537
1538 if (op2 != 0) {
1539 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
1540 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
1541 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1542 }
1543}
1544
1545static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right)
1546{
1547 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
1548 TCGv_i32 t0, t1;
1549
1550
1551 if (op1 == OR_TMP0) {
1552 gen_op_ld_v(s, ot, s->T0, s->A0);
1553 } else {
1554 gen_op_mov_v_reg(s, ot, s->T0, op1);
1555 }
1556
1557 tcg_gen_andi_tl(s->T1, s->T1, mask);
1558
1559 switch (ot) {
1560 case MO_8:
1561
1562 tcg_gen_ext8u_tl(s->T0, s->T0);
1563 tcg_gen_muli_tl(s->T0, s->T0, 0x01010101);
1564 goto do_long;
1565 case MO_16:
1566
1567 tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16);
1568 goto do_long;
1569 do_long:
1570#ifdef TARGET_X86_64
1571 case MO_32:
1572 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1573 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
1574 if (is_right) {
1575 tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1576 } else {
1577 tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
1578 }
1579 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1580 break;
1581#endif
1582 default:
1583 if (is_right) {
1584 tcg_gen_rotr_tl(s->T0, s->T0, s->T1);
1585 } else {
1586 tcg_gen_rotl_tl(s->T0, s->T0, s->T1);
1587 }
1588 break;
1589 }
1590
1591
1592 gen_op_st_rm_T0_A0(s, ot, op1);
1593
1594
1595 gen_compute_eflags(s);
1596
1597
1598
1599
1600
1601 if (is_right) {
1602 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1603 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1604 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1605 } else {
1606 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1607 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1608 }
1609 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1610 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1611
1612
1613
1614
1615
1616 t0 = tcg_const_i32(0);
1617 t1 = tcg_temp_new_i32();
1618 tcg_gen_trunc_tl_i32(t1, s->T1);
1619 tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX);
1620 tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS);
1621 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1622 s->tmp2_i32, s->tmp3_i32);
1623 tcg_temp_free_i32(t0);
1624 tcg_temp_free_i32(t1);
1625
1626
1627 set_cc_op(s, CC_OP_DYNAMIC);
1628}
1629
1630static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2,
1631 int is_right)
1632{
1633 int mask = (ot == MO_64 ? 0x3f : 0x1f);
1634 int shift;
1635
1636
1637 if (op1 == OR_TMP0) {
1638 gen_op_ld_v(s, ot, s->T0, s->A0);
1639 } else {
1640 gen_op_mov_v_reg(s, ot, s->T0, op1);
1641 }
1642
1643 op2 &= mask;
1644 if (op2 != 0) {
1645 switch (ot) {
1646#ifdef TARGET_X86_64
1647 case MO_32:
1648 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
1649 if (is_right) {
1650 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2);
1651 } else {
1652 tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2);
1653 }
1654 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
1655 break;
1656#endif
1657 default:
1658 if (is_right) {
1659 tcg_gen_rotri_tl(s->T0, s->T0, op2);
1660 } else {
1661 tcg_gen_rotli_tl(s->T0, s->T0, op2);
1662 }
1663 break;
1664 case MO_8:
1665 mask = 7;
1666 goto do_shifts;
1667 case MO_16:
1668 mask = 15;
1669 do_shifts:
1670 shift = op2 & mask;
1671 if (is_right) {
1672 shift = mask + 1 - shift;
1673 }
1674 gen_extu(ot, s->T0);
1675 tcg_gen_shli_tl(s->tmp0, s->T0, shift);
1676 tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift);
1677 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
1678 break;
1679 }
1680 }
1681
1682
1683 gen_op_st_rm_T0_A0(s, ot, op1);
1684
1685 if (op2 != 0) {
1686
1687 gen_compute_eflags(s);
1688
1689
1690
1691
1692
1693 if (is_right) {
1694 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1695 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
1696 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
1697 } else {
1698 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1699 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
1700 }
1701 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1702 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1703 set_cc_op(s, CC_OP_ADCOX);
1704 }
1705}
1706
1707
1708static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
1709 int is_right)
1710{
1711 gen_compute_eflags(s);
1712 assert(s->cc_op == CC_OP_EFLAGS);
1713
1714
1715 if (op1 == OR_TMP0)
1716 gen_op_ld_v(s, ot, s->T0, s->A0);
1717 else
1718 gen_op_mov_v_reg(s, ot, s->T0, op1);
1719
1720 if (is_right) {
1721 switch (ot) {
1722 case MO_8:
1723 gen_helper_rcrb(s->T0, cpu_env, s->T0, s->T1);
1724 break;
1725 case MO_16:
1726 gen_helper_rcrw(s->T0, cpu_env, s->T0, s->T1);
1727 break;
1728 case MO_32:
1729 gen_helper_rcrl(s->T0, cpu_env, s->T0, s->T1);
1730 break;
1731#ifdef TARGET_X86_64
1732 case MO_64:
1733 gen_helper_rcrq(s->T0, cpu_env, s->T0, s->T1);
1734 break;
1735#endif
1736 default:
1737 tcg_abort();
1738 }
1739 } else {
1740 switch (ot) {
1741 case MO_8:
1742 gen_helper_rclb(s->T0, cpu_env, s->T0, s->T1);
1743 break;
1744 case MO_16:
1745 gen_helper_rclw(s->T0, cpu_env, s->T0, s->T1);
1746 break;
1747 case MO_32:
1748 gen_helper_rcll(s->T0, cpu_env, s->T0, s->T1);
1749 break;
1750#ifdef TARGET_X86_64
1751 case MO_64:
1752 gen_helper_rclq(s->T0, cpu_env, s->T0, s->T1);
1753 break;
1754#endif
1755 default:
1756 tcg_abort();
1757 }
1758 }
1759
1760 gen_op_st_rm_T0_A0(s, ot, op1);
1761}
1762
1763
1764static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
1765 bool is_right, TCGv count_in)
1766{
1767 target_ulong mask = (ot == MO_64 ? 63 : 31);
1768 TCGv count;
1769
1770
1771 if (op1 == OR_TMP0) {
1772 gen_op_ld_v(s, ot, s->T0, s->A0);
1773 } else {
1774 gen_op_mov_v_reg(s, ot, s->T0, op1);
1775 }
1776
1777 count = tcg_temp_new();
1778 tcg_gen_andi_tl(count, count_in, mask);
1779
1780 switch (ot) {
1781 case MO_16:
1782
1783
1784
1785 if (is_right) {
1786 tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16);
1787 tcg_gen_mov_tl(s->T1, s->T0);
1788 tcg_gen_mov_tl(s->T0, s->tmp0);
1789 } else {
1790 tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
1791 }
1792
1793#ifdef TARGET_X86_64
1794 case MO_32:
1795
1796 tcg_gen_subi_tl(s->tmp0, count, 1);
1797 if (is_right) {
1798 tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1);
1799 tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0);
1800 tcg_gen_shr_i64(s->T0, s->T0, count);
1801 } else {
1802 tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0);
1803 tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0);
1804 tcg_gen_shl_i64(s->T0, s->T0, count);
1805 tcg_gen_shri_i64(s->tmp0, s->tmp0, 32);
1806 tcg_gen_shri_i64(s->T0, s->T0, 32);
1807 }
1808 break;
1809#endif
1810 default:
1811 tcg_gen_subi_tl(s->tmp0, count, 1);
1812 if (is_right) {
1813 tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0);
1814
1815 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1816 tcg_gen_shr_tl(s->T0, s->T0, count);
1817 tcg_gen_shl_tl(s->T1, s->T1, s->tmp4);
1818 } else {
1819 tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0);
1820 if (ot == MO_16) {
1821
1822 tcg_gen_subfi_tl(s->tmp4, 33, count);
1823 tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4);
1824 tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4);
1825 }
1826
1827 tcg_gen_subfi_tl(s->tmp4, mask + 1, count);
1828 tcg_gen_shl_tl(s->T0, s->T0, count);
1829 tcg_gen_shr_tl(s->T1, s->T1, s->tmp4);
1830 }
1831 tcg_gen_movi_tl(s->tmp4, 0);
1832 tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4,
1833 s->tmp4, s->T1);
1834 tcg_gen_or_tl(s->T0, s->T0, s->T1);
1835 break;
1836 }
1837
1838
1839 gen_op_st_rm_T0_A0(s, ot, op1);
1840
1841 gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
1842 tcg_temp_free(count);
1843}
1844
1845static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s)
1846{
1847 if (s != OR_TMP1)
1848 gen_op_mov_v_reg(s1, ot, s1->T1, s);
1849 switch(op) {
1850 case OP_ROL:
1851 gen_rot_rm_T1(s1, ot, d, 0);
1852 break;
1853 case OP_ROR:
1854 gen_rot_rm_T1(s1, ot, d, 1);
1855 break;
1856 case OP_SHL:
1857 case OP_SHL1:
1858 gen_shift_rm_T1(s1, ot, d, 0, 0);
1859 break;
1860 case OP_SHR:
1861 gen_shift_rm_T1(s1, ot, d, 1, 0);
1862 break;
1863 case OP_SAR:
1864 gen_shift_rm_T1(s1, ot, d, 1, 1);
1865 break;
1866 case OP_RCL:
1867 gen_rotc_rm_T1(s1, ot, d, 0);
1868 break;
1869 case OP_RCR:
1870 gen_rotc_rm_T1(s1, ot, d, 1);
1871 break;
1872 }
1873}
1874
1875static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c)
1876{
1877 switch(op) {
1878 case OP_ROL:
1879 gen_rot_rm_im(s1, ot, d, c, 0);
1880 break;
1881 case OP_ROR:
1882 gen_rot_rm_im(s1, ot, d, c, 1);
1883 break;
1884 case OP_SHL:
1885 case OP_SHL1:
1886 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1887 break;
1888 case OP_SHR:
1889 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1890 break;
1891 case OP_SAR:
1892 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1893 break;
1894 default:
1895
1896 tcg_gen_movi_tl(s1->T1, c);
1897 gen_shift(s1, op, ot, d, OR_TMP1);
1898 break;
1899 }
1900}
1901
1902#define X86_MAX_INSN_LENGTH 15
1903
1904static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
1905{
1906 uint64_t pc = s->pc;
1907
1908 s->pc += num_bytes;
1909 if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
1910
1911
1912
1913
1914
1915 if (((s->pc - 1) ^ (pc - 1)) & TARGET_PAGE_MASK) {
1916 volatile uint8_t unused =
1917 cpu_ldub_code(env, (s->pc - 1) & TARGET_PAGE_MASK);
1918 (void) unused;
1919 }
1920 siglongjmp(s->jmpbuf, 1);
1921 }
1922
1923 return pc;
1924}
1925
1926static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
1927{
1928 return translator_ldub(env, advance_pc(env, s, 1));
1929}
1930
1931static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
1932{
1933 return translator_ldsw(env, advance_pc(env, s, 2));
1934}
1935
1936static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
1937{
1938 return translator_lduw(env, advance_pc(env, s, 2));
1939}
1940
1941static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
1942{
1943 return translator_ldl(env, advance_pc(env, s, 4));
1944}
1945
1946#ifdef TARGET_X86_64
1947static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
1948{
1949 return translator_ldq(env, advance_pc(env, s, 8));
1950}
1951#endif
1952
1953
1954
1955typedef struct AddressParts {
1956 int def_seg;
1957 int base;
1958 int index;
1959 int scale;
1960 target_long disp;
1961} AddressParts;
1962
1963static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
1964 int modrm)
1965{
1966 int def_seg, base, index, scale, mod, rm;
1967 target_long disp;
1968 bool havesib;
1969
1970 def_seg = R_DS;
1971 index = -1;
1972 scale = 0;
1973 disp = 0;
1974
1975 mod = (modrm >> 6) & 3;
1976 rm = modrm & 7;
1977 base = rm | REX_B(s);
1978
1979 if (mod == 3) {
1980
1981
1982 goto done;
1983 }
1984
1985 switch (s->aflag) {
1986 case MO_64:
1987 case MO_32:
1988 havesib = 0;
1989 if (rm == 4) {
1990 int code = x86_ldub_code(env, s);
1991 scale = (code >> 6) & 3;
1992 index = ((code >> 3) & 7) | REX_X(s);
1993 if (index == 4) {
1994 index = -1;
1995 }
1996 base = (code & 7) | REX_B(s);
1997 havesib = 1;
1998 }
1999
2000 switch (mod) {
2001 case 0:
2002 if ((base & 7) == 5) {
2003 base = -1;
2004 disp = (int32_t)x86_ldl_code(env, s);
2005 if (CODE64(s) && !havesib) {
2006 base = -2;
2007 disp += s->pc + s->rip_offset;
2008 }
2009 }
2010 break;
2011 case 1:
2012 disp = (int8_t)x86_ldub_code(env, s);
2013 break;
2014 default:
2015 case 2:
2016 disp = (int32_t)x86_ldl_code(env, s);
2017 break;
2018 }
2019
2020
2021 if (base == R_ESP && s->popl_esp_hack) {
2022 disp += s->popl_esp_hack;
2023 }
2024 if (base == R_EBP || base == R_ESP) {
2025 def_seg = R_SS;
2026 }
2027 break;
2028
2029 case MO_16:
2030 if (mod == 0) {
2031 if (rm == 6) {
2032 base = -1;
2033 disp = x86_lduw_code(env, s);
2034 break;
2035 }
2036 } else if (mod == 1) {
2037 disp = (int8_t)x86_ldub_code(env, s);
2038 } else {
2039 disp = (int16_t)x86_lduw_code(env, s);
2040 }
2041
2042 switch (rm) {
2043 case 0:
2044 base = R_EBX;
2045 index = R_ESI;
2046 break;
2047 case 1:
2048 base = R_EBX;
2049 index = R_EDI;
2050 break;
2051 case 2:
2052 base = R_EBP;
2053 index = R_ESI;
2054 def_seg = R_SS;
2055 break;
2056 case 3:
2057 base = R_EBP;
2058 index = R_EDI;
2059 def_seg = R_SS;
2060 break;
2061 case 4:
2062 base = R_ESI;
2063 break;
2064 case 5:
2065 base = R_EDI;
2066 break;
2067 case 6:
2068 base = R_EBP;
2069 def_seg = R_SS;
2070 break;
2071 default:
2072 case 7:
2073 base = R_EBX;
2074 break;
2075 }
2076 break;
2077
2078 default:
2079 tcg_abort();
2080 }
2081
2082 done:
2083 return (AddressParts){ def_seg, base, index, scale, disp };
2084}
2085
2086
2087static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a)
2088{
2089 TCGv ea = NULL;
2090
2091 if (a.index >= 0) {
2092 if (a.scale == 0) {
2093 ea = cpu_regs[a.index];
2094 } else {
2095 tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale);
2096 ea = s->A0;
2097 }
2098 if (a.base >= 0) {
2099 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2100 ea = s->A0;
2101 }
2102 } else if (a.base >= 0) {
2103 ea = cpu_regs[a.base];
2104 }
2105 if (!ea) {
2106 tcg_gen_movi_tl(s->A0, a.disp);
2107 ea = s->A0;
2108 } else if (a.disp != 0) {
2109 tcg_gen_addi_tl(s->A0, ea, a.disp);
2110 ea = s->A0;
2111 }
2112
2113 return ea;
2114}
2115
2116static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2117{
2118 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2119 TCGv ea = gen_lea_modrm_1(s, a);
2120 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2121}
2122
2123static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2124{
2125 (void)gen_lea_modrm_0(env, s, modrm);
2126}
2127
2128
2129static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2130 TCGCond cond, TCGv_i64 bndv)
2131{
2132 TCGv ea = gen_lea_modrm_1(s, gen_lea_modrm_0(env, s, modrm));
2133
2134 tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
2135 if (!CODE64(s)) {
2136 tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64);
2137 }
2138 tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv);
2139 tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64);
2140 gen_helper_bndck(cpu_env, s->tmp2_i32);
2141}
2142
2143
2144static void gen_add_A0_ds_seg(DisasContext *s)
2145{
2146 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
2147}
2148
2149
2150
2151static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2152 MemOp ot, int reg, int is_store)
2153{
2154 int mod, rm;
2155
2156 mod = (modrm >> 6) & 3;
2157 rm = (modrm & 7) | REX_B(s);
2158 if (mod == 3) {
2159 if (is_store) {
2160 if (reg != OR_TMP0)
2161 gen_op_mov_v_reg(s, ot, s->T0, reg);
2162 gen_op_mov_reg_v(s, ot, rm, s->T0);
2163 } else {
2164 gen_op_mov_v_reg(s, ot, s->T0, rm);
2165 if (reg != OR_TMP0)
2166 gen_op_mov_reg_v(s, ot, reg, s->T0);
2167 }
2168 } else {
2169 gen_lea_modrm(env, s, modrm);
2170 if (is_store) {
2171 if (reg != OR_TMP0)
2172 gen_op_mov_v_reg(s, ot, s->T0, reg);
2173 gen_op_st_v(s, ot, s->T0, s->A0);
2174 } else {
2175 gen_op_ld_v(s, ot, s->T0, s->A0);
2176 if (reg != OR_TMP0)
2177 gen_op_mov_reg_v(s, ot, reg, s->T0);
2178 }
2179 }
2180}
2181
2182static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
2183{
2184 uint32_t ret;
2185
2186 switch (ot) {
2187 case MO_8:
2188 ret = x86_ldub_code(env, s);
2189 break;
2190 case MO_16:
2191 ret = x86_lduw_code(env, s);
2192 break;
2193 case MO_32:
2194#ifdef TARGET_X86_64
2195 case MO_64:
2196#endif
2197 ret = x86_ldl_code(env, s);
2198 break;
2199 default:
2200 tcg_abort();
2201 }
2202 return ret;
2203}
2204
2205static inline int insn_const_size(MemOp ot)
2206{
2207 if (ot <= MO_32) {
2208 return 1 << ot;
2209 } else {
2210 return 4;
2211 }
2212}
2213
2214static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2215{
2216#ifndef CONFIG_USER_ONLY
2217 return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
2218 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2219#else
2220 return true;
2221#endif
2222}
2223
2224static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2225{
2226 target_ulong pc = s->cs_base + eip;
2227
2228 if (use_goto_tb(s, pc)) {
2229
2230 tcg_gen_goto_tb(tb_num);
2231 gen_jmp_im(s, eip);
2232 tcg_gen_exit_tb(s->base.tb, tb_num);
2233 s->base.is_jmp = DISAS_NORETURN;
2234 } else {
2235
2236 gen_jmp_im(s, eip);
2237 gen_jr(s, s->tmp0);
2238 }
2239}
2240
2241static inline void gen_jcc(DisasContext *s, int b,
2242 target_ulong val, target_ulong next_eip)
2243{
2244 TCGLabel *l1, *l2;
2245
2246 if (s->jmp_opt) {
2247 l1 = gen_new_label();
2248 gen_jcc1(s, b, l1);
2249
2250 gen_goto_tb(s, 0, next_eip);
2251
2252 gen_set_label(l1);
2253 gen_goto_tb(s, 1, val);
2254 } else {
2255 l1 = gen_new_label();
2256 l2 = gen_new_label();
2257 gen_jcc1(s, b, l1);
2258
2259 gen_jmp_im(s, next_eip);
2260 tcg_gen_br(l2);
2261
2262 gen_set_label(l1);
2263 gen_jmp_im(s, val);
2264 gen_set_label(l2);
2265 gen_eob(s);
2266 }
2267}
2268
2269static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
2270 int modrm, int reg)
2271{
2272 CCPrepare cc;
2273
2274 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2275
2276 cc = gen_prepare_cc(s, b, s->T1);
2277 if (cc.mask != -1) {
2278 TCGv t0 = tcg_temp_new();
2279 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2280 cc.reg = t0;
2281 }
2282 if (!cc.use_reg2) {
2283 cc.reg2 = tcg_const_tl(cc.imm);
2284 }
2285
2286 tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2,
2287 s->T0, cpu_regs[reg]);
2288 gen_op_mov_reg_v(s, ot, reg, s->T0);
2289
2290 if (cc.mask != -1) {
2291 tcg_temp_free(cc.reg);
2292 }
2293 if (!cc.use_reg2) {
2294 tcg_temp_free(cc.reg2);
2295 }
2296}
2297
2298static inline void gen_op_movl_T0_seg(DisasContext *s, int seg_reg)
2299{
2300 tcg_gen_ld32u_tl(s->T0, cpu_env,
2301 offsetof(CPUX86State,segs[seg_reg].selector));
2302}
2303
2304static inline void gen_op_movl_seg_T0_vm(DisasContext *s, int seg_reg)
2305{
2306 tcg_gen_ext16u_tl(s->T0, s->T0);
2307 tcg_gen_st32_tl(s->T0, cpu_env,
2308 offsetof(CPUX86State,segs[seg_reg].selector));
2309 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
2310}
2311
2312
2313
2314static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
2315{
2316 if (s->pe && !s->vm86) {
2317 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
2318 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), s->tmp2_i32);
2319
2320
2321
2322
2323 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) {
2324 s->base.is_jmp = DISAS_TOO_MANY;
2325 }
2326 } else {
2327 gen_op_movl_seg_T0_vm(s, seg_reg);
2328 if (seg_reg == R_SS) {
2329 s->base.is_jmp = DISAS_TOO_MANY;
2330 }
2331 }
2332}
2333
2334static inline int svm_is_rep(int prefixes)
2335{
2336 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2337}
2338
2339static inline void
2340gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2341 uint32_t type, uint64_t param)
2342{
2343
2344 if (likely(!(s->flags & HF_GUEST_MASK)))
2345 return;
2346 gen_update_cc_op(s);
2347 gen_jmp_im(s, pc_start - s->cs_base);
2348 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2349 tcg_const_i64(param));
2350}
2351
2352static inline void
2353gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2354{
2355 gen_svm_check_intercept_param(s, pc_start, type, 0);
2356}
2357
2358static inline void gen_stack_update(DisasContext *s, int addend)
2359{
2360 gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend);
2361}
2362
2363
2364static void gen_push_v(DisasContext *s, TCGv val)
2365{
2366 MemOp d_ot = mo_pushpop(s, s->dflag);
2367 MemOp a_ot = mo_stacksize(s);
2368 int size = 1 << d_ot;
2369 TCGv new_esp = s->A0;
2370
2371 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2372
2373 if (!CODE64(s)) {
2374 if (s->addseg) {
2375 new_esp = s->tmp4;
2376 tcg_gen_mov_tl(new_esp, s->A0);
2377 }
2378 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2379 }
2380
2381 gen_op_st_v(s, d_ot, val, s->A0);
2382 gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp);
2383}
2384
2385
2386static MemOp gen_pop_T0(DisasContext *s)
2387{
2388 MemOp d_ot = mo_pushpop(s, s->dflag);
2389
2390 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
2391 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2392
2393 return d_ot;
2394}
2395
2396static inline void gen_pop_update(DisasContext *s, MemOp ot)
2397{
2398 gen_stack_update(s, 1 << ot);
2399}
2400
2401static inline void gen_stack_A0(DisasContext *s)
2402{
2403 gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2404}
2405
2406static void gen_pusha(DisasContext *s)
2407{
2408 MemOp s_ot = s->ss32 ? MO_32 : MO_16;
2409 MemOp d_ot = s->dflag;
2410 int size = 1 << d_ot;
2411 int i;
2412
2413 for (i = 0; i < 8; i++) {
2414 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size);
2415 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2416 gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0);
2417 }
2418
2419 gen_stack_update(s, -8 * size);
2420}
2421
2422static void gen_popa(DisasContext *s)
2423{
2424 MemOp s_ot = s->ss32 ? MO_32 : MO_16;
2425 MemOp d_ot = s->dflag;
2426 int size = 1 << d_ot;
2427 int i;
2428
2429 for (i = 0; i < 8; i++) {
2430
2431 if (7 - i == R_ESP) {
2432 continue;
2433 }
2434 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size);
2435 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2436 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2437 gen_op_mov_reg_v(s, d_ot, 7 - i, s->T0);
2438 }
2439
2440 gen_stack_update(s, 8 * size);
2441}
2442
2443static void gen_enter(DisasContext *s, int esp_addend, int level)
2444{
2445 MemOp d_ot = mo_pushpop(s, s->dflag);
2446 MemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
2447 int size = 1 << d_ot;
2448
2449
2450 tcg_gen_subi_tl(s->T1, cpu_regs[R_ESP], size);
2451 gen_lea_v_seg(s, a_ot, s->T1, R_SS, -1);
2452 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0);
2453
2454 level &= 31;
2455 if (level != 0) {
2456 int i;
2457
2458
2459 for (i = 1; i < level; ++i) {
2460 tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i);
2461 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2462 gen_op_ld_v(s, d_ot, s->tmp0, s->A0);
2463
2464 tcg_gen_subi_tl(s->A0, s->T1, size * i);
2465 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2466 gen_op_st_v(s, d_ot, s->tmp0, s->A0);
2467 }
2468
2469
2470 tcg_gen_subi_tl(s->A0, s->T1, size * level);
2471 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2472 gen_op_st_v(s, d_ot, s->T1, s->A0);
2473 }
2474
2475
2476 gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
2477
2478
2479 tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
2480 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2481}
2482
2483static void gen_leave(DisasContext *s)
2484{
2485 MemOp d_ot = mo_pushpop(s, s->dflag);
2486 MemOp a_ot = mo_stacksize(s);
2487
2488 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
2489 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2490
2491 tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot);
2492
2493 gen_op_mov_reg_v(s, d_ot, R_EBP, s->T0);
2494 gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
2495}
2496
2497
2498
2499
2500static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2501{
2502 gen_illegal_opcode(s);
2503
2504 if (qemu_loglevel_mask(LOG_UNIMP)) {
2505 target_ulong pc = s->pc_start, end = s->pc;
2506 qemu_log_lock();
2507 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2508 for (; pc < end; ++pc) {
2509 qemu_log(" %02x", cpu_ldub_code(env, pc));
2510 }
2511 qemu_log("\n");
2512 qemu_log_unlock();
2513 }
2514}
2515
2516
2517
2518static void gen_interrupt(DisasContext *s, int intno,
2519 target_ulong cur_eip, target_ulong next_eip)
2520{
2521 gen_update_cc_op(s);
2522 gen_jmp_im(s, cur_eip);
2523 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2524 tcg_const_i32(next_eip - cur_eip));
2525 s->base.is_jmp = DISAS_NORETURN;
2526}
2527
2528static void gen_debug(DisasContext *s, target_ulong cur_eip)
2529{
2530 gen_update_cc_op(s);
2531 gen_jmp_im(s, cur_eip);
2532 gen_helper_debug(cpu_env);
2533 s->base.is_jmp = DISAS_NORETURN;
2534}
2535
2536static void gen_set_hflag(DisasContext *s, uint32_t mask)
2537{
2538 if ((s->flags & mask) == 0) {
2539 TCGv_i32 t = tcg_temp_new_i32();
2540 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2541 tcg_gen_ori_i32(t, t, mask);
2542 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2543 tcg_temp_free_i32(t);
2544 s->flags |= mask;
2545 }
2546}
2547
2548static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2549{
2550 if (s->flags & mask) {
2551 TCGv_i32 t = tcg_temp_new_i32();
2552 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2553 tcg_gen_andi_i32(t, t, ~mask);
2554 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2555 tcg_temp_free_i32(t);
2556 s->flags &= ~mask;
2557 }
2558}
2559
2560
2561static void gen_bnd_jmp(DisasContext *s)
2562{
2563
2564
2565
2566 if ((s->prefix & PREFIX_REPNZ) == 0
2567 && (s->flags & HF_MPX_EN_MASK) != 0
2568 && (s->flags & HF_MPX_IU_MASK) != 0) {
2569 gen_helper_bnd_jmp(cpu_env);
2570 }
2571}
2572
2573
2574
2575
2576
2577static void
2578do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2579{
2580 gen_update_cc_op(s);
2581
2582
2583 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2584 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2585 } else {
2586 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2587 }
2588
2589 if (s->base.tb->flags & HF_RF_MASK) {
2590 gen_helper_reset_rf(cpu_env);
2591 }
2592 if (s->base.singlestep_enabled) {
2593 gen_helper_debug(cpu_env);
2594 } else if (recheck_tf) {
2595 gen_helper_rechecking_single_step(cpu_env);
2596 tcg_gen_exit_tb(NULL, 0);
2597 } else if (s->tf) {
2598 gen_helper_single_step(cpu_env);
2599 } else if (jr) {
2600 tcg_gen_lookup_and_goto_ptr();
2601 } else {
2602 tcg_gen_exit_tb(NULL, 0);
2603 }
2604 s->base.is_jmp = DISAS_NORETURN;
2605}
2606
2607static inline void
2608gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2609{
2610 do_gen_eob_worker(s, inhibit, recheck_tf, false);
2611}
2612
2613
2614
2615static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2616{
2617 gen_eob_worker(s, inhibit, false);
2618}
2619
2620
2621static void gen_eob(DisasContext *s)
2622{
2623 gen_eob_worker(s, false, false);
2624}
2625
2626
2627static void gen_jr(DisasContext *s, TCGv dest)
2628{
2629 do_gen_eob_worker(s, false, false, true);
2630}
2631
2632
2633
2634static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2635{
2636 gen_update_cc_op(s);
2637 set_cc_op(s, CC_OP_DYNAMIC);
2638 if (s->jmp_opt) {
2639 gen_goto_tb(s, tb_num, eip);
2640 } else {
2641 gen_jmp_im(s, eip);
2642 gen_eob(s);
2643 }
2644}
2645
2646static void gen_jmp(DisasContext *s, target_ulong eip)
2647{
2648 gen_jmp_tb(s, eip, 0);
2649}
2650
2651static inline void gen_ldq_env_A0(DisasContext *s, int offset)
2652{
2653 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2654 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset);
2655}
2656
2657static inline void gen_stq_env_A0(DisasContext *s, int offset)
2658{
2659 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset);
2660 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
2661}
2662
2663static inline void gen_ldo_env_A0(DisasContext *s, int offset)
2664{
2665 int mem_index = s->mem_index;
2666 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2667 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2668 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2669 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2670 tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2671}
2672
2673static inline void gen_sto_env_A0(DisasContext *s, int offset)
2674{
2675 int mem_index = s->mem_index;
2676 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
2677 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
2678 tcg_gen_addi_tl(s->tmp0, s->A0, 8);
2679 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
2680 tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
2681}
2682
2683static inline void gen_op_movo(DisasContext *s, int d_offset, int s_offset)
2684{
2685 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2686 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2687 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2688 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
2689}
2690
2691static inline void gen_op_movq(DisasContext *s, int d_offset, int s_offset)
2692{
2693 tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset);
2694 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2695}
2696
2697static inline void gen_op_movl(DisasContext *s, int d_offset, int s_offset)
2698{
2699 tcg_gen_ld_i32(s->tmp2_i32, cpu_env, s_offset);
2700 tcg_gen_st_i32(s->tmp2_i32, cpu_env, d_offset);
2701}
2702
2703static inline void gen_op_movq_env_0(DisasContext *s, int d_offset)
2704{
2705 tcg_gen_movi_i64(s->tmp1_i64, 0);
2706 tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset);
2707}
2708
2709typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2710typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2711typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2712typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2713typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2714typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2715 TCGv_i32 val);
2716typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2717typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2718 TCGv val);
2719
2720#define SSE_SPECIAL ((void *)1)
2721#define SSE_DUMMY ((void *)2)
2722
2723#define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2724#define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2725 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2726
2727static const SSEFunc_0_epp sse_op_table1[256][4] = {
2728
2729 [0x0e] = { SSE_DUMMY },
2730 [0x0f] = { SSE_DUMMY },
2731
2732 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2733 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2734 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2735 [0x13] = { SSE_SPECIAL, SSE_SPECIAL },
2736 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2737 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2738 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2739 [0x17] = { SSE_SPECIAL, SSE_SPECIAL },
2740
2741 [0x28] = { SSE_SPECIAL, SSE_SPECIAL },
2742 [0x29] = { SSE_SPECIAL, SSE_SPECIAL },
2743 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2744 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2745 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2746 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2747 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2748 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2749 [0x50] = { SSE_SPECIAL, SSE_SPECIAL },
2750 [0x51] = SSE_FOP(sqrt),
2751 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2752 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2753 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm },
2754 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm },
2755 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm },
2756 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm },
2757 [0x58] = SSE_FOP(add),
2758 [0x59] = SSE_FOP(mul),
2759 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2760 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2761 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2762 [0x5c] = SSE_FOP(sub),
2763 [0x5d] = SSE_FOP(min),
2764 [0x5e] = SSE_FOP(div),
2765 [0x5f] = SSE_FOP(max),
2766
2767 [0xc2] = SSE_FOP(cmpeq),
2768 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2769 (SSEFunc_0_epp)gen_helper_shufpd },
2770
2771
2772 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2773 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2774
2775
2776 [0x60] = MMX_OP2(punpcklbw),
2777 [0x61] = MMX_OP2(punpcklwd),
2778 [0x62] = MMX_OP2(punpckldq),
2779 [0x63] = MMX_OP2(packsswb),
2780 [0x64] = MMX_OP2(pcmpgtb),
2781 [0x65] = MMX_OP2(pcmpgtw),
2782 [0x66] = MMX_OP2(pcmpgtl),
2783 [0x67] = MMX_OP2(packuswb),
2784 [0x68] = MMX_OP2(punpckhbw),
2785 [0x69] = MMX_OP2(punpckhwd),
2786 [0x6a] = MMX_OP2(punpckhdq),
2787 [0x6b] = MMX_OP2(packssdw),
2788 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2789 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2790 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL },
2791 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2792 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2793 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2794 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2795 (SSEFunc_0_epp)gen_helper_pshuflw_xmm },
2796 [0x71] = { SSE_SPECIAL, SSE_SPECIAL },
2797 [0x72] = { SSE_SPECIAL, SSE_SPECIAL },
2798 [0x73] = { SSE_SPECIAL, SSE_SPECIAL },
2799 [0x74] = MMX_OP2(pcmpeqb),
2800 [0x75] = MMX_OP2(pcmpeqw),
2801 [0x76] = MMX_OP2(pcmpeql),
2802 [0x77] = { SSE_DUMMY },
2803 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL },
2804 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2805 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2806 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2807 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2808 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2809 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL },
2810 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL },
2811 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2812 [0xd1] = MMX_OP2(psrlw),
2813 [0xd2] = MMX_OP2(psrld),
2814 [0xd3] = MMX_OP2(psrlq),
2815 [0xd4] = MMX_OP2(paddq),
2816 [0xd5] = MMX_OP2(pmullw),
2817 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2818 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL },
2819 [0xd8] = MMX_OP2(psubusb),
2820 [0xd9] = MMX_OP2(psubusw),
2821 [0xda] = MMX_OP2(pminub),
2822 [0xdb] = MMX_OP2(pand),
2823 [0xdc] = MMX_OP2(paddusb),
2824 [0xdd] = MMX_OP2(paddusw),
2825 [0xde] = MMX_OP2(pmaxub),
2826 [0xdf] = MMX_OP2(pandn),
2827 [0xe0] = MMX_OP2(pavgb),
2828 [0xe1] = MMX_OP2(psraw),
2829 [0xe2] = MMX_OP2(psrad),
2830 [0xe3] = MMX_OP2(pavgw),
2831 [0xe4] = MMX_OP2(pmulhuw),
2832 [0xe5] = MMX_OP2(pmulhw),
2833 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
2834 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },
2835 [0xe8] = MMX_OP2(psubsb),
2836 [0xe9] = MMX_OP2(psubsw),
2837 [0xea] = MMX_OP2(pminsw),
2838 [0xeb] = MMX_OP2(por),
2839 [0xec] = MMX_OP2(paddsb),
2840 [0xed] = MMX_OP2(paddsw),
2841 [0xee] = MMX_OP2(pmaxsw),
2842 [0xef] = MMX_OP2(pxor),
2843 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL },
2844 [0xf1] = MMX_OP2(psllw),
2845 [0xf2] = MMX_OP2(pslld),
2846 [0xf3] = MMX_OP2(psllq),
2847 [0xf4] = MMX_OP2(pmuludq),
2848 [0xf5] = MMX_OP2(pmaddwd),
2849 [0xf6] = MMX_OP2(psadbw),
2850 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2851 (SSEFunc_0_epp)gen_helper_maskmov_xmm },
2852 [0xf8] = MMX_OP2(psubb),
2853 [0xf9] = MMX_OP2(psubw),
2854 [0xfa] = MMX_OP2(psubl),
2855 [0xfb] = MMX_OP2(psubq),
2856 [0xfc] = MMX_OP2(paddb),
2857 [0xfd] = MMX_OP2(paddw),
2858 [0xfe] = MMX_OP2(paddl),
2859};
2860
2861static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
2862 [0 + 2] = MMX_OP2(psrlw),
2863 [0 + 4] = MMX_OP2(psraw),
2864 [0 + 6] = MMX_OP2(psllw),
2865 [8 + 2] = MMX_OP2(psrld),
2866 [8 + 4] = MMX_OP2(psrad),
2867 [8 + 6] = MMX_OP2(pslld),
2868 [16 + 2] = MMX_OP2(psrlq),
2869 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
2870 [16 + 6] = MMX_OP2(psllq),
2871 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
2872};
2873
2874static const SSEFunc_0_epi sse_op_table3ai[] = {
2875 gen_helper_cvtsi2ss,
2876 gen_helper_cvtsi2sd
2877};
2878
2879#ifdef TARGET_X86_64
2880static const SSEFunc_0_epl sse_op_table3aq[] = {
2881 gen_helper_cvtsq2ss,
2882 gen_helper_cvtsq2sd
2883};
2884#endif
2885
2886static const SSEFunc_i_ep sse_op_table3bi[] = {
2887 gen_helper_cvttss2si,
2888 gen_helper_cvtss2si,
2889 gen_helper_cvttsd2si,
2890 gen_helper_cvtsd2si
2891};
2892
2893#ifdef TARGET_X86_64
2894static const SSEFunc_l_ep sse_op_table3bq[] = {
2895 gen_helper_cvttss2sq,
2896 gen_helper_cvtss2sq,
2897 gen_helper_cvttsd2sq,
2898 gen_helper_cvtsd2sq
2899};
2900#endif
2901
2902static const SSEFunc_0_epp sse_op_table4[8][4] = {
2903 SSE_FOP(cmpeq),
2904 SSE_FOP(cmplt),
2905 SSE_FOP(cmple),
2906 SSE_FOP(cmpunord),
2907 SSE_FOP(cmpneq),
2908 SSE_FOP(cmpnlt),
2909 SSE_FOP(cmpnle),
2910 SSE_FOP(cmpord),
2911};
2912
2913static const SSEFunc_0_epp sse_op_table5[256] = {
2914 [0x0c] = gen_helper_pi2fw,
2915 [0x0d] = gen_helper_pi2fd,
2916 [0x1c] = gen_helper_pf2iw,
2917 [0x1d] = gen_helper_pf2id,
2918 [0x8a] = gen_helper_pfnacc,
2919 [0x8e] = gen_helper_pfpnacc,
2920 [0x90] = gen_helper_pfcmpge,
2921 [0x94] = gen_helper_pfmin,
2922 [0x96] = gen_helper_pfrcp,
2923 [0x97] = gen_helper_pfrsqrt,
2924 [0x9a] = gen_helper_pfsub,
2925 [0x9e] = gen_helper_pfadd,
2926 [0xa0] = gen_helper_pfcmpgt,
2927 [0xa4] = gen_helper_pfmax,
2928 [0xa6] = gen_helper_movq,
2929 [0xa7] = gen_helper_movq,
2930 [0xaa] = gen_helper_pfsubr,
2931 [0xae] = gen_helper_pfacc,
2932 [0xb0] = gen_helper_pfcmpeq,
2933 [0xb4] = gen_helper_pfmul,
2934 [0xb6] = gen_helper_movq,
2935 [0xb7] = gen_helper_pmulhrw_mmx,
2936 [0xbb] = gen_helper_pswapd,
2937 [0xbf] = gen_helper_pavgb_mmx
2938};
2939
2940struct SSEOpHelper_epp {
2941 SSEFunc_0_epp op[2];
2942 uint32_t ext_mask;
2943};
2944
2945struct SSEOpHelper_eppi {
2946 SSEFunc_0_eppi op[2];
2947 uint32_t ext_mask;
2948};
2949
2950#define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2951#define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2952#define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
2953#define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
2954#define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2955 CPUID_EXT_PCLMULQDQ }
2956#define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
2957
2958static const struct SSEOpHelper_epp sse_op_table6[256] = {
2959 [0x00] = SSSE3_OP(pshufb),
2960 [0x01] = SSSE3_OP(phaddw),
2961 [0x02] = SSSE3_OP(phaddd),
2962 [0x03] = SSSE3_OP(phaddsw),
2963 [0x04] = SSSE3_OP(pmaddubsw),
2964 [0x05] = SSSE3_OP(phsubw),
2965 [0x06] = SSSE3_OP(phsubd),
2966 [0x07] = SSSE3_OP(phsubsw),
2967 [0x08] = SSSE3_OP(psignb),
2968 [0x09] = SSSE3_OP(psignw),
2969 [0x0a] = SSSE3_OP(psignd),
2970 [0x0b] = SSSE3_OP(pmulhrsw),
2971 [0x10] = SSE41_OP(pblendvb),
2972 [0x14] = SSE41_OP(blendvps),
2973 [0x15] = SSE41_OP(blendvpd),
2974 [0x17] = SSE41_OP(ptest),
2975 [0x1c] = SSSE3_OP(pabsb),
2976 [0x1d] = SSSE3_OP(pabsw),
2977 [0x1e] = SSSE3_OP(pabsd),
2978 [0x20] = SSE41_OP(pmovsxbw),
2979 [0x21] = SSE41_OP(pmovsxbd),
2980 [0x22] = SSE41_OP(pmovsxbq),
2981 [0x23] = SSE41_OP(pmovsxwd),
2982 [0x24] = SSE41_OP(pmovsxwq),
2983 [0x25] = SSE41_OP(pmovsxdq),
2984 [0x28] = SSE41_OP(pmuldq),
2985 [0x29] = SSE41_OP(pcmpeqq),
2986 [0x2a] = SSE41_SPECIAL,
2987 [0x2b] = SSE41_OP(packusdw),
2988 [0x30] = SSE41_OP(pmovzxbw),
2989 [0x31] = SSE41_OP(pmovzxbd),
2990 [0x32] = SSE41_OP(pmovzxbq),
2991 [0x33] = SSE41_OP(pmovzxwd),
2992 [0x34] = SSE41_OP(pmovzxwq),
2993 [0x35] = SSE41_OP(pmovzxdq),
2994 [0x37] = SSE42_OP(pcmpgtq),
2995 [0x38] = SSE41_OP(pminsb),
2996 [0x39] = SSE41_OP(pminsd),
2997 [0x3a] = SSE41_OP(pminuw),
2998 [0x3b] = SSE41_OP(pminud),
2999 [0x3c] = SSE41_OP(pmaxsb),
3000 [0x3d] = SSE41_OP(pmaxsd),
3001 [0x3e] = SSE41_OP(pmaxuw),
3002 [0x3f] = SSE41_OP(pmaxud),
3003 [0x40] = SSE41_OP(pmulld),
3004 [0x41] = SSE41_OP(phminposuw),
3005 [0xdb] = AESNI_OP(aesimc),
3006 [0xdc] = AESNI_OP(aesenc),
3007 [0xdd] = AESNI_OP(aesenclast),
3008 [0xde] = AESNI_OP(aesdec),
3009 [0xdf] = AESNI_OP(aesdeclast),
3010};
3011
3012static const struct SSEOpHelper_eppi sse_op_table7[256] = {
3013 [0x08] = SSE41_OP(roundps),
3014 [0x09] = SSE41_OP(roundpd),
3015 [0x0a] = SSE41_OP(roundss),
3016 [0x0b] = SSE41_OP(roundsd),
3017 [0x0c] = SSE41_OP(blendps),
3018 [0x0d] = SSE41_OP(blendpd),
3019 [0x0e] = SSE41_OP(pblendw),
3020 [0x0f] = SSSE3_OP(palignr),
3021 [0x14] = SSE41_SPECIAL,
3022 [0x15] = SSE41_SPECIAL,
3023 [0x16] = SSE41_SPECIAL,
3024 [0x17] = SSE41_SPECIAL,
3025 [0x20] = SSE41_SPECIAL,
3026 [0x21] = SSE41_SPECIAL,
3027 [0x22] = SSE41_SPECIAL,
3028 [0x40] = SSE41_OP(dpps),
3029 [0x41] = SSE41_OP(dppd),
3030 [0x42] = SSE41_OP(mpsadbw),
3031 [0x44] = PCLMULQDQ_OP(pclmulqdq),
3032 [0x60] = SSE42_OP(pcmpestrm),
3033 [0x61] = SSE42_OP(pcmpestri),
3034 [0x62] = SSE42_OP(pcmpistrm),
3035 [0x63] = SSE42_OP(pcmpistri),
3036 [0xdf] = AESNI_OP(aeskeygenassist),
3037};
3038
3039static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3040 target_ulong pc_start, int rex_r)
3041{
3042 int b1, op1_offset, op2_offset, is_xmm, val;
3043 int modrm, mod, rm, reg;
3044 SSEFunc_0_epp sse_fn_epp;
3045 SSEFunc_0_eppi sse_fn_eppi;
3046 SSEFunc_0_ppi sse_fn_ppi;
3047 SSEFunc_0_eppt sse_fn_eppt;
3048 MemOp ot;
3049
3050 b &= 0xff;
3051 if (s->prefix & PREFIX_DATA)
3052 b1 = 1;
3053 else if (s->prefix & PREFIX_REPZ)
3054 b1 = 2;
3055 else if (s->prefix & PREFIX_REPNZ)
3056 b1 = 3;
3057 else
3058 b1 = 0;
3059 sse_fn_epp = sse_op_table1[b][b1];
3060 if (!sse_fn_epp) {
3061 goto unknown_op;
3062 }
3063 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3064 is_xmm = 1;
3065 } else {
3066 if (b1 == 0) {
3067
3068 is_xmm = 0;
3069 } else {
3070 is_xmm = 1;
3071 }
3072 }
3073
3074 if (s->flags & HF_TS_MASK) {
3075 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3076 return;
3077 }
3078 if (s->flags & HF_EM_MASK) {
3079 illegal_op:
3080 gen_illegal_opcode(s);
3081 return;
3082 }
3083 if (is_xmm
3084 && !(s->flags & HF_OSFXSR_MASK)
3085 && ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
3086 goto unknown_op;
3087 }
3088 if (b == 0x0e) {
3089 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3090
3091 goto unknown_op;
3092 }
3093
3094 gen_helper_emms(cpu_env);
3095 return;
3096 }
3097 if (b == 0x77) {
3098
3099 gen_helper_emms(cpu_env);
3100 return;
3101 }
3102
3103
3104 if (!is_xmm) {
3105 gen_helper_enter_mmx(cpu_env);
3106 }
3107
3108 modrm = x86_ldub_code(env, s);
3109 reg = ((modrm >> 3) & 7);
3110 if (is_xmm)
3111 reg |= rex_r;
3112 mod = (modrm >> 6) & 3;
3113 if (sse_fn_epp == SSE_SPECIAL) {
3114 b |= (b1 << 8);
3115 switch(b) {
3116 case 0x0e7:
3117 if (mod == 3) {
3118 goto illegal_op;
3119 }
3120 gen_lea_modrm(env, s, modrm);
3121 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3122 break;
3123 case 0x1e7:
3124 case 0x02b:
3125 case 0x12b:
3126 if (mod == 3)
3127 goto illegal_op;
3128 gen_lea_modrm(env, s, modrm);
3129 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3130 break;
3131 case 0x3f0:
3132 if (mod == 3)
3133 goto illegal_op;
3134 gen_lea_modrm(env, s, modrm);
3135 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3136 break;
3137 case 0x22b:
3138 case 0x32b:
3139 if (mod == 3)
3140 goto illegal_op;
3141 gen_lea_modrm(env, s, modrm);
3142 if (b1 & 1) {
3143 gen_stq_env_A0(s, offsetof(CPUX86State,
3144 xmm_regs[reg].ZMM_Q(0)));
3145 } else {
3146 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
3147 xmm_regs[reg].ZMM_L(0)));
3148 gen_op_st_v(s, MO_32, s->T0, s->A0);
3149 }
3150 break;
3151 case 0x6e:
3152#ifdef TARGET_X86_64
3153 if (s->dflag == MO_64) {
3154 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3155 tcg_gen_st_tl(s->T0, cpu_env,
3156 offsetof(CPUX86State, fpregs[reg].mmx));
3157 } else
3158#endif
3159 {
3160 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3161 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3162 offsetof(CPUX86State,fpregs[reg].mmx));
3163 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3164 gen_helper_movl_mm_T0_mmx(s->ptr0, s->tmp2_i32);
3165 }
3166 break;
3167 case 0x16e:
3168#ifdef TARGET_X86_64
3169 if (s->dflag == MO_64) {
3170 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
3171 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3172 offsetof(CPUX86State,xmm_regs[reg]));
3173 gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0);
3174 } else
3175#endif
3176 {
3177 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
3178 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3179 offsetof(CPUX86State,xmm_regs[reg]));
3180 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3181 gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32);
3182 }
3183 break;
3184 case 0x6f:
3185 if (mod != 3) {
3186 gen_lea_modrm(env, s, modrm);
3187 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3188 } else {
3189 rm = (modrm & 7);
3190 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
3191 offsetof(CPUX86State,fpregs[rm].mmx));
3192 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
3193 offsetof(CPUX86State,fpregs[reg].mmx));
3194 }
3195 break;
3196 case 0x010:
3197 case 0x110:
3198 case 0x028:
3199 case 0x128:
3200 case 0x16f:
3201 case 0x26f:
3202 if (mod != 3) {
3203 gen_lea_modrm(env, s, modrm);
3204 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3205 } else {
3206 rm = (modrm & 7) | REX_B(s);
3207 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[reg]),
3208 offsetof(CPUX86State,xmm_regs[rm]));
3209 }
3210 break;
3211 case 0x210:
3212 if (mod != 3) {
3213 gen_lea_modrm(env, s, modrm);
3214 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3215 tcg_gen_st32_tl(s->T0, cpu_env,
3216 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3217 tcg_gen_movi_tl(s->T0, 0);
3218 tcg_gen_st32_tl(s->T0, cpu_env,
3219 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)));
3220 tcg_gen_st32_tl(s->T0, cpu_env,
3221 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3222 tcg_gen_st32_tl(s->T0, cpu_env,
3223 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3224 } else {
3225 rm = (modrm & 7) | REX_B(s);
3226 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3227 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3228 }
3229 break;
3230 case 0x310:
3231 if (mod != 3) {
3232 gen_lea_modrm(env, s, modrm);
3233 gen_ldq_env_A0(s, offsetof(CPUX86State,
3234 xmm_regs[reg].ZMM_Q(0)));
3235 tcg_gen_movi_tl(s->T0, 0);
3236 tcg_gen_st32_tl(s->T0, cpu_env,
3237 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3238 tcg_gen_st32_tl(s->T0, cpu_env,
3239 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
3240 } else {
3241 rm = (modrm & 7) | REX_B(s);
3242 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3243 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3244 }
3245 break;
3246 case 0x012:
3247 case 0x112:
3248 if (mod != 3) {
3249 gen_lea_modrm(env, s, modrm);
3250 gen_ldq_env_A0(s, offsetof(CPUX86State,
3251 xmm_regs[reg].ZMM_Q(0)));
3252 } else {
3253
3254 rm = (modrm & 7) | REX_B(s);
3255 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3256 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
3257 }
3258 break;
3259 case 0x212:
3260 if (mod != 3) {
3261 gen_lea_modrm(env, s, modrm);
3262 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3263 } else {
3264 rm = (modrm & 7) | REX_B(s);
3265 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3266 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3267 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3268 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
3269 }
3270 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3271 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3272 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3273 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
3274 break;
3275 case 0x312:
3276 if (mod != 3) {
3277 gen_lea_modrm(env, s, modrm);
3278 gen_ldq_env_A0(s, offsetof(CPUX86State,
3279 xmm_regs[reg].ZMM_Q(0)));
3280 } else {
3281 rm = (modrm & 7) | REX_B(s);
3282 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3283 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3284 }
3285 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3286 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3287 break;
3288 case 0x016:
3289 case 0x116:
3290 if (mod != 3) {
3291 gen_lea_modrm(env, s, modrm);
3292 gen_ldq_env_A0(s, offsetof(CPUX86State,
3293 xmm_regs[reg].ZMM_Q(1)));
3294 } else {
3295
3296 rm = (modrm & 7) | REX_B(s);
3297 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)),
3298 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3299 }
3300 break;
3301 case 0x216:
3302 if (mod != 3) {
3303 gen_lea_modrm(env, s, modrm);
3304 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3305 } else {
3306 rm = (modrm & 7) | REX_B(s);
3307 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
3308 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3309 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)),
3310 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
3311 }
3312 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
3313 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3314 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)),
3315 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
3316 break;
3317 case 0x178:
3318 case 0x378:
3319 {
3320 int bit_index, field_length;
3321
3322 if (b1 == 1 && reg != 0)
3323 goto illegal_op;
3324 field_length = x86_ldub_code(env, s) & 0x3F;
3325 bit_index = x86_ldub_code(env, s) & 0x3F;
3326 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3327 offsetof(CPUX86State,xmm_regs[reg]));
3328 if (b1 == 1)
3329 gen_helper_extrq_i(cpu_env, s->ptr0,
3330 tcg_const_i32(bit_index),
3331 tcg_const_i32(field_length));
3332 else
3333 gen_helper_insertq_i(cpu_env, s->ptr0,
3334 tcg_const_i32(bit_index),
3335 tcg_const_i32(field_length));
3336 }
3337 break;
3338 case 0x7e:
3339#ifdef TARGET_X86_64
3340 if (s->dflag == MO_64) {
3341 tcg_gen_ld_i64(s->T0, cpu_env,
3342 offsetof(CPUX86State,fpregs[reg].mmx));
3343 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3344 } else
3345#endif
3346 {
3347 tcg_gen_ld32u_tl(s->T0, cpu_env,
3348 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3349 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3350 }
3351 break;
3352 case 0x17e:
3353#ifdef TARGET_X86_64
3354 if (s->dflag == MO_64) {
3355 tcg_gen_ld_i64(s->T0, cpu_env,
3356 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3357 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
3358 } else
3359#endif
3360 {
3361 tcg_gen_ld32u_tl(s->T0, cpu_env,
3362 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3363 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
3364 }
3365 break;
3366 case 0x27e:
3367 if (mod != 3) {
3368 gen_lea_modrm(env, s, modrm);
3369 gen_ldq_env_A0(s, offsetof(CPUX86State,
3370 xmm_regs[reg].ZMM_Q(0)));
3371 } else {
3372 rm = (modrm & 7) | REX_B(s);
3373 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3374 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3375 }
3376 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3377 break;
3378 case 0x7f:
3379 if (mod != 3) {
3380 gen_lea_modrm(env, s, modrm);
3381 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
3382 } else {
3383 rm = (modrm & 7);
3384 gen_op_movq(s, offsetof(CPUX86State, fpregs[rm].mmx),
3385 offsetof(CPUX86State,fpregs[reg].mmx));
3386 }
3387 break;
3388 case 0x011:
3389 case 0x111:
3390 case 0x029:
3391 case 0x129:
3392 case 0x17f:
3393 case 0x27f:
3394 if (mod != 3) {
3395 gen_lea_modrm(env, s, modrm);
3396 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
3397 } else {
3398 rm = (modrm & 7) | REX_B(s);
3399 gen_op_movo(s, offsetof(CPUX86State, xmm_regs[rm]),
3400 offsetof(CPUX86State,xmm_regs[reg]));
3401 }
3402 break;
3403 case 0x211:
3404 if (mod != 3) {
3405 gen_lea_modrm(env, s, modrm);
3406 tcg_gen_ld32u_tl(s->T0, cpu_env,
3407 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3408 gen_op_st_v(s, MO_32, s->T0, s->A0);
3409 } else {
3410 rm = (modrm & 7) | REX_B(s);
3411 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0)),
3412 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3413 }
3414 break;
3415 case 0x311:
3416 if (mod != 3) {
3417 gen_lea_modrm(env, s, modrm);
3418 gen_stq_env_A0(s, offsetof(CPUX86State,
3419 xmm_regs[reg].ZMM_Q(0)));
3420 } else {
3421 rm = (modrm & 7) | REX_B(s);
3422 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3423 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3424 }
3425 break;
3426 case 0x013:
3427 case 0x113:
3428 if (mod != 3) {
3429 gen_lea_modrm(env, s, modrm);
3430 gen_stq_env_A0(s, offsetof(CPUX86State,
3431 xmm_regs[reg].ZMM_Q(0)));
3432 } else {
3433 goto illegal_op;
3434 }
3435 break;
3436 case 0x017:
3437 case 0x117:
3438 if (mod != 3) {
3439 gen_lea_modrm(env, s, modrm);
3440 gen_stq_env_A0(s, offsetof(CPUX86State,
3441 xmm_regs[reg].ZMM_Q(1)));
3442 } else {
3443 goto illegal_op;
3444 }
3445 break;
3446 case 0x71:
3447 case 0x72:
3448 case 0x73:
3449 case 0x171:
3450 case 0x172:
3451 case 0x173:
3452 if (b1 >= 2) {
3453 goto unknown_op;
3454 }
3455 val = x86_ldub_code(env, s);
3456 if (is_xmm) {
3457 tcg_gen_movi_tl(s->T0, val);
3458 tcg_gen_st32_tl(s->T0, cpu_env,
3459 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3460 tcg_gen_movi_tl(s->T0, 0);
3461 tcg_gen_st32_tl(s->T0, cpu_env,
3462 offsetof(CPUX86State, xmm_t0.ZMM_L(1)));
3463 op1_offset = offsetof(CPUX86State,xmm_t0);
3464 } else {
3465 tcg_gen_movi_tl(s->T0, val);
3466 tcg_gen_st32_tl(s->T0, cpu_env,
3467 offsetof(CPUX86State, mmx_t0.MMX_L(0)));
3468 tcg_gen_movi_tl(s->T0, 0);
3469 tcg_gen_st32_tl(s->T0, cpu_env,
3470 offsetof(CPUX86State, mmx_t0.MMX_L(1)));
3471 op1_offset = offsetof(CPUX86State,mmx_t0);
3472 }
3473 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3474 (((modrm >> 3)) & 7)][b1];
3475 if (!sse_fn_epp) {
3476 goto unknown_op;
3477 }
3478 if (is_xmm) {
3479 rm = (modrm & 7) | REX_B(s);
3480 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3481 } else {
3482 rm = (modrm & 7);
3483 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3484 }
3485 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3486 tcg_gen_addi_ptr(s->ptr1, cpu_env, op1_offset);
3487 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3488 break;
3489 case 0x050:
3490 rm = (modrm & 7) | REX_B(s);
3491 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3492 offsetof(CPUX86State,xmm_regs[rm]));
3493 gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0);
3494 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3495 break;
3496 case 0x150:
3497 rm = (modrm & 7) | REX_B(s);
3498 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3499 offsetof(CPUX86State,xmm_regs[rm]));
3500 gen_helper_movmskpd(s->tmp2_i32, cpu_env, s->ptr0);
3501 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3502 break;
3503 case 0x02a:
3504 case 0x12a:
3505 gen_helper_enter_mmx(cpu_env);
3506 if (mod != 3) {
3507 gen_lea_modrm(env, s, modrm);
3508 op2_offset = offsetof(CPUX86State,mmx_t0);
3509 gen_ldq_env_A0(s, op2_offset);
3510 } else {
3511 rm = (modrm & 7);
3512 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3513 }
3514 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3515 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3516 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3517 switch(b >> 8) {
3518 case 0x0:
3519 gen_helper_cvtpi2ps(cpu_env, s->ptr0, s->ptr1);
3520 break;
3521 default:
3522 case 0x1:
3523 gen_helper_cvtpi2pd(cpu_env, s->ptr0, s->ptr1);
3524 break;
3525 }
3526 break;
3527 case 0x22a:
3528 case 0x32a:
3529 ot = mo_64_32(s->dflag);
3530 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3531 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3532 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3533 if (ot == MO_32) {
3534 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3535 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3536 sse_fn_epi(cpu_env, s->ptr0, s->tmp2_i32);
3537 } else {
3538#ifdef TARGET_X86_64
3539 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3540 sse_fn_epl(cpu_env, s->ptr0, s->T0);
3541#else
3542 goto illegal_op;
3543#endif
3544 }
3545 break;
3546 case 0x02c:
3547 case 0x12c:
3548 case 0x02d:
3549 case 0x12d:
3550 gen_helper_enter_mmx(cpu_env);
3551 if (mod != 3) {
3552 gen_lea_modrm(env, s, modrm);
3553 op2_offset = offsetof(CPUX86State,xmm_t0);
3554 gen_ldo_env_A0(s, op2_offset);
3555 } else {
3556 rm = (modrm & 7) | REX_B(s);
3557 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3558 }
3559 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3560 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3561 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3562 switch(b) {
3563 case 0x02c:
3564 gen_helper_cvttps2pi(cpu_env, s->ptr0, s->ptr1);
3565 break;
3566 case 0x12c:
3567 gen_helper_cvttpd2pi(cpu_env, s->ptr0, s->ptr1);
3568 break;
3569 case 0x02d:
3570 gen_helper_cvtps2pi(cpu_env, s->ptr0, s->ptr1);
3571 break;
3572 case 0x12d:
3573 gen_helper_cvtpd2pi(cpu_env, s->ptr0, s->ptr1);
3574 break;
3575 }
3576 break;
3577 case 0x22c:
3578 case 0x32c:
3579 case 0x22d:
3580 case 0x32d:
3581 ot = mo_64_32(s->dflag);
3582 if (mod != 3) {
3583 gen_lea_modrm(env, s, modrm);
3584 if ((b >> 8) & 1) {
3585 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
3586 } else {
3587 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3588 tcg_gen_st32_tl(s->T0, cpu_env,
3589 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3590 }
3591 op2_offset = offsetof(CPUX86State,xmm_t0);
3592 } else {
3593 rm = (modrm & 7) | REX_B(s);
3594 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3595 }
3596 tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset);
3597 if (ot == MO_32) {
3598 SSEFunc_i_ep sse_fn_i_ep =
3599 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3600 sse_fn_i_ep(s->tmp2_i32, cpu_env, s->ptr0);
3601 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
3602 } else {
3603#ifdef TARGET_X86_64
3604 SSEFunc_l_ep sse_fn_l_ep =
3605 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3606 sse_fn_l_ep(s->T0, cpu_env, s->ptr0);
3607#else
3608 goto illegal_op;
3609#endif
3610 }
3611 gen_op_mov_reg_v(s, ot, reg, s->T0);
3612 break;
3613 case 0xc4:
3614 case 0x1c4:
3615 s->rip_offset = 1;
3616 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
3617 val = x86_ldub_code(env, s);
3618 if (b1) {
3619 val &= 7;
3620 tcg_gen_st16_tl(s->T0, cpu_env,
3621 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
3622 } else {
3623 val &= 3;
3624 tcg_gen_st16_tl(s->T0, cpu_env,
3625 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3626 }
3627 break;
3628 case 0xc5:
3629 case 0x1c5:
3630 if (mod != 3)
3631 goto illegal_op;
3632 ot = mo_64_32(s->dflag);
3633 val = x86_ldub_code(env, s);
3634 if (b1) {
3635 val &= 7;
3636 rm = (modrm & 7) | REX_B(s);
3637 tcg_gen_ld16u_tl(s->T0, cpu_env,
3638 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
3639 } else {
3640 val &= 3;
3641 rm = (modrm & 7);
3642 tcg_gen_ld16u_tl(s->T0, cpu_env,
3643 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3644 }
3645 reg = ((modrm >> 3) & 7) | rex_r;
3646 gen_op_mov_reg_v(s, ot, reg, s->T0);
3647 break;
3648 case 0x1d6:
3649 if (mod != 3) {
3650 gen_lea_modrm(env, s, modrm);
3651 gen_stq_env_A0(s, offsetof(CPUX86State,
3652 xmm_regs[reg].ZMM_Q(0)));
3653 } else {
3654 rm = (modrm & 7) | REX_B(s);
3655 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)),
3656 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3657 gen_op_movq_env_0(s,
3658 offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(1)));
3659 }
3660 break;
3661 case 0x2d6:
3662 gen_helper_enter_mmx(cpu_env);
3663 rm = (modrm & 7);
3664 gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
3665 offsetof(CPUX86State,fpregs[rm].mmx));
3666 gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
3667 break;
3668 case 0x3d6:
3669 gen_helper_enter_mmx(cpu_env);
3670 rm = (modrm & 7) | REX_B(s);
3671 gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx),
3672 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
3673 break;
3674 case 0xd7:
3675 case 0x1d7:
3676 if (mod != 3)
3677 goto illegal_op;
3678 if (b1) {
3679 rm = (modrm & 7) | REX_B(s);
3680 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3681 offsetof(CPUX86State, xmm_regs[rm]));
3682 gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0);
3683 } else {
3684 rm = (modrm & 7);
3685 tcg_gen_addi_ptr(s->ptr0, cpu_env,
3686 offsetof(CPUX86State, fpregs[rm].mmx));
3687 gen_helper_pmovmskb_mmx(s->tmp2_i32, cpu_env, s->ptr0);
3688 }
3689 reg = ((modrm >> 3) & 7) | rex_r;
3690 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
3691 break;
3692
3693 case 0x138:
3694 case 0x038:
3695 b = modrm;
3696 if ((b & 0xf0) == 0xf0) {
3697 goto do_0f_38_fx;
3698 }
3699 modrm = x86_ldub_code(env, s);
3700 rm = modrm & 7;
3701 reg = ((modrm >> 3) & 7) | rex_r;
3702 mod = (modrm >> 6) & 3;
3703 if (b1 >= 2) {
3704 goto unknown_op;
3705 }
3706
3707 sse_fn_epp = sse_op_table6[b].op[b1];
3708 if (!sse_fn_epp) {
3709 goto unknown_op;
3710 }
3711 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3712 goto illegal_op;
3713
3714 if (b1) {
3715 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3716 if (mod == 3) {
3717 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3718 } else {
3719 op2_offset = offsetof(CPUX86State,xmm_t0);
3720 gen_lea_modrm(env, s, modrm);
3721 switch (b) {
3722 case 0x20: case 0x30:
3723 case 0x23: case 0x33:
3724 case 0x25: case 0x35:
3725 gen_ldq_env_A0(s, op2_offset +
3726 offsetof(ZMMReg, ZMM_Q(0)));
3727 break;
3728 case 0x21: case 0x31:
3729 case 0x24: case 0x34:
3730 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
3731 s->mem_index, MO_LEUL);
3732 tcg_gen_st_i32(s->tmp2_i32, cpu_env, op2_offset +
3733 offsetof(ZMMReg, ZMM_L(0)));
3734 break;
3735 case 0x22: case 0x32:
3736 tcg_gen_qemu_ld_tl(s->tmp0, s->A0,
3737 s->mem_index, MO_LEUW);
3738 tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset +
3739 offsetof(ZMMReg, ZMM_W(0)));
3740 break;
3741 case 0x2a:
3742 gen_ldo_env_A0(s, op1_offset);
3743 return;
3744 default:
3745 gen_ldo_env_A0(s, op2_offset);
3746 }
3747 }
3748 } else {
3749 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3750 if (mod == 3) {
3751 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3752 } else {
3753 op2_offset = offsetof(CPUX86State,mmx_t0);
3754 gen_lea_modrm(env, s, modrm);
3755 gen_ldq_env_A0(s, op2_offset);
3756 }
3757 }
3758 if (sse_fn_epp == SSE_SPECIAL) {
3759 goto unknown_op;
3760 }
3761
3762 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
3763 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
3764 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
3765
3766 if (b == 0x17) {
3767 set_cc_op(s, CC_OP_EFLAGS);
3768 }
3769 break;
3770
3771 case 0x238:
3772 case 0x338:
3773 do_0f_38_fx:
3774
3775 b = modrm | (b1 << 8);
3776 modrm = x86_ldub_code(env, s);
3777 reg = ((modrm >> 3) & 7) | rex_r;
3778
3779 switch (b) {
3780 case 0x3f0:
3781 case 0x3f1:
3782 do_crc32:
3783 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3784 goto illegal_op;
3785 }
3786 if ((b & 0xff) == 0xf0) {
3787 ot = MO_8;
3788 } else if (s->dflag != MO_64) {
3789 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3790 } else {
3791 ot = MO_64;
3792 }
3793
3794 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[reg]);
3795 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3796 gen_helper_crc32(s->T0, s->tmp2_i32,
3797 s->T0, tcg_const_i32(8 << ot));
3798
3799 ot = mo_64_32(s->dflag);
3800 gen_op_mov_reg_v(s, ot, reg, s->T0);
3801 break;
3802
3803 case 0x1f0:
3804 case 0x1f1:
3805
3806
3807
3808 if (s->prefix & PREFIX_REPNZ) {
3809 goto do_crc32;
3810 }
3811
3812 case 0x0f0:
3813 case 0x0f1:
3814 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3815 goto illegal_op;
3816 }
3817 if (s->dflag != MO_64) {
3818 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
3819 } else {
3820 ot = MO_64;
3821 }
3822
3823 gen_lea_modrm(env, s, modrm);
3824 if ((b & 1) == 0) {
3825 tcg_gen_qemu_ld_tl(s->T0, s->A0,
3826 s->mem_index, ot | MO_BE);
3827 gen_op_mov_reg_v(s, ot, reg, s->T0);
3828 } else {
3829 tcg_gen_qemu_st_tl(cpu_regs[reg], s->A0,
3830 s->mem_index, ot | MO_BE);
3831 }
3832 break;
3833
3834 case 0x0f2:
3835 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3836 || !(s->prefix & PREFIX_VEX)
3837 || s->vex_l != 0) {
3838 goto illegal_op;
3839 }
3840 ot = mo_64_32(s->dflag);
3841 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3842 tcg_gen_andc_tl(s->T0, s->T0, cpu_regs[s->vex_v]);
3843 gen_op_mov_reg_v(s, ot, reg, s->T0);
3844 gen_op_update1_cc(s);
3845 set_cc_op(s, CC_OP_LOGICB + ot);
3846 break;
3847
3848 case 0x0f7:
3849 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3850 || !(s->prefix & PREFIX_VEX)
3851 || s->vex_l != 0) {
3852 goto illegal_op;
3853 }
3854 ot = mo_64_32(s->dflag);
3855 {
3856 TCGv bound, zero;
3857
3858 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3859
3860
3861 tcg_gen_ext8u_tl(s->A0, cpu_regs[s->vex_v]);
3862 tcg_gen_shr_tl(s->T0, s->T0, s->A0);
3863
3864 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3865 zero = tcg_const_tl(0);
3866 tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound,
3867 s->T0, zero);
3868 tcg_temp_free(zero);
3869
3870
3871
3872 tcg_gen_extract_tl(s->A0, cpu_regs[s->vex_v], 8, 8);
3873 tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound,
3874 s->A0, bound);
3875 tcg_temp_free(bound);
3876 tcg_gen_movi_tl(s->T1, 1);
3877 tcg_gen_shl_tl(s->T1, s->T1, s->A0);
3878 tcg_gen_subi_tl(s->T1, s->T1, 1);
3879 tcg_gen_and_tl(s->T0, s->T0, s->T1);
3880
3881 gen_op_mov_reg_v(s, ot, reg, s->T0);
3882 gen_op_update1_cc(s);
3883 set_cc_op(s, CC_OP_LOGICB + ot);
3884 }
3885 break;
3886
3887 case 0x0f5:
3888 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3889 || !(s->prefix & PREFIX_VEX)
3890 || s->vex_l != 0) {
3891 goto illegal_op;
3892 }
3893 ot = mo_64_32(s->dflag);
3894 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3895 tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]);
3896 {
3897 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
3898
3899
3900 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3901 s->T1, bound);
3902 tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1,
3903 bound, bound, s->T1);
3904 tcg_temp_free(bound);
3905 }
3906 tcg_gen_movi_tl(s->A0, -1);
3907 tcg_gen_shl_tl(s->A0, s->A0, s->T1);
3908 tcg_gen_andc_tl(s->T0, s->T0, s->A0);
3909 gen_op_mov_reg_v(s, ot, reg, s->T0);
3910 gen_op_update1_cc(s);
3911 set_cc_op(s, CC_OP_BMILGB + ot);
3912 break;
3913
3914 case 0x3f6:
3915 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3916 || !(s->prefix & PREFIX_VEX)
3917 || s->vex_l != 0) {
3918 goto illegal_op;
3919 }
3920 ot = mo_64_32(s->dflag);
3921 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3922 switch (ot) {
3923 default:
3924 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
3925 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EDX]);
3926 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
3927 s->tmp2_i32, s->tmp3_i32);
3928 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32);
3929 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp3_i32);
3930 break;
3931#ifdef TARGET_X86_64
3932 case MO_64:
3933 tcg_gen_mulu2_i64(s->T0, s->T1,
3934 s->T0, cpu_regs[R_EDX]);
3935 tcg_gen_mov_i64(cpu_regs[s->vex_v], s->T0);
3936 tcg_gen_mov_i64(cpu_regs[reg], s->T1);
3937 break;
3938#endif
3939 }
3940 break;
3941
3942 case 0x3f5:
3943 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3944 || !(s->prefix & PREFIX_VEX)
3945 || s->vex_l != 0) {
3946 goto illegal_op;
3947 }
3948 ot = mo_64_32(s->dflag);
3949 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3950
3951
3952 if (ot == MO_64) {
3953 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
3954 } else {
3955 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
3956 }
3957 gen_helper_pdep(cpu_regs[reg], s->T0, s->T1);
3958 break;
3959
3960 case 0x2f5:
3961 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3962 || !(s->prefix & PREFIX_VEX)
3963 || s->vex_l != 0) {
3964 goto illegal_op;
3965 }
3966 ot = mo_64_32(s->dflag);
3967 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3968
3969
3970 if (ot == MO_64) {
3971 tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]);
3972 } else {
3973 tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]);
3974 }
3975 gen_helper_pext(cpu_regs[reg], s->T0, s->T1);
3976 break;
3977
3978 case 0x1f6:
3979 case 0x2f6:
3980 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3981 goto illegal_op;
3982 } else {
3983 TCGv carry_in, carry_out, zero;
3984 int end_op;
3985
3986 ot = mo_64_32(s->dflag);
3987 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3988
3989
3990 carry_in = NULL;
3991 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3992 switch (s->cc_op) {
3993 case CC_OP_ADCX:
3994 if (b == 0x1f6) {
3995 carry_in = cpu_cc_dst;
3996 end_op = CC_OP_ADCX;
3997 } else {
3998 end_op = CC_OP_ADCOX;
3999 }
4000 break;
4001 case CC_OP_ADOX:
4002 if (b == 0x1f6) {
4003 end_op = CC_OP_ADCOX;
4004 } else {
4005 carry_in = cpu_cc_src2;
4006 end_op = CC_OP_ADOX;
4007 }
4008 break;
4009 case CC_OP_ADCOX:
4010 end_op = CC_OP_ADCOX;
4011 carry_in = carry_out;
4012 break;
4013 default:
4014 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
4015 break;
4016 }
4017
4018 if (!carry_in) {
4019 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4020 gen_compute_eflags(s);
4021 }
4022 carry_in = s->tmp0;
4023 tcg_gen_extract_tl(carry_in, cpu_cc_src,
4024 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
4025 }
4026
4027 switch (ot) {
4028#ifdef TARGET_X86_64
4029 case MO_32:
4030
4031
4032 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
4033 tcg_gen_ext32u_i64(s->T0, s->T0);
4034 tcg_gen_add_i64(s->T0, s->T0, cpu_regs[reg]);
4035 tcg_gen_add_i64(s->T0, s->T0, carry_in);
4036 tcg_gen_ext32u_i64(cpu_regs[reg], s->T0);
4037 tcg_gen_shri_i64(carry_out, s->T0, 32);
4038 break;
4039#endif
4040 default:
4041
4042 zero = tcg_const_tl(0);
4043 tcg_gen_add2_tl(s->T0, carry_out,
4044 s->T0, zero,
4045 carry_in, zero);
4046 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4047 cpu_regs[reg], carry_out,
4048 s->T0, zero);
4049 tcg_temp_free(zero);
4050 break;
4051 }
4052 set_cc_op(s, end_op);
4053 }
4054 break;
4055
4056 case 0x1f7:
4057 case 0x2f7:
4058 case 0x3f7:
4059 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4060 || !(s->prefix & PREFIX_VEX)
4061 || s->vex_l != 0) {
4062 goto illegal_op;
4063 }
4064 ot = mo_64_32(s->dflag);
4065 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4066 if (ot == MO_64) {
4067 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 63);
4068 } else {
4069 tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 31);
4070 }
4071 if (b == 0x1f7) {
4072 tcg_gen_shl_tl(s->T0, s->T0, s->T1);
4073 } else if (b == 0x2f7) {
4074 if (ot != MO_64) {
4075 tcg_gen_ext32s_tl(s->T0, s->T0);
4076 }
4077 tcg_gen_sar_tl(s->T0, s->T0, s->T1);
4078 } else {
4079 if (ot != MO_64) {
4080 tcg_gen_ext32u_tl(s->T0, s->T0);
4081 }
4082 tcg_gen_shr_tl(s->T0, s->T0, s->T1);
4083 }
4084 gen_op_mov_reg_v(s, ot, reg, s->T0);
4085 break;
4086
4087 case 0x0f3:
4088 case 0x1f3:
4089 case 0x2f3:
4090 case 0x3f3:
4091 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4092 || !(s->prefix & PREFIX_VEX)
4093 || s->vex_l != 0) {
4094 goto illegal_op;
4095 }
4096 ot = mo_64_32(s->dflag);
4097 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4098
4099 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4100 switch (reg & 7) {
4101 case 1:
4102 tcg_gen_subi_tl(s->T1, s->T0, 1);
4103 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4104 break;
4105 case 2:
4106 tcg_gen_subi_tl(s->T1, s->T0, 1);
4107 tcg_gen_xor_tl(s->T0, s->T0, s->T1);
4108 break;
4109 case 3:
4110 tcg_gen_neg_tl(s->T1, s->T0);
4111 tcg_gen_and_tl(s->T0, s->T0, s->T1);
4112 break;
4113 default:
4114 goto unknown_op;
4115 }
4116 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4117 gen_op_mov_reg_v(s, ot, s->vex_v, s->T0);
4118 set_cc_op(s, CC_OP_BMILGB + ot);
4119 break;
4120
4121 default:
4122 goto unknown_op;
4123 }
4124 break;
4125
4126 case 0x03a:
4127 case 0x13a:
4128 b = modrm;
4129 modrm = x86_ldub_code(env, s);
4130 rm = modrm & 7;
4131 reg = ((modrm >> 3) & 7) | rex_r;
4132 mod = (modrm >> 6) & 3;
4133 if (b1 >= 2) {
4134 goto unknown_op;
4135 }
4136
4137 sse_fn_eppi = sse_op_table7[b].op[b1];
4138 if (!sse_fn_eppi) {
4139 goto unknown_op;
4140 }
4141 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4142 goto illegal_op;
4143
4144 s->rip_offset = 1;
4145
4146 if (sse_fn_eppi == SSE_SPECIAL) {
4147 ot = mo_64_32(s->dflag);
4148 rm = (modrm & 7) | REX_B(s);
4149 if (mod != 3)
4150 gen_lea_modrm(env, s, modrm);
4151 reg = ((modrm >> 3) & 7) | rex_r;
4152 val = x86_ldub_code(env, s);
4153 switch (b) {
4154 case 0x14:
4155 tcg_gen_ld8u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4156 xmm_regs[reg].ZMM_B(val & 15)));
4157 if (mod == 3) {
4158 gen_op_mov_reg_v(s, ot, rm, s->T0);
4159 } else {
4160 tcg_gen_qemu_st_tl(s->T0, s->A0,
4161 s->mem_index, MO_UB);
4162 }
4163 break;
4164 case 0x15:
4165 tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4166 xmm_regs[reg].ZMM_W(val & 7)));
4167 if (mod == 3) {
4168 gen_op_mov_reg_v(s, ot, rm, s->T0);
4169 } else {
4170 tcg_gen_qemu_st_tl(s->T0, s->A0,
4171 s->mem_index, MO_LEUW);
4172 }
4173 break;
4174 case 0x16:
4175 if (ot == MO_32) {
4176 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4177 offsetof(CPUX86State,
4178 xmm_regs[reg].ZMM_L(val & 3)));
4179 if (mod == 3) {
4180 tcg_gen_extu_i32_tl(cpu_regs[rm], s->tmp2_i32);
4181 } else {
4182 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
4183 s->mem_index, MO_LEUL);
4184 }
4185 } else {
4186#ifdef TARGET_X86_64
4187 tcg_gen_ld_i64(s->tmp1_i64, cpu_env,
4188 offsetof(CPUX86State,
4189 xmm_regs[reg].ZMM_Q(val & 1)));
4190 if (mod == 3) {
4191 tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64);
4192 } else {
4193 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
4194 s->mem_index, MO_LEQ);
4195 }
4196#else
4197 goto illegal_op;
4198#endif
4199 }
4200 break;
4201 case 0x17:
4202 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
4203 xmm_regs[reg].ZMM_L(val & 3)));
4204 if (mod == 3) {
4205 gen_op_mov_reg_v(s, ot, rm, s->T0);
4206 } else {
4207 tcg_gen_qemu_st_tl(s->T0, s->A0,
4208 s->mem_index, MO_LEUL);
4209 }
4210 break;
4211 case 0x20:
4212 if (mod == 3) {
4213 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
4214 } else {
4215 tcg_gen_qemu_ld_tl(s->T0, s->A0,
4216 s->mem_index, MO_UB);
4217 }
4218 tcg_gen_st8_tl(s->T0, cpu_env, offsetof(CPUX86State,
4219 xmm_regs[reg].ZMM_B(val & 15)));
4220 break;
4221 case 0x21:
4222 if (mod == 3) {
4223 tcg_gen_ld_i32(s->tmp2_i32, cpu_env,
4224 offsetof(CPUX86State,xmm_regs[rm]
4225 .ZMM_L((val >> 6) & 3)));
4226 } else {
4227 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4228 s->mem_index, MO_LEUL);
4229 }
4230 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4231 offsetof(CPUX86State,xmm_regs[reg]
4232 .ZMM_L((val >> 4) & 3)));
4233 if ((val >> 0) & 1)
4234 tcg_gen_st_i32(tcg_const_i32(0 ),
4235 cpu_env, offsetof(CPUX86State,
4236 xmm_regs[reg].ZMM_L(0)));
4237 if ((val >> 1) & 1)
4238 tcg_gen_st_i32(tcg_const_i32(0 ),
4239 cpu_env, offsetof(CPUX86State,
4240 xmm_regs[reg].ZMM_L(1)));
4241 if ((val >> 2) & 1)
4242 tcg_gen_st_i32(tcg_const_i32(0 ),
4243 cpu_env, offsetof(CPUX86State,
4244 xmm_regs[reg].ZMM_L(2)));
4245 if ((val >> 3) & 1)
4246 tcg_gen_st_i32(tcg_const_i32(0 ),
4247 cpu_env, offsetof(CPUX86State,
4248 xmm_regs[reg].ZMM_L(3)));
4249 break;
4250 case 0x22:
4251 if (ot == MO_32) {
4252 if (mod == 3) {
4253 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[rm]);
4254 } else {
4255 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
4256 s->mem_index, MO_LEUL);
4257 }
4258 tcg_gen_st_i32(s->tmp2_i32, cpu_env,
4259 offsetof(CPUX86State,
4260 xmm_regs[reg].ZMM_L(val & 3)));
4261 } else {
4262#ifdef TARGET_X86_64
4263 if (mod == 3) {
4264 gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm);
4265 } else {
4266 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
4267 s->mem_index, MO_LEQ);
4268 }
4269 tcg_gen_st_i64(s->tmp1_i64, cpu_env,
4270 offsetof(CPUX86State,
4271 xmm_regs[reg].ZMM_Q(val & 1)));
4272#else
4273 goto illegal_op;
4274#endif
4275 }
4276 break;
4277 }
4278 return;
4279 }
4280
4281 if (b1) {
4282 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4283 if (mod == 3) {
4284 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4285 } else {
4286 op2_offset = offsetof(CPUX86State,xmm_t0);
4287 gen_lea_modrm(env, s, modrm);
4288 gen_ldo_env_A0(s, op2_offset);
4289 }
4290 } else {
4291 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4292 if (mod == 3) {
4293 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4294 } else {
4295 op2_offset = offsetof(CPUX86State,mmx_t0);
4296 gen_lea_modrm(env, s, modrm);
4297 gen_ldq_env_A0(s, op2_offset);
4298 }
4299 }
4300 val = x86_ldub_code(env, s);
4301
4302 if ((b & 0xfc) == 0x60) {
4303 set_cc_op(s, CC_OP_EFLAGS);
4304
4305 if (s->dflag == MO_64) {
4306
4307 val |= 1 << 8;
4308 }
4309 }
4310
4311 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4312 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4313 sse_fn_eppi(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val));
4314 break;
4315
4316 case 0x33a:
4317
4318 b = modrm | (b1 << 8);
4319 modrm = x86_ldub_code(env, s);
4320 reg = ((modrm >> 3) & 7) | rex_r;
4321
4322 switch (b) {
4323 case 0x3f0:
4324 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4325 || !(s->prefix & PREFIX_VEX)
4326 || s->vex_l != 0) {
4327 goto illegal_op;
4328 }
4329 ot = mo_64_32(s->dflag);
4330 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4331 b = x86_ldub_code(env, s);
4332 if (ot == MO_64) {
4333 tcg_gen_rotri_tl(s->T0, s->T0, b & 63);
4334 } else {
4335 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4336 tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b & 31);
4337 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
4338 }
4339 gen_op_mov_reg_v(s, ot, reg, s->T0);
4340 break;
4341
4342 default:
4343 goto unknown_op;
4344 }
4345 break;
4346
4347 default:
4348 unknown_op:
4349 gen_unknown_opcode(env, s);
4350 return;
4351 }
4352 } else {
4353
4354 switch(b) {
4355 case 0x70:
4356 case 0xc6:
4357 case 0xc2:
4358 s->rip_offset = 1;
4359 break;
4360 default:
4361 break;
4362 }
4363 if (is_xmm) {
4364 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4365 if (mod != 3) {
4366 int sz = 4;
4367
4368 gen_lea_modrm(env, s, modrm);
4369 op2_offset = offsetof(CPUX86State,xmm_t0);
4370
4371 switch (b) {
4372 case 0x50 ... 0x5a:
4373 case 0x5c ... 0x5f:
4374 case 0xc2:
4375
4376 if (b1 == 2) {
4377 sz = 2;
4378 } else if (b1 == 3) {
4379 sz = 3;
4380 }
4381 break;
4382
4383 case 0x2e:
4384 case 0x2f:
4385 if (b1 == 0) {
4386 sz = 2;
4387 } else {
4388 sz = 3;
4389 }
4390 break;
4391 }
4392
4393 switch (sz) {
4394 case 2:
4395
4396 gen_op_ld_v(s, MO_32, s->T0, s->A0);
4397 tcg_gen_st32_tl(s->T0, cpu_env,
4398 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
4399 break;
4400 case 3:
4401
4402 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
4403 break;
4404 default:
4405
4406 gen_ldo_env_A0(s, op2_offset);
4407 break;
4408 }
4409 } else {
4410 rm = (modrm & 7) | REX_B(s);
4411 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4412 }
4413 } else {
4414 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4415 if (mod != 3) {
4416 gen_lea_modrm(env, s, modrm);
4417 op2_offset = offsetof(CPUX86State,mmx_t0);
4418 gen_ldq_env_A0(s, op2_offset);
4419 } else {
4420 rm = (modrm & 7);
4421 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4422 }
4423 }
4424 switch(b) {
4425 case 0x0f:
4426 val = x86_ldub_code(env, s);
4427 sse_fn_epp = sse_op_table5[val];
4428 if (!sse_fn_epp) {
4429 goto unknown_op;
4430 }
4431 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
4432 goto illegal_op;
4433 }
4434 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4435 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4436 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4437 break;
4438 case 0x70:
4439 case 0xc6:
4440 val = x86_ldub_code(env, s);
4441 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4442 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4443
4444 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4445 sse_fn_ppi(s->ptr0, s->ptr1, tcg_const_i32(val));
4446 break;
4447 case 0xc2:
4448
4449 val = x86_ldub_code(env, s);
4450 if (val >= 8)
4451 goto unknown_op;
4452 sse_fn_epp = sse_op_table4[val][b1];
4453
4454 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4455 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4456 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4457 break;
4458 case 0xf7:
4459
4460 if (mod != 3)
4461 goto illegal_op;
4462 tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]);
4463 gen_extu(s->aflag, s->A0);
4464 gen_add_A0_ds_seg(s);
4465
4466 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4467 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4468
4469 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4470 sse_fn_eppt(cpu_env, s->ptr0, s->ptr1, s->A0);
4471 break;
4472 default:
4473 tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset);
4474 tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
4475 sse_fn_epp(cpu_env, s->ptr0, s->ptr1);
4476 break;
4477 }
4478 if (b == 0x2e || b == 0x2f) {
4479 set_cc_op(s, CC_OP_EFLAGS);
4480 }
4481 }
4482}
4483
4484
4485
4486static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
4487{
4488 CPUX86State *env = cpu->env_ptr;
4489 int b, prefixes;
4490 int shift;
4491 MemOp ot, aflag, dflag;
4492 int modrm, reg, rm, mod, op, opreg, val;
4493 target_ulong next_eip, tval;
4494 int rex_w, rex_r;
4495 target_ulong pc_start = s->base.pc_next;
4496
4497 s->pc_start = s->pc = pc_start;
4498 s->override = -1;
4499#ifdef TARGET_X86_64
4500 s->rex_x = 0;
4501 s->rex_b = 0;
4502 s->x86_64_hregs = false;
4503#endif
4504 s->rip_offset = 0;
4505 s->vex_l = 0;
4506 s->vex_v = 0;
4507 if (sigsetjmp(s->jmpbuf, 0) != 0) {
4508 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4509 return s->pc;
4510 }
4511
4512 prefixes = 0;
4513 rex_w = -1;
4514 rex_r = 0;
4515
4516 next_byte:
4517 b = x86_ldub_code(env, s);
4518
4519 switch (b) {
4520 case 0xf3:
4521 prefixes |= PREFIX_REPZ;
4522 goto next_byte;
4523 case 0xf2:
4524 prefixes |= PREFIX_REPNZ;
4525 goto next_byte;
4526 case 0xf0:
4527 prefixes |= PREFIX_LOCK;
4528 goto next_byte;
4529 case 0x2e:
4530 s->override = R_CS;
4531 goto next_byte;
4532 case 0x36:
4533 s->override = R_SS;
4534 goto next_byte;
4535 case 0x3e:
4536 s->override = R_DS;
4537 goto next_byte;
4538 case 0x26:
4539 s->override = R_ES;
4540 goto next_byte;
4541 case 0x64:
4542 s->override = R_FS;
4543 goto next_byte;
4544 case 0x65:
4545 s->override = R_GS;
4546 goto next_byte;
4547 case 0x66:
4548 prefixes |= PREFIX_DATA;
4549 goto next_byte;
4550 case 0x67:
4551 prefixes |= PREFIX_ADR;
4552 goto next_byte;
4553#ifdef TARGET_X86_64
4554 case 0x40 ... 0x4f:
4555 if (CODE64(s)) {
4556
4557 rex_w = (b >> 3) & 1;
4558 rex_r = (b & 0x4) << 1;
4559 s->rex_x = (b & 0x2) << 2;
4560 REX_B(s) = (b & 0x1) << 3;
4561
4562 s->x86_64_hregs = true;
4563 goto next_byte;
4564 }
4565 break;
4566#endif
4567 case 0xc5:
4568 case 0xc4:
4569
4570
4571 if (s->code32 && !s->vm86) {
4572 static const int pp_prefix[4] = {
4573 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4574 };
4575 int vex3, vex2 = x86_ldub_code(env, s);
4576
4577 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4578
4579
4580 s->pc--;
4581 break;
4582 }
4583
4584
4585 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4586 | PREFIX_LOCK | PREFIX_DATA)) {
4587 goto illegal_op;
4588 }
4589#ifdef TARGET_X86_64
4590 if (s->x86_64_hregs) {
4591 goto illegal_op;
4592 }
4593#endif
4594 rex_r = (~vex2 >> 4) & 8;
4595 if (b == 0xc5) {
4596
4597 vex3 = vex2;
4598 b = x86_ldub_code(env, s) | 0x100;
4599 } else {
4600
4601#ifdef TARGET_X86_64
4602 s->rex_x = (~vex2 >> 3) & 8;
4603 s->rex_b = (~vex2 >> 2) & 8;
4604#endif
4605 vex3 = x86_ldub_code(env, s);
4606 rex_w = (vex3 >> 7) & 1;
4607 switch (vex2 & 0x1f) {
4608 case 0x01:
4609 b = x86_ldub_code(env, s) | 0x100;
4610 break;
4611 case 0x02:
4612 b = 0x138;
4613 break;
4614 case 0x03:
4615 b = 0x13a;
4616 break;
4617 default:
4618 goto unknown_op;
4619 }
4620 }
4621 s->vex_v = (~vex3 >> 3) & 0xf;
4622 s->vex_l = (vex3 >> 2) & 1;
4623 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4624 }
4625 break;
4626 }
4627
4628
4629 if (CODE64(s)) {
4630
4631
4632
4633 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
4634
4635 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
4636 } else {
4637
4638 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4639 dflag = MO_32;
4640 } else {
4641 dflag = MO_16;
4642 }
4643
4644 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4645 aflag = MO_32;
4646 } else {
4647 aflag = MO_16;
4648 }
4649 }
4650
4651 s->prefix = prefixes;
4652 s->aflag = aflag;
4653 s->dflag = dflag;
4654
4655
4656 reswitch:
4657 switch(b) {
4658 case 0x0f:
4659
4660
4661 b = x86_ldub_code(env, s) | 0x100;
4662 goto reswitch;
4663
4664
4665
4666 case 0x00 ... 0x05:
4667 case 0x08 ... 0x0d:
4668 case 0x10 ... 0x15:
4669 case 0x18 ... 0x1d:
4670 case 0x20 ... 0x25:
4671 case 0x28 ... 0x2d:
4672 case 0x30 ... 0x35:
4673 case 0x38 ... 0x3d:
4674 {
4675 int op, f, val;
4676 op = (b >> 3) & 7;
4677 f = (b >> 1) & 3;
4678
4679 ot = mo_b_d(b, dflag);
4680
4681 switch(f) {
4682 case 0:
4683 modrm = x86_ldub_code(env, s);
4684 reg = ((modrm >> 3) & 7) | rex_r;
4685 mod = (modrm >> 6) & 3;
4686 rm = (modrm & 7) | REX_B(s);
4687 if (mod != 3) {
4688 gen_lea_modrm(env, s, modrm);
4689 opreg = OR_TMP0;
4690 } else if (op == OP_XORL && rm == reg) {
4691 xor_zero:
4692
4693 set_cc_op(s, CC_OP_CLR);
4694 tcg_gen_movi_tl(s->T0, 0);
4695 gen_op_mov_reg_v(s, ot, reg, s->T0);
4696 break;
4697 } else {
4698 opreg = rm;
4699 }
4700 gen_op_mov_v_reg(s, ot, s->T1, reg);
4701 gen_op(s, op, ot, opreg);
4702 break;
4703 case 1:
4704 modrm = x86_ldub_code(env, s);
4705 mod = (modrm >> 6) & 3;
4706 reg = ((modrm >> 3) & 7) | rex_r;
4707 rm = (modrm & 7) | REX_B(s);
4708 if (mod != 3) {
4709 gen_lea_modrm(env, s, modrm);
4710 gen_op_ld_v(s, ot, s->T1, s->A0);
4711 } else if (op == OP_XORL && rm == reg) {
4712 goto xor_zero;
4713 } else {
4714 gen_op_mov_v_reg(s, ot, s->T1, rm);
4715 }
4716 gen_op(s, op, ot, reg);
4717 break;
4718 case 2:
4719 val = insn_get(env, s, ot);
4720 tcg_gen_movi_tl(s->T1, val);
4721 gen_op(s, op, ot, OR_EAX);
4722 break;
4723 }
4724 }
4725 break;
4726
4727 case 0x82:
4728 if (CODE64(s))
4729 goto illegal_op;
4730
4731 case 0x80:
4732 case 0x81:
4733 case 0x83:
4734 {
4735 int val;
4736
4737 ot = mo_b_d(b, dflag);
4738
4739 modrm = x86_ldub_code(env, s);
4740 mod = (modrm >> 6) & 3;
4741 rm = (modrm & 7) | REX_B(s);
4742 op = (modrm >> 3) & 7;
4743
4744 if (mod != 3) {
4745 if (b == 0x83)
4746 s->rip_offset = 1;
4747 else
4748 s->rip_offset = insn_const_size(ot);
4749 gen_lea_modrm(env, s, modrm);
4750 opreg = OR_TMP0;
4751 } else {
4752 opreg = rm;
4753 }
4754
4755 switch(b) {
4756 default:
4757 case 0x80:
4758 case 0x81:
4759 case 0x82:
4760 val = insn_get(env, s, ot);
4761 break;
4762 case 0x83:
4763 val = (int8_t)insn_get(env, s, MO_8);
4764 break;
4765 }
4766 tcg_gen_movi_tl(s->T1, val);
4767 gen_op(s, op, ot, opreg);
4768 }
4769 break;
4770
4771
4772
4773 case 0x40 ... 0x47:
4774 ot = dflag;
4775 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4776 break;
4777 case 0x48 ... 0x4f:
4778 ot = dflag;
4779 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4780 break;
4781 case 0xf6:
4782 case 0xf7:
4783 ot = mo_b_d(b, dflag);
4784
4785 modrm = x86_ldub_code(env, s);
4786 mod = (modrm >> 6) & 3;
4787 rm = (modrm & 7) | REX_B(s);
4788 op = (modrm >> 3) & 7;
4789 if (mod != 3) {
4790 if (op == 0) {
4791 s->rip_offset = insn_const_size(ot);
4792 }
4793 gen_lea_modrm(env, s, modrm);
4794
4795 if (!(s->prefix & PREFIX_LOCK)
4796 || op != 2) {
4797 gen_op_ld_v(s, ot, s->T0, s->A0);
4798 }
4799 } else {
4800 gen_op_mov_v_reg(s, ot, s->T0, rm);
4801 }
4802
4803 switch(op) {
4804 case 0:
4805 val = insn_get(env, s, ot);
4806 tcg_gen_movi_tl(s->T1, val);
4807 gen_op_testl_T0_T1_cc(s);
4808 set_cc_op(s, CC_OP_LOGICB + ot);
4809 break;
4810 case 2:
4811 if (s->prefix & PREFIX_LOCK) {
4812 if (mod == 3) {
4813 goto illegal_op;
4814 }
4815 tcg_gen_movi_tl(s->T0, ~0);
4816 tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0,
4817 s->mem_index, ot | MO_LE);
4818 } else {
4819 tcg_gen_not_tl(s->T0, s->T0);
4820 if (mod != 3) {
4821 gen_op_st_v(s, ot, s->T0, s->A0);
4822 } else {
4823 gen_op_mov_reg_v(s, ot, rm, s->T0);
4824 }
4825 }
4826 break;
4827 case 3:
4828 if (s->prefix & PREFIX_LOCK) {
4829 TCGLabel *label1;
4830 TCGv a0, t0, t1, t2;
4831
4832 if (mod == 3) {
4833 goto illegal_op;
4834 }
4835 a0 = tcg_temp_local_new();
4836 t0 = tcg_temp_local_new();
4837 label1 = gen_new_label();
4838
4839 tcg_gen_mov_tl(a0, s->A0);
4840 tcg_gen_mov_tl(t0, s->T0);
4841
4842 gen_set_label(label1);
4843 t1 = tcg_temp_new();
4844 t2 = tcg_temp_new();
4845 tcg_gen_mov_tl(t2, t0);
4846 tcg_gen_neg_tl(t1, t0);
4847 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4848 s->mem_index, ot | MO_LE);
4849 tcg_temp_free(t1);
4850 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4851
4852 tcg_temp_free(t2);
4853 tcg_temp_free(a0);
4854 tcg_gen_mov_tl(s->T0, t0);
4855 tcg_temp_free(t0);
4856 } else {
4857 tcg_gen_neg_tl(s->T0, s->T0);
4858 if (mod != 3) {
4859 gen_op_st_v(s, ot, s->T0, s->A0);
4860 } else {
4861 gen_op_mov_reg_v(s, ot, rm, s->T0);
4862 }
4863 }
4864 gen_op_update_neg_cc(s);
4865 set_cc_op(s, CC_OP_SUBB + ot);
4866 break;
4867 case 4:
4868 switch(ot) {
4869 case MO_8:
4870 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4871 tcg_gen_ext8u_tl(s->T0, s->T0);
4872 tcg_gen_ext8u_tl(s->T1, s->T1);
4873
4874 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4875 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4876 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4877 tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00);
4878 set_cc_op(s, CC_OP_MULB);
4879 break;
4880 case MO_16:
4881 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
4882 tcg_gen_ext16u_tl(s->T0, s->T0);
4883 tcg_gen_ext16u_tl(s->T1, s->T1);
4884
4885 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4886 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4887 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4888 tcg_gen_shri_tl(s->T0, s->T0, 16);
4889 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
4890 tcg_gen_mov_tl(cpu_cc_src, s->T0);
4891 set_cc_op(s, CC_OP_MULW);
4892 break;
4893 default:
4894 case MO_32:
4895 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4896 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
4897 tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32,
4898 s->tmp2_i32, s->tmp3_i32);
4899 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
4900 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
4901 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4902 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4903 set_cc_op(s, CC_OP_MULL);
4904 break;
4905#ifdef TARGET_X86_64
4906 case MO_64:
4907 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4908 s->T0, cpu_regs[R_EAX]);
4909 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4910 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
4911 set_cc_op(s, CC_OP_MULQ);
4912 break;
4913#endif
4914 }
4915 break;
4916 case 5:
4917 switch(ot) {
4918 case MO_8:
4919 gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX);
4920 tcg_gen_ext8s_tl(s->T0, s->T0);
4921 tcg_gen_ext8s_tl(s->T1, s->T1);
4922
4923 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4924 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4925 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4926 tcg_gen_ext8s_tl(s->tmp0, s->T0);
4927 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
4928 set_cc_op(s, CC_OP_MULB);
4929 break;
4930 case MO_16:
4931 gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX);
4932 tcg_gen_ext16s_tl(s->T0, s->T0);
4933 tcg_gen_ext16s_tl(s->T1, s->T1);
4934
4935 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
4936 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
4937 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4938 tcg_gen_ext16s_tl(s->tmp0, s->T0);
4939 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
4940 tcg_gen_shri_tl(s->T0, s->T0, 16);
4941 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
4942 set_cc_op(s, CC_OP_MULW);
4943 break;
4944 default:
4945 case MO_32:
4946 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
4947 tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]);
4948 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
4949 s->tmp2_i32, s->tmp3_i32);
4950 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32);
4951 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32);
4952 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
4953 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4954 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
4955 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
4956 set_cc_op(s, CC_OP_MULL);
4957 break;
4958#ifdef TARGET_X86_64
4959 case MO_64:
4960 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4961 s->T0, cpu_regs[R_EAX]);
4962 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4963 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4964 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
4965 set_cc_op(s, CC_OP_MULQ);
4966 break;
4967#endif
4968 }
4969 break;
4970 case 6:
4971 switch(ot) {
4972 case MO_8:
4973 gen_helper_divb_AL(cpu_env, s->T0);
4974 break;
4975 case MO_16:
4976 gen_helper_divw_AX(cpu_env, s->T0);
4977 break;
4978 default:
4979 case MO_32:
4980 gen_helper_divl_EAX(cpu_env, s->T0);
4981 break;
4982#ifdef TARGET_X86_64
4983 case MO_64:
4984 gen_helper_divq_EAX(cpu_env, s->T0);
4985 break;
4986#endif
4987 }
4988 break;
4989 case 7:
4990 switch(ot) {
4991 case MO_8:
4992 gen_helper_idivb_AL(cpu_env, s->T0);
4993 break;
4994 case MO_16:
4995 gen_helper_idivw_AX(cpu_env, s->T0);
4996 break;
4997 default:
4998 case MO_32:
4999 gen_helper_idivl_EAX(cpu_env, s->T0);
5000 break;
5001#ifdef TARGET_X86_64
5002 case MO_64:
5003 gen_helper_idivq_EAX(cpu_env, s->T0);
5004 break;
5005#endif
5006 }
5007 break;
5008 default:
5009 goto unknown_op;
5010 }
5011 break;
5012
5013 case 0xfe:
5014 case 0xff:
5015 ot = mo_b_d(b, dflag);
5016
5017 modrm = x86_ldub_code(env, s);
5018 mod = (modrm >> 6) & 3;
5019 rm = (modrm & 7) | REX_B(s);
5020 op = (modrm >> 3) & 7;
5021 if (op >= 2 && b == 0xfe) {
5022 goto unknown_op;
5023 }
5024 if (CODE64(s)) {
5025 if (op == 2 || op == 4) {
5026
5027 ot = MO_64;
5028 } else if (op == 3 || op == 5) {
5029 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
5030 } else if (op == 6) {
5031
5032 ot = mo_pushpop(s, dflag);
5033 }
5034 }
5035 if (mod != 3) {
5036 gen_lea_modrm(env, s, modrm);
5037 if (op >= 2 && op != 3 && op != 5)
5038 gen_op_ld_v(s, ot, s->T0, s->A0);
5039 } else {
5040 gen_op_mov_v_reg(s, ot, s->T0, rm);
5041 }
5042
5043 switch(op) {
5044 case 0:
5045 if (mod != 3)
5046 opreg = OR_TMP0;
5047 else
5048 opreg = rm;
5049 gen_inc(s, ot, opreg, 1);
5050 break;
5051 case 1:
5052 if (mod != 3)
5053 opreg = OR_TMP0;
5054 else
5055 opreg = rm;
5056 gen_inc(s, ot, opreg, -1);
5057 break;
5058 case 2:
5059
5060 if (dflag == MO_16) {
5061 tcg_gen_ext16u_tl(s->T0, s->T0);
5062 }
5063 next_eip = s->pc - s->cs_base;
5064 tcg_gen_movi_tl(s->T1, next_eip);
5065 gen_push_v(s, s->T1);
5066 gen_op_jmp_v(s->T0);
5067 gen_bnd_jmp(s);
5068 gen_jr(s, s->T0);
5069 break;
5070 case 3:
5071 gen_op_ld_v(s, ot, s->T1, s->A0);
5072 gen_add_A0_im(s, 1 << ot);
5073 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5074 do_lcall:
5075 if (s->pe && !s->vm86) {
5076 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5077 gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
5078 tcg_const_i32(dflag - 1),
5079 tcg_const_tl(s->pc - s->cs_base));
5080 } else {
5081 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5082 gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1,
5083 tcg_const_i32(dflag - 1),
5084 tcg_const_i32(s->pc - s->cs_base));
5085 }
5086 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5087 gen_jr(s, s->tmp4);
5088 break;
5089 case 4:
5090 if (dflag == MO_16) {
5091 tcg_gen_ext16u_tl(s->T0, s->T0);
5092 }
5093 gen_op_jmp_v(s->T0);
5094 gen_bnd_jmp(s);
5095 gen_jr(s, s->T0);
5096 break;
5097 case 5:
5098 gen_op_ld_v(s, ot, s->T1, s->A0);
5099 gen_add_A0_im(s, 1 << ot);
5100 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5101 do_ljmp:
5102 if (s->pe && !s->vm86) {
5103 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5104 gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1,
5105 tcg_const_tl(s->pc - s->cs_base));
5106 } else {
5107 gen_op_movl_seg_T0_vm(s, R_CS);
5108 gen_op_jmp_v(s->T1);
5109 }
5110 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
5111 gen_jr(s, s->tmp4);
5112 break;
5113 case 6:
5114 gen_push_v(s, s->T0);
5115 break;
5116 default:
5117 goto unknown_op;
5118 }
5119 break;
5120
5121 case 0x84:
5122 case 0x85:
5123 ot = mo_b_d(b, dflag);
5124
5125 modrm = x86_ldub_code(env, s);
5126 reg = ((modrm >> 3) & 7) | rex_r;
5127
5128 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5129 gen_op_mov_v_reg(s, ot, s->T1, reg);
5130 gen_op_testl_T0_T1_cc(s);
5131 set_cc_op(s, CC_OP_LOGICB + ot);
5132 break;
5133
5134 case 0xa8:
5135 case 0xa9:
5136 ot = mo_b_d(b, dflag);
5137 val = insn_get(env, s, ot);
5138
5139 gen_op_mov_v_reg(s, ot, s->T0, OR_EAX);
5140 tcg_gen_movi_tl(s->T1, val);
5141 gen_op_testl_T0_T1_cc(s);
5142 set_cc_op(s, CC_OP_LOGICB + ot);
5143 break;
5144
5145 case 0x98:
5146 switch (dflag) {
5147#ifdef TARGET_X86_64
5148 case MO_64:
5149 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5150 tcg_gen_ext32s_tl(s->T0, s->T0);
5151 gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0);
5152 break;
5153#endif
5154 case MO_32:
5155 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5156 tcg_gen_ext16s_tl(s->T0, s->T0);
5157 gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0);
5158 break;
5159 case MO_16:
5160 gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX);
5161 tcg_gen_ext8s_tl(s->T0, s->T0);
5162 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
5163 break;
5164 default:
5165 tcg_abort();
5166 }
5167 break;
5168 case 0x99:
5169 switch (dflag) {
5170#ifdef TARGET_X86_64
5171 case MO_64:
5172 gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX);
5173 tcg_gen_sari_tl(s->T0, s->T0, 63);
5174 gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0);
5175 break;
5176#endif
5177 case MO_32:
5178 gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
5179 tcg_gen_ext32s_tl(s->T0, s->T0);
5180 tcg_gen_sari_tl(s->T0, s->T0, 31);
5181 gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0);
5182 break;
5183 case MO_16:
5184 gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX);
5185 tcg_gen_ext16s_tl(s->T0, s->T0);
5186 tcg_gen_sari_tl(s->T0, s->T0, 15);
5187 gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
5188 break;
5189 default:
5190 tcg_abort();
5191 }
5192 break;
5193 case 0x1af:
5194 case 0x69:
5195 case 0x6b:
5196 ot = dflag;
5197 modrm = x86_ldub_code(env, s);
5198 reg = ((modrm >> 3) & 7) | rex_r;
5199 if (b == 0x69)
5200 s->rip_offset = insn_const_size(ot);
5201 else if (b == 0x6b)
5202 s->rip_offset = 1;
5203 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5204 if (b == 0x69) {
5205 val = insn_get(env, s, ot);
5206 tcg_gen_movi_tl(s->T1, val);
5207 } else if (b == 0x6b) {
5208 val = (int8_t)insn_get(env, s, MO_8);
5209 tcg_gen_movi_tl(s->T1, val);
5210 } else {
5211 gen_op_mov_v_reg(s, ot, s->T1, reg);
5212 }
5213 switch (ot) {
5214#ifdef TARGET_X86_64
5215 case MO_64:
5216 tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1);
5217 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5218 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5219 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1);
5220 break;
5221#endif
5222 case MO_32:
5223 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
5224 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
5225 tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32,
5226 s->tmp2_i32, s->tmp3_i32);
5227 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
5228 tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31);
5229 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5230 tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32);
5231 tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32);
5232 break;
5233 default:
5234 tcg_gen_ext16s_tl(s->T0, s->T0);
5235 tcg_gen_ext16s_tl(s->T1, s->T1);
5236
5237 tcg_gen_mul_tl(s->T0, s->T0, s->T1);
5238 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5239 tcg_gen_ext16s_tl(s->tmp0, s->T0);
5240 tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0);
5241 gen_op_mov_reg_v(s, ot, reg, s->T0);
5242 break;
5243 }
5244 set_cc_op(s, CC_OP_MULB + ot);
5245 break;
5246 case 0x1c0:
5247 case 0x1c1:
5248 ot = mo_b_d(b, dflag);
5249 modrm = x86_ldub_code(env, s);
5250 reg = ((modrm >> 3) & 7) | rex_r;
5251 mod = (modrm >> 6) & 3;
5252 gen_op_mov_v_reg(s, ot, s->T0, reg);
5253 if (mod == 3) {
5254 rm = (modrm & 7) | REX_B(s);
5255 gen_op_mov_v_reg(s, ot, s->T1, rm);
5256 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5257 gen_op_mov_reg_v(s, ot, reg, s->T1);
5258 gen_op_mov_reg_v(s, ot, rm, s->T0);
5259 } else {
5260 gen_lea_modrm(env, s, modrm);
5261 if (s->prefix & PREFIX_LOCK) {
5262 tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0,
5263 s->mem_index, ot | MO_LE);
5264 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5265 } else {
5266 gen_op_ld_v(s, ot, s->T1, s->A0);
5267 tcg_gen_add_tl(s->T0, s->T0, s->T1);
5268 gen_op_st_v(s, ot, s->T0, s->A0);
5269 }
5270 gen_op_mov_reg_v(s, ot, reg, s->T1);
5271 }
5272 gen_op_update2_cc(s);
5273 set_cc_op(s, CC_OP_ADDB + ot);
5274 break;
5275 case 0x1b0:
5276 case 0x1b1:
5277 {
5278 TCGv oldv, newv, cmpv;
5279
5280 ot = mo_b_d(b, dflag);
5281 modrm = x86_ldub_code(env, s);
5282 reg = ((modrm >> 3) & 7) | rex_r;
5283 mod = (modrm >> 6) & 3;
5284 oldv = tcg_temp_new();
5285 newv = tcg_temp_new();
5286 cmpv = tcg_temp_new();
5287 gen_op_mov_v_reg(s, ot, newv, reg);
5288 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5289
5290 if (s->prefix & PREFIX_LOCK) {
5291 if (mod == 3) {
5292 goto illegal_op;
5293 }
5294 gen_lea_modrm(env, s, modrm);
5295 tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
5296 s->mem_index, ot | MO_LE);
5297 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5298 } else {
5299 if (mod == 3) {
5300 rm = (modrm & 7) | REX_B(s);
5301 gen_op_mov_v_reg(s, ot, oldv, rm);
5302 } else {
5303 gen_lea_modrm(env, s, modrm);
5304 gen_op_ld_v(s, ot, oldv, s->A0);
5305 rm = 0;
5306 }
5307 gen_extu(ot, oldv);
5308 gen_extu(ot, cmpv);
5309
5310 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5311 if (mod == 3) {
5312 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5313 gen_op_mov_reg_v(s, ot, rm, newv);
5314 } else {
5315
5316
5317
5318
5319 gen_op_st_v(s, ot, newv, s->A0);
5320 gen_op_mov_reg_v(s, ot, R_EAX, oldv);
5321 }
5322 }
5323 tcg_gen_mov_tl(cpu_cc_src, oldv);
5324 tcg_gen_mov_tl(s->cc_srcT, cmpv);
5325 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
5326 set_cc_op(s, CC_OP_SUBB + ot);
5327 tcg_temp_free(oldv);
5328 tcg_temp_free(newv);
5329 tcg_temp_free(cmpv);
5330 }
5331 break;
5332 case 0x1c7:
5333 modrm = x86_ldub_code(env, s);
5334 mod = (modrm >> 6) & 3;
5335 switch ((modrm >> 3) & 7) {
5336 case 1:
5337 if (mod == 3) {
5338 goto illegal_op;
5339 }
5340#ifdef TARGET_X86_64
5341 if (dflag == MO_64) {
5342 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) {
5343 goto illegal_op;
5344 }
5345 gen_lea_modrm(env, s, modrm);
5346 if ((s->prefix & PREFIX_LOCK) &&
5347 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5348 gen_helper_cmpxchg16b(cpu_env, s->A0);
5349 } else {
5350 gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0);
5351 }
5352 set_cc_op(s, CC_OP_EFLAGS);
5353 break;
5354 }
5355#endif
5356 if (!(s->cpuid_features & CPUID_CX8)) {
5357 goto illegal_op;
5358 }
5359 gen_lea_modrm(env, s, modrm);
5360 if ((s->prefix & PREFIX_LOCK) &&
5361 (tb_cflags(s->base.tb) & CF_PARALLEL)) {
5362 gen_helper_cmpxchg8b(cpu_env, s->A0);
5363 } else {
5364 gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0);
5365 }
5366 set_cc_op(s, CC_OP_EFLAGS);
5367 break;
5368
5369 case 7:
5370 case 6:
5371 if (mod != 3 ||
5372 (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
5373 !(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
5374 goto illegal_op;
5375 }
5376 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5377 gen_io_start();
5378 }
5379 gen_helper_rdrand(s->T0, cpu_env);
5380 rm = (modrm & 7) | REX_B(s);
5381 gen_op_mov_reg_v(s, dflag, rm, s->T0);
5382 set_cc_op(s, CC_OP_EFLAGS);
5383 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5384 gen_jmp(s, s->pc - s->cs_base);
5385 }
5386 break;
5387
5388 default:
5389 goto illegal_op;
5390 }
5391 break;
5392
5393
5394
5395 case 0x50 ... 0x57:
5396 gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s));
5397 gen_push_v(s, s->T0);
5398 break;
5399 case 0x58 ... 0x5f:
5400 ot = gen_pop_T0(s);
5401
5402 gen_pop_update(s, ot);
5403 gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0);
5404 break;
5405 case 0x60:
5406 if (CODE64(s))
5407 goto illegal_op;
5408 gen_pusha(s);
5409 break;
5410 case 0x61:
5411 if (CODE64(s))
5412 goto illegal_op;
5413 gen_popa(s);
5414 break;
5415 case 0x68:
5416 case 0x6a:
5417 ot = mo_pushpop(s, dflag);
5418 if (b == 0x68)
5419 val = insn_get(env, s, ot);
5420 else
5421 val = (int8_t)insn_get(env, s, MO_8);
5422 tcg_gen_movi_tl(s->T0, val);
5423 gen_push_v(s, s->T0);
5424 break;
5425 case 0x8f:
5426 modrm = x86_ldub_code(env, s);
5427 mod = (modrm >> 6) & 3;
5428 ot = gen_pop_T0(s);
5429 if (mod == 3) {
5430
5431 gen_pop_update(s, ot);
5432 rm = (modrm & 7) | REX_B(s);
5433 gen_op_mov_reg_v(s, ot, rm, s->T0);
5434 } else {
5435
5436 s->popl_esp_hack = 1 << ot;
5437 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5438 s->popl_esp_hack = 0;
5439 gen_pop_update(s, ot);
5440 }
5441 break;
5442 case 0xc8:
5443 {
5444 int level;
5445 val = x86_lduw_code(env, s);
5446 level = x86_ldub_code(env, s);
5447 gen_enter(s, val, level);
5448 }
5449 break;
5450 case 0xc9:
5451 gen_leave(s);
5452 break;
5453 case 0x06:
5454 case 0x0e:
5455 case 0x16:
5456 case 0x1e:
5457 if (CODE64(s))
5458 goto illegal_op;
5459 gen_op_movl_T0_seg(s, b >> 3);
5460 gen_push_v(s, s->T0);
5461 break;
5462 case 0x1a0:
5463 case 0x1a8:
5464 gen_op_movl_T0_seg(s, (b >> 3) & 7);
5465 gen_push_v(s, s->T0);
5466 break;
5467 case 0x07:
5468 case 0x17:
5469 case 0x1f:
5470 if (CODE64(s))
5471 goto illegal_op;
5472 reg = b >> 3;
5473 ot = gen_pop_T0(s);
5474 gen_movl_seg_T0(s, reg);
5475 gen_pop_update(s, ot);
5476
5477 if (s->base.is_jmp) {
5478 gen_jmp_im(s, s->pc - s->cs_base);
5479 if (reg == R_SS) {
5480 s->tf = 0;
5481 gen_eob_inhibit_irq(s, true);
5482 } else {
5483 gen_eob(s);
5484 }
5485 }
5486 break;
5487 case 0x1a1:
5488 case 0x1a9:
5489 ot = gen_pop_T0(s);
5490 gen_movl_seg_T0(s, (b >> 3) & 7);
5491 gen_pop_update(s, ot);
5492 if (s->base.is_jmp) {
5493 gen_jmp_im(s, s->pc - s->cs_base);
5494 gen_eob(s);
5495 }
5496 break;
5497
5498
5499
5500 case 0x88:
5501 case 0x89:
5502 ot = mo_b_d(b, dflag);
5503 modrm = x86_ldub_code(env, s);
5504 reg = ((modrm >> 3) & 7) | rex_r;
5505
5506
5507 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5508 break;
5509 case 0xc6:
5510 case 0xc7:
5511 ot = mo_b_d(b, dflag);
5512 modrm = x86_ldub_code(env, s);
5513 mod = (modrm >> 6) & 3;
5514 if (mod != 3) {
5515 s->rip_offset = insn_const_size(ot);
5516 gen_lea_modrm(env, s, modrm);
5517 }
5518 val = insn_get(env, s, ot);
5519 tcg_gen_movi_tl(s->T0, val);
5520 if (mod != 3) {
5521 gen_op_st_v(s, ot, s->T0, s->A0);
5522 } else {
5523 gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0);
5524 }
5525 break;
5526 case 0x8a:
5527 case 0x8b:
5528 ot = mo_b_d(b, dflag);
5529 modrm = x86_ldub_code(env, s);
5530 reg = ((modrm >> 3) & 7) | rex_r;
5531
5532 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5533 gen_op_mov_reg_v(s, ot, reg, s->T0);
5534 break;
5535 case 0x8e:
5536 modrm = x86_ldub_code(env, s);
5537 reg = (modrm >> 3) & 7;
5538 if (reg >= 6 || reg == R_CS)
5539 goto illegal_op;
5540 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
5541 gen_movl_seg_T0(s, reg);
5542
5543 if (s->base.is_jmp) {
5544 gen_jmp_im(s, s->pc - s->cs_base);
5545 if (reg == R_SS) {
5546 s->tf = 0;
5547 gen_eob_inhibit_irq(s, true);
5548 } else {
5549 gen_eob(s);
5550 }
5551 }
5552 break;
5553 case 0x8c:
5554 modrm = x86_ldub_code(env, s);
5555 reg = (modrm >> 3) & 7;
5556 mod = (modrm >> 6) & 3;
5557 if (reg >= 6)
5558 goto illegal_op;
5559 gen_op_movl_T0_seg(s, reg);
5560 ot = mod == 3 ? dflag : MO_16;
5561 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5562 break;
5563
5564 case 0x1b6:
5565 case 0x1b7:
5566 case 0x1be:
5567 case 0x1bf:
5568 {
5569 MemOp d_ot;
5570 MemOp s_ot;
5571
5572
5573 d_ot = dflag;
5574
5575 ot = (b & 1) + MO_8;
5576
5577 s_ot = b & 8 ? MO_SIGN | ot : ot;
5578
5579 modrm = x86_ldub_code(env, s);
5580 reg = ((modrm >> 3) & 7) | rex_r;
5581 mod = (modrm >> 6) & 3;
5582 rm = (modrm & 7) | REX_B(s);
5583
5584 if (mod == 3) {
5585 if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) {
5586 tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8);
5587 } else {
5588 gen_op_mov_v_reg(s, ot, s->T0, rm);
5589 switch (s_ot) {
5590 case MO_UB:
5591 tcg_gen_ext8u_tl(s->T0, s->T0);
5592 break;
5593 case MO_SB:
5594 tcg_gen_ext8s_tl(s->T0, s->T0);
5595 break;
5596 case MO_UW:
5597 tcg_gen_ext16u_tl(s->T0, s->T0);
5598 break;
5599 default:
5600 case MO_SW:
5601 tcg_gen_ext16s_tl(s->T0, s->T0);
5602 break;
5603 }
5604 }
5605 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5606 } else {
5607 gen_lea_modrm(env, s, modrm);
5608 gen_op_ld_v(s, s_ot, s->T0, s->A0);
5609 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
5610 }
5611 }
5612 break;
5613
5614 case 0x8d:
5615 modrm = x86_ldub_code(env, s);
5616 mod = (modrm >> 6) & 3;
5617 if (mod == 3)
5618 goto illegal_op;
5619 reg = ((modrm >> 3) & 7) | rex_r;
5620 {
5621 AddressParts a = gen_lea_modrm_0(env, s, modrm);
5622 TCGv ea = gen_lea_modrm_1(s, a);
5623 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
5624 gen_op_mov_reg_v(s, dflag, reg, s->A0);
5625 }
5626 break;
5627
5628 case 0xa0:
5629 case 0xa1:
5630 case 0xa2:
5631 case 0xa3:
5632 {
5633 target_ulong offset_addr;
5634
5635 ot = mo_b_d(b, dflag);
5636 switch (s->aflag) {
5637#ifdef TARGET_X86_64
5638 case MO_64:
5639 offset_addr = x86_ldq_code(env, s);
5640 break;
5641#endif
5642 default:
5643 offset_addr = insn_get(env, s, s->aflag);
5644 break;
5645 }
5646 tcg_gen_movi_tl(s->A0, offset_addr);
5647 gen_add_A0_ds_seg(s);
5648 if ((b & 2) == 0) {
5649 gen_op_ld_v(s, ot, s->T0, s->A0);
5650 gen_op_mov_reg_v(s, ot, R_EAX, s->T0);
5651 } else {
5652 gen_op_mov_v_reg(s, ot, s->T0, R_EAX);
5653 gen_op_st_v(s, ot, s->T0, s->A0);
5654 }
5655 }
5656 break;
5657 case 0xd7:
5658 tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]);
5659 tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]);
5660 tcg_gen_add_tl(s->A0, s->A0, s->T0);
5661 gen_extu(s->aflag, s->A0);
5662 gen_add_A0_ds_seg(s);
5663 gen_op_ld_v(s, MO_8, s->T0, s->A0);
5664 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
5665 break;
5666 case 0xb0 ... 0xb7:
5667 val = insn_get(env, s, MO_8);
5668 tcg_gen_movi_tl(s->T0, val);
5669 gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0);
5670 break;
5671 case 0xb8 ... 0xbf:
5672#ifdef TARGET_X86_64
5673 if (dflag == MO_64) {
5674 uint64_t tmp;
5675
5676 tmp = x86_ldq_code(env, s);
5677 reg = (b & 7) | REX_B(s);
5678 tcg_gen_movi_tl(s->T0, tmp);
5679 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
5680 } else
5681#endif
5682 {
5683 ot = dflag;
5684 val = insn_get(env, s, ot);
5685 reg = (b & 7) | REX_B(s);
5686 tcg_gen_movi_tl(s->T0, val);
5687 gen_op_mov_reg_v(s, ot, reg, s->T0);
5688 }
5689 break;
5690
5691 case 0x91 ... 0x97:
5692 do_xchg_reg_eax:
5693 ot = dflag;
5694 reg = (b & 7) | REX_B(s);
5695 rm = R_EAX;
5696 goto do_xchg_reg;
5697 case 0x86:
5698 case 0x87:
5699 ot = mo_b_d(b, dflag);
5700 modrm = x86_ldub_code(env, s);
5701 reg = ((modrm >> 3) & 7) | rex_r;
5702 mod = (modrm >> 6) & 3;
5703 if (mod == 3) {
5704 rm = (modrm & 7) | REX_B(s);
5705 do_xchg_reg:
5706 gen_op_mov_v_reg(s, ot, s->T0, reg);
5707 gen_op_mov_v_reg(s, ot, s->T1, rm);
5708 gen_op_mov_reg_v(s, ot, rm, s->T0);
5709 gen_op_mov_reg_v(s, ot, reg, s->T1);
5710 } else {
5711 gen_lea_modrm(env, s, modrm);
5712 gen_op_mov_v_reg(s, ot, s->T0, reg);
5713
5714 tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0,
5715 s->mem_index, ot | MO_LE);
5716 gen_op_mov_reg_v(s, ot, reg, s->T1);
5717 }
5718 break;
5719 case 0xc4:
5720
5721 op = R_ES;
5722 goto do_lxx;
5723 case 0xc5:
5724
5725 op = R_DS;
5726 goto do_lxx;
5727 case 0x1b2:
5728 op = R_SS;
5729 goto do_lxx;
5730 case 0x1b4:
5731 op = R_FS;
5732 goto do_lxx;
5733 case 0x1b5:
5734 op = R_GS;
5735 do_lxx:
5736 ot = dflag != MO_16 ? MO_32 : MO_16;
5737 modrm = x86_ldub_code(env, s);
5738 reg = ((modrm >> 3) & 7) | rex_r;
5739 mod = (modrm >> 6) & 3;
5740 if (mod == 3)
5741 goto illegal_op;
5742 gen_lea_modrm(env, s, modrm);
5743 gen_op_ld_v(s, ot, s->T1, s->A0);
5744 gen_add_A0_im(s, 1 << ot);
5745
5746 gen_op_ld_v(s, MO_16, s->T0, s->A0);
5747 gen_movl_seg_T0(s, op);
5748
5749 gen_op_mov_reg_v(s, ot, reg, s->T1);
5750 if (s->base.is_jmp) {
5751 gen_jmp_im(s, s->pc - s->cs_base);
5752 gen_eob(s);
5753 }
5754 break;
5755
5756
5757
5758 case 0xc0:
5759 case 0xc1:
5760
5761 shift = 2;
5762 grp2:
5763 {
5764 ot = mo_b_d(b, dflag);
5765 modrm = x86_ldub_code(env, s);
5766 mod = (modrm >> 6) & 3;
5767 op = (modrm >> 3) & 7;
5768
5769 if (mod != 3) {
5770 if (shift == 2) {
5771 s->rip_offset = 1;
5772 }
5773 gen_lea_modrm(env, s, modrm);
5774 opreg = OR_TMP0;
5775 } else {
5776 opreg = (modrm & 7) | REX_B(s);
5777 }
5778
5779
5780 if (shift == 0) {
5781 gen_shift(s, op, ot, opreg, OR_ECX);
5782 } else {
5783 if (shift == 2) {
5784 shift = x86_ldub_code(env, s);
5785 }
5786 gen_shifti(s, op, ot, opreg, shift);
5787 }
5788 }
5789 break;
5790 case 0xd0:
5791 case 0xd1:
5792
5793 shift = 1;
5794 goto grp2;
5795 case 0xd2:
5796 case 0xd3:
5797
5798 shift = 0;
5799 goto grp2;
5800
5801 case 0x1a4:
5802 op = 0;
5803 shift = 1;
5804 goto do_shiftd;
5805 case 0x1a5:
5806 op = 0;
5807 shift = 0;
5808 goto do_shiftd;
5809 case 0x1ac:
5810 op = 1;
5811 shift = 1;
5812 goto do_shiftd;
5813 case 0x1ad:
5814 op = 1;
5815 shift = 0;
5816 do_shiftd:
5817 ot = dflag;
5818 modrm = x86_ldub_code(env, s);
5819 mod = (modrm >> 6) & 3;
5820 rm = (modrm & 7) | REX_B(s);
5821 reg = ((modrm >> 3) & 7) | rex_r;
5822 if (mod != 3) {
5823 gen_lea_modrm(env, s, modrm);
5824 opreg = OR_TMP0;
5825 } else {
5826 opreg = rm;
5827 }
5828 gen_op_mov_v_reg(s, ot, s->T1, reg);
5829
5830 if (shift) {
5831 TCGv imm = tcg_const_tl(x86_ldub_code(env, s));
5832 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5833 tcg_temp_free(imm);
5834 } else {
5835 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5836 }
5837 break;
5838
5839
5840
5841 case 0xd8 ... 0xdf:
5842 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5843
5844
5845 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5846 break;
5847 }
5848 modrm = x86_ldub_code(env, s);
5849 mod = (modrm >> 6) & 3;
5850 rm = modrm & 7;
5851 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5852 if (mod != 3) {
5853
5854 gen_lea_modrm(env, s, modrm);
5855 switch(op) {
5856 case 0x00 ... 0x07:
5857 case 0x10 ... 0x17:
5858 case 0x20 ... 0x27:
5859 case 0x30 ... 0x37:
5860 {
5861 int op1;
5862 op1 = op & 7;
5863
5864 switch(op >> 4) {
5865 case 0:
5866 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5867 s->mem_index, MO_LEUL);
5868 gen_helper_flds_FT0(cpu_env, s->tmp2_i32);
5869 break;
5870 case 1:
5871 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5872 s->mem_index, MO_LEUL);
5873 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5874 break;
5875 case 2:
5876 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5877 s->mem_index, MO_LEQ);
5878 gen_helper_fldl_FT0(cpu_env, s->tmp1_i64);
5879 break;
5880 case 3:
5881 default:
5882 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5883 s->mem_index, MO_LESW);
5884 gen_helper_fildl_FT0(cpu_env, s->tmp2_i32);
5885 break;
5886 }
5887
5888 gen_helper_fp_arith_ST0_FT0(op1);
5889 if (op1 == 3) {
5890
5891 gen_helper_fpop(cpu_env);
5892 }
5893 }
5894 break;
5895 case 0x08:
5896 case 0x0a:
5897 case 0x0b:
5898 case 0x18 ... 0x1b:
5899 case 0x28 ... 0x2b:
5900 case 0x38 ... 0x3b:
5901 switch(op & 7) {
5902 case 0:
5903 switch(op >> 4) {
5904 case 0:
5905 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5906 s->mem_index, MO_LEUL);
5907 gen_helper_flds_ST0(cpu_env, s->tmp2_i32);
5908 break;
5909 case 1:
5910 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5911 s->mem_index, MO_LEUL);
5912 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
5913 break;
5914 case 2:
5915 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
5916 s->mem_index, MO_LEQ);
5917 gen_helper_fldl_ST0(cpu_env, s->tmp1_i64);
5918 break;
5919 case 3:
5920 default:
5921 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5922 s->mem_index, MO_LESW);
5923 gen_helper_fildl_ST0(cpu_env, s->tmp2_i32);
5924 break;
5925 }
5926 break;
5927 case 1:
5928
5929 switch(op >> 4) {
5930 case 1:
5931 gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env);
5932 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5933 s->mem_index, MO_LEUL);
5934 break;
5935 case 2:
5936 gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env);
5937 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
5938 s->mem_index, MO_LEQ);
5939 break;
5940 case 3:
5941 default:
5942 gen_helper_fistt_ST0(s->tmp2_i32, cpu_env);
5943 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5944 s->mem_index, MO_LEUW);
5945 break;
5946 }
5947 gen_helper_fpop(cpu_env);
5948 break;
5949 default:
5950 switch(op >> 4) {
5951 case 0:
5952 gen_helper_fsts_ST0(s->tmp2_i32, cpu_env);
5953 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5954 s->mem_index, MO_LEUL);
5955 break;
5956 case 1:
5957 gen_helper_fistl_ST0(s->tmp2_i32, cpu_env);
5958 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5959 s->mem_index, MO_LEUL);
5960 break;
5961 case 2:
5962 gen_helper_fstl_ST0(s->tmp1_i64, cpu_env);
5963 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
5964 s->mem_index, MO_LEQ);
5965 break;
5966 case 3:
5967 default:
5968 gen_helper_fist_ST0(s->tmp2_i32, cpu_env);
5969 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5970 s->mem_index, MO_LEUW);
5971 break;
5972 }
5973 if ((op & 7) == 3)
5974 gen_helper_fpop(cpu_env);
5975 break;
5976 }
5977 break;
5978 case 0x0c:
5979 gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
5980 break;
5981 case 0x0d:
5982 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
5983 s->mem_index, MO_LEUW);
5984 gen_helper_fldcw(cpu_env, s->tmp2_i32);
5985 break;
5986 case 0x0e:
5987 gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
5988 break;
5989 case 0x0f:
5990 gen_helper_fnstcw(s->tmp2_i32, cpu_env);
5991 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
5992 s->mem_index, MO_LEUW);
5993 break;
5994 case 0x1d:
5995 gen_helper_fldt_ST0(cpu_env, s->A0);
5996 break;
5997 case 0x1f:
5998 gen_helper_fstt_ST0(cpu_env, s->A0);
5999 gen_helper_fpop(cpu_env);
6000 break;
6001 case 0x2c:
6002 gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6003 break;
6004 case 0x2e:
6005 gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1));
6006 break;
6007 case 0x2f:
6008 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6009 tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0,
6010 s->mem_index, MO_LEUW);
6011 break;
6012 case 0x3c:
6013 gen_helper_fbld_ST0(cpu_env, s->A0);
6014 break;
6015 case 0x3e:
6016 gen_helper_fbst_ST0(cpu_env, s->A0);
6017 gen_helper_fpop(cpu_env);
6018 break;
6019 case 0x3d:
6020 tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6021 gen_helper_fildll_ST0(cpu_env, s->tmp1_i64);
6022 break;
6023 case 0x3f:
6024 gen_helper_fistll_ST0(s->tmp1_i64, cpu_env);
6025 tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
6026 gen_helper_fpop(cpu_env);
6027 break;
6028 default:
6029 goto unknown_op;
6030 }
6031 } else {
6032
6033 opreg = rm;
6034
6035 switch(op) {
6036 case 0x08:
6037 gen_helper_fpush(cpu_env);
6038 gen_helper_fmov_ST0_STN(cpu_env,
6039 tcg_const_i32((opreg + 1) & 7));
6040 break;
6041 case 0x09:
6042 case 0x29:
6043 case 0x39:
6044 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
6045 break;
6046 case 0x0a:
6047 switch(rm) {
6048 case 0:
6049
6050 gen_helper_fwait(cpu_env);
6051 break;
6052 default:
6053 goto unknown_op;
6054 }
6055 break;
6056 case 0x0c:
6057 switch(rm) {
6058 case 0:
6059 gen_helper_fchs_ST0(cpu_env);
6060 break;
6061 case 1:
6062 gen_helper_fabs_ST0(cpu_env);
6063 break;
6064 case 4:
6065 gen_helper_fldz_FT0(cpu_env);
6066 gen_helper_fcom_ST0_FT0(cpu_env);
6067 break;
6068 case 5:
6069 gen_helper_fxam_ST0(cpu_env);
6070 break;
6071 default:
6072 goto unknown_op;
6073 }
6074 break;
6075 case 0x0d:
6076 {
6077 switch(rm) {
6078 case 0:
6079 gen_helper_fpush(cpu_env);
6080 gen_helper_fld1_ST0(cpu_env);
6081 break;
6082 case 1:
6083 gen_helper_fpush(cpu_env);
6084 gen_helper_fldl2t_ST0(cpu_env);
6085 break;
6086 case 2:
6087 gen_helper_fpush(cpu_env);
6088 gen_helper_fldl2e_ST0(cpu_env);
6089 break;
6090 case 3:
6091 gen_helper_fpush(cpu_env);
6092 gen_helper_fldpi_ST0(cpu_env);
6093 break;
6094 case 4:
6095 gen_helper_fpush(cpu_env);
6096 gen_helper_fldlg2_ST0(cpu_env);
6097 break;
6098 case 5:
6099 gen_helper_fpush(cpu_env);
6100 gen_helper_fldln2_ST0(cpu_env);
6101 break;
6102 case 6:
6103 gen_helper_fpush(cpu_env);
6104 gen_helper_fldz_ST0(cpu_env);
6105 break;
6106 default:
6107 goto unknown_op;
6108 }
6109 }
6110 break;
6111 case 0x0e:
6112 switch(rm) {
6113 case 0:
6114 gen_helper_f2xm1(cpu_env);
6115 break;
6116 case 1:
6117 gen_helper_fyl2x(cpu_env);
6118 break;
6119 case 2:
6120 gen_helper_fptan(cpu_env);
6121 break;
6122 case 3:
6123 gen_helper_fpatan(cpu_env);
6124 break;
6125 case 4:
6126 gen_helper_fxtract(cpu_env);
6127 break;
6128 case 5:
6129 gen_helper_fprem1(cpu_env);
6130 break;
6131 case 6:
6132 gen_helper_fdecstp(cpu_env);
6133 break;
6134 default:
6135 case 7:
6136 gen_helper_fincstp(cpu_env);
6137 break;
6138 }
6139 break;
6140 case 0x0f:
6141 switch(rm) {
6142 case 0:
6143 gen_helper_fprem(cpu_env);
6144 break;
6145 case 1:
6146 gen_helper_fyl2xp1(cpu_env);
6147 break;
6148 case 2:
6149 gen_helper_fsqrt(cpu_env);
6150 break;
6151 case 3:
6152 gen_helper_fsincos(cpu_env);
6153 break;
6154 case 5:
6155 gen_helper_fscale(cpu_env);
6156 break;
6157 case 4:
6158 gen_helper_frndint(cpu_env);
6159 break;
6160 case 6:
6161 gen_helper_fsin(cpu_env);
6162 break;
6163 default:
6164 case 7:
6165 gen_helper_fcos(cpu_env);
6166 break;
6167 }
6168 break;
6169 case 0x00: case 0x01: case 0x04 ... 0x07:
6170 case 0x20: case 0x21: case 0x24 ... 0x27:
6171 case 0x30: case 0x31: case 0x34 ... 0x37:
6172 {
6173 int op1;
6174
6175 op1 = op & 7;
6176 if (op >= 0x20) {
6177 gen_helper_fp_arith_STN_ST0(op1, opreg);
6178 if (op >= 0x30)
6179 gen_helper_fpop(cpu_env);
6180 } else {
6181 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6182 gen_helper_fp_arith_ST0_FT0(op1);
6183 }
6184 }
6185 break;
6186 case 0x02:
6187 case 0x22:
6188 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6189 gen_helper_fcom_ST0_FT0(cpu_env);
6190 break;
6191 case 0x03:
6192 case 0x23:
6193 case 0x32:
6194 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6195 gen_helper_fcom_ST0_FT0(cpu_env);
6196 gen_helper_fpop(cpu_env);
6197 break;
6198 case 0x15:
6199 switch(rm) {
6200 case 1:
6201 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6202 gen_helper_fucom_ST0_FT0(cpu_env);
6203 gen_helper_fpop(cpu_env);
6204 gen_helper_fpop(cpu_env);
6205 break;
6206 default:
6207 goto unknown_op;
6208 }
6209 break;
6210 case 0x1c:
6211 switch(rm) {
6212 case 0:
6213 break;
6214 case 1:
6215 break;
6216 case 2:
6217 gen_helper_fclex(cpu_env);
6218 break;
6219 case 3:
6220 gen_helper_fninit(cpu_env);
6221 break;
6222 case 4:
6223 break;
6224 default:
6225 goto unknown_op;
6226 }
6227 break;
6228 case 0x1d:
6229 if (!(s->cpuid_features & CPUID_CMOV)) {
6230 goto illegal_op;
6231 }
6232 gen_update_cc_op(s);
6233 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6234 gen_helper_fucomi_ST0_FT0(cpu_env);
6235 set_cc_op(s, CC_OP_EFLAGS);
6236 break;
6237 case 0x1e:
6238 if (!(s->cpuid_features & CPUID_CMOV)) {
6239 goto illegal_op;
6240 }
6241 gen_update_cc_op(s);
6242 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6243 gen_helper_fcomi_ST0_FT0(cpu_env);
6244 set_cc_op(s, CC_OP_EFLAGS);
6245 break;
6246 case 0x28:
6247 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6248 break;
6249 case 0x2a:
6250 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6251 break;
6252 case 0x2b:
6253 case 0x0b:
6254 case 0x3a:
6255 case 0x3b:
6256 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6257 gen_helper_fpop(cpu_env);
6258 break;
6259 case 0x2c:
6260 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6261 gen_helper_fucom_ST0_FT0(cpu_env);
6262 break;
6263 case 0x2d:
6264 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6265 gen_helper_fucom_ST0_FT0(cpu_env);
6266 gen_helper_fpop(cpu_env);
6267 break;
6268 case 0x33:
6269 switch(rm) {
6270 case 1:
6271 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6272 gen_helper_fcom_ST0_FT0(cpu_env);
6273 gen_helper_fpop(cpu_env);
6274 gen_helper_fpop(cpu_env);
6275 break;
6276 default:
6277 goto unknown_op;
6278 }
6279 break;
6280 case 0x38:
6281 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6282 gen_helper_fpop(cpu_env);
6283 break;
6284 case 0x3c:
6285 switch(rm) {
6286 case 0:
6287 gen_helper_fnstsw(s->tmp2_i32, cpu_env);
6288 tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
6289 gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
6290 break;
6291 default:
6292 goto unknown_op;
6293 }
6294 break;
6295 case 0x3d:
6296 if (!(s->cpuid_features & CPUID_CMOV)) {
6297 goto illegal_op;
6298 }
6299 gen_update_cc_op(s);
6300 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6301 gen_helper_fucomi_ST0_FT0(cpu_env);
6302 gen_helper_fpop(cpu_env);
6303 set_cc_op(s, CC_OP_EFLAGS);
6304 break;
6305 case 0x3e:
6306 if (!(s->cpuid_features & CPUID_CMOV)) {
6307 goto illegal_op;
6308 }
6309 gen_update_cc_op(s);
6310 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6311 gen_helper_fcomi_ST0_FT0(cpu_env);
6312 gen_helper_fpop(cpu_env);
6313 set_cc_op(s, CC_OP_EFLAGS);
6314 break;
6315 case 0x10 ... 0x13:
6316 case 0x18 ... 0x1b:
6317 {
6318 int op1;
6319 TCGLabel *l1;
6320 static const uint8_t fcmov_cc[8] = {
6321 (JCC_B << 1),
6322 (JCC_Z << 1),
6323 (JCC_BE << 1),
6324 (JCC_P << 1),
6325 };
6326
6327 if (!(s->cpuid_features & CPUID_CMOV)) {
6328 goto illegal_op;
6329 }
6330 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6331 l1 = gen_new_label();
6332 gen_jcc1_noeob(s, op1, l1);
6333 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6334 gen_set_label(l1);
6335 }
6336 break;
6337 default:
6338 goto unknown_op;
6339 }
6340 }
6341 break;
6342
6343
6344
6345 case 0xa4:
6346 case 0xa5:
6347 ot = mo_b_d(b, dflag);
6348 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6349 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6350 } else {
6351 gen_movs(s, ot);
6352 }
6353 break;
6354
6355 case 0xaa:
6356 case 0xab:
6357 ot = mo_b_d(b, dflag);
6358 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6359 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6360 } else {
6361 gen_stos(s, ot);
6362 }
6363 break;
6364 case 0xac:
6365 case 0xad:
6366 ot = mo_b_d(b, dflag);
6367 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6368 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6369 } else {
6370 gen_lods(s, ot);
6371 }
6372 break;
6373 case 0xae:
6374 case 0xaf:
6375 ot = mo_b_d(b, dflag);
6376 if (prefixes & PREFIX_REPNZ) {
6377 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6378 } else if (prefixes & PREFIX_REPZ) {
6379 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6380 } else {
6381 gen_scas(s, ot);
6382 }
6383 break;
6384
6385 case 0xa6:
6386 case 0xa7:
6387 ot = mo_b_d(b, dflag);
6388 if (prefixes & PREFIX_REPNZ) {
6389 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6390 } else if (prefixes & PREFIX_REPZ) {
6391 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6392 } else {
6393 gen_cmps(s, ot);
6394 }
6395 break;
6396 case 0x6c:
6397 case 0x6d:
6398 ot = mo_b_d32(b, dflag);
6399 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6400 gen_check_io(s, ot, pc_start - s->cs_base,
6401 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6402 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6403 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6404 } else {
6405 gen_ins(s, ot);
6406 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6407 gen_jmp(s, s->pc - s->cs_base);
6408 }
6409 }
6410 break;
6411 case 0x6e:
6412 case 0x6f:
6413 ot = mo_b_d32(b, dflag);
6414 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6415 gen_check_io(s, ot, pc_start - s->cs_base,
6416 svm_is_rep(prefixes) | 4);
6417 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6418 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6419 } else {
6420 gen_outs(s, ot);
6421 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6422 gen_jmp(s, s->pc - s->cs_base);
6423 }
6424 }
6425 break;
6426
6427
6428
6429
6430 case 0xe4:
6431 case 0xe5:
6432 ot = mo_b_d32(b, dflag);
6433 val = x86_ldub_code(env, s);
6434 tcg_gen_movi_tl(s->T0, val);
6435 gen_check_io(s, ot, pc_start - s->cs_base,
6436 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6437 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6438 gen_io_start();
6439 }
6440 tcg_gen_movi_i32(s->tmp2_i32, val);
6441 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6442 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6443 gen_bpt_io(s, s->tmp2_i32, ot);
6444 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6445 gen_jmp(s, s->pc - s->cs_base);
6446 }
6447 break;
6448 case 0xe6:
6449 case 0xe7:
6450 ot = mo_b_d32(b, dflag);
6451 val = x86_ldub_code(env, s);
6452 tcg_gen_movi_tl(s->T0, val);
6453 gen_check_io(s, ot, pc_start - s->cs_base,
6454 svm_is_rep(prefixes));
6455 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6456
6457 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6458 gen_io_start();
6459 }
6460 tcg_gen_movi_i32(s->tmp2_i32, val);
6461 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6462 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6463 gen_bpt_io(s, s->tmp2_i32, ot);
6464 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6465 gen_jmp(s, s->pc - s->cs_base);
6466 }
6467 break;
6468 case 0xec:
6469 case 0xed:
6470 ot = mo_b_d32(b, dflag);
6471 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6472 gen_check_io(s, ot, pc_start - s->cs_base,
6473 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6474 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6475 gen_io_start();
6476 }
6477 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
6478 gen_helper_in_func(ot, s->T1, s->tmp2_i32);
6479 gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
6480 gen_bpt_io(s, s->tmp2_i32, ot);
6481 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6482 gen_jmp(s, s->pc - s->cs_base);
6483 }
6484 break;
6485 case 0xee:
6486 case 0xef:
6487 ot = mo_b_d32(b, dflag);
6488 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
6489 gen_check_io(s, ot, pc_start - s->cs_base,
6490 svm_is_rep(prefixes));
6491 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
6492
6493 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6494 gen_io_start();
6495 }
6496 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
6497 tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
6498 gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
6499 gen_bpt_io(s, s->tmp2_i32, ot);
6500 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
6501 gen_jmp(s, s->pc - s->cs_base);
6502 }
6503 break;
6504
6505
6506
6507 case 0xc2:
6508 val = x86_ldsw_code(env, s);
6509 ot = gen_pop_T0(s);
6510 gen_stack_update(s, val + (1 << ot));
6511
6512 gen_op_jmp_v(s->T0);
6513 gen_bnd_jmp(s);
6514 gen_jr(s, s->T0);
6515 break;
6516 case 0xc3:
6517 ot = gen_pop_T0(s);
6518 gen_pop_update(s, ot);
6519
6520 gen_op_jmp_v(s->T0);
6521 gen_bnd_jmp(s);
6522 gen_jr(s, s->T0);
6523 break;
6524 case 0xca:
6525 val = x86_ldsw_code(env, s);
6526 do_lret:
6527 if (s->pe && !s->vm86) {
6528 gen_update_cc_op(s);
6529 gen_jmp_im(s, pc_start - s->cs_base);
6530 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
6531 tcg_const_i32(val));
6532 } else {
6533 gen_stack_A0(s);
6534
6535 gen_op_ld_v(s, dflag, s->T0, s->A0);
6536
6537
6538 gen_op_jmp_v(s->T0);
6539
6540 gen_add_A0_im(s, 1 << dflag);
6541 gen_op_ld_v(s, dflag, s->T0, s->A0);
6542 gen_op_movl_seg_T0_vm(s, R_CS);
6543
6544 gen_stack_update(s, val + (2 << dflag));
6545 }
6546 gen_eob(s);
6547 break;
6548 case 0xcb:
6549 val = 0;
6550 goto do_lret;
6551 case 0xcf:
6552 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6553 if (!s->pe) {
6554
6555 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6556 set_cc_op(s, CC_OP_EFLAGS);
6557 } else if (s->vm86) {
6558 if (s->iopl != 3) {
6559 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6560 } else {
6561 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
6562 set_cc_op(s, CC_OP_EFLAGS);
6563 }
6564 } else {
6565 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
6566 tcg_const_i32(s->pc - s->cs_base));
6567 set_cc_op(s, CC_OP_EFLAGS);
6568 }
6569 gen_eob(s);
6570 break;
6571 case 0xe8:
6572 {
6573 if (dflag != MO_16) {
6574 tval = (int32_t)insn_get(env, s, MO_32);
6575 } else {
6576 tval = (int16_t)insn_get(env, s, MO_16);
6577 }
6578 next_eip = s->pc - s->cs_base;
6579 tval += next_eip;
6580 if (dflag == MO_16) {
6581 tval &= 0xffff;
6582 } else if (!CODE64(s)) {
6583 tval &= 0xffffffff;
6584 }
6585 tcg_gen_movi_tl(s->T0, next_eip);
6586 gen_push_v(s, s->T0);
6587 gen_bnd_jmp(s);
6588 gen_jmp(s, tval);
6589 }
6590 break;
6591 case 0x9a:
6592 {
6593 unsigned int selector, offset;
6594
6595 if (CODE64(s))
6596 goto illegal_op;
6597 ot = dflag;
6598 offset = insn_get(env, s, ot);
6599 selector = insn_get(env, s, MO_16);
6600
6601 tcg_gen_movi_tl(s->T0, selector);
6602 tcg_gen_movi_tl(s->T1, offset);
6603 }
6604 goto do_lcall;
6605 case 0xe9:
6606 if (dflag != MO_16) {
6607 tval = (int32_t)insn_get(env, s, MO_32);
6608 } else {
6609 tval = (int16_t)insn_get(env, s, MO_16);
6610 }
6611 tval += s->pc - s->cs_base;
6612 if (dflag == MO_16) {
6613 tval &= 0xffff;
6614 } else if (!CODE64(s)) {
6615 tval &= 0xffffffff;
6616 }
6617 gen_bnd_jmp(s);
6618 gen_jmp(s, tval);
6619 break;
6620 case 0xea:
6621 {
6622 unsigned int selector, offset;
6623
6624 if (CODE64(s))
6625 goto illegal_op;
6626 ot = dflag;
6627 offset = insn_get(env, s, ot);
6628 selector = insn_get(env, s, MO_16);
6629
6630 tcg_gen_movi_tl(s->T0, selector);
6631 tcg_gen_movi_tl(s->T1, offset);
6632 }
6633 goto do_ljmp;
6634 case 0xeb:
6635 tval = (int8_t)insn_get(env, s, MO_8);
6636 tval += s->pc - s->cs_base;
6637 if (dflag == MO_16) {
6638 tval &= 0xffff;
6639 }
6640 gen_jmp(s, tval);
6641 break;
6642 case 0x70 ... 0x7f:
6643 tval = (int8_t)insn_get(env, s, MO_8);
6644 goto do_jcc;
6645 case 0x180 ... 0x18f:
6646 if (dflag != MO_16) {
6647 tval = (int32_t)insn_get(env, s, MO_32);
6648 } else {
6649 tval = (int16_t)insn_get(env, s, MO_16);
6650 }
6651 do_jcc:
6652 next_eip = s->pc - s->cs_base;
6653 tval += next_eip;
6654 if (dflag == MO_16) {
6655 tval &= 0xffff;
6656 }
6657 gen_bnd_jmp(s);
6658 gen_jcc(s, b, tval, next_eip);
6659 break;
6660
6661 case 0x190 ... 0x19f:
6662 modrm = x86_ldub_code(env, s);
6663 gen_setcc1(s, b, s->T0);
6664 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
6665 break;
6666 case 0x140 ... 0x14f:
6667 if (!(s->cpuid_features & CPUID_CMOV)) {
6668 goto illegal_op;
6669 }
6670 ot = dflag;
6671 modrm = x86_ldub_code(env, s);
6672 reg = ((modrm >> 3) & 7) | rex_r;
6673 gen_cmovcc1(env, s, ot, b, modrm, reg);
6674 break;
6675
6676
6677
6678 case 0x9c:
6679 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6680 if (s->vm86 && s->iopl != 3) {
6681 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6682 } else {
6683 gen_update_cc_op(s);
6684 gen_helper_read_eflags(s->T0, cpu_env);
6685 gen_push_v(s, s->T0);
6686 }
6687 break;
6688 case 0x9d:
6689 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6690 if (s->vm86 && s->iopl != 3) {
6691 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6692 } else {
6693 ot = gen_pop_T0(s);
6694 if (s->cpl == 0) {
6695 if (dflag != MO_16) {
6696 gen_helper_write_eflags(cpu_env, s->T0,
6697 tcg_const_i32((TF_MASK | AC_MASK |
6698 ID_MASK | NT_MASK |
6699 IF_MASK |
6700 IOPL_MASK)));
6701 } else {
6702 gen_helper_write_eflags(cpu_env, s->T0,
6703 tcg_const_i32((TF_MASK | AC_MASK |
6704 ID_MASK | NT_MASK |
6705 IF_MASK | IOPL_MASK)
6706 & 0xffff));
6707 }
6708 } else {
6709 if (s->cpl <= s->iopl) {
6710 if (dflag != MO_16) {
6711 gen_helper_write_eflags(cpu_env, s->T0,
6712 tcg_const_i32((TF_MASK |
6713 AC_MASK |
6714 ID_MASK |
6715 NT_MASK |
6716 IF_MASK)));
6717 } else {
6718 gen_helper_write_eflags(cpu_env, s->T0,
6719 tcg_const_i32((TF_MASK |
6720 AC_MASK |
6721 ID_MASK |
6722 NT_MASK |
6723 IF_MASK)
6724 & 0xffff));
6725 }
6726 } else {
6727 if (dflag != MO_16) {
6728 gen_helper_write_eflags(cpu_env, s->T0,
6729 tcg_const_i32((TF_MASK | AC_MASK |
6730 ID_MASK | NT_MASK)));
6731 } else {
6732 gen_helper_write_eflags(cpu_env, s->T0,
6733 tcg_const_i32((TF_MASK | AC_MASK |
6734 ID_MASK | NT_MASK)
6735 & 0xffff));
6736 }
6737 }
6738 }
6739 gen_pop_update(s, ot);
6740 set_cc_op(s, CC_OP_EFLAGS);
6741
6742 gen_jmp_im(s, s->pc - s->cs_base);
6743 gen_eob(s);
6744 }
6745 break;
6746 case 0x9e:
6747 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6748 goto illegal_op;
6749 gen_op_mov_v_reg(s, MO_8, s->T0, R_AH);
6750 gen_compute_eflags(s);
6751 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6752 tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6753 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
6754 break;
6755 case 0x9f:
6756 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6757 goto illegal_op;
6758 gen_compute_eflags(s);
6759
6760 tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02);
6761 gen_op_mov_reg_v(s, MO_8, R_AH, s->T0);
6762 break;
6763 case 0xf5:
6764 gen_compute_eflags(s);
6765 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6766 break;
6767 case 0xf8:
6768 gen_compute_eflags(s);
6769 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6770 break;
6771 case 0xf9:
6772 gen_compute_eflags(s);
6773 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6774 break;
6775 case 0xfc:
6776 tcg_gen_movi_i32(s->tmp2_i32, 1);
6777 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6778 break;
6779 case 0xfd:
6780 tcg_gen_movi_i32(s->tmp2_i32, -1);
6781 tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6782 break;
6783
6784
6785
6786 case 0x1ba:
6787 ot = dflag;
6788 modrm = x86_ldub_code(env, s);
6789 op = (modrm >> 3) & 7;
6790 mod = (modrm >> 6) & 3;
6791 rm = (modrm & 7) | REX_B(s);
6792 if (mod != 3) {
6793 s->rip_offset = 1;
6794 gen_lea_modrm(env, s, modrm);
6795 if (!(s->prefix & PREFIX_LOCK)) {
6796 gen_op_ld_v(s, ot, s->T0, s->A0);
6797 }
6798 } else {
6799 gen_op_mov_v_reg(s, ot, s->T0, rm);
6800 }
6801
6802 val = x86_ldub_code(env, s);
6803 tcg_gen_movi_tl(s->T1, val);
6804 if (op < 4)
6805 goto unknown_op;
6806 op -= 4;
6807 goto bt_op;
6808 case 0x1a3:
6809 op = 0;
6810 goto do_btx;
6811 case 0x1ab:
6812 op = 1;
6813 goto do_btx;
6814 case 0x1b3:
6815 op = 2;
6816 goto do_btx;
6817 case 0x1bb:
6818 op = 3;
6819 do_btx:
6820 ot = dflag;
6821 modrm = x86_ldub_code(env, s);
6822 reg = ((modrm >> 3) & 7) | rex_r;
6823 mod = (modrm >> 6) & 3;
6824 rm = (modrm & 7) | REX_B(s);
6825 gen_op_mov_v_reg(s, MO_32, s->T1, reg);
6826 if (mod != 3) {
6827 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6828
6829 gen_exts(ot, s->T1);
6830 tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
6831 tcg_gen_shli_tl(s->tmp0, s->tmp0, ot);
6832 tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a), s->tmp0);
6833 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
6834 if (!(s->prefix & PREFIX_LOCK)) {
6835 gen_op_ld_v(s, ot, s->T0, s->A0);
6836 }
6837 } else {
6838 gen_op_mov_v_reg(s, ot, s->T0, rm);
6839 }
6840 bt_op:
6841 tcg_gen_andi_tl(s->T1, s->T1, (1 << (3 + ot)) - 1);
6842 tcg_gen_movi_tl(s->tmp0, 1);
6843 tcg_gen_shl_tl(s->tmp0, s->tmp0, s->T1);
6844 if (s->prefix & PREFIX_LOCK) {
6845 switch (op) {
6846 case 0:
6847
6848
6849 gen_op_ld_v(s, ot, s->T0, s->A0);
6850 break;
6851 case 1:
6852 tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, s->tmp0,
6853 s->mem_index, ot | MO_LE);
6854 break;
6855 case 2:
6856 tcg_gen_not_tl(s->tmp0, s->tmp0);
6857 tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, s->tmp0,
6858 s->mem_index, ot | MO_LE);
6859 break;
6860 default:
6861 case 3:
6862 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0,
6863 s->mem_index, ot | MO_LE);
6864 break;
6865 }
6866 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6867 } else {
6868 tcg_gen_shr_tl(s->tmp4, s->T0, s->T1);
6869 switch (op) {
6870 case 0:
6871
6872 break;
6873 case 1:
6874 tcg_gen_or_tl(s->T0, s->T0, s->tmp0);
6875 break;
6876 case 2:
6877 tcg_gen_andc_tl(s->T0, s->T0, s->tmp0);
6878 break;
6879 default:
6880 case 3:
6881 tcg_gen_xor_tl(s->T0, s->T0, s->tmp0);
6882 break;
6883 }
6884 if (op != 0) {
6885 if (mod != 3) {
6886 gen_op_st_v(s, ot, s->T0, s->A0);
6887 } else {
6888 gen_op_mov_reg_v(s, ot, rm, s->T0);
6889 }
6890 }
6891 }
6892
6893
6894
6895
6896 switch (s->cc_op) {
6897 case CC_OP_MULB ... CC_OP_MULQ:
6898 case CC_OP_ADDB ... CC_OP_ADDQ:
6899 case CC_OP_ADCB ... CC_OP_ADCQ:
6900 case CC_OP_SUBB ... CC_OP_SUBQ:
6901 case CC_OP_SBBB ... CC_OP_SBBQ:
6902 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6903 case CC_OP_INCB ... CC_OP_INCQ:
6904 case CC_OP_DECB ... CC_OP_DECQ:
6905 case CC_OP_SHLB ... CC_OP_SHLQ:
6906 case CC_OP_SARB ... CC_OP_SARQ:
6907 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6908
6909
6910
6911
6912 tcg_gen_mov_tl(cpu_cc_src, s->tmp4);
6913 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6914 break;
6915 default:
6916
6917 gen_compute_eflags(s);
6918 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, s->tmp4,
6919 ctz32(CC_C), 1);
6920 break;
6921 }
6922 break;
6923 case 0x1bc:
6924 case 0x1bd:
6925 ot = dflag;
6926 modrm = x86_ldub_code(env, s);
6927 reg = ((modrm >> 3) & 7) | rex_r;
6928 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6929 gen_extu(ot, s->T0);
6930
6931
6932 if ((prefixes & PREFIX_REPZ)
6933 && (b & 1
6934 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6935 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6936 int size = 8 << ot;
6937
6938 tcg_gen_mov_tl(cpu_cc_src, s->T0);
6939 if (b & 1) {
6940
6941
6942 tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
6943 tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
6944 } else {
6945
6946 tcg_gen_ctzi_tl(s->T0, s->T0, size);
6947 }
6948
6949 gen_op_update1_cc(s);
6950 set_cc_op(s, CC_OP_BMILGB + ot);
6951 } else {
6952
6953
6954 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
6955 set_cc_op(s, CC_OP_LOGICB + ot);
6956
6957
6958
6959
6960
6961 if (b & 1) {
6962
6963
6964 tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
6965 tcg_gen_clz_tl(s->T0, s->T0, s->T1);
6966 tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
6967 } else {
6968 tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
6969 }
6970 }
6971 gen_op_mov_reg_v(s, ot, reg, s->T0);
6972 break;
6973
6974
6975 case 0x27:
6976 if (CODE64(s))
6977 goto illegal_op;
6978 gen_update_cc_op(s);
6979 gen_helper_daa(cpu_env);
6980 set_cc_op(s, CC_OP_EFLAGS);
6981 break;
6982 case 0x2f:
6983 if (CODE64(s))
6984 goto illegal_op;
6985 gen_update_cc_op(s);
6986 gen_helper_das(cpu_env);
6987 set_cc_op(s, CC_OP_EFLAGS);
6988 break;
6989 case 0x37:
6990 if (CODE64(s))
6991 goto illegal_op;
6992 gen_update_cc_op(s);
6993 gen_helper_aaa(cpu_env);
6994 set_cc_op(s, CC_OP_EFLAGS);
6995 break;
6996 case 0x3f:
6997 if (CODE64(s))
6998 goto illegal_op;
6999 gen_update_cc_op(s);
7000 gen_helper_aas(cpu_env);
7001 set_cc_op(s, CC_OP_EFLAGS);
7002 break;
7003 case 0xd4:
7004 if (CODE64(s))
7005 goto illegal_op;
7006 val = x86_ldub_code(env, s);
7007 if (val == 0) {
7008 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
7009 } else {
7010 gen_helper_aam(cpu_env, tcg_const_i32(val));
7011 set_cc_op(s, CC_OP_LOGICB);
7012 }
7013 break;
7014 case 0xd5:
7015 if (CODE64(s))
7016 goto illegal_op;
7017 val = x86_ldub_code(env, s);
7018 gen_helper_aad(cpu_env, tcg_const_i32(val));
7019 set_cc_op(s, CC_OP_LOGICB);
7020 break;
7021
7022
7023 case 0x90:
7024
7025 if (prefixes & PREFIX_LOCK) {
7026 goto illegal_op;
7027 }
7028
7029 if (REX_B(s)) {
7030 goto do_xchg_reg_eax;
7031 }
7032 if (prefixes & PREFIX_REPZ) {
7033 gen_update_cc_op(s);
7034 gen_jmp_im(s, pc_start - s->cs_base);
7035 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
7036 s->base.is_jmp = DISAS_NORETURN;
7037 }
7038 break;
7039 case 0x9b:
7040 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7041 (HF_MP_MASK | HF_TS_MASK)) {
7042 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7043 } else {
7044 gen_helper_fwait(cpu_env);
7045 }
7046 break;
7047 case 0xcc:
7048 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7049 break;
7050 case 0xcd:
7051 val = x86_ldub_code(env, s);
7052 if (s->vm86 && s->iopl != 3) {
7053 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7054 } else {
7055 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7056 }
7057 break;
7058 case 0xce:
7059 if (CODE64(s))
7060 goto illegal_op;
7061 gen_update_cc_op(s);
7062 gen_jmp_im(s, pc_start - s->cs_base);
7063 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
7064 break;
7065#ifdef WANT_ICEBP
7066 case 0xf1:
7067 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
7068 gen_debug(s, pc_start - s->cs_base);
7069 break;
7070#endif
7071 case 0xfa:
7072 if (!s->vm86) {
7073 if (s->cpl <= s->iopl) {
7074 gen_helper_cli(cpu_env);
7075 } else {
7076 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7077 }
7078 } else {
7079 if (s->iopl == 3) {
7080 gen_helper_cli(cpu_env);
7081 } else {
7082 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7083 }
7084 }
7085 break;
7086 case 0xfb:
7087 if (s->vm86 ? s->iopl == 3 : s->cpl <= s->iopl) {
7088 gen_helper_sti(cpu_env);
7089
7090 gen_jmp_im(s, s->pc - s->cs_base);
7091 gen_eob_inhibit_irq(s, true);
7092 } else {
7093 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7094 }
7095 break;
7096 case 0x62:
7097 if (CODE64(s))
7098 goto illegal_op;
7099 ot = dflag;
7100 modrm = x86_ldub_code(env, s);
7101 reg = (modrm >> 3) & 7;
7102 mod = (modrm >> 6) & 3;
7103 if (mod == 3)
7104 goto illegal_op;
7105 gen_op_mov_v_reg(s, ot, s->T0, reg);
7106 gen_lea_modrm(env, s, modrm);
7107 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7108 if (ot == MO_16) {
7109 gen_helper_boundw(cpu_env, s->A0, s->tmp2_i32);
7110 } else {
7111 gen_helper_boundl(cpu_env, s->A0, s->tmp2_i32);
7112 }
7113 break;
7114 case 0x1c8 ... 0x1cf:
7115 reg = (b & 7) | REX_B(s);
7116#ifdef TARGET_X86_64
7117 if (dflag == MO_64) {
7118 gen_op_mov_v_reg(s, MO_64, s->T0, reg);
7119 tcg_gen_bswap64_i64(s->T0, s->T0);
7120 gen_op_mov_reg_v(s, MO_64, reg, s->T0);
7121 } else
7122#endif
7123 {
7124 gen_op_mov_v_reg(s, MO_32, s->T0, reg);
7125 tcg_gen_ext32u_tl(s->T0, s->T0);
7126 tcg_gen_bswap32_tl(s->T0, s->T0);
7127 gen_op_mov_reg_v(s, MO_32, reg, s->T0);
7128 }
7129 break;
7130 case 0xd6:
7131 if (CODE64(s))
7132 goto illegal_op;
7133 gen_compute_eflags_c(s, s->T0);
7134 tcg_gen_neg_tl(s->T0, s->T0);
7135 gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0);
7136 break;
7137 case 0xe0:
7138 case 0xe1:
7139 case 0xe2:
7140 case 0xe3:
7141 {
7142 TCGLabel *l1, *l2, *l3;
7143
7144 tval = (int8_t)insn_get(env, s, MO_8);
7145 next_eip = s->pc - s->cs_base;
7146 tval += next_eip;
7147 if (dflag == MO_16) {
7148 tval &= 0xffff;
7149 }
7150
7151 l1 = gen_new_label();
7152 l2 = gen_new_label();
7153 l3 = gen_new_label();
7154 b &= 3;
7155 switch(b) {
7156 case 0:
7157 case 1:
7158 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7159 gen_op_jz_ecx(s, s->aflag, l3);
7160 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7161 break;
7162 case 2:
7163 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
7164 gen_op_jnz_ecx(s, s->aflag, l1);
7165 break;
7166 default:
7167 case 3:
7168 gen_op_jz_ecx(s, s->aflag, l1);
7169 break;
7170 }
7171
7172 gen_set_label(l3);
7173 gen_jmp_im(s, next_eip);
7174 tcg_gen_br(l2);
7175
7176 gen_set_label(l1);
7177 gen_jmp_im(s, tval);
7178 gen_set_label(l2);
7179 gen_eob(s);
7180 }
7181 break;
7182 case 0x130:
7183 case 0x132:
7184 if (s->cpl != 0) {
7185 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7186 } else {
7187 gen_update_cc_op(s);
7188 gen_jmp_im(s, pc_start - s->cs_base);
7189 if (b & 2) {
7190 gen_helper_rdmsr(cpu_env);
7191 } else {
7192 gen_helper_wrmsr(cpu_env);
7193 }
7194 }
7195 break;
7196 case 0x131:
7197 gen_update_cc_op(s);
7198 gen_jmp_im(s, pc_start - s->cs_base);
7199 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7200 gen_io_start();
7201 }
7202 gen_helper_rdtsc(cpu_env);
7203 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7204 gen_jmp(s, s->pc - s->cs_base);
7205 }
7206 break;
7207 case 0x133:
7208 gen_update_cc_op(s);
7209 gen_jmp_im(s, pc_start - s->cs_base);
7210 gen_helper_rdpmc(cpu_env);
7211 break;
7212 case 0x134:
7213
7214 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7215 goto illegal_op;
7216 if (!s->pe) {
7217 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7218 } else {
7219 gen_helper_sysenter(cpu_env);
7220 gen_eob(s);
7221 }
7222 break;
7223 case 0x135:
7224
7225 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7226 goto illegal_op;
7227 if (!s->pe) {
7228 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7229 } else {
7230 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
7231 gen_eob(s);
7232 }
7233 break;
7234#ifdef TARGET_X86_64
7235 case 0x105:
7236
7237 gen_update_cc_op(s);
7238 gen_jmp_im(s, pc_start - s->cs_base);
7239 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7240
7241
7242
7243 gen_eob_worker(s, false, true);
7244 break;
7245 case 0x107:
7246 if (!s->pe) {
7247 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7248 } else {
7249 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
7250
7251 if (s->lma) {
7252 set_cc_op(s, CC_OP_EFLAGS);
7253 }
7254
7255
7256
7257
7258 gen_eob_worker(s, false, true);
7259 }
7260 break;
7261#endif
7262 case 0x1a2:
7263 gen_update_cc_op(s);
7264 gen_jmp_im(s, pc_start - s->cs_base);
7265 gen_helper_cpuid(cpu_env);
7266 break;
7267 case 0xf4:
7268 if (s->cpl != 0) {
7269 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7270 } else {
7271 gen_update_cc_op(s);
7272 gen_jmp_im(s, pc_start - s->cs_base);
7273 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7274 s->base.is_jmp = DISAS_NORETURN;
7275 }
7276 break;
7277 case 0x100:
7278 modrm = x86_ldub_code(env, s);
7279 mod = (modrm >> 6) & 3;
7280 op = (modrm >> 3) & 7;
7281 switch(op) {
7282 case 0:
7283 if (!s->pe || s->vm86)
7284 goto illegal_op;
7285 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7286 tcg_gen_ld32u_tl(s->T0, cpu_env,
7287 offsetof(CPUX86State, ldt.selector));
7288 ot = mod == 3 ? dflag : MO_16;
7289 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7290 break;
7291 case 2:
7292 if (!s->pe || s->vm86)
7293 goto illegal_op;
7294 if (s->cpl != 0) {
7295 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7296 } else {
7297 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7298 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7299 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7300 gen_helper_lldt(cpu_env, s->tmp2_i32);
7301 }
7302 break;
7303 case 1:
7304 if (!s->pe || s->vm86)
7305 goto illegal_op;
7306 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7307 tcg_gen_ld32u_tl(s->T0, cpu_env,
7308 offsetof(CPUX86State, tr.selector));
7309 ot = mod == 3 ? dflag : MO_16;
7310 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7311 break;
7312 case 3:
7313 if (!s->pe || s->vm86)
7314 goto illegal_op;
7315 if (s->cpl != 0) {
7316 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7317 } else {
7318 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7319 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7320 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
7321 gen_helper_ltr(cpu_env, s->tmp2_i32);
7322 }
7323 break;
7324 case 4:
7325 case 5:
7326 if (!s->pe || s->vm86)
7327 goto illegal_op;
7328 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7329 gen_update_cc_op(s);
7330 if (op == 4) {
7331 gen_helper_verr(cpu_env, s->T0);
7332 } else {
7333 gen_helper_verw(cpu_env, s->T0);
7334 }
7335 set_cc_op(s, CC_OP_EFLAGS);
7336 break;
7337 default:
7338 goto unknown_op;
7339 }
7340 break;
7341
7342 case 0x101:
7343 modrm = x86_ldub_code(env, s);
7344 switch (modrm) {
7345 CASE_MODRM_MEM_OP(0):
7346 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7347 gen_lea_modrm(env, s, modrm);
7348 tcg_gen_ld32u_tl(s->T0,
7349 cpu_env, offsetof(CPUX86State, gdt.limit));
7350 gen_op_st_v(s, MO_16, s->T0, s->A0);
7351 gen_add_A0_im(s, 2);
7352 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7353 if (dflag == MO_16) {
7354 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7355 }
7356 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7357 break;
7358
7359 case 0xc8:
7360 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7361 goto illegal_op;
7362 }
7363 gen_update_cc_op(s);
7364 gen_jmp_im(s, pc_start - s->cs_base);
7365 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7366 gen_extu(s->aflag, s->A0);
7367 gen_add_A0_ds_seg(s);
7368 gen_helper_monitor(cpu_env, s->A0);
7369 break;
7370
7371 case 0xc9:
7372 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7373 goto illegal_op;
7374 }
7375 gen_update_cc_op(s);
7376 gen_jmp_im(s, pc_start - s->cs_base);
7377 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7378 gen_eob(s);
7379 break;
7380
7381 case 0xca:
7382 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7383 || s->cpl != 0) {
7384 goto illegal_op;
7385 }
7386 gen_helper_clac(cpu_env);
7387 gen_jmp_im(s, s->pc - s->cs_base);
7388 gen_eob(s);
7389 break;
7390
7391 case 0xcb:
7392 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7393 || s->cpl != 0) {
7394 goto illegal_op;
7395 }
7396 gen_helper_stac(cpu_env);
7397 gen_jmp_im(s, s->pc - s->cs_base);
7398 gen_eob(s);
7399 break;
7400
7401 CASE_MODRM_MEM_OP(1):
7402 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7403 gen_lea_modrm(env, s, modrm);
7404 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit));
7405 gen_op_st_v(s, MO_16, s->T0, s->A0);
7406 gen_add_A0_im(s, 2);
7407 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7408 if (dflag == MO_16) {
7409 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7410 }
7411 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7412 break;
7413
7414 case 0xd0:
7415 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7416 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7417 | PREFIX_REPZ | PREFIX_REPNZ))) {
7418 goto illegal_op;
7419 }
7420 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7421 gen_helper_xgetbv(s->tmp1_i64, cpu_env, s->tmp2_i32);
7422 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7423 break;
7424
7425 case 0xd1:
7426 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7427 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7428 | PREFIX_REPZ | PREFIX_REPNZ))) {
7429 goto illegal_op;
7430 }
7431 if (s->cpl != 0) {
7432 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7433 break;
7434 }
7435 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7436 cpu_regs[R_EDX]);
7437 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7438 gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
7439
7440 gen_jmp_im(s, s->pc - s->cs_base);
7441 gen_eob(s);
7442 break;
7443
7444 case 0xd8:
7445 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7446 goto illegal_op;
7447 }
7448 if (s->cpl != 0) {
7449 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7450 break;
7451 }
7452 gen_update_cc_op(s);
7453 gen_jmp_im(s, pc_start - s->cs_base);
7454 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7455 tcg_const_i32(s->pc - pc_start));
7456 tcg_gen_exit_tb(NULL, 0);
7457 s->base.is_jmp = DISAS_NORETURN;
7458 break;
7459
7460 case 0xd9:
7461 if (!(s->flags & HF_SVME_MASK)) {
7462 goto illegal_op;
7463 }
7464 gen_update_cc_op(s);
7465 gen_jmp_im(s, pc_start - s->cs_base);
7466 gen_helper_vmmcall(cpu_env);
7467 break;
7468
7469 case 0xda:
7470 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7471 goto illegal_op;
7472 }
7473 if (s->cpl != 0) {
7474 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7475 break;
7476 }
7477 gen_update_cc_op(s);
7478 gen_jmp_im(s, pc_start - s->cs_base);
7479 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7480 break;
7481
7482 case 0xdb:
7483 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7484 goto illegal_op;
7485 }
7486 if (s->cpl != 0) {
7487 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7488 break;
7489 }
7490 gen_update_cc_op(s);
7491 gen_jmp_im(s, pc_start - s->cs_base);
7492 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7493 break;
7494
7495 case 0xdc:
7496 if ((!(s->flags & HF_SVME_MASK)
7497 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7498 || !s->pe) {
7499 goto illegal_op;
7500 }
7501 if (s->cpl != 0) {
7502 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7503 break;
7504 }
7505 gen_update_cc_op(s);
7506 gen_helper_stgi(cpu_env);
7507 gen_jmp_im(s, s->pc - s->cs_base);
7508 gen_eob(s);
7509 break;
7510
7511 case 0xdd:
7512 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7513 goto illegal_op;
7514 }
7515 if (s->cpl != 0) {
7516 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7517 break;
7518 }
7519 gen_update_cc_op(s);
7520 gen_jmp_im(s, pc_start - s->cs_base);
7521 gen_helper_clgi(cpu_env);
7522 break;
7523
7524 case 0xde:
7525 if ((!(s->flags & HF_SVME_MASK)
7526 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7527 || !s->pe) {
7528 goto illegal_op;
7529 }
7530 gen_update_cc_op(s);
7531 gen_jmp_im(s, pc_start - s->cs_base);
7532 gen_helper_skinit(cpu_env);
7533 break;
7534
7535 case 0xdf:
7536 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7537 goto illegal_op;
7538 }
7539 if (s->cpl != 0) {
7540 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7541 break;
7542 }
7543 gen_update_cc_op(s);
7544 gen_jmp_im(s, pc_start - s->cs_base);
7545 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7546 break;
7547
7548 CASE_MODRM_MEM_OP(2):
7549 if (s->cpl != 0) {
7550 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7551 break;
7552 }
7553 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE);
7554 gen_lea_modrm(env, s, modrm);
7555 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7556 gen_add_A0_im(s, 2);
7557 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7558 if (dflag == MO_16) {
7559 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7560 }
7561 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
7562 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7563 break;
7564
7565 CASE_MODRM_MEM_OP(3):
7566 if (s->cpl != 0) {
7567 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7568 break;
7569 }
7570 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7571 gen_lea_modrm(env, s, modrm);
7572 gen_op_ld_v(s, MO_16, s->T1, s->A0);
7573 gen_add_A0_im(s, 2);
7574 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
7575 if (dflag == MO_16) {
7576 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
7577 }
7578 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
7579 tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, idt.limit));
7580 break;
7581
7582 CASE_MODRM_OP(4):
7583 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7584 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
7585 if (CODE64(s)) {
7586 mod = (modrm >> 6) & 3;
7587 ot = (mod != 3 ? MO_16 : s->dflag);
7588 } else {
7589 ot = MO_16;
7590 }
7591 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7592 break;
7593 case 0xee:
7594 if (prefixes & PREFIX_LOCK) {
7595 goto illegal_op;
7596 }
7597 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7598 gen_helper_rdpkru(s->tmp1_i64, cpu_env, s->tmp2_i32);
7599 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
7600 break;
7601 case 0xef:
7602 if (prefixes & PREFIX_LOCK) {
7603 goto illegal_op;
7604 }
7605 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
7606 cpu_regs[R_EDX]);
7607 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
7608 gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64);
7609 break;
7610 CASE_MODRM_OP(6):
7611 if (s->cpl != 0) {
7612 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7613 break;
7614 }
7615 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7616 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7617 gen_helper_lmsw(cpu_env, s->T0);
7618 gen_jmp_im(s, s->pc - s->cs_base);
7619 gen_eob(s);
7620 break;
7621
7622 CASE_MODRM_MEM_OP(7):
7623 if (s->cpl != 0) {
7624 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7625 break;
7626 }
7627 gen_update_cc_op(s);
7628 gen_jmp_im(s, pc_start - s->cs_base);
7629 gen_lea_modrm(env, s, modrm);
7630 gen_helper_invlpg(cpu_env, s->A0);
7631 gen_jmp_im(s, s->pc - s->cs_base);
7632 gen_eob(s);
7633 break;
7634
7635 case 0xf8:
7636#ifdef TARGET_X86_64
7637 if (CODE64(s)) {
7638 if (s->cpl != 0) {
7639 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7640 } else {
7641 tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]);
7642 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7643 offsetof(CPUX86State, kernelgsbase));
7644 tcg_gen_st_tl(s->T0, cpu_env,
7645 offsetof(CPUX86State, kernelgsbase));
7646 }
7647 break;
7648 }
7649#endif
7650 goto illegal_op;
7651
7652 case 0xf9:
7653 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7654 goto illegal_op;
7655 }
7656 gen_update_cc_op(s);
7657 gen_jmp_im(s, pc_start - s->cs_base);
7658 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7659 gen_io_start();
7660 }
7661 gen_helper_rdtscp(cpu_env);
7662 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7663 gen_jmp(s, s->pc - s->cs_base);
7664 }
7665 break;
7666
7667 default:
7668 goto unknown_op;
7669 }
7670 break;
7671
7672 case 0x108:
7673 case 0x109:
7674 if (s->cpl != 0) {
7675 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7676 } else {
7677 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7678
7679 }
7680 break;
7681 case 0x63:
7682#ifdef TARGET_X86_64
7683 if (CODE64(s)) {
7684 int d_ot;
7685
7686 d_ot = dflag;
7687
7688 modrm = x86_ldub_code(env, s);
7689 reg = ((modrm >> 3) & 7) | rex_r;
7690 mod = (modrm >> 6) & 3;
7691 rm = (modrm & 7) | REX_B(s);
7692
7693 if (mod == 3) {
7694 gen_op_mov_v_reg(s, MO_32, s->T0, rm);
7695
7696 if (d_ot == MO_64) {
7697 tcg_gen_ext32s_tl(s->T0, s->T0);
7698 }
7699 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7700 } else {
7701 gen_lea_modrm(env, s, modrm);
7702 gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0);
7703 gen_op_mov_reg_v(s, d_ot, reg, s->T0);
7704 }
7705 } else
7706#endif
7707 {
7708 TCGLabel *label1;
7709 TCGv t0, t1, t2, a0;
7710
7711 if (!s->pe || s->vm86)
7712 goto illegal_op;
7713 t0 = tcg_temp_local_new();
7714 t1 = tcg_temp_local_new();
7715 t2 = tcg_temp_local_new();
7716 ot = MO_16;
7717 modrm = x86_ldub_code(env, s);
7718 reg = (modrm >> 3) & 7;
7719 mod = (modrm >> 6) & 3;
7720 rm = modrm & 7;
7721 if (mod != 3) {
7722 gen_lea_modrm(env, s, modrm);
7723 gen_op_ld_v(s, ot, t0, s->A0);
7724 a0 = tcg_temp_local_new();
7725 tcg_gen_mov_tl(a0, s->A0);
7726 } else {
7727 gen_op_mov_v_reg(s, ot, t0, rm);
7728 a0 = NULL;
7729 }
7730 gen_op_mov_v_reg(s, ot, t1, reg);
7731 tcg_gen_andi_tl(s->tmp0, t0, 3);
7732 tcg_gen_andi_tl(t1, t1, 3);
7733 tcg_gen_movi_tl(t2, 0);
7734 label1 = gen_new_label();
7735 tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1);
7736 tcg_gen_andi_tl(t0, t0, ~3);
7737 tcg_gen_or_tl(t0, t0, t1);
7738 tcg_gen_movi_tl(t2, CC_Z);
7739 gen_set_label(label1);
7740 if (mod != 3) {
7741 gen_op_st_v(s, ot, t0, a0);
7742 tcg_temp_free(a0);
7743 } else {
7744 gen_op_mov_reg_v(s, ot, rm, t0);
7745 }
7746 gen_compute_eflags(s);
7747 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7748 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7749 tcg_temp_free(t0);
7750 tcg_temp_free(t1);
7751 tcg_temp_free(t2);
7752 }
7753 break;
7754 case 0x102:
7755 case 0x103:
7756 {
7757 TCGLabel *label1;
7758 TCGv t0;
7759 if (!s->pe || s->vm86)
7760 goto illegal_op;
7761 ot = dflag != MO_16 ? MO_32 : MO_16;
7762 modrm = x86_ldub_code(env, s);
7763 reg = ((modrm >> 3) & 7) | rex_r;
7764 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
7765 t0 = tcg_temp_local_new();
7766 gen_update_cc_op(s);
7767 if (b == 0x102) {
7768 gen_helper_lar(t0, cpu_env, s->T0);
7769 } else {
7770 gen_helper_lsl(t0, cpu_env, s->T0);
7771 }
7772 tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z);
7773 label1 = gen_new_label();
7774 tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
7775 gen_op_mov_reg_v(s, ot, reg, t0);
7776 gen_set_label(label1);
7777 set_cc_op(s, CC_OP_EFLAGS);
7778 tcg_temp_free(t0);
7779 }
7780 break;
7781 case 0x118:
7782 modrm = x86_ldub_code(env, s);
7783 mod = (modrm >> 6) & 3;
7784 op = (modrm >> 3) & 7;
7785 switch(op) {
7786 case 0:
7787 case 1:
7788 case 2:
7789 case 3:
7790 if (mod == 3)
7791 goto illegal_op;
7792 gen_nop_modrm(env, s, modrm);
7793
7794 break;
7795 default:
7796 gen_nop_modrm(env, s, modrm);
7797 break;
7798 }
7799 break;
7800 case 0x11a:
7801 modrm = x86_ldub_code(env, s);
7802 if (s->flags & HF_MPX_EN_MASK) {
7803 mod = (modrm >> 6) & 3;
7804 reg = ((modrm >> 3) & 7) | rex_r;
7805 if (prefixes & PREFIX_REPZ) {
7806
7807 if (reg >= 4
7808 || (prefixes & PREFIX_LOCK)
7809 || s->aflag == MO_16) {
7810 goto illegal_op;
7811 }
7812 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7813 } else if (prefixes & PREFIX_REPNZ) {
7814
7815 if (reg >= 4
7816 || (prefixes & PREFIX_LOCK)
7817 || s->aflag == MO_16) {
7818 goto illegal_op;
7819 }
7820 TCGv_i64 notu = tcg_temp_new_i64();
7821 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7822 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7823 tcg_temp_free_i64(notu);
7824 } else if (prefixes & PREFIX_DATA) {
7825
7826 if (reg >= 4 || s->aflag == MO_16) {
7827 goto illegal_op;
7828 }
7829 if (mod == 3) {
7830 int reg2 = (modrm & 7) | REX_B(s);
7831 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7832 goto illegal_op;
7833 }
7834 if (s->flags & HF_MPX_IU_MASK) {
7835 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7836 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7837 }
7838 } else {
7839 gen_lea_modrm(env, s, modrm);
7840 if (CODE64(s)) {
7841 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7842 s->mem_index, MO_LEQ);
7843 tcg_gen_addi_tl(s->A0, s->A0, 8);
7844 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7845 s->mem_index, MO_LEQ);
7846 } else {
7847 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
7848 s->mem_index, MO_LEUL);
7849 tcg_gen_addi_tl(s->A0, s->A0, 4);
7850 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
7851 s->mem_index, MO_LEUL);
7852 }
7853
7854 gen_set_hflag(s, HF_MPX_IU_MASK);
7855 }
7856 } else if (mod != 3) {
7857
7858 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7859 if (reg >= 4
7860 || (prefixes & PREFIX_LOCK)
7861 || s->aflag == MO_16
7862 || a.base < -1) {
7863 goto illegal_op;
7864 }
7865 if (a.base >= 0) {
7866 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
7867 } else {
7868 tcg_gen_movi_tl(s->A0, 0);
7869 }
7870 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
7871 if (a.index >= 0) {
7872 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
7873 } else {
7874 tcg_gen_movi_tl(s->T0, 0);
7875 }
7876 if (CODE64(s)) {
7877 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0);
7878 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7879 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7880 } else {
7881 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0);
7882 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7883 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7884 }
7885 gen_set_hflag(s, HF_MPX_IU_MASK);
7886 }
7887 }
7888 gen_nop_modrm(env, s, modrm);
7889 break;
7890 case 0x11b:
7891 modrm = x86_ldub_code(env, s);
7892 if (s->flags & HF_MPX_EN_MASK) {
7893 mod = (modrm >> 6) & 3;
7894 reg = ((modrm >> 3) & 7) | rex_r;
7895 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7896
7897 if (reg >= 4
7898 || (prefixes & PREFIX_LOCK)
7899 || s->aflag == MO_16) {
7900 goto illegal_op;
7901 }
7902 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7903 if (a.base >= 0) {
7904 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7905 if (!CODE64(s)) {
7906 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7907 }
7908 } else if (a.base == -1) {
7909
7910 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7911 } else {
7912
7913 goto illegal_op;
7914 }
7915 tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a));
7916 if (!CODE64(s)) {
7917 tcg_gen_ext32u_tl(s->A0, s->A0);
7918 }
7919 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
7920
7921 gen_set_hflag(s, HF_MPX_IU_MASK);
7922 break;
7923 } else if (prefixes & PREFIX_REPNZ) {
7924
7925 if (reg >= 4
7926 || (prefixes & PREFIX_LOCK)
7927 || s->aflag == MO_16) {
7928 goto illegal_op;
7929 }
7930 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
7931 } else if (prefixes & PREFIX_DATA) {
7932
7933 if (reg >= 4 || s->aflag == MO_16) {
7934 goto illegal_op;
7935 }
7936 if (mod == 3) {
7937 int reg2 = (modrm & 7) | REX_B(s);
7938 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7939 goto illegal_op;
7940 }
7941 if (s->flags & HF_MPX_IU_MASK) {
7942 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7943 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7944 }
7945 } else {
7946 gen_lea_modrm(env, s, modrm);
7947 if (CODE64(s)) {
7948 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
7949 s->mem_index, MO_LEQ);
7950 tcg_gen_addi_tl(s->A0, s->A0, 8);
7951 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
7952 s->mem_index, MO_LEQ);
7953 } else {
7954 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
7955 s->mem_index, MO_LEUL);
7956 tcg_gen_addi_tl(s->A0, s->A0, 4);
7957 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
7958 s->mem_index, MO_LEUL);
7959 }
7960 }
7961 } else if (mod != 3) {
7962
7963 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7964 if (reg >= 4
7965 || (prefixes & PREFIX_LOCK)
7966 || s->aflag == MO_16
7967 || a.base < -1) {
7968 goto illegal_op;
7969 }
7970 if (a.base >= 0) {
7971 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
7972 } else {
7973 tcg_gen_movi_tl(s->A0, 0);
7974 }
7975 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
7976 if (a.index >= 0) {
7977 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
7978 } else {
7979 tcg_gen_movi_tl(s->T0, 0);
7980 }
7981 if (CODE64(s)) {
7982 gen_helper_bndstx64(cpu_env, s->A0, s->T0,
7983 cpu_bndl[reg], cpu_bndu[reg]);
7984 } else {
7985 gen_helper_bndstx32(cpu_env, s->A0, s->T0,
7986 cpu_bndl[reg], cpu_bndu[reg]);
7987 }
7988 }
7989 }
7990 gen_nop_modrm(env, s, modrm);
7991 break;
7992 case 0x119: case 0x11c ... 0x11f:
7993 modrm = x86_ldub_code(env, s);
7994 gen_nop_modrm(env, s, modrm);
7995 break;
7996 case 0x120:
7997 case 0x122:
7998 if (s->cpl != 0) {
7999 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8000 } else {
8001 modrm = x86_ldub_code(env, s);
8002
8003
8004
8005
8006
8007 rm = (modrm & 7) | REX_B(s);
8008 reg = ((modrm >> 3) & 7) | rex_r;
8009 if (CODE64(s))
8010 ot = MO_64;
8011 else
8012 ot = MO_32;
8013 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
8014 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
8015 reg = 8;
8016 }
8017 switch(reg) {
8018 case 0:
8019 case 2:
8020 case 3:
8021 case 4:
8022 case 8:
8023 gen_update_cc_op(s);
8024 gen_jmp_im(s, pc_start - s->cs_base);
8025 if (b & 2) {
8026 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8027 gen_io_start();
8028 }
8029 gen_op_mov_v_reg(s, ot, s->T0, rm);
8030 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
8031 s->T0);
8032 gen_jmp_im(s, s->pc - s->cs_base);
8033 gen_eob(s);
8034 } else {
8035 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8036 gen_io_start();
8037 }
8038 gen_helper_read_crN(s->T0, cpu_env, tcg_const_i32(reg));
8039 gen_op_mov_reg_v(s, ot, rm, s->T0);
8040 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8041 gen_io_end();
8042 }
8043 }
8044 break;
8045 default:
8046 goto unknown_op;
8047 }
8048 }
8049 break;
8050 case 0x121:
8051 case 0x123:
8052 if (s->cpl != 0) {
8053 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8054 } else {
8055 modrm = x86_ldub_code(env, s);
8056
8057
8058
8059
8060
8061 rm = (modrm & 7) | REX_B(s);
8062 reg = ((modrm >> 3) & 7) | rex_r;
8063 if (CODE64(s))
8064 ot = MO_64;
8065 else
8066 ot = MO_32;
8067 if (reg >= 8) {
8068 goto illegal_op;
8069 }
8070 if (b & 2) {
8071 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
8072 gen_op_mov_v_reg(s, ot, s->T0, rm);
8073 tcg_gen_movi_i32(s->tmp2_i32, reg);
8074 gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
8075 gen_jmp_im(s, s->pc - s->cs_base);
8076 gen_eob(s);
8077 } else {
8078 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
8079 tcg_gen_movi_i32(s->tmp2_i32, reg);
8080 gen_helper_get_dr(s->T0, cpu_env, s->tmp2_i32);
8081 gen_op_mov_reg_v(s, ot, rm, s->T0);
8082 }
8083 }
8084 break;
8085 case 0x106:
8086 if (s->cpl != 0) {
8087 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8088 } else {
8089 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
8090 gen_helper_clts(cpu_env);
8091
8092 gen_jmp_im(s, s->pc - s->cs_base);
8093 gen_eob(s);
8094 }
8095 break;
8096
8097 case 0x1c3:
8098 if (!(s->cpuid_features & CPUID_SSE2))
8099 goto illegal_op;
8100 ot = mo_64_32(dflag);
8101 modrm = x86_ldub_code(env, s);
8102 mod = (modrm >> 6) & 3;
8103 if (mod == 3)
8104 goto illegal_op;
8105 reg = ((modrm >> 3) & 7) | rex_r;
8106
8107 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
8108 break;
8109 case 0x1ae:
8110 modrm = x86_ldub_code(env, s);
8111 switch (modrm) {
8112 CASE_MODRM_MEM_OP(0):
8113 if (!(s->cpuid_features & CPUID_FXSR)
8114 || (prefixes & PREFIX_LOCK)) {
8115 goto illegal_op;
8116 }
8117 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8118 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8119 break;
8120 }
8121 gen_lea_modrm(env, s, modrm);
8122 gen_helper_fxsave(cpu_env, s->A0);
8123 break;
8124
8125 CASE_MODRM_MEM_OP(1):
8126 if (!(s->cpuid_features & CPUID_FXSR)
8127 || (prefixes & PREFIX_LOCK)) {
8128 goto illegal_op;
8129 }
8130 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
8131 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8132 break;
8133 }
8134 gen_lea_modrm(env, s, modrm);
8135 gen_helper_fxrstor(cpu_env, s->A0);
8136 break;
8137
8138 CASE_MODRM_MEM_OP(2):
8139 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8140 goto illegal_op;
8141 }
8142 if (s->flags & HF_TS_MASK) {
8143 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8144 break;
8145 }
8146 gen_lea_modrm(env, s, modrm);
8147 tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
8148 gen_helper_ldmxcsr(cpu_env, s->tmp2_i32);
8149 break;
8150
8151 CASE_MODRM_MEM_OP(3):
8152 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8153 goto illegal_op;
8154 }
8155 if (s->flags & HF_TS_MASK) {
8156 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8157 break;
8158 }
8159 gen_lea_modrm(env, s, modrm);
8160 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr));
8161 gen_op_st_v(s, MO_32, s->T0, s->A0);
8162 break;
8163
8164 CASE_MODRM_MEM_OP(4):
8165 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8166 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8167 | PREFIX_REPZ | PREFIX_REPNZ))) {
8168 goto illegal_op;
8169 }
8170 gen_lea_modrm(env, s, modrm);
8171 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8172 cpu_regs[R_EDX]);
8173 gen_helper_xsave(cpu_env, s->A0, s->tmp1_i64);
8174 break;
8175
8176 CASE_MODRM_MEM_OP(5):
8177 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8178 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8179 | PREFIX_REPZ | PREFIX_REPNZ))) {
8180 goto illegal_op;
8181 }
8182 gen_lea_modrm(env, s, modrm);
8183 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8184 cpu_regs[R_EDX]);
8185 gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64);
8186
8187
8188 gen_update_cc_op(s);
8189 gen_jmp_im(s, s->pc - s->cs_base);
8190 gen_eob(s);
8191 break;
8192
8193 CASE_MODRM_MEM_OP(6):
8194 if (prefixes & PREFIX_LOCK) {
8195 goto illegal_op;
8196 }
8197 if (prefixes & PREFIX_DATA) {
8198
8199 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
8200 goto illegal_op;
8201 }
8202 gen_nop_modrm(env, s, modrm);
8203 } else {
8204
8205 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8206 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8207 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8208 goto illegal_op;
8209 }
8210 gen_lea_modrm(env, s, modrm);
8211 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
8212 cpu_regs[R_EDX]);
8213 gen_helper_xsaveopt(cpu_env, s->A0, s->tmp1_i64);
8214 }
8215 break;
8216
8217 CASE_MODRM_MEM_OP(7):
8218 if (prefixes & PREFIX_LOCK) {
8219 goto illegal_op;
8220 }
8221 if (prefixes & PREFIX_DATA) {
8222
8223 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8224 goto illegal_op;
8225 }
8226 } else {
8227
8228 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8229 || !(s->cpuid_features & CPUID_CLFLUSH)) {
8230 goto illegal_op;
8231 }
8232 }
8233 gen_nop_modrm(env, s, modrm);
8234 break;
8235
8236 case 0xc0 ... 0xc7:
8237 case 0xc8 ... 0xcf:
8238 case 0xd0 ... 0xd7:
8239 case 0xd8 ... 0xdf:
8240 if (CODE64(s)
8241 && (prefixes & PREFIX_REPZ)
8242 && !(prefixes & PREFIX_LOCK)
8243 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8244 TCGv base, treg, src, dst;
8245
8246
8247 tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
8248 gen_helper_cr4_testbit(cpu_env, s->tmp2_i32);
8249
8250 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8251 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8252
8253 if (modrm & 0x10) {
8254
8255 dst = base, src = treg;
8256 } else {
8257
8258 dst = treg, src = base;
8259 }
8260
8261 if (s->dflag == MO_32) {
8262 tcg_gen_ext32u_tl(dst, src);
8263 } else {
8264 tcg_gen_mov_tl(dst, src);
8265 }
8266 break;
8267 }
8268 goto unknown_op;
8269
8270 case 0xf8:
8271 if (prefixes & PREFIX_DATA) {
8272
8273 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8274 || (prefixes & PREFIX_LOCK)) {
8275 goto illegal_op;
8276 }
8277 break;
8278 }
8279
8280 case 0xf9 ... 0xff:
8281 if (!(s->cpuid_features & CPUID_SSE)
8282 || (prefixes & PREFIX_LOCK)) {
8283 goto illegal_op;
8284 }
8285 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
8286 break;
8287 case 0xe8 ... 0xef:
8288 if (!(s->cpuid_features & CPUID_SSE)
8289 || (prefixes & PREFIX_LOCK)) {
8290 goto illegal_op;
8291 }
8292 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8293 break;
8294 case 0xf0 ... 0xf7:
8295 if (!(s->cpuid_features & CPUID_SSE2)
8296 || (prefixes & PREFIX_LOCK)) {
8297 goto illegal_op;
8298 }
8299 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8300 break;
8301
8302 default:
8303 goto unknown_op;
8304 }
8305 break;
8306
8307 case 0x10d:
8308 modrm = x86_ldub_code(env, s);
8309 mod = (modrm >> 6) & 3;
8310 if (mod == 3)
8311 goto illegal_op;
8312 gen_nop_modrm(env, s, modrm);
8313 break;
8314 case 0x1aa:
8315 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
8316 if (!(s->flags & HF_SMM_MASK))
8317 goto illegal_op;
8318 gen_update_cc_op(s);
8319 gen_jmp_im(s, s->pc - s->cs_base);
8320 gen_helper_rsm(cpu_env);
8321 gen_eob(s);
8322 break;
8323 case 0x1b8:
8324 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8325 PREFIX_REPZ)
8326 goto illegal_op;
8327 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8328 goto illegal_op;
8329
8330 modrm = x86_ldub_code(env, s);
8331 reg = ((modrm >> 3) & 7) | rex_r;
8332
8333 if (s->prefix & PREFIX_DATA) {
8334 ot = MO_16;
8335 } else {
8336 ot = mo_64_32(dflag);
8337 }
8338
8339 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
8340 gen_extu(ot, s->T0);
8341 tcg_gen_mov_tl(cpu_cc_src, s->T0);
8342 tcg_gen_ctpop_tl(s->T0, s->T0);
8343 gen_op_mov_reg_v(s, ot, reg, s->T0);
8344
8345 set_cc_op(s, CC_OP_POPCNT);
8346 break;
8347 case 0x10e ... 0x10f:
8348
8349 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
8350
8351 case 0x110 ... 0x117:
8352 case 0x128 ... 0x12f:
8353 case 0x138 ... 0x13a:
8354 case 0x150 ... 0x179:
8355 case 0x17c ... 0x17f:
8356 case 0x1c2:
8357 case 0x1c4 ... 0x1c6:
8358 case 0x1d0 ... 0x1fe:
8359 gen_sse(env, s, b, pc_start, rex_r);
8360 break;
8361 default:
8362 goto unknown_op;
8363 }
8364 return s->pc;
8365 illegal_op:
8366 gen_illegal_opcode(s);
8367 return s->pc;
8368 unknown_op:
8369 gen_unknown_opcode(env, s);
8370 return s->pc;
8371}
8372
8373void tcg_x86_init(void)
8374{
8375 static const char reg_names[CPU_NB_REGS][4] = {
8376#ifdef TARGET_X86_64
8377 [R_EAX] = "rax",
8378 [R_EBX] = "rbx",
8379 [R_ECX] = "rcx",
8380 [R_EDX] = "rdx",
8381 [R_ESI] = "rsi",
8382 [R_EDI] = "rdi",
8383 [R_EBP] = "rbp",
8384 [R_ESP] = "rsp",
8385 [8] = "r8",
8386 [9] = "r9",
8387 [10] = "r10",
8388 [11] = "r11",
8389 [12] = "r12",
8390 [13] = "r13",
8391 [14] = "r14",
8392 [15] = "r15",
8393#else
8394 [R_EAX] = "eax",
8395 [R_EBX] = "ebx",
8396 [R_ECX] = "ecx",
8397 [R_EDX] = "edx",
8398 [R_ESI] = "esi",
8399 [R_EDI] = "edi",
8400 [R_EBP] = "ebp",
8401 [R_ESP] = "esp",
8402#endif
8403 };
8404 static const char seg_base_names[6][8] = {
8405 [R_CS] = "cs_base",
8406 [R_DS] = "ds_base",
8407 [R_ES] = "es_base",
8408 [R_FS] = "fs_base",
8409 [R_GS] = "gs_base",
8410 [R_SS] = "ss_base",
8411 };
8412 static const char bnd_regl_names[4][8] = {
8413 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8414 };
8415 static const char bnd_regu_names[4][8] = {
8416 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8417 };
8418 int i;
8419
8420 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
8421 offsetof(CPUX86State, cc_op), "cc_op");
8422 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
8423 "cc_dst");
8424 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
8425 "cc_src");
8426 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
8427 "cc_src2");
8428
8429 for (i = 0; i < CPU_NB_REGS; ++i) {
8430 cpu_regs[i] = tcg_global_mem_new(cpu_env,
8431 offsetof(CPUX86State, regs[i]),
8432 reg_names[i]);
8433 }
8434
8435 for (i = 0; i < 6; ++i) {
8436 cpu_seg_base[i]
8437 = tcg_global_mem_new(cpu_env,
8438 offsetof(CPUX86State, segs[i].base),
8439 seg_base_names[i]);
8440 }
8441
8442 for (i = 0; i < 4; ++i) {
8443 cpu_bndl[i]
8444 = tcg_global_mem_new_i64(cpu_env,
8445 offsetof(CPUX86State, bnd_regs[i].lb),
8446 bnd_regl_names[i]);
8447 cpu_bndu[i]
8448 = tcg_global_mem_new_i64(cpu_env,
8449 offsetof(CPUX86State, bnd_regs[i].ub),
8450 bnd_regu_names[i]);
8451 }
8452}
8453
8454static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
8455{
8456 DisasContext *dc = container_of(dcbase, DisasContext, base);
8457 CPUX86State *env = cpu->env_ptr;
8458 uint32_t flags = dc->base.tb->flags;
8459 target_ulong cs_base = dc->base.tb->cs_base;
8460
8461 dc->pe = (flags >> HF_PE_SHIFT) & 1;
8462 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8463 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8464 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8465 dc->f_st = 0;
8466 dc->vm86 = (flags >> VM_SHIFT) & 1;
8467 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8468 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8469 dc->tf = (flags >> TF_SHIFT) & 1;
8470 dc->cc_op = CC_OP_DYNAMIC;
8471 dc->cc_op_dirty = false;
8472 dc->cs_base = cs_base;
8473 dc->popl_esp_hack = 0;
8474
8475 dc->mem_index = 0;
8476#ifdef CONFIG_SOFTMMU
8477 dc->mem_index = cpu_mmu_index(env, false);
8478#endif
8479 dc->cpuid_features = env->features[FEAT_1_EDX];
8480 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8481 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8482 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8483 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
8484 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
8485#ifdef TARGET_X86_64
8486 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8487 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8488#endif
8489 dc->flags = flags;
8490 dc->jmp_opt = !(dc->tf || dc->base.singlestep_enabled ||
8491 (flags & HF_INHIBIT_IRQ_MASK));
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502 dc->repz_opt = !dc->jmp_opt && !(tb_cflags(dc->base.tb) & CF_USE_ICOUNT);
8503#if 0
8504
8505 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8506 printf("ERROR addseg\n");
8507#endif
8508
8509 dc->T0 = tcg_temp_new();
8510 dc->T1 = tcg_temp_new();
8511 dc->A0 = tcg_temp_new();
8512
8513 dc->tmp0 = tcg_temp_new();
8514 dc->tmp1_i64 = tcg_temp_new_i64();
8515 dc->tmp2_i32 = tcg_temp_new_i32();
8516 dc->tmp3_i32 = tcg_temp_new_i32();
8517 dc->tmp4 = tcg_temp_new();
8518 dc->ptr0 = tcg_temp_new_ptr();
8519 dc->ptr1 = tcg_temp_new_ptr();
8520 dc->cc_srcT = tcg_temp_local_new();
8521}
8522
8523static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
8524{
8525}
8526
8527static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8528{
8529 DisasContext *dc = container_of(dcbase, DisasContext, base);
8530
8531 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
8532}
8533
8534static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8535 const CPUBreakpoint *bp)
8536{
8537 DisasContext *dc = container_of(dcbase, DisasContext, base);
8538
8539 int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
8540 if (bp->flags & flags) {
8541 gen_debug(dc, dc->base.pc_next - dc->cs_base);
8542 dc->base.is_jmp = DISAS_NORETURN;
8543
8544
8545
8546
8547 dc->base.pc_next += 1;
8548 return true;
8549 } else {
8550 return false;
8551 }
8552}
8553
8554static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8555{
8556 DisasContext *dc = container_of(dcbase, DisasContext, base);
8557 target_ulong pc_next = disas_insn(dc, cpu);
8558
8559 if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
8560
8561
8562
8563
8564
8565 dc->base.is_jmp = DISAS_TOO_MANY;
8566 } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
8567 && ((pc_next & TARGET_PAGE_MASK)
8568 != ((pc_next + TARGET_MAX_INSN_SIZE - 1)
8569 & TARGET_PAGE_MASK)
8570 || (pc_next & ~TARGET_PAGE_MASK) == 0)) {
8571
8572
8573
8574
8575
8576
8577 dc->base.is_jmp = DISAS_TOO_MANY;
8578 } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
8579 dc->base.is_jmp = DISAS_TOO_MANY;
8580 }
8581
8582 dc->base.pc_next = pc_next;
8583}
8584
8585static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8586{
8587 DisasContext *dc = container_of(dcbase, DisasContext, base);
8588
8589 if (dc->base.is_jmp == DISAS_TOO_MANY) {
8590 gen_jmp_im(dc, dc->base.pc_next - dc->cs_base);
8591 gen_eob(dc);
8592 }
8593}
8594
8595static void i386_tr_disas_log(const DisasContextBase *dcbase,
8596 CPUState *cpu)
8597{
8598 DisasContext *dc = container_of(dcbase, DisasContext, base);
8599
8600 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
8601 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
8602}
8603
8604static const TranslatorOps i386_tr_ops = {
8605 .init_disas_context = i386_tr_init_disas_context,
8606 .tb_start = i386_tr_tb_start,
8607 .insn_start = i386_tr_insn_start,
8608 .breakpoint_check = i386_tr_breakpoint_check,
8609 .translate_insn = i386_tr_translate_insn,
8610 .tb_stop = i386_tr_tb_stop,
8611 .disas_log = i386_tr_disas_log,
8612};
8613
8614
8615void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
8616{
8617 DisasContext dc;
8618
8619 translator_loop(&i386_tr_ops, &dc.base, cpu, tb, max_insns);
8620}
8621
8622void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8623 target_ulong *data)
8624{
8625 int cc_op = data[1];
8626 env->eip = data[0] - tb->cs_base;
8627 if (cc_op != CC_OP_DYNAMIC) {
8628 env->cc_op = cc_op;
8629 }
8630}
8631