reenable tests
[openpower-isa.git] / src / openpower / decoder / power_decoder2.py
index a0e87d19756ec1362f65ac3b70736ab55b541762..b73fbe761e311e75402de7e8e981a3dff04e8aa4 100644 (file)
@@ -31,8 +31,8 @@ from openpower.decoder.power_enums import (MicrOp, CryIn, Function,
                                            CRInSel, CROutSel,
                                            LdstLen, In1Sel, In2Sel, In3Sel,
                                            OutSel, SPRfull, SPRreduced,
-                                           RC, SVP64LDSTmode, LDSTMode,
-                                           SVEXTRA, SVEtype, SVPtype)
+                                           RCOE, SVP64LDSTmode, LDSTMode,
+                                           SVEXTRA, SVEType, SVPType)
 from openpower.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
                                                Decode2ToOperand)
 
@@ -163,6 +163,13 @@ class DecodeA(Elaboratable):
             comb += reg.data.eq(frs)
             comb += reg.ok.eq(1)
 
+        # select Register FRT field,
+        frt = Signal(5, reset_less=True)
+        comb += frt.eq(self.dec.FRT)
+        with m.If(self.sel_in == In1Sel.FRT):
+            comb += reg.data.eq(frt)
+            comb += reg.ok.eq(1)
+
         # decode Fast-SPR based on instruction type
         with m.Switch(op.internal_op):
 
@@ -330,9 +337,6 @@ class DecodeBImm(Elaboratable):
             with m.Case(In2Sel.CONST_SH32):  # unsigned - for shift
                 comb += self.imm_out.data.eq(self.dec.SH32)
                 comb += self.imm_out.ok.eq(1)
-            with m.Case(In2Sel.CONST_XBI):  # unsigned - for grevi
-                comb += self.imm_out.data.eq(self.dec.FormXB.XBI)
-                comb += self.imm_out.ok.eq(1)
 
         return m
 
@@ -365,6 +369,9 @@ class DecodeC(Elaboratable):
             with m.Case(In3Sel.FRS):
                 comb += reg.data.eq(self.dec.FRS)
                 comb += reg.ok.eq(1)
+            with m.Case(In3Sel.FRA):
+                comb += reg.data.eq(self.dec.FRA)
+                comb += reg.ok.eq(1)
             with m.Case(In3Sel.FRC):
                 comb += reg.data.eq(self.dec.FRC)
                 comb += reg.ok.eq(1)
@@ -385,7 +392,7 @@ class DecodeC(Elaboratable):
 class DecodeOut(Elaboratable):
     """DecodeOut from instruction
 
-    decodes output register RA, RT or SPR
+    decodes output register RA, RT, FRS, FRT, or SPR
     """
 
     def __init__(self, dec, op, regreduce_en):
@@ -412,6 +419,12 @@ class DecodeOut(Elaboratable):
 
         # select Register out field
         with m.Switch(self.sel_in):
+            with m.Case(OutSel.FRS):
+                comb += reg.data.eq(self.dec.FRS)
+                comb += reg.ok.eq(1)
+            with m.Case(OutSel.FRA):
+                comb += reg.data.eq(self.dec.FRA)
+                comb += reg.ok.eq(1)
             with m.Case(OutSel.FRT):
                 comb += reg.data.eq(self.dec.FRT)
                 comb += reg.ok.eq(1)
@@ -467,11 +480,12 @@ class DecodeOut2(Elaboratable):
         self.dec = dec
         self.op = op
         self.sel_in = Signal(OutSel, reset_less=True)
