fix Bug 607 - unnecessary code added related to MMU in PowerDecoder2
[soc.git] / src / soc / decoder / power_decoder2.py
index 883c91281339cf95407a9f2b9bd9f7e70530c001..4cee7ab7c903faeef3416db3f530ed2a10faed98 100644 (file)
@@ -8,6 +8,8 @@ over-riding the internal opcode when an exception is needed.
 
 from nmigen import Module, Elaboratable, Signal, Mux, Const, Cat, Repl, Record
 from nmigen.cli import rtlil
+from nmutil.util import sel
+
 from soc.regfile.regfiles import XERRegs
 
 from nmutil.picker import PriorityPicker
@@ -27,7 +29,8 @@ from soc.decoder.power_enums import (MicrOp, CryIn, Function,
 from soc.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
                                          Decode2ToOperand)
 from soc.sv.svp64 import SVP64Rec
-from soc.consts import MSR
+from soc.consts import (MSR, SPEC, EXTRA2, EXTRA3, SVP64P, field,
+                        SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs)
 
 from soc.regfile.regfiles import FastRegs
 from soc.consts import TT
@@ -48,8 +51,7 @@ def instr_is_priv(m, op, insn):
         with m.Case(MicrOp.OP_ATTN, MicrOp.OP_MFMSR, MicrOp.OP_MTMSRD,
                     MicrOp.OP_MTMSR, MicrOp.OP_RFID):
             comb += is_priv_insn.eq(1)
-        # XXX TODO
-        #with m.Case(MicrOp.OP_TLBIE) : comb += is_priv_insn.eq(1)
+        with m.Case(MicrOp.OP_TLBIE) : comb += is_priv_insn.eq(1)
         with m.Case(MicrOp.OP_MFSPR, MicrOp.OP_MTSPR):
             with m.If(insn[20]):  # field XFX.spr[-1] i think
                 comb += is_priv_insn.eq(1)
