diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 38f90f27f4..a9e1bc2eb4 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -247,6 +247,7 @@ struct CPUMIPSState { int32_t CP0_PageGrain; #define CP0PG_RIE 31 #define CP0PG_XIE 30 +#define CP0PG_IEC 27 int32_t CP0_Wired; int32_t CP0_SRSConf0_rw_bitmask; int32_t CP0_SRSConf0; @@ -646,8 +647,10 @@ enum { EXCP_C2E, EXCP_CACHE, /* 32 */ EXCP_DSPDIS, + EXCP_TLBXI, + EXCP_TLBRI, - EXCP_LAST = EXCP_DSPDIS, + EXCP_LAST = EXCP_TLBRI, }; /* Dummy exception for conditional stores. */ #define EXCP_SC 0x100 diff --git a/target-mips/helper.c b/target-mips/helper.c index 49187a3d08..37038ef799 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -273,7 +273,22 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, /* TLB match but 'D' bit is cleared */ exception = EXCP_LTLBL; break; - + case TLBRET_XI: + /* Execute-Inhibit Exception */ + if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { + exception = EXCP_TLBXI; + } else { + exception = EXCP_TLBL; + } + break; + case TLBRET_RI: + /* Read-Inhibit Exception */ + if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { + exception = EXCP_TLBRI; + } else { + exception = EXCP_TLBL; + } + break; } /* Raise exception */ env->CP0_BadVAddr = address; @@ -404,6 +419,8 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_MDMX] = "MDMX", [EXCP_C2E] = "precise coprocessor 2", [EXCP_CACHE] = "cache error", + [EXCP_TLBXI] = "TLB execute-inhibit", + [EXCP_TLBRI] = "TLB read-inhibit", }; target_ulong exception_resume_pc (CPUMIPSState *env) @@ -622,6 +639,12 @@ void mips_cpu_do_interrupt(CPUState *cs) case EXCP_C2E: cause = 18; goto set_EPC; + case EXCP_TLBRI: + cause = 19; + goto set_EPC; + case EXCP_TLBXI: + cause = 20; + goto set_EPC; case EXCP_MDMX: cause = 22; goto set_EPC;