-        self.svp64_fft_mode = Signal(reset_less=True)  # SVP64 FFT mode
+        self.implicit_rs = Signal(reset_less=True)  # SVP64 implicit RS/FRS
+        self.implicit_from_rc = Signal(reset_less=True)# implicit RS from RC
         self.lk = Signal(reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(5, "reg_o2")
-        self.fp_madd_en = Signal(reset_less=True)  # FFT instruction detected
+        self.rs_en = Signal(reset_less=True)  # FFT instruction detected
         self.fast_out = Data(4, "fast_o2")
         self.fast_out3 = Data(4, "fast_o3")
 
@@ -510,10 +524,13 @@ class DecodeOut2(Elaboratable):
         # SVP64 FFT mode, FP mul-add: 2nd output reg (FRS) same as FRT
         # will be offset by VL in hardware
         # with m.Case(MicrOp.OP_FP_MADD):
-        with m.If(self.svp64_fft_mode):
-            comb += self.reg_out.data.eq(self.dec.FRT)
+        with m.If(self.implicit_rs):
+            with m.If(self.implicit_from_rc):
+                comb += self.reg_out.data.eq(self.dec.FRC) # same as RC
+            with m.Else():
+                comb += self.reg_out.data.eq(self.dec.FRT) # same as RT
             comb += self.reg_out.ok.eq(1)
-            comb += self.fp_madd_en.eq(1)
+            comb += self.rs_en.eq(1)
 
         return m
 
@@ -526,7 +543,7 @@ class DecodeRC(Elaboratable):
 
     def __init__(self, dec):
         self.dec = dec
-        self.sel_in = Signal(RC, reset_less=True)
+        self.sel_in = Signal(RCOE, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.rc_out = Data(1, "rc")
 
@@ -536,13 +553,13 @@ class DecodeRC(Elaboratable):
 
         # select Record bit out field
         with m.Switch(self.sel_in):
-            with m.Case(RC.RC):
+            with m.Case(RCOE.RC, RCOE.RC_ONLY):
                 comb += self.rc_out.data.eq(self.dec.Rc)
                 comb += self.rc_out.ok.eq(1)
-            with m.Case(RC.ONE):
+            with m.Case(RCOE.ONE):
                 comb += self.rc_out.data.eq(1)
                 comb += self.rc_out.ok.eq(1)
-            with m.Case(RC.NONE):
+            with m.Case(RCOE.NONE):
                 comb += self.rc_out.data.eq(0)
                 comb += self.rc_out.ok.eq(1)
 
@@ -552,48 +569,30 @@ class DecodeRC(Elaboratable):
 class DecodeOE(Elaboratable):
     """DecodeOE from instruction
 
-    decodes OE field: uses RC decode detection which might not be good
-
-    -- For now, use "rc" in the decode table to decide whether oe exists.
-    -- This is not entirely correct architecturally: For mulhd and
-    -- mulhdu, the OE field is reserved. It remains to be seen what an
-    -- actual POWER9 does if we set it on those instructions, for now we
-    -- test that further down when assigning to the multiplier oe input.
+    decodes OE field: uses RC decode detection which has now been
+    updated to separate out RC_ONLY.  all cases RC_ONLY are *NOT*
+    listening to the OE field, here.
     """
 
     def __init__(self, dec, op):
         self.dec = dec
         self.op = op
-        self.sel_in = Signal(RC, reset_less=True)
+        self.sel_in = Signal(RCOE, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.oe_out = Data(1, "oe")
 
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
-        op = self.op
-
-        with m.Switch(op.internal_op):
 
-            # mulhw, mulhwu, mulhd, mulhdu - these *ignore* OE
-            # also rotate
-            # XXX ARGH! ignoring OE causes incompatibility with microwatt
-            # http://lists.libre-soc.org/pipermail/libre-soc-dev/2020-August/000302.html
-            with m.Case(MicrOp.OP_MUL_H64, MicrOp.OP_MUL_H32,
-                        MicrOp.OP_EXTS, MicrOp.OP_CNTZ,
-                        MicrOp.OP_SHL, MicrOp.OP_SHR, MicrOp.OP_RLC,
-                        MicrOp.OP_LOAD, MicrOp.OP_STORE,
-                        MicrOp.OP_RLCL, MicrOp.OP_RLCR,
-                        MicrOp.OP_EXTSWSLI, MicrOp.OP_GREV):
-                pass
-
-            # all other ops decode OE field
+        with m.Switch(self.sel_in):
+            with m.Case(RCOE.RC):
+                comb += self.oe_out.data.eq(self.dec.OE)
+                comb += self.oe_out.ok.eq(1)
             with m.Default():
-                # select OE bit out field
-                with m.Switch(self.sel_in):
-                    with m.Case(RC.RC):
-                        comb += self.oe_out.data.eq(self.dec.OE)
-                        comb += self.oe_out.ok.eq(1)
+                # default: clear OE.
+                comb += self.oe_out.data.eq(0)
+                comb += self.oe_out.ok.eq(0)
 
         return m
 
@@ -689,6 +688,8 @@ class DecodeCROut(Elaboratable):
         self.cr_bitfield = Data(3, "cr_bitfield")
         self.whole_reg = Data(8,  "cr_fxm")
         self.sv_override = Signal(2, reset_less=True)  # do not do EXTRA spec
+        self.cr_5bit = Signal(reset_less=True)  # set True for 5-bit
+        self.cr_2bit = Signal(2, reset_less=True)  # get lowest 2 bits
 
     def elaborate(self, platform):
         m = Module()
@@ -700,6 +701,7 @@ class DecodeCROut(Elaboratable):
         comb += self.cr_bitfield.ok.eq(0)
         comb += self.whole_reg.ok.eq(0)
         comb += self.sv_override.eq(0)
+        comb += self.cr_5bit.eq(0)
 
         # please note these MUST match (setting of cr_bitfield.ok) exactly
         # with write_cr0 below in PowerDecoder2.  the reason it's separated
@@ -724,6 +726,8 @@ class DecodeCROut(Elaboratable):
             with m.Case(CROutSel.BT):
                 comb += self.cr_bitfield.data.eq(self.dec.FormXL.BT[2:5])
                 comb += self.cr_bitfield.ok.eq(1)
+                comb += self.cr_5bit.eq(1)
+                comb += self.cr_2bit.eq(self.dec.FormXL.BT[0:2])
             with m.Case(CROutSel.WHOLE_REG):
                 comb += self.whole_reg.ok.eq(1)
                 move_one = Signal(reset_less=True)
@@ -751,6 +755,7 @@ class DecodeCROut(Elaboratable):
 record_names = {'insn_type': 'internal_op',
                 'fn_unit': 'function_unit',
                 'SV_Ptype': 'SV_Ptype',
+                'SV_mode': 'SV_mode',
                 'rc': 'rc_sel',
                 'oe': 'rc_sel',
                 'zero_a': 'in1_sel',
@@ -779,14 +784,16 @@ class PowerDecodeSubset(Elaboratable):
     """
 
     def __init__(self, dec, opkls=None, fn_name=None, final=False, state=None,
-                 svp64_en=True, regreduce_en=False):
+                 svp64_en=True, regreduce_en=False, fp_en=False):
 
         self.svp64_en = svp64_en
         self.regreduce_en = regreduce_en
+        self.fp_en = fp_en
         if svp64_en:
             self.is_svp64_mode = Signal()  # mark decoding as SVP64 Mode
-            self.use_svp64_ldst_dec = Signal()  # must use LDST decoder
-            self.use_svp64_fft = Signal()      # FFT Mode
+            self.implicit_rs = Signal()    # implicit RS/FRS
+            self.extend_rb_maxvl = Signal() # jumps RB by an additional MAXVL
+            self.extend_rc_maxvl = Signal() # jumps RS by MAXVL from RC
             self.sv_rm = SVP64Rec(name="dec_svp64")  # SVP64 RM field
             self.rm_dec = SVP64RMModeDecode("svp64_rm_dec")
             # set these to the predicate mask bits needed for the ALU
@@ -810,8 +817,8 @@ class PowerDecodeSubset(Elaboratable):
         # alternatives.  useful for PCR (Program Compatibility Register)
         # amongst other things
         if svp64_en:
-            conditions = {'SVP64BREV': self.use_svp64_ldst_dec,
-                          'SVP64FFT': self.use_svp64_fft,
+            conditions = {
+                          # XXX NO 'SVP64FFT': self.use_svp64_fft,
                           }
         else:
             conditions = None
@@ -825,7 +832,7 @@ class PowerDecodeSubset(Elaboratable):
         if dec is None:
             dec = create_pdecode(name=fn_name, col_subset=col_subset,
                                  row_subset=row_subset,
-                                 conditions=conditions)
+                                 conditions=conditions, include_fp=fp_en)
         self.dec = dec
 
         # set up a copy of the PowerOp
@@ -860,6 +867,11 @@ class PowerDecodeSubset(Elaboratable):
                 # to support multiple tasks (unit column multiple entries)
                 # see https://bugs.libre-soc.org/show_bug.cgi?id=310
                 (self.fn_name == 'MMU' and row['unit'] == 'SPR' and
+                 row['internal op'] in ['OP_MTSPR', 'OP_MFSPR']) or
+                # urrr... and the KAIVB SPR, which must also be redirected
+                # (to the TRAP pipeline)
+                # see https://bugs.libre-soc.org/show_bug.cgi?id=859
+                (self.fn_name == 'TRAP' and row['unit'] == 'SPR' and
                  row['internal op'] in ['OP_MTSPR', 'OP_MFSPR'])
                 )
 
@@ -868,8 +880,7 @@ class PowerDecodeSubset(Elaboratable):
         if self.svp64_en:
             ports += self.sv_rm.ports()
             ports.append(self.is_svp64_mode)
-            ports.append(self.use_svp64_ldst_dec)
-            ports.append(self.use_svp64_fft)
+            ports.append(self.implicit_rs)
         return ports
 
     def needs_field(self, field, op_field):
@@ -953,20 +964,30 @@ class PowerDecodeSubset(Elaboratable):
 
         # Microwatt doesn't implement the partition table
         # instead has PRTBL register (SPR) to point to process table
+        # Kestrel has a KAIVB SPR to "rebase" exceptions. rebasing is normally
+        # done with Hypervisor Mode which is not implemented (yet)
         is_spr_mv = Signal()
         is_mmu_spr = Signal()
+        is_trap_spr = Signal()
         comb += is_spr_mv.eq((internal_op == MicrOp.OP_MTSPR) |
                              (internal_op == MicrOp.OP_MFSPR))
         comb += is_mmu_spr.eq((spr == SPR.DSISR.value) |
                               (spr == SPR.DAR.value) |
                               (spr == SPR.PRTBL.value) |
                               (spr == SPR.PIDR.value))
+        comb += is_trap_spr.eq((spr == SPR.KAIVB.value)
+                              )
         # MMU must receive MMU SPRs
         with m.If(is_spr_mv & (fn == Function.SPR) & is_mmu_spr):
             comb += self.do_copy("fn_unit", Function.MMU)
             comb += self.do_copy("insn_type", internal_op)
-        # SPR pipe must *not* receive MMU SPRs
-        with m.Elif(is_spr_mv & (fn == Function.MMU) & ~is_mmu_spr):
+        # TRAP must receive TRAP SPR KAIVB
+        with m.If(is_spr_mv & (fn == Function.SPR) & is_trap_spr):
+            comb += self.do_copy("fn_unit", Function.TRAP)
+            comb += self.do_copy("insn_type", internal_op)
+        # SPR pipe must *not* receive MMU or TRAP SPRs
+        with m.Elif(is_spr_mv & ((fn == Function.MMU) & ~is_mmu_spr) &
+                                ((fn == Function.TRAP) & ~is_trap_spr)):
             comb += self.do_copy("fn_unit", Function.NONE)
             comb += self.do_copy("insn_type", MicrOp.OP_ILLEGAL)
         # all others ok
@@ -984,15 +1005,6 @@ class PowerDecodeSubset(Elaboratable):
             comb += dec_bi.sel_in.eq(self.op_get("in2_sel"))
             comb += self.do_copy("imm_data", dec_bi.imm_out)  # imm in RB
 
-        # rc and oe out
-        comb += self.do_copy("rc", dec_rc.rc_out)
-        if self.svp64_en:
-            # OE only enabled when SVP64 not active
-            with m.If(~self.is_svp64_mode):
-                comb += self.do_copy("oe", dec_oe.oe_out)
-        else:
-            comb += self.do_copy("oe", dec_oe.oe_out)
-
         # CR in/out - note: these MUST match with what happens in
         # DecodeCROut!
         rc_out = self.dec_rc.rc_out.data
@@ -1012,28 +1024,10 @@ class PowerDecodeSubset(Elaboratable):
             # quickly determined, and the Decoder result MUXed over to
             # the alternative decoder, svdecldst. what a mess... *sigh*
             sv_ptype = self.op_get("SV_Ptype")
+            sv_mode = self.op_get("SV_mode")
             fn = self.op_get("function_unit")
-            # detect major opcode for LDs: include 58 here. from CSV files.
-            # BLECH! TODO: these should be done using "mini decoders",
-            # using row and column subsets
-            is_major_ld = Signal()
-            # bits... errr... MSB0 0..5 which is 26:32 python
-            major = Signal(6)
-            comb += major.eq(self.dec.opcode_in[26:32])
-            comb += is_major_ld.eq((major == 34) | (major == 35) |
-                                   (major == 50) | (major == 51) |
-                                   (major == 48) | (major == 49) |
-                                   (major == 42) | (major == 43) |
-                                   (major == 40) | (major == 41) |
-                                   (major == 32) | (major == 33) |
-                                   (major == 58))
-            with m.If(self.is_svp64_mode & is_major_ld):
-                # straight-up: "it's a LD".  this gives enough info
-                # for SVP64 RM Mode decoding to detect LD/ST, and
-                # consequently detect the SHIFT mode. sigh
-                comb += rm_dec.fn_in.eq(Function.LDST)
-            with m.Else():
-                comb += rm_dec.fn_in.eq(fn)  # decode needs to know Fn type
+            comb += rm_dec.sv_mode.eq(sv_mode)  # BRANCH/CROP/LDST_IMM etc.
+            comb += rm_dec.fn_in.eq(fn)  # decode needs to know Fn type
             comb += rm_dec.ptype_in.eq(sv_ptype)  # Single/Twin predicated
             comb += rm_dec.rc_in.eq(rc_out)  # Rc=1
             comb += rm_dec.rm_in.eq(self.sv_rm)  # SVP64 RM mode
@@ -1042,20 +1036,73 @@ class PowerDecodeSubset(Elaboratable):
                 comb += rm_dec.ldst_imz_in.eq(bzero)  # B immediate is zero
 
             # main PowerDecoder2 determines if different SVP64 modes enabled
-            if not self.final:
-                # if shift mode requested
-                shiftmode = rm_dec.ldstmode == SVP64LDSTmode.SHIFT
-                comb += self.use_svp64_ldst_dec.eq(shiftmode)
             # detect if SVP64 FFT mode enabled (really bad hack),
             # exclude fcfids and others
             # XXX this is a REALLY bad hack, REALLY has to be done better.
             # likely with a sub-decoder.
-            xo5 = Signal(1)  # 1 bit from Minor 59 XO field == 0b0XXXX
-            comb += xo5.eq(self.dec.opcode_in[5])
-            xo = Signal(5)  # 5 bits from Minor 59 fcfids == 0b01110
-            comb += xo.eq(self.dec.opcode_in[1:6])
-            comb += self.use_svp64_fft.eq((major == 59) & (xo5 == 0b0) &
-                                          (xo != 0b01110))
+            # what this ultimately does is enable the 2nd implicit register
+            # (FRS) for SVP64-decoding.  all of these instructions are
+            # 3-in 2-out but there is not enough room either in the
+            # opcode *or* EXTRA2/3 to specify a 5th operand.
+            major = Signal(6)
+            comb += major.eq(self.dec.opcode_in[26:32])
+            xo = Signal(10)
+            comb += xo.eq(self.dec.opcode_in[1:11])
+            comb += self.implicit_rs.eq(0)
+            comb += self.extend_rb_maxvl.eq(0)
+            comb += self.extend_rc_maxvl.eq(0)
+            # implicit RS for major 59
+            with m.If((major == 59) & xo.matches(
+                    '-----00100',  # ffmsubs
+                    '-----00101',  # ffmadds
+                    '-----00110',  # ffnmsubs
+                    '-----00111',  # ffnmadds
+                    '1111100000',  # ffadds
+                    '-----11011',  # fdmadds
+                )):
+                comb += self.implicit_rs.eq(1)
+                comb += self.extend_rb_maxvl.eq(1) # extend RB
+            xo6 = Signal(6)
+            comb += xo6.eq(self.dec.opcode_in[0:6])
+            # implicit RS for major 4
+            with m.If((major == 4) & xo6.matches(
+                    '111000',  # pcdec
+                    '110010',  # maddedu
+                    '111001',  # maddedus
+                    '111010',  # divmod2du
+                    '11010-',  # dsld
+                    '11011-',  # dsrd
+                )):
+                comb += self.implicit_rs.eq(1)
+                comb += self.extend_rc_maxvl.eq(1) # RS=RT+MAXVL or RS=RC
+            # implicit RS for major 22, integer maddsubrs
+            with m.If((major == 22) & xo6.matches(
+                    '-01000',  # maddsubrs
+                    '-01001',  # maddrs
+                    '-01011',  # msubrs
+                )):
+                comb += self.implicit_rs.eq(1)
+                comb += self.extend_rb_maxvl.eq(1) # extend RB
+
+        # rc and oe out
+        comb += self.do_copy("rc", dec_rc.rc_out)
+        if self.svp64_en:
+            # OE only enabled when SVP64 not active
+            with m.If(~self.is_svp64_mode):
+                comb += self.do_copy("oe", dec_oe.oe_out)
+            # RC1 overrides Rc if rc type is NONE or ONE or Rc=0, in svp64_mode
+            # for instructions with a forced-Rc=1 (stbcx., pcdec.)
+            # the RC1 RM bit *becomes* Rc=0/1, but for instructions
+            # that have Rc=0/1 then when Rc=0 RC1 *becomes* (replaces) Rc.
+            with m.Elif((dec_rc.sel_in.matches(RCOE.RC, RCOE.RC_ONLY) &
+                         dec_rc.rc_out.data == 0) |
+                         (dec_rc.sel_in == RCOE.ONE)):
+                RC1 = Data(1, "RC1")
+                comb += RC1.ok.eq(rm_dec.RC1)
+                comb += RC1.RC1.eq(rm_dec.RC1)
+                comb += self.do_copy("rc", RC1)
+        else:
+            comb += self.do_copy("oe", dec_oe.oe_out)
 
         # decoded/selected instruction flags
         comb += self.do_copy("data_len", self.op_get("ldst_len"))
@@ -1128,11 +1175,12 @@ class PowerDecode2(PowerDecodeSubset):
     """
 
     def __init__(self, dec, opkls=None, fn_name=None, final=False,
-                 state=None, svp64_en=True, regreduce_en=False):
+                 state=None, svp64_en=True, regreduce_en=False, fp_en=False):
         super().__init__(dec, opkls, fn_name, final, state, svp64_en,
-                         regreduce_en=False)
+                         regreduce_en=False, fp_en=fp_en)
         self.ldst_exc = LDSTException("dec2_exc")  # rewrites as OP_TRAP
         self.instr_fault = Signal()  # rewrites instruction as OP_FETCH_FAILED
+        self.crout_5bit = Signal()  # CR out is 5-bit
 
         if self.svp64_en:
             self.cr_out_isvec = Signal(1, name="cr_out_isvec")
@@ -1175,6 +1223,7 @@ class PowerDecode2(PowerDecodeSubset):
             subset.add("sv_cr_out")
             subset.add("SV_Etype")
             subset.add("SV_Ptype")
+            subset.add("SV_mode")
             # from SVP64RMModeDecode
             for (field, _) in sv_input_record_layout:
                 subset.add(field)
@@ -1205,6 +1254,7 @@ class PowerDecode2(PowerDecodeSubset):
         m.submodules.dec_cr_in = self.dec_cr_in = DecodeCRIn(self.dec, op)
         m.submodules.dec_cr_out = self.dec_cr_out = DecodeCROut(self.dec, op)
         comb += dec_a.sv_nz.eq(self.sv_a_nz)
+        comb += self.crout_5bit.eq(self.dec_cr_out.cr_5bit)
 
         if self.svp64_en:
             # and SVP64 Extra decoders
@@ -1247,7 +1297,8 @@ class PowerDecode2(PowerDecodeSubset):
         comb += dec_o.sel_in.eq(self.op_get("out_sel"))
         comb += dec_o2.sel_in.eq(self.op_get("out_sel"))
         if self.svp64_en:
-            comb += dec_o2.svp64_fft_mode.eq(self.use_svp64_fft)
+            comb += dec_o2.implicit_rs.eq(self.implicit_rs)
+            comb += dec_o2.implicit_from_rc.eq(self.extend_rc_maxvl)
         if hasattr(do, "lk"):
             comb += dec_o2.lk.eq(do.lk)
 
@@ -1288,16 +1339,29 @@ class PowerDecode2(PowerDecodeSubset):
 
             # get SVSTATE srcstep (TODO: elwidth etc.) needed below
             vl = Signal.like(self.state.svstate.vl)
+            maxvl = Signal.like(self.state.svstate.maxvl)
+            subvl = Signal.like(self.rm_dec.rm_in.subvl)
             srcstep = Signal.like(self.state.svstate.srcstep)
             dststep = Signal.like(self.state.svstate.dststep)
+            ssubstep = Signal.like(self.state.svstate.ssubstep)
+            dsubstep = Signal.like(self.state.svstate.ssubstep)
             comb += vl.eq(self.state.svstate.vl)
+            comb += maxvl.eq(self.state.svstate.maxvl)
+            comb += subvl.eq(self.rm_dec.rm_in.subvl)
             comb += srcstep.eq(self.state.svstate.srcstep)
             comb += dststep.eq(self.state.svstate.dststep)
+            comb += ssubstep.eq(self.state.svstate.ssubstep)
+            comb += dsubstep.eq(self.state.svstate.dsubstep)
 
             in1_step, in2_step = self.in1_step, self.in2_step
             in3_step = self.in3_step
             o_step, o2_step = self.o_step, self.o2_step
 
+            # multiply vl by subvl - note that this is only 7 bit!
+            # when elwidth overrides get involved this will have to go up
+            vmax = Signal(7)
+            comb += vmax.eq(vl*(subvl+1))
+
             # registers a, b, c and out and out2 (LD/ST EA)
             sv_etype = self.op_get("SV_Etype")
             for i, stuff in enumerate((
@@ -1305,7 +1369,7 @@ class PowerDecode2(PowerDecodeSubset):
                 ("RB", e.read_reg2, dec_b.reg_out, in2_svdec, in2_step, False),
                 ("RC", e.read_reg3, dec_c.reg_out, in3_svdec, in3_step, False),
                 ("RT", e.write_reg, dec_o.reg_out, o_svdec, o_step, True),
-                    ("EA", e.write_ea, dec_o2.reg_out, o2_svdec, o2_step, True))):
+                ("EA", e.write_ea, dec_o2.reg_out, o2_svdec, o2_step, True))):
                 rname, to_reg, fromreg, svdec, remapstep, out = stuff
                 comb += svdec.extra.eq(extra)     # EXTRA field of SVP64 RM
                 comb += svdec.etype.eq(sv_etype)  # EXTRA2/3 for this insn
