diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-03-26 22:26:53 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-03-26 22:26:53 +0000 |
commit | 08cea4eef8e17114dcdbce93f95cb111c9d622f6 (patch) | |
tree | d708e9ce4d32057cd80834b7ca7c131e12a09d89 /target-i386 | |
parent | 883da8e21932b24630f87ed4d801ea1ad48b735b (diff) |
fixed ljmp and iret to TSS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@682 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/exec.h | 4 | ||||
-rw-r--r-- | target-i386/helper.c | 10 | ||||
-rw-r--r-- | target-i386/op.c | 4 | ||||
-rw-r--r-- | target-i386/translate.c | 4 |
4 files changed, 10 insertions, 12 deletions
diff --git a/target-i386/exec.h b/target-i386/exec.h index 3f6ddf1b4b..63010f745d 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -123,11 +123,11 @@ typedef struct CCTable { extern CCTable cc_table[]; void load_seg(int seg_reg, int selector); -void helper_ljmp_protected_T0_T1(void); +void helper_ljmp_protected_T0_T1(int next_eip); void helper_lcall_real_T0_T1(int shift, int next_eip); void helper_lcall_protected_T0_T1(int shift, int next_eip); void helper_iret_real(int shift); -void helper_iret_protected(int shift); +void helper_iret_protected(int shift, int next_eip); void helper_lret_protected(int shift, int addend); void helper_lldt_T0(void); void helper_ltr_T0(void); diff --git a/target-i386/helper.c b/target-i386/helper.c index 6239436315..dbdabd82ee 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1219,7 +1219,7 @@ void load_seg(int seg_reg, int selector) } /* protected mode jump */ -void helper_ljmp_protected_T0_T1(void) +void helper_ljmp_protected_T0_T1(int next_eip) { int new_cs, new_eip, gate_cs, type; uint32_t e1, e2, cpl, dpl, rpl, limit; @@ -1267,8 +1267,7 @@ void helper_ljmp_protected_T0_T1(void) case 5: /* task gate */ if (dpl < cpl || dpl < rpl) raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); - /* XXX: check if it is really the current EIP */ - switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, env->eip); + switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip); break; case 4: /* 286 call gate */ case 12: /* 386 call gate */ @@ -1732,7 +1731,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) ESP = new_esp; } -void helper_iret_protected(int shift) +void helper_iret_protected(int shift, int next_eip) { int tss_selector, type; uint32_t e1, e2; @@ -1748,8 +1747,7 @@ void helper_iret_protected(int shift) /* NOTE: we check both segment and busy TSS */ if (type != 3) raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); - /* XXX: check if it is really the current EIP */ - switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, env->eip); + switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip); } else { helper_ret_protected(shift, 1, 0); } diff --git a/target-i386/op.c b/target-i386/op.c index f592b67a6a..1169f121ad 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -918,7 +918,7 @@ void OPPROTO op_arpl_update(void) /* T0: segment, T1:eip */ void OPPROTO op_ljmp_protected_T0_T1(void) { - helper_ljmp_protected_T0_T1(); + helper_ljmp_protected_T0_T1(PARAM1); } void OPPROTO op_lcall_real_T0_T1(void) @@ -938,7 +938,7 @@ void OPPROTO op_iret_real(void) void OPPROTO op_iret_protected(void) { - helper_iret_protected(PARAM1); + helper_iret_protected(PARAM1, PARAM2); } void OPPROTO op_lret_protected(void) diff --git a/target-i386/translate.c b/target-i386/translate.c index 12a74435ff..4a1a2767a9 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2172,7 +2172,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_jmp_im(pc_start - s->cs_base); - gen_op_ljmp_protected_T0_T1(); + gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base); } else { gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); gen_op_movl_T0_T1(); @@ -3453,7 +3453,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_jmp_im(pc_start - s->cs_base); - gen_op_iret_protected(s->dflag); + gen_op_iret_protected(s->dflag, s->pc - s->cs_base); s->cc_op = CC_OP_EFLAGS; } gen_eob(s); |