@@ -87,7 +89,7 @@ class SVP64ExtraSpec(Elaboratable):
     see https://libre-soc.org/openpower/sv/svp64/
     """
     def __init__(self):
-        self.extra   = Signal(10, reset_less=True)
+        self.extra   = Signal(9, reset_less=True)
         self.etype   = Signal(SVEtype, reset_less=True) # 2 or 3 bits
         self.idx     = Signal(SVEXTRA, reset_less=True) # which part of extra
         self.spec  = Signal(3) # EXTRA spec for the register
@@ -96,6 +98,7 @@ class SVP64ExtraSpec(Elaboratable):
         m = Module()
         comb = m.d.comb
         spec = self.spec
+        extra = self.extra
 
         # back in the LDSTRM-* and RM-* files generated by sv_analysis.py
         # we marked every op with an Etype: EXTRA2 or EXTRA3, and also said
@@ -105,23 +108,30 @@ class SVP64ExtraSpec(Elaboratable):
             # 2-bit index selection mode
             with m.Case(SVEtype.EXTRA2):
                 with m.Switch(self.idx):
-                    with m.Case(SVEXTRA.Idx0): # 1st 2 bits
-                        comb += spec[1:3].eq(self.extra[0:2])
-                    with m.Case(SVEXTRA.Idx1): # 2nd 2 bits
-                        comb += spec[1:3].eq(self.extra[2:4])
-                    with m.Case(SVEXTRA.Idx2): # 3rd 2 bits
-                        comb += spec[1:3].eq(self.extra[4:6])
-                    with m.Case(SVEXTRA.Idx3): # 4th 2 bits
-                        comb += spec[1:3].eq(self.extra[6:8])
+                    with m.Case(SVEXTRA.Idx0):  # 1st 2 bits [0:1]
+                        comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX0_VEC])
+                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX0_MSB])
+                    with m.Case(SVEXTRA.Idx1):  # 2nd 2 bits [2:3]
+                        comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX1_VEC])
+                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX1_MSB])
+                    with m.Case(SVEXTRA.Idx2):  # 3rd 2 bits [4:5]
+                        comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX2_VEC])
+                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX2_MSB])
+                    with m.Case(SVEXTRA.Idx3):  # 4th 2 bits [6:7]
+                        comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX3_VEC])
+                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX3_MSB])
             # 3-bit index selection mode
             with m.Case(SVEtype.EXTRA3):
                 with m.Switch(self.idx):
-                    with m.Case(SVEXTRA.Idx0): # 1st 3 bits
-                        comb += spec.eq(self.extra[0:3])
-                    with m.Case(SVEXTRA.Idx1): # 2nd 3 bits
-                        comb += spec.eq(self.extra[3:6])
-                    with m.Case(SVEXTRA.Idx2): # 3rd 3 bits
-                        comb += spec.eq(self.extra[6:9])
+                    with m.Case(SVEXTRA.Idx0):  # 1st 3 bits [0:2]
+                        extra3_idx0 = sel(m, extra, EXTRA3.IDX0)
+                        comb += spec.eq(extra3_idx0)
+                    with m.Case(SVEXTRA.Idx1):  # 2nd 3 bits [3:5]
+                        extra3_idx1 = sel(m, extra, EXTRA3.IDX1)
+                        comb += spec.eq(extra3_idx1)
+                    with m.Case(SVEXTRA.Idx2):  # 3rd 3 bits [6:8]
+                        extra3_idx2 = sel(m, extra, EXTRA3.IDX2)
+                        comb += spec.eq(extra3_idx2)
                     # cannot fit more than 9 bits so there is no 4th thing
 
         return m
@@ -152,19 +162,22 @@ class SVP64RegExtra(SVP64ExtraSpec):
         # which is zero which is ok.
         spec = self.spec
 
-        # now decode it. bit 2 is "scalar/vector".  note that spec could be zero
+        # now decode it. bit 0 is "scalar/vector".  note that spec could be zero
         #  from above, which (by design) has the effect of "no change", below.
 
         # simple: isvec is top bit of spec
-        comb += self.isvec.eq(spec[2])
+        comb += self.isvec.eq(spec[SPEC.VEC])
+        # extra bits for register number augmentation
+        spec_aug = Signal(SPEC_AUG_SIZE)
+        comb += spec_aug.eq(field(spec, SPECb.MSB, SPECb.LSB, SPEC_SIZE))
 
         # decode vector differently from scalar
         with m.If(self.isvec):
-            # Vector: shifted up, extra in LSBs (RA << 2) | spec[0:1]
-            comb += self.reg_out.eq(Cat(spec[:2], self.reg_in))
+            # Vector: shifted up, extra in LSBs (RA << 2) | spec[1:2]
+            comb += self.reg_out.eq(Cat(spec_aug, self.reg_in))
         with m.Else():
-            # Scalar: not shifted up, extra in MSBs RA | (spec[0:1] << 5)
-            comb += self.reg_out.eq(Cat(self.reg_in, spec[:2]))
+            # Scalar: not shifted up, extra in MSBs RA | (spec[1:2] << 5)
+            comb += self.reg_out.eq(Cat(self.reg_in, spec_aug))
 
         return m
 
@@ -184,7 +197,7 @@ class SVP64CRExtra(SVP64ExtraSpec):
     """
     def __init__(self):
         SVP64ExtraSpec.__init__(self)
-        self.cr_in  = Signal(3) # incoming CR number (3 bits, BA[2:5], BFA)
+        self.cr_in  = Signal(3) # incoming CR number (3 bits, BA[0:2], BFA)
         self.cr_out = Signal(7) # extra-augmented CR output (7 bits)
         self.isvec  = Signal(1) # reg is marked as vector if true
 
@@ -196,19 +209,22 @@ class SVP64CRExtra(SVP64ExtraSpec):
         # which is zero which is ok.
         spec = self.spec
 
-        # now decode it. bit 2 is "scalar/vector".  note that spec could be zero
+        # now decode it. bit 0 is "scalar/vector".  note that spec could be zero
         #  from above, which (by design) has the effect of "no change", below.
 
         # simple: isvec is top bit of spec