@@ -1320,26 +1384,30 @@ class PowerDecode2(PowerDecodeSubset):
                     # automagically add on an extra offset to RB.
                     # however when REMAP is active, the FFT REMAP
                     # schedule takes care of this offset.
-                    with m.If(dec_o2.reg_out.ok & dec_o2.fp_madd_en):
+                    with m.If(dec_o2.reg_out.ok & dec_o2.rs_en &
+                              self.extend_rb_maxvl):
                         with m.If(~self.remap_active[i]):
                             with m.If(svdec.isvec):
-                                comb += offs.eq(vl)  # VL for Vectors
+                                comb += offs.eq(maxvl)  # MAXVL for Vectors
                 # detect if Vectorised: add srcstep/dststep if yes.
                 # to_reg is 7-bits, outs get dststep added, ins get srcstep
                 with m.If(svdec.isvec):
                     selectstep = dststep if out else srcstep
+                    subselect = dsubstep if out else ssubstep
                     step = Signal(7, name="step_%s" % rname.lower())
                     with m.If(self.remap_active[i]):
-                        comb += step.eq(remapstep)
+                        comb += step.eq((remapstep*(subvl+1))+subselect)
                     with m.Else():
-                        comb += step.eq(selectstep)
+                        comb += step.eq((selectstep*(subvl+1))+subselect)
                     # reverse gear goes the opposite way
                     with m.If(self.rm_dec.reverse_gear):
