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