aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/helper_regs.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/ppc/helper_regs.c')
-rw-r--r--target/ppc/helper_regs.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index f211bc9..a07e6a7 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -27,6 +27,8 @@
#include "power8-pmu.h"
#include "cpu-models.h"
#include "spr_common.h"
+#include "accel/tcg/cpu-ops.h"
+#include "internal.h"
/* Swap temporary saved registers with GPRs */
void hreg_swap_gpr_tgpr(CPUPPCState *env)
@@ -184,6 +186,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
if (env->spr[SPR_LPCR] & LPCR_HR) {
hflags |= 1 << HFLAGS_HR;
}
+ if (unlikely(ppc_flags & POWERPC_FLAG_PPE42)) {
+ /* PPE42 has a single address space and no problem state */
+ msr = 0;
+ }
#ifndef CONFIG_USER_ONLY
if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) {
@@ -255,26 +261,24 @@ void hreg_update_pmu_hflags(CPUPPCState *env)
env->hflags |= hreg_compute_pmu_hflags_value(env);
}
-#ifdef CONFIG_DEBUG_TCG
-void cpu_get_tb_cpu_state(CPUPPCState *env, vaddr *pc,
- uint64_t *cs_base, uint32_t *flags)
+TCGTBCPUState ppc_get_tb_cpu_state(CPUState *cs)
{
+ CPUPPCState *env = cpu_env(cs);
uint32_t hflags_current = env->hflags;
- uint32_t hflags_rebuilt;
-
- *pc = env->nip;
- *cs_base = 0;
- *flags = hflags_current;
- hflags_rebuilt = hreg_compute_hflags_value(env);
+#ifdef CONFIG_DEBUG_TCG
+ uint32_t hflags_rebuilt = hreg_compute_hflags_value(env);
if (unlikely(hflags_current != hflags_rebuilt)) {
cpu_abort(env_cpu(env),
"TCG hflags mismatch (current:0x%08x rebuilt:0x%08x)\n",
hflags_current, hflags_rebuilt);
}
-}
#endif
+ return (TCGTBCPUState){ .pc = env->nip, .flags = hflags_current };
+}
+
+#ifndef CONFIG_USER_ONLY
void cpu_interrupt_exittb(CPUState *cs)
{
/*
@@ -286,6 +290,7 @@ void cpu_interrupt_exittb(CPUState *cs)
cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
}
}
+#endif
int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
{
@@ -307,9 +312,6 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
value &= ~(1 << MSR_ME);
value |= env->msr & (1 << MSR_ME);
}
- if ((value ^ env->msr) & (R_MSR_IR_MASK | R_MSR_DR_MASK)) {
- cpu_interrupt_exittb(cs);
- }
if ((env->mmu_model == POWERPC_MMU_BOOKE ||
env->mmu_model == POWERPC_MMU_BOOKE206) &&
((value ^ env->msr) & R_MSR_GS_MASK)) {
@@ -320,8 +322,14 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
/* Swap temporary saved registers with GPRs */
hreg_swap_gpr_tgpr(env);
}
- if (unlikely((value ^ env->msr) & R_MSR_EP_MASK)) {
- env->excp_prefix = FIELD_EX64(value, MSR, EP) * 0xFFF00000;
+ /* PPE42 uses IR, DR and EP MSR bits for other purposes */
+ if (likely(!(env->flags & POWERPC_FLAG_PPE42))) {
+ if ((value ^ env->msr) & (R_MSR_IR_MASK | R_MSR_DR_MASK)) {
+ cpu_interrupt_exittb(cs);
+ }
+ if (unlikely((value ^ env->msr) & R_MSR_EP_MASK)) {
+ env->excp_prefix = FIELD_EX64(value, MSR, EP) * 0xFFF00000;
+ }
}
/*
* If PR=1 then EE, IR and DR must be 1
@@ -463,6 +471,23 @@ void register_generic_sprs(PowerPCCPU *cpu)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+
+ spr_register(env, SPR_PVR, "PVR",
+ /* Linux permits userspace to read PVR */
+#if defined(CONFIG_LINUX_USER)
+ &spr_read_generic,
+#else
+ SPR_NOACCESS,
+#endif
+ SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
+ pcc->pvr);
+
+ /* PPE42 doesn't support SPRG1-3, SVR or TB regs */
+ if (env->insns_flags2 & PPC2_PPE42) {
+ return;
+ }
+
spr_register(env, SPR_SPRG1, "SPRG1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
@@ -476,17 +501,6 @@ void register_generic_sprs(PowerPCCPU *cpu)
&spr_read_generic, &spr_write_generic,
0x00000000);
- spr_register(env, SPR_PVR, "PVR",
- /* Linux permits userspace to read PVR */
-#if defined(CONFIG_LINUX_USER)
- &spr_read_generic,
-#else
- SPR_NOACCESS,
-#endif
- SPR_NOACCESS,
- &spr_read_generic, SPR_NOACCESS,
- pcc->pvr);
-
/* Register SVR if it's defined to anything else than POWERPC_SVR_NONE */
if (pcc->svr != POWERPC_SVR_NONE) {
if (pcc->svr & POWERPC_SVR_E500) {