diff options
Diffstat (limited to 'target-mips/helper.c')
-rw-r--r-- | target-mips/helper.c | 99 |
1 files changed, 53 insertions, 46 deletions
diff --git a/target-mips/helper.c b/target-mips/helper.c index 4a372777c7..0b5ec3e566 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -201,6 +201,58 @@ static int get_physical_address (CPUState *env, target_phys_addr_t *physical, } #endif +static void raise_mmu_exception(CPUState *env, target_ulong address, + int rw, int tlb_error) +{ + int exception = 0, error_code = 0; + + switch (tlb_error) { + default: + case TLBRET_BADADDR: + /* Reference to kernel address from user mode or supervisor mode */ + /* Reference to supervisor address from user mode */ + if (rw) + exception = EXCP_AdES; + else + exception = EXCP_AdEL; + break; + case TLBRET_NOMATCH: + /* No TLB match for a mapped address */ + if (rw) + exception = EXCP_TLBS; + else + exception = EXCP_TLBL; + error_code = 1; + break; + case TLBRET_INVALID: + /* TLB match with no valid bit */ + if (rw) + exception = EXCP_TLBS; + else + exception = EXCP_TLBL; + break; + case TLBRET_DIRTY: + /* TLB match but 'D' bit is cleared */ + exception = EXCP_LTLBL; + break; + + } + /* Raise exception */ + env->CP0_BadVAddr = address; + env->CP0_Context = (env->CP0_Context & ~0x007fffff) | + ((address >> 9) & 0x007ffff0); + env->CP0_EntryHi = + (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); +#if defined(TARGET_MIPS64) + env->CP0_EntryHi &= env->SEGMask; + env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | + ((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) | + ((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9); +#endif + env->exception_index = exception; + env->error_code = error_code; +} + target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { #if defined(CONFIG_USER_ONLY) @@ -222,7 +274,6 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, target_phys_addr_t physical; int prot; #endif - int exception = 0, error_code = 0; int access_type; int ret = 0; @@ -252,51 +303,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, } else if (ret < 0) #endif { - switch (ret) { - default: - case TLBRET_BADADDR: - /* Reference to kernel address from user mode or supervisor mode */ - /* Reference to supervisor address from user mode */ - if (rw) - exception = EXCP_AdES; - else - exception = EXCP_AdEL; - break; - case TLBRET_NOMATCH: - /* No TLB match for a mapped address */ - if (rw) - exception = EXCP_TLBS; - else - exception = EXCP_TLBL; - error_code = 1; - break; - case TLBRET_INVALID: - /* TLB match with no valid bit */ - if (rw) - exception = EXCP_TLBS; - else - exception = EXCP_TLBL; - break; - case TLBRET_DIRTY: - /* TLB match but 'D' bit is cleared */ - exception = EXCP_LTLBL; - break; - - } - /* Raise exception */ - env->CP0_BadVAddr = address; - env->CP0_Context = (env->CP0_Context & ~0x007fffff) | - ((address >> 9) & 0x007ffff0); - env->CP0_EntryHi = - (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); -#if defined(TARGET_MIPS64) - env->CP0_EntryHi &= env->SEGMask; - env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | - ((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) | - ((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9); -#endif - env->exception_index = exception; - env->error_code = error_code; + raise_mmu_exception(env, address, rw, ret); ret = 1; } |