Commit 9c605cb13547a5faa5cb1092e3e44ac8b0d0b841

Authored by bellard
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,21 +76,16 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop)
76 extern FILE *logfile; 76 extern FILE *logfile;
77 extern int loglevel; 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 typedef struct DisasContext { 86 typedef struct DisasContext {
93 /* current insn context */ 87 /* current insn context */
  88 + int override; /* -1 if no override */
94 int prefix; 89 int prefix;
95 int aflag, dflag; 90 int aflag, dflag;
96 uint8_t *pc; /* pc = eip + cs_base */ 91 uint8_t *pc; /* pc = eip + cs_base */
@@ -103,6 +98,7 @@ typedef struct DisasContext { @@ -103,6 +98,7 @@ typedef struct DisasContext {
103 int cc_op; /* current CC operation */ 98 int cc_op; /* current CC operation */
104 int addseg; /* non zero if either DS/ES/SS have a non zero base */ 99 int addseg; /* non zero if either DS/ES/SS have a non zero base */
105 int f_st; /* currently unused */ 100 int f_st; /* currently unused */
  101 + int vm86; /* vm86 mode */
106 } DisasContext; 102 } DisasContext;
107 103
108 /* i386 arith/logic operations */ 104 /* i386 arith/logic operations */
@@ -130,7 +126,7 @@ enum { @@ -130,7 +126,7 @@ enum {
130 }; 126 };
131 127
132 enum { 128 enum {
133 -#define DEF(s) INDEX_op_ ## s, 129 +#define DEF(s, n) INDEX_op_ ## s,
134 #include "opc-i386.h" 130 #include "opc-i386.h"
135 #undef DEF 131 #undef DEF
136 NB_OPS, 132 NB_OPS,
@@ -556,76 +552,100 @@ static GenOpFunc *gen_op_st_T0_A0[3] = { @@ -556,76 +552,100 @@ static GenOpFunc *gen_op_st_T0_A0[3] = {
556 gen_op_stl_T0_A0, 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 static GenOpFunc *gen_op_in[3] = { 649 static GenOpFunc *gen_op_in[3] = {
630 gen_op_inb_T0_T1, 650 gen_op_inb_T0_T1,
631 gen_op_inw_T0_T1, 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,26 +869,10 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
849 int opreg; 869 int opreg;
850 int mod, rm, code, override, must_add_seg; 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 must_add_seg = s->addseg; 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 must_add_seg = 1; 875 must_add_seg = 1;
870 - }  
871 -  
872 mod = (modrm >> 6) & 3; 876 mod = (modrm >> 6) & 3;
873 rm = modrm & 7; 877 rm = modrm & 7;
874 878
@@ -1343,7 +1347,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1343,7 +1347,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1343 prefixes = 0; 1347 prefixes = 0;
1344 aflag = s->code32; 1348 aflag = s->code32;
1345 dflag = s->code32; 1349 dflag = s->code32;
1346 - // cur_pc = s->pc; /* for insn generation */ 1350 + s->override = -1;
1347 next_byte: 1351 next_byte:
1348 b = ldub(s->pc); 1352 b = ldub(s->pc);
1349 s->pc++; 1353 s->pc++;
@@ -1359,22 +1363,22 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1359,22 +1363,22 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1359 prefixes |= PREFIX_LOCK; 1363 prefixes |= PREFIX_LOCK;
1360 goto next_byte; 1364 goto next_byte;
1361 case 0x2e: 1365 case 0x2e:
1362 - prefixes |= PREFIX_CS; 1366 + s->override = R_CS;
1363 goto next_byte; 1367 goto next_byte;
1364 case 0x36: 1368 case 0x36:
1365 - prefixes |= PREFIX_SS; 1369 + s->override = R_SS;
1366 goto next_byte; 1370 goto next_byte;
1367 case 0x3e: 1371 case 0x3e:
1368 - prefixes |= PREFIX_DS; 1372 + s->override = R_DS;
1369 goto next_byte; 1373 goto next_byte;
1370 case 0x26: 1374 case 0x26:
1371 - prefixes |= PREFIX_ES; 1375 + s->override = R_ES;
1372 goto next_byte; 1376 goto next_byte;
1373 case 0x64: 1377 case 0x64:
1374 - prefixes |= PREFIX_FS; 1378 + s->override = R_FS;
1375 goto next_byte; 1379 goto next_byte;
1376 case 0x65: 1380 case 0x65:
1377 - prefixes |= PREFIX_GS; 1381 + s->override = R_GS;
1378 goto next_byte; 1382 goto next_byte;
1379 case 0x66: 1383 case 0x66:
1380 prefixes |= PREFIX_DATA; 1384 prefixes |= PREFIX_DATA;
@@ -1830,6 +1834,17 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1830,6 +1834,17 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1830 } 1834 }
1831 s->cc_op = CC_OP_SUBB + ot; 1835 s->cc_op = CC_OP_SUBB + ot;
1832 break; 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, &reg_addr, &offset_addr);
  1845 + gen_op_cmpxchg8b();
  1846 + s->cc_op = CC_OP_EFLAGS;
  1847 + break;
1833 1848
1834 /**************************/ 1849 /**************************/
1835 /* push/pop */ 1850 /* push/pop */
@@ -2027,8 +2042,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2027,8 +2042,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2027 modrm = ldub(s->pc++); 2042 modrm = ldub(s->pc++);
2028 reg = (modrm >> 3) & 7; 2043 reg = (modrm >> 3) & 7;
2029 /* we must ensure that no segment is added */ 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 val = s->addseg; 2046 val = s->addseg;
2033 s->addseg = 0; 2047 s->addseg = 0;
2034 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); 2048 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
@@ -2050,26 +2064,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2050,26 +2064,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2050 offset_addr = insn_get(s, OT_WORD); 2064 offset_addr = insn_get(s, OT_WORD);
2051 gen_op_movl_A0_im(offset_addr); 2065 gen_op_movl_A0_im(offset_addr);
2052 /* handle override */ 2066 /* handle override */
2053 - /* XXX: factorize that */  
2054 { 2067 {
2055 int override, must_add_seg; 2068 int override, must_add_seg;
2056 - override = R_DS;  
2057 must_add_seg = s->addseg; 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 must_add_seg = 1; 2072 must_add_seg = 1;
  2073 + } else {
  2074 + override = R_DS;
2073 } 2075 }
2074 if (must_add_seg) { 2076 if (must_add_seg) {
2075 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); 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,31 +2086,20 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2084 } 2086 }
2085 break; 2087 break;
2086 case 0xd7: /* xlat */ 2088 case 0xd7: /* xlat */
2087 - /* handle override */  
2088 gen_op_movl_A0_reg[R_EBX](); 2089 gen_op_movl_A0_reg[R_EBX]();
2089 gen_op_addl_A0_AL(); 2090 gen_op_addl_A0_AL();
2090 if (s->aflag == 0) 2091 if (s->aflag == 0)
2091 gen_op_andl_A0_ffff(); 2092 gen_op_andl_A0_ffff();
2092 - /* XXX: factorize that */ 2093 + /* handle override */
2093 { 2094 {
2094 int override, must_add_seg; 2095 int override, must_add_seg;
2095 - override = R_DS;  
2096 must_add_seg = s->addseg; 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 must_add_seg = 1; 2100 must_add_seg = 1;
  2101 + } else {
  2102 + override = R_DS;
2112 } 2103 }
2113 if (must_add_seg) { 2104 if (must_add_seg) {
2114 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); 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,6 +2176,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2185 mod = (modrm >> 6) & 3; 2176 mod = (modrm >> 6) & 3;
2186 if (mod == 3) 2177 if (mod == 3)
2187 goto illegal_op; 2178 goto illegal_op;
  2179 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2188 gen_op_ld_T1_A0[ot](); 2180 gen_op_ld_T1_A0[ot]();
2189 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); 2181 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2190 /* load the segment first to handle exceptions properly */ 2182 /* load the segment first to handle exceptions properly */
@@ -2658,16 +2650,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2658,16 +2650,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2658 break; 2650 break;
2659 /************************/ 2651 /************************/
2660 /* string ops */ 2652 /* string ops */
  2653 +
2661 case 0xa4: /* movsS */ 2654 case 0xa4: /* movsS */
2662 case 0xa5: 2655 case 0xa5:
2663 if ((b & 1) == 0) 2656 if ((b & 1) == 0)
2664 ot = OT_BYTE; 2657 ot = OT_BYTE;
2665 else 2658 else
2666 ot = dflag ? OT_LONG : OT_WORD; 2659 ot = dflag ? OT_LONG : OT_WORD;
  2660 +
2667 if (prefixes & PREFIX_REPZ) { 2661 if (prefixes & PREFIX_REPZ) {
2668 - gen_op_movs[3 + ot](); 2662 + gen_string_ds(s, ot, gen_op_movs + 9);
2669 } else { 2663 } else {
2670 - gen_op_movs[ot](); 2664 + gen_string_ds(s, ot, gen_op_movs);
2671 } 2665 }
2672 break; 2666 break;
2673 2667
@@ -2677,10 +2671,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2677,10 +2671,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2677 ot = OT_BYTE; 2671 ot = OT_BYTE;
2678 else 2672 else
2679 ot = dflag ? OT_LONG : OT_WORD; 2673 ot = dflag ? OT_LONG : OT_WORD;
  2674 +
2680 if (prefixes & PREFIX_REPZ) { 2675 if (prefixes & PREFIX_REPZ) {
2681 - gen_op_stos[3 + ot](); 2676 + gen_string_es(s, ot, gen_op_stos + 9);
2682 } else { 2677 } else {
2683 - gen_op_stos[ot](); 2678 + gen_string_es(s, ot, gen_op_stos);
2684 } 2679 }
2685 break; 2680 break;
2686 case 0xac: /* lodsS */ 2681 case 0xac: /* lodsS */
@@ -2690,9 +2685,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2690,9 +2685,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2690 else 2685 else
2691 ot = dflag ? OT_LONG : OT_WORD; 2686 ot = dflag ? OT_LONG : OT_WORD;
2692 if (prefixes & PREFIX_REPZ) { 2687 if (prefixes & PREFIX_REPZ) {
2693 - gen_op_lods[3 + ot](); 2688 + gen_string_ds(s, ot, gen_op_lods + 9);
2694 } else { 2689 } else {
2695 - gen_op_lods[ot](); 2690 + gen_string_ds(s, ot, gen_op_lods);
2696 } 2691 }
2697 break; 2692 break;
2698 case 0xae: /* scasS */ 2693 case 0xae: /* scasS */
@@ -2700,19 +2695,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2700,19 +2695,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2700 if ((b & 1) == 0) 2695 if ((b & 1) == 0)
2701 ot = OT_BYTE; 2696 ot = OT_BYTE;
2702 else 2697 else
2703 - ot = dflag ? OT_LONG : OT_WORD; 2698 + ot = dflag ? OT_LONG : OT_WORD;
2704 if (prefixes & PREFIX_REPNZ) { 2699 if (prefixes & PREFIX_REPNZ) {
2705 if (s->cc_op != CC_OP_DYNAMIC) 2700 if (s->cc_op != CC_OP_DYNAMIC)
2706 gen_op_set_cc_op(s->cc_op); 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 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 2703 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2709 } else if (prefixes & PREFIX_REPZ) { 2704 } else if (prefixes & PREFIX_REPZ) {
2710 if (s->cc_op != CC_OP_DYNAMIC) 2705 if (s->cc_op != CC_OP_DYNAMIC)
2711 gen_op_set_cc_op(s->cc_op); 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 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 2708 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2714 } else { 2709 } else {
2715 - gen_op_scas[ot](); 2710 + gen_string_es(s, ot, gen_op_scas);
2716 s->cc_op = CC_OP_SUBB + ot; 2711 s->cc_op = CC_OP_SUBB + ot;
2717 } 2712 }
2718 break; 2713 break;
@@ -2726,21 +2721,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2726,21 +2721,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2726 if (prefixes & PREFIX_REPNZ) { 2721 if (prefixes & PREFIX_REPNZ) {
2727 if (s->cc_op != CC_OP_DYNAMIC) 2722 if (s->cc_op != CC_OP_DYNAMIC)
2728 gen_op_set_cc_op(s->cc_op); 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 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 2725 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2731 } else if (prefixes & PREFIX_REPZ) { 2726 } else if (prefixes & PREFIX_REPZ) {
2732 if (s->cc_op != CC_OP_DYNAMIC) 2727 if (s->cc_op != CC_OP_DYNAMIC)
2733 gen_op_set_cc_op(s->cc_op); 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 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 2730 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2736 } else { 2731 } else {
2737 - gen_op_cmps[ot](); 2732 + gen_string_ds(s, ot, gen_op_cmps);
2738 s->cc_op = CC_OP_SUBB + ot; 2733 s->cc_op = CC_OP_SUBB + ot;
2739 } 2734 }
2740 break; 2735 break;
2741 -  
2742 - /************************/  
2743 - /* port I/O */  
2744 case 0x6c: /* insS */ 2736 case 0x6c: /* insS */
2745 case 0x6d: 2737 case 0x6d:
2746 if ((b & 1) == 0) 2738 if ((b & 1) == 0)
@@ -2748,9 +2740,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2748,9 +2740,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2748 else 2740 else
2749 ot = dflag ? OT_LONG : OT_WORD; 2741 ot = dflag ? OT_LONG : OT_WORD;
2750 if (prefixes & PREFIX_REPZ) { 2742 if (prefixes & PREFIX_REPZ) {
2751 - gen_op_ins[3 + ot](); 2743 + gen_string_es(s, ot, gen_op_ins + 9);
2752 } else { 2744 } else {
2753 - gen_op_ins[ot](); 2745 + gen_string_es(s, ot, gen_op_ins);
2754 } 2746 }
2755 break; 2747 break;
2756 case 0x6e: /* outsS */ 2748 case 0x6e: /* outsS */
@@ -2760,11 +2752,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2760,11 +2752,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2760 else 2752 else
2761 ot = dflag ? OT_LONG : OT_WORD; 2753 ot = dflag ? OT_LONG : OT_WORD;
2762 if (prefixes & PREFIX_REPZ) { 2754 if (prefixes & PREFIX_REPZ) {
2763 - gen_op_outs[3 + ot](); 2755 + gen_string_ds(s, ot, gen_op_outs + 9);
2764 } else { 2756 } else {
2765 - gen_op_outs[ot](); 2757 + gen_string_ds(s, ot, gen_op_outs);
2766 } 2758 }
2767 break; 2759 break;
  2760 +
  2761 + /************************/
  2762 + /* port I/O */
2768 case 0xe4: 2763 case 0xe4:
2769 case 0xe5: 2764 case 0xe5:
2770 if ((b & 1) == 0) 2765 if ((b & 1) == 0)
@@ -3150,14 +3145,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3150,14 +3145,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3150 case 0xcd: /* int N */ 3145 case 0xcd: /* int N */
3151 val = ldub(s->pc++); 3146 val = ldub(s->pc++);
3152 /* XXX: currently we ignore the interrupt number */ 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 s->is_jmp = 1; 3149 s->is_jmp = 1;
3155 break; 3150 break;
3156 case 0xce: /* into */ 3151 case 0xce: /* into */
3157 if (s->cc_op != CC_OP_DYNAMIC) 3152 if (s->cc_op != CC_OP_DYNAMIC)
3158 gen_op_set_cc_op(s->cc_op); 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, &reg_addr, &offset_addr);
  3165 + if (ot == OT_WORD)
  3166 + gen_op_boundw();
  3167 + else
  3168 + gen_op_boundl();
3161 break; 3169 break;
3162 case 0x1c8 ... 0x1cf: /* bswap reg */ 3170 case 0x1c8 ... 0x1cf: /* bswap reg */
3163 reg = b & 7; 3171 reg = b & 7;
@@ -3188,11 +3196,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3188,11 +3196,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3188 case 0x131: /* rdtsc */ 3196 case 0x131: /* rdtsc */
3189 gen_op_rdtsc(); 3197 gen_op_rdtsc();
3190 break; 3198 break;
3191 -#if 0  
3192 case 0x1a2: /* cpuid */ 3199 case 0x1a2: /* cpuid */
3193 - gen_insn0(OP_ASM); 3200 + gen_op_cpuid();
3194 break; 3201 break;
3195 -#endif  
3196 default: 3202 default:
3197 goto illegal_op; 3203 goto illegal_op;
3198 } 3204 }
@@ -3399,28 +3405,30 @@ static uint16_t opc_write_flags[NB_OPS] = { @@ -3399,28 +3405,30 @@ static uint16_t opc_write_flags[NB_OPS] = {
3399 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC, 3405 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3400 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC, 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 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC, 3428 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3423 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC, 3429 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
  3430 +
  3431 + [INDEX_op_cmpxchg8b] = CC_Z,
3424 }; 3432 };
3425 3433
3426 /* simpler form of an operation if no flags need to be generated */ 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,21 +3503,36 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3495 3503
3496 #ifdef DEBUG_DISAS 3504 #ifdef DEBUG_DISAS
3497 static const char *op_str[] = { 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 #include "opc-i386.h" 3513 #include "opc-i386.h"
3500 #undef DEF 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 const uint16_t *opc_ptr; 3519 const uint16_t *opc_ptr;
3506 - int c; 3520 + const uint32_t *opparam_ptr;
  3521 + int c, n, i;
  3522 +
3507 opc_ptr = opc_buf; 3523 opc_ptr = opc_buf;
  3524 + opparam_ptr = opparam_buf;
3508 for(;;) { 3525 for(;;) {
3509 c = *opc_ptr++; 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 if (c == INDEX_op_end) 3533 if (c == INDEX_op_end)
3512 break; 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,6 +3570,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3547 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; 3570 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3548 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; 3571 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3549 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; 3572 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
  3573 + dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3550 dc->cc_op = CC_OP_DYNAMIC; 3574 dc->cc_op = CC_OP_DYNAMIC;
3551 dc->cs_base = cs_base; 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,7 +3634,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3610 fprintf(logfile, "\n"); 3634 fprintf(logfile, "\n");
3611 3635
3612 fprintf(logfile, "OP:\n"); 3636 fprintf(logfile, "OP:\n");
3613 - dump_ops(gen_opc_buf); 3637 + dump_ops(gen_opc_buf, gen_opparam_buf);
3614 fprintf(logfile, "\n"); 3638 fprintf(logfile, "\n");
3615 } 3639 }
3616 #endif 3640 #endif
@@ -3621,7 +3645,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, @@ -3621,7 +3645,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3621 #ifdef DEBUG_DISAS 3645 #ifdef DEBUG_DISAS
3622 if (loglevel) { 3646 if (loglevel) {
3623 fprintf(logfile, "AFTER FLAGS OPT:\n"); 3647 fprintf(logfile, "AFTER FLAGS OPT:\n");
3624 - dump_ops(gen_opc_buf); 3648 + dump_ops(gen_opc_buf, gen_opparam_buf);
3625 fprintf(logfile, "\n"); 3649 fprintf(logfile, "\n");
3626 } 3650 }
3627 #endif 3651 #endif
@@ -3683,8 +3707,8 @@ CPUX86State *cpu_x86_init(void) @@ -3683,8 +3707,8 @@ CPUX86State *cpu_x86_init(void)
3683 for(i = 0;i < 8; i++) 3707 for(i = 0;i < 8; i++)
3684 env->fptags[i] = 1; 3708 env->fptags[i] = 1;
3685 env->fpuc = 0x37f; 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 /* init various static tables */ 3713 /* init various static tables */
3690 if (!inited) { 3714 if (!inited) {