-        comb += self.isvec.eq(spec[2])
+        comb += self.isvec.eq(spec[SPEC.VEC])
+        # extra bits for register number augmentation
+        spec_aug = Signal(SPEC_AUG_SIZE)
+        comb += spec_aug.eq(field(spec, SPECb.MSB, SPECb.LSB, SPEC_SIZE))
 
-        # decode vector differently from scalar, insert bits 0 and 1 accordingly
+        # decode vector differently from scalar, insert bits 1 and 2 accordingly
         with m.If(self.isvec):
-            # Vector: shifted up, extra in LSBs (CR << 4) | (spec[0:1] << 2)
-            comb += self.cr_out.eq(Cat(Const(0, 2), spec[:2], self.cr_in))
+            # Vector: shifted up, extra in LSBs (CR << 4) | (spec[1:2] << 2)
+            comb += self.cr_out.eq(Cat(Const(0, 2), spec_aug, self.cr_in))
         with m.Else():
-            # Scalar: not shifted up, extra in MSBs CR | (spec[0:1] << 3)
-            comb += self.cr_out.eq(Cat(self.cr_in, spec[:2]))
+            # Scalar: not shifted up, extra in MSBs CR | (spec[1:2] << 3)
+            comb += self.cr_out.eq(Cat(self.cr_in, spec_aug))
 
         return m
 
@@ -649,6 +665,7 @@ class DecodeCRIn(Elaboratable):
         self.cr_bitfield_b = Data(3, "cr_bitfield_b")
         self.cr_bitfield_o = Data(3, "cr_bitfield_o")
         self.whole_reg = Data(8,  "cr_fxm")
+        self.sv_override = Signal(2, reset_less=True) # do not do EXTRA spec
 
     def elaborate(self, platform):
         m = Module()
@@ -662,6 +679,7 @@ class DecodeCRIn(Elaboratable):
         comb += self.cr_bitfield_b.ok.eq(0)
         comb += self.cr_bitfield_o.ok.eq(0)
         comb += self.whole_reg.ok.eq(0)
+        comb += self.sv_override.eq(0)
 
         # select the relevant CR bitfields
         with m.Switch(self.sel_in):
@@ -670,6 +688,11 @@ class DecodeCRIn(Elaboratable):
             with m.Case(CRInSel.CR0):
                 comb += self.cr_bitfield.data.eq(0) # CR0 (MSB0 numbering)
                 comb += self.cr_bitfield.ok.eq(1)
+                comb += self.sv_override.eq(1)
+            with m.Case(CRInSel.CR1):
+                comb += self.cr_bitfield.data.eq(1) # CR1 (MSB0 numbering)
+                comb += self.cr_bitfield.ok.eq(1)
+                comb += self.sv_override.eq(2)
             with m.Case(CRInSel.BI):
                 comb += self.cr_bitfield.data.eq(self.dec.BI[2:5])
                 comb += self.cr_bitfield.ok.eq(1)
@@ -715,6 +738,7 @@ class DecodeCROut(Elaboratable):
         self.insn_in = Signal(32, reset_less=True)
         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
 
     def elaborate(self, platform):
         m = Module()
@@ -725,6 +749,13 @@ class DecodeCROut(Elaboratable):
 
         comb += self.cr_bitfield.ok.eq(0)
         comb += self.whole_reg.ok.eq(0)
+        comb += self.sv_override.eq(0)
+
+        # please note these MUST match (setting of cr_bitfield.ok) exactly
+        # with write_cr0 below in PowerDecoder2.  the reason it's separated
+        # is to avoid having duplicate copies of DecodeCROut in multiple
+        # PowerDecoderSubsets.  register decoding should be a one-off in
+        # PowerDecoder2.  see https://bugs.libre-soc.org/show_bug.cgi?id=606
 
         with m.Switch(self.sel_in):
             with m.Case(CROutSel.NONE):
