Revision 9c605cb1 translate-i386.c
b/translate-i386.c | ||
---|---|---|
76 | 76 |
extern FILE *logfile; |
77 | 77 |
extern int loglevel; |
78 | 78 |
|
79 |
#define PREFIX_REPZ 1 |
|
80 |
#define PREFIX_REPNZ 2 |
|
81 |
#define PREFIX_LOCK 4 |
|
82 |
#define PREFIX_CS 8 |
|
83 |
#define PREFIX_SS 0x10 |
|
84 |
#define PREFIX_DS 0x20 |
|
85 |
#define PREFIX_ES 0x40 |
|
86 |
#define PREFIX_FS 0x80 |
|
87 |
#define PREFIX_GS 0x100 |
|
88 |
#define PREFIX_DATA 0x200 |
|
89 |
#define PREFIX_ADR 0x400 |
|
90 |
#define PREFIX_FWAIT 0x800 |
|
79 |
#define PREFIX_REPZ 0x01 |
|
80 |
#define PREFIX_REPNZ 0x02 |
|
81 |
#define PREFIX_LOCK 0x04 |
|
82 |
#define PREFIX_DATA 0x08 |
|
83 |
#define PREFIX_ADR 0x10 |
|
84 |
#define PREFIX_FWAIT 0x20 |
|
91 | 85 |
|
92 | 86 |
typedef struct DisasContext { |
93 | 87 |
/* current insn context */ |
88 |
int override; /* -1 if no override */ |
|
94 | 89 |
int prefix; |
95 | 90 |
int aflag, dflag; |
96 | 91 |
uint8_t *pc; /* pc = eip + cs_base */ |
... | ... | |
103 | 98 |
int cc_op; /* current CC operation */ |
104 | 99 |
int addseg; /* non zero if either DS/ES/SS have a non zero base */ |
105 | 100 |
int f_st; /* currently unused */ |
101 |
int vm86; /* vm86 mode */ |
|
106 | 102 |
} DisasContext; |
107 | 103 |
|
108 | 104 |
/* i386 arith/logic operations */ |
... | ... | |
130 | 126 |
}; |
131 | 127 |
|
132 | 128 |
enum { |
133 |
#define DEF(s) INDEX_op_ ## s, |
|
129 |
#define DEF(s, n) INDEX_op_ ## s,
|
|
134 | 130 |
#include "opc-i386.h" |
135 | 131 |
#undef DEF |
136 | 132 |
NB_OPS, |
... | ... | |
556 | 552 |
gen_op_stl_T0_A0, |
557 | 553 |
}; |
558 | 554 |
|
559 |
static GenOpFunc *gen_op_movs[6] = { |
|
560 |
gen_op_movsb, |
|
561 |
gen_op_movsw, |
|
562 |
gen_op_movsl, |
|
563 |
gen_op_rep_movsb, |
|
564 |
gen_op_rep_movsw, |
|
565 |
gen_op_rep_movsl, |
|
555 |
/* the _a32 and _a16 string operations use A0 as the base register. */ |
|
556 |
|
|
557 |
#define STRINGOP(x) \ |
|
558 |
gen_op_ ## x ## b_fast, \ |
|
559 |
gen_op_ ## x ## w_fast, \ |
|
560 |
gen_op_ ## x ## l_fast, \ |
|
561 |
gen_op_ ## x ## b_a32, \ |
|
562 |
gen_op_ ## x ## w_a32, \ |
|
563 |
gen_op_ ## x ## l_a32, \ |
|
564 |
gen_op_ ## x ## b_a16, \ |
|
565 |
gen_op_ ## x ## w_a16, \ |
|
566 |
gen_op_ ## x ## l_a16, |
|
567 |
|
|
568 |
static GenOpFunc *gen_op_movs[9 * 2] = { |
|
569 |
STRINGOP(movs) |
|
570 |
STRINGOP(rep_movs) |
|
566 | 571 |
}; |
567 | 572 |
|
568 |
static GenOpFunc *gen_op_stos[6] = { |
|
569 |
gen_op_stosb, |
|
570 |
gen_op_stosw, |
|
571 |
gen_op_stosl, |
|
572 |
gen_op_rep_stosb, |
|
573 |
gen_op_rep_stosw, |
|
574 |
gen_op_rep_stosl, |
|
573 |
static GenOpFunc *gen_op_stos[9 * 2] = { |
|
574 |
STRINGOP(stos) |
|
575 |
STRINGOP(rep_stos) |
|
575 | 576 |
}; |
576 | 577 |
|
577 |
static GenOpFunc *gen_op_lods[6] = { |
|
578 |
gen_op_lodsb, |
|
579 |
gen_op_lodsw, |
|
580 |
gen_op_lodsl, |
|
581 |
gen_op_rep_lodsb, |
|
582 |
gen_op_rep_lodsw, |
|
583 |
gen_op_rep_lodsl, |
|
578 |
static GenOpFunc *gen_op_lods[9 * 2] = { |
|
579 |
STRINGOP(lods) |
|
580 |
STRINGOP(rep_lods) |
|
584 | 581 |
}; |
585 | 582 |
|
586 |
static GenOpFunc *gen_op_scas[9] = { |
|
587 |
gen_op_scasb, |
|
588 |
gen_op_scasw, |
|
589 |
gen_op_scasl, |
|
590 |
gen_op_repz_scasb, |
|
591 |
gen_op_repz_scasw, |
|
592 |
gen_op_repz_scasl, |
|
593 |
gen_op_repnz_scasb, |
|
594 |
gen_op_repnz_scasw, |
|
595 |
gen_op_repnz_scasl, |
|
583 |
static GenOpFunc *gen_op_scas[9 * 3] = { |
|
584 |
STRINGOP(scas) |
|
585 |
STRINGOP(repz_scas) |
|
586 |
STRINGOP(repnz_scas) |
|
596 | 587 |
}; |
597 | 588 |
|
598 |
static GenOpFunc *gen_op_cmps[9] = { |
|
599 |
gen_op_cmpsb, |
|
600 |
gen_op_cmpsw, |
|
601 |
gen_op_cmpsl, |
|
602 |
gen_op_repz_cmpsb, |
|
603 |
gen_op_repz_cmpsw, |
|
604 |
gen_op_repz_cmpsl, |
|
605 |
gen_op_repnz_cmpsb, |
|
606 |
gen_op_repnz_cmpsw, |
|
607 |
gen_op_repnz_cmpsl, |
|
589 |
static GenOpFunc *gen_op_cmps[9 * 3] = { |
|
590 |
STRINGOP(cmps) |
|
591 |
STRINGOP(repz_cmps) |
|
592 |
STRINGOP(repnz_cmps) |
|
608 | 593 |
}; |
609 | 594 |
|
610 |
static GenOpFunc *gen_op_ins[6] = { |
|
611 |
gen_op_insb, |
|
612 |
gen_op_insw, |
|
613 |
gen_op_insl, |
|
614 |
gen_op_rep_insb, |
|
615 |
gen_op_rep_insw, |
|
616 |
gen_op_rep_insl, |
|
595 |
static GenOpFunc *gen_op_ins[9 * 2] = { |
|
596 |
STRINGOP(ins) |
|
597 |
STRINGOP(rep_ins) |
|
617 | 598 |
}; |
618 | 599 |
|
619 | 600 |
|
620 |
static GenOpFunc *gen_op_outs[6] = { |
|
621 |
gen_op_outsb, |
|
622 |
gen_op_outsw, |
|
623 |
gen_op_outsl, |
|
624 |
gen_op_rep_outsb, |
|
625 |
gen_op_rep_outsw, |
|
626 |
gen_op_rep_outsl, |
|
601 |
static GenOpFunc *gen_op_outs[9 * 2] = { |
|
602 |
STRINGOP(outs) |
|
603 |
STRINGOP(rep_outs) |
|
627 | 604 |
}; |
628 | 605 |
|
606 |
|
|
607 |
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func) |
|
608 |
{ |
|
609 |
int index, override; |
|
610 |
|
|
611 |
override = s->override; |
|
612 |
if (s->aflag) { |
|
613 |
/* 32 bit address */ |
|
614 |
if (s->addseg && override < 0) |
|
615 |
override = R_DS; |
|
616 |
if (override >= 0) { |
|
617 |
gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
|
618 |
index = 3 + ot; |
|
619 |
} else { |
|
620 |
index = ot; |
|
621 |
} |
|
622 |
} else { |
|
623 |
if (override < 0) |
|
624 |
override = R_DS; |
|
625 |
gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
|
626 |
/* 16 address, always override */ |
|
627 |
index = 6 + ot; |
|
628 |
} |
|
629 |
func[index](); |
|
630 |
} |
|
631 |
|
|
632 |
static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func) |
|
633 |
{ |
|
634 |
int index; |
|
635 |
|
|
636 |
if (s->aflag) { |
|
637 |
if (s->addseg) { |
|
638 |
index = 3 + ot; |
|
639 |
} else { |
|
640 |
index = ot; |
|
641 |
} |
|
642 |
} else { |
|
643 |
index = 6 + ot; |
|
644 |
} |
|
645 |
func[index](); |
|
646 |
} |
|
647 |
|
|
648 |
|
|
629 | 649 |
static GenOpFunc *gen_op_in[3] = { |
630 | 650 |
gen_op_inb_T0_T1, |
631 | 651 |
gen_op_inw_T0_T1, |
... | ... | |
849 | 869 |
int opreg; |
850 | 870 |
int mod, rm, code, override, must_add_seg; |
851 | 871 |
|
852 |
/* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */ |
|
853 |
override = -1; |
|
872 |
override = s->override; |
|
854 | 873 |
must_add_seg = s->addseg; |
855 |
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | |
|
856 |
PREFIX_ES | PREFIX_FS | PREFIX_GS)) { |
|
857 |
if (s->prefix & PREFIX_ES) |
|
858 |
override = R_ES; |
|
859 |
else if (s->prefix & PREFIX_CS) |
|
860 |
override = R_CS; |
|
861 |
else if (s->prefix & PREFIX_SS) |
|
862 |
override = R_SS; |
|
863 |
else if (s->prefix & PREFIX_DS) |
|
864 |
override = R_DS; |
|
865 |
else if (s->prefix & PREFIX_FS) |
|
866 |
override = R_FS; |
|
867 |
else |
|
868 |
override = R_GS; |
|
874 |
if (override >= 0) |
|
869 | 875 |
must_add_seg = 1; |
870 |
} |
|
871 |
|
|
872 | 876 |
mod = (modrm >> 6) & 3; |
873 | 877 |
rm = modrm & 7; |
874 | 878 |
|
... | ... | |
1343 | 1347 |
prefixes = 0; |
1344 | 1348 |
aflag = s->code32; |
1345 | 1349 |
dflag = s->code32; |
1346 |
// cur_pc = s->pc; /* for insn generation */
|
|
1350 |
s->override = -1;
|
|
1347 | 1351 |
next_byte: |
1348 | 1352 |
b = ldub(s->pc); |
1349 | 1353 |
s->pc++; |
... | ... | |
1359 | 1363 |
prefixes |= PREFIX_LOCK; |
1360 | 1364 |
goto next_byte; |
1361 | 1365 |
case 0x2e: |
1362 |
prefixes |= PREFIX_CS;
|
|
1366 |
s->override = R_CS;
|
|
1363 | 1367 |
goto next_byte; |
1364 | 1368 |
case 0x36: |
1365 |
prefixes |= PREFIX_SS;
|
|
1369 |
s->override = R_SS;
|
|
1366 | 1370 |
goto next_byte; |
1367 | 1371 |
case 0x3e: |
1368 |
prefixes |= PREFIX_DS;
|
|
1372 |
s->override = R_DS;
|
|
1369 | 1373 |
goto next_byte; |
1370 | 1374 |
case 0x26: |
1371 |
prefixes |= PREFIX_ES;
|
|
1375 |
s->override = R_ES;
|
|
1372 | 1376 |
goto next_byte; |
1373 | 1377 |
case 0x64: |
1374 |
prefixes |= PREFIX_FS;
|
|
1378 |
s->override = R_FS;
|
|
1375 | 1379 |
goto next_byte; |
1376 | 1380 |
case 0x65: |
1377 |
prefixes |= PREFIX_GS;
|
|
1381 |
s->override = R_GS;
|
|
1378 | 1382 |
goto next_byte; |
1379 | 1383 |
case 0x66: |
1380 | 1384 |
prefixes |= PREFIX_DATA; |
... | ... | |
1830 | 1834 |
} |
1831 | 1835 |
s->cc_op = CC_OP_SUBB + ot; |
1832 | 1836 |
break; |
1837 |
case 0x1c7: /* cmpxchg8b */ |
|
1838 |
modrm = ldub(s->pc++); |
|
1839 |
mod = (modrm >> 6) & 3; |
|
1840 |
if (mod == 3) |
|
1841 |
goto illegal_op; |
|
1842 |
if (s->cc_op != CC_OP_DYNAMIC) |
|
1843 |
gen_op_set_cc_op(s->cc_op); |
|
1844 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
1845 |
gen_op_cmpxchg8b(); |
|
1846 |
s->cc_op = CC_OP_EFLAGS; |
|
1847 |
break; |
|
1833 | 1848 |
|
1834 | 1849 |
/**************************/ |
1835 | 1850 |
/* push/pop */ |
... | ... | |
2027 | 2042 |
modrm = ldub(s->pc++); |
2028 | 2043 |
reg = (modrm >> 3) & 7; |
2029 | 2044 |
/* we must ensure that no segment is added */ |
2030 |
s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS | |
|
2031 |
PREFIX_ES | PREFIX_FS | PREFIX_GS); |
|
2045 |
s->override = -1; |
|
2032 | 2046 |
val = s->addseg; |
2033 | 2047 |
s->addseg = 0; |
2034 | 2048 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
... | ... | |
2050 | 2064 |
offset_addr = insn_get(s, OT_WORD); |
2051 | 2065 |
gen_op_movl_A0_im(offset_addr); |
2052 | 2066 |
/* handle override */ |
2053 |
/* XXX: factorize that */ |
|
2054 | 2067 |
{ |
2055 | 2068 |
int override, must_add_seg; |
2056 |
override = R_DS; |
|
2057 | 2069 |
must_add_seg = s->addseg; |
2058 |
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | |
|
2059 |
PREFIX_ES | PREFIX_FS | PREFIX_GS)) { |
|
2060 |
if (s->prefix & PREFIX_ES) |
|
2061 |
override = R_ES; |
|
2062 |
else if (s->prefix & PREFIX_CS) |
|
2063 |
override = R_CS; |
|
2064 |
else if (s->prefix & PREFIX_SS) |
|
2065 |
override = R_SS; |
|
2066 |
else if (s->prefix & PREFIX_DS) |
|
2067 |
override = R_DS; |
|
2068 |
else if (s->prefix & PREFIX_FS) |
|
2069 |
override = R_FS; |
|
2070 |
else |
|
2071 |
override = R_GS; |
|
2070 |
if (s->override >= 0) { |
|
2071 |
override = s->override; |
|
2072 | 2072 |
must_add_seg = 1; |
2073 |
} else { |
|
2074 |
override = R_DS; |
|
2073 | 2075 |
} |
2074 | 2076 |
if (must_add_seg) { |
2075 | 2077 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
... | ... | |
2084 | 2086 |
} |
2085 | 2087 |
break; |
2086 | 2088 |
case 0xd7: /* xlat */ |
2087 |
/* handle override */ |
|
2088 | 2089 |
gen_op_movl_A0_reg[R_EBX](); |
2089 | 2090 |
gen_op_addl_A0_AL(); |
2090 | 2091 |
if (s->aflag == 0) |
2091 | 2092 |
gen_op_andl_A0_ffff(); |
2092 |
/* XXX: factorize that */
|
|
2093 |
/* handle override */
|
|
2093 | 2094 |
{ |
2094 | 2095 |
int override, must_add_seg; |
2095 |
override = R_DS; |
|
2096 | 2096 |
must_add_seg = s->addseg; |
2097 |
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | |
|
2098 |
PREFIX_ES | PREFIX_FS | PREFIX_GS)) { |
|
2099 |
if (s->prefix & PREFIX_ES) |
|
2100 |
override = R_ES; |
|
2101 |
else if (s->prefix & PREFIX_CS) |
|
2102 |
override = R_CS; |
|
2103 |
else if (s->prefix & PREFIX_SS) |
|
2104 |
override = R_SS; |
|
2105 |
else if (s->prefix & PREFIX_DS) |
|
2106 |
override = R_DS; |
|
2107 |
else if (s->prefix & PREFIX_FS) |
|
2108 |
override = R_FS; |
|
2109 |
else |
|
2110 |
override = R_GS; |
|
2097 |
override = R_DS; |
|
2098 |
if (s->override >= 0) { |
|
2099 |
override = s->override; |
|
2111 | 2100 |
must_add_seg = 1; |
2101 |
} else { |
|
2102 |
override = R_DS; |
|
2112 | 2103 |
} |
2113 | 2104 |
if (must_add_seg) { |
2114 | 2105 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
... | ... | |
2185 | 2176 |
mod = (modrm >> 6) & 3; |
2186 | 2177 |
if (mod == 3) |
2187 | 2178 |
goto illegal_op; |
2179 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
2188 | 2180 |
gen_op_ld_T1_A0[ot](); |
2189 | 2181 |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
2190 | 2182 |
/* load the segment first to handle exceptions properly */ |
... | ... | |
2658 | 2650 |
break; |
2659 | 2651 |
/************************/ |
2660 | 2652 |
/* string ops */ |
2653 |
|
|
2661 | 2654 |
case 0xa4: /* movsS */ |
2662 | 2655 |
case 0xa5: |
2663 | 2656 |
if ((b & 1) == 0) |
2664 | 2657 |
ot = OT_BYTE; |
2665 | 2658 |
else |
2666 | 2659 |
ot = dflag ? OT_LONG : OT_WORD; |
2660 |
|
|
2667 | 2661 |
if (prefixes & PREFIX_REPZ) { |
2668 |
gen_op_movs[3 + ot]();
|
|
2662 |
gen_string_ds(s, ot, gen_op_movs + 9);
|
|
2669 | 2663 |
} else { |
2670 |
gen_op_movs[ot]();
|
|
2664 |
gen_string_ds(s, ot, gen_op_movs);
|
|
2671 | 2665 |
} |
2672 | 2666 |
break; |
2673 | 2667 |
|
... | ... | |
2677 | 2671 |
ot = OT_BYTE; |
2678 | 2672 |
else |
2679 | 2673 |
ot = dflag ? OT_LONG : OT_WORD; |
2674 |
|
|
2680 | 2675 |
if (prefixes & PREFIX_REPZ) { |
2681 |
gen_op_stos[3 + ot]();
|
|
2676 |
gen_string_es(s, ot, gen_op_stos + 9);
|
|
2682 | 2677 |
} else { |
2683 |
gen_op_stos[ot]();
|
|
2678 |
gen_string_es(s, ot, gen_op_stos);
|
|
2684 | 2679 |
} |
2685 | 2680 |
break; |
2686 | 2681 |
case 0xac: /* lodsS */ |
... | ... | |
2690 | 2685 |
else |
2691 | 2686 |
ot = dflag ? OT_LONG : OT_WORD; |
2692 | 2687 |
if (prefixes & PREFIX_REPZ) { |
2693 |
gen_op_lods[3 + ot]();
|
|
2688 |
gen_string_ds(s, ot, gen_op_lods + 9);
|
|
2694 | 2689 |
} else { |
2695 |
gen_op_lods[ot]();
|
|
2690 |
gen_string_ds(s, ot, gen_op_lods);
|
|
2696 | 2691 |
} |
2697 | 2692 |
break; |
2698 | 2693 |
case 0xae: /* scasS */ |
... | ... | |
2700 | 2695 |
if ((b & 1) == 0) |
2701 | 2696 |
ot = OT_BYTE; |
2702 | 2697 |
else |
2703 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2698 |
ot = dflag ? OT_LONG : OT_WORD;
|
|
2704 | 2699 |
if (prefixes & PREFIX_REPNZ) { |
2705 | 2700 |
if (s->cc_op != CC_OP_DYNAMIC) |
2706 | 2701 |
gen_op_set_cc_op(s->cc_op); |
2707 |
gen_op_scas[6 + ot]();
|
|
2702 |
gen_string_es(s, ot, gen_op_scas + 9 * 2);
|
|
2708 | 2703 |
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
2709 | 2704 |
} else if (prefixes & PREFIX_REPZ) { |
2710 | 2705 |
if (s->cc_op != CC_OP_DYNAMIC) |
2711 | 2706 |
gen_op_set_cc_op(s->cc_op); |
2712 |
gen_op_scas[3 + ot]();
|
|
2707 |
gen_string_es(s, ot, gen_op_scas + 9);
|
|
2713 | 2708 |
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
2714 | 2709 |
} else { |
2715 |
gen_op_scas[ot]();
|
|
2710 |
gen_string_es(s, ot, gen_op_scas);
|
|
2716 | 2711 |
s->cc_op = CC_OP_SUBB + ot; |
2717 | 2712 |
} |
2718 | 2713 |
break; |
... | ... | |
2726 | 2721 |
if (prefixes & PREFIX_REPNZ) { |
2727 | 2722 |
if (s->cc_op != CC_OP_DYNAMIC) |
2728 | 2723 |
gen_op_set_cc_op(s->cc_op); |
2729 |
gen_op_cmps[6 + ot]();
|
|
2724 |
gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
|
|
2730 | 2725 |
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
2731 | 2726 |
} else if (prefixes & PREFIX_REPZ) { |
2732 | 2727 |
if (s->cc_op != CC_OP_DYNAMIC) |
2733 | 2728 |
gen_op_set_cc_op(s->cc_op); |
2734 |
gen_op_cmps[3 + ot]();
|
|
2729 |
gen_string_ds(s, ot, gen_op_cmps + 9);
|
|
2735 | 2730 |
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
2736 | 2731 |
} else { |
2737 |
gen_op_cmps[ot]();
|
|
2732 |
gen_string_ds(s, ot, gen_op_cmps);
|
|
2738 | 2733 |
s->cc_op = CC_OP_SUBB + ot; |
2739 | 2734 |
} |
2740 | 2735 |
break; |
2741 |
|
|
2742 |
/************************/ |
|
2743 |
/* port I/O */ |
|
2744 | 2736 |
case 0x6c: /* insS */ |
2745 | 2737 |
case 0x6d: |
2746 | 2738 |
if ((b & 1) == 0) |
... | ... | |
2748 | 2740 |
else |
2749 | 2741 |
ot = dflag ? OT_LONG : OT_WORD; |
2750 | 2742 |
if (prefixes & PREFIX_REPZ) { |
2751 |
gen_op_ins[3 + ot]();
|
|
2743 |
gen_string_es(s, ot, gen_op_ins + 9);
|
|
2752 | 2744 |
} else { |
2753 |
gen_op_ins[ot]();
|
|
2745 |
gen_string_es(s, ot, gen_op_ins);
|
|
2754 | 2746 |
} |
2755 | 2747 |
break; |
2756 | 2748 |
case 0x6e: /* outsS */ |
... | ... | |
2760 | 2752 |
else |
2761 | 2753 |
ot = dflag ? OT_LONG : OT_WORD; |
2762 | 2754 |
if (prefixes & PREFIX_REPZ) { |
2763 |
gen_op_outs[3 + ot]();
|
|
2755 |
gen_string_ds(s, ot, gen_op_outs + 9);
|
|
2764 | 2756 |
} else { |
2765 |
gen_op_outs[ot]();
|
|
2757 |
gen_string_ds(s, ot, gen_op_outs);
|
|
2766 | 2758 |
} |
2767 | 2759 |
break; |
2760 |
|
|
2761 |
/************************/ |
|
2762 |
/* port I/O */ |
|
2768 | 2763 |
case 0xe4: |
2769 | 2764 |
case 0xe5: |
2770 | 2765 |
if ((b & 1) == 0) |
... | ... | |
3150 | 3145 |
case 0xcd: /* int N */ |
3151 | 3146 |
val = ldub(s->pc++); |
3152 | 3147 |
/* XXX: currently we ignore the interrupt number */ |
3153 |
gen_op_int_im((long)pc_start);
|
|
3148 |
gen_op_int_im(pc_start - s->cs_base);
|
|
3154 | 3149 |
s->is_jmp = 1; |
3155 | 3150 |
break; |
3156 | 3151 |
case 0xce: /* into */ |
3157 | 3152 |
if (s->cc_op != CC_OP_DYNAMIC) |
3158 | 3153 |
gen_op_set_cc_op(s->cc_op); |
3159 |
gen_op_into((long)pc_start, (long)s->pc); |
|
3160 |
s->is_jmp = 1; |
|
3154 |
gen_op_into(); |
|
3155 |
break; |
|
3156 |
case 0x62: /* bound */ |
|
3157 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3158 |
modrm = ldub(s->pc++); |
|
3159 |
reg = (modrm >> 3) & 7; |
|
3160 |
mod = (modrm >> 6) & 3; |
|
3161 |
if (mod == 3) |
|
3162 |
goto illegal_op; |
|
3163 |
gen_op_mov_reg_T0[ot][reg](); |
|
3164 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3165 |
if (ot == OT_WORD) |
|
3166 |
gen_op_boundw(); |
|
3167 |
else |
|
3168 |
gen_op_boundl(); |
|
3161 | 3169 |
break; |
3162 | 3170 |
case 0x1c8 ... 0x1cf: /* bswap reg */ |
3163 | 3171 |
reg = b & 7; |
... | ... | |
3188 | 3196 |
case 0x131: /* rdtsc */ |
3189 | 3197 |
gen_op_rdtsc(); |
3190 | 3198 |
break; |
3191 |
#if 0 |
|
3192 | 3199 |
case 0x1a2: /* cpuid */ |
3193 |
gen_insn0(OP_ASM);
|
|
3200 |
gen_op_cpuid();
|
|
3194 | 3201 |
break; |
3195 |
#endif |
|
3196 | 3202 |
default: |
3197 | 3203 |
goto illegal_op; |
3198 | 3204 |
} |
... | ... | |
3399 | 3405 |
[INDEX_op_bsrw_T0_cc] = CC_OSZAPC, |
3400 | 3406 |
[INDEX_op_bsrl_T0_cc] = CC_OSZAPC, |
3401 | 3407 |
|
3402 |
[INDEX_op_scasb] = CC_OSZAPC,
|
|
3403 |
[INDEX_op_scasw] = CC_OSZAPC,
|
|
3404 |
[INDEX_op_scasl] = CC_OSZAPC,
|
|
3405 |
[INDEX_op_repz_scasb] = CC_OSZAPC,
|
|
3406 |
[INDEX_op_repz_scasw] = CC_OSZAPC,
|
|
3407 |
[INDEX_op_repz_scasl] = CC_OSZAPC,
|
|
3408 |
[INDEX_op_repnz_scasb] = CC_OSZAPC,
|
|
3409 |
[INDEX_op_repnz_scasw] = CC_OSZAPC,
|
|
3410 |
[INDEX_op_repnz_scasl] = CC_OSZAPC,
|
|
3411 |
|
|
3412 |
[INDEX_op_cmpsb] = CC_OSZAPC,
|
|
3413 |
[INDEX_op_cmpsw] = CC_OSZAPC, |
|
3414 |
[INDEX_op_cmpsl] = CC_OSZAPC,
|
|
3415 |
[INDEX_op_repz_cmpsb] = CC_OSZAPC,
|
|
3416 |
[INDEX_op_repz_cmpsw] = CC_OSZAPC,
|
|
3417 |
[INDEX_op_repz_cmpsl] = CC_OSZAPC,
|
|
3418 |
[INDEX_op_repnz_cmpsb] = CC_OSZAPC,
|
|
3419 |
[INDEX_op_repnz_cmpsw] = CC_OSZAPC,
|
|
3420 |
[INDEX_op_repnz_cmpsl] = CC_OSZAPC, |
|
3421 |
|
|
3408 |
#undef STRINGOP
|
|
3409 |
#define STRINGOP(x) \
|
|
3410 |
[INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
|
|
3411 |
[INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
|
|
3412 |
[INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
|
|
3413 |
[INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
|
|
3414 |
[INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
|
|
3415 |
[INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
|
|
3416 |
[INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
|
|
3417 |
[INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \ |
|
3418 |
[INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
|
|
3419 |
|
|
3420 |
STRINGOP(scas)
|
|
3421 |
STRINGOP(repz_scas)
|
|
3422 |
STRINGOP(repnz_scas)
|
|
3423 |
STRINGOP(cmps)
|
|
3424 |
STRINGOP(repz_cmps)
|
|
3425 |
STRINGOP(repnz_cmps)
|
|
3426 |
|
|
3427 |
[INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC, |
|
3422 | 3428 |
[INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC, |
3423 | 3429 |
[INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC, |
3430 |
|
|
3431 |
[INDEX_op_cmpxchg8b] = CC_Z, |
|
3424 | 3432 |
}; |
3425 | 3433 |
|
3426 | 3434 |
/* simpler form of an operation if no flags need to be generated */ |
... | ... | |
3495 | 3503 |
|
3496 | 3504 |
#ifdef DEBUG_DISAS |
3497 | 3505 |
static const char *op_str[] = { |
3498 |
#define DEF(s) #s, |
|
3506 |
#define DEF(s, n) #s, |
|
3507 |
#include "opc-i386.h" |
|
3508 |
#undef DEF |
|
3509 |
}; |
|
3510 |
|
|
3511 |
static uint8_t op_nb_args[] = { |
|
3512 |
#define DEF(s, n) n, |
|
3499 | 3513 |
#include "opc-i386.h" |
3500 | 3514 |
#undef DEF |
3501 | 3515 |
}; |
3502 | 3516 |
|
3503 |
static void dump_ops(const uint16_t *opc_buf) |
|
3517 |
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
|
|
3504 | 3518 |
{ |
3505 | 3519 |
const uint16_t *opc_ptr; |
3506 |
int c; |
|
3520 |
const uint32_t *opparam_ptr; |
|
3521 |
int c, n, i; |
|
3522 |
|
|
3507 | 3523 |
opc_ptr = opc_buf; |
3524 |
opparam_ptr = opparam_buf; |
|
3508 | 3525 |
for(;;) { |
3509 | 3526 |
c = *opc_ptr++; |
3510 |
fprintf(logfile, "0x%04x: %s\n", opc_ptr - opc_buf - 1, op_str[c]); |
|
3527 |
n = op_nb_args[c]; |
|
3528 |
fprintf(logfile, "0x%04x: %s", opc_ptr - opc_buf - 1, op_str[c]); |
|
3529 |
for(i = 0; i < n; i++) { |
|
3530 |
fprintf(logfile, " 0x%x", opparam_ptr[i]); |
|
3531 |
} |
|
3532 |
fprintf(logfile, "\n"); |
|
3511 | 3533 |
if (c == INDEX_op_end) |
3512 | 3534 |
break; |
3535 |
opparam_ptr += n; |
|
3513 | 3536 |
} |
3514 | 3537 |
} |
3515 | 3538 |
|
... | ... | |
3547 | 3570 |
dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; |
3548 | 3571 |
dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
3549 | 3572 |
dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
3573 |
dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
|
3550 | 3574 |
dc->cc_op = CC_OP_DYNAMIC; |
3551 | 3575 |
dc->cs_base = cs_base; |
3552 | 3576 |
|
... | ... | |
3610 | 3634 |
fprintf(logfile, "\n"); |
3611 | 3635 |
|
3612 | 3636 |
fprintf(logfile, "OP:\n"); |
3613 |
dump_ops(gen_opc_buf); |
|
3637 |
dump_ops(gen_opc_buf, gen_opparam_buf);
|
|
3614 | 3638 |
fprintf(logfile, "\n"); |
3615 | 3639 |
} |
3616 | 3640 |
#endif |
... | ... | |
3621 | 3645 |
#ifdef DEBUG_DISAS |
3622 | 3646 |
if (loglevel) { |
3623 | 3647 |
fprintf(logfile, "AFTER FLAGS OPT:\n"); |
3624 |
dump_ops(gen_opc_buf); |
|
3648 |
dump_ops(gen_opc_buf, gen_opparam_buf);
|
|
3625 | 3649 |
fprintf(logfile, "\n"); |
3626 | 3650 |
} |
3627 | 3651 |
#endif |
... | ... | |
3683 | 3707 |
for(i = 0;i < 8; i++) |
3684 | 3708 |
env->fptags[i] = 1; |
3685 | 3709 |
env->fpuc = 0x37f; |
3686 |
/* flags setup */ |
|
3687 |
env->eflags = 0; |
|
3710 |
/* flags setup : we activate the IRQs by default as in user mode */
|
|
3711 |
env->eflags = 0x2 | IF_MASK;
|
|
3688 | 3712 |
|
3689 | 3713 |
/* init various static tables */ |
3690 | 3714 |
if (!inited) { |
Also available in: Unified diff