target-mips: split code raising MMU exception in a separate function

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Aurelien Jarno 2009-11-22 13:41:18 +01:00
parent 0ae430454c
commit 1147e18994
1 changed files with 53 additions and 46 deletions

View File

@ -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;
}