Commit 4136f33c7e3c034b17bb0032fa5d4297ae2f317a
1 parent
6dca2016
fixed eflags IF/IOPL update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@476 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
70 additions
and
59 deletions
target-i386/exec.h
| @@ -512,11 +512,6 @@ static inline uint32_t compute_eflags(void) | @@ -512,11 +512,6 @@ static inline uint32_t compute_eflags(void) | ||
| 512 | return env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); | 512 | return env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); |
| 513 | } | 513 | } |
| 514 | 514 | ||
| 515 | -#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK) | ||
| 516 | - | ||
| 517 | -#define FL_UPDATE_CPL0_MASK (TF_MASK | IF_MASK | IOPL_MASK | NT_MASK | \ | ||
| 518 | - RF_MASK | AC_MASK | ID_MASK) | ||
| 519 | - | ||
| 520 | /* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */ | 515 | /* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */ |
| 521 | static inline void load_eflags(int eflags, int update_mask) | 516 | static inline void load_eflags(int eflags, int update_mask) |
| 522 | { | 517 | { |
target-i386/helper.c
| @@ -419,7 +419,8 @@ static void switch_tss(int tss_selector, | @@ -419,7 +419,8 @@ static void switch_tss(int tss_selector, | ||
| 419 | /* load all registers without an exception, then reload them with | 419 | /* load all registers without an exception, then reload them with |
| 420 | possible exception */ | 420 | possible exception */ |
| 421 | env->eip = new_eip; | 421 | env->eip = new_eip; |
| 422 | - eflags_mask = FL_UPDATE_CPL0_MASK; | 422 | + eflags_mask = TF_MASK | AC_MASK | ID_MASK | |
| 423 | + IF_MASK | IOPL_MASK | VM_MASK | RF_MASK; | ||
| 423 | if (!(type & 8)) | 424 | if (!(type & 8)) |
| 424 | eflags_mask &= 0xffff; | 425 | eflags_mask &= 0xffff; |
| 425 | load_eflags(new_eflags, eflags_mask); | 426 | load_eflags(new_eflags, eflags_mask); |
| @@ -575,27 +576,6 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -575,27 +576,6 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 575 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; | 576 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; |
| 576 | uint32_t old_eip; | 577 | uint32_t old_eip; |
| 577 | 578 | ||
| 578 | -#ifdef DEBUG_PCALL | ||
| 579 | - if (loglevel) { | ||
| 580 | - static int count; | ||
| 581 | - fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d CS:IP=%04x:%08x CPL=%d\n", | ||
| 582 | - count, intno, error_code, is_int, env->segs[R_CS].selector, env->eip, env->hflags & 3); | ||
| 583 | -#if 0 | ||
| 584 | - { | ||
| 585 | - int i; | ||
| 586 | - uint8_t *ptr; | ||
| 587 | - printf(" code="); | ||
| 588 | - ptr = env->segs[R_CS].base + env->eip; | ||
| 589 | - for(i = 0; i < 16; i++) { | ||
| 590 | - printf(" %02x", ldub(ptr + i)); | ||
| 591 | - } | ||
| 592 | - printf("\n"); | ||
| 593 | - } | ||
| 594 | -#endif | ||
| 595 | - count++; | ||
| 596 | - } | ||
| 597 | -#endif | ||
| 598 | - | ||
| 599 | has_error_code = 0; | 579 | has_error_code = 0; |
| 600 | if (!is_int && !is_hw) { | 580 | if (!is_int && !is_hw) { |
| 601 | switch(intno) { | 581 | switch(intno) { |
| @@ -775,7 +755,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -775,7 +755,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 775 | 755 | ||
| 776 | /* real mode interrupt */ | 756 | /* real mode interrupt */ |
| 777 | static void do_interrupt_real(int intno, int is_int, int error_code, | 757 | static void do_interrupt_real(int intno, int is_int, int error_code, |
| 778 | - unsigned int next_eip) | 758 | + unsigned int next_eip) |
| 779 | { | 759 | { |
| 780 | SegmentCache *dt; | 760 | SegmentCache *dt; |
| 781 | uint8_t *ptr, *ssp; | 761 | uint8_t *ptr, *ssp; |
| @@ -844,6 +824,27 @@ void do_interrupt_user(int intno, int is_int, int error_code, | @@ -844,6 +824,27 @@ void do_interrupt_user(int intno, int is_int, int error_code, | ||
| 844 | void do_interrupt(int intno, int is_int, int error_code, | 824 | void do_interrupt(int intno, int is_int, int error_code, |
| 845 | unsigned int next_eip, int is_hw) | 825 | unsigned int next_eip, int is_hw) |
| 846 | { | 826 | { |
| 827 | +#ifdef DEBUG_PCALL | ||
| 828 | + if (loglevel) { | ||
| 829 | + static int count; | ||
| 830 | + fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d\n", | ||
| 831 | + count, intno, error_code, is_int); | ||
| 832 | + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); | ||
| 833 | +#if 0 | ||
| 834 | + { | ||
| 835 | + int i; | ||
| 836 | + uint8_t *ptr; | ||
| 837 | + printf(" code="); | ||
| 838 | + ptr = env->segs[R_CS].base + env->eip; | ||
| 839 | + for(i = 0; i < 16; i++) { | ||
| 840 | + printf(" %02x", ldub(ptr + i)); | ||
| 841 | + } | ||
| 842 | + printf("\n"); | ||
| 843 | + } | ||
| 844 | +#endif | ||
| 845 | + count++; | ||
| 846 | + } | ||
| 847 | +#endif | ||
| 847 | if (env->cr[0] & CR0_PE_MASK) { | 848 | if (env->cr[0] & CR0_PE_MASK) { |
| 848 | do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); | 849 | do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); |
| 849 | } else { | 850 | } else { |
| @@ -1293,6 +1294,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) | @@ -1293,6 +1294,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) | ||
| 1293 | if (loglevel) { | 1294 | if (loglevel) { |
| 1294 | fprintf(logfile, "lcall %04x:%08x\n", | 1295 | fprintf(logfile, "lcall %04x:%08x\n", |
| 1295 | new_cs, new_eip); | 1296 | new_cs, new_eip); |
| 1297 | + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); | ||
| 1296 | } | 1298 | } |
| 1297 | #endif | 1299 | #endif |
| 1298 | if ((new_cs & 0xfffc) == 0) | 1300 | if ((new_cs & 0xfffc) == 0) |
| @@ -1493,13 +1495,13 @@ void helper_iret_real(int shift) | @@ -1493,13 +1495,13 @@ void helper_iret_real(int shift) | ||
| 1493 | POPW(ssp, sp, sp_mask, new_cs); | 1495 | POPW(ssp, sp, sp_mask, new_cs); |
| 1494 | POPW(ssp, sp, sp_mask, new_eflags); | 1496 | POPW(ssp, sp, sp_mask, new_eflags); |
| 1495 | } | 1497 | } |
| 1496 | - ESP = (ESP & ~sp_mask) | (sp & 0xffff); | 1498 | + ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
| 1497 | load_seg_vm(R_CS, new_cs); | 1499 | load_seg_vm(R_CS, new_cs); |
| 1498 | env->eip = new_eip; | 1500 | env->eip = new_eip; |
| 1499 | if (env->eflags & VM_MASK) | 1501 | if (env->eflags & VM_MASK) |
| 1500 | - eflags_mask = FL_UPDATE_MASK32 | IF_MASK | RF_MASK; | 1502 | + eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK; |
| 1501 | else | 1503 | else |
| 1502 | - eflags_mask = FL_UPDATE_CPL0_MASK; | 1504 | + eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK; |
| 1503 | if (shift == 0) | 1505 | if (shift == 0) |
| 1504 | eflags_mask &= 0xffff; | 1506 | eflags_mask &= 0xffff; |
| 1505 | load_eflags(new_eflags, eflags_mask); | 1507 | load_eflags(new_eflags, eflags_mask); |
| @@ -1511,7 +1513,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1511,7 +1513,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1511 | uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask; | 1513 | uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask; |
| 1512 | uint32_t new_es, new_ds, new_fs, new_gs; | 1514 | uint32_t new_es, new_ds, new_fs, new_gs; |
| 1513 | uint32_t e1, e2, ss_e1, ss_e2; | 1515 | uint32_t e1, e2, ss_e1, ss_e2; |
| 1514 | - int cpl, dpl, rpl, eflags_mask; | 1516 | + int cpl, dpl, rpl, eflags_mask, iopl; |
| 1515 | uint8_t *ssp; | 1517 | uint8_t *ssp; |
| 1516 | 1518 | ||
| 1517 | sp_mask = get_sp_mask(env->segs[R_SS].flags); | 1519 | sp_mask = get_sp_mask(env->segs[R_SS].flags); |
| @@ -1536,8 +1538,9 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1536,8 +1538,9 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1536 | } | 1538 | } |
| 1537 | #ifdef DEBUG_PCALL | 1539 | #ifdef DEBUG_PCALL |
| 1538 | if (loglevel) { | 1540 | if (loglevel) { |
| 1539 | - fprintf(logfile, "lret new %04x:%08x\n", | ||
| 1540 | - new_cs, new_eip); | 1541 | + fprintf(logfile, "lret new %04x:%08x addend=0x%x\n", |
| 1542 | + new_cs, new_eip, addend); | ||
| 1543 | + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); | ||
| 1541 | } | 1544 | } |
| 1542 | #endif | 1545 | #endif |
| 1543 | if ((new_cs & 0xfffc) == 0) | 1546 | if ((new_cs & 0xfffc) == 0) |
| @@ -1611,11 +1614,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1611,11 +1614,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1611 | ESP = (ESP & ~sp_mask) | (sp & sp_mask); | 1614 | ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
| 1612 | env->eip = new_eip; | 1615 | env->eip = new_eip; |
| 1613 | if (is_iret) { | 1616 | if (is_iret) { |
| 1614 | - /* NOTE: 'cpl' can be different from the current CPL */ | 1617 | + /* NOTE: 'cpl' is the _old_ CPL */ |
| 1618 | + eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK; | ||
| 1615 | if (cpl == 0) | 1619 | if (cpl == 0) |
| 1616 | - eflags_mask = FL_UPDATE_CPL0_MASK; | ||
| 1617 | - else | ||
| 1618 | - eflags_mask = FL_UPDATE_MASK32; | 1620 | + eflags_mask |= IOPL_MASK; |
| 1621 | + iopl = (env->eflags >> IOPL_SHIFT) & 3; | ||
| 1622 | + if (cpl <= iopl) | ||
| 1623 | + eflags_mask |= IF_MASK; | ||
| 1619 | if (shift == 0) | 1624 | if (shift == 0) |
| 1620 | eflags_mask &= 0xffff; | 1625 | eflags_mask &= 0xffff; |
| 1621 | load_eflags(new_eflags, eflags_mask); | 1626 | load_eflags(new_eflags, eflags_mask); |
| @@ -1631,7 +1636,8 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1631,7 +1636,8 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1631 | POPL(ssp, sp, sp_mask, new_gs); | 1636 | POPL(ssp, sp, sp_mask, new_gs); |
| 1632 | 1637 | ||
| 1633 | /* modify processor state */ | 1638 | /* modify processor state */ |
| 1634 | - load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); | 1639 | + load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | |
| 1640 | + IF_MASK | IOPL_MASK | VM_MASK | VIF_MASK | VIP_MASK); | ||
| 1635 | load_seg_vm(R_CS, new_cs & 0xffff); | 1641 | load_seg_vm(R_CS, new_cs & 0xffff); |
| 1636 | cpu_x86_set_cpl(env, 3); | 1642 | cpu_x86_set_cpl(env, 3); |
| 1637 | load_seg_vm(R_SS, new_ss & 0xffff); | 1643 | load_seg_vm(R_SS, new_ss & 0xffff); |
target-i386/op.c
| @@ -1138,38 +1138,36 @@ void OPPROTO op_set_cc_op(void) | @@ -1138,38 +1138,36 @@ void OPPROTO op_set_cc_op(void) | ||
| 1138 | CC_OP = PARAM1; | 1138 | CC_OP = PARAM1; |
| 1139 | } | 1139 | } |
| 1140 | 1140 | ||
| 1141 | -#define FL_UPDATE_MASK16 (FL_UPDATE_MASK32 & 0xffff) | 1141 | +/* XXX: clear VIF/VIP in all ops ? */ |
| 1142 | 1142 | ||
| 1143 | void OPPROTO op_movl_eflags_T0(void) | 1143 | void OPPROTO op_movl_eflags_T0(void) |
| 1144 | { | 1144 | { |
| 1145 | - int eflags; | ||
| 1146 | - eflags = T0; | ||
| 1147 | - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | ||
| 1148 | - DF = 1 - (2 * ((eflags >> 10) & 1)); | ||
| 1149 | - /* we also update some system flags as in user mode */ | ||
| 1150 | - env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | | ||
| 1151 | - (eflags & FL_UPDATE_MASK32); | 1145 | + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK)); |
| 1152 | } | 1146 | } |
| 1153 | 1147 | ||
| 1154 | void OPPROTO op_movw_eflags_T0(void) | 1148 | void OPPROTO op_movw_eflags_T0(void) |
| 1155 | { | 1149 | { |
| 1156 | - int eflags; | ||
| 1157 | - eflags = T0; | ||
| 1158 | - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | ||
| 1159 | - DF = 1 - (2 * ((eflags >> 10) & 1)); | ||
| 1160 | - /* we also update some system flags as in user mode */ | ||
| 1161 | - env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | | ||
| 1162 | - (eflags & FL_UPDATE_MASK16); | 1150 | + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK) & 0xffff); |
| 1151 | +} | ||
| 1152 | + | ||
| 1153 | +void OPPROTO op_movl_eflags_T0_io(void) | ||
| 1154 | +{ | ||
| 1155 | + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK)); | ||
| 1156 | +} | ||
| 1157 | + | ||
| 1158 | +void OPPROTO op_movw_eflags_T0_io(void) | ||
| 1159 | +{ | ||
| 1160 | + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK) & 0xffff); | ||
| 1163 | } | 1161 | } |
| 1164 | 1162 | ||
| 1165 | void OPPROTO op_movl_eflags_T0_cpl0(void) | 1163 | void OPPROTO op_movl_eflags_T0_cpl0(void) |
| 1166 | { | 1164 | { |
| 1167 | - load_eflags(T0, FL_UPDATE_CPL0_MASK); | 1165 | + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK)); |
| 1168 | } | 1166 | } |
| 1169 | 1167 | ||
| 1170 | void OPPROTO op_movw_eflags_T0_cpl0(void) | 1168 | void OPPROTO op_movw_eflags_T0_cpl0(void) |
| 1171 | { | 1169 | { |
| 1172 | - load_eflags(T0, FL_UPDATE_CPL0_MASK & 0xffff); | 1170 | + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK) & 0xffff); |
| 1173 | } | 1171 | } |
| 1174 | 1172 | ||
| 1175 | #if 0 | 1173 | #if 0 |
target-i386/translate.c
| @@ -3540,10 +3540,18 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3540,10 +3540,18 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3540 | gen_op_movw_eflags_T0_cpl0(); | 3540 | gen_op_movw_eflags_T0_cpl0(); |
| 3541 | } | 3541 | } |
| 3542 | } else { | 3542 | } else { |
| 3543 | - if (s->dflag) { | ||
| 3544 | - gen_op_movl_eflags_T0(); | 3543 | + if (s->cpl <= s->iopl) { |
| 3544 | + if (s->dflag) { | ||
| 3545 | + gen_op_movl_eflags_T0_io(); | ||
| 3546 | + } else { | ||
| 3547 | + gen_op_movw_eflags_T0_io(); | ||
| 3548 | + } | ||
| 3545 | } else { | 3549 | } else { |
| 3546 | - gen_op_movw_eflags_T0(); | 3550 | + if (s->dflag) { |
| 3551 | + gen_op_movl_eflags_T0(); | ||
| 3552 | + } else { | ||
| 3553 | + gen_op_movw_eflags_T0(); | ||
| 3554 | + } | ||
| 3547 | } | 3555 | } |
| 3548 | } | 3556 | } |
| 3549 | gen_pop_update(s); | 3557 | gen_pop_update(s); |
| @@ -4265,6 +4273,10 @@ static uint16_t opc_write_flags[NB_OPS] = { | @@ -4265,6 +4273,10 @@ static uint16_t opc_write_flags[NB_OPS] = { | ||
| 4265 | [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, | 4273 | [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, |
| 4266 | [INDEX_op_movw_eflags_T0] = CC_OSZAPC, | 4274 | [INDEX_op_movw_eflags_T0] = CC_OSZAPC, |
| 4267 | [INDEX_op_movl_eflags_T0] = CC_OSZAPC, | 4275 | [INDEX_op_movl_eflags_T0] = CC_OSZAPC, |
| 4276 | + [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC, | ||
| 4277 | + [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC, | ||
| 4278 | + [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC, | ||
| 4279 | + [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC, | ||
| 4268 | [INDEX_op_clc] = CC_C, | 4280 | [INDEX_op_clc] = CC_C, |
| 4269 | [INDEX_op_stc] = CC_C, | 4281 | [INDEX_op_stc] = CC_C, |
| 4270 | [INDEX_op_cmc] = CC_C, | 4282 | [INDEX_op_cmc] = CC_C, |