diff options
Diffstat (limited to 'target/mips/cp0_helper.c')
-rw-r--r-- | target/mips/cp0_helper.c | 27 |
1 files changed, 21 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) |