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,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, ®_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, ®_addr, &offset_addr); | 2048 | gen_lea_modrm(s, modrm, ®_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, ®_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, ®_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) { |