@@ -732,6 +763,11 @@ class DecodeCROut(Elaboratable):
             with m.Case(CROutSel.CR0):
                 comb += self.cr_bitfield.data.eq(0) # CR0 (MSB0 numbering)
                 comb += self.cr_bitfield.ok.eq(self.rc_in)  # only when RC=1
+                comb += self.sv_override.eq(1)
+            with m.Case(CROutSel.CR1):
+                comb += self.cr_bitfield.data.eq(1) # CR1 (MSB0 numbering)
+                comb += self.cr_bitfield.ok.eq(self.rc_in)  # only when RC=1
+                comb += self.sv_override.eq(2)
             with m.Case(CROutSel.BF):
                 comb += self.cr_bitfield.data.eq(self.dec.FormX.BF)
                 comb += self.cr_bitfield.ok.eq(1)
@@ -853,7 +889,6 @@ class PowerDecodeSubset(Elaboratable):
         state = self.state
         op, do = self.dec.op, self.do
         msr, cia = state.msr, state.pc
-
         # fill in for a normal instruction (not an exception)
         # copy over if non-exception, non-privileged etc. is detected
         if not self.final:
@@ -865,23 +900,16 @@ class PowerDecodeSubset(Elaboratable):
 
         # set up submodule decoders
         m.submodules.dec = self.dec
-        m.submodules.dec_rc = dec_rc = DecodeRC(self.dec)
+        m.submodules.dec_rc = self.dec_rc = dec_rc = DecodeRC(self.dec)
         m.submodules.dec_oe = dec_oe = DecodeOE(self.dec)
-        m.submodules.dec_cr_in = self.dec_cr_in = DecodeCRIn(self.dec)
-        m.submodules.dec_cr_out = self.dec_cr_out = DecodeCROut(self.dec)
 
         # copy instruction through...
-        for i in [do.insn,
-                  dec_rc.insn_in, dec_oe.insn_in,
-                  self.dec_cr_in.insn_in, self.dec_cr_out.insn_in]:
+        for i in [do.insn, dec_rc.insn_in, dec_oe.insn_in, ]:
             comb += i.eq(self.dec.opcode_in)
 
         # ...and subdecoders' input fields
         comb += dec_rc.sel_in.eq(op.rc_sel)
         comb += dec_oe.sel_in.eq(op.rc_sel)  # XXX should be OE sel
-        comb += self.dec_cr_in.sel_in.eq(op.cr_in)
-        comb += self.dec_cr_out.sel_in.eq(op.cr_out)
-        comb += self.dec_cr_out.rc_in.eq(dec_rc.rc_out.data)
 
         # copy "state" over
         comb += self.do_copy("msr", msr)
@@ -889,16 +917,8 @@ class PowerDecodeSubset(Elaboratable):
 
         # set up instruction type
         # no op: defaults to OP_ILLEGAL
-        if self.fn_name=="MMU":
-            # mmu is special case: needs SPR opcode as well
-            mmu0 = self.mmu0_spr_dec
-            with m.If(((mmu0.dec.op.internal_op == MicrOp.OP_MTSPR) |
-                       (mmu0.dec.op.internal_op == MicrOp.OP_MFSPR))):
-                comb += self.do_copy("insn_type", mmu0.op_get("internal_op"))
-            with m.Else():
-                comb += self.do_copy("insn_type", self.op_get("internal_op"))
-        else:
-            comb += self.do_copy("insn_type", self.op_get("internal_op"))
+        # FIX https://bugs.libre-soc.org/show_bug.cgi?id=607
+        comb += self.do_copy("insn_type", self.op_get("internal_op"))
 
         # function unit for decoded instruction: requires minor redirect
         # for SPR set/get
@@ -906,14 +926,12 @@ class PowerDecodeSubset(Elaboratable):
         spr = Signal(10, reset_less=True)
         comb += spr.eq(decode_spr_num(self.dec.SPR)) # from XFX
 
-        SPR_PID   = 48  # TODO read docs for POWER9
         # Microwatt doesn't implement the partition table