-                        comb += to_reg.data.eq(offs+svdec.reg_out+(vl-1-step))
+                        comb += to_reg.offs.eq(offs+(vmax-1-step))
                     with m.Else():
-                        comb += to_reg.data.eq(offs+step+svdec.reg_out)
+                        comb += to_reg.offs.eq(offs+step)
                 with m.Else():
-                    comb += to_reg.data.eq(offs+svdec.reg_out)
+                    comb += to_reg.offs.eq(offs)
+                comb += to_reg.base.eq(svdec.reg_out)
+                comb += to_reg.data.eq(to_reg.base + to_reg.offs)
 
             # SVP64 in/out fields
             comb += in1_svdec.idx.eq(self.op_get("sv_in1"))  # reg #1 (in1_sel)
@@ -1360,33 +1428,47 @@ class PowerDecode2(PowerDecodeSubset):
             comb += self.o2_isvec.eq(o2_svdec.isvec)
 
             # urrr... don't ask... the implicit register FRS in FFT mode
-            # "tracks" FRT exactly except it's offset by VL.  rather than
+            # "tracks" FRT exactly except it's offset by MAXVL.  rather than
             # mess up the above with if-statements, override it here.
-            # same trick is applied to FRA, above, but it's a lot cleaner, there
-            with m.If(dec_o2.reg_out.ok & dec_o2.fp_madd_en):
+            # same trick is applied to FRB, above, but it's a lot cleaner there
+            with m.If(dec_o2.reg_out.ok & dec_o2.rs_en):
+                imp_reg_out = Signal(7)
+                imp_isvec   = Signal(1)
+                with m.If(self.extend_rc_maxvl): # maddedu etc. from RC
+                    comb += imp_isvec.eq(in3_svdec.isvec)
+                    comb += imp_reg_out.eq(in3_svdec.reg_out)
+                with m.Else():
+                    comb += imp_isvec.eq(o_svdec.isvec)
+                    comb += imp_reg_out.eq(o_svdec.reg_out)
                 comb += offs.eq(0)
                 with m.If(~self.remap_active[4]):
