diff options
author | Maciej W. Rozycki <macro@codesourcery.com> | 2014-11-10 13:45:41 +0000 |
---|---|---|
committer | Leon Alrae <leon.alrae@imgtec.com> | 2014-12-16 12:45:19 +0000 |
commit | f88f79ec9df06d26d84e1d2e0c02d2634b4d8583 (patch) | |
tree | bb05d8347d736583dddb8375bcb371bd87eebf2e /target-mips/op_helper.c | |
parent | c3577479815f5bcf9d38993967bca2115af245d8 (diff) |
target-mips: Correct the handling of writes to CP0.Status for MIPSr6
Correct these issues with the handling of CP0.Status for MIPSr6:
* only ignore the bit pattern of 0b11 on writes to CP0.Status.KSU, that
is for processors that do implement Supervisor Mode, let the bit
pattern be written to CP0.Status.UM:R0 freely (of course the value
written to read-only CP0.Status.R0 will be discarded anyway); this is
in accordance to the relevant architecture specification[1],
* check the newly written pattern rather than the current contents of
CP0.Status for the KSU bits being 0b11,
* use meaningful macro names to refer to CP0.Status bits rather than
magic numbers.
References:
[1] "MIPS Architecture For Programmers, Volume III: MIPS64 / microMIPS64
Privileged Resource Architecture", MIPS Technologies, Inc., Document
Number: MD00091, Revision 6.00, March 31, 2014, Table 9.45 "Status
Register Field Descriptions", pp. 210-211.
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
Diffstat (limited to 'target-mips/op_helper.c')
-rw-r--r-- | target-mips/op_helper.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index d25424f5bf..a0cc729526 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1423,10 +1423,12 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1) uint32_t mask = env->CP0_Status_rw_bitmask; if (env->insn_flags & ISA_MIPS32R6) { - if (extract32(env->CP0_Status, CP0St_KSU, 2) == 0x3) { + bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3; + + if (has_supervisor && extract32(arg1, CP0St_KSU, 2) == 0x3) { mask &= ~(3 << CP0St_KSU); } - mask &= ~(0x00180000 & arg1); + mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & arg1); } val = arg1 & mask; |