aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-ppc/helper.c')
-rw-r--r--target-ppc/helper.c418
1 files changed, 137 insertions, 281 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 7631247..ea672bb 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;