Commit 9c605cb13547a5faa5cb1092e3e44ac8b0d0b841
1 parent
24f9e90b
added cmpxchg8b, cpuid, bound, eflags support, vm86 mode, 16bit/override string ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@55 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
206 additions
and
182 deletions
translate-i386.c
... | ... | @@ -76,21 +76,16 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop) |
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,6 +98,7 @@ typedef struct DisasContext { |
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,7 +126,7 @@ enum { |
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,76 +552,100 @@ static GenOpFunc *gen_op_st_T0_A0[3] = { |
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,26 +869,10 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
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,7 +1347,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,22 +1363,22 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,6 +1834,17 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,8 +2042,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,26 +2064,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,31 +2086,20 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,6 +2176,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,16 +2650,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,10 +2671,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,9 +2685,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,19 +2695,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,21 +2721,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,9 +2740,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,11 +2752,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,14 +3145,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,11 +3196,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
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,28 +3405,30 @@ static uint16_t opc_write_flags[NB_OPS] = { |
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,21 +3503,36 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) |
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,6 +3570,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, |
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,7 +3634,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, |
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,7 +3645,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, |
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,8 +3707,8 @@ CPUX86State *cpu_x86_init(void) |
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) { | ... | ... |