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, | ... | ... |