diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-02-22 19:14:33 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-02-22 19:14:33 +0000 |
commit | 55754d9ef27178cf0e13aea85062fc4c32e25f83 (patch) | |
tree | 271c2866a7a1016e05d4035c83aba1f43256151c /target-sparc/op_helper.c | |
parent | afc7df11480cfbfe45e6c3db2af9d8c670ec69d9 (diff) |
MMU fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1308 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sparc/op_helper.c')
-rw-r--r-- | target-sparc/op_helper.c | 50 |
1 files changed, 36 insertions, 14 deletions
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 */ |