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 <mil...@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