-                    with m.If(o2_svdec.isvec):
-                        comb += offs.eq(vl)  # VL for Vectors
+                    with m.If(imp_isvec):
+                        comb += offs.eq(maxvl)  # MAXVL for Vectors
+                    with m.Elif(self.extend_rc_maxvl): # maddedu etc. from RC
+                        comb += offs.eq(0)  # keep as RC
                     with m.Else():
                         comb += offs.eq(1)  # add 1 if scalar
-                svdec = o_svdec  # yes take source as o_svdec...
-                with m.If(svdec.isvec):
+                with m.If(imp_isvec):
                     step = Signal(7, name="step_%s" % rname.lower())
                     with m.If(self.remap_active[4]):
-                        comb += step.eq(o2_step)
+                        with m.If(self.extend_rc_maxvl): # maddedu etc. from RC
+                            comb += step.eq(in3_step)
+                        with m.Else():
+                            comb += step.eq(o2_step)
                     with m.Else():
                         comb += step.eq(dststep)
                     # reverse gear goes the opposite way
                     with m.If(self.rm_dec.reverse_gear):
                         roffs = offs+(vl-1-step)
-                        comb += to_reg.data.eq(roffs+svdec.reg_out)
+                        comb += e.write_ea.data.eq(roffs)
                     with m.Else():
-                        comb += to_reg.data.eq(offs+step+svdec.reg_out)
+                        comb += e.write_ea.data.eq(offs+step)
                 with m.Else():
-                    comb += to_reg.data.eq(offs+svdec.reg_out)
+                    comb += e.write_ea.offs.eq(offs)
+                comb += e.write_ea.base.eq(imp_reg_out)
+                comb += e.write_ea.data.eq(e.write_ea.base + e.write_ea.offs)
                 # ... but write to *second* output
-                comb += self.o2_isvec.eq(svdec.isvec)
+                comb += self.o2_isvec.eq(imp_isvec)
                 comb += o2_svdec.idx.eq(self.op_get("sv_out"))
 
             # TODO add SPRs here.  must be True when *all* are scalar
@@ -1406,11 +1488,11 @@ class PowerDecode2(PowerDecodeSubset):
             # should continue.  this doesn't include predication bit-tests
             loop = self.loop_continue
             with m.Switch(self.op_get("SV_Ptype")):
-                with m.Case(SVPtype.P2.value):
+                with m.Case(SVPType.P2.value):
                     # twin-predication
                     # TODO: *and cache-inhibited LD/ST!*
                     comb += loop.eq(~(self.no_in_vec | self.no_out_vec))
-                with m.Case(SVPtype.P1.value):
+                with m.Case(SVPType.P1.value):
                     # single-predication, test relies on dest only
                     comb += loop.eq(~self.no_out_vec)
                 with m.Default():