-        # instead has PRTBL register (SPR) to point to process table
-        SPR_PRTBL = 720 # see common.vhdl in microwatt, not in POWER9
+        # instead has PRTBL(SVSRR0) register (SPR) to point to process table
         with m.If(((self.dec.op.internal_op == MicrOp.OP_MTSPR) |
                    (self.dec.op.internal_op == MicrOp.OP_MFSPR)) &
-                  ((spr == SPR.DSISR) | (spr == SPR.DAR)
-                   | (spr==SPR_PRTBL) | (spr==SPR_PID))):
+                   ((spr == SPR.DSISR.value) | (spr == SPR.DAR.value) |
+                     (spr==SPR.SVSRR0.value) | (spr==SPR.PIDR.value))):
             comb += self.do_copy("fn_unit", Function.MMU)
         with m.Else():
             comb += self.do_copy("fn_unit",fn)
@@ -932,10 +950,14 @@ class PowerDecodeSubset(Elaboratable):
         comb += self.do_copy("rc", dec_rc.rc_out)
         comb += self.do_copy("oe", dec_oe.oe_out)
 
-        # CR in/out
-        comb += self.do_copy("read_cr_whole", self.dec_cr_in.whole_reg)
-        comb += self.do_copy("write_cr_whole", self.dec_cr_out.whole_reg)
-        comb += self.do_copy("write_cr0", self.dec_cr_out.cr_bitfield.ok)
+        # CR in/out - note: these MUST match with what happens in
+        # DecodeCROut!
+        rc_out = self.dec_rc.rc_out.data
+        with m.Switch(op.cr_out):
+            with m.Case(CROutSel.CR0, CROutSel.CR1):
+                comb += self.do_copy("write_cr0", rc_out) # only when RC=1
+            with m.Case(CROutSel.BF, CROutSel.BT):
+                comb += self.do_copy("write_cr0", 1)
 
         comb += self.do_copy("input_cr", self.op_get("cr_in"))   # CR in
         comb += self.do_copy("output_cr", self.op_get("cr_out"))  # CR out
@@ -1004,6 +1026,7 @@ class PowerDecode2(PowerDecodeSubset):
         self.in3_isvec = Signal(1, name="reg_c_isvec")
         self.o_isvec = Signal(1, name="reg_o_isvec")
         self.o2_isvec = Signal(1, name="reg_o2_isvec")
+        self.no_out_vec = Signal(1, name="no_out_vec") # no outputs are vectors
 
     def get_col_subset(self, opkls):
         subset = super().get_col_subset(opkls)
@@ -1031,6 +1054,7 @@ class PowerDecode2(PowerDecodeSubset):
         state = self.state
         e_out, op, do_out = self.e, self.dec.op, self.e.do
         dec_spr, msr, cia, ext_irq = state.dec, state.msr, state.pc, state.eint
+        rc_out = self.dec_rc.rc_out.data
         e = self.e_tmp
         do = e.do
 
@@ -1043,6 +1067,8 @@ class PowerDecode2(PowerDecodeSubset):
         m.submodules.dec_c = dec_c = DecodeC(self.dec)
         m.submodules.dec_o = dec_o = DecodeOut(self.dec)
         m.submodules.dec_o2 = dec_o2 = DecodeOut2(self.dec)
+        m.submodules.dec_cr_in = self.dec_cr_in = DecodeCRIn(self.dec)
+        m.submodules.dec_cr_out = self.dec_cr_out = DecodeCROut(self.dec)
 
         # and SVP64 Extra decoders
         m.submodules.crout_svdec = crout_svdec = SVP64CRExtra()
@@ -1055,14 +1081,27 @@ class PowerDecode2(PowerDecodeSubset):
         m.submodules.o_svdec = o_svdec = SVP64RegExtra()
         m.submodules.o2_svdec = o2_svdec = SVP64RegExtra()
 
+        # debug access to crout_svdec (used in get_pdecode_cr_out)
+        self.crout_svdec = crout_svdec
+
         # get the 5-bit reg data before svp64-munging it into 7-bit plus isvec
         reg = Signal(5, reset_less=True)
 
         # copy instruction through...
         for i in [do.insn, dec_a.insn_in, dec_b.insn_in,
+                  self.dec_cr_in.insn_in, self.dec_cr_out.insn_in,
                   dec_c.insn_in, dec_o.insn_in, dec_o2.insn_in]:
             comb += i.eq(self.dec.opcode_in)
 
