diff options
-rw-r--r-- | target/mips/cp0_helper.c | 27 | ||||
-rw-r--r-- | target/mips/cpu.h | 1 |
2 files changed, 22 insertions, 6 deletions
diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c index 709cc9a..a1b5140 100644 --- a/target/mips/cp0_helper.c +++ b/target/mips/cp0_helper.c @@ -892,13 +892,28 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1) void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask) { - uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1); - if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) || - (mask == 0x0000 || mask == 0x0003 || mask == 0x000F || - mask == 0x003F || mask == 0x00FF || mask == 0x03FF || - mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) { - env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1)); + uint32_t mask; + int maskbits; + + /* Don't care MASKX as we don't support 1KB page */ + mask = extract32((uint32_t)arg1, CP0PM_MASK, 16); + maskbits = cto32(mask); + + /* Ensure no more set bit after first zero */ + if ((mask >> maskbits) != 0) { + goto invalid; } + /* We don't support VTLB entry smaller than target page */ + if ((maskbits + 12) < TARGET_PAGE_BITS) { + goto invalid; + } + env->CP0_PageMask = mask << CP0PM_MASK; + + return; + +invalid: + /* When invalid, set to default target page size. */ + env->CP0_PageMask = (~TARGET_PAGE_MASK >> 12) << CP0PM_MASK; } void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index d41579d..23f8c6f 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -619,6 +619,7 @@ struct CPUMIPSState { * CP0 Register 5 */ int32_t CP0_PageMask; +#define CP0PM_MASK 13 int32_t CP0_PageGrain_rw_bitmask; int32_t CP0_PageGrain; #define CP0PG_RIE 31 |