aboutsummaryrefslogtreecommitdiff
path: root/target/mips/helper.c
diff options
context:
space:
mode:
authorYongbok Kim <yongbok.kim@mips.com>2019-12-20 10:29:34 +0100
committerAleksandar Markovic <amarkovic@wavecomp.com>2020-01-29 19:28:52 +0100
commit99029be1c2875cd857614397674bbf563ddb6f91 (patch)
tree28c1dde351decde94f717efd13a1db2db8bd561d /target/mips/helper.c
parentfeafe82cc2289a31b3e3f11dc76f3539ea22d670 (diff)
target/mips: Add implementation of GINVT instruction
Implement emulation of GINVT instruction. As QEMU doesn't support caches and virtualization, this implementation covers only one instruction (GINVT - Global Invalidate TLB) among all TLB-related MIPS instructions. Reviewed-by: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com> Signed-off-by: Yongbok Kim <yongbok.kim@mips.com> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> Message-Id: <1579883929-1517-5-git-send-email-aleksandar.markovic@rt-rk.com>
Diffstat (limited to 'target/mips/helper.c')
-rw-r--r--target/mips/helper.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/target/mips/helper.c b/target/mips/helper.c
index 781930a7dd..afd78b1990 100644
--- a/target/mips/helper.c
+++ b/target/mips/helper.c
@@ -72,8 +72,13 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
target_ulong address, int rw, int access_type)
{
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+ uint32_t MMID = env->CP0_MemoryMapID;
+ bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
+ uint32_t tlb_mmid;
int i;
+ MMID = mi ? MMID : (uint32_t) ASID;
+
for (i = 0; i < env->tlb->tlb_in_use; i++) {
r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
/* 1k pages are not supported. */
@@ -84,8 +89,9 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
tag &= env->SEGMask;
#endif
- /* Check ASID, virtual page number & size */
- if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
+ /* Check ASID/MMID, virtual page number & size */
+ tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
+ if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) {
/* TLB match */
int n = !!(address & mask & ~(mask >> 1));
/* Check access rights */
@@ -1418,14 +1424,20 @@ void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra)
target_ulong addr;
target_ulong end;
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+ uint32_t MMID = env->CP0_MemoryMapID;
+ bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
+ uint32_t tlb_mmid;
target_ulong mask;
+ MMID = mi ? MMID : (uint32_t) ASID;
+
tlb = &env->tlb->mmu.r4k.tlb[idx];
/*
- * The qemu TLB is flushed when the ASID changes, so no need to
+ * The qemu TLB is flushed when the ASID/MMID changes, so no need to
* flush these entries again.
*/
- if (tlb->G == 0 && tlb->ASID != ASID) {
+ tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
+ if (tlb->G == 0 && tlb_mmid != MMID) {
return;
}