+        # CR setup
+        comb += self.dec_cr_in.sel_in.eq(op.cr_in)
+        comb += self.dec_cr_out.sel_in.eq(op.cr_out)
+        comb += self.dec_cr_out.rc_in.eq(rc_out)
+
+        # CR register info
+        comb += self.do_copy("read_cr_whole", self.dec_cr_in.whole_reg)
+        comb += self.do_copy("write_cr_whole", self.dec_cr_out.whole_reg)
+
         # now do the SVP64 munging.  op.SV_Etype and op.sv_in1 comes from
         # PowerDecoder which in turn comes from LDST-RM*.csv and RM-*.csv
         # which in turn were auto-generated by sv_analysis.py
@@ -1104,6 +1143,10 @@ class PowerDecode2(PowerDecodeSubset):
         if hasattr(do, "lk"):
             comb += dec_o2.lk.eq(do.lk)
 
+        # get SVSTATE srcstep (TODO: elwidth, dststep etc.) needed below
+        srcstep = Signal.like(self.state.svstate.srcstep)
+        comb += srcstep.eq(self.state.svstate.srcstep)
+
         # registers a, b, c and out and out2 (LD/ST EA)
         for to_reg, fromreg, svdec in (
             (e.read_reg1, dec_a.reg_out, in1_svdec),
@@ -1114,8 +1157,13 @@ class PowerDecode2(PowerDecodeSubset):
             comb += svdec.extra.eq(extra)        # EXTRA field of SVP64 RM
             comb += svdec.etype.eq(op.SV_Etype)  # EXTRA2/3 for this insn
             comb += svdec.reg_in.eq(fromreg.data) # 3-bit (CR0/BC/BFA)
-            comb += to_reg.data.eq(svdec.reg_out) # 7-bit output
             comb += to_reg.ok.eq(fromreg.ok)
+            # detect if Vectorised: add srcstep if yes.  TODO: a LOT.
+            # this trick only holds when elwidth=default and in single-pred
+            with m.If(svdec.isvec):
+                comb += to_reg.data.eq(srcstep+svdec.reg_out) # 7-bit output
+            with m.Else():
+                comb += to_reg.data.eq(svdec.reg_out) # 7-bit output
 
         comb += in1_svdec.idx.eq(op.sv_in1)  # SVP64 reg #1 (matches in1_sel)
         comb += in2_svdec.idx.eq(op.sv_in2)  # SVP64 reg #2 (matches in2_sel)
@@ -1126,11 +1174,15 @@ class PowerDecode2(PowerDecodeSubset):
         # "update mode" rather than specified cleanly as its own CSV column
         #comb += o2_svdec.idx.eq(op.sv_out)    # SVP64 output (implicit)
 
+        # output reg-is-vectorised (and when no output is vectorised)
         comb += self.in1_isvec.eq(in1_svdec.isvec)
         comb += self.in2_isvec.eq(in2_svdec.isvec)
         comb += self.in3_isvec.eq(in3_svdec.isvec)
         comb += self.o_isvec.eq(o_svdec.isvec)
         comb += self.o2_isvec.eq(o2_svdec.isvec)
+        # TODO: include SPRs and CRs here!  must be True when *all* are scalar
+        comb += self.no_out_vec.eq((~o2_svdec.isvec) & (~o_svdec.isvec) &
+                                   (~crout_svdec.isvec))
 
         # SPRs out
         comb += e.read_spr1.eq(dec_a.spr_out)
@@ -1143,15 +1195,29 @@ class PowerDecode2(PowerDecodeSubset):
         comb += e.write_fast2.eq(dec_o2.fast_out)
 
         # condition registers (CR)
-        for to_reg, fromreg, svdec in (
-            (e.read_cr1, self.dec_cr_in.cr_bitfield, crin_svdec),
-            (e.read_cr2, self.dec_cr_in.cr_bitfield_b, crin_svdec_b),
-            (e.read_cr3, self.dec_cr_in.cr_bitfield_o, crin_svdec_o),
-            (e.write_cr, self.dec_cr_out.cr_bitfield, crout_svdec)):
+        for to_reg, cr, name, svdec in (
+            (e.read_cr1, self.dec_cr_in, "cr_bitfield", crin_svdec),
+            (e.read_cr2, self.dec_cr_in, "cr_bitfield_b", crin_svdec_b),
+            (e.read_cr3, self.dec_cr_in, "cr_bitfield_o", crin_svdec_o),
+            (e.write_cr, self.dec_cr_out, "cr_bitfield", crout_svdec)):
+            fromreg = getattr(cr, name)
             comb += svdec.extra.eq(extra)        # EXTRA field of SVP64 RM
             comb += svdec.etype.eq(op.SV_Etype)  # EXTRA2/3 for this insn
             comb += svdec.cr_in.eq(fromreg.data) # 3-bit (CR0/BC/BFA)
-            comb += to_reg.data.eq(svdec.cr_out) # 7-bit output
+            with m.If(svdec.isvec):
+                # check if this is CR0 or CR1: treated differently
+                # (does not "listen" to EXTRA2/3 spec for a start)
+                # also: the CRs start from completely different locations
+                with m.If(cr.sv_override == 1): # CR0
+                    offs = SVP64CROffs.CR0
+                    comb += to_reg.data.eq(srcstep+offs)
+                with m.Elif(cr.sv_override == 2): # CR1
+                    offs = SVP64CROffs.CR1
+                    comb += to_reg.data.eq(srcstep+1)
+                with m.Else():
+                    comb += to_reg.data.eq(srcstep+svdec.cr_out) # 7-bit output
+            with m.Else():
+                comb += to_reg.data.eq(svdec.cr_out) # 7-bit output
             comb += to_reg.ok.eq(fromreg.ok)
 
         # sigh this is exactly the sort of thing for which the
@@ -1295,6 +1361,7 @@ class SVP64PrefixDecoder(Elaboratable):
 
     def elaborate(self, platform):
         m = Module()
+        opcode_in = self.opcode_in
         comb = m.d.comb
         # sigh copied this from TopPowerDecoder
         # raw opcode in assumed to be in LE order: byte-reverse it to get BE
@@ -1304,23 +1371,21 @@ class SVP64PrefixDecoder(Elaboratable):
             l.append(raw_le[i:i+8])
         l.reverse()
         raw_be = Cat(*l)
-        comb += self.opcode_in.eq(Mux(self.bigendian, raw_be, raw_le))
+        comb += opcode_in.eq(Mux(self.bigendian, raw_be, raw_le))
 
         # start identifying if the incoming opcode is SVP64 prefix)
-        major = Signal(6, reset_less=True)
+        major = sel(m, opcode_in, SVP64P.OPC)
+        ident = sel(m, opcode_in, SVP64P.SVP64_7_9)
 
-        comb += major.eq(self.opcode_in[26:32])
-        comb += self.is_svp64_mode.eq((major == Const(1, 6)) & # EXT01
-                                      self.opcode_in[31-7] & # identifier
-                                      self.opcode_in[31-9])  # bits
+        comb += self.is_svp64_mode.eq(
+            (major == Const(1, 6)) &   # EXT01
+            (ident == Const(0b11, 2))  # identifier bits
+        )
 
-        # now grab the 24-bit ReMap context bits,
-        rmfields = [6, 8] + list(range(10,32)) # SVP64 24-bit RM
-        l = []
-        for idx in rmfields:
-            l.append(self.opcode_in[32-idx])
         with m.If(self.is_svp64_mode):
-            comb += self.svp64_rm.eq(Cat(*l))
+            # now grab the 24-bit ReMap context bits,
+            rm = sel(m, opcode_in, SVP64P.RM)
+            comb += self.svp64_rm.eq(rm)
 
         return m