summaryrefslogtreecommitdiffstats
path: root/target/mips/op_helper.c
diff options
context:
space:
mode:
authorJames Hogan2017-07-18 13:55:49 +0200
committerYongbok Kim2017-07-20 23:42:26 +0200
commit74dbf824a1313b6064bbebb981a7440951d70896 (patch)
treeecd1b2ca5ee642293b08e9527fbece6fa6298188 /target/mips/op_helper.c
parenttarget/mips: Weaken TLB flush on UX,SX,KX,ASID changes (diff)
downloadqemu-74dbf824a1313b6064bbebb981a7440951d70896.tar.gz
qemu-74dbf824a1313b6064bbebb981a7440951d70896.tar.xz
qemu-74dbf824a1313b6064bbebb981a7440951d70896.zip
target/mips: Add CP0_Ebase.WG (write gate) support
Add support for the CP0_EBase.WG bit, which allows upper bits to be written (bits 31:30 on MIPS32, or bits 63:30 on MIPS64), along with the CP0_Config5.CV bit to control whether the exception vector for Cache Error exceptions is forced into KSeg1. This is necessary on MIPS32 to support Segmentation Control and Enhanced Virtual Addressing (EVA) extensions (where KSeg1 addresses may not represent an unmapped uncached segment). It is also useful on MIPS64 to allow the exception base to reside in XKPhys, and possibly out of range of KSEG0 and KSEG1. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Yongbok Kim <yongbok.kim@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com> [yongbok.kim@imgtec.com: minor changes] Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
Diffstat (limited to 'target/mips/op_helper.c')
-rw-r--r--target/mips/op_helper.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index 091afd5ade..3b560d96b4 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -1515,14 +1515,22 @@ target_ulong helper_mftc0_ebase(CPUMIPSState *env)
void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1)
{
- env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
+ target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
+ if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
+ mask |= ~0x3FFFFFFF;
+ }
+ env->CP0_EBase = (env->CP0_EBase & ~mask) | (arg1 & mask);
}
void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1)
{
int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
- other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
+ target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
+ if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
+ mask |= ~0x3FFFFFFF;
+ }
+ other->CP0_EBase = (other->CP0_EBase & ~mask) | (arg1 & mask);
}
target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx)