| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -3,9 +3,10 @@ from amaranth.utils import log2_int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				from power_fv import pfv
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				from power_fv.insn.const import *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				from power_fv.intr import *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				from . import InsnSpec
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				from .utils import iea, byte_reversed
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				from .utils import iea, byte_reversed, msr_to_srr1
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				__all__ = ["LoadStoreSpec"]
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -18,250 +19,296 @@ class LoadStoreSpec(InsnSpec, Elaboratable):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.pfv.stb .eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.pfv.insn.eq(Cat(Const(0, 32), self.insn.as_value())),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.pfv.nia .eq(iea(self.pfv.cia + 4, self.pfv.msr.r_data.sf)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.pfv.msr.r_mask.sf.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # EA (effective address) = ea_base + ea_offset
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # Raise an interrupt if RA is invalid
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ea        = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ea_base   = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ea_offset = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # ea_base : (RA|0) or (RA)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        m.d.comb += self.pfv.ra.index.eq(self.insn.RA)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        illegal_insn = Record([
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ("ra_zero", 1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ("ra_rt"  , 1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZ, LBZX, LHZ, LHZX, LHA, LHAX, LWZ, LWZX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STB, STBX, STH, STHX, STW, STWX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LWBRX, STHBRX, STWBRX
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.ra.r_stb.eq(self.insn.RA != 0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ea_base.eq(Mux(self.insn.RA != 0, self.pfv.ra.r_data, 0)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZU, LBZUX, LHZU, LHZUX, LHAU, LHAUX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STBU, STBUX, STHU, STHUX, STWU, STWUX
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STBU, STBUX, STHU, STHUX, STWU, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.ra.r_stb.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ea_base.eq(self.pfv.ra.r_data),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # ea_offset : EXTS(D) or (RB)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += illegal_insn.ra_zero.eq(self.insn.RA == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZ, LBZU, LHZ, LHZU, LHA, LHAU, LWZ, LWZU,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STB, STBU, STH, STHU, STW, STWU,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += ea_offset.eq(self.insn.D.as_signed())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZX, LBZUX, LHZX, LHZUX, LHAX, LHAUX, LWZX, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STBX, STBUX, STHX, STHUX, STWX, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LWBRX, STHBRX, STWBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZU, LBZUX, LHZU, LHZUX, LHAU, LHAUX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.rb.index.eq(self.insn.RB),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.rb.r_stb.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ea_offset.eq(self.pfv.rb.r_data)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        m.d.comb += ea.eq(iea(ea_base + ea_offset, self.pfv.msr.r_data.sf))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # If `pfv.mem_aligned` is set, `pfv.mem.addr` points to the dword containing EA.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # If `pfv.mem_aligned` is unset, `pfv.mem.addr` is equal to EA.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        byte_offset = Signal(3)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        half_offset = Signal(2)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        word_offset = Signal(1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += illegal_insn.ra_rt.eq(self.insn.RA == self.insn.RT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        m.d.comb += self.pfv.mem.addr[3:].eq(ea[3:])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        with m.If(illegal_insn.any()):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if self.pfv.illegal_insn_heai:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                raise NotImplementedError
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if self.pfv.mem_aligned:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.mem.addr[:3].eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                byte_offset.eq(ea[:3]),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.mem.addr[:3].eq(ea[:3]),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                byte_offset.eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.intr.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.nia .eq(INTR_PROGRAM.vector_addr),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                INTR_PROGRAM.write_msr(self.pfv.msr),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr0.w_mask.eq(Repl(1, 64)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr0.w_data.eq(iea(self.pfv.cia, self.pfv.msr.r_data.sf)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr1.w_mask[63-36:64-33].eq(Repl(1, 4)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr1.w_data[63-36:64-33].eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr1.w_mask[63-42].eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr1.w_data[63-42].eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr1.w_mask[63-46:64-43].eq(Repl(1, 4)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr1.w_data[63-46:64-43].eq(0b0100), # Illegal Instruction type (deprecated)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr1.w_mask[63-47].eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.srr1.w_data[63-47].eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                msr_to_srr1(self.pfv.msr, self.pfv.srr1,  0, 32),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                msr_to_srr1(self.pfv.msr, self.pfv.srr1, 37, 41),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                msr_to_srr1(self.pfv.msr, self.pfv.srr1, 48, 63),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            half_offset.eq(byte_offset[1:]),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            word_offset.eq(byte_offset[2:]),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        with m.Else():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            # EA (effective address) = ea_base + ea_offset
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        msr_le = self.pfv.msr.r_data.le
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        m.d.comb += self.pfv.msr.r_mask.le.eq(1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ea        = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ea_base   = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ea_offset = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # Load: read from memory, then write the result to RT.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            # ea_base : (RA|0) or (RA)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZ, LBZX, LBZU, LBZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LHZ, LHZX, LHZU, LHZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LHA, LHAX, LHAU, LHAUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LWZ, LWZX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LWBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            load_byte   = Signal( 8)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            load_half   = Signal(16)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            load_word   = Signal(32)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            load_result = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                load_byte.eq(self.pfv.mem.r_data.word_select(byte_offset, width= 8)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                load_half.eq(self.pfv.mem.r_data.word_select(half_offset, width=16)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                load_word.eq(self.pfv.mem.r_data.word_select(word_offset, width=32)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += self.pfv.ra.index.eq(self.insn.RA)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if isinstance(self.insn, (LBZ, LBZX, LBZU, LBZUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LBZ, LBZX, LHZ, LHZX, LHA, LHAX, LWZ, LWZX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                STB, STBX, STH, STHX, STW, STWX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LWBRX, STHBRX, STWBRX
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.r_mask.word_select(byte_offset, width=1).eq(0x1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_result.eq(load_byte.as_unsigned()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.ra.r_stb.eq(self.insn.RA != 0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    ea_base.eq(Mux(self.insn.RA != 0, self.pfv.ra.r_data, 0)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (LHZ, LHZX, LHZU, LHZUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LBZU, LBZUX, LHZU, LHZUX, LHAU, LHAUX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                STBU, STBUX, STHU, STHUX, STWU, STWUX
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.r_mask.word_select(half_offset, width=2).eq(0x3),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_result.eq(byte_reversed(load_half, ~msr_le).as_unsigned()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.ra.r_stb.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    ea_base.eq(self.pfv.ra.r_data),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (LHA, LHAX, LHAU, LHAUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.r_mask.word_select(half_offset, width=2).eq(0x3),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_result.eq(byte_reversed(load_half, ~msr_le).as_signed())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (LWZ, LWZX, LWZU, LWZUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.r_mask.word_select(word_offset, width=4).eq(0xf),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_result.eq(byte_reversed(load_word, ~msr_le).as_unsigned()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, LWBRX):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            # ea_offset : EXTS(D) or (RB)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LBZ, LBZU, LHZ, LHZU, LHA, LHAU, LWZ, LWZU,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                STB, STBU, STH, STHU, STW, STWU,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += ea_offset.eq(self.insn.D.as_signed())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LBZX, LBZUX, LHZX, LHZUX, LHAX, LHAUX, LWZX, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                STBX, STBUX, STHX, STHUX, STWX, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LWBRX, STHBRX, STWBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.r_mask.word_select(word_offset, width=4).eq(0xf),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_result.eq(byte_reversed(load_word, msr_le).as_unsigned()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.rb.index.eq(self.insn.RB),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.rb.r_stb.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    ea_offset.eq(self.pfv.rb.r_data)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.rt.index .eq(self.insn.RT),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.rt.w_stb .eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.rt.w_data.eq(load_result),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += ea.eq(iea(ea_base + ea_offset, self.pfv.msr.r_data.sf))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # Store: read from RS, then write the result to memory.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            byte_offset = Signal(3)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            half_offset = Signal(2)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            word_offset = Signal(1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STB, STBX, STBU, STBUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STH, STHX, STHU, STHUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STW, STWX, STWU, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STHBRX, STWBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            store_byte = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            store_half = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            store_word = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            # If `pfv.mem_aligned` is set, `pfv.mem.addr` points to the dword containing EA.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            # If `pfv.mem_aligned` is unset, `pfv.mem.addr` is equal to EA.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.rs.index.eq(self.insn.RS),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.rs.r_stb.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += self.pfv.mem.addr[3:].eq(ea[3:])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                store_byte.eq(Repl(self.pfv.rs.r_data[: 8], count=8)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                store_half.eq(Repl(self.pfv.rs.r_data[:16], count=4)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                store_word.eq(Repl(self.pfv.rs.r_data[:32], count=2)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if isinstance(self.insn, (STB, STBX, STBU, STBUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_mask.word_select(byte_offset, width=1).eq(0x1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_data.eq(store_byte),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (STH, STHX, STHU, STHUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_mask.word_select(half_offset, width=2).eq(0x3),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_data.eq(byte_reversed(store_half, ~msr_le)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (STW, STWX, STWU, STWUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_mask.word_select(word_offset, width=4).eq(0xf),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_data.eq(byte_reversed(store_word, ~msr_le)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, STHBRX):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if self.pfv.mem_aligned:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_mask.word_select(half_offset, width=2).eq(0x3),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_data.eq(byte_reversed(store_half, msr_le)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.addr[:3].eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    byte_offset.eq(ea[:3]),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, STWBRX):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_mask.word_select(word_offset, width=4).eq(0xf),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.w_data.eq(byte_reversed(store_word, msr_le)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.mem.addr[:3].eq(ea[:3]),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    byte_offset.eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # Load/store with update: write EA to RA.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZU, LBZUX, LHZU, LHZUX, LHAU, LHAUX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STBU, STBUX, STHU, STHUX, STWU, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.ra.w_stb .eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                self.pfv.ra.w_data.eq(ea),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                half_offset.eq(byte_offset[1:]),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                word_offset.eq(byte_offset[2:]),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # Interrupt causes
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            # Raise an Alignment Interrupt if EA is misaligned wrt. `pfv.mem`
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ea_misaligned = Signal()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LBZ, LBZX, LBZU, LBZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                STB, STBX, STBU, STBUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += ea_misaligned.eq(0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LHZ, LHZX, LHZU, LHZUX, LHA, LHAX, LHAU, LHAUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                STH, STHX, STHU, STHUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                STHBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += ea_misaligned.eq(byte_offset[0])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LWZ, LWZX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                STW, STWX, STWU, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                LWBRX, STWBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += ea_misaligned.eq(byte_offset[:1].any())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        intr = Record([
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ("misaligned",  1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ("update_zero", 1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ("update_rt",   1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            with m.If(ea_misaligned):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.intr.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.nia .eq(INTR_ALIGNMENT.vector_addr),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    INTR_ALIGNMENT.write_msr(self.pfv.msr),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZ, LBZX, LBZU, LBZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STB, STBX, STBU, STBUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += intr.misaligned.eq(0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LHZ, LHZX, LHZU, LHZUX, LHA, LHAX, LHAU, LHAUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STH, STHX, STHU, STHUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STHBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += intr.misaligned.eq(byte_offset[0])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LWZ, LWZX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STW, STWX, STWU, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LWBRX, STWBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += intr.misaligned.eq(byte_offset[:1].any())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.srr0.w_mask.eq(Repl(1, 64)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.srr0.w_data.eq(iea(self.pfv.cia, self.pfv.msr.r_data.sf)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZU, LBZUX, LHZU, LHZUX, LHAU, LHAUX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            STBU, STBUX, STHU, STHUX, STWU, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += intr.update_zero.eq(self.insn.RA == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += intr.update_zero.eq(0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.srr1.w_mask[63-36:64-33].eq(Repl(1, 4)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.srr1.w_mask[63-36:64-33].eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.srr1.w_mask[63-47:64-42].eq(Repl(1, 6)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.pfv.srr1.w_mask[63-47:64-42].eq(0),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LBZU, LBZUX, LHZU, LHZUX, LHAU, LHAUX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += intr.update_rt.eq(self.insn.RA == self.insn.RT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += intr.update_rt.eq(0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    msr_to_srr1(self.pfv.msr, self.pfv.srr1,  0, 32),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    msr_to_srr1(self.pfv.msr, self.pfv.srr1, 37, 41),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    msr_to_srr1(self.pfv.msr, self.pfv.srr1, 48, 63),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        m.d.comb += self.pfv.intr.eq(intr.any())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            with m.Else():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                m.d.comb += self.pfv.msr.r_mask.le.eq(1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                msr_le = self.pfv.msr.r_data.le
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                # Load: read from memory, then write the result to RT.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    LBZ, LBZX, LBZU, LBZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    LHZ, LHZX, LHZU, LHZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    LHA, LHAX, LHAU, LHAUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    LWZ, LWZX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    LWBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_byte   = Signal( 8)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_half   = Signal(16)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_word   = Signal(32)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    load_result = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        load_byte.eq(self.pfv.mem.r_data.word_select(byte_offset, width= 8)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        load_half.eq(self.pfv.mem.r_data.word_select(half_offset, width=16)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        load_word.eq(self.pfv.mem.r_data.word_select(word_offset, width=32)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    if isinstance(self.insn, (LBZ, LBZX, LBZU, LBZUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.r_mask.word_select(byte_offset, width=1).eq(0x1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            load_result.eq(load_byte.as_unsigned()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    elif isinstance(self.insn, (LHZ, LHZX, LHZU, LHZUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.r_mask.word_select(half_offset, width=2).eq(0x3),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            load_result.eq(byte_reversed(load_half, ~msr_le).as_unsigned()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    elif isinstance(self.insn, (LHA, LHAX, LHAU, LHAUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.r_mask.word_select(half_offset, width=2).eq(0x3),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            load_result.eq(byte_reversed(load_half, ~msr_le).as_signed())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    elif isinstance(self.insn, (LWZ, LWZX, LWZU, LWZUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.r_mask.word_select(word_offset, width=4).eq(0xf),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            load_result.eq(byte_reversed(load_word, ~msr_le).as_unsigned()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    elif isinstance(self.insn, LWBRX):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.r_mask.word_select(word_offset, width=4).eq(0xf),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            load_result.eq(byte_reversed(load_word, msr_le).as_unsigned()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.pfv.rt.index .eq(self.insn.RT),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.pfv.rt.w_stb .eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.pfv.rt.w_data.eq(load_result),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                # Store: read from RS, then write the result to memory.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                elif isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    STB, STBX, STBU, STBUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    STH, STHX, STHU, STHUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    STW, STWX, STWU, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    STHBRX, STWBRX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    store_byte = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    store_half = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    store_word = Signal(64)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.pfv.rs.index.eq(self.insn.RS),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.pfv.rs.r_stb.eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        store_byte.eq(Repl(self.pfv.rs.r_data[: 8], count=8)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        store_half.eq(Repl(self.pfv.rs.r_data[:16], count=4)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        store_word.eq(Repl(self.pfv.rs.r_data[:32], count=2)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    if isinstance(self.insn, (STB, STBX, STBU, STBUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_mask.word_select(byte_offset, width=1).eq(0x1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_data.eq(store_byte),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    elif isinstance(self.insn, (STH, STHX, STHU, STHUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_mask.word_select(half_offset, width=2).eq(0x3),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_data.eq(byte_reversed(store_half, ~msr_le)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    elif isinstance(self.insn, (STW, STWX, STWU, STWUX)):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_mask.word_select(word_offset, width=4).eq(0xf),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_data.eq(byte_reversed(store_word, ~msr_le)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    elif isinstance(self.insn, STHBRX):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_mask.word_select(half_offset, width=2).eq(0x3),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_data.eq(byte_reversed(store_half, msr_le)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    elif isinstance(self.insn, STWBRX):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_mask.word_select(word_offset, width=4).eq(0xf),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            self.pfv.mem.w_data.eq(byte_reversed(store_word, msr_le)),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    assert False
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                # Load/store with update: write EA to RA.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if isinstance(self.insn, (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    LBZU, LBZUX, LHZU, LHZUX, LHAU, LHAUX, LWZU, LWZUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    STBU, STBUX, STHU, STHUX, STWU, STWUX,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    )):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    m.d.comb += [
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.pfv.ra.w_stb .eq(1),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.pfv.ra.w_data.eq(ea),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    ]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            # Update NIA
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            m.d.comb += self.pfv.nia.eq(iea(self.pfv.cia + 4, self.pfv.msr.r_data.sf))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return m
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |