target-mips: split code raising MMU exception in a separate function
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
0ae430454c
commit
1147e18994
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user