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