#define MSR_DE 9 /* Debug interrupts enable on embedded PowerPC x */
#define MSR_FE1 8 /* Floating point exception mode 1 hflags */
#define MSR_AL 7 /* AL bit on POWER */
-#define MSR_EP 3 /* Exception prefix on 601 */
+#define MSR_EP 6 /* Exception prefix on 601 */
#define MSR_IR 5 /* Instruction relocate */
#define MSR_DR 4 /* Data relocate */
#define MSR_PE 3 /* Protection enable on 403 */
#define MSR_PMM 2 /* Performance monitor mark on POWER x */
#define MSR_RI 1 /* Recoverable interrupt 1 */
#define MSR_LE 0 /* Little-endian mode 1 hflags */
-#define msr_sf env->msr[MSR_SF]
-#define msr_isf env->msr[MSR_ISF]
-#define msr_hv env->msr[MSR_HV]
-#define msr_cm env->msr[MSR_CM]
-#define msr_icm env->msr[MSR_ICM]
-#define msr_ucle env->msr[MSR_UCLE]
-#define msr_vr env->msr[MSR_VR]
-#define msr_spe env->msr[MSR_SPE]
-#define msr_ap env->msr[MSR_AP]
-#define msr_sa env->msr[MSR_SA]
-#define msr_key env->msr[MSR_KEY]
-#define msr_pow env->msr[MSR_POW]
-#define msr_tgpr env->msr[MSR_TGPR]
-#define msr_ce env->msr[MSR_CE]
-#define msr_ile env->msr[MSR_ILE]
-#define msr_ee env->msr[MSR_EE]
-#define msr_pr env->msr[MSR_PR]
-#define msr_fp env->msr[MSR_FP]
-#define msr_me env->msr[MSR_ME]
-#define msr_fe0 env->msr[MSR_FE0]
-#define msr_se env->msr[MSR_SE]
-#define msr_dwe env->msr[MSR_DWE]
-#define msr_uble env->msr[MSR_UBLE]
-#define msr_be env->msr[MSR_BE]
-#define msr_de env->msr[MSR_DE]
-#define msr_fe1 env->msr[MSR_FE1]
-#define msr_al env->msr[MSR_AL]
-#define msr_ir env->msr[MSR_IR]
-#define msr_dr env->msr[MSR_DR]
-#define msr_pe env->msr[MSR_PE]
-#define msr_ep env->msr[MSR_EP]
-#define msr_px env->msr[MSR_PX]
-#define msr_pmm env->msr[MSR_PMM]
-#define msr_ri env->msr[MSR_RI]
-#define msr_le env->msr[MSR_LE]
+
+#define msr_sf ((env->msr >> MSR_SF) & 1)
+#define msr_isf ((env->msr >> MSR_ISF) & 1)
+#define msr_hv ((env->msr >> MSR_HV) & 1)
+#define msr_cm ((env->msr >> MSR_CM) & 1)
+#define msr_icm ((env->msr >> MSR_ICM) & 1)
+#define msr_ucle ((env->msr >> MSR_UCLE) & 1)
+#define msr_vr ((env->msr >> MSR_VR) & 1)
+#define msr_spe ((env->msr >> MSR_SE) & 1)
+#define msr_ap ((env->msr >> MSR_AP) & 1)
+#define msr_sa ((env->msr >> MSR_SA) & 1)
+#define msr_key ((env->msr >> MSR_KEY) & 1)
+#define msr_pow ((env->msr >> MSR_POW) & 1)
+#define msr_tgpr ((env->msr >> MSR_TGPR) & 1)
+#define msr_ce ((env->msr >> MSR_CE) & 1)
+#define msr_ile ((env->msr >> MSR_ILE) & 1)
+#define msr_ee ((env->msr >> MSR_EE) & 1)
+#define msr_pr ((env->msr >> MSR_PR) & 1)
+#define msr_fp ((env->msr >> MSR_FP) & 1)
+#define msr_me ((env->msr >> MSR_ME) & 1)
+#define msr_fe0 ((env->msr >> MSR_FE0) & 1)
+#define msr_se ((env->msr >> MSR_SE) & 1)
+#define msr_dwe ((env->msr >> MSR_DWE) & 1)
+#define msr_uble ((env->msr >> MSR_UBLE) & 1)
+#define msr_be ((env->msr >> MSR_BE) & 1)
+#define msr_de ((env->msr >> MSR_DE) & 1)
+#define msr_fe1 ((env->msr >> MSR_FE1) & 1)
+#define msr_al ((env->msr >> MSR_AL) & 1)
+#define msr_ep ((env->msr >> MSR_EP) & 1)
+#define msr_ir ((env->msr >> MSR_IR) & 1)
+#define msr_dr ((env->msr >> MSR_DR) & 1)
+#define msr_pe ((env->msr >> MSR_PE) & 1)
+#define msr_px ((env->msr >> MSR_PX) & 1)
+#define msr_pmm ((env->msr >> MSR_PMM) & 1)
+#define msr_ri ((env->msr >> MSR_RI) & 1)
+#define msr_le ((env->msr >> MSR_LE) & 1)
enum {
POWERPC_FLAG_NONE = 0x00000000,
/* Those ones are used in supervisor mode only */
/* machine state register */
- uint8_t msr[64];
+ target_ulong msr;
/* temporary general purpose registers */
ppc_gpr_t tgpr[4]; /* Used to speed-up TLB assist handlers */
#endif /* !defined(CONFIG_USER_ONLY) */
target_ulong ppc_load_xer (CPUPPCState *env);
void ppc_store_xer (CPUPPCState *env, target_ulong value);
-target_ulong do_load_msr (CPUPPCState *env);
-int do_store_msr (CPUPPCState *env, target_ulong value);
-#if defined(TARGET_PPC64)
-int ppc_store_msr_32 (CPUPPCState *env, uint32_t value);
-#endif
+void ppc_store_msr (CPUPPCState *env, target_ulong value);
-void do_compute_hflags (CPUPPCState *env);
void cpu_ppc_reset (void *opaque);
CPUPPCState *cpu_ppc_init (void);
void cpu_ppc_close(CPUPPCState *env);
#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
{
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)
type == ACCESS_CODE ? 'I' : 'D', virtual);
}
#endif
+ pr = msr_pr;
switch (type) {
case ACCESS_CODE:
BATlt = env->IBAT[1];
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)) |
#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)
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;
{
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;
" 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
}
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;
{
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,
/* Check execute enable bit */
switch (zpr) {
case 0x2:
- if (msr_pr)
+ if (pr != 0)
goto check_perms;
/* No break here */
case 0x3:
ret = 0;
break;
case 0x0:
- if (msr_pr) {
+ if (pr != 0) {
ctx->prot = 0;
ret = -2;
break;
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;
int rw, int access_type, int check_BATs)
{
int ret;
+
#if 0
if (loglevel != 0) {
fprintf(logfile, "%s\n", __func__);
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);
}
/*****************************************************************************/
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;
/* 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;
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) {
"\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 */
"\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 */
#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 */
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;
}
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 */
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 */
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)
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) {
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 */
"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");
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) */
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 */
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 */
"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:
}
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:
}
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:
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:
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";
"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,
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) {
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;
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 */
}
#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);
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;
*/
#include "exec.h"
+#include "helper_regs.h"
#include "op_helper.h"
#define MEMSUFFIX _raw
}
}
-void do_load_xer (void)
-{
- T0 = (xer_so << XER_SO) |
- (xer_ov << XER_OV) |
- (xer_ca << XER_CA) |
- (xer_bc << XER_BC) |
- (xer_cmp << XER_CMP);
-}
-
-void do_store_xer (void)
-{
- xer_so = (T0 >> XER_SO) & 0x01;
- xer_ov = (T0 >> XER_OV) & 0x01;
- xer_ca = (T0 >> XER_CA) & 0x01;
- xer_cmp = (T0 >> XER_CMP) & 0xFF;
- xer_bc = (T0 >> XER_BC) & 0x7F;
-}
-
#if defined(TARGET_PPC64)
void do_store_pri (int prio)
{
#if !defined (CONFIG_USER_ONLY)
void cpu_dump_rfi (target_ulong RA, target_ulong msr);
-void do_rfi (void)
+
+void do_store_msr (void)
+{
+ T0 = hreg_store_msr(env, T0);
+ if (T0 != 0) {
+ env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ do_raise_exception(T0);
+ }
+}
+
+static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
+ target_ulong msrm, int keep_msrh)
{
#if defined(TARGET_PPC64)
- if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
- env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
- do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+ if (msr & (1ULL << MSR_SF)) {
+ nip = (uint64_t)nip;
+ msr &= (uint64_t)msrm;
} else {
- env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
- ppc_store_msr_32(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+ nip = (uint32_t)nip;
+ msr = (uint32_t)(msr & msrm);
+ if (keep_msrh)
+ msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
}
#else
- env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
- do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+ nip = (uint32_t)nip;
+ msr &= (uint32_t)msrm;
#endif
+ /* XXX: beware: this is false if VLE is supported */
+ env->nip = nip & ~((target_ulong)0x00000003);
+ hreg_store_msr(env, msr);
#if defined (DEBUG_OP)
- cpu_dump_rfi(env->nip, do_load_msr(env));
+ cpu_dump_rfi(env->nip, env->msr);
#endif
+ /* No need to raise an exception here,
+ * as rfi is always the last insn of a TB
+ */
env->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
+void do_rfi (void)
+{
+ __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+ ~((target_ulong)0xFFFF0000), 1);
+}
+
#if defined(TARGET_PPC64)
void do_rfid (void)
{
- if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
- env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
- do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
- } else {
- env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
- do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
- }
-#if defined (DEBUG_OP)
- cpu_dump_rfi(env->nip, do_load_msr(env));
-#endif
- env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+ ~((target_ulong)0xFFFF0000), 0);
}
#endif
#if defined(TARGET_PPC64H)
void do_hrfid (void)
{
- if (env->spr[SPR_HSRR1] & (1ULL << MSR_SF)) {
- env->nip = (uint64_t)(env->spr[SPR_HSRR0] & ~0x00000003);
- do_store_msr(env, (uint64_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL));
- } else {
- env->nip = (uint32_t)(env->spr[SPR_HSRR0] & ~0x00000003);
- do_store_msr(env, (uint32_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL));
- }
-#if defined (DEBUG_OP)
- cpu_dump_rfi(env->nip, do_load_msr(env));
-#endif
- env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
+ ~((target_ulong)0xFFFF0000), 0);
}
#endif
#endif
void do_POWER_rfsvc (void)
{
- env->nip = env->lr & ~0x00000003UL;
- T0 = env->ctr & 0x0000FFFFUL;
- do_store_msr(env, T0);
-#if defined (DEBUG_OP)
- cpu_dump_rfi(env->nip, do_load_msr(env));
-#endif
- env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
}
/* PowerPC 601 BAT management helper */
#if !defined(CONFIG_USER_ONLY)
void do_40x_rfci (void)
{
- env->nip = env->spr[SPR_40x_SRR2];
- do_store_msr(env, env->spr[SPR_40x_SRR3] & ~0xFFFF0000);
-#if defined (DEBUG_OP)
- cpu_dump_rfi(env->nip, do_load_msr(env));
-#endif
- env->interrupt_request = CPU_INTERRUPT_EXITTB;
+ __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
+ ~((target_ulong)0xFFFF0000), 0);
}
void do_rfci (void)
{
-#if defined(TARGET_PPC64)
- if (env->spr[SPR_BOOKE_CSRR1] & (1 << MSR_CM)) {
- env->nip = (uint64_t)env->spr[SPR_BOOKE_CSRR0];
- } else
-#endif
- {
- env->nip = (uint32_t)env->spr[SPR_BOOKE_CSRR0];
- }
- do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_CSRR1] & ~0x3FFF0000);
-#if defined (DEBUG_OP)
- cpu_dump_rfi(env->nip, do_load_msr(env));
-#endif
- env->interrupt_request = CPU_INTERRUPT_EXITTB;
+ __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
+ ~((target_ulong)0x3FFF0000), 0);
}
void do_rfdi (void)
{
-#if defined(TARGET_PPC64)
- if (env->spr[SPR_BOOKE_DSRR1] & (1 << MSR_CM)) {
- env->nip = (uint64_t)env->spr[SPR_BOOKE_DSRR0];
- } else
-#endif
- {
- env->nip = (uint32_t)env->spr[SPR_BOOKE_DSRR0];
- }
- do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_DSRR1] & ~0x3FFF0000);
-#if defined (DEBUG_OP)
- cpu_dump_rfi(env->nip, do_load_msr(env));
-#endif
- env->interrupt_request = CPU_INTERRUPT_EXITTB;
+ __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
+ ~((target_ulong)0x3FFF0000), 0);
}
void do_rfmci (void)
{
-#if defined(TARGET_PPC64)
- if (env->spr[SPR_BOOKE_MCSRR1] & (1 << MSR_CM)) {
- env->nip = (uint64_t)env->spr[SPR_BOOKE_MCSRR0];
- } else
-#endif
- {
- env->nip = (uint32_t)env->spr[SPR_BOOKE_MCSRR0];
- }
- do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_MCSRR1] & ~0x3FFF0000);
-#if defined (DEBUG_OP)
- cpu_dump_rfi(env->nip, do_load_msr(env));
-#endif
- env->interrupt_request = CPU_INTERRUPT_EXITTB;
+ __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
+ ~((target_ulong)0x3FFF0000), 0);
}
void do_load_403_pb (int num)