diff options
-rw-r--r-- | target-sparc/helper.c | 4 | ||||
-rw-r--r-- | target-sparc/op_helper.c | 50 |
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 */ |