diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-10-25 21:35:50 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-10-25 21:35:50 +0000 |
commit | 0411a9725829d626bb0b2f11a461463c96061682 (patch) | |
tree | 105135188a4e2af4e3cf44518f5e2b14a7e83e01 /target-ppc/helper.c | |
parent | 7ac256b8725304aabae78bf012c25b6416509c46 (diff) |
Gprof prooved the PowerPC emulation spent too much time in MSR load and store
routines. Coming back to a raw MSR storage model then speed-up the emulation.
Improve fast MSR updates (wrtee wrteei and mtriee cases).
Share rfi family instructions helpers code to avoid bug in duplicated code.
Allow entering halt mode as the result of a rfi instruction.
Add a new helper_regs.h file to avoid duplication of special registers
manipulation routines (currently XER and MSR).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3436 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/helper.c')
-rw-r--r-- | target-ppc/helper.c | 418 |
1 files changed, 137 insertions, 281 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 76312476a0..ea672bb4a2 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -27,10 +27,12 @@ #include "cpu.h" #include "exec-all.h" +#include "helper_regs.h" //#define DEBUG_MMU //#define DEBUG_BATS //#define DEBUG_SOFTWARE_TLB +//#define DUMP_PAGE_TABLES //#define DEBUG_EXCEPTIONS //#define FLUSH_ALL_TLBS @@ -447,7 +449,7 @@ static int get_bat (CPUState *env, mmu_ctx_t *ctx, { target_ulong *BATlt, *BATut, *BATu, *BATl; target_ulong base, BEPIl, BEPIu, bl; - int i, pp; + int i, pp, pr; int ret = -1; #if defined (DEBUG_BATS) @@ -456,6 +458,7 @@ static int get_bat (CPUState *env, mmu_ctx_t *ctx, type == ACCESS_CODE ? 'I' : 'D', virtual); } #endif + pr = msr_pr; switch (type) { case ACCESS_CODE: BATlt = env->IBAT[1]; @@ -490,8 +493,8 @@ static int get_bat (CPUState *env, mmu_ctx_t *ctx, if ((virtual & 0xF0000000) == BEPIu && ((virtual & 0x0FFE0000) & ~bl) == BEPIl) { /* BAT matches */ - if ((msr_pr == 0 && (*BATu & 0x00000002)) || - (msr_pr == 1 && (*BATu & 0x00000001))) { + if (((pr == 0) && (*BATu & 0x00000002)) || + ((pr != 0) && (*BATu & 0x00000001))) { /* Get physical address */ ctx->raddr = (*BATl & 0xF0000000) | ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) | @@ -851,9 +854,10 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, #if defined(TARGET_PPC64) int attr; #endif - int ds, vsid_sh, sdr_sh; + int ds, vsid_sh, sdr_sh, pr; int ret, ret2; + pr = msr_pr; #if defined(TARGET_PPC64) if (env->mmu_model == POWERPC_MMU_64B) { #if defined (DEBUG_MMU) @@ -864,8 +868,8 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); if (ret < 0) return ret; - ctx->key = ((attr & 0x40) && msr_pr == 1) || - ((attr & 0x80) && msr_pr == 0) ? 1 : 0; + ctx->key = ((attr & 0x40) && (pr != 0)) || + ((attr & 0x80) && (pr == 0)) ? 1 : 0; ds = 0; ctx->nx = attr & 0x20 ? 1 : 0; vsid_mask = 0x00003FFFFFFFFF80ULL; @@ -877,8 +881,8 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, { sr = env->sr[eaddr >> 28]; page_mask = 0x0FFFFFFF; - ctx->key = (((sr & 0x20000000) && msr_pr == 1) || - ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0; + ctx->key = (((sr & 0x20000000) && (pr != 0)) || + ((sr & 0x40000000) && (pr == 0))) ? 1 : 0; ds = sr & 0x80000000 ? 1 : 0; ctx->nx = sr & 0x10000000 ? 1 : 0; vsid = sr & 0x00FFFFFF; @@ -892,7 +896,8 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, " nip=0x" ADDRX " lr=0x" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n", eaddr, (int)(eaddr >> 28), sr, env->nip, - env->lr, msr_ir, msr_dr, msr_pr, rw, type); + env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0, + rw, type); } #endif } @@ -981,7 +986,7 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, ret = ret2; } } -#if defined (DEBUG_MMU) +#if defined (DUMP_PAGE_TABLES) if (loglevel != 0) { target_phys_addr_t curaddr; uint32_t a0, a1, a2, a3; @@ -1157,10 +1162,11 @@ int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx, { ppcemb_tlb_t *tlb; target_phys_addr_t raddr; - int i, ret, zsel, zpr; + int i, ret, zsel, zpr, pr; ret = -1; raddr = -1; + pr = msr_pr; for (i = 0; i < env->nb_tlb; i++) { tlb = &env->tlb[i].tlbe; if (ppcemb_tlb_check(env, tlb, &raddr, address, @@ -1177,7 +1183,7 @@ int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx, /* Check execute enable bit */ switch (zpr) { case 0x2: - if (msr_pr) + if (pr != 0) goto check_perms; /* No break here */ case 0x3: @@ -1186,7 +1192,7 @@ int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx, ret = 0; break; case 0x0: - if (msr_pr) { + if (pr != 0) { ctx->prot = 0; ret = -2; break; @@ -1248,7 +1254,7 @@ int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx, if (ppcemb_tlb_check(env, tlb, &raddr, address, env->spr[SPR_BOOKE_PID], 1, i) < 0) continue; - if (msr_pr) + if (msr_pr != 0) prot = tlb->prot & 0xF; else prot = (tlb->prot >> 4) & 0xF; @@ -1343,6 +1349,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, int rw, int access_type, int check_BATs) { int ret; + #if 0 if (loglevel != 0) { fprintf(logfile, "%s\n", __func__); @@ -1949,180 +1956,18 @@ void do_store_sr (CPUPPCState *env, int srnum, target_ulong value) target_ulong ppc_load_xer (CPUPPCState *env) { - return (xer_so << XER_SO) | - (xer_ov << XER_OV) | - (xer_ca << XER_CA) | - (xer_bc << XER_BC) | - (xer_cmp << XER_CMP); + return hreg_load_xer(env); } void ppc_store_xer (CPUPPCState *env, target_ulong value) { - xer_so = (value >> XER_SO) & 0x01; - xer_ov = (value >> XER_OV) & 0x01; - xer_ca = (value >> XER_CA) & 0x01; - xer_cmp = (value >> XER_CMP) & 0xFF; - xer_bc = (value >> XER_BC) & 0x7F; -} - -/* Swap temporary saved registers with GPRs */ -static always_inline void swap_gpr_tgpr (CPUPPCState *env) -{ - ppc_gpr_t tmp; - - tmp = env->gpr[0]; - env->gpr[0] = env->tgpr[0]; - env->tgpr[0] = tmp; - tmp = env->gpr[1]; - env->gpr[1] = env->tgpr[1]; - env->tgpr[1] = tmp; - tmp = env->gpr[2]; - env->gpr[2] = env->tgpr[2]; - env->tgpr[2] = tmp; - tmp = env->gpr[3]; - env->gpr[3] = env->tgpr[3]; - env->tgpr[3] = tmp; + hreg_store_xer(env, value); } /* GDBstub can read and write MSR... */ -target_ulong do_load_msr (CPUPPCState *env) -{ - return -#if defined (TARGET_PPC64) - ((target_ulong)msr_sf << MSR_SF) | - ((target_ulong)msr_isf << MSR_ISF) | - ((target_ulong)msr_hv << MSR_HV) | -#endif - ((target_ulong)msr_ucle << MSR_UCLE) | - ((target_ulong)msr_vr << MSR_VR) | /* VR / SPE */ - ((target_ulong)msr_ap << MSR_AP) | - ((target_ulong)msr_sa << MSR_SA) | - ((target_ulong)msr_key << MSR_KEY) | - ((target_ulong)msr_pow << MSR_POW) | - ((target_ulong)msr_tgpr << MSR_TGPR) | /* TGPR / CE */ - ((target_ulong)msr_ile << MSR_ILE) | - ((target_ulong)msr_ee << MSR_EE) | - ((target_ulong)msr_pr << MSR_PR) | - ((target_ulong)msr_fp << MSR_FP) | - ((target_ulong)msr_me << MSR_ME) | - ((target_ulong)msr_fe0 << MSR_FE0) | - ((target_ulong)msr_se << MSR_SE) | /* SE / DWE / UBLE */ - ((target_ulong)msr_be << MSR_BE) | /* BE / DE */ - ((target_ulong)msr_fe1 << MSR_FE1) | - ((target_ulong)msr_al << MSR_AL) | - ((target_ulong)msr_ep << MSR_EP) | - ((target_ulong)msr_ir << MSR_IR) | - ((target_ulong)msr_dr << MSR_DR) | - ((target_ulong)msr_pe << MSR_PE) | - ((target_ulong)msr_px << MSR_PX) | /* PX / PMM */ - ((target_ulong)msr_ri << MSR_RI) | - ((target_ulong)msr_le << MSR_LE); -} - -int do_store_msr (CPUPPCState *env, target_ulong value) -{ - int enter_pm; - - value &= env->msr_mask; - if (((value >> MSR_IR) & 1) != msr_ir || - ((value >> MSR_DR) & 1) != msr_dr) { - /* Flush all tlb when changing translation mode */ - tlb_flush(env, 1); - env->interrupt_request |= CPU_INTERRUPT_EXITTB; - } -#if !defined (CONFIG_USER_ONLY) - if (unlikely((env->flags & POWERPC_FLAG_TGPR) && - ((value >> MSR_TGPR) & 1) != msr_tgpr)) { - /* Swap temporary saved registers with GPRs */ - swap_gpr_tgpr(env); - } - if (unlikely((value >> MSR_EP) & 1) != msr_ep) { - /* Change the exception prefix on PowerPC 601 */ - env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000; - } -#endif -#if defined (TARGET_PPC64) - msr_sf = (value >> MSR_SF) & 1; - msr_isf = (value >> MSR_ISF) & 1; - msr_hv = (value >> MSR_HV) & 1; -#endif - msr_ucle = (value >> MSR_UCLE) & 1; - msr_vr = (value >> MSR_VR) & 1; /* VR / SPE */ - msr_ap = (value >> MSR_AP) & 1; - msr_sa = (value >> MSR_SA) & 1; - msr_key = (value >> MSR_KEY) & 1; - msr_pow = (value >> MSR_POW) & 1; - msr_tgpr = (value >> MSR_TGPR) & 1; /* TGPR / CE */ - msr_ile = (value >> MSR_ILE) & 1; - msr_ee = (value >> MSR_EE) & 1; - msr_pr = (value >> MSR_PR) & 1; - msr_fp = (value >> MSR_FP) & 1; - msr_me = (value >> MSR_ME) & 1; - msr_fe0 = (value >> MSR_FE0) & 1; - msr_se = (value >> MSR_SE) & 1; /* SE / DWE / UBLE */ - msr_be = (value >> MSR_BE) & 1; /* BE / DE */ - msr_fe1 = (value >> MSR_FE1) & 1; - msr_al = (value >> MSR_AL) & 1; - msr_ep = (value >> MSR_EP) & 1; - msr_ir = (value >> MSR_IR) & 1; - msr_dr = (value >> MSR_DR) & 1; - msr_pe = (value >> MSR_PE) & 1; - msr_px = (value >> MSR_PX) & 1; /* PX / PMM */ - msr_ri = (value >> MSR_RI) & 1; - msr_le = (value >> MSR_LE) & 1; - do_compute_hflags(env); - - enter_pm = 0; - switch (env->excp_model) { - case POWERPC_EXCP_603: - case POWERPC_EXCP_603E: - case POWERPC_EXCP_G2: - /* Don't handle SLEEP mode: we should disable all clocks... - * No dynamic power-management. - */ - if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00C00000) != 0) - enter_pm = 1; - break; - case POWERPC_EXCP_604: - if (msr_pow == 1) - enter_pm = 1; - break; - case POWERPC_EXCP_7x0: - if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0) - enter_pm = 1; - break; - default: - break; - } - - return enter_pm; -} - -#if defined(TARGET_PPC64) -int ppc_store_msr_32 (CPUPPCState *env, uint32_t value) -{ - return do_store_msr(env, (do_load_msr(env) & ~0xFFFFFFFFULL) | - (value & 0xFFFFFFFF)); -} -#endif - -void do_compute_hflags (CPUPPCState *env) +void ppc_store_msr (CPUPPCState *env, target_ulong value) { - /* Compute current hflags */ - env->hflags = (msr_vr << MSR_VR) | - (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | (msr_pr << MSR_PR) | - (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_se << MSR_SE) | - (msr_be << MSR_BE) | (msr_fe1 << MSR_FE1) | (msr_le << MSR_LE); -#if defined (TARGET_PPC64) - env->hflags |= msr_cm << MSR_CM; - env->hflags |= (uint64_t)msr_sf << MSR_SF; - env->hflags |= (uint64_t)msr_hv << MSR_HV; - /* Precompute MMU index */ - if (msr_pr == 0 && msr_hv == 1) - env->mmu_idx = 2; - else -#endif - env->mmu_idx = 1 - msr_pr; + hreg_store_msr(env, value); } /*****************************************************************************/ @@ -2154,14 +1999,15 @@ static void dump_syscall (CPUState *env) static always_inline void powerpc_excp (CPUState *env, int excp_model, int excp) { - target_ulong msr, vector; + target_ulong msr, new_msr, vector; int srr0, srr1, asrr0, asrr1; if (loglevel & CPU_LOG_INT) { fprintf(logfile, "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n", env->nip, excp, env->error_code); } - msr = do_load_msr(env); + msr = env->msr; + new_msr = msr; srr0 = SPR_SRR0; srr1 = SPR_SRR1; asrr0 = -1; @@ -2172,7 +2018,7 @@ static always_inline void powerpc_excp (CPUState *env, /* Should never happen */ return; case POWERPC_EXCP_CRITICAL: /* Critical input */ - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ switch (excp_model) { case POWERPC_EXCP_40x: srr0 = SPR_40x_SRR2; @@ -2203,10 +2049,10 @@ static always_inline void powerpc_excp (CPUState *env, env->halted = 1; env->interrupt_request |= CPU_INTERRUPT_EXITTB; } - msr_ri = 0; - msr_me = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); + new_msr &= ~((target_ulong)1 << MSR_ME); #if defined(TARGET_PPC64H) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif /* XXX: should also have something loaded in DAR / DSISR */ switch (excp_model) { @@ -2231,10 +2077,10 @@ static always_inline void powerpc_excp (CPUState *env, "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); } #endif - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_next; case POWERPC_EXCP_ISI: /* Instruction storage exception */ @@ -2244,25 +2090,25 @@ static always_inline void powerpc_excp (CPUState *env, "\n", msr, env->nip); } #endif - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif msr |= env->error_code; goto store_next; case POWERPC_EXCP_EXTERNAL: /* External input */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes0 == 1) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_next; case POWERPC_EXCP_ALIGN: /* Alignment exception */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif /* XXX: this is false */ /* Get rS/rD and rA from faulting opcode */ @@ -2279,10 +2125,10 @@ static always_inline void powerpc_excp (CPUState *env, #endif return; } - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif msr |= 0x00100000; /* Set FX */ @@ -2303,26 +2149,26 @@ static always_inline void powerpc_excp (CPUState *env, env->nip); } #endif - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif msr |= 0x00080000; break; case POWERPC_EXCP_PRIV: - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif msr |= 0x00040000; break; case POWERPC_EXCP_TRAP: - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif msr |= 0x00020000; break; @@ -2334,10 +2180,10 @@ static always_inline void powerpc_excp (CPUState *env, } goto store_next; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_current; case POWERPC_EXCP_SYSCALL: /* System call exception */ @@ -2352,20 +2198,20 @@ static always_inline void powerpc_excp (CPUState *env, if (loglevel & CPU_LOG_INT) { dump_syscall(env); } - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_next; case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); goto store_current; case POWERPC_EXCP_DECR: /* Decrementer exception */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_next; case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ @@ -2374,7 +2220,7 @@ static always_inline void powerpc_excp (CPUState *env, if (loglevel != 0) fprintf(logfile, "FIT exception\n"); #endif - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ #if defined (DEBUG_EXCEPTIONS) @@ -2389,13 +2235,13 @@ static always_inline void powerpc_excp (CPUState *env, default: break; } - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_DTLB: /* Data TLB error */ - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_ITLB: /* Instruction TLB error */ - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_DEBUG: /* Debug interrupt */ switch (excp_model) { @@ -2413,7 +2259,7 @@ static always_inline void powerpc_excp (CPUState *env, goto store_next; #if defined(TARGET_PPCEMB) case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */ - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_current; case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ /* XXX: TODO */ @@ -2426,7 +2272,7 @@ static always_inline void powerpc_excp (CPUState *env, "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: TODO */ cpu_abort(env, "Performance counter exception is not implemented yet !\n"); @@ -2451,24 +2297,24 @@ static always_inline void powerpc_excp (CPUState *env, goto store_next; #endif /* defined(TARGET_PPCEMB) */ case POWERPC_EXCP_RESET: /* System reset exception */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_next; #if defined(TARGET_PPC64) case POWERPC_EXCP_DSEG: /* Data segment exception */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_next; case POWERPC_EXCP_ISEG: /* Instruction segment exception */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_next; #endif /* defined(TARGET_PPC64) */ @@ -2476,46 +2322,43 @@ static always_inline void powerpc_excp (CPUState *env, case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ srr0 = SPR_HSRR0; srr1 = SPR_HSSR1; - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; goto store_next; #endif case POWERPC_EXCP_TRACE: /* Trace exception */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_next; #if defined(TARGET_PPC64H) case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ srr0 = SPR_HSRR0; srr1 = SPR_HSSR1; - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; goto store_next; case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ srr0 = SPR_HSRR0; srr1 = SPR_HSSR1; - msr_hv = 1; - /* XXX: TODO */ - cpu_abort(env, "Hypervisor instruction storage exception " - "is not implemented yet !\n"); + new_msr |= (target_ulong)1 << MSR_HV; goto store_next; case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ srr0 = SPR_HSRR0; srr1 = SPR_HSSR1; - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; goto store_next; case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ srr0 = SPR_HSRR0; srr1 = SPR_HSSR1; - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; goto store_next; #endif /* defined(TARGET_PPC64H) */ case POWERPC_EXCP_VPU: /* Vector unavailable exception */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif goto store_current; case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ @@ -2523,7 +2366,7 @@ static always_inline void powerpc_excp (CPUState *env, if (loglevel != 0) fprintf(logfile, "PIT exception\n"); #endif - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_IO: /* IO error exception */ /* XXX: TODO */ @@ -2539,10 +2382,10 @@ static always_inline void powerpc_excp (CPUState *env, "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ #if defined(TARGET_PPC64H) /* XXX: check this */ if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif switch (excp_model) { case POWERPC_EXCP_602: @@ -2560,10 +2403,10 @@ static always_inline void powerpc_excp (CPUState *env, } break; case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ #if defined(TARGET_PPC64H) /* XXX: check this */ if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif switch (excp_model) { case POWERPC_EXCP_602: @@ -2581,10 +2424,10 @@ static always_inline void powerpc_excp (CPUState *env, } break; case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ - msr_ri = 0; /* XXX: check this */ + new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ #if defined(TARGET_PPC64H) /* XXX: check this */ if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif switch (excp_model) { case POWERPC_EXCP_602: @@ -2593,8 +2436,10 @@ static always_inline void powerpc_excp (CPUState *env, case POWERPC_EXCP_G2: tlb_miss_tgpr: /* Swap temporary saved registers with GPRs */ - swap_gpr_tgpr(env); - msr_tgpr = 1; + if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { + new_msr |= (target_ulong)1 << MSR_TGPR; + hreg_swap_gpr_tgpr(env); + } goto tlb_miss; case POWERPC_EXCP_7x5: tlb_miss: @@ -2639,8 +2484,8 @@ static always_inline void powerpc_excp (CPUState *env, if (excp == POWERPC_EXCP_IFTLB) { es = "I"; en = 'I'; - miss = &env->spr[SPR_IMISS]; - cmp = &env->spr[SPR_ICMP]; + miss = &env->spr[SPR_TLBMISS]; + cmp = &env->spr[SPR_PTEHI]; } else { if (excp == POWERPC_EXCP_DLTLB) es = "DL"; @@ -2681,10 +2526,10 @@ static always_inline void powerpc_excp (CPUState *env, "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ - msr_ri = 0; + new_msr &= ~((target_ulong)1 << MSR_RI); #if defined(TARGET_PPC64H) if (lpes1 == 0) - msr_hv = 1; + new_msr |= (target_ulong)1 << MSR_HV; #endif /* XXX: TODO */ cpu_abort(env, @@ -2725,23 +2570,26 @@ static always_inline void powerpc_excp (CPUState *env, if (asrr1 != -1) env->spr[asrr1] = env->spr[srr1]; /* If we disactivated any translation, flush TLBs */ - if (msr_ir || msr_dr) + if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR))) tlb_flush(env, 1); /* reload MSR with correct bits */ - msr_ee = 0; - msr_pr = 0; - msr_fp = 0; - msr_fe0 = 0; - msr_se = 0; - msr_be = 0; - msr_fe1 = 0; - msr_ir = 0; - msr_dr = 0; + new_msr &= ~((target_ulong)1 << MSR_EE); + new_msr &= ~((target_ulong)1 << MSR_PR); + new_msr &= ~((target_ulong)1 << MSR_FP); + new_msr &= ~((target_ulong)1 << MSR_FE0); + new_msr &= ~((target_ulong)1 << MSR_SE); + new_msr &= ~((target_ulong)1 << MSR_BE); + new_msr &= ~((target_ulong)1 << MSR_FE1); + new_msr &= ~((target_ulong)1 << MSR_IR); + new_msr &= ~((target_ulong)1 << MSR_DR); #if 0 /* Fix this: not on all targets */ - msr_pmm = 0; + new_msr &= ~((target_ulong)1 << MSR_PMM); #endif - msr_le = msr_ile; - do_compute_hflags(env); + new_msr &= ~((target_ulong)1 << MSR_LE); + if (msr_ile) + new_msr |= (target_ulong)1 << MSR_LE; + else + new_msr &= ~((target_ulong)1 << MSR_LE); /* Jump to handler */ vector = env->excp_vectors[excp]; if (vector == (target_ulong)-1) { @@ -2751,15 +2599,26 @@ static always_inline void powerpc_excp (CPUState *env, vector |= env->excp_prefix; #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { - msr_cm = msr_icm; - if (!msr_cm) + if (!msr_icm) { + new_msr &= ~((target_ulong)1 << MSR_CM); vector = (uint32_t)vector; + } else { + new_msr |= (target_ulong)1 << MSR_CM; + } } else { - msr_sf = msr_isf; - if (!msr_sf) + if (!msr_isf) { + new_msr &= ~((target_ulong)1 << MSR_SF); vector = (uint32_t)vector; + } else { + new_msr |= (target_ulong)1 << MSR_SF; + } } #endif + /* XXX: we don't use hreg_store_msr here as already have treated + * any special case that could occur. Just store MSR and update hflags + */ + env->msr = new_msr; + hreg_compute_hflags(env); env->nip = vector; /* Reset exception state */ env->exception_index = POWERPC_EXCP_NONE; @@ -2773,11 +2632,11 @@ void do_interrupt (CPUState *env) void ppc_hw_interrupt (CPUPPCState *env) { -#if 1 +#if 0 if (loglevel & CPU_LOG_INT) { fprintf(logfile, "%s: %p pending %08x req %08x me %d ee %d\n", __func__, env, env->pending_interrupts, - env->interrupt_request, msr_me, msr_ee); + env->interrupt_request, (int)msr_me, (int)msr_ee); } #endif /* External reset */ @@ -2801,7 +2660,7 @@ void ppc_hw_interrupt (CPUPPCState *env) } #endif #if defined(TARGET_PPC64H) - if ((msr_ee != 0 || msr_hv == 0 || msr_pr == 1) & hdice != 0) { + if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) & hdice != 0) { /* Hypervisor decrementer exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); @@ -2933,34 +2792,31 @@ void cpu_dump_rfi (target_ulong RA, target_ulong msr) void cpu_ppc_reset (void *opaque) { CPUPPCState *env; - int i; + target_ulong msr; env = opaque; - /* XXX: some of those flags initialisation values could depend - * on the actual PowerPC implementation - */ - for (i = 0; i < 63; i++) - env->msr[i] = 0; + msr = (target_ulong)0; #if defined(TARGET_PPC64) - msr_hv = 0; /* Should be 1... */ + msr |= (target_ulong)0 << MSR_HV; /* Should be 1... */ #endif - msr_ap = 0; /* TO BE CHECKED */ - msr_sa = 0; /* TO BE CHECKED */ - msr_ep = 1; + msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */ + msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */ + msr |= (target_ulong)1 << MSR_EP; #if defined (DO_SINGLE_STEP) && 0 /* Single step trace mode */ - msr_se = 1; - msr_be = 1; + msr |= (target_ulong)1 << MSR_SE; + msr |= (target_ulong)1 << MSR_BE; #endif #if defined(CONFIG_USER_ONLY) - msr_fp = 1; /* Allow floating point exceptions */ - msr_pr = 1; + msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */ + msr |= (target_ulong)1 << MSR_PR; #else env->nip = env->hreset_vector | env->excp_prefix; if (env->mmu_model != POWERPC_MMU_REAL_4xx) ppc_tlb_invalidate_all(env); #endif - do_compute_hflags(env); + env->msr = msr; + hreg_compute_hflags(env); env->reserve = -1; /* Be sure no exception or interrupt is pending */ env->pending_interrupts = 0; |