aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-mips/cpu.h11
-rw-r--r--target-mips/helper.c11
-rw-r--r--target-mips/op_helper.c8
3 files changed, 29 insertions, 1 deletions
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 91e781e26a..13f3a48198 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -30,6 +30,10 @@ struct r4k_tlb_t {
uint_fast16_t V1:1;
uint_fast16_t D0:1;
uint_fast16_t D1:1;
+ uint_fast16_t XI0:1;
+ uint_fast16_t XI1:1;
+ uint_fast16_t RI0:1;
+ uint_fast16_t RI1:1;
target_ulong PFN[2];
};
@@ -229,6 +233,13 @@ struct CPUMIPSState {
#define CP0VPEOpt_DWX0 0
target_ulong CP0_EntryLo0;
target_ulong CP0_EntryLo1;
+#if defined(TARGET_MIPS64)
+# define CP0EnLo_RI 63
+# define CP0EnLo_XI 62
+#else
+# define CP0EnLo_RI 31
+# define CP0EnLo_XI 30
+#endif
target_ulong CP0_Context;
target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
int32_t CP0_PageMask;
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 1c9e69d8f4..49187a3d08 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -27,6 +27,8 @@
#include "sysemu/kvm.h"
enum {
+ TLBRET_XI = -6,
+ TLBRET_RI = -5,
TLBRET_DIRTY = -4,
TLBRET_INVALID = -3,
TLBRET_NOMATCH = -2,
@@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
/* TLB match */
int n = !!(address & mask & ~(mask >> 1));
/* Check access rights */
- if (!(n ? tlb->V1 : tlb->V0))
+ if (!(n ? tlb->V1 : tlb->V0)) {
return TLBRET_INVALID;
+ }
+ if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
+ return TLBRET_XI;
+ }
+ if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
+ return TLBRET_RI;
+ }
if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
*physical = tlb->PFN[n] | (address & (mask >> 1));
*prot = PAGE_READ;
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 9ec548cc02..582c84e1a4 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1849,10 +1849,14 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
+ tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
+ tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
+ tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
+ tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
}
@@ -1964,8 +1968,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
env->CP0_EntryHi = tlb->VPN | tlb->ASID;
env->CP0_PageMask = tlb->PageMask;
env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
+ ((target_ulong)tlb->RI0 << CP0EnLo_RI) |
+ ((target_ulong)tlb->XI0 << CP0EnLo_XI) |
(tlb->C0 << 3) | (tlb->PFN[0] >> 6);
env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
+ ((target_ulong)tlb->RI1 << CP0EnLo_RI) |
+ ((target_ulong)tlb->XI1 << CP0EnLo_XI) |
(tlb->C1 << 3) | (tlb->PFN[1] >> 6);
}