Commit 4136f33c7e3c034b17bb0032fa5d4297ae2f317a

Authored by bellard
1 parent 6dca2016

fixed eflags IF/IOPL update


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@476 c046a42c-6fe2-441c-8c8c-71466251a162
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,
... ...