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 | 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 | 515 | /* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */ |
| 521 | 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 | 419 | /* load all registers without an exception, then reload them with |
| 420 | 420 | possible exception */ |
| 421 | 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 | 424 | if (!(type & 8)) |
| 424 | 425 | eflags_mask &= 0xffff; |
| 425 | 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 | 576 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; |
| 576 | 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 | 579 | has_error_code = 0; |
| 600 | 580 | if (!is_int && !is_hw) { |
| 601 | 581 | switch(intno) { |
| ... | ... | @@ -775,7 +755,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
| 775 | 755 | |
| 776 | 756 | /* real mode interrupt */ |
| 777 | 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 | 760 | SegmentCache *dt; |
| 781 | 761 | uint8_t *ptr, *ssp; |
| ... | ... | @@ -844,6 +824,27 @@ void do_interrupt_user(int intno, int is_int, int error_code, |
| 844 | 824 | void do_interrupt(int intno, int is_int, int error_code, |
| 845 | 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 | 848 | if (env->cr[0] & CR0_PE_MASK) { |
| 848 | 849 | do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); |
| 849 | 850 | } else { |
| ... | ... | @@ -1293,6 +1294,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
| 1293 | 1294 | if (loglevel) { |
| 1294 | 1295 | fprintf(logfile, "lcall %04x:%08x\n", |
| 1295 | 1296 | new_cs, new_eip); |
| 1297 | + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); | |
| 1296 | 1298 | } |
| 1297 | 1299 | #endif |
| 1298 | 1300 | if ((new_cs & 0xfffc) == 0) |
| ... | ... | @@ -1493,13 +1495,13 @@ void helper_iret_real(int shift) |
| 1493 | 1495 | POPW(ssp, sp, sp_mask, new_cs); |
| 1494 | 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 | 1499 | load_seg_vm(R_CS, new_cs); |
| 1498 | 1500 | env->eip = new_eip; |
| 1499 | 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 | 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 | 1505 | if (shift == 0) |
| 1504 | 1506 | eflags_mask &= 0xffff; |
| 1505 | 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 | 1513 | uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask; |
| 1512 | 1514 | uint32_t new_es, new_ds, new_fs, new_gs; |
| 1513 | 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 | 1517 | uint8_t *ssp; |
| 1516 | 1518 | |
| 1517 | 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 | 1538 | } |
| 1537 | 1539 | #ifdef DEBUG_PCALL |
| 1538 | 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 | 1545 | #endif |
| 1543 | 1546 | if ((new_cs & 0xfffc) == 0) |
| ... | ... | @@ -1611,11 +1614,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
| 1611 | 1614 | ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
| 1612 | 1615 | env->eip = new_eip; |
| 1613 | 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 | 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 | 1624 | if (shift == 0) |
| 1620 | 1625 | eflags_mask &= 0xffff; |
| 1621 | 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 | 1636 | POPL(ssp, sp, sp_mask, new_gs); |
| 1632 | 1637 | |
| 1633 | 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 | 1641 | load_seg_vm(R_CS, new_cs & 0xffff); |
| 1636 | 1642 | cpu_x86_set_cpl(env, 3); |
| 1637 | 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 | 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 | 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 | 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 | 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 | 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 | 1173 | #if 0 | ... | ... |
target-i386/translate.c
| ... | ... | @@ -3540,10 +3540,18 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3540 | 3540 | gen_op_movw_eflags_T0_cpl0(); |
| 3541 | 3541 | } |
| 3542 | 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 | 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 | 3557 | gen_pop_update(s); |
| ... | ... | @@ -4265,6 +4273,10 @@ static uint16_t opc_write_flags[NB_OPS] = { |
| 4265 | 4273 | [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, |
| 4266 | 4274 | [INDEX_op_movw_eflags_T0] = CC_OSZAPC, |
| 4267 | 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 | 4280 | [INDEX_op_clc] = CC_C, |
| 4269 | 4281 | [INDEX_op_stc] = CC_C, |
| 4270 | 4282 | [INDEX_op_cmc] = CC_C, | ... | ... |