diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-11-23 23:09:40 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-11-23 23:09:40 +0000 |
commit | 4136f33c7e3c034b17bb0032fa5d4297ae2f317a (patch) | |
tree | e56d20e93e79ef871bb47d9654d664377ab2cec1 /target-i386 | |
parent | 6dca2016fc0cca49ce866b7f2fcfffe011c1f496 (diff) |
fixed eflags IF/IOPL update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@476 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/exec.h | 5 | ||||
-rw-r--r-- | target-i386/helper.c | 74 | ||||
-rw-r--r-- | target-i386/op.c | 32 | ||||
-rw-r--r-- | target-i386/translate.c | 18 |
4 files changed, 70 insertions, 59 deletions
diff --git a/target-i386/exec.h b/target-i386/exec.h index dd11a3a3ed..f6c717eedb 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -512,11 +512,6 @@ static inline uint32_t compute_eflags(void) return env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); } -#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK) - -#define FL_UPDATE_CPL0_MASK (TF_MASK | IF_MASK | IOPL_MASK | NT_MASK | \ - RF_MASK | AC_MASK | ID_MASK) - /* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */ static inline void load_eflags(int eflags, int update_mask) { diff --git a/target-i386/helper.c b/target-i386/helper.c index 861266fa14..a743cfb5a3 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -419,7 +419,8 @@ static void switch_tss(int tss_selector, /* load all registers without an exception, then reload them with possible exception */ env->eip = new_eip; - eflags_mask = FL_UPDATE_CPL0_MASK; + eflags_mask = TF_MASK | AC_MASK | ID_MASK | + IF_MASK | IOPL_MASK | VM_MASK | RF_MASK; if (!(type & 8)) eflags_mask &= 0xffff; load_eflags(new_eflags, eflags_mask); @@ -575,27 +576,6 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; uint32_t old_eip; -#ifdef DEBUG_PCALL - if (loglevel) { - static int count; - fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d CS:IP=%04x:%08x CPL=%d\n", - count, intno, error_code, is_int, env->segs[R_CS].selector, env->eip, env->hflags & 3); -#if 0 - { - int i; - uint8_t *ptr; - printf(" code="); - ptr = env->segs[R_CS].base + env->eip; - for(i = 0; i < 16; i++) { - printf(" %02x", ldub(ptr + i)); - } - printf("\n"); - } -#endif - count++; - } -#endif - has_error_code = 0; if (!is_int && !is_hw) { switch(intno) { @@ -775,7 +755,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, /* real mode interrupt */ static void do_interrupt_real(int intno, int is_int, int error_code, - unsigned int next_eip) + unsigned int next_eip) { SegmentCache *dt; uint8_t *ptr, *ssp; @@ -844,6 +824,27 @@ void do_interrupt_user(int intno, int is_int, int error_code, void do_interrupt(int intno, int is_int, int error_code, unsigned int next_eip, int is_hw) { +#ifdef DEBUG_PCALL + if (loglevel) { + static int count; + fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d\n", + count, intno, error_code, is_int); + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); +#if 0 + { + int i; + uint8_t *ptr; + printf(" code="); + ptr = env->segs[R_CS].base + env->eip; + for(i = 0; i < 16; i++) { + printf(" %02x", ldub(ptr + i)); + } + printf("\n"); + } +#endif + count++; + } +#endif if (env->cr[0] & CR0_PE_MASK) { do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); } else { @@ -1293,6 +1294,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) if (loglevel) { fprintf(logfile, "lcall %04x:%08x\n", new_cs, new_eip); + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); } #endif if ((new_cs & 0xfffc) == 0) @@ -1493,13 +1495,13 @@ void helper_iret_real(int shift) POPW(ssp, sp, sp_mask, new_cs); POPW(ssp, sp, sp_mask, new_eflags); } - ESP = (ESP & ~sp_mask) | (sp & 0xffff); + ESP = (ESP & ~sp_mask) | (sp & sp_mask); load_seg_vm(R_CS, new_cs); env->eip = new_eip; if (env->eflags & VM_MASK) - eflags_mask = FL_UPDATE_MASK32 | IF_MASK | RF_MASK; + eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK; else - eflags_mask = FL_UPDATE_CPL0_MASK; + eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK; if (shift == 0) eflags_mask &= 0xffff; load_eflags(new_eflags, eflags_mask); @@ -1511,7 +1513,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask; uint32_t new_es, new_ds, new_fs, new_gs; uint32_t e1, e2, ss_e1, ss_e2; - int cpl, dpl, rpl, eflags_mask; + int cpl, dpl, rpl, eflags_mask, iopl; uint8_t *ssp; 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) } #ifdef DEBUG_PCALL if (loglevel) { - fprintf(logfile, "lret new %04x:%08x\n", - new_cs, new_eip); + fprintf(logfile, "lret new %04x:%08x addend=0x%x\n", + new_cs, new_eip, addend); + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); } #endif if ((new_cs & 0xfffc) == 0) @@ -1611,11 +1614,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) ESP = (ESP & ~sp_mask) | (sp & sp_mask); env->eip = new_eip; if (is_iret) { - /* NOTE: 'cpl' can be different from the current CPL */ + /* NOTE: 'cpl' is the _old_ CPL */ + eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK; if (cpl == 0) - eflags_mask = FL_UPDATE_CPL0_MASK; - else - eflags_mask = FL_UPDATE_MASK32; + eflags_mask |= IOPL_MASK; + iopl = (env->eflags >> IOPL_SHIFT) & 3; + if (cpl <= iopl) + eflags_mask |= IF_MASK; if (shift == 0) eflags_mask &= 0xffff; load_eflags(new_eflags, eflags_mask); @@ -1631,7 +1636,8 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) POPL(ssp, sp, sp_mask, new_gs); /* modify processor state */ - load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); + load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | + IF_MASK | IOPL_MASK | VM_MASK | VIF_MASK | VIP_MASK); load_seg_vm(R_CS, new_cs & 0xffff); cpu_x86_set_cpl(env, 3); load_seg_vm(R_SS, new_ss & 0xffff); diff --git a/target-i386/op.c b/target-i386/op.c index 04046fc0b5..8988e061cb 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -1138,38 +1138,36 @@ void OPPROTO op_set_cc_op(void) CC_OP = PARAM1; } -#define FL_UPDATE_MASK16 (FL_UPDATE_MASK32 & 0xffff) +/* XXX: clear VIF/VIP in all ops ? */ void OPPROTO op_movl_eflags_T0(void) { - int eflags; - eflags = T0; - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); - DF = 1 - (2 * ((eflags >> 10) & 1)); - /* we also update some system flags as in user mode */ - env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | - (eflags & FL_UPDATE_MASK32); + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK)); } void OPPROTO op_movw_eflags_T0(void) { - int eflags; - eflags = T0; - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); - DF = 1 - (2 * ((eflags >> 10) & 1)); - /* we also update some system flags as in user mode */ - env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | - (eflags & FL_UPDATE_MASK16); + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK) & 0xffff); +} + +void OPPROTO op_movl_eflags_T0_io(void) +{ + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK)); +} + +void OPPROTO op_movw_eflags_T0_io(void) +{ + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK) & 0xffff); } void OPPROTO op_movl_eflags_T0_cpl0(void) { - load_eflags(T0, FL_UPDATE_CPL0_MASK); + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK)); } void OPPROTO op_movw_eflags_T0_cpl0(void) { - load_eflags(T0, FL_UPDATE_CPL0_MASK & 0xffff); + load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK) & 0xffff); } #if 0 diff --git a/target-i386/translate.c b/target-i386/translate.c index b09f1b7a4c..9c5c52e4b2 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -3540,10 +3540,18 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_movw_eflags_T0_cpl0(); } } else { - if (s->dflag) { - gen_op_movl_eflags_T0(); + if (s->cpl <= s->iopl) { + if (s->dflag) { + gen_op_movl_eflags_T0_io(); + } else { + gen_op_movw_eflags_T0_io(); + } } else { - gen_op_movw_eflags_T0(); + if (s->dflag) { + gen_op_movl_eflags_T0(); + } else { + gen_op_movw_eflags_T0(); + } } } gen_pop_update(s); @@ -4265,6 +4273,10 @@ static uint16_t opc_write_flags[NB_OPS] = { [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, [INDEX_op_movw_eflags_T0] = CC_OSZAPC, [INDEX_op_movl_eflags_T0] = CC_OSZAPC, + [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC, + [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC, + [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC, + [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC, [INDEX_op_clc] = CC_C, [INDEX_op_stc] = CC_C, [INDEX_op_cmc] = CC_C, |