?? helper.c
字號:
return -1; case POWERPC_MMU_BOOKE_FSL: /* XXX: TODO */ cpu_abort(env, "BookE FSL MMU model is not implemented\n"); return -1; case POWERPC_MMU_REAL: cpu_abort(env, "PowerPC in real mode should never raise " "any MMU exceptions\n"); return -1; default: cpu_abort(env, "Unknown or invalid MMU model\n"); return -1; } break; case -2: /* Access rights violation */ env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; if (rw == 1) env->spr[SPR_DSISR] = 0x0A000000; else env->spr[SPR_DSISR] = 0x08000000; break; case -4: /* Direct store exception */ switch (access_type) { case ACCESS_FLOAT: /* Floating point load/store */ env->exception_index = POWERPC_EXCP_ALIGN; env->error_code = POWERPC_EXCP_ALIGN_FP; env->spr[SPR_DAR] = address; break; case ACCESS_RES: /* lwarx, ldarx or stwcx. */ env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; if (rw == 1) env->spr[SPR_DSISR] = 0x06000000; else env->spr[SPR_DSISR] = 0x04000000; break; case ACCESS_EXT: /* eciwx or ecowx */ env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; if (rw == 1) env->spr[SPR_DSISR] = 0x06100000; else env->spr[SPR_DSISR] = 0x04100000; break; default: printf("DSI: invalid exception (%d)\n", ret); env->exception_index = POWERPC_EXCP_PROGRAM; env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; env->spr[SPR_DAR] = address; break; } break;#if defined(TARGET_PPC64) case -5: /* No match in segment table */ if (env->mmu_model == POWERPC_MMU_620) { env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; /* XXX: this might be incorrect */ if (rw == 1) env->spr[SPR_DSISR] = 0x42000000; else env->spr[SPR_DSISR] = 0x40000000; } else { env->exception_index = POWERPC_EXCP_DSEG; env->error_code = 0; env->spr[SPR_DAR] = address; } break;#endif } }#if 0 printf("%s: set exception to %d %02x\n", __func__, env->exception, env->error_code);#endif ret = 1; } return ret;}/*****************************************************************************//* BATs management */#if !defined(FLUSH_ALL_TLBS)static always_inline void do_invalidate_BAT (CPUPPCState *env, target_ulong BATu, target_ulong mask){ target_ulong base, end, page; base = BATu & ~0x0001FFFF; end = base + mask + 0x00020000;#if defined (DEBUG_BATS) if (loglevel != 0) { fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n", base, end, mask); }#endif for (page = base; page != end; page += TARGET_PAGE_SIZE) tlb_flush_page(env, page);#if defined (DEBUG_BATS) if (loglevel != 0) fprintf(logfile, "Flush done\n");#endif}#endifstatic always_inline void dump_store_bat (CPUPPCState *env, char ID, int ul, int nr, target_ulong value){#if defined (DEBUG_BATS) if (loglevel != 0) { fprintf(logfile, "Set %cBAT%d%c to " ADDRX " (" ADDRX ")\n", ID, nr, ul == 0 ? 'u' : 'l', value, env->nip); }#endif}target_ulong do_load_ibatu (CPUPPCState *env, int nr){ return env->IBAT[0][nr];}target_ulong do_load_ibatl (CPUPPCState *env, int nr){ return env->IBAT[1][nr];}void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value){ target_ulong mask; dump_store_bat(env, 'I', 0, nr, value); if (env->IBAT[0][nr] != value) { mask = (value << 15) & 0x0FFE0000UL;#if !defined(FLUSH_ALL_TLBS) do_invalidate_BAT(env, env->IBAT[0][nr], mask);#endif /* When storing valid upper BAT, mask BEPI and BRPN * and invalidate all TLBs covered by this BAT */ mask = (value << 15) & 0x0FFE0000UL; env->IBAT[0][nr] = (value & 0x00001FFFUL) | (value & ~0x0001FFFFUL & ~mask); env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) | (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);#if !defined(FLUSH_ALL_TLBS) do_invalidate_BAT(env, env->IBAT[0][nr], mask);#else tlb_flush(env, 1);#endif }}void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value){ dump_store_bat(env, 'I', 1, nr, value); env->IBAT[1][nr] = value;}target_ulong do_load_dbatu (CPUPPCState *env, int nr){ return env->DBAT[0][nr];}target_ulong do_load_dbatl (CPUPPCState *env, int nr){ return env->DBAT[1][nr];}void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value){ target_ulong mask; dump_store_bat(env, 'D', 0, nr, value); if (env->DBAT[0][nr] != value) { /* When storing valid upper BAT, mask BEPI and BRPN * and invalidate all TLBs covered by this BAT */ mask = (value << 15) & 0x0FFE0000UL;#if !defined(FLUSH_ALL_TLBS) do_invalidate_BAT(env, env->DBAT[0][nr], mask);#endif mask = (value << 15) & 0x0FFE0000UL; env->DBAT[0][nr] = (value & 0x00001FFFUL) | (value & ~0x0001FFFFUL & ~mask); env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) | (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);#if !defined(FLUSH_ALL_TLBS) do_invalidate_BAT(env, env->DBAT[0][nr], mask);#else tlb_flush(env, 1);#endif }}void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value){ dump_store_bat(env, 'D', 1, nr, value); env->DBAT[1][nr] = value;}void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value){ target_ulong mask; int do_inval; dump_store_bat(env, 'I', 0, nr, value); if (env->IBAT[0][nr] != value) { do_inval = 0; mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL; if (env->IBAT[1][nr] & 0x40) { /* Invalidate BAT only if it is valid */#if !defined(FLUSH_ALL_TLBS) do_invalidate_BAT(env, env->IBAT[0][nr], mask);#else do_inval = 1;#endif } /* When storing valid upper BAT, mask BEPI and BRPN * and invalidate all TLBs covered by this BAT */ env->IBAT[0][nr] = (value & 0x00001FFFUL) | (value & ~0x0001FFFFUL & ~mask); env->DBAT[0][nr] = env->IBAT[0][nr]; if (env->IBAT[1][nr] & 0x40) {#if !defined(FLUSH_ALL_TLBS) do_invalidate_BAT(env, env->IBAT[0][nr], mask);#else do_inval = 1;#endif }#if defined(FLUSH_ALL_TLBS) if (do_inval) tlb_flush(env, 1);#endif }}void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value){ target_ulong mask; int do_inval; dump_store_bat(env, 'I', 1, nr, value); if (env->IBAT[1][nr] != value) { do_inval = 0; if (env->IBAT[1][nr] & 0x40) {#if !defined(FLUSH_ALL_TLBS) mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL; do_invalidate_BAT(env, env->IBAT[0][nr], mask);#else do_inval = 1;#endif } if (value & 0x40) {#if !defined(FLUSH_ALL_TLBS) mask = (value << 17) & 0x0FFE0000UL; do_invalidate_BAT(env, env->IBAT[0][nr], mask);#else do_inval = 1;#endif } env->IBAT[1][nr] = value; env->DBAT[1][nr] = value;#if defined(FLUSH_ALL_TLBS) if (do_inval) tlb_flush(env, 1);#endif }}/*****************************************************************************//* TLB management */void ppc_tlb_invalidate_all (CPUPPCState *env){ switch (env->mmu_model) { case POWERPC_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_74xx: ppc6xx_tlb_invalidate_all(env); break; case POWERPC_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx_Z: ppc4xx_tlb_invalidate_all(env); break; case POWERPC_MMU_REAL: cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n"); break; case POWERPC_MMU_MPC8xx: /* XXX: TODO */ cpu_abort(env, "MPC8xx MMU model is not implemented\n"); break; case POWERPC_MMU_BOOKE: /* XXX: TODO */ cpu_abort(env, "BookE MMU model is not implemented\n"); break; case POWERPC_MMU_BOOKE_FSL: /* XXX: TODO */ cpu_abort(env, "BookE MMU model is not implemented\n"); break; case POWERPC_MMU_32B: case POWERPC_MMU_601:#if defined(TARGET_PPC64) case POWERPC_MMU_620: case POWERPC_MMU_64B:#endif /* defined(TARGET_PPC64) */ tlb_flush(env, 1); break; default: /* XXX: TODO */ cpu_abort(env, "Unknown MMU model\n"); break; }}void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr){#if !defined(FLUSH_ALL_TLBS) addr &= TARGET_PAGE_MASK; switch (env->mmu_model) { case POWERPC_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_74xx: ppc6xx_tlb_invalidate_virt(env, addr, 0); if (env->id_tlbs == 1) ppc6xx_tlb_invalidate_virt(env, addr, 1); break; case POWERPC_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx_Z: ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]); break; case POWERPC_MMU_REAL: cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n"); break; case POWERPC_MMU_MPC8xx: /* XXX: TODO */ cpu_abort(env, "MPC8xx MMU model is not implemented\n"); break; case POWERPC_MMU_BOOKE: /* XXX: TODO */ cpu_abort(env, "BookE MMU model is not implemented\n"); break; case POWERPC_MMU_BOOKE_FSL: /* XXX: TODO */ cpu_abort(env, "BookE FSL MMU model is not implemented\n"); break; case POWERPC_MMU_32B: case POWERPC_MMU_601: /* tlbie invalidate TLBs for all segments */ addr &= ~((target_ulong)-1ULL << 28); /* XXX: this case should be optimized, * giving a mask to tlb_flush_page */ tlb_flush_page(env, addr | (0x0 << 28)); tlb_flush_page(env, addr | (0x1 << 28)); tlb_flush_page(env, addr | (0x2 << 28)); tlb_flush_page(env, addr | (0x3 << 28)); tlb_flush_page(env, addr | (0x4 << 28)); tlb_flush_page(env, addr | (0x5 << 28)); tlb_flush_page(env, addr | (0x6 << 28)); tlb_flush_page(env, addr | (0x7 << 28)); tlb_flush_page(env, addr | (0x8 << 28)); tlb_flush_page(env, addr | (0x9 << 28)); tlb_flush_page(env, addr | (0xA << 28)); tlb_flush_page(env, addr | (0xB << 28)); tlb_flush_page(env, addr | (0xC << 28)); tlb_flush_page(env, addr | (0xD << 28)); tlb_flush_page(env, addr | (0xE << 28)); tlb_flush_page(env, addr | (0xF << 28)); break;#if defined(TARGET_PPC64) case POWERPC_MMU_620: case POWERPC_MMU_64B: /* tlbie invalidate TLBs for all segments */ /* XXX: given the fact that there are too many segments to invalidate, * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu, * we just invalidate all TLBs */ tlb_flush(env, 1); break;#endif /* defined(TARGET_PPC64) */ default: /* XXX: TODO */ cpu_abort(env, "Unknown MMU model\n"); break; }#else ppc_tlb_invalidate_all(env);#endif}/*****************************************************************************//* Special registers manipulation */#if defined(TARGET_PPC64)target_ulong ppc_load_asr (CPUPPCState *env){ return env->asr;}void ppc_store_asr (CPUPPCState *env, target_ulong value){ if (env->asr != value)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -