aboutsummaryrefslogtreecommitdiff
path: root/target/ppc
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-03-13 12:37:27 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-03-13 12:37:27 +0000
commit51e31f21407190df9bd048a539267534cea7dd66 (patch)
tree20ac46bd9ec7cc618a1b208136d910d699542d2c /target/ppc
parentbab9dabe7df6a52209b2646da5479ffb629ab8f5 (diff)
parente1617b845104032f0aaad9b91dcda56c7c437998 (diff)
downloadqemu-51e31f21407190df9bd048a539267534cea7dd66.zip
qemu-51e31f21407190df9bd048a539267534cea7dd66.tar.gz
qemu-51e31f21407190df9bd048a539267534cea7dd66.tar.bz2
Merge tag 'pull-ppc-for-9.0-2-20240313' of https://gitlab.com/npiggin/qemu into staging
* PAPR nested hypervisor host implementation for spapr TCG * excp_helper.c code cleanups and improvements * Move more ops to decodetree * Deprecate pseries-2.12 machines and P9 and P10 DD1.0 CPUs * Document running Linux on AmigaNG * Update dt feature advertising POWER CPUs. * Add P10 PMU SPRs * Improve pnv topology calculation for SMT8 CPUs. * Various bug fixes. # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEETkN92lZhb0MpsKeVZ7MCdqhiHK4FAmXwiT8ACgkQZ7MCdqhi # HK7C/w//XxEO2bQTFPLFDTrP/voq7pcX8XeQNVyXCkXYjvsbu05oQow50k+Y5UAE # US4MFjt8jFz0vuIKuKyoA3kG41zDSOzoX4TQXMM+tyTWbuFF3KAyfizb1xE6SYAN # xJEGvmiXv/EgoSBD7BTKQp1tMPdIGZLwSdYiA0lmOo7YaMCgYAXaujW5hnNjQecT # 873sN+10pHtQY++mINtD9Nfb6AcDGMWw0b+bykqIXhNRkI8IGOS4WF4vAuMBrwfe # UM00wDnNRb86Dk14bv2XVNDr6/i0VRtUMwM4yiptrQ1TQx18LZaPSQFYjQfPaan7 # LwN4QkMFnBX54yJ7Npvjvu8BCBF47kwOVu4CIAFJ4sIm0WfTmozDpPttwcZ5w7Ve # iXDOB9ECAB4pQ2rCgbSNG8MYUZgoHHOuThqolOP0Vh9NHRRJxpdw6CyAbmCGftc0 # lvRDPFiKp8xmCNJ/j3XzoUdHoG7NMwpUmHv9ruGU18SdQ8hyJN9AcQGWYrB4v0RV # /hs2RAbwntG7ahkcwd8uy5aFw88Wph/uGXPXc49EWj7i49vHeIV2y5+gtthMywje # qqjFXkistXuF+JHVnyoYmqqCyXaHX5CEwtawMv4EQeaJs76bLhMeMTKKl9rRp8qB # DtbIZphO8iMsocrBnje48sA5HR0PM+H4HTjw10i8R0fLlWitaIY= # =XnY5 # -----END PGP SIGNATURE----- # gpg: Signature made Tue 12 Mar 2024 16:56:31 GMT # gpg: using RSA key 4E437DDA56616F4329B0A79567B30276A8621CAE # gpg: Good signature from "Nicholas Piggin <npiggin@gmail.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 4E43 7DDA 5661 6F43 29B0 A795 67B3 0276 A862 1CAE * tag 'pull-ppc-for-9.0-2-20240313' of https://gitlab.com/npiggin/qemu: (38 commits) spapr: nested: Introduce cap-nested-papr for Nested PAPR API spapr: nested: Introduce H_GUEST_RUN_VCPU hcall. spapr: nested: Use correct source for parttbl info for nested PAPR API. spapr: nested: Introduce H_GUEST_[GET|SET]_STATE hcalls. spapr: nested: Initialize the GSB elements lookup table. spapr: nested: Extend nested_ppc_state for nested PAPR API spapr: nested: Introduce H_GUEST_CREATE_VCPU hcall. spapr: nested: Introduce H_GUEST_[CREATE|DELETE] hcalls. spapr: nested: Introduce H_GUEST_[GET|SET]_CAPABILITIES hcalls. spapr: nested: Document Nested PAPR API spapr: nested: keep nested-hv related code restricted to its API. spapr: nested: Introduce SpaprMachineStateNested to store related info. spapr: nested: move nested part of spapr_get_pate into spapr_nested.c spapr: nested: register nested-hv api hcalls only for cap-nested-hv target/ppc: Remove interrupt handler wrapper functions target/ppc: Clean up ifdefs in excp_helper.c, part 3 target/ppc: Clean up ifdefs in excp_helper.c, part 2 target/ppc: Clean up ifdefs in excp_helper.c, part 1 target/ppc: Add gen_exception_err_nip() function target/ppc: Readability improvements in exception handlers ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/ppc')
-rw-r--r--target/ppc/cpu-models.c4
-rw-r--r--target/ppc/cpu.h11
-rw-r--r--target/ppc/cpu_init.c46
-rw-r--r--target/ppc/excp_helper.c418
-rw-r--r--target/ppc/gdbstub.c7
-rw-r--r--target/ppc/helper_regs.c5
-rw-r--r--target/ppc/insn32.decode26
-rw-r--r--target/ppc/kvm.c11
-rw-r--r--target/ppc/misc_helper.c3
-rw-r--r--target/ppc/translate.c164
-rw-r--r--target/ppc/translate/fixedpoint-impl.c.inc70
11 files changed, 312 insertions, 453 deletions
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 36e465b..f2301b4 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -728,14 +728,10 @@
"POWER8 v2.0")
POWERPC_DEF("power8nvl_v1.0", CPU_POWERPC_POWER8NVL_v10, POWER8,
"POWER8NVL v1.0")
- POWERPC_DEF("power9_v1.0", CPU_POWERPC_POWER9_DD1, POWER9,
- "POWER9 v1.0")
POWERPC_DEF("power9_v2.0", CPU_POWERPC_POWER9_DD20, POWER9,
"POWER9 v2.0")
POWERPC_DEF("power9_v2.2", CPU_POWERPC_POWER9_DD22, POWER9,
"POWER9 v2.2")
- POWERPC_DEF("power10_v1.0", CPU_POWERPC_POWER10_DD1, POWER10,
- "POWER10 v1.0")
POWERPC_DEF("power10_v2.0", CPU_POWERPC_POWER10_DD20, POWER10,
"POWER10 v2.0")
#endif /* defined (TARGET_PPC64) */
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 0133da4..67e6b2e 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1584,6 +1584,8 @@ uint64_t cpu_ppc_load_atbl(CPUPPCState *env);
uint32_t cpu_ppc_load_atbu(CPUPPCState *env);
void cpu_ppc_store_atbl(CPUPPCState *env, uint32_t value);
void cpu_ppc_store_atbu(CPUPPCState *env, uint32_t value);
+void cpu_ppc_increase_tb_by_offset(CPUPPCState *env, int64_t offset);
+void cpu_ppc_decrease_tb_by_offset(CPUPPCState *env, int64_t offset);
uint64_t cpu_ppc_load_vtb(CPUPPCState *env);
void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value);
bool ppc_decr_clear_on_delivery(CPUPPCState *env);
@@ -1755,9 +1757,11 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_PSPB (0x09F)
#define SPR_DPDES (0x0B0)
#define SPR_DAWR0 (0x0B4)
+#define SPR_DAWR1 (0x0B5)
#define SPR_RPR (0x0BA)
#define SPR_CIABR (0x0BB)
#define SPR_DAWRX0 (0x0BC)
+#define SPR_DAWRX1 (0x0BD)
#define SPR_HFSCR (0x0BE)
#define SPR_VRSAVE (0x100)
#define SPR_USPRG0 (0x100)
@@ -1951,6 +1955,12 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_BOOKE_TLB2CFG (0x2B2)
#define SPR_BOOKE_TLB3CFG (0x2B3)
#define SPR_BOOKE_EPR (0x2BE)
+#define SPR_POWER_USIER2 (0x2E0)
+#define SPR_POWER_USIER3 (0x2E1)
+#define SPR_POWER_UMMCR3 (0x2E2)
+#define SPR_POWER_SIER2 (0x2F0)
+#define SPR_POWER_SIER3 (0x2F1)
+#define SPR_POWER_MMCR3 (0x2F2)
#define SPR_PERF0 (0x300)
#define SPR_RCPU_MI_RBA0 (0x300)
#define SPR_MPC_MI_CTR (0x300)
@@ -2948,6 +2958,7 @@ static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr)
}
#if !defined(CONFIG_USER_ONLY)
+/* Sort out endianness of interrupt. Depends on the CPU, HV mode, etc. */
static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu, bool hv)
{
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 1487e2e..7e65f08 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5308,6 +5308,38 @@ static void register_power8_pmu_user_sprs(CPUPPCState *env)
0x00000000);
}
+static void register_power10_pmu_sup_sprs(CPUPPCState *env)
+{
+ spr_register_kvm(env, SPR_POWER_MMCR3, "MMCR3",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_MMCR3, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_SIER2, "SIER2",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_SIER2, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_SIER3, "SIER3",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_SIER3, 0x00000000);
+}
+
+static void register_power10_pmu_user_sprs(CPUPPCState *env)
+{
+ spr_register(env, SPR_POWER_UMMCR3, "UMMCR3",
+ &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_POWER_USIER2, "USIER2",
+ &spr_read_generic, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_POWER_USIER3, "USIER3",
+ &spr_read_generic, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+}
+
static void register_power5p_ear_sprs(CPUPPCState *env)
{
/* External access control */
@@ -6350,10 +6382,7 @@ static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr, bool best)
return false;
}
- if ((pvr & 0x0f00) == 0x100) {
- /* DD1.x always matches power9_v1.0 */
- return true;
- } else if ((pvr & 0x0f00) == 0x200) {
+ if ((pvr & 0x0f00) == 0x200) {
if ((pvr & 0xf) < 2) {
/* DD2.0, DD2.1 match power9_v2.0 */
if ((pcc->pvr & 0xf) == 0) {
@@ -6505,6 +6534,8 @@ static void init_proc_POWER10(CPUPPCState *env)
register_power9_mmu_sprs(env);
register_power10_hash_sprs(env);
register_power10_dexcr_sprs(env);
+ register_power10_pmu_sup_sprs(env);
+ register_power10_pmu_user_sprs(env);
/* FIXME: Filter fields properly based on privilege level */
spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL,
@@ -6536,7 +6567,7 @@ static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr, bool best)
}
if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) {
- /* Major DD version matches to power10_v1.0 and power10_v2.0 */
+ /* Major DD version matches power10_v2.0 */
return true;
}
@@ -6576,11 +6607,10 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
- PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_ISA310 |
+ PPC2_ISA300 | PPC2_PRCNTL | PPC2_ISA310 |
PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_HV) |
- (1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
(1ull << MSR_EE) |
@@ -6620,7 +6650,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
- POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV;
+ POWERPC_FLAG_VSX | POWERPC_FLAG_SCV;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
}
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 6bb6fee..80f584f 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -35,7 +35,7 @@
/*****************************************************************************/
/* Exception processing */
-#if !defined(CONFIG_USER_ONLY)
+#ifndef CONFIG_USER_ONLY
static const char *powerpc_excp_name(int excp)
{
@@ -186,7 +186,7 @@ static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
env->error_code);
}
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
static int powerpc_reset_wakeup(CPUPPCState *env, int excp, target_ulong *msr)
{
/* We no longer are in a PM state */
@@ -380,7 +380,7 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr,
}
}
}
-#endif
+#endif /* TARGET_PPC64 */
static void powerpc_reset_excp_state(PowerPCCPU *cpu)
{
@@ -403,9 +403,8 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
* We don't use hreg_store_msr here as already have treated any
* special case that could occur. Just store MSR and update hflags
*
- * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
- * will prevent setting of the HV bit which some exceptions might need
- * to do.
+ * Note: We *MUST* not use hreg_store_msr() as-is anyway because it will
+ * prevent setting of the HV bit which some exceptions might need to do.
*/
env->nip = vector;
env->msr = msr;
@@ -445,38 +444,26 @@ static void powerpc_mcheck_checkstop(CPUPPCState *env)
static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
{
- CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
- int srr0, srr1;
+ int srr0 = SPR_SRR0, srr1 = SPR_SRR1;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
- /*
- * new interrupt handler msr preserves existing ME unless
- * explicitly overridden.
- */
+ /* new interrupt handler msr preserves ME unless explicitly overridden */
new_msr = env->msr & (((target_ulong)1 << MSR_ME));
- /* target registers */
- srr0 = SPR_SRR0;
- srr1 = SPR_SRR1;
-
- /*
- * Hypervisor emulation assistance interrupt only exists on server
- * arch 2.05 server or later.
- */
+ /* HV emu assistance interrupt only exists on server arch 2.05 or later */
if (excp == POWERPC_EXCP_HV_EMU) {
excp = POWERPC_EXCP_PROGRAM;
}
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
- cpu_abort(cs, "Raised an exception without defined vector %d\n",
- excp);
+ cpu_abort(env_cpu(env),
+ "Raised an exception without defined vector %d\n", excp);
}
-
vector |= env->excp_prefix;
switch (excp) {
@@ -488,7 +475,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
powerpc_mcheck_checkstop(env);
/* machine check exceptions don't have ME set */
new_msr &= ~((target_ulong)1 << MSR_ME);
-
srr0 = SPR_40x_SRR2;
srr1 = SPR_40x_SRR3;
break;
@@ -523,7 +509,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
env->spr[SPR_40x_ESR] = ESR_PTR;
break;
default:
- cpu_abort(cs, "Invalid program exception %d. Aborting\n",
+ cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
env->error_code);
break;
}
@@ -550,52 +536,41 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
trace_ppc_excp_print("PIT");
break;
case POWERPC_EXCP_DEBUG: /* Debug interrupt */
- cpu_abort(cs, "%s exception not implemented\n",
+ cpu_abort(env_cpu(env), "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
default:
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
+ excp);
break;
}
- /* Save PC */
env->spr[srr0] = env->nip;
-
- /* Save MSR */
env->spr[srr1] = msr;
-
powerpc_set_excp_state(cpu, vector, new_msr);
}
static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
{
- CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
- /*
- * new interrupt handler msr preserves existing ME unless
- * explicitly overridden
- */
+ /* new interrupt handler msr preserves ME unless explicitly overridden */
new_msr = env->msr & ((target_ulong)1 << MSR_ME);
- /*
- * Hypervisor emulation assistance interrupt only exists on server
- * arch 2.05 server or later.
- */
+ /* HV emu assistance interrupt only exists on server arch 2.05 or later */
if (excp == POWERPC_EXCP_HV_EMU) {
excp = POWERPC_EXCP_PROGRAM;
}
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
- cpu_abort(cs, "Raised an exception without defined vector %d\n",
- excp);
+ cpu_abort(env_cpu(env),
+ "Raised an exception without defined vector %d\n", excp);
}
-
vector |= env->excp_prefix;
switch (excp) {
@@ -605,7 +580,6 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
powerpc_mcheck_checkstop(env);
/* machine check exceptions don't have ME set */
new_msr &= ~((target_ulong)1 << MSR_ME);
-
break;
case POWERPC_EXCP_DSI: /* Data storage exception */
trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
@@ -633,11 +607,9 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
powerpc_reset_excp_state(cpu);
return;
}
-
/*
- * FP exceptions always have NIP pointing to the faulting
- * instruction, so always use store_next and claim we are
- * precise in the MSR.
+ * NIP always points to the faulting instruction for FP exceptions,
+ * so always use store_next and claim we are precise in the MSR.
*/
msr |= 0x00100000;
break;
@@ -653,7 +625,7 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
break;
default:
/* Should never occur */
- cpu_abort(cs, "Invalid program exception %d. Aborting\n",
+ cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
env->error_code);
break;
}
@@ -675,8 +647,9 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
break;
case POWERPC_EXCP_RESET: /* System reset exception */
if (FIELD_EX64(env->msr, MSR, POW)) {
- cpu_abort(cs, "Trying to deliver power-saving system reset "
- "exception %d with no HV support\n", excp);
+ cpu_abort(env_cpu(env),
+ "Trying to deliver power-saving system reset exception "
+ "%d with no HV support\n", excp);
}
break;
case POWERPC_EXCP_TRACE: /* Trace exception */
@@ -703,60 +676,44 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_SMI: /* System management interrupt */
case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
- cpu_abort(cs, "%s exception not implemented\n",
+ cpu_abort(env_cpu(env), "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
default:
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
+ excp);
break;
}
- /*
- * Sort out endianness of interrupt, this differs depending on the
- * CPU, the HV mode, etc...
- */
if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
new_msr |= (target_ulong)1 << MSR_LE;
}
-
- /* Save PC */
env->spr[SPR_SRR0] = env->nip;
-
- /* Save MSR */
env->spr[SPR_SRR1] = msr;
-
powerpc_set_excp_state(cpu, vector, new_msr);
}
static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
{
- CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
- /*
- * new interrupt handler msr preserves existing ME unless
- * explicitly overridden
- */
+ /* new interrupt handler msr preserves ME unless explicitly overridden */
new_msr = env->msr & ((target_ulong)1 << MSR_ME);
- /*
- * Hypervisor emulation assistance interrupt only exists on server
- * arch 2.05 server or later.
- */
+ /* HV emu assistance interrupt only exists on server arch 2.05 or later */
if (excp == POWERPC_EXCP_HV_EMU) {
excp = POWERPC_EXCP_PROGRAM;
}
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
- cpu_abort(cs, "Raised an exception without defined vector %d\n",
- excp);
+ cpu_abort(env_cpu(env),
+ "Raised an exception without defined vector %d\n", excp);
}
-
vector |= env->excp_prefix;
switch (excp) {
@@ -764,7 +721,6 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
powerpc_mcheck_checkstop(env);
/* machine check exceptions don't have ME set */
new_msr &= ~((target_ulong)1 << MSR_ME);
-
break;
case POWERPC_EXCP_DSI: /* Data storage exception */
trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
@@ -792,11 +748,9 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
powerpc_reset_excp_state(cpu);
return;
}
-
/*
- * FP exceptions always have NIP pointing to the faulting
- * instruction, so always use store_next and claim we are
- * precise in the MSR.
+ * NIP always points to the faulting instruction for FP exceptions,
+ * so always use store_next and claim we are precise in the MSR.
*/
msr |= 0x00100000;
break;
@@ -812,7 +766,7 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
break;
default:
/* Should never occur */
- cpu_abort(cs, "Invalid program exception %d. Aborting\n",
+ cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
env->error_code);
break;
}
@@ -854,8 +808,9 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
break;
case POWERPC_EXCP_RESET: /* System reset exception */
if (FIELD_EX64(env->msr, MSR, POW)) {
- cpu_abort(cs, "Trying to deliver power-saving system reset "
- "exception %d with no HV support\n", excp);
+ cpu_abort(env_cpu(env),
+ "Trying to deliver power-saving system reset exception "
+ "%d with no HV support\n", excp);
}
break;
case POWERPC_EXCP_TRACE: /* Trace exception */
@@ -864,71 +819,53 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
ppc_excp_debug_sw_tlb(env, excp);
-
msr |= env->crf[0] << 28;
msr |= env->error_code; /* key, D/I, S/L bits */
/* Set way using a LRU mechanism */
msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
-
break;
case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
case POWERPC_EXCP_SMI: /* System management interrupt */
case POWERPC_EXCP_THERM: /* Thermal interrupt */
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
- cpu_abort(cs, "%s exception not implemented\n",
+ cpu_abort(env_cpu(env), "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
default:
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
+ excp);
break;
}
- /*
- * Sort out endianness of interrupt, this differs depending on the
- * CPU, the HV mode, etc...
- */
if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
new_msr |= (target_ulong)1 << MSR_LE;
}
-
- /* Save PC */
env->spr[SPR_SRR0] = env->nip;
-
- /* Save MSR */
env->spr[SPR_SRR1] = msr;
-
powerpc_set_excp_state(cpu, vector, new_msr);
}
static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
{
- CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
- /*
- * new interrupt handler msr preserves existing ME unless
- * explicitly overridden
- */
+ /* new interrupt handler msr preserves ME unless explicitly overridden */
new_msr = env->msr & ((target_ulong)1 << MSR_ME);
- /*
- * Hypervisor emulation assistance interrupt only exists on server
- * arch 2.05 server or later.
- */
+ /* HV emu assistance interrupt only exists on server arch 2.05 or later */
if (excp == POWERPC_EXCP_HV_EMU) {
excp = POWERPC_EXCP_PROGRAM;
}
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
- cpu_abort(cs, "Raised an exception without defined vector %d\n",
- excp);
+ cpu_abort(env_cpu(env),
+ "Raised an exception without defined vector %d\n", excp);
}
-
vector |= env->excp_prefix;
switch (excp) {
@@ -936,7 +873,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
powerpc_mcheck_checkstop(env);
/* machine check exceptions don't have ME set */
new_msr &= ~((target_ulong)1 << MSR_ME);
-
break;
case POWERPC_EXCP_DSI: /* Data storage exception */
trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
@@ -964,11 +900,9 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
powerpc_reset_excp_state(cpu);
return;
}
-
/*
- * FP exceptions always have NIP pointing to the faulting
- * instruction, so always use store_next and claim we are
- * precise in the MSR.
+ * NIP always points to the faulting instruction for FP exceptions,
+ * so always use store_next and claim we are precise in the MSR.
*/
msr |= 0x00100000;
break;
@@ -984,7 +918,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
break;
default:
/* Should never occur */
- cpu_abort(cs, "Invalid program exception %d. Aborting\n",
+ cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
env->error_code);
break;
}
@@ -1026,7 +960,8 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
break;
case POWERPC_EXCP_RESET: /* System reset exception */
if (FIELD_EX64(env->msr, MSR, POW)) {
- cpu_abort(cs, "Trying to deliver power-saving system reset "
+ cpu_abort(env_cpu(env),
+ "Trying to deliver power-saving system reset "
"exception %d with no HV support\n", excp);
}
break;
@@ -1039,54 +974,39 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_THERM: /* Thermal interrupt */
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
case POWERPC_EXCP_VPUA: /* Vector assist exception */
- cpu_abort(cs, "%s exception not implemented\n",
+ cpu_abort(env_cpu(env), "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
default:
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
+ excp);
break;
}
- /*
- * Sort out endianness of interrupt, this differs depending on the
- * CPU, the HV mode, etc...
- */
if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
new_msr |= (target_ulong)1 << MSR_LE;
}
-
- /* Save PC */
env->spr[SPR_SRR0] = env->nip;
-
- /* Save MSR */
env->spr[SPR_SRR1] = msr;
-
powerpc_set_excp_state(cpu, vector, new_msr);
}
static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
{
- CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
- int srr0, srr1;
-
- msr = env->msr;
+ int srr0 = SPR_SRR0, srr1 = SPR_SRR1;
/*
- * new interrupt handler msr preserves existing ME unless
- * explicitly overridden
+ * Book E does not play games with certain bits of xSRR1 being MSR save
+ * bits and others being error status. xSRR1 is the old MSR, period.
*/
- new_msr = env->msr & ((target_ulong)1 << MSR_ME);
+ msr = env->msr;
- /* target registers */
- srr0 = SPR_SRR0;
- srr1 = SPR_SRR1;
+ /* new interrupt handler msr preserves ME unless explicitly overridden */
+ new_msr = env->msr & ((target_ulong)1 << MSR_ME);
- /*
- * Hypervisor emulation assistance interrupt only exists on server
- * arch 2.05 server or later.
- */
+ /* HV emu assistance interrupt only exists on server arch 2.05 or later */
if (excp == POWERPC_EXCP_HV_EMU) {
excp = POWERPC_EXCP_PROGRAM;
}
@@ -1103,10 +1023,9 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
- cpu_abort(cs, "Raised an exception without defined vector %d\n",
- excp);
+ cpu_abort(env_cpu(env),
+ "Raised an exception without defined vector %d\n", excp);
}
-
vector |= env->excp_prefix;
switch (excp) {
@@ -1135,6 +1054,7 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
break;
case POWERPC_EXCP_EXTERNAL: /* External input */
if (env->mpic_proxy) {
+ CPUState *cs = env_cpu(env);
/* IACK the IRQ on delivery */
env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
}
@@ -1149,11 +1069,9 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
powerpc_reset_excp_state(cpu);
return;
}
-
/*
- * FP exceptions always have NIP pointing to the faulting
- * instruction, so always use store_next and claim we are
- * precise in the MSR.
+ * NIP always points to the faulting instruction for FP exceptions,
+ * so always use store_next and claim we are precise in the MSR.
*/
msr |= 0x00100000;
env->spr[SPR_BOOKE_ESR] = ESR_FP;
@@ -1173,7 +1091,7 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
break;
default:
/* Should never occur */
- cpu_abort(cs, "Invalid program exception %d. Aborting\n",
+ cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
env->error_code);
break;
}
@@ -1214,7 +1132,8 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
/* DBSR already modified by caller */
} else {
- cpu_abort(cs, "Debug exception triggered on unsupported model\n");
+ cpu_abort(env_cpu(env),
+ "Debug exception triggered on unsupported model\n");
}
break;
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
@@ -1228,21 +1147,23 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
break;
case POWERPC_EXCP_RESET: /* System reset exception */
if (FIELD_EX64(env->msr, MSR, POW)) {
- cpu_abort(cs, "Trying to deliver power-saving system reset "
+ cpu_abort(env_cpu(env),
+ "Trying to deliver power-saving system reset "
"exception %d with no HV support\n", excp);
}
break;
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
- cpu_abort(cs, "%s exception not implemented\n",
+ cpu_abort(env_cpu(env), "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
default:
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
+ excp);
break;
}
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
/* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
new_msr |= (target_ulong)1 << MSR_CM;
@@ -1251,12 +1172,8 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
}
#endif
- /* Save PC */
env->spr[srr0] = env->nip;
-
- /* Save MSR */
env->spr[srr1] = msr;
-
powerpc_set_excp_state(cpu, vector, new_msr);
}
@@ -1376,24 +1293,19 @@ static bool is_prefix_insn_excp(PowerPCCPU *cpu, int excp)
static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
{
- CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
- int srr0, srr1, lev = -1;
+ int srr0 = SPR_SRR0, srr1 = SPR_SRR1, lev = -1;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
/*
- * new interrupt handler msr preserves existing HV and ME unless
- * explicitly overridden
+ * new interrupt handler msr preserves HV and ME unless explicitly
+ * overridden
*/
new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
- /* target registers */
- srr0 = SPR_SRR0;
- srr1 = SPR_SRR1;
-
/*
* check for special resume at 0x100 from doze/nap/sleep/winkle on
* P7/P8/P9
@@ -1415,10 +1327,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
- cpu_abort(cs, "Raised an exception without defined vector %d\n",
- excp);
+ cpu_abort(env_cpu(env),
+ "Raised an exception without defined vector %d\n", excp);
}
-
vector |= env->excp_prefix;
if (is_prefix_insn_excp(cpu, excp)) {
@@ -1435,7 +1346,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
*/
new_msr |= (target_ulong)MSR_HVB;
}
-
/* machine check exceptions don't have ME set */
new_msr &= ~((target_ulong)1 << MSR_ME);
@@ -1453,23 +1363,17 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
{
bool lpes0;
- /*
- * LPES0 is only taken into consideration if we support HV
- * mode for this CPU.
- */
+ /* LPES0 is only taken into consideration if we support HV mode */
if (!env->has_hv_mode) {
break;
}
-
lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
-
if (!lpes0) {
new_msr |= (target_ulong)MSR_HVB;
new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
}
-
break;
}
case POWERPC_EXCP_ALIGN: /* Alignment exception */
@@ -1492,11 +1396,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
powerpc_reset_excp_state(cpu);
return;
}
-
/*
- * FP exceptions always have NIP pointing to the faulting
- * instruction, so always use store_next and claim we are
- * precise in the MSR.
+ * NIP always points to the faulting instruction for FP exceptions,
+ * so always use store_next and claim we are precise in the MSR.
*/
msr |= 0x00100000;
break;
@@ -1512,7 +1414,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
break;
default:
/* Should never occur */
- cpu_abort(cs, "Invalid program exception %d. Aborting\n",
+ cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
env->error_code);
break;
}
@@ -1578,7 +1480,8 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
new_msr |= (target_ulong)MSR_HVB;
} else {
if (FIELD_EX64(env->msr, MSR, POW)) {
- cpu_abort(cs, "Trying to deliver power-saving system reset "
+ cpu_abort(env_cpu(env),
+ "Trying to deliver power-saving system reset "
"exception %d with no HV support\n", excp);
}
}
@@ -1650,29 +1553,22 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_VPUA: /* Vector assist exception */
case POWERPC_EXCP_MAINT: /* Maintenance exception */
case POWERPC_EXCP_HV_MAINT: /* Hypervisor Maintenance exception */
- cpu_abort(cs, "%s exception not implemented\n",
+ cpu_abort(env_cpu(env), "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
default:
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
+ excp);
break;
}
- /*
- * Sort out endianness of interrupt, this differs depending on the
- * CPU, the HV mode, etc...
- */
if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
new_msr |= (target_ulong)1 << MSR_LE;
}
-
new_msr |= (target_ulong)1 << MSR_SF;
if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
- /* Save PC */
env->spr[srr0] = env->nip;
-
- /* Save MSR */
env->spr[srr1] = msr;
}
@@ -1681,19 +1577,15 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
/* Deliver interrupt to L1 by returning from the H_ENTER_NESTED call */
vhc->deliver_hv_excp(cpu, excp);
-
powerpc_reset_excp_state(cpu);
-
} else {
/* Sanity check */
if (!(env->msr_mask & MSR_HVB) && srr0 == SPR_HSRR0) {
- cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
- "no HV support\n", excp);
+ cpu_abort(env_cpu(env), "Trying to deliver HV exception (HSRR) %d "
+ "with no HV support\n", excp);
}
-
/* This can update new_msr and vector if AIL applies */
ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector);
-
powerpc_set_excp_state(cpu, vector, new_msr);
}
}
@@ -1702,15 +1594,15 @@ static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
{
g_assert_not_reached();
}
-#endif
+#endif /* TARGET_PPC64 */
static void powerpc_excp(PowerPCCPU *cpu, int excp)
{
- CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ cpu_abort(env_cpu(env), "Invalid PowerPC exception %d. Aborting\n",
+ excp);
}
qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
@@ -1753,7 +1645,7 @@ void ppc_cpu_do_interrupt(CPUState *cs)
powerpc_excp(cpu, cs->exception_index);
}
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
#define P7_UNUSED_INTERRUPTS \
(PPC_INTERRUPT_RESET | PPC_INTERRUPT_HVIRT | PPC_INTERRUPT_CEXT | \
PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \
@@ -2084,10 +1976,23 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env)
return 0;
}
-#endif
+#endif /* TARGET_PPC64 */
-static int ppc_next_unmasked_interrupt_generic(CPUPPCState *env)
+static int ppc_next_unmasked_interrupt(CPUPPCState *env)
{
+#ifdef TARGET_PPC64
+ switch (env->excp_model) {
+ case POWERPC_EXCP_POWER7:
+ return p7_next_unmasked_interrupt(env);
+ case POWERPC_EXCP_POWER8:
+ return p8_next_unmasked_interrupt(env);
+ case POWERPC_EXCP_POWER9:
+ case POWERPC_EXCP_POWER10:
+ return p9_next_unmasked_interrupt(env);
+ default:
+ break;
+ }
+#endif
bool async_deliver;
/* External reset */
@@ -2198,23 +2103,6 @@ static int ppc_next_unmasked_interrupt_generic(CPUPPCState *env)
return 0;
}
-static int ppc_next_unmasked_interrupt(CPUPPCState *env)
-{
- switch (env->excp_model) {
-#if defined(TARGET_PPC64)
- case POWERPC_EXCP_POWER7:
- return p7_next_unmasked_interrupt(env);
- case POWERPC_EXCP_POWER8:
- return p8_next_unmasked_interrupt(env);
- case POWERPC_EXCP_POWER9:
- case POWERPC_EXCP_POWER10:
- return p9_next_unmasked_interrupt(env);
-#endif
- default:
- return ppc_next_unmasked_interrupt_generic(env);
- }
-}
-
/*
* Sets CPU_INTERRUPT_HARD if there is at least one unmasked interrupt to be
* delivered and clears CPU_INTERRUPT_HARD otherwise.
@@ -2240,11 +2128,10 @@ void ppc_maybe_interrupt(CPUPPCState *env)
}
}
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
{
PowerPCCPU *cpu = env_archcpu(env);
- CPUState *cs = env_cpu(env);
switch (interrupt) {
case PPC_INTERRUPT_MCK: /* Machine check exception */
@@ -2288,14 +2175,14 @@ static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
assert(!env->resume_as_sreset);
break;
default:
- cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
+ cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n",
+ interrupt);
}
}
static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
{
PowerPCCPU *cpu = env_archcpu(env);
- CPUState *cs = env_cpu(env);
switch (interrupt) {
case PPC_INTERRUPT_MCK: /* Machine check exception */
@@ -2359,7 +2246,8 @@ static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
assert(!env->resume_as_sreset);
break;
default:
- cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
+ cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n",
+ interrupt);
}
}
@@ -2438,15 +2326,28 @@ static void p9_deliver_interrupt(CPUPPCState *env, int interrupt)
assert(!env->resume_as_sreset);
break;
default:
- cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
+ cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n",
+ interrupt);
}
}
-#endif
+#endif /* TARGET_PPC64 */
-static void ppc_deliver_interrupt_generic(CPUPPCState *env, int interrupt)
+static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt)
{
+#ifdef TARGET_PPC64
+ switch (env->excp_model) {
+ case POWERPC_EXCP_POWER7:
+ return p7_deliver_interrupt(env, interrupt);
+ case POWERPC_EXCP_POWER8:
+ return p8_deliver_interrupt(env, interrupt);
+ case POWERPC_EXCP_POWER9:
+ case POWERPC_EXCP_POWER10:
+ return p9_deliver_interrupt(env, interrupt);
+ default:
+ break;
+ }
+#endif
PowerPCCPU *cpu = env_archcpu(env);
- CPUState *cs = env_cpu(env);
switch (interrupt) {
case PPC_INTERRUPT_RESET: /* External reset */
@@ -2543,27 +2444,8 @@ static void ppc_deliver_interrupt_generic(CPUPPCState *env, int interrupt)
assert(!env->resume_as_sreset);
break;
default:
- cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
- }
-}
-
-static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt)
-{
- switch (env->excp_model) {
-#if defined(TARGET_PPC64)
- case POWERPC_EXCP_POWER7:
- p7_deliver_interrupt(env, interrupt);
- break;
- case POWERPC_EXCP_POWER8:
- p8_deliver_interrupt(env, interrupt);
- break;
- case POWERPC_EXCP_POWER9:
- case POWERPC_EXCP_POWER10:
- p9_deliver_interrupt(env, interrupt);
- break;
-#endif
- default:
- ppc_deliver_interrupt_generic(env, interrupt);
+ cpu_abort(env_cpu(env), "Invalid PowerPC interrupt %d. Aborting\n",
+ interrupt);
}
}
@@ -2659,10 +2541,8 @@ void helper_raise_exception(CPUPPCState *env, uint32_t exception)
{
raise_exception_err_ra(env, exception, 0, 0);
}
-#endif
-#if !defined(CONFIG_USER_ONLY)
-#ifdef CONFIG_TCG
+#ifndef CONFIG_USER_ONLY
void helper_store_msr(CPUPPCState *env, target_ulong val)
{
uint32_t excp = hreg_store_msr(env, val, 0);
@@ -2678,7 +2558,7 @@ void helper_ppc_maybe_interrupt(CPUPPCState *env)
ppc_maybe_interrupt(env);
}
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
void helper_scv(CPUPPCState *env, uint32_t lev)
{
if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
@@ -2706,7 +2586,7 @@ void helper_pminsn(CPUPPCState *env, uint32_t insn)
ppc_maybe_interrupt(env);
}
-#endif /* defined(TARGET_PPC64) */
+#endif /* TARGET_PPC64 */
static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
{
@@ -2717,7 +2597,7 @@ static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
if (env->flags & POWERPC_FLAG_TGPR)
msr &= ~(1ULL << MSR_TGPR);
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
/* Switching to 32-bit ? Crop the nip */
if (!msr_is_64bit(env, msr)) {
nip = (uint32_t)nip;
@@ -2746,7 +2626,7 @@ void helper_rfi(CPUPPCState *env)
do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
}
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
void helper_rfid(CPUPPCState *env)
{
/*
@@ -2767,9 +2647,7 @@ void helper_hrfid(CPUPPCState *env)
{
do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
}
-#endif
-#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
void helper_rfebb(CPUPPCState *env, target_ulong s)
{
target_ulong msr = env->msr;
@@ -2844,7 +2722,7 @@ void raise_ebb_perfm_exception(CPUPPCState *env)
do_ebb(env, POWERPC_EXCP_PERFM_EBB);
}
-#endif
+#endif /* TARGET_PPC64 */
/*****************************************************************************/
/* Embedded PowerPC specific helpers */
@@ -2869,10 +2747,8 @@ void helper_rfmci(CPUPPCState *env)
/* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
}
-#endif /* CONFIG_TCG */
-#endif /* !defined(CONFIG_USER_ONLY) */
+#endif /* !CONFIG_USER_ONLY */
-#ifdef CONFIG_TCG
void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
uint32_t flags)
{
@@ -2886,7 +2762,7 @@ void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
}
}
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
uint32_t flags)
{
@@ -2899,10 +2775,8 @@ void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
POWERPC_EXCP_TRAP, GETPC());
}
}
-#endif
-#endif
+#endif /* TARGET_PPC64 */
-#ifdef CONFIG_TCG
static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t lane)
{
const uint16_t c = 0xfffc;
@@ -3013,12 +2887,8 @@ HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true, NPHIE)
HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false, NPHIE)
HELPER_HASH(HASHSTP, env->spr[SPR_HASHPKEYR], true, PHIE)
HELPER_HASH(HASHCHKP, env->spr[SPR_HASHPKEYR], false, PHIE)
-#endif /* CONFIG_TCG */
-
-#if !defined(CONFIG_USER_ONLY)
-
-#ifdef CONFIG_TCG
+#ifndef CONFIG_USER_ONLY
/* Embedded.Processor Control */
static int dbell2irq(target_ulong rb)
{
@@ -3125,7 +2995,7 @@ void helper_book3s_msgsnd(target_ulong rb)
book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
}
-#if defined(TARGET_PPC64)
+#ifdef TARGET_PPC64
void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
{
helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
@@ -3365,5 +3235,5 @@ bool ppc_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
return false;
}
-#endif /* CONFIG_TCG */
#endif /* !CONFIG_USER_ONLY */
+#endif /* CONFIG_TCG */
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 769551e..3f1e61b 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -320,6 +320,9 @@ static void gdb_gen_spr_feature(CPUState *cs)
continue;
}
+ gdb_feature_builder_append_reg(&builder, g_ascii_strdown(spr->name, -1),
+ TARGET_LONG_BITS, num_regs,
+ "int", "spr");
/*
* GDB identifies registers based on the order they are
* presented in the XML. These ids will not match QEMU's
@@ -330,10 +333,6 @@ static void gdb_gen_spr_feature(CPUState *cs)
*/
spr->gdb_id = num_regs;
num_regs++;
-
- gdb_feature_builder_append_reg(&builder, g_ascii_strdown(spr->name, -1),
- TARGET_LONG_BITS, num_regs,
- "int", "spr");
}
gdb_feature_builder_end(&builder);
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 410b39c..2525898 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -264,6 +264,11 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
value &= ~MSR_HVB;
value |= env->msr & MSR_HVB;
}
+ /* Attempt to modify MSR[ME] in guest state is ignored */
+ if (is_book3s_arch2x(env) && !(env->msr & MSR_HVB)) {
+ 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);
}
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 4fcf3af..eada59f 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -187,6 +187,12 @@
&X_a ra
@X_a ...... ra:3 .. ..... ..... .......... . &X_a
+&XO rt ra rb oe:bool rc:bool
+@XO ...... rt:5 ra:5 rb:5 oe:1 ......... rc:1 &XO
+
+&XO_ta rt ra oe:bool rc:bool
+@XO_ta ...... rt:5 ra:5 ..... oe:1 ......... rc:1 &XO_ta
+
%xx_xt 0:1 21:5
%xx_xb 1:1 11:5
%xx_xa 2:1 16:5
@@ -322,10 +328,30 @@ CMPLI 001010 ... - . ..... ................ @D_bfu
### Fixed-Point Arithmetic Instructions
+ADD 011111 ..... ..... ..... . 100001010 . @XO
+ADDC 011111 ..... ..... ..... . 000001010 . @XO
+ADDE 011111 ..... ..... ..... . 010001010 . @XO
+
+# ADDEX is Z23-form, with CY=0; all other values for CY are reserved.
+# This works out the same as X-form.
+ADDEX 011111 ..... ..... ..... 00 10101010 - @X
+
ADDI 001110 ..... ..... ................ @D
ADDIS 001111 ..... ..... ................ @D
+ADDIC 001100 ..... ..... ................ @D
+ADDIC_ 001101 ..... ..... ................ @D
ADDPCIS 010011 ..... ..... .......... 00010 . @DX
+ADDME 011111 ..... ..... ----- . 011101010 . @XO_ta
+ADDZE 011111 ..... ..... ----- . 011001010 . @XO_ta
+
+SUBF 011111 ..... ..... ..... . 000101000 . @XO
+SUBFIC 001000 ..... ..... ................ @D
+SUBFC 011111 ..... ..... ..... . 000001000 . @XO
+SUBFE 011111 ..... ..... ..... . 010001000 . @XO
+
+SUBFME 011111 ..... ..... ----- . 011101000 . @XO_ta
+SUBFZE 011111 ..... ..... ----- . 011001000 . @XO_ta
## Fixed-Point Logical Instructions
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 6dfa5de..8231feb 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2365,17 +2365,6 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
#if defined(TARGET_PPC64)
pcc->radix_page_info = kvmppc_get_radix_page_info();
-
- if ((pcc->pvr & 0xffffff00) == CPU_POWERPC_POWER9_DD1) {
- /*
- * POWER9 DD1 has some bugs which make it not really ISA 3.00
- * compliant. More importantly, advertising ISA 3.00
- * architected mode may prevent guests from activating
- * necessary DD1 workarounds.
- */
- pcc->pcr_supported &= ~(PCR_COMPAT_3_00 | PCR_COMPAT_2_07
- | PCR_COMPAT_2_06 | PCR_COMPAT_2_05);
- }
#endif /* defined(TARGET_PPC64) */
}
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index a9d41d2..58e808d 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -49,9 +49,6 @@ void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn,
CPUState *cs = env_cpu(env);
CPUState *ccs;
uint32_t nr_threads = cs->nr_threads;
- uint32_t core_id = env->spr[SPR_PIR] & ~(nr_threads - 1);
-
- assert(core_id == env->spr[SPR_PIR] - env->spr[SPR_TIR]);
if (nr_threads == 1) {
env->spr[sprn] = val;
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 28fc779..93ffec7 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -296,33 +296,26 @@ static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
tcg_gen_movi_tl(cpu_nip, nip);
}
-static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
+static void gen_exception_err_nip(DisasContext *ctx, uint32_t excp,
+ uint32_t error, target_ulong nip)
{
TCGv_i32 t0, t1;
- /*
- * These are all synchronous exceptions, we set the PC back to the
- * faulting instruction
- */
- gen_update_nip(ctx, ctx->cia);
+ gen_update_nip(ctx, nip);
t0 = tcg_constant_i32(excp);
t1 = tcg_constant_i32(error);
gen_helper_raise_exception_err(tcg_env, t0, t1);
ctx->base.is_jmp = DISAS_NORETURN;
}
-static void gen_exception(DisasContext *ctx, uint32_t excp)
+static inline void gen_exception_err(DisasContext *ctx, uint32_t excp,
+ uint32_t error)
{
- TCGv_i32 t0;
-
/*
* These are all synchronous exceptions, we set the PC back to the
* faulting instruction
*/
- gen_update_nip(ctx, ctx->cia);
- t0 = tcg_constant_i32(excp);
- gen_helper_raise_exception(tcg_env, t0);
- ctx->base.is_jmp = DISAS_NORETURN;
+ gen_exception_err_nip(ctx, excp, error, ctx->cia);
}
static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
@@ -336,6 +329,15 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
ctx->base.is_jmp = DISAS_NORETURN;
}
+static inline void gen_exception(DisasContext *ctx, uint32_t excp)
+{
+ /*
+ * These are all synchronous exceptions, we set the PC back to the
+ * faulting instruction
+ */
+ gen_exception_nip(ctx, excp, ctx->cia);
+}
+
#if !defined(CONFIG_USER_ONLY)
static void gen_ppc_maybe_interrupt(DisasContext *ctx)
{
@@ -1735,61 +1737,6 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
tcg_gen_mov_tl(ret, t0);
}
}
-/* Add functions with two operands */
-#define GEN_INT_ARITH_ADD(name, opc3, ca, add_ca, compute_ca, compute_ov) \
-static void glue(gen_, name)(DisasContext *ctx) \
-{ \
- gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
- ca, glue(ca, 32), \
- add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
-}
-/* Add functions with one operand and one immediate */
-#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, ca, \
- add_ca, compute_ca, compute_ov) \
-static void glue(gen_, name)(DisasContext *ctx) \
-{ \
- TCGv t0 = tcg_constant_tl(const_val); \
- gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
- cpu_gpr[rA(ctx->opcode)], t0, \
- ca, glue(ca, 32), \
- add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
-}
-
-/* add add. addo addo. */
-GEN_INT_ARITH_ADD(add, 0x08, cpu_ca, 0, 0, 0)
-GEN_INT_ARITH_ADD(addo, 0x18, cpu_ca, 0, 0, 1)
-/* addc addc. addco addco. */
-GEN_INT_ARITH_ADD(addc, 0x00, cpu_ca, 0, 1, 0)
-GEN_INT_ARITH_ADD(addco, 0x10, cpu_ca, 0, 1, 1)
-/* adde adde. addeo addeo. */
-GEN_INT_ARITH_ADD(adde, 0x04, cpu_ca, 1, 1, 0)
-GEN_INT_ARITH_ADD(addeo, 0x14, cpu_ca, 1, 1, 1)
-/* addme addme. addmeo addmeo. */
-GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, cpu_ca, 1, 1, 0)
-GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, cpu_ca, 1, 1, 1)
-/* addex */
-GEN_INT_ARITH_ADD(addex, 0x05, cpu_ov, 1, 1, 0);
-/* addze addze. addzeo addzeo.*/
-GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, cpu_ca, 1, 1, 0)
-GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, cpu_ca, 1, 1, 1)
-/* addic addic.*/
-static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
-{
- TCGv c = tcg_constant_tl(SIMM(ctx->opcode));
- gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
- c, cpu_ca, cpu_ca32, 0, 1, 0, compute_rc0);
-}
-
-static void gen_addic(DisasContext *ctx)
-{
- gen_op_addic(ctx, 0);
-}
-
-static void gen_addic_(DisasContext *ctx)
-{
- gen_op_addic(ctx, 1);
-}
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
TCGv arg2, int sign, int compute_ov)
@@ -2210,47 +2157,6 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
tcg_gen_mov_tl(ret, t0);
}
}
-/* Sub functions with Two operands functions */
-#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
-static void glue(gen_, name)(DisasContext *ctx) \
-{ \
- gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
- add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
-}
-/* Sub functions with one operand and one immediate */
-#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
- add_ca, compute_ca, compute_ov) \
-static void glue(gen_, name)(DisasContext *ctx) \
-{ \
- TCGv t0 = tcg_constant_tl(const_val); \
- gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
- cpu_gpr[rA(ctx->opcode)], t0, \
- add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
-}
-/* subf subf. subfo subfo. */
-GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
-GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
-/* subfc subfc. subfco subfco. */
-GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
-GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
-/* subfe subfe. subfeo subfo. */
-GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
-GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
-/* subfme subfme. subfmeo subfmeo. */
-GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
-GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
-/* subfze subfze. subfzeo subfzeo.*/
-GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
-GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
-
-/* subfic */
-static void gen_subfic(DisasContext *ctx)
-{
- TCGv c = tcg_constant_tl(SIMM(ctx->opcode));
- gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
- c, 0, 1, 0, 0);
-}
/* neg neg. nego nego. */
static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
@@ -6524,8 +6430,6 @@ GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x00400001, PPC_NONE, PPC2_ISA300),
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
-GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
-GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
@@ -6536,7 +6440,6 @@ GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
-GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
@@ -6747,25 +6650,6 @@ GEN_HANDLER_E(maddhd_maddhdu, 0x04, 0x18, 0xFF, 0x00000000, PPC_NONE,
GEN_HANDLER_E(maddld, 0x04, 0x19, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300),
#endif
-#undef GEN_INT_ARITH_ADD
-#undef GEN_INT_ARITH_ADD_CONST
-#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
-GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
-#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
- add_ca, compute_ca, compute_ov) \
-GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
-GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
-GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
-GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
-GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
-GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
-GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
-GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
-GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
-GEN_HANDLER_E(addex, 0x1F, 0x0A, 0x05, 0x00000000, PPC_NONE, PPC2_ISA300),
-GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
-GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
-
#undef GEN_INT_ARITH_DIVW
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
@@ -6804,24 +6688,6 @@ GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
#endif
-#undef GEN_INT_ARITH_SUBF
-#undef GEN_INT_ARITH_SUBF_CONST
-#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
-GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
-#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
- add_ca, compute_ca, compute_ov) \
-GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
-GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
-GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
-GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
-GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
-GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
-GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
-GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
-GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
-GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
-GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
-
#undef GEN_LOGICAL1
#undef GEN_LOGICAL2
#define GEN_LOGICAL2(name, tcg_op, opc, type) \
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc
index 51c6fa7..0c66465 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -325,6 +325,76 @@ static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
return true;
}
+static bool trans_ADDEX(DisasContext *ctx, arg_X *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
+ cpu_ov, cpu_ov32, true, true, false, false);
+ return true;
+}
+
+static bool do_add_D(DisasContext *ctx, arg_D *a, bool add_ca, bool compute_ca,
+ bool compute_ov, bool compute_rc0)
+{
+ gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
+ tcg_constant_tl(a->si), cpu_ca, cpu_ca32,
+ add_ca, compute_ca, compute_ov, compute_rc0);
+ return true;
+}
+
+static bool do_add_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
+ bool compute_ca)
+{
+ gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
+ cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
+ return true;
+}
+
+static bool do_add_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
+ bool add_ca, bool compute_ca)
+{
+ gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
+ cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
+ return true;
+}
+
+TRANS(ADD, do_add_XO, false, false);
+TRANS(ADDC, do_add_XO, false, true);
+TRANS(ADDE, do_add_XO, true, true);
+TRANS(ADDME, do_add_const_XO, tcg_constant_tl(-1LL), true, true);
+TRANS(ADDZE, do_add_const_XO, tcg_constant_tl(0), true, true);
+TRANS(ADDIC, do_add_D, false, true, false, false);
+TRANS(ADDIC_, do_add_D, false, true, false, true);
+
+static bool trans_SUBFIC(DisasContext *ctx, arg_D *a)
+{
+ gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
+ tcg_constant_tl(a->si), false, true, false, false);
+ return true;
+}
+
+static bool do_subf_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
+ bool compute_ca)
+{
+ gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
+ add_ca, compute_ca, a->oe, a->rc);
+ return true;
+}
+
+static bool do_subf_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
+ bool add_ca, bool compute_ca)
+{
+ gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
+ add_ca, compute_ca, a->oe, a->rc);
+ return true;
+}
+
+TRANS(SUBF, do_subf_XO, false, false)
+TRANS(SUBFC, do_subf_XO, false, true)
+TRANS(SUBFE, do_subf_XO, true, true)
+TRANS(SUBFME, do_subf_const_XO, tcg_constant_tl(-1LL), true, true)
+TRANS(SUBFZE, do_subf_const_XO, tcg_constant_tl(0), true, true)
+
static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
{
gen_invalid(ctx);