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


Reply via email to