Adds the IBM PPE42 family of processors supporting the
PPE42, PPE42X and PPE42XM processor versions. These
processors are used as embedded processors in the IBM
Power9, Power10 and Power12 processors for various
tasks. It is basically a stripped down version of the
IBM PowerPC 405 processor, with some added instructions
for handling 64-bit loads and stores.
For more information on the PPE 42 processor please visit:
https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
Supports PPE42 SPR's (Including the MSR) and Exceptions.
Does not yet support new PPE42 instructions and does not
prevent access to some invalid instructions and registers
(currently allows for access to invalid GPR's and CR fields).
Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
---
target/ppc/cpu-models.c | 7 +
target/ppc/cpu-models.h | 4 +
target/ppc/cpu.h | 66 +++++++-
target/ppc/cpu_init.c | 286 ++++++++++++++++++++++++++++++-----
target/ppc/excp_helper.c | 171 +++++++++++++++++++++
target/ppc/helper_regs.c | 28 +++-
target/ppc/tcg-excp_helper.c | 12 ++
target/ppc/translate.c | 6 +-
8 files changed, 535 insertions(+), 45 deletions(-)
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index ea86ea202a..09f73e23a8 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -116,6 +116,13 @@
NULL)
POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
NULL)
+ /* PPE42 Embedded Controllers */
+ POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
+ "Generic PPE 42")
+ POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
+ "Generic PPE 42X")
+ POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
+ "Generic PPE 42XM")
/* PowerPC 440 family */
#if defined(TODO_USER_ONLY)
POWERPC_DEF("440", CPU_POWERPC_440, 440GP,
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index 72ad31ba50..c6cd27f390 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -69,6 +69,10 @@ enum {
/* Xilinx cores */
CPU_POWERPC_X2VP4 = 0x20010820,
CPU_POWERPC_X2VP20 = 0x20010860,
+ /* IBM PPE42 Family */
+ CPU_POWERPC_PPE42 = 0x42000000,
+ CPU_POWERPC_PPE42X = 0x42100000,
+ CPU_POWERPC_PPE42XM = 0x42200000,
/* PowerPC 440 family */
/* Generic PowerPC 440 */
#define CPU_POWERPC_440 CPU_POWERPC_440GXf
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 6b90543811..f2fc84f384 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -220,6 +220,8 @@ typedef enum powerpc_excp_t {
POWERPC_EXCP_POWER10,
/* POWER11 exception model */
POWERPC_EXCP_POWER11,
+ /* PPE42 exception model */
+ POWERPC_EXCP_PPE42,
} powerpc_excp_t;
/*****************************************************************************/
@@ -282,6 +284,8 @@ typedef enum powerpc_input_t {
PPC_FLAGS_INPUT_POWER9,
/* Freescale RCPU bus */
PPC_FLAGS_INPUT_RCPU,
+ /* PPE42 bus */
+ PPC_FLAGS_INPUT_PPE42,
} powerpc_input_t;
#define PPC_INPUT(env) ((env)->bus_model)
@@ -433,39 +437,64 @@ typedef enum {
#define MSR_TM PPC_BIT_NR(31) /* Transactional Memory Available (Book3s) */
#define MSR_CM PPC_BIT_NR(32) /* Computation mode for BookE hflags */
#define MSR_ICM PPC_BIT_NR(33) /* Interrupt computation mode for BookE */
+#define MSR_SEM0 PPC_BIT_NR(33) /* SIB Error Mask Bit 0 (PPE42) */
+#define MSR_SEM1 PPC_BIT_NR(34) /* SIB Error Mask Bit 1 (PPE42) */
+#define MSR_SEM2 PPC_BIT_NR(35) /* SIB Error Mask Bit 2 (PPE42) */
#define MSR_GS PPC_BIT_NR(35) /* guest state for BookE */
+#define MSR_SEM3 PPC_BIT_NR(36) /* SIB Error Mask Bit 3 (PPE42) */
+#define MSR_SEM4 PPC_BIT_NR(37) /* SIB Error Mask Bit 4 (PPE42) */
#define MSR_UCLE PPC_BIT_NR(37) /* User-mode cache lock enable for BookE */
#define MSR_VR PPC_BIT_NR(38) /* altivec available x hflags */
#define MSR_SPE PPC_BIT_NR(38) /* SPE enable for BookE x hflags */
+#define MSR_SEM5 PPC_BIT_NR(38) /* SIB Error Mask Bit 5 (PPE42) */
+#define MSR_SEM6 PPC_BIT_NR(39) /* SIB Error Mask Bit 6 (PPE42) */
#define MSR_VSX PPC_BIT_NR(40) /* Vector Scalar Extension (>= 2.06)x hflags */
+#define MSR_IS0 PPC_BIT_NR(40) /* Instance Specific Bit 0 (PPE42) */
#define MSR_S PPC_BIT_NR(41) /* Secure state */
+#define MSR_SIBRC0 PPC_BIT_NR(41) /* Last SIB return code Bit 0 (PPE42) */
+#define MSR_SIBRC1 PPC_BIT_NR(42) /* Last SIB return code Bit 1 (PPE42) */
+#define MSR_SIBRC2 PPC_BIT_NR(43) /* Last SIB return code Bit 2 (PPE42) */
+#define MSR_LP PPC_BIT_NR(44) /* Low Priority (PPE42) */
#define MSR_KEY PPC_BIT_NR(44) /* key bit on 603e */
#define MSR_POW PPC_BIT_NR(45) /* Power management */
#define MSR_WE PPC_BIT_NR(45) /* Wait State Enable on 405 */
+#define MSR_IS1 PPC_BIT_NR(46) /* Instance Specific Bit 1 (PPE42) */
#define MSR_TGPR PPC_BIT_NR(46) /* TGPR usage on 602/603 x */
#define MSR_CE PPC_BIT_NR(46) /* Critical int. enable on embedded PPC x */
#define MSR_ILE PPC_BIT_NR(47) /* Interrupt little-endian mode */
+#define MSR_UIE PPC_BIT_NR(47) /* Unmaskable Interrupt Enable (PPE42) */
#define MSR_EE PPC_BIT_NR(48) /* External interrupt enable */
#define MSR_PR PPC_BIT_NR(49) /* Problem state hflags */
#define MSR_FP PPC_BIT_NR(50) /* Floating point available hflags */
#define MSR_ME PPC_BIT_NR(51) /* Machine check interrupt enable */
#define MSR_FE0 PPC_BIT_NR(52) /* Floating point exception mode 0 */
+#define MSR_IS2 PPC_BIT_NR(52) /* Instance Specific Bit 2 (PPE42) */
+#define MSR_IS3 PPC_BIT_NR(53) /* Instance Specific Bit 3 (PPE42) */
#define MSR_SE PPC_BIT_NR(53) /* Single-step trace enable x hflags */
#define MSR_DWE PPC_BIT_NR(53) /* Debug wait enable on 405 x */
#define MSR_UBLE PPC_BIT_NR(53) /* User BTB lock enable on e500 x */
#define MSR_BE PPC_BIT_NR(54) /* Branch trace enable x hflags */
#define MSR_DE PPC_BIT_NR(54) /* Debug int. enable on embedded PPC x */
#define MSR_FE1 PPC_BIT_NR(55) /* Floating point exception mode 1 */
+#define MSR_IPE PPC_BIT_NR(55) /* Imprecise Mode Enable (PPE42) */
#define MSR_AL PPC_BIT_NR(56) /* AL bit on POWER */
+#define MSR_SIBRCA0 PPC_BIT_NR(56) /* SIB Return Code Accumulator bit0 (PPE42) */
+#define MSR_SIBRCA1 PPC_BIT_NR(57) /* SIB Return Code Accumulator bit1 (PPE42) */
#define MSR_EP PPC_BIT_NR(57) /* Exception prefix on 601 */
#define MSR_IR PPC_BIT_NR(58) /* Instruction relocate */
#define MSR_IS PPC_BIT_NR(58) /* Instruction address space (BookE) */
+#define MSR_SIBRCA2 PPC_BIT_NR(58) /* SIB Return Code Accumulator bit2 (PPE42) */
+#define MSR_SIBRCA3 PPC_BIT_NR(59) /* SIB Return Code Accumulator bit3 (PPE42) */
#define MSR_DR PPC_BIT_NR(59) /* Data relocate */
#define MSR_DS PPC_BIT_NR(59) /* Data address space (BookE) */
#define MSR_PE PPC_BIT_NR(60) /* Protection enable on 403 */
+#define MSR_SIBRCA4 PPC_BIT_NR(60) /* SIB Return Code Accumulator bit4 (PPE42) */
+#define MSR_SIBRCA5 PPC_BIT_NR(61) /* SIB Return Code Accumulator bit5 (PPE42) */
#define MSR_PX PPC_BIT_NR(61) /* Protection exclusive on 403 x */
#define MSR_PMM PPC_BIT_NR(61) /* Performance monitor mark on POWER x */
#define MSR_RI PPC_BIT_NR(62) /* Recoverable interrupt 1 */
+#define MSR_SIBRCA6 PPC_BIT_NR(62) /* SIB Return Code Accumulator bit6 (PPE42) */
+#define MSR_SIBRCA7 PPC_BIT_NR(63) /* SIB Return Code Accumulator bit7 (PPE42) */
#define MSR_LE PPC_BIT_NR(63) /* Little-endian mode 1 hflags */
FIELD(MSR, SF, MSR_SF, 1)
@@ -517,6 +546,9 @@ FIELD(MSR, PX, MSR_PX, 1)
FIELD(MSR, PMM, MSR_PMM, 1)
FIELD(MSR, RI, MSR_RI, 1)
FIELD(MSR, LE, MSR_LE, 1)
+FIELD(MSR, SEM, MSR_SEM6, 7)
+FIELD(MSR, SIBRC, MSR_SIBRC2, 3)
+FIELD(MSR, SIBRCA, MSR_SIBRCA7, 8)
/*
* FE0 and FE1 bits are not side-by-side
@@ -730,6 +762,21 @@ FIELD(MSR, LE, MSR_LE, 1)
#define ESR_VLEMI PPC_BIT(58) /* VLE operation */
#define ESR_MIF PPC_BIT(62) /* Misaligned instruction (VLE) */
+/* PPE42 Interrupt Status Register bits */
+#define ISR_SRSMS0 PPC_BIT_NR(48) /* System Reset State Machine State 0 */
+#define ISR_SRSMS1 PPC_BIT_NR(49) /* System Reset State Machine State 1 */
+#define ISR_SRSMS2 PPC_BIT_NR(50) /* System Reset State Machine State 2 */
+#define ISR_SRSMS3 PPC_BIT_NR(51) /* System Reset State Machine State 3 */
+#define ISR_EP PPC_BIT_NR(53) /* MSR[EE] Maskable Event Pending */
+#define ISR_PTR PPC_BIT_NR(56) /* Program Interrupt from trap */
+#define ISR_ST PPC_BIT_NR(57) /* Data Interrupt caused by store */
+#define ISR_MFE PPC_BIT_NR(60) /* Multiple Fault Error */
+#define ISR_MCS0 PPC_BIT_NR(61) /* Machine Check Status bit0 */
+#define ISR_MCS1 PPC_BIT_NR(62) /* Machine Check Status bit1 */
+#define ISR_MCS2 PPC_BIT_NR(63) /* Machine Check Status bit2 */
+FIELD(ISR, SRSMS, ISR_SRSMS3, 4)
+FIELD(ISR, MCS, ISR_MCS2, 3)
+
/* Transaction EXception And Summary Register bits */
#define TEXASR_FAILURE_PERSISTENT (63 - 7)
#define TEXASR_DISALLOWED (63 - 8)
@@ -785,6 +832,8 @@ enum {
POWERPC_FLAG_SMT_1LPAR = 0x00800000,
/* Has BHRB */
POWERPC_FLAG_BHRB = 0x01000000,
+ /* Use PPE42-specific behavior */
+ POWERPC_FLAG_PPE42 = 0x02000000,
};
/*
@@ -1750,9 +1799,12 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_BOOKE_CSRR0 (0x03A)
#define SPR_BOOKE_CSRR1 (0x03B)
#define SPR_BOOKE_DEAR (0x03D)
+#define SPR_PPE42_EDR (0x03D)
#define SPR_IAMR (0x03D)
#define SPR_BOOKE_ESR (0x03E)
+#define SPR_PPE42_ISR (0x03E)
#define SPR_BOOKE_IVPR (0x03F)
+#define SPR_PPE42_IVPR (0x03F)
#define SPR_MPC_EIE (0x050)
#define SPR_MPC_EID (0x051)
#define SPR_MPC_NRI (0x052)
@@ -1818,6 +1870,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_TBU40 (0x11E)
#define SPR_SVR (0x11E)
#define SPR_BOOKE_PIR (0x11E)
+#define SPR_PPE42_PIR (0x11E)
#define SPR_PVR (0x11F)
#define SPR_HSPRG0 (0x130)
#define SPR_BOOKE_DBSR (0x130)
@@ -1827,6 +1880,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_BOOKE_EPCR (0x133)
#define SPR_SPURR (0x134)
#define SPR_BOOKE_DBCR0 (0x134)
+#define SPR_PPE42_DBCR (0x134)
#define SPR_IBCR (0x135)
#define SPR_PURR (0x135)
#define SPR_BOOKE_DBCR1 (0x135)
@@ -1844,6 +1898,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_HSRR1 (0x13B)
#define SPR_BOOKE_IAC4 (0x13B)
#define SPR_BOOKE_DAC1 (0x13C)
+#define SPR_PPE42_DACR (0x13C)
#define SPR_MMCRH (0x13C)
#define SPR_DABR2 (0x13D)
#define SPR_BOOKE_DAC2 (0x13D)
@@ -1853,12 +1908,14 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_BOOKE_DVC2 (0x13F)
#define SPR_LPIDR (0x13F)
#define SPR_BOOKE_TSR (0x150)
+#define SPR_PPE42_TSR (0x150)
#define SPR_HMER (0x150)
#define SPR_HMEER (0x151)
#define SPR_PCR (0x152)
#define SPR_HEIR (0x153)
#define SPR_BOOKE_LPIDR (0x152)
#define SPR_BOOKE_TCR (0x154)
+#define SPR_PPE42_TCR (0x154)
#define SPR_BOOKE_TLB0PS (0x158)
#define SPR_BOOKE_TLB1PS (0x159)
#define SPR_BOOKE_TLB2PS (0x15A)
@@ -2528,6 +2585,12 @@ enum {
PPC2_MEM_LWSYNC = 0x0000000000200000ULL,
/* ISA 2.06 BCD assist instructions */
PPC2_BCDA_ISA206 = 0x0000000000400000ULL,
+ /* PPE42 instructions */
+ PPC2_PPE42 = 0x0000000000800000ULL,
+ /* PPE42X instructions */
+ PPC2_PPE42X = 0x0000000001000000ULL,
+ /* PPE42XM instructions */
+ PPC2_PPE42XM = 0x0000000002000000ULL,
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
PPC2_ISA205 | PPC2_VSX207 | PPC2_PERM_ISA206 | \
@@ -2537,7 +2600,8 @@ enum {
PPC2_ALTIVEC_207 | PPC2_ISA207S | PPC2_DFP | \
PPC2_FP_CVT_S64 | PPC2_TM | PPC2_PM_ISA206 | \
PPC2_ISA300 | PPC2_ISA310 | PPC2_MEM_LWSYNC | \
- PPC2_BCDA_ISA206)
+ PPC2_BCDA_ISA206 | PPC2_PPE42 | PPC2_PPE42X | \
+ PPC2_PPE42XM)
};
/*****************************************************************************/
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index a0e77f2673..317670a96b 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -1653,6 +1653,47 @@ static void register_8xx_sprs(CPUPPCState *env)
* ... and more (thermal management, performance counters, ...)
*/
+static void register_ppe42_sprs(CPUPPCState *env)
+{
+ spr_register(env, SPR_PPE42_EDR, "EDR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_PPE42_ISR, "ISR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_PPE42_IVPR, "IVPR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
+ 0xfff80000);
+ spr_register(env, SPR_PPE42_PIR, "PIR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_pir,
+ 0x00000000);
+ spr_register(env, SPR_PPE42_DBCR, "DBCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_40x_dbcr0,
+ 0x00000000);
+ spr_register(env, SPR_PPE42_DACR, "DACR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* Timer */
+ spr_register(env, SPR_DECR, "DECR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_decr, &spr_write_decr,
+ 0x00000000);
+ spr_register(env, SPR_PPE42_TSR, "TSR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_booke_tsr,
+ 0x00000000);
+ spr_register(env, SPR_BOOKE_TCR, "TCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_booke_tcr,
+ 0x00000000);
+}
+
/*****************************************************************************/
/* Exception vectors models */
static void init_excp_4xx(CPUPPCState *env)
@@ -1679,6 +1720,30 @@ static void init_excp_4xx(CPUPPCState *env)
#endif
}
+static void init_excp_ppe42(CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+ /* Machine Check vector changed after version 0 */
+ if (((env->spr[SPR_PVR] & 0xf00000ul) >> 20) == 0) {
+ env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000000;
+ } else {
+ env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000020;
+ }
+ env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000040;
+ env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000060;
+ env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000080;
+ env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x000000A0;
+ env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x000000C0;
+ env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x000000E0;
+ env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000100;
+ env->excp_vectors[POWERPC_EXCP_FIT] = 0x00000120;
+ env->excp_vectors[POWERPC_EXCP_WDT] = 0x00000140;
+ env->ivpr_mask = 0xFFFFFE00UL;
+ /* Hardware reset vector */
+ env->hreset_vector = 0x00000040UL;
+#endif
+}
+
static void init_excp_MPC5xx(CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
@@ -2200,6 +2265,125 @@ POWERPC_FAMILY(405)(ObjectClass *oc, const void *data)
POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
}
+static void init_proc_ppe42(CPUPPCState *env)
+{
+ register_ppe42_sprs(env);
+
+ init_excp_ppe42(env);
+ env->dcache_line_size = 32;
+ env->icache_line_size = 32;
+ /* Allocate hardware IRQ controller */
+ ppc40x_irq_init(env_archcpu(env));
+
+ SET_FIT_PERIOD(8, 12, 16, 20);
+ SET_WDT_PERIOD(16, 20, 24, 28);
+}
+
+POWERPC_FAMILY(ppe42)(ObjectClass *oc, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+ dc->desc = "PPE 42";
+ pcc->init_proc = init_proc_ppe42;
+ pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
+ pcc->insns_flags = PPC_INSNS_BASE |
+ PPC_WRTEE |
+ PPC_CACHE |
+ PPC_CACHE_DCBZ |
+ PPC_MEM_SYNC;
+ pcc->insns_flags2 = PPC2_PPE42;
+ pcc->msr_mask = R_MSR_SEM_MASK |
+ (1ull << MSR_IS0) |
+ R_MSR_SIBRC_MASK |
+ (1ull << MSR_LP) |
+ (1ull << MSR_WE) |
+ (1ull << MSR_IS1) |
+ (1ull << MSR_UIE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_IS2) |
+ (1ull << MSR_IS3) |
+ (1ull << MSR_IPE) |
+ R_MSR_SIBRCA_MASK;
+ pcc->mmu_model = POWERPC_MMU_REAL;
+ pcc->excp_model = POWERPC_EXCP_PPE42;
+ pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
+ pcc->bfd_mach = bfd_mach_ppc_403;
+ pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
+}
+
+POWERPC_FAMILY(ppe42x)(ObjectClass *oc, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+ dc->desc = "PPE 42X";
+ pcc->init_proc = init_proc_ppe42;
+ pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
+ pcc->insns_flags = PPC_INSNS_BASE |
+ PPC_WRTEE |
+ PPC_CACHE |
+ PPC_CACHE_DCBZ |
+ PPC_MEM_SYNC;
+ pcc->insns_flags2 = PPC2_PPE42 | PPC2_PPE42X;
+ pcc->msr_mask = R_MSR_SEM_MASK |
+ (1ull << MSR_IS0) |
+ R_MSR_SIBRC_MASK |
+ (1ull << MSR_LP) |
+ (1ull << MSR_WE) |
+ (1ull << MSR_IS1) |
+ (1ull << MSR_UIE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_IS2) |
+ (1ull << MSR_IS3) |
+ (1ull << MSR_IPE) |
+ R_MSR_SIBRCA_MASK;
+ pcc->mmu_model = POWERPC_MMU_REAL;
+ pcc->excp_model = POWERPC_EXCP_PPE42;
+ pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
+ pcc->bfd_mach = bfd_mach_ppc_403;
+ pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
+}
+
+POWERPC_FAMILY(ppe42xm)(ObjectClass *oc, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+ dc->desc = "PPE 42XM";
+ pcc->init_proc = init_proc_ppe42;
+ pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
+ pcc->insns_flags = PPC_INSNS_BASE |
+ PPC_WRTEE |
+ PPC_CACHE |
+ PPC_CACHE_DCBZ |
+ PPC_MEM_SYNC;
+ pcc->insns_flags2 = PPC2_PPE42 | PPC2_PPE42X | PPC2_PPE42XM;
+ pcc->msr_mask = R_MSR_SEM_MASK |
+ (1ull << MSR_IS0) |
+ R_MSR_SIBRC_MASK |
+ (1ull << MSR_LP) |
+ (1ull << MSR_WE) |
+ (1ull << MSR_IS1) |
+ (1ull << MSR_UIE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_IS2) |
+ (1ull << MSR_IS3) |
+ (1ull << MSR_IPE) |
+ R_MSR_SIBRCA_MASK;
+ pcc->mmu_model = POWERPC_MMU_REAL;
+ pcc->excp_model = POWERPC_EXCP_PPE42;
+ pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
+ pcc->bfd_mach = bfd_mach_ppc_403;
+ pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
+}
+
static void init_proc_440EP(CPUPPCState *env)
{
register_BookE_sprs(env, 0x000000000000FFFFULL);
@@ -6802,53 +6986,63 @@ static void init_ppc_proc(PowerPCCPU *cpu)
/* MSR bits & flags consistency checks */
if (env->msr_mask & (1 << 25)) {
- switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
+ switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE |
+ POWERPC_FLAG_PPE42)) {
case POWERPC_FLAG_SPE:
case POWERPC_FLAG_VRE:
+ case POWERPC_FLAG_PPE42:
break;
default:
fprintf(stderr, "PowerPC MSR definition inconsistency\n"
- "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n");
+ "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n"
+ "or POWERPC_FLAG_PPE42\n");
exit(1);
}
} else if (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
fprintf(stderr, "PowerPC MSR definition inconsistency\n"
- "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n");
+ "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n"
+ "nor POWERPC_FLAG_PPE42\n");
exit(1);
}
if (env->msr_mask & (1 << 17)) {
- switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
+ switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE |
+ POWERPC_FLAG_PPE42)) {
case POWERPC_FLAG_TGPR:
case POWERPC_FLAG_CE:
+ case POWERPC_FLAG_PPE42:
break;
default:
fprintf(stderr, "PowerPC MSR definition inconsistency\n"
- "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n");
+ "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n"
+ "or POWERPC_FLAG_PPE42\n");
exit(1);
}
- } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
+ } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE |
+ POWERPC_FLAG_PPE42)) {
fprintf(stderr, "PowerPC MSR definition inconsistency\n"
- "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n");
+ "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n"
+ "nor POWERPC_FLAG_PPE42\n");
exit(1);
}
if (env->msr_mask & (1 << 10)) {
switch (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
- POWERPC_FLAG_UBLE)) {
+ POWERPC_FLAG_UBLE | POWERPC_FLAG_PPE42)) {
case POWERPC_FLAG_SE:
case POWERPC_FLAG_DWE:
case POWERPC_FLAG_UBLE:
+ case POWERPC_FLAG_PPE42:
break;
default:
fprintf(stderr, "PowerPC MSR definition inconsistency\n"
"Should define POWERPC_FLAG_SE or POWERPC_FLAG_DWE or "
- "POWERPC_FLAG_UBLE\n");
+ "POWERPC_FLAG_UBLE or POWERPC_FLAG_PPE42\n");
exit(1);
}
} else if (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
- POWERPC_FLAG_UBLE)) {
+ POWERPC_FLAG_UBLE | POWERPC_FLAG_PPE42)) {
fprintf(stderr, "PowerPC MSR definition inconsistency\n"
"Should not define POWERPC_FLAG_SE nor POWERPC_FLAG_DWE nor "
- "POWERPC_FLAG_UBLE\n");
+ "POWERPC_FLAG_UBLE nor POWERPC_FLAG_PPE42\n");
exit(1);
}
if (env->msr_mask & (1 << 9)) {
@@ -6867,18 +7061,23 @@ static void init_ppc_proc(PowerPCCPU *cpu)
exit(1);
}
if (env->msr_mask & (1 << 2)) {
- switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
+ switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM |
+ POWERPC_FLAG_PPE42)) {
case POWERPC_FLAG_PX:
case POWERPC_FLAG_PMM:
+ case POWERPC_FLAG_PPE42:
break;
default:
fprintf(stderr, "PowerPC MSR definition inconsistency\n"
- "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n");
+ "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n"
+ "or POWERPC_FLAG_PPE42\n");
exit(1);
}
- } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
+ } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM |
+ POWERPC_FLAG_PPE42)) {
fprintf(stderr, "PowerPC MSR definition inconsistency\n"
- "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n");
+ "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n"
+ "nor POWERPC_FLAG_PPE42\n");
exit(1);
}
if ((env->flags & POWERPC_FLAG_BUS_CLK) == 0) {
@@ -7243,39 +7442,40 @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
}
msr = (target_ulong)0;
- msr |= (target_ulong)MSR_HVB;
- msr |= (target_ulong)1 << MSR_EP;
+ if (!(env->flags & POWERPC_FLAG_PPE42)) {
+ msr |= (target_ulong)MSR_HVB;
+ msr |= (target_ulong)1 << MSR_EP;
#if defined(DO_SINGLE_STEP) && 0
- /* Single step trace mode */
- msr |= (target_ulong)1 << MSR_SE;
- msr |= (target_ulong)1 << MSR_BE;
+ /* Single step trace mode */
+ msr |= (target_ulong)1 << MSR_SE;
+ msr |= (target_ulong)1 << MSR_BE;
#endif
#if defined(CONFIG_USER_ONLY)
- msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
- msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
- msr |= (target_ulong)1 << MSR_FE1;
- msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
- msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
- msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
- msr |= (target_ulong)1 << MSR_PR;
+ msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
+ msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
+ msr |= (target_ulong)1 << MSR_FE1;
+ msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
+ msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
+ msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
+ msr |= (target_ulong)1 << MSR_PR;
#if defined(TARGET_PPC64)
- msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
+ msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
#endif
#if !TARGET_BIG_ENDIAN
- msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
- if (!((env->msr_mask >> MSR_LE) & 1)) {
- fprintf(stderr, "Selected CPU does not support little-endian.\n");
- exit(1);
- }
+ msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
+ if (!((env->msr_mask >> MSR_LE) & 1)) {
+ fprintf(stderr, "Selected CPU does not support little-endian.\n");
+ exit(1);
+ }
#endif
#endif
#if defined(TARGET_PPC64)
- if (mmu_is_64bit(env->mmu_model)) {
- msr |= (1ULL << MSR_SF);
- }
+ if (mmu_is_64bit(env->mmu_model)) {
+ msr |= (1ULL << MSR_SF);
+ }
#endif
-
+ }
hreg_store_msr(env, msr, 1);
#if !defined(CONFIG_USER_ONLY)
@@ -7725,6 +7925,18 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
* they can be read with "p $ivor0", "p $ivor1", etc.
*/
break;
+ case POWERPC_EXCP_PPE42:
+ qemu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx "\n",
+ env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
+
+ qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
+ " ISR " TARGET_FMT_lx " EDR " TARGET_FMT_lx "\n",
+ env->spr[SPR_PPE42_TCR], env->spr[SPR_PPE42_TSR],
+ env->spr[SPR_PPE42_ISR], env->spr[SPR_PPE42_EDR]);
+
+ qemu_fprintf(f, " PIR " TARGET_FMT_lx " IVPR " TARGET_FMT_lx "\n",
+ env->spr[SPR_PPE42_PIR], env->spr[SPR_PPE42_IVPR]);
+ break;
case POWERPC_EXCP_40x:
qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
" ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 1efdc4066e..2e35e63826 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -949,6 +949,133 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
powerpc_set_excp_state(cpu, vector, new_msr);
}
+#define ISR_MCS_INSTRUCTION 0
+#define ISR_MCS_DATA_LOAD 1
+#define ISR_MCS_DATA_PRECISE_STORE 2
+#define ISR_MCS_DATA_IMPRECISE_STORE 3
+#define ISR_MCS_PROGRAM 4
+#define ISR_MCS_ISI 5
+#define ISR_MCS_ALIGNMENT 6
+#define ISR_MCS_DSI 7
+static void powerpc_excp_ppe42(PowerPCCPU *cpu, int excp)
+{
+ CPUPPCState *env = &cpu->env;
+ target_ulong msr, new_msr, vector;
+ target_ulong mcs = ISR_MCS_INSTRUCTION;
+ bool promote_unmaskable;
+
+ msr = env->msr;
+
+ /*
+ * New interrupt handler msr preserves SIBRC and ME unless explicitly
+ * overridden by the exception. All other MSR bits are zeroed out.
+ */
+ new_msr = env->msr & (((target_ulong)1 << MSR_ME) | R_MSR_SIBRC_MASK);
+
+ /* HV emu assistance interrupt only exists on server arch 2.05 or later */
+ if (excp == POWERPC_EXCP_HV_EMU) {
+ excp = POWERPC_EXCP_PROGRAM;
+ }
+
+ /*
+ * Unmaskable interrupts (Program, ISI, Alignment and DSI) are promoted to
+ * machine check if MSR_UIE is 0.
+ */
+ promote_unmaskable = !(msr & ((target_ulong)1 << MSR_UIE));
+
+
+ switch (excp) {
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
+ trace_ppc_excp_dsi(env->spr[SPR_PPE42_ISR], env->spr[SPR_PPE42_EDR]);
+ if (promote_unmaskable) {
+ excp = POWERPC_EXCP_MCHECK;
+ mcs = ISR_MCS_DSI;
+ }
+ break;
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ trace_ppc_excp_isi(msr, env->nip);
+ if (promote_unmaskable) {
+ excp = POWERPC_EXCP_MCHECK;
+ mcs = ISR_MCS_ISI;
+ }
+ break;
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ break;
+ case POWERPC_EXCP_ALIGN: /* Alignment exception */
+ if (promote_unmaskable) {
+ excp = POWERPC_EXCP_MCHECK;
+ mcs = ISR_MCS_ALIGNMENT;
+ }
+ break;
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ if (promote_unmaskable) {
+ excp = POWERPC_EXCP_MCHECK;
+ mcs = ISR_MCS_PROGRAM;
+ }
+ switch (env->error_code & ~0xF) {
+ case POWERPC_EXCP_INVAL:
+ trace_ppc_excp_inval(env->nip);
+ env->spr[SPR_PPE42_ISR] &= ~((target_ulong)1 << ISR_PTR);
+ break;
+ case POWERPC_EXCP_TRAP:
+ env->spr[SPR_PPE42_ISR] |= ((target_ulong)1 << ISR_PTR);
+ break;
+ default:
+ /* Should never occur */
+ cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
+ env->error_code);
+ break;
+ }
+#ifdef CONFIG_TCG
+ env->spr[SPR_PPE42_EDR] = ppc_ldl_code(env, env->nip);
+#endif
+ break;
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ break;
+ case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
+ trace_ppc_excp_print("FIT");
+ break;
+ case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
+ trace_ppc_excp_print("WDT");
+ break;
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ /* reset exceptions don't have ME set */
+ new_msr &= ~((target_ulong)1 << MSR_ME);
+ break;
+ default:
+ cpu_abort(env_cpu(env), "Invalid PPE42 exception %d. Aborting\n",
+ excp);
+ break;
+ }
+
+ env->spr[SPR_SRR0] = env->nip;
+ env->spr[SPR_SRR1] = msr;
+
+ vector = env->excp_vectors[excp];
+ if (vector == (target_ulong)-1ULL) {
+ cpu_abort(env_cpu(env),
+ "Raised an exception without defined vector %d\n", excp);
+ }
+ vector |= env->spr[SPR_PPE42_IVPR];
+
+ if (excp == POWERPC_EXCP_MCHECK) {
+ /* Also set the Machine Check Status (MCS) */
+ env->spr[SPR_PPE42_ISR] &= ~R_ISR_MCS_MASK;
+ env->spr[SPR_PPE42_ISR] |= (mcs & R_ISR_MCS_MASK);
+ env->spr[SPR_PPE42_ISR] &= ~((target_ulong)1 << ISR_MFE);
+
+ /* Machine checks halt execution if MSR_ME is 0 */
+ powerpc_mcheck_checkstop(env);
+
+ /* machine check exceptions don't have ME set */
+ new_msr &= ~((target_ulong)1 << MSR_ME);
+ }
+
+ powerpc_set_excp_state(cpu, vector, new_msr);
+}
+
static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
{
CPUPPCState *env = &cpu->env;
@@ -1589,6 +1716,9 @@ void powerpc_excp(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_POWER11:
powerpc_excp_books(cpu, excp);
break;
+ case POWERPC_EXCP_PPE42:
+ powerpc_excp_ppe42(cpu, excp);
+ break;
default:
g_assert_not_reached();
}
@@ -1945,6 +2075,43 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env,
}
#endif /* TARGET_PPC64 */
+static int ppe42_next_unmasked_interrupt(CPUPPCState *env)
+{
+ bool async_deliver;
+
+ /* External reset */
+ if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
+ return PPC_INTERRUPT_RESET;
+ }
+ /* Machine check exception */
+ if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
+ return PPC_INTERRUPT_MCK;
+ }
+
+ async_deliver = FIELD_EX64(env->msr, MSR, EE);
+
+ if (async_deliver != 0) {
+ /* Watchdog timer */
+ if (env->pending_interrupts & PPC_INTERRUPT_WDT) {
+ return PPC_INTERRUPT_WDT;
+ }
+ /* External Interrupt */
+ if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
+ return PPC_INTERRUPT_EXT;
+ }
+ /* Fixed interval timer */
+ if (env->pending_interrupts & PPC_INTERRUPT_FIT) {
+ return PPC_INTERRUPT_FIT;
+ }
+ /* Decrementer exception */
+ if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
+ return PPC_INTERRUPT_DECR;
+ }
+ }
+
+ return 0;
+}
+
static int ppc_next_unmasked_interrupt(CPUPPCState *env)
{
uint32_t pending_interrupts = env->pending_interrupts;
@@ -1970,6 +2137,10 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
}
#endif
+ if (env->excp_model == POWERPC_EXCP_PPE42) {
+ return ppe42_next_unmasked_interrupt(env);
+ }
+
/* External reset */
if (pending_interrupts & PPC_INTERRUPT_RESET) {
return PPC_INTERRUPT_RESET;
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 7e5726871e..7be00f5bbe 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -186,6 +186,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
if (env->spr[SPR_LPCR] & LPCR_HR) {
hflags |= 1 << HFLAGS_HR;
}
+ if (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))) {
@@ -306,9 +310,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)) {
@@ -319,8 +320,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 MSR has bits overlapping with others */
+ if (!(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
@@ -462,6 +469,17 @@ void register_generic_sprs(PowerPCCPU *cpu)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+
+ if (env->insns_flags2 & PPC2_PPE42) {
+ spr_register(env, SPR_PVR, "PVR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
+ pcc->pvr);
+
+ /* PPE42 doesn't support additional SPRG regs or timebase */
+ return;
+ }
+
spr_register(env, SPR_SPRG1, "SPRG1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
diff --git a/target/ppc/tcg-excp_helper.c b/target/ppc/tcg-excp_helper.c
index f835be5156..14f3ad92fe 100644
--- a/target/ppc/tcg-excp_helper.c
+++ b/target/ppc/tcg-excp_helper.c
@@ -229,6 +229,18 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
case POWERPC_MMU_BOOKE206:
env->spr[SPR_BOOKE_DEAR] = vaddr;
break;
+ case POWERPC_MMU_REAL:
+ if (env->flags & POWERPC_FLAG_PPE42) {
+ env->spr[SPR_PPE42_EDR] = vaddr;
+ if (access_type == MMU_DATA_STORE) {
+ env->spr[SPR_PPE42_ISR] |= ISR_ST;
+ } else {
+ env->spr[SPR_PPE42_ISR] &= ~ISR_ST;
+ }
+ } else {
+ env->spr[SPR_DAR] = vaddr;
+ }
+ break;
default:
env->spr[SPR_DAR] = vaddr;
break;
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 27f90c3cc5..b4f4d10384 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4264,8 +4264,10 @@ static void gen_mtmsr(DisasContext *ctx)
/* L=1 form only updates EE and RI */
mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);
} else {
- /* mtmsr does not alter S, ME, or LE */
- mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
+ if (!(ctx->insns_flags2 & PPC2_PPE42)) {
+ /* mtmsr does not alter S, ME, or LE */
+ mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
+ }
/*
* XXX: we need to update nip before the store if we enter
--
2.43.0
Hi Glenn,
This seems significant work. Thanks for upstreaming.
On 8/20/25 02:58, Glenn Miles wrote:
> Adds the IBM PPE42 family of processors supporting the
family of 32-bit processors ?
> PPE42, PPE42X and PPE42XM processor versions. These
> processors are used as embedded processors in the IBM
> Power9, Power10 and Power12 processors for various
> tasks. It is basically a stripped down version of the
> IBM PowerPC 405 processor, with some added instructions
> for handling 64-bit loads and stores.
>
> For more information on the PPE 42 processor please visit:
>
> https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
>
> Supports PPE42 SPR's (Including the MSR) and Exceptions.
>
> Does not yet support new PPE42 instructions and does not
> prevent access to some invalid instructions and registers
> (currently allows for access to invalid GPR's and CR fields).
>
> Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
> ---
> target/ppc/cpu-models.c | 7 +
> target/ppc/cpu-models.h | 4 +
> target/ppc/cpu.h | 66 +++++++-
> target/ppc/cpu_init.c | 286 ++++++++++++++++++++++++++++++-----
> target/ppc/excp_helper.c | 171 +++++++++++++++++++++
> target/ppc/helper_regs.c | 28 +++-
> target/ppc/tcg-excp_helper.c | 12 ++
> target/ppc/translate.c | 6 +-
> 8 files changed, 535 insertions(+), 45 deletions(-)
>
> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
> index ea86ea202a..09f73e23a8 100644
> --- a/target/ppc/cpu-models.c
> +++ b/target/ppc/cpu-models.c
> @@ -116,6 +116,13 @@
> NULL)
> POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
> NULL)
> + /* PPE42 Embedded Controllers */
> + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
> + "Generic PPE 42")
> + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
> + "Generic PPE 42X")
> + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
> + "Generic PPE 42XM")
Can all the PPE42 specific code be conditionally compiled only for
!TARGET_PPC64 (and !CONFIG_USER_ONLY wherever possible)?
Not only to reduce the bloating size of respective binaries, but also to
avoid some code being added to hot path routines like
hreg_compute_hflags_value().
> /* PowerPC 440 family */
> #if defined(TODO_USER_ONLY)
> POWERPC_DEF("440", CPU_POWERPC_440, 440GP,
> diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
> index 72ad31ba50..c6cd27f390 100644
> --- a/target/ppc/cpu-models.h
> +++ b/target/ppc/cpu-models.h
> @@ -69,6 +69,10 @@ enum {
> /* Xilinx cores */
> CPU_POWERPC_X2VP4 = 0x20010820,
> CPU_POWERPC_X2VP20 = 0x20010860,
> + /* IBM PPE42 Family */
> + CPU_POWERPC_PPE42 = 0x42000000,
> + CPU_POWERPC_PPE42X = 0x42100000,
> + CPU_POWERPC_PPE42XM = 0x42200000,
> /* PowerPC 440 family */
> /* Generic PowerPC 440 */
> #define CPU_POWERPC_440 CPU_POWERPC_440GXf
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 6b90543811..f2fc84f384 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -220,6 +220,8 @@ typedef enum powerpc_excp_t {
> POWERPC_EXCP_POWER10,
> /* POWER11 exception model */
> POWERPC_EXCP_POWER11,
> + /* PPE42 exception model */
> + POWERPC_EXCP_PPE42,
> } powerpc_excp_t;
>
> /*****************************************************************************/
> @@ -282,6 +284,8 @@ typedef enum powerpc_input_t {
> PPC_FLAGS_INPUT_POWER9,
> /* Freescale RCPU bus */
> PPC_FLAGS_INPUT_RCPU,
> + /* PPE42 bus */
> + PPC_FLAGS_INPUT_PPE42,
> } powerpc_input_t;
>
> #define PPC_INPUT(env) ((env)->bus_model)
> @@ -433,39 +437,64 @@ typedef enum {
> #define MSR_TM PPC_BIT_NR(31) /* Transactional Memory Available (Book3s) */
> #define MSR_CM PPC_BIT_NR(32) /* Computation mode for BookE hflags */
> #define MSR_ICM PPC_BIT_NR(33) /* Interrupt computation mode for BookE */
> +#define MSR_SEM0 PPC_BIT_NR(33) /* SIB Error Mask Bit 0 (PPE42) */
> +#define MSR_SEM1 PPC_BIT_NR(34) /* SIB Error Mask Bit 1 (PPE42) */
> +#define MSR_SEM2 PPC_BIT_NR(35) /* SIB Error Mask Bit 2 (PPE42) */
> #define MSR_GS PPC_BIT_NR(35) /* guest state for BookE */
> +#define MSR_SEM3 PPC_BIT_NR(36) /* SIB Error Mask Bit 3 (PPE42) */
> +#define MSR_SEM4 PPC_BIT_NR(37) /* SIB Error Mask Bit 4 (PPE42) */
> #define MSR_UCLE PPC_BIT_NR(37) /* User-mode cache lock enable for BookE */
> #define MSR_VR PPC_BIT_NR(38) /* altivec available x hflags */
> #define MSR_SPE PPC_BIT_NR(38) /* SPE enable for BookE x hflags */
> +#define MSR_SEM5 PPC_BIT_NR(38) /* SIB Error Mask Bit 5 (PPE42) */
> +#define MSR_SEM6 PPC_BIT_NR(39) /* SIB Error Mask Bit 6 (PPE42) */
> #define MSR_VSX PPC_BIT_NR(40) /* Vector Scalar Extension (>= 2.06)x hflags */
> +#define MSR_IS0 PPC_BIT_NR(40) /* Instance Specific Bit 0 (PPE42) */
> #define MSR_S PPC_BIT_NR(41) /* Secure state */
> +#define MSR_SIBRC0 PPC_BIT_NR(41) /* Last SIB return code Bit 0 (PPE42) */
> +#define MSR_SIBRC1 PPC_BIT_NR(42) /* Last SIB return code Bit 1 (PPE42) */
> +#define MSR_SIBRC2 PPC_BIT_NR(43) /* Last SIB return code Bit 2 (PPE42) */
> +#define MSR_LP PPC_BIT_NR(44) /* Low Priority (PPE42) */
> #define MSR_KEY PPC_BIT_NR(44) /* key bit on 603e */
> #define MSR_POW PPC_BIT_NR(45) /* Power management */
> #define MSR_WE PPC_BIT_NR(45) /* Wait State Enable on 405 */
> +#define MSR_IS1 PPC_BIT_NR(46) /* Instance Specific Bit 1 (PPE42) */
> #define MSR_TGPR PPC_BIT_NR(46) /* TGPR usage on 602/603 x */
> #define MSR_CE PPC_BIT_NR(46) /* Critical int. enable on embedded PPC x */
> #define MSR_ILE PPC_BIT_NR(47) /* Interrupt little-endian mode */
> +#define MSR_UIE PPC_BIT_NR(47) /* Unmaskable Interrupt Enable (PPE42) */
> #define MSR_EE PPC_BIT_NR(48) /* External interrupt enable */
> #define MSR_PR PPC_BIT_NR(49) /* Problem state hflags */
> #define MSR_FP PPC_BIT_NR(50) /* Floating point available hflags */
> #define MSR_ME PPC_BIT_NR(51) /* Machine check interrupt enable */
> #define MSR_FE0 PPC_BIT_NR(52) /* Floating point exception mode 0 */
> +#define MSR_IS2 PPC_BIT_NR(52) /* Instance Specific Bit 2 (PPE42) */
> +#define MSR_IS3 PPC_BIT_NR(53) /* Instance Specific Bit 3 (PPE42) */
> #define MSR_SE PPC_BIT_NR(53) /* Single-step trace enable x hflags */
> #define MSR_DWE PPC_BIT_NR(53) /* Debug wait enable on 405 x */
> #define MSR_UBLE PPC_BIT_NR(53) /* User BTB lock enable on e500 x */
> #define MSR_BE PPC_BIT_NR(54) /* Branch trace enable x hflags */
> #define MSR_DE PPC_BIT_NR(54) /* Debug int. enable on embedded PPC x */
> #define MSR_FE1 PPC_BIT_NR(55) /* Floating point exception mode 1 */
> +#define MSR_IPE PPC_BIT_NR(55) /* Imprecise Mode Enable (PPE42) */
> #define MSR_AL PPC_BIT_NR(56) /* AL bit on POWER */
> +#define MSR_SIBRCA0 PPC_BIT_NR(56) /* SIB Return Code Accumulator bit0 (PPE42) */
> +#define MSR_SIBRCA1 PPC_BIT_NR(57) /* SIB Return Code Accumulator bit1 (PPE42) */
> #define MSR_EP PPC_BIT_NR(57) /* Exception prefix on 601 */
> #define MSR_IR PPC_BIT_NR(58) /* Instruction relocate */
> #define MSR_IS PPC_BIT_NR(58) /* Instruction address space (BookE) */
> +#define MSR_SIBRCA2 PPC_BIT_NR(58) /* SIB Return Code Accumulator bit2 (PPE42) */
> +#define MSR_SIBRCA3 PPC_BIT_NR(59) /* SIB Return Code Accumulator bit3 (PPE42) */
> #define MSR_DR PPC_BIT_NR(59) /* Data relocate */
> #define MSR_DS PPC_BIT_NR(59) /* Data address space (BookE) */
> #define MSR_PE PPC_BIT_NR(60) /* Protection enable on 403 */
> +#define MSR_SIBRCA4 PPC_BIT_NR(60) /* SIB Return Code Accumulator bit4 (PPE42) */
> +#define MSR_SIBRCA5 PPC_BIT_NR(61) /* SIB Return Code Accumulator bit5 (PPE42) */
> #define MSR_PX PPC_BIT_NR(61) /* Protection exclusive on 403 x */
> #define MSR_PMM PPC_BIT_NR(61) /* Performance monitor mark on POWER x */
> #define MSR_RI PPC_BIT_NR(62) /* Recoverable interrupt 1 */
> +#define MSR_SIBRCA6 PPC_BIT_NR(62) /* SIB Return Code Accumulator bit6 (PPE42) */
> +#define MSR_SIBRCA7 PPC_BIT_NR(63) /* SIB Return Code Accumulator bit7 (PPE42) */
> #define MSR_LE PPC_BIT_NR(63) /* Little-endian mode 1 hflags */
>
You may keep PPE42 bits together for easier review/maintenance with
conditional compilation getting enabled, but I am ok with either.
> FIELD(MSR, SF, MSR_SF, 1)
> @@ -517,6 +546,9 @@ FIELD(MSR, PX, MSR_PX, 1)
> FIELD(MSR, PMM, MSR_PMM, 1)
> FIELD(MSR, RI, MSR_RI, 1)
> FIELD(MSR, LE, MSR_LE, 1)
> +FIELD(MSR, SEM, MSR_SEM6, 7)
> +FIELD(MSR, SIBRC, MSR_SIBRC2, 3)
> +FIELD(MSR, SIBRCA, MSR_SIBRCA7, 8)
>
> /*
> * FE0 and FE1 bits are not side-by-side
> @@ -730,6 +762,21 @@ FIELD(MSR, LE, MSR_LE, 1)
> #define ESR_VLEMI PPC_BIT(58) /* VLE operation */
> #define ESR_MIF PPC_BIT(62) /* Misaligned instruction (VLE) */
>
> +/* PPE42 Interrupt Status Register bits */
> +#define ISR_SRSMS0 PPC_BIT_NR(48) /* System Reset State Machine State 0 */
> +#define ISR_SRSMS1 PPC_BIT_NR(49) /* System Reset State Machine State 1 */
> +#define ISR_SRSMS2 PPC_BIT_NR(50) /* System Reset State Machine State 2 */
> +#define ISR_SRSMS3 PPC_BIT_NR(51) /* System Reset State Machine State 3 */
> +#define ISR_EP PPC_BIT_NR(53) /* MSR[EE] Maskable Event Pending */
> +#define ISR_PTR PPC_BIT_NR(56) /* Program Interrupt from trap */
> +#define ISR_ST PPC_BIT_NR(57) /* Data Interrupt caused by store */
> +#define ISR_MFE PPC_BIT_NR(60) /* Multiple Fault Error */
> +#define ISR_MCS0 PPC_BIT_NR(61) /* Machine Check Status bit0 */
> +#define ISR_MCS1 PPC_BIT_NR(62) /* Machine Check Status bit1 */
> +#define ISR_MCS2 PPC_BIT_NR(63) /* Machine Check Status bit2 */
Better to have PPE42_ prefix ?
> +FIELD(ISR, SRSMS, ISR_SRSMS3, 4)
> +FIELD(ISR, MCS, ISR_MCS2, 3)
> +
> /* Transaction EXception And Summary Register bits */
> #define TEXASR_FAILURE_PERSISTENT (63 - 7)
> #define TEXASR_DISALLOWED (63 - 8)
> @@ -785,6 +832,8 @@ enum {
> POWERPC_FLAG_SMT_1LPAR = 0x00800000,
> /* Has BHRB */
> POWERPC_FLAG_BHRB = 0x01000000,
> + /* Use PPE42-specific behavior */
> + POWERPC_FLAG_PPE42 = 0x02000000,
> };
>
> /*
> @@ -1750,9 +1799,12 @@ void ppc_compat_add_property(Object *obj, const char *name,
> #define SPR_BOOKE_CSRR0 (0x03A)
> #define SPR_BOOKE_CSRR1 (0x03B)
> #define SPR_BOOKE_DEAR (0x03D)
> +#define SPR_PPE42_EDR (0x03D)
> #define SPR_IAMR (0x03D)
> #define SPR_BOOKE_ESR (0x03E)
> +#define SPR_PPE42_ISR (0x03E)
> #define SPR_BOOKE_IVPR (0x03F)
> +#define SPR_PPE42_IVPR (0x03F)
> #define SPR_MPC_EIE (0x050)
> #define SPR_MPC_EID (0x051)
> #define SPR_MPC_NRI (0x052)
> @@ -1818,6 +1870,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> #define SPR_TBU40 (0x11E)
> #define SPR_SVR (0x11E)
> #define SPR_BOOKE_PIR (0x11E)
> +#define SPR_PPE42_PIR (0x11E)
> #define SPR_PVR (0x11F)
> #define SPR_HSPRG0 (0x130)
> #define SPR_BOOKE_DBSR (0x130)
> @@ -1827,6 +1880,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> #define SPR_BOOKE_EPCR (0x133)
> #define SPR_SPURR (0x134)
> #define SPR_BOOKE_DBCR0 (0x134)
> +#define SPR_PPE42_DBCR (0x134)
> #define SPR_IBCR (0x135)
> #define SPR_PURR (0x135)
> #define SPR_BOOKE_DBCR1 (0x135)
> @@ -1844,6 +1898,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> #define SPR_HSRR1 (0x13B)
> #define SPR_BOOKE_IAC4 (0x13B)
> #define SPR_BOOKE_DAC1 (0x13C)
> +#define SPR_PPE42_DACR (0x13C)
> #define SPR_MMCRH (0x13C)
> #define SPR_DABR2 (0x13D)
> #define SPR_BOOKE_DAC2 (0x13D)
> @@ -1853,12 +1908,14 @@ void ppc_compat_add_property(Object *obj, const char *name,
> #define SPR_BOOKE_DVC2 (0x13F)
> #define SPR_LPIDR (0x13F)
> #define SPR_BOOKE_TSR (0x150)
> +#define SPR_PPE42_TSR (0x150)
> #define SPR_HMER (0x150)
> #define SPR_HMEER (0x151)
> #define SPR_PCR (0x152)
> #define SPR_HEIR (0x153)
> #define SPR_BOOKE_LPIDR (0x152)
> #define SPR_BOOKE_TCR (0x154)
> +#define SPR_PPE42_TCR (0x154)
> #define SPR_BOOKE_TLB0PS (0x158)
> #define SPR_BOOKE_TLB1PS (0x159)
> #define SPR_BOOKE_TLB2PS (0x15A)
> @@ -2528,6 +2585,12 @@ enum {
> PPC2_MEM_LWSYNC = 0x0000000000200000ULL,
> /* ISA 2.06 BCD assist instructions */
> PPC2_BCDA_ISA206 = 0x0000000000400000ULL,
> + /* PPE42 instructions */
> + PPC2_PPE42 = 0x0000000000800000ULL,
> + /* PPE42X instructions */
> + PPC2_PPE42X = 0x0000000001000000ULL,
> + /* PPE42XM instructions */
> + PPC2_PPE42XM = 0x0000000002000000ULL,
>
> #define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
> PPC2_ISA205 | PPC2_VSX207 | PPC2_PERM_ISA206 | \
> @@ -2537,7 +2600,8 @@ enum {
> PPC2_ALTIVEC_207 | PPC2_ISA207S | PPC2_DFP | \
> PPC2_FP_CVT_S64 | PPC2_TM | PPC2_PM_ISA206 | \
> PPC2_ISA300 | PPC2_ISA310 | PPC2_MEM_LWSYNC | \
> - PPC2_BCDA_ISA206)
> + PPC2_BCDA_ISA206 | PPC2_PPE42 | PPC2_PPE42X | \
> + PPC2_PPE42XM)
> };
>
> /*****************************************************************************/
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index a0e77f2673..317670a96b 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -1653,6 +1653,47 @@ static void register_8xx_sprs(CPUPPCState *env)
> * ... and more (thermal management, performance counters, ...)
> */
>
> +static void register_ppe42_sprs(CPUPPCState *env)
> +{
> + spr_register(env, SPR_PPE42_EDR, "EDR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_write_generic,
> + 0x00000000);
> + spr_register(env, SPR_PPE42_ISR, "ISR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_write_generic,
> + 0x00000000);
> + spr_register(env, SPR_PPE42_IVPR, "IVPR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, SPR_NOACCESS,
> + 0xfff80000);
> + spr_register(env, SPR_PPE42_PIR, "PIR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_write_pir,
> + 0x00000000);
> + spr_register(env, SPR_PPE42_DBCR, "DBCR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_write_40x_dbcr0,
> + 0x00000000);
> + spr_register(env, SPR_PPE42_DACR, "DACR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_write_generic,
> + 0x00000000);
> + /* Timer */
> + spr_register(env, SPR_DECR, "DECR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_decr, &spr_write_decr,
> + 0x00000000);
> + spr_register(env, SPR_PPE42_TSR, "TSR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_write_booke_tsr,
> + 0x00000000);
> + spr_register(env, SPR_BOOKE_TCR, "TCR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_write_booke_tcr,
> + 0x00000000);
> +}
> +
> /*****************************************************************************/
> /* Exception vectors models */
> static void init_excp_4xx(CPUPPCState *env)
> @@ -1679,6 +1720,30 @@ static void init_excp_4xx(CPUPPCState *env)
> #endif
> }
>
> +static void init_excp_ppe42(CPUPPCState *env)
> +{
> +#if !defined(CONFIG_USER_ONLY)
> + /* Machine Check vector changed after version 0 */
> + if (((env->spr[SPR_PVR] & 0xf00000ul) >> 20) == 0) {
> + env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000000;
> + } else {
> + env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000020;
> + }
> + env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000040;
> + env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000060;
> + env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000080;
> + env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x000000A0;
> + env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x000000C0;
> + env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x000000E0;
> + env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000100;
> + env->excp_vectors[POWERPC_EXCP_FIT] = 0x00000120;
> + env->excp_vectors[POWERPC_EXCP_WDT] = 0x00000140;
> + env->ivpr_mask = 0xFFFFFE00UL;
> + /* Hardware reset vector */
> + env->hreset_vector = 0x00000040UL;
> +#endif
> +}
> +
> static void init_excp_MPC5xx(CPUPPCState *env)
> {
> #if !defined(CONFIG_USER_ONLY)
> @@ -2200,6 +2265,125 @@ POWERPC_FAMILY(405)(ObjectClass *oc, const void *data)
> POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
> }
>
> +static void init_proc_ppe42(CPUPPCState *env)
> +{
> + register_ppe42_sprs(env);
> +
> + init_excp_ppe42(env);
> + env->dcache_line_size = 32;
> + env->icache_line_size = 32;
> + /* Allocate hardware IRQ controller */
> + ppc40x_irq_init(env_archcpu(env));
> +
> + SET_FIT_PERIOD(8, 12, 16, 20);
> + SET_WDT_PERIOD(16, 20, 24, 28);
> +}
> +
> +POWERPC_FAMILY(ppe42)(ObjectClass *oc, const void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> +
> + dc->desc = "PPE 42";
> + pcc->init_proc = init_proc_ppe42;
> + pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> + pcc->insns_flags = PPC_INSNS_BASE |
> + PPC_WRTEE |
> + PPC_CACHE |
> + PPC_CACHE_DCBZ |
> + PPC_MEM_SYNC;
> + pcc->insns_flags2 = PPC2_PPE42;
> + pcc->msr_mask = R_MSR_SEM_MASK |
> + (1ull << MSR_IS0) |
> + R_MSR_SIBRC_MASK |
> + (1ull << MSR_LP) |
> + (1ull << MSR_WE) |
> + (1ull << MSR_IS1) |
> + (1ull << MSR_UIE) |
> + (1ull << MSR_EE) |
> + (1ull << MSR_ME) |
> + (1ull << MSR_IS2) |
> + (1ull << MSR_IS3) |
> + (1ull << MSR_IPE) |
> + R_MSR_SIBRCA_MASK;
> + pcc->mmu_model = POWERPC_MMU_REAL;
> + pcc->excp_model = POWERPC_EXCP_PPE42;
> + pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
> + pcc->bfd_mach = bfd_mach_ppc_403;
> + pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
This shares common code with ppe42x and ppe42xm variants.
Could this be re-used from a common routine?
> +}
> +
> +POWERPC_FAMILY(ppe42x)(ObjectClass *oc, const void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> +
> + dc->desc = "PPE 42X";
> + pcc->init_proc = init_proc_ppe42;
> + pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> + pcc->insns_flags = PPC_INSNS_BASE |
> + PPC_WRTEE |
> + PPC_CACHE |
> + PPC_CACHE_DCBZ |
> + PPC_MEM_SYNC;
> + pcc->insns_flags2 = PPC2_PPE42 | PPC2_PPE42X;
> + pcc->msr_mask = R_MSR_SEM_MASK |
> + (1ull << MSR_IS0) |
> + R_MSR_SIBRC_MASK |
> + (1ull << MSR_LP) |
> + (1ull << MSR_WE) |
> + (1ull << MSR_IS1) |
> + (1ull << MSR_UIE) |
> + (1ull << MSR_EE) |
> + (1ull << MSR_ME) |
> + (1ull << MSR_IS2) |
> + (1ull << MSR_IS3) |
> + (1ull << MSR_IPE) |
> + R_MSR_SIBRCA_MASK;
> + pcc->mmu_model = POWERPC_MMU_REAL;
> + pcc->excp_model = POWERPC_EXCP_PPE42;
> + pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
> + pcc->bfd_mach = bfd_mach_ppc_403;
> + pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
> +}
> +
> +POWERPC_FAMILY(ppe42xm)(ObjectClass *oc, const void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> +
> + dc->desc = "PPE 42XM";
> + pcc->init_proc = init_proc_ppe42;
> + pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> + pcc->insns_flags = PPC_INSNS_BASE |
> + PPC_WRTEE |
> + PPC_CACHE |
> + PPC_CACHE_DCBZ |
> + PPC_MEM_SYNC;
> + pcc->insns_flags2 = PPC2_PPE42 | PPC2_PPE42X | PPC2_PPE42XM;
> + pcc->msr_mask = R_MSR_SEM_MASK |
> + (1ull << MSR_IS0) |
> + R_MSR_SIBRC_MASK |
> + (1ull << MSR_LP) |
> + (1ull << MSR_WE) |
> + (1ull << MSR_IS1) |
> + (1ull << MSR_UIE) |
> + (1ull << MSR_EE) |
> + (1ull << MSR_ME) |
> + (1ull << MSR_IS2) |
> + (1ull << MSR_IS3) |
> + (1ull << MSR_IPE) |
> + R_MSR_SIBRCA_MASK;
> + pcc->mmu_model = POWERPC_MMU_REAL;
> + pcc->excp_model = POWERPC_EXCP_PPE42;
> + pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
> + pcc->bfd_mach = bfd_mach_ppc_403;
> + pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
> +}
> +
> static void init_proc_440EP(CPUPPCState *env)
> {
> register_BookE_sprs(env, 0x000000000000FFFFULL);
> @@ -6802,53 +6986,63 @@ static void init_ppc_proc(PowerPCCPU *cpu)
>
> /* MSR bits & flags consistency checks */
> if (env->msr_mask & (1 << 25)) {
> - switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
> + switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE |
> + POWERPC_FLAG_PPE42)) {
> case POWERPC_FLAG_SPE:
> case POWERPC_FLAG_VRE:
> + case POWERPC_FLAG_PPE42:
> break;
> default:
> fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> - "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n");
> + "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n"
> + "or POWERPC_FLAG_PPE42\n");
> exit(1);
> }
> } else if (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
> fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> - "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n");
> + "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n"
> + "nor POWERPC_FLAG_PPE42\n");
> exit(1);
> }
> if (env->msr_mask & (1 << 17)) {
> - switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
> + switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE |
> + POWERPC_FLAG_PPE42)) {
> case POWERPC_FLAG_TGPR:
> case POWERPC_FLAG_CE:
> + case POWERPC_FLAG_PPE42:
> break;
> default:
> fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> - "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n");
> + "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n"
> + "or POWERPC_FLAG_PPE42\n");
> exit(1);
> }
> - } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
> + } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE |
> + POWERPC_FLAG_PPE42)) {
> fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> - "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n");
> + "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n"
> + "nor POWERPC_FLAG_PPE42\n");
> exit(1);
> }
> if (env->msr_mask & (1 << 10)) {
> switch (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
> - POWERPC_FLAG_UBLE)) {
> + POWERPC_FLAG_UBLE | POWERPC_FLAG_PPE42)) {
> case POWERPC_FLAG_SE:
> case POWERPC_FLAG_DWE:
> case POWERPC_FLAG_UBLE:
> + case POWERPC_FLAG_PPE42:
> break;
> default:
> fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> "Should define POWERPC_FLAG_SE or POWERPC_FLAG_DWE or "
> - "POWERPC_FLAG_UBLE\n");
> + "POWERPC_FLAG_UBLE or POWERPC_FLAG_PPE42\n");
> exit(1);
> }
> } else if (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
> - POWERPC_FLAG_UBLE)) {
> + POWERPC_FLAG_UBLE | POWERPC_FLAG_PPE42)) {
> fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> "Should not define POWERPC_FLAG_SE nor POWERPC_FLAG_DWE nor "
> - "POWERPC_FLAG_UBLE\n");
> + "POWERPC_FLAG_UBLE nor POWERPC_FLAG_PPE42\n");
> exit(1);
> }
> if (env->msr_mask & (1 << 9)) {
> @@ -6867,18 +7061,23 @@ static void init_ppc_proc(PowerPCCPU *cpu)
> exit(1);
> }
> if (env->msr_mask & (1 << 2)) {
> - switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
> + switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM |
> + POWERPC_FLAG_PPE42)) {
> case POWERPC_FLAG_PX:
> case POWERPC_FLAG_PMM:
> + case POWERPC_FLAG_PPE42:
> break;
> default:
> fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> - "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n");
> + "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n"
> + "or POWERPC_FLAG_PPE42\n");
> exit(1);
> }
> - } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
> + } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM |
> + POWERPC_FLAG_PPE42)) {
> fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> - "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n");
> + "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n"
> + "nor POWERPC_FLAG_PPE42\n");
> exit(1);
> }
> if ((env->flags & POWERPC_FLAG_BUS_CLK) == 0) {
> @@ -7243,39 +7442,40 @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
> }
>
> msr = (target_ulong)0;
> - msr |= (target_ulong)MSR_HVB;
> - msr |= (target_ulong)1 << MSR_EP;
> + if (!(env->flags & POWERPC_FLAG_PPE42)) {
> + msr |= (target_ulong)MSR_HVB;
> + msr |= (target_ulong)1 << MSR_EP;
> #if defined(DO_SINGLE_STEP) && 0
> - /* Single step trace mode */
> - msr |= (target_ulong)1 << MSR_SE;
> - msr |= (target_ulong)1 << MSR_BE;
> + /* Single step trace mode */
> + msr |= (target_ulong)1 << MSR_SE;
> + msr |= (target_ulong)1 << MSR_BE;
> #endif
> #if defined(CONFIG_USER_ONLY)
> - msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
> - msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
> - msr |= (target_ulong)1 << MSR_FE1;
> - msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
> - msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
> - msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
> - msr |= (target_ulong)1 << MSR_PR;
> + msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
> + msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
> + msr |= (target_ulong)1 << MSR_FE1;
> + msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
> + msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
> + msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
> + msr |= (target_ulong)1 << MSR_PR;
> #if defined(TARGET_PPC64)
> - msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
> + msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
> #endif
> #if !TARGET_BIG_ENDIAN
> - msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
> - if (!((env->msr_mask >> MSR_LE) & 1)) {
> - fprintf(stderr, "Selected CPU does not support little-endian.\n");
> - exit(1);
> - }
> + msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
> + if (!((env->msr_mask >> MSR_LE) & 1)) {
> + fprintf(stderr, "Selected CPU does not support little-endian.\n");
> + exit(1);
> + }
> #endif
> #endif
>
> #if defined(TARGET_PPC64)
> - if (mmu_is_64bit(env->mmu_model)) {
> - msr |= (1ULL << MSR_SF);
> - }
> + if (mmu_is_64bit(env->mmu_model)) {
> + msr |= (1ULL << MSR_SF);
> + }
> #endif
> -
> + }
> hreg_store_msr(env, msr, 1);
>
> #if !defined(CONFIG_USER_ONLY)
> @@ -7725,6 +7925,18 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> * they can be read with "p $ivor0", "p $ivor1", etc.
> */
> break;
> + case POWERPC_EXCP_PPE42:
> + qemu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx "\n",
> + env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
> +
> + qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
> + " ISR " TARGET_FMT_lx " EDR " TARGET_FMT_lx "\n",
> + env->spr[SPR_PPE42_TCR], env->spr[SPR_PPE42_TSR],
> + env->spr[SPR_PPE42_ISR], env->spr[SPR_PPE42_EDR]);
> +
> + qemu_fprintf(f, " PIR " TARGET_FMT_lx " IVPR " TARGET_FMT_lx "\n",
> + env->spr[SPR_PPE42_PIR], env->spr[SPR_PPE42_IVPR]);
> + break;
> case POWERPC_EXCP_40x:
> qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
> " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index 1efdc4066e..2e35e63826 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -949,6 +949,133 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
> powerpc_set_excp_state(cpu, vector, new_msr);
> }
>
> +#define ISR_MCS_INSTRUCTION 0
> +#define ISR_MCS_DATA_LOAD 1
> +#define ISR_MCS_DATA_PRECISE_STORE 2
> +#define ISR_MCS_DATA_IMPRECISE_STORE 3
> +#define ISR_MCS_PROGRAM 4
> +#define ISR_MCS_ISI 5
> +#define ISR_MCS_ALIGNMENT 6
> +#define ISR_MCS_DSI 7
Should these have a PPE42_ prefix?
Also, may better be kept in cpu.h alongwith other PPE42 ISR bits ?
> +static void powerpc_excp_ppe42(PowerPCCPU *cpu, int excp)
> +{
> + CPUPPCState *env = &cpu->env;
> + target_ulong msr, new_msr, vector;
> + target_ulong mcs = ISR_MCS_INSTRUCTION;
> + bool promote_unmaskable;
> +
> + msr = env->msr;
> +
> + /*
> + * New interrupt handler msr preserves SIBRC and ME unless explicitly
> + * overridden by the exception. All other MSR bits are zeroed out.
> + */
> + new_msr = env->msr & (((target_ulong)1 << MSR_ME) | R_MSR_SIBRC_MASK);
> +
> + /* HV emu assistance interrupt only exists on server arch 2.05 or later */
> + if (excp == POWERPC_EXCP_HV_EMU) {
> + excp = POWERPC_EXCP_PROGRAM;
> + }
> +
> + /*
> + * Unmaskable interrupts (Program, ISI, Alignment and DSI) are promoted to
> + * machine check if MSR_UIE is 0.
> + */
> + promote_unmaskable = !(msr & ((target_ulong)1 << MSR_UIE));
> +
> +
> + switch (excp) {
> + case POWERPC_EXCP_MCHECK: /* Machine check exception */
> + break;
> + case POWERPC_EXCP_DSI: /* Data storage exception */
> + trace_ppc_excp_dsi(env->spr[SPR_PPE42_ISR], env->spr[SPR_PPE42_EDR]);
> + if (promote_unmaskable) {
> + excp = POWERPC_EXCP_MCHECK;
> + mcs = ISR_MCS_DSI;
> + }
> + break;
> + case POWERPC_EXCP_ISI: /* Instruction storage exception */
> + trace_ppc_excp_isi(msr, env->nip);
> + if (promote_unmaskable) {
> + excp = POWERPC_EXCP_MCHECK;
> + mcs = ISR_MCS_ISI;
> + }
> + break;
> + case POWERPC_EXCP_EXTERNAL: /* External input */
> + break;
> + case POWERPC_EXCP_ALIGN: /* Alignment exception */
> + if (promote_unmaskable) {
> + excp = POWERPC_EXCP_MCHECK;
> + mcs = ISR_MCS_ALIGNMENT;
> + }
> + break;
> + case POWERPC_EXCP_PROGRAM: /* Program exception */
> + if (promote_unmaskable) {
> + excp = POWERPC_EXCP_MCHECK;
> + mcs = ISR_MCS_PROGRAM;
> + }
> + switch (env->error_code & ~0xF) {
> + case POWERPC_EXCP_INVAL:
> + trace_ppc_excp_inval(env->nip);
> + env->spr[SPR_PPE42_ISR] &= ~((target_ulong)1 << ISR_PTR);
> + break;
> + case POWERPC_EXCP_TRAP:
> + env->spr[SPR_PPE42_ISR] |= ((target_ulong)1 << ISR_PTR);
> + break;
> + default:
> + /* Should never occur */
> + cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
> + env->error_code);
> + break;
> + }
> +#ifdef CONFIG_TCG
> + env->spr[SPR_PPE42_EDR] = ppc_ldl_code(env, env->nip);
> +#endif
> + break;
> + case POWERPC_EXCP_DECR: /* Decrementer exception */
> + break;
> + case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
> + trace_ppc_excp_print("FIT");
> + break;
> + case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
> + trace_ppc_excp_print("WDT");
> + break;
> + case POWERPC_EXCP_RESET: /* System reset exception */
> + /* reset exceptions don't have ME set */
> + new_msr &= ~((target_ulong)1 << MSR_ME);
> + break;
> + default:
> + cpu_abort(env_cpu(env), "Invalid PPE42 exception %d. Aborting\n",
> + excp);
> + break;
> + }
> +
> + env->spr[SPR_SRR0] = env->nip;
> + env->spr[SPR_SRR1] = msr;
> +
> + vector = env->excp_vectors[excp];
> + if (vector == (target_ulong)-1ULL) {
> + cpu_abort(env_cpu(env),
> + "Raised an exception without defined vector %d\n", excp);
> + }
> + vector |= env->spr[SPR_PPE42_IVPR];
> +
> + if (excp == POWERPC_EXCP_MCHECK) {
> + /* Also set the Machine Check Status (MCS) */
> + env->spr[SPR_PPE42_ISR] &= ~R_ISR_MCS_MASK;
> + env->spr[SPR_PPE42_ISR] |= (mcs & R_ISR_MCS_MASK);
> + env->spr[SPR_PPE42_ISR] &= ~((target_ulong)1 << ISR_MFE);
> +
> + /* Machine checks halt execution if MSR_ME is 0 */
> + powerpc_mcheck_checkstop(env);
> +
> + /* machine check exceptions don't have ME set */
> + new_msr &= ~((target_ulong)1 << MSR_ME);
> + }
> +
> + powerpc_set_excp_state(cpu, vector, new_msr);
> +}
> +
> static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
> {
> CPUPPCState *env = &cpu->env;
> @@ -1589,6 +1716,9 @@ void powerpc_excp(PowerPCCPU *cpu, int excp)
> case POWERPC_EXCP_POWER11:
> powerpc_excp_books(cpu, excp);
> break;
> + case POWERPC_EXCP_PPE42:
> + powerpc_excp_ppe42(cpu, excp);
> + break;
> default:
> g_assert_not_reached();
> }
> @@ -1945,6 +2075,43 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env,
> }
> #endif /* TARGET_PPC64 */
>
> +static int ppe42_next_unmasked_interrupt(CPUPPCState *env)
> +{
> + bool async_deliver;
> +
> + /* External reset */
> + if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
> + return PPC_INTERRUPT_RESET;
> + }
> + /* Machine check exception */
> + if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
> + return PPC_INTERRUPT_MCK;
> + }
> +
> + async_deliver = FIELD_EX64(env->msr, MSR, EE);
> +
> + if (async_deliver != 0) {
> + /* Watchdog timer */
> + if (env->pending_interrupts & PPC_INTERRUPT_WDT) {
> + return PPC_INTERRUPT_WDT;
> + }
> + /* External Interrupt */
> + if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
> + return PPC_INTERRUPT_EXT;
> + }
> + /* Fixed interval timer */
> + if (env->pending_interrupts & PPC_INTERRUPT_FIT) {
> + return PPC_INTERRUPT_FIT;
> + }
> + /* Decrementer exception */
> + if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
> + return PPC_INTERRUPT_DECR;
> + }
> + }
> +
> + return 0;
> +}
> +
> static int ppc_next_unmasked_interrupt(CPUPPCState *env)
> {
> uint32_t pending_interrupts = env->pending_interrupts;
> @@ -1970,6 +2137,10 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
> }
> #endif
>
> + if (env->excp_model == POWERPC_EXCP_PPE42) {
> + return ppe42_next_unmasked_interrupt(env);
> + }
> +
> /* External reset */
> if (pending_interrupts & PPC_INTERRUPT_RESET) {
> return PPC_INTERRUPT_RESET;
> diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
> index 7e5726871e..7be00f5bbe 100644
> --- a/target/ppc/helper_regs.c
> +++ b/target/ppc/helper_regs.c
> @@ -186,6 +186,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
> if (env->spr[SPR_LPCR] & LPCR_HR) {
> hflags |= 1 << HFLAGS_HR;
> }
> + if (ppc_flags & POWERPC_FLAG_PPE42) {
> + /* PPE42 has a single address space and no problem state */
> + msr = 0;
> + }
We really dont want this to be checked on PPC64 machines, hence
!TARGET_PPC64 needed.
>
> #ifndef CONFIG_USER_ONLY
> if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) {
> @@ -306,9 +310,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)) {
> @@ -319,8 +320,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 MSR has bits overlapping with others */
> + if (!(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
> @@ -462,6 +469,17 @@ void register_generic_sprs(PowerPCCPU *cpu)
> SPR_NOACCESS, SPR_NOACCESS,
> &spr_read_generic, &spr_write_generic,
> 0x00000000);
> +
> + if (env->insns_flags2 & PPC2_PPE42) {
> + spr_register(env, SPR_PVR, "PVR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, SPR_NOACCESS,
> + pcc->pvr);
> +
> + /* PPE42 doesn't support additional SPRG regs or timebase */
> + return;
> + }
> +
> spr_register(env, SPR_SPRG1, "SPRG1",
> SPR_NOACCESS, SPR_NOACCESS,
> &spr_read_generic, &spr_write_generic,
> diff --git a/target/ppc/tcg-excp_helper.c b/target/ppc/tcg-excp_helper.c
> index f835be5156..14f3ad92fe 100644
> --- a/target/ppc/tcg-excp_helper.c
> +++ b/target/ppc/tcg-excp_helper.c
> @@ -229,6 +229,18 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
> case POWERPC_MMU_BOOKE206:
> env->spr[SPR_BOOKE_DEAR] = vaddr;
> break;
> + case POWERPC_MMU_REAL:
> + if (env->flags & POWERPC_FLAG_PPE42) {
> + env->spr[SPR_PPE42_EDR] = vaddr;
> + if (access_type == MMU_DATA_STORE) {
> + env->spr[SPR_PPE42_ISR] |= ISR_ST;
> + } else {
> + env->spr[SPR_PPE42_ISR] &= ~ISR_ST;
> + }
> + } else {
> + env->spr[SPR_DAR] = vaddr;
> + }
> + break;
> default:
> env->spr[SPR_DAR] = vaddr;
> break;
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 27f90c3cc5..b4f4d10384 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -4264,8 +4264,10 @@ static void gen_mtmsr(DisasContext *ctx)
> /* L=1 form only updates EE and RI */
> mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);
> } else {
> - /* mtmsr does not alter S, ME, or LE */
> - mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
> + if (!(ctx->insns_flags2 & PPC2_PPE42)) {
you may want to use likely() in above check?
Also check other instances wherever applicable.
Thanks
Harsh
> + /* mtmsr does not alter S, ME, or LE */
> + mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
> + }
>
> /*
> * XXX: we need to update nip before the store if we enter
Hi Harsh, Thanks for taking a look! Please see inline responses below.
On Mon, 2025-08-25 at 16:54 +0530, Harsh Prateek Bora wrote:
> Hi Glenn,
>
> This seems significant work. Thanks for upstreaming.
>
> On 8/20/25 02:58, Glenn Miles wrote:
> > Adds the IBM PPE42 family of processors supporting the
>
> family of 32-bit processors ?
Sure, I can add that to the commit message.
>
> > PPE42, PPE42X and PPE42XM processor versions. These
> > processors are used as embedded processors in the IBM
> > Power9, Power10 and Power12 processors for various
> > tasks. It is basically a stripped down version of the
> > IBM PowerPC 405 processor, with some added instructions
> > for handling 64-bit loads and stores.
> >
> > For more information on the PPE 42 processor please visit:
> >
> > https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
> >
> > Supports PPE42 SPR's (Including the MSR) and Exceptions.
> >
> > Does not yet support new PPE42 instructions and does not
> > prevent access to some invalid instructions and registers
> > (currently allows for access to invalid GPR's and CR fields).
> >
> > Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
> > ---
> > target/ppc/cpu-models.c | 7 +
> > target/ppc/cpu-models.h | 4 +
> > target/ppc/cpu.h | 66 +++++++-
> > target/ppc/cpu_init.c | 286 ++++++++++++++++++++++++++++++-----
> > target/ppc/excp_helper.c | 171 +++++++++++++++++++++
> > target/ppc/helper_regs.c | 28 +++-
> > target/ppc/tcg-excp_helper.c | 12 ++
> > target/ppc/translate.c | 6 +-
> > 8 files changed, 535 insertions(+), 45 deletions(-)
> >
> > diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
> > index ea86ea202a..09f73e23a8 100644
> > --- a/target/ppc/cpu-models.c
> > +++ b/target/ppc/cpu-models.c
> > @@ -116,6 +116,13 @@
> > NULL)
> > POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
> > NULL)
> > + /* PPE42 Embedded Controllers */
> > + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
> > + "Generic PPE 42")
> > + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
> > + "Generic PPE 42X")
> > + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
> > + "Generic PPE 42XM")
>
> Can all the PPE42 specific code be conditionally compiled only for
> !TARGET_PPC64 (and !CONFIG_USER_ONLY wherever possible)?
> Not only to reduce the bloating size of respective binaries, but also to
> avoid some code being added to hot path routines like
> hreg_compute_hflags_value().
>
Harsh, it sounds like there is a desire to keep the 32-bit CPU support
enabled even for the 64-bit executable, so I will keep it in for now
and I will audit the code for adding more likely/unlikely statements to
conditionals where it makes sense to do so. Would that be acceptable?
> > /* PowerPC 440 family */
> > #if defined(TODO_USER_ONLY)
> > POWERPC_DEF("440", CPU_POWERPC_440, 440GP,
> > diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
> > index 72ad31ba50..c6cd27f390 100644
> > --- a/target/ppc/cpu-models.h
> > +++ b/target/ppc/cpu-models.h
> > @@ -69,6 +69,10 @@ enum {
> > /* Xilinx cores */
> > CPU_POWERPC_X2VP4 = 0x20010820,
> > CPU_POWERPC_X2VP20 = 0x20010860,
> > + /* IBM PPE42 Family */
> > + CPU_POWERPC_PPE42 = 0x42000000,
> > + CPU_POWERPC_PPE42X = 0x42100000,
> > + CPU_POWERPC_PPE42XM = 0x42200000,
> > /* PowerPC 440 family */
> > /* Generic PowerPC 440 */
> > #define CPU_POWERPC_440 CPU_POWERPC_440GXf
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index 6b90543811..f2fc84f384 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -220,6 +220,8 @@ typedef enum powerpc_excp_t {
> > POWERPC_EXCP_POWER10,
> > /* POWER11 exception model */
> > POWERPC_EXCP_POWER11,
> > + /* PPE42 exception model */
> > + POWERPC_EXCP_PPE42,
> > } powerpc_excp_t;
> >
> > /*****************************************************************************/
> > @@ -282,6 +284,8 @@ typedef enum powerpc_input_t {
> > PPC_FLAGS_INPUT_POWER9,
> > /* Freescale RCPU bus */
> > PPC_FLAGS_INPUT_RCPU,
> > + /* PPE42 bus */
> > + PPC_FLAGS_INPUT_PPE42,
> > } powerpc_input_t;
> >
> > #define PPC_INPUT(env) ((env)->bus_model)
> > @@ -433,39 +437,64 @@ typedef enum {
> > #define MSR_TM PPC_BIT_NR(31) /* Transactional Memory Available (Book3s) */
> > #define MSR_CM PPC_BIT_NR(32) /* Computation mode for BookE hflags */
> > #define MSR_ICM PPC_BIT_NR(33) /* Interrupt computation mode for BookE */
> > +#define MSR_SEM0 PPC_BIT_NR(33) /* SIB Error Mask Bit 0 (PPE42) */
> > +#define MSR_SEM1 PPC_BIT_NR(34) /* SIB Error Mask Bit 1 (PPE42) */
> > +#define MSR_SEM2 PPC_BIT_NR(35) /* SIB Error Mask Bit 2 (PPE42) */
> > #define MSR_GS PPC_BIT_NR(35) /* guest state for BookE */
> > +#define MSR_SEM3 PPC_BIT_NR(36) /* SIB Error Mask Bit 3 (PPE42) */
> > +#define MSR_SEM4 PPC_BIT_NR(37) /* SIB Error Mask Bit 4 (PPE42) */
> > #define MSR_UCLE PPC_BIT_NR(37) /* User-mode cache lock enable for BookE */
> > #define MSR_VR PPC_BIT_NR(38) /* altivec available x hflags */
> > #define MSR_SPE PPC_BIT_NR(38) /* SPE enable for BookE x hflags */
> > +#define MSR_SEM5 PPC_BIT_NR(38) /* SIB Error Mask Bit 5 (PPE42) */
> > +#define MSR_SEM6 PPC_BIT_NR(39) /* SIB Error Mask Bit 6 (PPE42) */
> > #define MSR_VSX PPC_BIT_NR(40) /* Vector Scalar Extension (>= 2.06)x hflags */
> > +#define MSR_IS0 PPC_BIT_NR(40) /* Instance Specific Bit 0 (PPE42) */
> > #define MSR_S PPC_BIT_NR(41) /* Secure state */
> > +#define MSR_SIBRC0 PPC_BIT_NR(41) /* Last SIB return code Bit 0 (PPE42) */
> > +#define MSR_SIBRC1 PPC_BIT_NR(42) /* Last SIB return code Bit 1 (PPE42) */
> > +#define MSR_SIBRC2 PPC_BIT_NR(43) /* Last SIB return code Bit 2 (PPE42) */
> > +#define MSR_LP PPC_BIT_NR(44) /* Low Priority (PPE42) */
> > #define MSR_KEY PPC_BIT_NR(44) /* key bit on 603e */
> > #define MSR_POW PPC_BIT_NR(45) /* Power management */
> > #define MSR_WE PPC_BIT_NR(45) /* Wait State Enable on 405 */
> > +#define MSR_IS1 PPC_BIT_NR(46) /* Instance Specific Bit 1 (PPE42) */
> > #define MSR_TGPR PPC_BIT_NR(46) /* TGPR usage on 602/603 x */
> > #define MSR_CE PPC_BIT_NR(46) /* Critical int. enable on embedded PPC x */
> > #define MSR_ILE PPC_BIT_NR(47) /* Interrupt little-endian mode */
> > +#define MSR_UIE PPC_BIT_NR(47) /* Unmaskable Interrupt Enable (PPE42) */
> > #define MSR_EE PPC_BIT_NR(48) /* External interrupt enable */
> > #define MSR_PR PPC_BIT_NR(49) /* Problem state hflags */
> > #define MSR_FP PPC_BIT_NR(50) /* Floating point available hflags */
> > #define MSR_ME PPC_BIT_NR(51) /* Machine check interrupt enable */
> > #define MSR_FE0 PPC_BIT_NR(52) /* Floating point exception mode 0 */
> > +#define MSR_IS2 PPC_BIT_NR(52) /* Instance Specific Bit 2 (PPE42) */
> > +#define MSR_IS3 PPC_BIT_NR(53) /* Instance Specific Bit 3 (PPE42) */
> > #define MSR_SE PPC_BIT_NR(53) /* Single-step trace enable x hflags */
> > #define MSR_DWE PPC_BIT_NR(53) /* Debug wait enable on 405 x */
> > #define MSR_UBLE PPC_BIT_NR(53) /* User BTB lock enable on e500 x */
> > #define MSR_BE PPC_BIT_NR(54) /* Branch trace enable x hflags */
> > #define MSR_DE PPC_BIT_NR(54) /* Debug int. enable on embedded PPC x */
> > #define MSR_FE1 PPC_BIT_NR(55) /* Floating point exception mode 1 */
> > +#define MSR_IPE PPC_BIT_NR(55) /* Imprecise Mode Enable (PPE42) */
> > #define MSR_AL PPC_BIT_NR(56) /* AL bit on POWER */
> > +#define MSR_SIBRCA0 PPC_BIT_NR(56) /* SIB Return Code Accumulator bit0 (PPE42) */
> > +#define MSR_SIBRCA1 PPC_BIT_NR(57) /* SIB Return Code Accumulator bit1 (PPE42) */
> > #define MSR_EP PPC_BIT_NR(57) /* Exception prefix on 601 */
> > #define MSR_IR PPC_BIT_NR(58) /* Instruction relocate */
> > #define MSR_IS PPC_BIT_NR(58) /* Instruction address space (BookE) */
> > +#define MSR_SIBRCA2 PPC_BIT_NR(58) /* SIB Return Code Accumulator bit2 (PPE42) */
> > +#define MSR_SIBRCA3 PPC_BIT_NR(59) /* SIB Return Code Accumulator bit3 (PPE42) */
> > #define MSR_DR PPC_BIT_NR(59) /* Data relocate */
> > #define MSR_DS PPC_BIT_NR(59) /* Data address space (BookE) */
> > #define MSR_PE PPC_BIT_NR(60) /* Protection enable on 403 */
> > +#define MSR_SIBRCA4 PPC_BIT_NR(60) /* SIB Return Code Accumulator bit4 (PPE42) */
> > +#define MSR_SIBRCA5 PPC_BIT_NR(61) /* SIB Return Code Accumulator bit5 (PPE42) */
> > #define MSR_PX PPC_BIT_NR(61) /* Protection exclusive on 403 x */
> > #define MSR_PMM PPC_BIT_NR(61) /* Performance monitor mark on POWER x */
> > #define MSR_RI PPC_BIT_NR(62) /* Recoverable interrupt 1 */
> > +#define MSR_SIBRCA6 PPC_BIT_NR(62) /* SIB Return Code Accumulator bit6 (PPE42) */
> > +#define MSR_SIBRCA7 PPC_BIT_NR(63) /* SIB Return Code Accumulator bit7 (PPE42) */
> > #define MSR_LE PPC_BIT_NR(63) /* Little-endian mode 1 hflags */
> >
>
> You may keep PPE42 bits together for easier review/maintenance with
> conditional compilation getting enabled, but I am ok with either.
>
Yeah, I went back and forth on this, but ultimately landed with keeping
it in numberical order with the other definitions. I think this makes
it more clear on which bits overlap between CPUs.
> > FIELD(MSR, SF, MSR_SF, 1)
> > @@ -517,6 +546,9 @@ FIELD(MSR, PX, MSR_PX, 1)
> > FIELD(MSR, PMM, MSR_PMM, 1)
> > FIELD(MSR, RI, MSR_RI, 1)
> > FIELD(MSR, LE, MSR_LE, 1)
> > +FIELD(MSR, SEM, MSR_SEM6, 7)
> > +FIELD(MSR, SIBRC, MSR_SIBRC2, 3)
> > +FIELD(MSR, SIBRCA, MSR_SIBRCA7, 8)
> >
> > /*
> > * FE0 and FE1 bits are not side-by-side
> > @@ -730,6 +762,21 @@ FIELD(MSR, LE, MSR_LE, 1)
> > #define ESR_VLEMI PPC_BIT(58) /* VLE operation */
> > #define ESR_MIF PPC_BIT(62) /* Misaligned instruction (VLE) */
> >
> > +/* PPE42 Interrupt Status Register bits */
> > +#define ISR_SRSMS0 PPC_BIT_NR(48) /* System Reset State Machine State 0 */
> > +#define ISR_SRSMS1 PPC_BIT_NR(49) /* System Reset State Machine State 1 */
> > +#define ISR_SRSMS2 PPC_BIT_NR(50) /* System Reset State Machine State 2 */
> > +#define ISR_SRSMS3 PPC_BIT_NR(51) /* System Reset State Machine State 3 */
> > +#define ISR_EP PPC_BIT_NR(53) /* MSR[EE] Maskable Event Pending */
> > +#define ISR_PTR PPC_BIT_NR(56) /* Program Interrupt from trap */
> > +#define ISR_ST PPC_BIT_NR(57) /* Data Interrupt caused by store */
> > +#define ISR_MFE PPC_BIT_NR(60) /* Multiple Fault Error */
> > +#define ISR_MCS0 PPC_BIT_NR(61) /* Machine Check Status bit0 */
> > +#define ISR_MCS1 PPC_BIT_NR(62) /* Machine Check Status bit1 */
> > +#define ISR_MCS2 PPC_BIT_NR(63) /* Machine Check Status bit2 */
>
> Better to have PPE42_ prefix ?
>
Sure, I'll add the prefix.
> > +FIELD(ISR, SRSMS, ISR_SRSMS3, 4)
> > +FIELD(ISR, MCS, ISR_MCS2, 3)
> > +
> > /* Transaction EXception And Summary Register bits */
> > #define TEXASR_FAILURE_PERSISTENT (63 - 7)
> > #define TEXASR_DISALLOWED (63 - 8)
> > @@ -785,6 +832,8 @@ enum {
> > POWERPC_FLAG_SMT_1LPAR = 0x00800000,
> > /* Has BHRB */
> > POWERPC_FLAG_BHRB = 0x01000000,
> > + /* Use PPE42-specific behavior */
> > + POWERPC_FLAG_PPE42 = 0x02000000,
> > };
> >
> > /*
> > @@ -1750,9 +1799,12 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_BOOKE_CSRR0 (0x03A)
> > #define SPR_BOOKE_CSRR1 (0x03B)
> > #define SPR_BOOKE_DEAR (0x03D)
> > +#define SPR_PPE42_EDR (0x03D)
> > #define SPR_IAMR (0x03D)
> > #define SPR_BOOKE_ESR (0x03E)
> > +#define SPR_PPE42_ISR (0x03E)
> > #define SPR_BOOKE_IVPR (0x03F)
> > +#define SPR_PPE42_IVPR (0x03F)
> > #define SPR_MPC_EIE (0x050)
> > #define SPR_MPC_EID (0x051)
> > #define SPR_MPC_NRI (0x052)
> > @@ -1818,6 +1870,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_TBU40 (0x11E)
> > #define SPR_SVR (0x11E)
> > #define SPR_BOOKE_PIR (0x11E)
> > +#define SPR_PPE42_PIR (0x11E)
> > #define SPR_PVR (0x11F)
> > #define SPR_HSPRG0 (0x130)
> > #define SPR_BOOKE_DBSR (0x130)
> > @@ -1827,6 +1880,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_BOOKE_EPCR (0x133)
> > #define SPR_SPURR (0x134)
> > #define SPR_BOOKE_DBCR0 (0x134)
> > +#define SPR_PPE42_DBCR (0x134)
> > #define SPR_IBCR (0x135)
> > #define SPR_PURR (0x135)
> > #define SPR_BOOKE_DBCR1 (0x135)
> > @@ -1844,6 +1898,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_HSRR1 (0x13B)
> > #define SPR_BOOKE_IAC4 (0x13B)
> > #define SPR_BOOKE_DAC1 (0x13C)
> > +#define SPR_PPE42_DACR (0x13C)
> > #define SPR_MMCRH (0x13C)
> > #define SPR_DABR2 (0x13D)
> > #define SPR_BOOKE_DAC2 (0x13D)
> > @@ -1853,12 +1908,14 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_BOOKE_DVC2 (0x13F)
> > #define SPR_LPIDR (0x13F)
> > #define SPR_BOOKE_TSR (0x150)
> > +#define SPR_PPE42_TSR (0x150)
> > #define SPR_HMER (0x150)
> > #define SPR_HMEER (0x151)
> > #define SPR_PCR (0x152)
> > #define SPR_HEIR (0x153)
> > #define SPR_BOOKE_LPIDR (0x152)
> > #define SPR_BOOKE_TCR (0x154)
> > +#define SPR_PPE42_TCR (0x154)
> > #define SPR_BOOKE_TLB0PS (0x158)
> > #define SPR_BOOKE_TLB1PS (0x159)
> > #define SPR_BOOKE_TLB2PS (0x15A)
> > @@ -2528,6 +2585,12 @@ enum {
> > PPC2_MEM_LWSYNC = 0x0000000000200000ULL,
> > /* ISA 2.06 BCD assist instructions */
> > PPC2_BCDA_ISA206 = 0x0000000000400000ULL,
> > + /* PPE42 instructions */
> > + PPC2_PPE42 = 0x0000000000800000ULL,
> > + /* PPE42X instructions */
> > + PPC2_PPE42X = 0x0000000001000000ULL,
> > + /* PPE42XM instructions */
> > + PPC2_PPE42XM = 0x0000000002000000ULL,
> >
> > #define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
> > PPC2_ISA205 | PPC2_VSX207 | PPC2_PERM_ISA206 | \
> > @@ -2537,7 +2600,8 @@ enum {
> > PPC2_ALTIVEC_207 | PPC2_ISA207S | PPC2_DFP | \
> > PPC2_FP_CVT_S64 | PPC2_TM | PPC2_PM_ISA206 | \
> > PPC2_ISA300 | PPC2_ISA310 | PPC2_MEM_LWSYNC | \
> > - PPC2_BCDA_ISA206)
> > + PPC2_BCDA_ISA206 | PPC2_PPE42 | PPC2_PPE42X | \
> > + PPC2_PPE42XM)
> > };
> >
> > /*****************************************************************************/
> > diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> > index a0e77f2673..317670a96b 100644
> > --- a/target/ppc/cpu_init.c
> > +++ b/target/ppc/cpu_init.c
> > @@ -1653,6 +1653,47 @@ static void register_8xx_sprs(CPUPPCState *env)
> > * ... and more (thermal management, performance counters, ...)
> > */
> >
> > +static void register_ppe42_sprs(CPUPPCState *env)
> > +{
> > + spr_register(env, SPR_PPE42_EDR, "EDR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_generic,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_ISR, "ISR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_generic,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_IVPR, "IVPR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, SPR_NOACCESS,
> > + 0xfff80000);
> > + spr_register(env, SPR_PPE42_PIR, "PIR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_pir,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_DBCR, "DBCR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_40x_dbcr0,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_DACR, "DACR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_generic,
> > + 0x00000000);
> > + /* Timer */
> > + spr_register(env, SPR_DECR, "DECR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_decr, &spr_write_decr,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_TSR, "TSR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_booke_tsr,
> > + 0x00000000);
> > + spr_register(env, SPR_BOOKE_TCR, "TCR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_booke_tcr,
> > + 0x00000000);
> > +}
> > +
> > /*****************************************************************************/
> > /* Exception vectors models */
> > static void init_excp_4xx(CPUPPCState *env)
> > @@ -1679,6 +1720,30 @@ static void init_excp_4xx(CPUPPCState *env)
> > #endif
> > }
> >
> > +static void init_excp_ppe42(CPUPPCState *env)
> > +{
> > +#if !defined(CONFIG_USER_ONLY)
> > + /* Machine Check vector changed after version 0 */
> > + if (((env->spr[SPR_PVR] & 0xf00000ul) >> 20) == 0) {
> > + env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000000;
> > + } else {
> > + env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000020;
> > + }
> > + env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000040;
> > + env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000060;
> > + env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000080;
> > + env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x000000A0;
> > + env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x000000C0;
> > + env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x000000E0;
> > + env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000100;
> > + env->excp_vectors[POWERPC_EXCP_FIT] = 0x00000120;
> > + env->excp_vectors[POWERPC_EXCP_WDT] = 0x00000140;
> > + env->ivpr_mask = 0xFFFFFE00UL;
> > + /* Hardware reset vector */
> > + env->hreset_vector = 0x00000040UL;
> > +#endif
> > +}
> > +
> > static void init_excp_MPC5xx(CPUPPCState *env)
> > {
> > #if !defined(CONFIG_USER_ONLY)
> > @@ -2200,6 +2265,125 @@ POWERPC_FAMILY(405)(ObjectClass *oc, const void *data)
> > POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
> > }
> >
> > +static void init_proc_ppe42(CPUPPCState *env)
> > +{
> > + register_ppe42_sprs(env);
> > +
> > + init_excp_ppe42(env);
> > + env->dcache_line_size = 32;
> > + env->icache_line_size = 32;
> > + /* Allocate hardware IRQ controller */
> > + ppc40x_irq_init(env_archcpu(env));
> > +
> > + SET_FIT_PERIOD(8, 12, 16, 20);
> > + SET_WDT_PERIOD(16, 20, 24, 28);
> > +}
> > +
> > +POWERPC_FAMILY(ppe42)(ObjectClass *oc, const void *data)
> > +{
> > + DeviceClass *dc = DEVICE_CLASS(oc);
> > + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> > +
> > + dc->desc = "PPE 42";
> > + pcc->init_proc = init_proc_ppe42;
> > + pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > + pcc->insns_flags = PPC_INSNS_BASE |
> > + PPC_WRTEE |
> > + PPC_CACHE |
> > + PPC_CACHE_DCBZ |
> > + PPC_MEM_SYNC;
> > + pcc->insns_flags2 = PPC2_PPE42;
> > + pcc->msr_mask = R_MSR_SEM_MASK |
> > + (1ull << MSR_IS0) |
> > + R_MSR_SIBRC_MASK |
> > + (1ull << MSR_LP) |
> > + (1ull << MSR_WE) |
> > + (1ull << MSR_IS1) |
> > + (1ull << MSR_UIE) |
> > + (1ull << MSR_EE) |
> > + (1ull << MSR_ME) |
> > + (1ull << MSR_IS2) |
> > + (1ull << MSR_IS3) |
> > + (1ull << MSR_IPE) |
> > + R_MSR_SIBRCA_MASK;
> > + pcc->mmu_model = POWERPC_MMU_REAL;
> > + pcc->excp_model = POWERPC_EXCP_PPE42;
> > + pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
> > + pcc->bfd_mach = bfd_mach_ppc_403;
> > + pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
>
> This shares common code with ppe42x and ppe42xm variants.
> Could this be re-used from a common routine?
>
Yes, I'll move the common code into a common function.
> > +}
> > +
> > +POWERPC_FAMILY(ppe42x)(ObjectClass *oc, const void *data)
> > +{
> > + DeviceClass *dc = DEVICE_CLASS(oc);
> > + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> > +
> > + dc->desc = "PPE 42X";
> > + pcc->init_proc = init_proc_ppe42;
> > + pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > + pcc->insns_flags = PPC_INSNS_BASE |
> > + PPC_WRTEE |
> > + PPC_CACHE |
> > + PPC_CACHE_DCBZ |
> > + PPC_MEM_SYNC;
> > + pcc->insns_flags2 = PPC2_PPE42 | PPC2_PPE42X;
> > + pcc->msr_mask = R_MSR_SEM_MASK |
> > + (1ull << MSR_IS0) |
> > + R_MSR_SIBRC_MASK |
> > + (1ull << MSR_LP) |
> > + (1ull << MSR_WE) |
> > + (1ull << MSR_IS1) |
> > + (1ull << MSR_UIE) |
> > + (1ull << MSR_EE) |
> > + (1ull << MSR_ME) |
> > + (1ull << MSR_IS2) |
> > + (1ull << MSR_IS3) |
> > + (1ull << MSR_IPE) |
> > + R_MSR_SIBRCA_MASK;
> > + pcc->mmu_model = POWERPC_MMU_REAL;
> > + pcc->excp_model = POWERPC_EXCP_PPE42;
> > + pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
> > + pcc->bfd_mach = bfd_mach_ppc_403;
> > + pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
> > +}
> > +
> > +POWERPC_FAMILY(ppe42xm)(ObjectClass *oc, const void *data)
> > +{
> > + DeviceClass *dc = DEVICE_CLASS(oc);
> > + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> > +
> > + dc->desc = "PPE 42XM";
> > + pcc->init_proc = init_proc_ppe42;
> > + pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > + pcc->insns_flags = PPC_INSNS_BASE |
> > + PPC_WRTEE |
> > + PPC_CACHE |
> > + PPC_CACHE_DCBZ |
> > + PPC_MEM_SYNC;
> > + pcc->insns_flags2 = PPC2_PPE42 | PPC2_PPE42X | PPC2_PPE42XM;
> > + pcc->msr_mask = R_MSR_SEM_MASK |
> > + (1ull << MSR_IS0) |
> > + R_MSR_SIBRC_MASK |
> > + (1ull << MSR_LP) |
> > + (1ull << MSR_WE) |
> > + (1ull << MSR_IS1) |
> > + (1ull << MSR_UIE) |
> > + (1ull << MSR_EE) |
> > + (1ull << MSR_ME) |
> > + (1ull << MSR_IS2) |
> > + (1ull << MSR_IS3) |
> > + (1ull << MSR_IPE) |
> > + R_MSR_SIBRCA_MASK;
> > + pcc->mmu_model = POWERPC_MMU_REAL;
> > + pcc->excp_model = POWERPC_EXCP_PPE42;
> > + pcc->bus_model = PPC_FLAGS_INPUT_PPE42; // Could be used in the future, but not yet for ppe
> > + pcc->bfd_mach = bfd_mach_ppc_403;
> > + pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
> > +}
> > +
> > static void init_proc_440EP(CPUPPCState *env)
> > {
> > register_BookE_sprs(env, 0x000000000000FFFFULL);
> > @@ -6802,53 +6986,63 @@ static void init_ppc_proc(PowerPCCPU *cpu)
> >
> > /* MSR bits & flags consistency checks */
> > if (env->msr_mask & (1 << 25)) {
> > - switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
> > + switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE |
> > + POWERPC_FLAG_PPE42)) {
> > case POWERPC_FLAG_SPE:
> > case POWERPC_FLAG_VRE:
> > + case POWERPC_FLAG_PPE42:
> > break;
> > default:
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n");
> > + "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n"
> > + "or POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > } else if (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n");
> > + "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n"
> > + "nor POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > if (env->msr_mask & (1 << 17)) {
> > - switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
> > + switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE |
> > + POWERPC_FLAG_PPE42)) {
> > case POWERPC_FLAG_TGPR:
> > case POWERPC_FLAG_CE:
> > + case POWERPC_FLAG_PPE42:
> > break;
> > default:
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n");
> > + "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n"
> > + "or POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > - } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
> > + } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE |
> > + POWERPC_FLAG_PPE42)) {
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n");
> > + "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n"
> > + "nor POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > if (env->msr_mask & (1 << 10)) {
> > switch (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
> > - POWERPC_FLAG_UBLE)) {
> > + POWERPC_FLAG_UBLE | POWERPC_FLAG_PPE42)) {
> > case POWERPC_FLAG_SE:
> > case POWERPC_FLAG_DWE:
> > case POWERPC_FLAG_UBLE:
> > + case POWERPC_FLAG_PPE42:
> > break;
> > default:
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > "Should define POWERPC_FLAG_SE or POWERPC_FLAG_DWE or "
> > - "POWERPC_FLAG_UBLE\n");
> > + "POWERPC_FLAG_UBLE or POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > } else if (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
> > - POWERPC_FLAG_UBLE)) {
> > + POWERPC_FLAG_UBLE | POWERPC_FLAG_PPE42)) {
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > "Should not define POWERPC_FLAG_SE nor POWERPC_FLAG_DWE nor "
> > - "POWERPC_FLAG_UBLE\n");
> > + "POWERPC_FLAG_UBLE nor POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > if (env->msr_mask & (1 << 9)) {
> > @@ -6867,18 +7061,23 @@ static void init_ppc_proc(PowerPCCPU *cpu)
> > exit(1);
> > }
> > if (env->msr_mask & (1 << 2)) {
> > - switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
> > + switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM |
> > + POWERPC_FLAG_PPE42)) {
> > case POWERPC_FLAG_PX:
> > case POWERPC_FLAG_PMM:
> > + case POWERPC_FLAG_PPE42:
> > break;
> > default:
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n");
> > + "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n"
> > + "or POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > - } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
> > + } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM |
> > + POWERPC_FLAG_PPE42)) {
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n");
> > + "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n"
> > + "nor POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > if ((env->flags & POWERPC_FLAG_BUS_CLK) == 0) {
> > @@ -7243,39 +7442,40 @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
> > }
> >
> > msr = (target_ulong)0;
> > - msr |= (target_ulong)MSR_HVB;
> > - msr |= (target_ulong)1 << MSR_EP;
> > + if (!(env->flags & POWERPC_FLAG_PPE42)) {
> > + msr |= (target_ulong)MSR_HVB;
> > + msr |= (target_ulong)1 << MSR_EP;
> > #if defined(DO_SINGLE_STEP) && 0
> > - /* Single step trace mode */
> > - msr |= (target_ulong)1 << MSR_SE;
> > - msr |= (target_ulong)1 << MSR_BE;
> > + /* Single step trace mode */
> > + msr |= (target_ulong)1 << MSR_SE;
> > + msr |= (target_ulong)1 << MSR_BE;
> > #endif
> > #if defined(CONFIG_USER_ONLY)
> > - msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
> > - msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
> > - msr |= (target_ulong)1 << MSR_FE1;
> > - msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
> > - msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
> > - msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
> > - msr |= (target_ulong)1 << MSR_PR;
> > + msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
> > + msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
> > + msr |= (target_ulong)1 << MSR_FE1;
> > + msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
> > + msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
> > + msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
> > + msr |= (target_ulong)1 << MSR_PR;
> > #if defined(TARGET_PPC64)
> > - msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
> > + msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
> > #endif
> > #if !TARGET_BIG_ENDIAN
> > - msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
> > - if (!((env->msr_mask >> MSR_LE) & 1)) {
> > - fprintf(stderr, "Selected CPU does not support little-endian.\n");
> > - exit(1);
> > - }
> > + msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
> > + if (!((env->msr_mask >> MSR_LE) & 1)) {
> > + fprintf(stderr, "Selected CPU does not support little-endian.\n");
> > + exit(1);
> > + }
> > #endif
> > #endif
> >
> > #if defined(TARGET_PPC64)
> > - if (mmu_is_64bit(env->mmu_model)) {
> > - msr |= (1ULL << MSR_SF);
> > - }
> > + if (mmu_is_64bit(env->mmu_model)) {
> > + msr |= (1ULL << MSR_SF);
> > + }
> > #endif
> > -
> > + }
> > hreg_store_msr(env, msr, 1);
> >
> > #if !defined(CONFIG_USER_ONLY)
> > @@ -7725,6 +7925,18 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> > * they can be read with "p $ivor0", "p $ivor1", etc.
> > */
> > break;
> > + case POWERPC_EXCP_PPE42:
> > + qemu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx "\n",
> > + env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
> > +
> > + qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
> > + " ISR " TARGET_FMT_lx " EDR " TARGET_FMT_lx "\n",
> > + env->spr[SPR_PPE42_TCR], env->spr[SPR_PPE42_TSR],
> > + env->spr[SPR_PPE42_ISR], env->spr[SPR_PPE42_EDR]);
> > +
> > + qemu_fprintf(f, " PIR " TARGET_FMT_lx " IVPR " TARGET_FMT_lx "\n",
> > + env->spr[SPR_PPE42_PIR], env->spr[SPR_PPE42_IVPR]);
> > + break;
> > case POWERPC_EXCP_40x:
> > qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
> > " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
> > diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> > index 1efdc4066e..2e35e63826 100644
> > --- a/target/ppc/excp_helper.c
> > +++ b/target/ppc/excp_helper.c
> > @@ -949,6 +949,133 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
> > powerpc_set_excp_state(cpu, vector, new_msr);
> > }
> >
> > +#define ISR_MCS_INSTRUCTION 0
> > +#define ISR_MCS_DATA_LOAD 1
> > +#define ISR_MCS_DATA_PRECISE_STORE 2
> > +#define ISR_MCS_DATA_IMPRECISE_STORE 3
> > +#define ISR_MCS_PROGRAM 4
> > +#define ISR_MCS_ISI 5
> > +#define ISR_MCS_ALIGNMENT 6
> > +#define ISR_MCS_DSI 7
>
> Should these have a PPE42_ prefix?
> Also, may better be kept in cpu.h alongwith other PPE42 ISR bits ?
>
Will do.
> > +static void powerpc_excp_ppe42(PowerPCCPU *cpu, int excp)
> > +{
> > + CPUPPCState *env = &cpu->env;
> > + target_ulong msr, new_msr, vector;
> > + target_ulong mcs = ISR_MCS_INSTRUCTION;
> > + bool promote_unmaskable;
> > +
> > + msr = env->msr;
> > +
> > + /*
> > + * New interrupt handler msr preserves SIBRC and ME unless explicitly
> > + * overridden by the exception. All other MSR bits are zeroed out.
> > + */
> > + new_msr = env->msr & (((target_ulong)1 << MSR_ME) | R_MSR_SIBRC_MASK);
> > +
> > + /* HV emu assistance interrupt only exists on server arch 2.05 or later */
> > + if (excp == POWERPC_EXCP_HV_EMU) {
> > + excp = POWERPC_EXCP_PROGRAM;
> > + }
> > +
> > + /*
> > + * Unmaskable interrupts (Program, ISI, Alignment and DSI) are promoted to
> > + * machine check if MSR_UIE is 0.
> > + */
> > + promote_unmaskable = !(msr & ((target_ulong)1 << MSR_UIE));
> > +
> > +
> > + switch (excp) {
> > + case POWERPC_EXCP_MCHECK: /* Machine check exception */
> > + break;
> > + case POWERPC_EXCP_DSI: /* Data storage exception */
> > + trace_ppc_excp_dsi(env->spr[SPR_PPE42_ISR], env->spr[SPR_PPE42_EDR]);
> > + if (promote_unmaskable) {
> > + excp = POWERPC_EXCP_MCHECK;
> > + mcs = ISR_MCS_DSI;
> > + }
> > + break;
> > + case POWERPC_EXCP_ISI: /* Instruction storage exception */
> > + trace_ppc_excp_isi(msr, env->nip);
> > + if (promote_unmaskable) {
> > + excp = POWERPC_EXCP_MCHECK;
> > + mcs = ISR_MCS_ISI;
> > + }
> > + break;
> > + case POWERPC_EXCP_EXTERNAL: /* External input */
> > + break;
> > + case POWERPC_EXCP_ALIGN: /* Alignment exception */
> > + if (promote_unmaskable) {
> > + excp = POWERPC_EXCP_MCHECK;
> > + mcs = ISR_MCS_ALIGNMENT;
> > + }
> > + break;
> > + case POWERPC_EXCP_PROGRAM: /* Program exception */
> > + if (promote_unmaskable) {
> > + excp = POWERPC_EXCP_MCHECK;
> > + mcs = ISR_MCS_PROGRAM;
> > + }
> > + switch (env->error_code & ~0xF) {
> > + case POWERPC_EXCP_INVAL:
> > + trace_ppc_excp_inval(env->nip);
> > + env->spr[SPR_PPE42_ISR] &= ~((target_ulong)1 << ISR_PTR);
> > + break;
> > + case POWERPC_EXCP_TRAP:
> > + env->spr[SPR_PPE42_ISR] |= ((target_ulong)1 << ISR_PTR);
> > + break;
> > + default:
> > + /* Should never occur */
> > + cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
> > + env->error_code);
> > + break;
> > + }
> > +#ifdef CONFIG_TCG
> > + env->spr[SPR_PPE42_EDR] = ppc_ldl_code(env, env->nip);
> > +#endif
> > + break;
> > + case POWERPC_EXCP_DECR: /* Decrementer exception */
> > + break;
> > + case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
> > + trace_ppc_excp_print("FIT");
> > + break;
> > + case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
> > + trace_ppc_excp_print("WDT");
> > + break;
> > + case POWERPC_EXCP_RESET: /* System reset exception */
> > + /* reset exceptions don't have ME set */
> > + new_msr &= ~((target_ulong)1 << MSR_ME);
> > + break;
> > + default:
> > + cpu_abort(env_cpu(env), "Invalid PPE42 exception %d. Aborting\n",
> > + excp);
> > + break;
> > + }
> > +
> > + env->spr[SPR_SRR0] = env->nip;
> > + env->spr[SPR_SRR1] = msr;
> > +
> > + vector = env->excp_vectors[excp];
> > + if (vector == (target_ulong)-1ULL) {
> > + cpu_abort(env_cpu(env),
> > + "Raised an exception without defined vector %d\n", excp);
> > + }
> > + vector |= env->spr[SPR_PPE42_IVPR];
> > +
> > + if (excp == POWERPC_EXCP_MCHECK) {
> > + /* Also set the Machine Check Status (MCS) */
> > + env->spr[SPR_PPE42_ISR] &= ~R_ISR_MCS_MASK;
> > + env->spr[SPR_PPE42_ISR] |= (mcs & R_ISR_MCS_MASK);
> > + env->spr[SPR_PPE42_ISR] &= ~((target_ulong)1 << ISR_MFE);
> > +
> > + /* Machine checks halt execution if MSR_ME is 0 */
> > + powerpc_mcheck_checkstop(env);
> > +
> > + /* machine check exceptions don't have ME set */
> > + new_msr &= ~((target_ulong)1 << MSR_ME);
> > + }
> > +
> > + powerpc_set_excp_state(cpu, vector, new_msr);
> > +}
> > +
> > static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
> > {
> > CPUPPCState *env = &cpu->env;
> > @@ -1589,6 +1716,9 @@ void powerpc_excp(PowerPCCPU *cpu, int excp)
> > case POWERPC_EXCP_POWER11:
> > powerpc_excp_books(cpu, excp);
> > break;
> > + case POWERPC_EXCP_PPE42:
> > + powerpc_excp_ppe42(cpu, excp);
> > + break;
> > default:
> > g_assert_not_reached();
> > }
> > @@ -1945,6 +2075,43 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env,
> > }
> > #endif /* TARGET_PPC64 */
> >
> > +static int ppe42_next_unmasked_interrupt(CPUPPCState *env)
> > +{
> > + bool async_deliver;
> > +
> > + /* External reset */
> > + if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
> > + return PPC_INTERRUPT_RESET;
> > + }
> > + /* Machine check exception */
> > + if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
> > + return PPC_INTERRUPT_MCK;
> > + }
> > +
> > + async_deliver = FIELD_EX64(env->msr, MSR, EE);
> > +
> > + if (async_deliver != 0) {
> > + /* Watchdog timer */
> > + if (env->pending_interrupts & PPC_INTERRUPT_WDT) {
> > + return PPC_INTERRUPT_WDT;
> > + }
> > + /* External Interrupt */
> > + if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
> > + return PPC_INTERRUPT_EXT;
> > + }
> > + /* Fixed interval timer */
> > + if (env->pending_interrupts & PPC_INTERRUPT_FIT) {
> > + return PPC_INTERRUPT_FIT;
> > + }
> > + /* Decrementer exception */
> > + if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
> > + return PPC_INTERRUPT_DECR;
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > +
> > static int ppc_next_unmasked_interrupt(CPUPPCState *env)
> > {
> > uint32_t pending_interrupts = env->pending_interrupts;
> > @@ -1970,6 +2137,10 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
> > }
> > #endif
> >
> > + if (env->excp_model == POWERPC_EXCP_PPE42) {
> > + return ppe42_next_unmasked_interrupt(env);
> > + }
> > +
> > /* External reset */
> > if (pending_interrupts & PPC_INTERRUPT_RESET) {
> > return PPC_INTERRUPT_RESET;
> > diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
> > index 7e5726871e..7be00f5bbe 100644
> > --- a/target/ppc/helper_regs.c
> > +++ b/target/ppc/helper_regs.c
> > @@ -186,6 +186,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
> > if (env->spr[SPR_LPCR] & LPCR_HR) {
> > hflags |= 1 << HFLAGS_HR;
> > }
> > + if (ppc_flags & POWERPC_FLAG_PPE42) {
> > + /* PPE42 has a single address space and no problem state */
> > + msr = 0;
> > + }
>
> We really dont want this to be checked on PPC64 machines, hence
> !TARGET_PPC64 needed.
>
This is related to the issue of whether we want to continue supporting
32-bit CPUs inside the 64-bit executable. It seems that the community
is saying that we should continue to do that, so I'd like to keep this
in even for PPC64 machines, but I will go ahead and add an 'unlikely'
here in order to possibly lessen the impact.
> >
> > #ifndef CONFIG_USER_ONLY
> > if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) {
> > @@ -306,9 +310,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)) {
> > @@ -319,8 +320,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 MSR has bits overlapping with others */
> > + if (!(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
> > @@ -462,6 +469,17 @@ void register_generic_sprs(PowerPCCPU *cpu)
> > SPR_NOACCESS, SPR_NOACCESS,
> > &spr_read_generic, &spr_write_generic,
> > 0x00000000);
> > +
> > + if (env->insns_flags2 & PPC2_PPE42) {
> > + spr_register(env, SPR_PVR, "PVR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, SPR_NOACCESS,
> > + pcc->pvr);
> > +
> > + /* PPE42 doesn't support additional SPRG regs or timebase */
> > + return;
> > + }
> > +
> > spr_register(env, SPR_SPRG1, "SPRG1",
> > SPR_NOACCESS, SPR_NOACCESS,
> > &spr_read_generic, &spr_write_generic,
> > diff --git a/target/ppc/tcg-excp_helper.c b/target/ppc/tcg-excp_helper.c
> > index f835be5156..14f3ad92fe 100644
> > --- a/target/ppc/tcg-excp_helper.c
> > +++ b/target/ppc/tcg-excp_helper.c
> > @@ -229,6 +229,18 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
> > case POWERPC_MMU_BOOKE206:
> > env->spr[SPR_BOOKE_DEAR] = vaddr;
> > break;
> > + case POWERPC_MMU_REAL:
> > + if (env->flags & POWERPC_FLAG_PPE42) {
> > + env->spr[SPR_PPE42_EDR] = vaddr;
> > + if (access_type == MMU_DATA_STORE) {
> > + env->spr[SPR_PPE42_ISR] |= ISR_ST;
> > + } else {
> > + env->spr[SPR_PPE42_ISR] &= ~ISR_ST;
> > + }
> > + } else {
> > + env->spr[SPR_DAR] = vaddr;
> > + }
> > + break;
> > default:
> > env->spr[SPR_DAR] = vaddr;
> > break;
> > diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> > index 27f90c3cc5..b4f4d10384 100644
> > --- a/target/ppc/translate.c
> > +++ b/target/ppc/translate.c
> > @@ -4264,8 +4264,10 @@ static void gen_mtmsr(DisasContext *ctx)
> > /* L=1 form only updates EE and RI */
> > mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);
> > } else {
> > - /* mtmsr does not alter S, ME, or LE */
> > - mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
> > + if (!(ctx->insns_flags2 & PPC2_PPE42)) {
>
> you may want to use likely() in above check?
> Also check other instances wherever applicable.
>
Yes, I think it does make sense to add it here.
> Thanks
> Harsh
>
> > + /* mtmsr does not alter S, ME, or LE */
> > + mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
> > + }
> >
> > /*
> > * XXX: we need to update nip before the store if we enter
On 8/25/25 22:26, Miles Glenn wrote:
>>> @@ -186,6 +186,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
>>> if (env->spr[SPR_LPCR] & LPCR_HR) {
>>> hflags |= 1 << HFLAGS_HR;
>>> }
>>> + if (ppc_flags & POWERPC_FLAG_PPE42) {
>>> + /* PPE42 has a single address space and no problem state */
>>> + msr = 0;
>>> + }
>> We really dont want this to be checked on PPC64 machines, hence
>> !TARGET_PPC64 needed.
>>
> This is related to the issue of whether we want to continue supporting
> 32-bit CPUs inside the 64-bit executable. It seems that the community
> is saying that we should continue to do that, so I'd like to keep this
> in even for PPC64 machines, but I will go ahead and add an 'unlikely'
> here in order to possibly lessen the impact.
Yeh, sure, that should suffice for now.
Thanks
Harsh
On 25/08/2025 13.24, Harsh Prateek Bora wrote:
> Hi Glenn,
>
> This seems significant work. Thanks for upstreaming.
>
> On 8/20/25 02:58, Glenn Miles wrote:
>> Adds the IBM PPE42 family of processors supporting the
>
> family of 32-bit processors ?
>
>> PPE42, PPE42X and PPE42XM processor versions. These
>> processors are used as embedded processors in the IBM
>> Power9, Power10 and Power12 processors for various
>> tasks. It is basically a stripped down version of the
>> IBM PowerPC 405 processor, with some added instructions
>> for handling 64-bit loads and stores.
>>
>> For more information on the PPE 42 processor please visit:
>>
>> https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
>>
>> Supports PPE42 SPR's (Including the MSR) and Exceptions.
>>
>> Does not yet support new PPE42 instructions and does not
>> prevent access to some invalid instructions and registers
>> (currently allows for access to invalid GPR's and CR fields).
>>
>> Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
>> ---
>> target/ppc/cpu-models.c | 7 +
>> target/ppc/cpu-models.h | 4 +
>> target/ppc/cpu.h | 66 +++++++-
>> target/ppc/cpu_init.c | 286 ++++++++++++++++++++++++++++++-----
>> target/ppc/excp_helper.c | 171 +++++++++++++++++++++
>> target/ppc/helper_regs.c | 28 +++-
>> target/ppc/tcg-excp_helper.c | 12 ++
>> target/ppc/translate.c | 6 +-
>> 8 files changed, 535 insertions(+), 45 deletions(-)
>>
>> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
>> index ea86ea202a..09f73e23a8 100644
>> --- a/target/ppc/cpu-models.c
>> +++ b/target/ppc/cpu-models.c
>> @@ -116,6 +116,13 @@
>> NULL)
>> POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
>> NULL)
>> + /* PPE42 Embedded
>> Controllers */
>> + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
>> + "Generic PPE 42")
>> + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
>> + "Generic PPE 42X")
>> + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM,
>> ppe42xm,
>> + "Generic PPE 42XM")
>
> Can all the PPE42 specific code be conditionally compiled only for
> !TARGET_PPC64 (and !CONFIG_USER_ONLY wherever possible)?
> Not only to reduce the bloating size of respective binaries, but also to
> avoid some code being added to hot path routines like
> hreg_compute_hflags_value().
qemu-system-ppc64 is a superset of qemu-system-ppc, and there are even
efforts to unify all system functionality into a singly binary, so excluding
a 32-bit feature from qemu-system-ppc64 sounds like a step into the wrong
direction to me right now...?
Thomas
Hi Thomas,
On 8/25/25 17:04, Thomas Huth wrote:
> On 25/08/2025 13.24, Harsh Prateek Bora wrote:
>> Hi Glenn,
>>
>> This seems significant work. Thanks for upstreaming.
>>
>> On 8/20/25 02:58, Glenn Miles wrote:
>>> Adds the IBM PPE42 family of processors supporting the
>>
>> family of 32-bit processors ?
>>
>>> PPE42, PPE42X and PPE42XM processor versions. These
>>> processors are used as embedded processors in the IBM
>>> Power9, Power10 and Power12 processors for various
>>> tasks. It is basically a stripped down version of the
>>> IBM PowerPC 405 processor, with some added instructions
>>> for handling 64-bit loads and stores.
>>>
>>> For more information on the PPE 42 processor please visit:
>>>
>>> https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
>>>
>>> Supports PPE42 SPR's (Including the MSR) and Exceptions.
>>>
>>> Does not yet support new PPE42 instructions and does not
>>> prevent access to some invalid instructions and registers
>>> (currently allows for access to invalid GPR's and CR fields).
>>>
>>> Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
>>> ---
>>> target/ppc/cpu-models.c | 7 +
>>> target/ppc/cpu-models.h | 4 +
>>> target/ppc/cpu.h | 66 +++++++-
>>> target/ppc/cpu_init.c | 286 ++++++++++++++++++++++++++++++-----
>>> target/ppc/excp_helper.c | 171 +++++++++++++++++++++
>>> target/ppc/helper_regs.c | 28 +++-
>>> target/ppc/tcg-excp_helper.c | 12 ++
>>> target/ppc/translate.c | 6 +-
>>> 8 files changed, 535 insertions(+), 45 deletions(-)
>>>
>>> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
>>> index ea86ea202a..09f73e23a8 100644
>>> --- a/target/ppc/cpu-models.c
>>> +++ b/target/ppc/cpu-models.c
>>> @@ -116,6 +116,13 @@
>>> NULL)
>>> POWERPC_DEF("x2vp20",
>>> CPU_POWERPC_X2VP20, 405,
>>> NULL)
>>> + /* PPE42 Embedded
>>> Controllers */
>>> + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42,
>>> ppe42,
>>> + "Generic PPE 42")
>>> + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X,
>>> ppe42x,
>>> + "Generic PPE 42X")
>>> + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
>>> + "Generic PPE 42XM")
>>
>> Can all the PPE42 specific code be conditionally compiled only for
>> !TARGET_PPC64 (and !CONFIG_USER_ONLY wherever possible)?
>> Not only to reduce the bloating size of respective binaries, but also to
>> avoid some code being added to hot path routines like
>> hreg_compute_hflags_value().
>
> qemu-system-ppc64 is a superset of qemu-system-ppc, and there are even
> efforts to unify all system functionality into a singly binary, so
> excluding a 32-bit feature from qemu-system-ppc64 sounds like a step
> into the wrong direction to me right now...?
We do have existing code getting conditionally compiled for TARGET_PPC64
which I guess gets enabled with:
--configure target-list=<ppc64|ppc>-softmmu
I understand the efforts are towards having a single binary to support
both, but what gets built-in is still decided with configure choice?
Please correct/clarify with above understanding.
regards,
Harsh
>
> Thomas
>
On 25/08/2025 13.46, Harsh Prateek Bora wrote:
> Hi Thomas,
>
> On 8/25/25 17:04, Thomas Huth wrote:
>> On 25/08/2025 13.24, Harsh Prateek Bora wrote:
>>> Hi Glenn,
>>>
>>> This seems significant work. Thanks for upstreaming.
>>>
>>> On 8/20/25 02:58, Glenn Miles wrote:
>>>> Adds the IBM PPE42 family of processors supporting the
>>>
>>> family of 32-bit processors ?
>>>
>>>> PPE42, PPE42X and PPE42XM processor versions. These
>>>> processors are used as embedded processors in the IBM
>>>> Power9, Power10 and Power12 processors for various
>>>> tasks. It is basically a stripped down version of the
>>>> IBM PowerPC 405 processor, with some added instructions
>>>> for handling 64-bit loads and stores.
>>>>
>>>> For more information on the PPE 42 processor please visit:
>>>>
>>>> https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
>>>>
>>>> Supports PPE42 SPR's (Including the MSR) and Exceptions.
>>>>
>>>> Does not yet support new PPE42 instructions and does not
>>>> prevent access to some invalid instructions and registers
>>>> (currently allows for access to invalid GPR's and CR fields).
>>>>
>>>> Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
>>>> ---
>>>> target/ppc/cpu-models.c | 7 +
>>>> target/ppc/cpu-models.h | 4 +
>>>> target/ppc/cpu.h | 66 +++++++-
>>>> target/ppc/cpu_init.c | 286 ++++++++++++++++++++++++++++++-----
>>>> target/ppc/excp_helper.c | 171 +++++++++++++++++++++
>>>> target/ppc/helper_regs.c | 28 +++-
>>>> target/ppc/tcg-excp_helper.c | 12 ++
>>>> target/ppc/translate.c | 6 +-
>>>> 8 files changed, 535 insertions(+), 45 deletions(-)
>>>>
>>>> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
>>>> index ea86ea202a..09f73e23a8 100644
>>>> --- a/target/ppc/cpu-models.c
>>>> +++ b/target/ppc/cpu-models.c
>>>> @@ -116,6 +116,13 @@
>>>> NULL)
>>>> POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
>>>> NULL)
>>>> + /* PPE42 Embedded
>>>> Controllers */
>>>> + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
>>>> + "Generic PPE 42")
>>>> + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
>>>> + "Generic PPE 42X")
>>>> + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
>>>> + "Generic PPE 42XM")
>>>
>>> Can all the PPE42 specific code be conditionally compiled only for
>>> !TARGET_PPC64 (and !CONFIG_USER_ONLY wherever possible)?
>>> Not only to reduce the bloating size of respective binaries, but also to
>>> avoid some code being added to hot path routines like
>>> hreg_compute_hflags_value().
>>
>> qemu-system-ppc64 is a superset of qemu-system-ppc, and there are even
>> efforts to unify all system functionality into a singly binary, so
>> excluding a 32-bit feature from qemu-system-ppc64 sounds like a step into
>> the wrong direction to me right now...?
>
> We do have existing code getting conditionally compiled for TARGET_PPC64
> which I guess gets enabled with:
> --configure target-list=<ppc64|ppc>-softmmu
> I understand the efforts are towards having a single binary to support
> both, but what gets built-in is still decided with configure choice?
>
> Please correct/clarify with above understanding.
As I said, qemu-system-ppc64 is currently a full superset of
qemu-system-ppc. The ppc64 binary contains all the 32-bit code, you can
perfectly run a "g3beige" or "bamboo" machine with qemu-system-ppc64, too.
By disabling the ppe42 code in the ppc64 binary, this would now introduce an
execption to that unwritten rule, so I'd expect that we'd not rather want to
do this now.
Thomas
On 8/25/25 17:28, Thomas Huth wrote:
> On 25/08/2025 13.46, Harsh Prateek Bora wrote:
>> Hi Thomas,
>>
>> On 8/25/25 17:04, Thomas Huth wrote:
>>> On 25/08/2025 13.24, Harsh Prateek Bora wrote:
>>>> Hi Glenn,
>>>>
>>>> This seems significant work. Thanks for upstreaming.
>>>>
>>>> On 8/20/25 02:58, Glenn Miles wrote:
>>>>> Adds the IBM PPE42 family of processors supporting the
>>>>
>>>> family of 32-bit processors ?
>>>>
>>>>> PPE42, PPE42X and PPE42XM processor versions. These
>>>>> processors are used as embedded processors in the IBM
>>>>> Power9, Power10 and Power12 processors for various
>>>>> tasks. It is basically a stripped down version of the
>>>>> IBM PowerPC 405 processor, with some added instructions
>>>>> for handling 64-bit loads and stores.
>>>>>
>>>>> For more information on the PPE 42 processor please visit:
>>>>>
>>>>> https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
>>>>>
>>>>> Supports PPE42 SPR's (Including the MSR) and Exceptions.
>>>>>
>>>>> Does not yet support new PPE42 instructions and does not
>>>>> prevent access to some invalid instructions and registers
>>>>> (currently allows for access to invalid GPR's and CR fields).
>>>>>
>>>>> Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
>>>>> ---
>>>>> target/ppc/cpu-models.c | 7 +
>>>>> target/ppc/cpu-models.h | 4 +
>>>>> target/ppc/cpu.h | 66 +++++++-
>>>>> target/ppc/cpu_init.c | 286
>>>>> ++++++++++++++++++++++++++++++-----
>>>>> target/ppc/excp_helper.c | 171 +++++++++++++++++++++
>>>>> target/ppc/helper_regs.c | 28 +++-
>>>>> target/ppc/tcg-excp_helper.c | 12 ++
>>>>> target/ppc/translate.c | 6 +-
>>>>> 8 files changed, 535 insertions(+), 45 deletions(-)
>>>>>
>>>>> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
>>>>> index ea86ea202a..09f73e23a8 100644
>>>>> --- a/target/ppc/cpu-models.c
>>>>> +++ b/target/ppc/cpu-models.c
>>>>> @@ -116,6 +116,13 @@
>>>>> NULL)
>>>>> POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
>>>>> NULL)
>>>>> + /* PPE42 Embedded
>>>>> Controllers */
>>>>> + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
>>>>> + "Generic PPE 42")
>>>>> + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
>>>>> + "Generic PPE 42X")
>>>>> + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
>>>>> + "Generic PPE 42XM")
>>>>
>>>> Can all the PPE42 specific code be conditionally compiled only for
>>>> !TARGET_PPC64 (and !CONFIG_USER_ONLY wherever possible)?
>>>> Not only to reduce the bloating size of respective binaries, but
>>>> also to
>>>> avoid some code being added to hot path routines like
>>>> hreg_compute_hflags_value().
>>>
>>> qemu-system-ppc64 is a superset of qemu-system-ppc, and there are
>>> even efforts to unify all system functionality into a singly binary,
>>> so excluding a 32-bit feature from qemu-system-ppc64 sounds like a
>>> step into the wrong direction to me right now...?
>>
>> We do have existing code getting conditionally compiled for TARGET_PPC64
>> which I guess gets enabled with:
>> --configure target-list=<ppc64|ppc>-softmmu
>> I understand the efforts are towards having a single binary to support
>> both, but what gets built-in is still decided with configure choice?
>>
>> Please correct/clarify with above understanding.
>
> As I said, qemu-system-ppc64 is currently a full superset of
> qemu-system-ppc. The ppc64 binary contains all the 32-bit code, you can
> perfectly run a "g3beige" or "bamboo" machine with qemu-system-ppc64,
> too. By disabling the ppe42 code in the ppc64 binary, this would now
> introduce an execption to that unwritten rule, so I'd expect that we'd
> not rather want to do this now.
My understanding is that above holds true only for default builds which
builds all targets. We certainly do not build 32 bit ppc code when using
--configure target-list=ppc64-softmmu. (we have ppc-softmmu for 32 bit
though)
Could you please add respective folks to this thread who are working on
unifying builds to clarify more on this. We certainly dont want 32-bit
specific code to be running on a 64-bit machine, specially in hot paths.
regards,
Harsh
>
> Thomas
>
On 25/08/2025 14.08, Harsh Prateek Bora wrote:
>
>
> On 8/25/25 17:28, Thomas Huth wrote:
>> On 25/08/2025 13.46, Harsh Prateek Bora wrote:
>>> Hi Thomas,
>>>
>>> On 8/25/25 17:04, Thomas Huth wrote:
>>>> On 25/08/2025 13.24, Harsh Prateek Bora wrote:
>>>>> Hi Glenn,
>>>>>
>>>>> This seems significant work. Thanks for upstreaming.
>>>>>
>>>>> On 8/20/25 02:58, Glenn Miles wrote:
>>>>>> Adds the IBM PPE42 family of processors supporting the
>>>>>
>>>>> family of 32-bit processors ?
>>>>>
>>>>>> PPE42, PPE42X and PPE42XM processor versions. These
>>>>>> processors are used as embedded processors in the IBM
>>>>>> Power9, Power10 and Power12 processors for various
>>>>>> tasks. It is basically a stripped down version of the
>>>>>> IBM PowerPC 405 processor, with some added instructions
>>>>>> for handling 64-bit loads and stores.
>>>>>>
>>>>>> For more information on the PPE 42 processor please visit:
>>>>>>
>>>>>> https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
>>>>>>
>>>>>> Supports PPE42 SPR's (Including the MSR) and Exceptions.
>>>>>>
>>>>>> Does not yet support new PPE42 instructions and does not
>>>>>> prevent access to some invalid instructions and registers
>>>>>> (currently allows for access to invalid GPR's and CR fields).
>>>>>>
>>>>>> Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
>>>>>> ---
>>>>>> target/ppc/cpu-models.c | 7 +
>>>>>> target/ppc/cpu-models.h | 4 +
>>>>>> target/ppc/cpu.h | 66 +++++++-
>>>>>> target/ppc/cpu_init.c | 286 ++++++++++++++++++++++++++++++-----
>>>>>> target/ppc/excp_helper.c | 171 +++++++++++++++++++++
>>>>>> target/ppc/helper_regs.c | 28 +++-
>>>>>> target/ppc/tcg-excp_helper.c | 12 ++
>>>>>> target/ppc/translate.c | 6 +-
>>>>>> 8 files changed, 535 insertions(+), 45 deletions(-)
>>>>>>
>>>>>> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
>>>>>> index ea86ea202a..09f73e23a8 100644
>>>>>> --- a/target/ppc/cpu-models.c
>>>>>> +++ b/target/ppc/cpu-models.c
>>>>>> @@ -116,6 +116,13 @@
>>>>>> NULL)
>>>>>> POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
>>>>>> NULL)
>>>>>> + /* PPE42 Embedded
>>>>>> Controllers */
>>>>>> + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
>>>>>> + "Generic PPE 42")
>>>>>> + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
>>>>>> + "Generic PPE 42X")
>>>>>> + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
>>>>>> + "Generic PPE 42XM")
>>>>>
>>>>> Can all the PPE42 specific code be conditionally compiled only for
>>>>> !TARGET_PPC64 (and !CONFIG_USER_ONLY wherever possible)?
>>>>> Not only to reduce the bloating size of respective binaries, but also to
>>>>> avoid some code being added to hot path routines like
>>>>> hreg_compute_hflags_value().
>>>>
>>>> qemu-system-ppc64 is a superset of qemu-system-ppc, and there are even
>>>> efforts to unify all system functionality into a singly binary, so
>>>> excluding a 32-bit feature from qemu-system-ppc64 sounds like a step
>>>> into the wrong direction to me right now...?
>>>
>>> We do have existing code getting conditionally compiled for TARGET_PPC64
>>> which I guess gets enabled with:
>>> --configure target-list=<ppc64|ppc>-softmmu
>>> I understand the efforts are towards having a single binary to support
>>> both, but what gets built-in is still decided with configure choice?
>>>
>>> Please correct/clarify with above understanding.
>>
>> As I said, qemu-system-ppc64 is currently a full superset of qemu-system-
>> ppc. The ppc64 binary contains all the 32-bit code, you can perfectly run
>> a "g3beige" or "bamboo" machine with qemu-system-ppc64, too. By disabling
>> the ppe42 code in the ppc64 binary, this would now introduce an execption
>> to that unwritten rule, so I'd expect that we'd not rather want to do this
>> now.
>
> My understanding is that above holds true only for default builds which
> builds all targets. We certainly do not build 32 bit ppc code when using
> --configure target-list=ppc64-softmmu. (we have ppc-softmmu for 32 bit though)
Just give it a try:
./configure --target-list=ppc64-softmmu --disable-docs
make -j$(nproc)
./qemu-system-ppc64 -M g3beige
... works perfectly fine for me.
AFAIK we don't have a switch to disable 32-bit code in the ppc64 binary.
Thomas
On 8/25/25 17:52, Thomas Huth wrote:
> On 25/08/2025 14.08, Harsh Prateek Bora wrote:
>>
>>
>> On 8/25/25 17:28, Thomas Huth wrote:
>>> On 25/08/2025 13.46, Harsh Prateek Bora wrote:
>>>> Hi Thomas,
>>>>
>>>> On 8/25/25 17:04, Thomas Huth wrote:
>>>>> On 25/08/2025 13.24, Harsh Prateek Bora wrote:
>>>>>> Hi Glenn,
>>>>>>
>>>>>> This seems significant work. Thanks for upstreaming.
>>>>>>
>>>>>> On 8/20/25 02:58, Glenn Miles wrote:
>>>>>>> Adds the IBM PPE42 family of processors supporting the
>>>>>>
>>>>>> family of 32-bit processors ?
>>>>>>
>>>>>>> PPE42, PPE42X and PPE42XM processor versions. These
>>>>>>> processors are used as embedded processors in the IBM
>>>>>>> Power9, Power10 and Power12 processors for various
>>>>>>> tasks. It is basically a stripped down version of the
>>>>>>> IBM PowerPC 405 processor, with some added instructions
>>>>>>> for handling 64-bit loads and stores.
>>>>>>>
>>>>>>> For more information on the PPE 42 processor please visit:
>>>>>>>
>>>>>>> https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
>>>>>>>
>>>>>>> Supports PPE42 SPR's (Including the MSR) and Exceptions.
>>>>>>>
>>>>>>> Does not yet support new PPE42 instructions and does not
>>>>>>> prevent access to some invalid instructions and registers
>>>>>>> (currently allows for access to invalid GPR's and CR fields).
>>>>>>>
>>>>>>> Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
>>>>>>> ---
>>>>>>> target/ppc/cpu-models.c | 7 +
>>>>>>> target/ppc/cpu-models.h | 4 +
>>>>>>> target/ppc/cpu.h | 66 +++++++-
>>>>>>> target/ppc/cpu_init.c | 286
>>>>>>> ++++++++++++++++++++++++++++++-----
>>>>>>> target/ppc/excp_helper.c | 171 +++++++++++++++++++++
>>>>>>> target/ppc/helper_regs.c | 28 +++-
>>>>>>> target/ppc/tcg-excp_helper.c | 12 ++
>>>>>>> target/ppc/translate.c | 6 +-
>>>>>>> 8 files changed, 535 insertions(+), 45 deletions(-)
>>>>>>>
>>>>>>> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
>>>>>>> index ea86ea202a..09f73e23a8 100644
>>>>>>> --- a/target/ppc/cpu-models.c
>>>>>>> +++ b/target/ppc/cpu-models.c
>>>>>>> @@ -116,6 +116,13 @@
>>>>>>> NULL)
>>>>>>> POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
>>>>>>> NULL)
>>>>>>> + /* PPE42 Embedded
>>>>>>> Controllers */
>>>>>>> + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
>>>>>>> + "Generic PPE 42")
>>>>>>> + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
>>>>>>> + "Generic PPE 42X")
>>>>>>> + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
>>>>>>> + "Generic PPE 42XM")
>>>>>>
>>>>>> Can all the PPE42 specific code be conditionally compiled only for
>>>>>> !TARGET_PPC64 (and !CONFIG_USER_ONLY wherever possible)?
>>>>>> Not only to reduce the bloating size of respective binaries, but
>>>>>> also to
>>>>>> avoid some code being added to hot path routines like
>>>>>> hreg_compute_hflags_value().
>>>>>
>>>>> qemu-system-ppc64 is a superset of qemu-system-ppc, and there are
>>>>> even efforts to unify all system functionality into a singly
>>>>> binary, so excluding a 32-bit feature from qemu-system-ppc64 sounds
>>>>> like a step into the wrong direction to me right now...?
>>>>
>>>> We do have existing code getting conditionally compiled for
>>>> TARGET_PPC64
>>>> which I guess gets enabled with:
>>>> --configure target-list=<ppc64|ppc>-softmmu
>>>> I understand the efforts are towards having a single binary to support
>>>> both, but what gets built-in is still decided with configure choice?
>>>>
>>>> Please correct/clarify with above understanding.
>>>
>>> As I said, qemu-system-ppc64 is currently a full superset of
>>> qemu-system- ppc. The ppc64 binary contains all the 32-bit code, you
>>> can perfectly run a "g3beige" or "bamboo" machine with
>>> qemu-system-ppc64, too. By disabling the ppe42 code in the ppc64
>>> binary, this would now introduce an execption to that unwritten rule,
>>> so I'd expect that we'd not rather want to do this now.
>>
>> My understanding is that above holds true only for default builds which
>> builds all targets. We certainly do not build 32 bit ppc code when using
>> --configure target-list=ppc64-softmmu. (we have ppc-softmmu for 32 bit
>> though)
>
> Just give it a try:
>
> ./configure --target-list=ppc64-softmmu --disable-docs
> make -j$(nproc)
> ./qemu-system-ppc64 -M g3beige
>
> ... works perfectly fine for me.
>
This would work because the respective code is not restricted with
#ifndef TARGET_PPC64.
However, there are instance like below in hw/ppc/mac_oldworld.c:
static void heathrow_class_init(ObjectClass *oc, const void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
mc->desc = "Heathrow based PowerMac";
mc->init = ppc_heathrow_init;
mc->block_default_type = IF_IDE;
/* SMP is not supported currently */
mc->max_cpus = 1;
#ifndef TARGET_PPC64
mc->is_default = true;
#endif
Similarly, we have multiple instances with #else block for #ifdef
TARGET_PPC64 which doesnt get compiled with ppc64-softmmu, but only with
ppc-softmmu meant for 32-bit targets. See target/ppc/excp_helper.c for
example.
regards,
Harsh
> AFAIK we don't have a switch to disable 32-bit code in the ppc64 binary.
>
> Thomas
>
On Mon, 25 Aug 2025, Harsh Prateek Bora wrote:
> On 8/25/25 17:52, Thomas Huth wrote:
>> On 25/08/2025 14.08, Harsh Prateek Bora wrote:
>>> On 8/25/25 17:28, Thomas Huth wrote:
>>>> As I said, qemu-system-ppc64 is currently a full superset of qemu-system-
>>>> ppc. The ppc64 binary contains all the 32-bit code, you can perfectly run
>>>> a "g3beige" or "bamboo" machine with qemu-system-ppc64, too. By disabling
>>>> the ppe42 code in the ppc64 binary, this would now introduce an execption
>>>> to that unwritten rule, so I'd expect that we'd not rather want to do
>>>> this now.
>>>
>>> My understanding is that above holds true only for default builds which
>>> builds all targets. We certainly do not build 32 bit ppc code when using
>>> --configure target-list=ppc64-softmmu. (we have ppc-softmmu for 32 bit
>>> though)
We do build 32-bit machines in ppc64-softmmu but leave out 64-bit from
ppc-softmmu so it's only one way.
>> Just give it a try:
>>
>> ./configure --target-list=ppc64-softmmu --disable-docs
>> make -j$(nproc)
>> ./qemu-system-ppc64 -M g3beige
>>
>> ... works perfectly fine for me.
>>
> This would work because the respective code is not restricted with #ifndef
> TARGET_PPC64.
>
> However, there are instance like below in hw/ppc/mac_oldworld.c:
>
> static void heathrow_class_init(ObjectClass *oc, const void *data)
> {
> MachineClass *mc = MACHINE_CLASS(oc);
> FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
>
> mc->desc = "Heathrow based PowerMac";
> mc->init = ppc_heathrow_init;
> mc->block_default_type = IF_IDE;
> /* SMP is not supported currently */
> mc->max_cpus = 1;
> #ifndef TARGET_PPC64
> mc->is_default = true;
> #endif
This is only because the default machine for ppc64-softmmu is different
than for ppc-softmmu as the 64-bit machines don't exist in ppc-softmmu but
ppc64-softmmu had different default machine before machines from
qemu-system-ppc got included in qemu-system-ppc64 so it kept that. (Looks
like the default used to be mac_newworld before commit 159f8286b760dea but
wasn't changed to match but to something else.) The default machines are
arbitrary, we could make "none" the default and always require users to
supply -machine but that would break existing command lines so this wasn't
done.
> Similarly, we have multiple instances with #else block for #ifdef
> TARGET_PPC64 which doesnt get compiled with ppc64-softmmu, but only with
> ppc-softmmu meant for 32-bit targets. See target/ppc/excp_helper.c for
> example.
This is again leaving out 64-bit code from ppc-softmmu but as Thomas says
32-bit machines are always included in qemu-softmmu-ppc64. I can't find
the commit which changed this, previously we had these to be separate and
since some types are different in ppc64-softmmu it wasn't clear if that
could cause any problems for 32-bit CPUs and machines so ppc-softmmu was
kept until that's cleaned up which never happened. There are also some
pecularities in some machines like mac_newworld that behaves differently
in qemu-system-ppc and qemu-system-ppc64 and the potentially lower
performance of qemu-system-ppc64 in emulating 32-bit machines which is why
we still have ppc-softmmu.
Regards,
BALATON Zoltan
> regards,
> Harsh
>
>> AFAIK we don't have a switch to disable 32-bit code in the ppc64 binary.
>>
>> Thomas
>>
>
>
On 8/25/25 20:03, BALATON Zoltan wrote:
> On Mon, 25 Aug 2025, Harsh Prateek Bora wrote:
>> On 8/25/25 17:52, Thomas Huth wrote:
>>> On 25/08/2025 14.08, Harsh Prateek Bora wrote:
>>>> On 8/25/25 17:28, Thomas Huth wrote:
>>>>> As I said, qemu-system-ppc64 is currently a full superset of
>>>>> qemu-system- ppc. The ppc64 binary contains all the 32-bit code,
>>>>> you can perfectly run a "g3beige" or "bamboo" machine with
>>>>> qemu-system-ppc64, too. By disabling the ppe42 code in the ppc64
>>>>> binary, this would now introduce an execption to that unwritten
>>>>> rule, so I'd expect that we'd not rather want to do this now.
>>>>
>>>> My understanding is that above holds true only for default builds which
>>>> builds all targets. We certainly do not build 32 bit ppc code when
>>>> using
>>>> --configure target-list=ppc64-softmmu. (we have ppc-softmmu for 32
>>>> bit though)
>
> We do build 32-bit machines in ppc64-softmmu but leave out 64-bit from
> ppc-softmmu so it's only one way.
>
>>> Just give it a try:
>>>
>>> ./configure --target-list=ppc64-softmmu --disable-docs
>>> make -j$(nproc)
>>> ./qemu-system-ppc64 -M g3beige
>>>
>>> ... works perfectly fine for me.
>>>
>> This would work because the respective code is not restricted with
>> #ifndef TARGET_PPC64.
>>
>> However, there are instance like below in hw/ppc/mac_oldworld.c:
>>
>> static void heathrow_class_init(ObjectClass *oc, const void *data)
>> {
>> MachineClass *mc = MACHINE_CLASS(oc);
>> FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
>>
>> mc->desc = "Heathrow based PowerMac";
>> mc->init = ppc_heathrow_init;
>> mc->block_default_type = IF_IDE;
>> /* SMP is not supported currently */
>> mc->max_cpus = 1;
>> #ifndef TARGET_PPC64
>> mc->is_default = true;
>> #endif
>
> This is only because the default machine for ppc64-softmmu is different
> than for ppc-softmmu as the 64-bit machines don't exist in ppc-softmmu
> but ppc64-softmmu had different default machine before machines from
> qemu-system-ppc got included in qemu-system-ppc64 so it kept that.
> (Looks like the default used to be mac_newworld before commit
> 159f8286b760dea but wasn't changed to match but to something else.) The
> default machines are arbitrary, we could make "none" the default and
> always require users to supply -machine but that would break existing
> command lines so this wasn't done.
>
>> Similarly, we have multiple instances with #else block for #ifdef
>> TARGET_PPC64 which doesnt get compiled with ppc64-softmmu, but only with
>> ppc-softmmu meant for 32-bit targets. See target/ppc/excp_helper.c for
>> example.
>
> This is again leaving out 64-bit code from ppc-softmmu but as Thomas
> says 32-bit machines are always included in qemu-softmmu-ppc64. I can't
> find the commit which changed this, previously we had these to be
> separate and since some types are different in ppc64-softmmu it wasn't
> clear if that could cause any problems for 32-bit CPUs and machines so
> ppc-softmmu was kept until that's cleaned up which never happened. There
> are also some pecularities in some machines like mac_newworld that
> behaves differently in qemu-system-ppc and qemu-system-ppc64 and the
> potentially lower performance of qemu-system-ppc64 in emulating 32-bit
> machines which is why we still have ppc-softmmu.
>
Ok, I see. So, if we wish to keep the 32-bit machines supported with
qemu-system-ppc64, we will have them co-exist with run-time checks for
!ppc64 and/or "unlikely" operations in the hot path routines, which
wouldnt be needed otherwise. I hope we can deal with run-time checks for
!ppc64 if such ops increase.
Thanks to Thomas and you for clarifying this.
regards,
Harsh
> Regards,
> BALATON Zoltan
>
>> regards,
>> Harsh
>>
>>> AFAIK we don't have a switch to disable 32-bit code in the ppc64 binary.
>>>
>>> Thomas
>>>
>>
>>
On Tue, 26 Aug 2025, Harsh Prateek Bora wrote:
> On 8/25/25 20:03, BALATON Zoltan wrote:
>> On Mon, 25 Aug 2025, Harsh Prateek Bora wrote:
>>> On 8/25/25 17:52, Thomas Huth wrote:
>>>> On 25/08/2025 14.08, Harsh Prateek Bora wrote:
>>>>> On 8/25/25 17:28, Thomas Huth wrote:
>>>>>> As I said, qemu-system-ppc64 is currently a full superset of
>>>>>> qemu-system- ppc. The ppc64 binary contains all the 32-bit code, you
>>>>>> can perfectly run a "g3beige" or "bamboo" machine with
>>>>>> qemu-system-ppc64, too. By disabling the ppe42 code in the ppc64
>>>>>> binary, this would now introduce an execption to that unwritten rule,
>>>>>> so I'd expect that we'd not rather want to do this now.
>>>>>
>>>>> My understanding is that above holds true only for default builds which
>>>>> builds all targets. We certainly do not build 32 bit ppc code when using
>>>>> --configure target-list=ppc64-softmmu. (we have ppc-softmmu for 32 bit
>>>>> though)
>>
>> We do build 32-bit machines in ppc64-softmmu but leave out 64-bit from
>> ppc-softmmu so it's only one way.
>>
>>>> Just give it a try:
>>>>
>>>> ./configure --target-list=ppc64-softmmu --disable-docs
>>>> make -j$(nproc)
>>>> ./qemu-system-ppc64 -M g3beige
>>>>
>>>> ... works perfectly fine for me.
>>>>
>>> This would work because the respective code is not restricted with #ifndef
>>> TARGET_PPC64.
>>>
>>> However, there are instance like below in hw/ppc/mac_oldworld.c:
>>>
>>> static void heathrow_class_init(ObjectClass *oc, const void *data)
>>> {
>>> MachineClass *mc = MACHINE_CLASS(oc);
>>> FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
>>>
>>> mc->desc = "Heathrow based PowerMac";
>>> mc->init = ppc_heathrow_init;
>>> mc->block_default_type = IF_IDE;
>>> /* SMP is not supported currently */
>>> mc->max_cpus = 1;
>>> #ifndef TARGET_PPC64
>>> mc->is_default = true;
>>> #endif
>>
>> This is only because the default machine for ppc64-softmmu is different
>> than for ppc-softmmu as the 64-bit machines don't exist in ppc-softmmu but
>> ppc64-softmmu had different default machine before machines from
>> qemu-system-ppc got included in qemu-system-ppc64 so it kept that. (Looks
>> like the default used to be mac_newworld before commit 159f8286b760dea but
>> wasn't changed to match but to something else.) The default machines are
>> arbitrary, we could make "none" the default and always require users to
>> supply -machine but that would break existing command lines so this wasn't
>> done.
>>
>>> Similarly, we have multiple instances with #else block for #ifdef
>>> TARGET_PPC64 which doesnt get compiled with ppc64-softmmu, but only with
>>> ppc-softmmu meant for 32-bit targets. See target/ppc/excp_helper.c for
>>> example.
>>
>> This is again leaving out 64-bit code from ppc-softmmu but as Thomas says
>> 32-bit machines are always included in qemu-softmmu-ppc64. I can't find the
>> commit which changed this, previously we had these to be separate and since
>> some types are different in ppc64-softmmu it wasn't clear if that could
>> cause any problems for 32-bit CPUs and machines so ppc-softmmu was kept
>> until that's cleaned up which never happened. There are also some
>> pecularities in some machines like mac_newworld that behaves differently in
>> qemu-system-ppc and qemu-system-ppc64 and the potentially lower performance
>> of qemu-system-ppc64 in emulating 32-bit machines which is why we still
>> have ppc-softmmu.
>>
>
> Ok, I see. So, if we wish to keep the 32-bit machines supported with
> qemu-system-ppc64, we will have them co-exist with run-time checks for !ppc64
> and/or "unlikely" operations in the hot path routines, which wouldnt be
> needed otherwise. I hope we can deal with run-time checks for !ppc64 if such
> ops increase.
I guess this will only get worse with the single binary that will also add
if target == checks and removes some of the optimisations that assumed
endianness and word size. It would be good if somebody could do some tests
to check performance issues which could be made part of the test suite so
we at least notice these changes. I'm not sure what would be a good set of
benchmarks, I've used STREAM to check memory access and exceptions/MMU and
lame some.waw some.mp3 to check FPU and vector instructions speed before
but maybe there are better tools.
I've also tried adding function pointers to CPU class for different
exception models to remove the switch from the beginning of excp handling
functions that call out to PPC64 specific versions but I found that to be
slower than the current switch at least on x86_64 host.
Regards,
BALATON Zoltan
On 2025-08-26 14:12, BALATON Zoltan wrote:
> On Tue, 26 Aug 2025, Harsh Prateek Bora wrote:
>> On 8/25/25 20:03, BALATON Zoltan wrote:
>>> On Mon, 25 Aug 2025, Harsh Prateek Bora wrote:
>>>> On 8/25/25 17:52, Thomas Huth wrote:
>>>>> On 25/08/2025 14.08, Harsh Prateek Bora wrote:
>>>>>> On 8/25/25 17:28, Thomas Huth wrote:
>>>>>>> As I said, qemu-system-ppc64 is currently a full superset of
>>>>>>> qemu-system- ppc. The ppc64 binary contains all the 32-bit code, you
>>>>>>> can perfectly run a "g3beige" or "bamboo" machine with
>>>>>>> qemu-system-ppc64, too. By disabling the ppe42 code in the ppc64
>>>>>>> binary, this would now introduce an execption to that unwritten rule,
>>>>>>> so I'd expect that we'd not rather want to do this now.
>>>>>>
>>>>>> My understanding is that above holds true only for default builds which
>>>>>> builds all targets. We certainly do not build 32 bit ppc code when using
>>>>>> --configure target-list=ppc64-softmmu. (we have ppc-softmmu for 32 bit
>>>>>> though)
>>>
>>> We do build 32-bit machines in ppc64-softmmu but leave out 64-bit from
>>> ppc-softmmu so it's only one way.
>>>
>>>>> Just give it a try:
>>>>>
>>>>> ./configure --target-list=ppc64-softmmu --disable-docs
>>>>> make -j$(nproc)
>>>>> ./qemu-system-ppc64 -M g3beige
>>>>>
>>>>> ... works perfectly fine for me.
>>>>>
>>>> This would work because the respective code is not restricted with #ifndef
>>>> TARGET_PPC64.
>>>>
>>>> However, there are instance like below in hw/ppc/mac_oldworld.c:
>>>>
>>>> static void heathrow_class_init(ObjectClass *oc, const void *data)
>>>> {
>>>> MachineClass *mc = MACHINE_CLASS(oc);
>>>> FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
>>>>
>>>> mc->desc = "Heathrow based PowerMac";
>>>> mc->init = ppc_heathrow_init;
>>>> mc->block_default_type = IF_IDE;
>>>> /* SMP is not supported currently */
>>>> mc->max_cpus = 1;
>>>> #ifndef TARGET_PPC64
>>>> mc->is_default = true;
>>>> #endif
>>>
>>> This is only because the default machine for ppc64-softmmu is different
>>> than for ppc-softmmu as the 64-bit machines don't exist in ppc-softmmu but
>>> ppc64-softmmu had different default machine before machines from
>>> qemu-system-ppc got included in qemu-system-ppc64 so it kept that. (Looks
>>> like the default used to be mac_newworld before commit 159f8286b760dea but
>>> wasn't changed to match but to something else.) The default machines are
>>> arbitrary, we could make "none" the default and always require users to
>>> supply -machine but that would break existing command lines so this wasn't
>>> done.
>>>
>>>> Similarly, we have multiple instances with #else block for #ifdef
>>>> TARGET_PPC64 which doesnt get compiled with ppc64-softmmu, but only with
>>>> ppc-softmmu meant for 32-bit targets. See target/ppc/excp_helper.c for
>>>> example.
>>>
>>> This is again leaving out 64-bit code from ppc-softmmu but as Thomas says
>>> 32-bit machines are always included in qemu-softmmu-ppc64. I can't find the
>>> commit which changed this, previously we had these to be separate and since
>>> some types are different in ppc64-softmmu it wasn't clear if that could
>>> cause any problems for 32-bit CPUs and machines so ppc-softmmu was kept
>>> until that's cleaned up which never happened. There are also some
>>> pecularities in some machines like mac_newworld that behaves differently in
>>> qemu-system-ppc and qemu-system-ppc64 and the potentially lower performance
>>> of qemu-system-ppc64 in emulating 32-bit machines which is why we still
>>> have ppc-softmmu.
>>>
>>
>> Ok, I see. So, if we wish to keep the 32-bit machines supported with
>> qemu-system-ppc64, we will have them co-exist with run-time checks for !ppc64
>> and/or "unlikely" operations in the hot path routines, which wouldnt be
>> needed otherwise. I hope we can deal with run-time checks for !ppc64 if such
>> ops increase.
>
> I guess this will only get worse with the single binary that will also add
> if target == checks and removes some of the optimisations that assumed
> endianness and word size. It would be good if somebody could do some tests
> to check performance issues which could be made part of the test suite so
> we at least notice these changes. I'm not sure what would be a good set of
> benchmarks, I've used STREAM to check memory access and exceptions/MMU and
> lame some.waw some.mp3 to check FPU and vector instructions speed before
> but maybe there are better tools.
>
> I've also tried adding function pointers to CPU class for different
> exception models to remove the switch from the beginning of excp handling
> functions that call out to PPC64 specific versions but I found that to be
> slower than the current switch at least on x86_64 host.
>
Having performance tests would be a great addition to the QEMU test
suite, whether it's for the single binary or any other change.
Concerning the single binary, we have no plan to modify ppc target code
for now. As well, most of other architecture already handle 32 vs 64bits
and endianness with runtime paths, and it has not been a problem so far.
I still think it's better to write proper code and eventually optimize
parts identified by proper profiling. But impacting architecture and use
preprocessor heavily before any proof that is needed has been found is
premature optimization IMHO.
Regards,
Pierrick
© 2016 - 2025 Red Hat, Inc.