diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-03-30 16:44:54 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-03-30 16:44:54 +0000 |
commit | 24c7b0e330fdbfcfe87f515d79e67156c57cbc4f (patch) | |
tree | 50ed71bd4fc4c3fc0e6fc5cccb222417244b5baa /target-mips/helper.c | |
parent | e69f67b6d58f366ffaa83a0973948edd1f74b370 (diff) |
Sanitize mips exception handling.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2546 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips/helper.c')
-rw-r--r-- | target-mips/helper.c | 45 |
1 files changed, 20 insertions, 25 deletions
diff --git a/target-mips/helper.c b/target-mips/helper.c index 0b23f359f0..fe5b2ab676 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -90,7 +90,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, if (user_mode && address > 0x7FFFFFFFUL) return TLBRET_BADADDR; if (address < (int32_t)0x80000000UL) { - if (!(env->hflags & MIPS_HFLAG_ERL)) { + if (!(env->CP0_Status & (1 << CP0St_ERL))) { #ifdef MIPS_USES_R4K_TLB ret = map_address(env, physical, prot, address, rw, access_type); #else @@ -289,21 +289,18 @@ void do_interrupt (CPUState *env) goto set_DEPC; case EXCP_DDBL: env->CP0_Debug |= 1 << CP0DB_DDBL; - goto set_DEPC; set_DEPC: if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ env->CP0_DEPC = env->PC - 4; - if (!(env->hflags & MIPS_HFLAG_EXL)) - env->CP0_Cause |= (1 << CP0Ca_BD); env->hflags &= ~MIPS_HFLAG_BMASK; } else { env->CP0_DEPC = env->PC; - env->CP0_Cause &= ~(1 << CP0Ca_BD); } enter_debug_mode: env->hflags |= MIPS_HFLAG_DM; + env->hflags &= ~MIPS_HFLAG_UM; /* EJTAG probe trap enable is not implemented... */ env->PC = (int32_t)0xBFC00480; break; @@ -311,25 +308,22 @@ void do_interrupt (CPUState *env) cpu_reset(env); break; case EXCP_SRESET: - env->CP0_Status = (1 << CP0St_SR); + env->CP0_Status |= (1 << CP0St_SR); env->CP0_WatchLo = 0; goto set_error_EPC; case EXCP_NMI: - env->CP0_Status = (1 << CP0St_NMI); + env->CP0_Status |= (1 << CP0St_NMI); set_error_EPC: if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ env->CP0_ErrorEPC = env->PC - 4; - if (!(env->hflags & MIPS_HFLAG_EXL)) - env->CP0_Cause |= (1 << CP0Ca_BD); env->hflags &= ~MIPS_HFLAG_BMASK; } else { env->CP0_ErrorEPC = env->PC; - env->CP0_Cause &= ~(1 << CP0Ca_BD); } - env->hflags |= MIPS_HFLAG_ERL; - env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); + env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); + env->hflags &= ~MIPS_HFLAG_UM; env->PC = (int32_t)0xBFC00000; break; case EXCP_MCHECK: @@ -350,7 +344,7 @@ void do_interrupt (CPUState *env) goto set_EPC; case EXCP_TLBL: cause = 2; - if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL)) + if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) offset = 0x000; goto set_EPC; case EXCP_IBE: @@ -384,28 +378,29 @@ void do_interrupt (CPUState *env) goto set_EPC; case EXCP_TLBS: cause = 3; - if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL)) + if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) offset = 0x000; - goto set_EPC; set_EPC: - if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_EPC = env->PC - 4; - if (!(env->hflags & MIPS_HFLAG_EXL)) + if (!(env->CP0_Status & (1 << CP0St_EXL))) { + if (env->hflags & MIPS_HFLAG_BMASK) { + /* If the exception was raised from a delay slot, + come back to the jump. */ + env->CP0_EPC = env->PC - 4; env->CP0_Cause |= (1 << CP0Ca_BD); - env->hflags &= ~MIPS_HFLAG_BMASK; + env->hflags &= ~MIPS_HFLAG_BMASK; + } else { + env->CP0_EPC = env->PC; + env->CP0_Cause &= ~(1 << CP0Ca_BD); + } } else { - env->CP0_EPC = env->PC; - env->CP0_Cause &= ~(1 << CP0Ca_BD); + env->CP0_Status |= (1 << CP0St_EXL); + env->hflags &= ~MIPS_HFLAG_UM; } if (env->CP0_Status & (1 << CP0St_BEV)) { env->PC = (int32_t)0xBFC00200; } else { env->PC = (int32_t)0x80000000; } - env->hflags |= MIPS_HFLAG_EXL; - env->CP0_Status |= (1 << CP0St_EXL); env->PC += offset; env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2); break; |