diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-05-29 11:08:52 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-05-29 11:08:52 +0000 |
commit | 023fe10d24acd124d0b7c5c5ac8edd41d6cc08f2 (patch) | |
tree | a8916df0fb3521f53aedf8e695ef312d0c2e7f13 /target-i386/helper.c | |
parent | f66723fab9eab2695a1b3cf15b55ffc2936b6418 (diff) |
fnop FPU exception support (aka FreeBSD FPU probe) - sysenter/sysexit support (untested, not enabled in cpuid)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@869 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386/helper.c')
-rw-r--r-- | target-i386/helper.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/target-i386/helper.c b/target-i386/helper.c index 5782babc20..9a88275f20 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1746,6 +1746,50 @@ void helper_lret_protected(int shift, int addend) helper_ret_protected(shift, 0, addend); } +void helper_sysenter(void) +{ + if (env->sysenter_cs == 0) { + raise_exception_err(EXCP0D_GPF, 0); + } + env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK); + cpu_x86_set_cpl(env, 0); + cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, + NULL, 0xffffffff, + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | + DESC_S_MASK | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); + cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, + NULL, 0xffffffff, + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | + DESC_S_MASK | + DESC_W_MASK | DESC_A_MASK); + ESP = env->sysenter_esp; + EIP = env->sysenter_eip; +} + +void helper_sysexit(void) +{ + int cpl; + + cpl = env->hflags & HF_CPL_MASK; + if (env->sysenter_cs == 0 || cpl != 0) { + raise_exception_err(EXCP0D_GPF, 0); + } + cpu_x86_set_cpl(env, 3); + cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, + NULL, 0xffffffff, + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); + cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, + NULL, 0xffffffff, + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | + DESC_W_MASK | DESC_A_MASK); + ESP = ECX; + EIP = EDX; +} + void helper_movl_crN_T0(int reg) { switch(reg) { |