@@ -1422,7 +1504,7 @@ class PowerDecode2(PowerDecodeSubset):
                 (e.read_cr1, self.dec_cr_in, "cr_bitfield", crin_svdec, 0),
                 (e.read_cr2, self.dec_cr_in, "cr_bitfield_b", crin_svdec_b, 0),
                 (e.read_cr3, self.dec_cr_in, "cr_bitfield_o", crin_svdec_o, 0),
-                    (e.write_cr, self.dec_cr_out, "cr_bitfield", crout_svdec, 1)):
+                (e.write_cr, self.dec_cr_out, "cr_bitfield", crout_svdec, 1)):
                 fromreg = getattr(cr, name)
                 comb += svdec.extra.eq(extra)     # EXTRA field of SVP64 RM
                 comb += svdec.etype.eq(sv_etype)  # EXTRA2/3 for this insn
@@ -1468,6 +1550,10 @@ class PowerDecode2(PowerDecodeSubset):
 
         if self.svp64_en:
             comb += self.rm_dec.ldst_ra_vec.eq(self.in1_isvec)  # RA is vector
+            comb += self.rm_dec.cr_5bit_in.eq(self.crout_5bit)  # CR is 5-bit
+            # take bottom 2 bits of CR out (CR field selector)
+            with m.If(self.crout_5bit):
+                comb += self.rm_dec.cr_2bit_in.eq(self.dec_cr_out.cr_2bit)
 
         # SPRs out
         comb += e.read_spr1.eq(dec_a.spr_out)
@@ -1582,12 +1668,6 @@ class PowerDecode2(PowerDecodeSubset):
         # Note: OP_SC could actually be modified to just be a trap
         with m.If((do_out.insn_type == MicrOp.OP_TRAP) |
                   (do_out.insn_type == MicrOp.OP_SC)):
-            # see fu/trap/main_stage.py trap() function: some bits of SRR1
-            # need to be preserved, rather than just blithely overwrite MSR.
-            # following microwatt, here.
-            # TRAP read fast2 = SRR1
-            comb += e_out.read_fast2.data.eq(FastRegsEnum.SRR1)  # SRR1
-            comb += e_out.read_fast2.ok.eq(1)
             # TRAP write fast1 = SRR0
             comb += e_out.write_fast1.data.eq(FastRegsEnum.SRR0)  # SRR0
             comb += e_out.write_fast1.ok.eq(1)