aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-sparc/helper.c4
-rw-r--r--target-sparc/op_helper.c50
2 files changed, 38 insertions, 16 deletions
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 0269d2eecc..bf28a36756 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -414,9 +414,9 @@ target_ulong mmu_probe(target_ulong address, int mmulev)
return 0;
}
+#ifdef DEBUG_MMU
void dump_mmu(void)
{
-#ifdef DEBUG_MMU
target_ulong va, va1, va2;
unsigned int n, m, o;
target_phys_addr_t pde_ptr, pa;
@@ -448,5 +448,5 @@ void dump_mmu(void)
}
}
printf("MMU dump ends\n");
-#endif
}
+#endif
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 9699d02f7c..4c65c64d67 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -105,8 +105,11 @@ void helper_ld_asi(int asi, int size, int sign)
int reg = (T0 >> 8) & 0xf;
ret = env->mmuregs[reg];
- if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/
- env->mmuregs[4] = 0;
+ if (reg == 3) /* Fault status cleared on read */
+ env->mmuregs[reg] = 0;
+#ifdef DEBUG_MMU
+ printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
+#endif
}
break;
case 0x20 ... 0x2f: /* MMU passthrough */
@@ -131,20 +134,25 @@ void helper_st_asi(int asi, int size, int sign)
int mmulev;
mmulev = (T0 >> 8) & 15;
+#ifdef DEBUG_MMU
+ printf("mmu flush level %d\n", mmulev);
+#endif
switch (mmulev) {
case 0: // flush page
- tlb_flush_page(cpu_single_env, T0 & 0xfffff000);
+ tlb_flush_page(env, T0 & 0xfffff000);
break;
case 1: // flush segment (256k)
case 2: // flush region (16M)
case 3: // flush context (4G)
case 4: // flush entire
- tlb_flush(cpu_single_env, 1);
+ tlb_flush(env, 1);
break;
default:
break;
}
+#ifdef DEBUG_MMU
dump_mmu();
+#endif
return;
}
case 4: /* write MMU regs */
@@ -152,20 +160,34 @@ void helper_st_asi(int asi, int size, int sign)
int reg = (T0 >> 8) & 0xf, oldreg;
oldreg = env->mmuregs[reg];
- if (reg == 0) {
+ switch(reg) {
+ case 0:
env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
- } else
+ if ((oldreg & MMU_E) != (env->mmuregs[reg] & MMU_E))
+ tlb_flush(env, 1);
+ break;
+ case 2:
env->mmuregs[reg] = T1;
- if (oldreg != env->mmuregs[reg]) {
-#if 0
- // XXX: Only if MMU mapping change, we may need to flush?
- tlb_flush(cpu_single_env, 1);
- cpu_loop_exit();
- FORCE_RET();
-#endif
- }
+ if (oldreg != env->mmuregs[reg]) {
+ /* we flush when the MMU context changes because
+ QEMU has no MMU context support */
+ tlb_flush(env, 1);
+ }
+ break;
+ case 3:
+ case 4:
+ break;
+ default:
+ env->mmuregs[reg] = T1;
+ break;
+ }
+#ifdef DEBUG_MMU
+ if (oldreg != env->mmuregs[reg]) {
+ printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
+ }
dump_mmu();
+#endif
return;
}
case 0x17: /* Block copy, sta access */