bit of a big reorg of data structures
[soc.git] / src / soc / decoder / power_decoder2.py
index 0f2a48601d2c02f42fdca87be406745180168fc0..c222170774461a2a08519b9160cd61b394639ef0 100644 (file)
@@ -8,6 +8,7 @@ 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 nmigen import Module, Elaboratable, Signal, Mux, Const, Cat, Repl, Record
 from nmigen.cli import rtlil
+from soc.regfile.regfiles import XERRegs
 
 from nmutil.picker import PriorityPicker
 from nmutil.iocontrol import RecordObject
 
 from nmutil.picker import PriorityPicker
 from nmutil.iocontrol import RecordObject
@@ -26,6 +27,7 @@ from soc.consts import MSR
 from soc.regfile.regfiles import FastRegs
 from soc.consts import TT
 from soc.config.state import CoreState
 from soc.regfile.regfiles import FastRegs
 from soc.consts import TT
 from soc.config.state import CoreState
+from soc.regfile.util import spr_to_fast
 
 
 def decode_spr_num(spr):
 
 
 def decode_spr_num(spr):
@@ -50,27 +52,32 @@ def instr_is_priv(m, op, insn):
 
 
 class SPRMap(Elaboratable):
 
 
 class SPRMap(Elaboratable):
-    """SPRMap: maps POWER9 SPR numbers to internal enum values
+    """SPRMap: maps POWER9 SPR numbers to internal enum values, fast and slow
     """
 
     def __init__(self):
         self.spr_i = Signal(10, reset_less=True)
     """
 
     def __init__(self):
         self.spr_i = Signal(10, reset_less=True)
-        self.spr_o = Signal(SPR, reset_less=True)
+        self.spr_o = Data(SPR, name="spr_o")
+        self.fast_o = Data(3, name="fast_o")
 
     def elaborate(self, platform):
         m = Module()
         with m.Switch(self.spr_i):
             for i, x in enumerate(SPR):
                 with m.Case(x.value):
 
     def elaborate(self, platform):
         m = Module()
         with m.Switch(self.spr_i):
             for i, x in enumerate(SPR):
                 with m.Case(x.value):
-                    m.d.comb += self.spr_o.eq(i)
+                    m.d.comb += self.spr_o.data.eq(i)
+                    m.d.comb += self.spr_o.ok.eq(1)
+            for x, v in spr_to_fast.items():
+                with m.Case(x.value):
+                    m.d.comb += self.fast_o.data.eq(v)
+                    m.d.comb += self.fast_o.ok.eq(1)
         return m
 
 
 class DecodeA(Elaboratable):
     """DecodeA from instruction
 
         return m
 
 
 class DecodeA(Elaboratable):
     """DecodeA from instruction
 
-    decodes register RA, whether immediate-zero, implicit and
-    explicit CSRs
+    decodes register RA, implicit and explicit CSRs
     """
 
     def __init__(self, dec):
     """
 
     def __init__(self, dec):
@@ -78,7 +85,6 @@ class DecodeA(Elaboratable):
         self.sel_in = Signal(In1Sel, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(5, name="reg_a")
         self.sel_in = Signal(In1Sel, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(5, name="reg_a")
-        self.immz_out = Signal(reset_less=True)
         self.spr_out = Data(SPR, "spr_a")
         self.fast_out = Data(3, "fast_a")
 
         self.spr_out = Data(SPR, "spr_a")
         self.fast_out = Data(3, "fast_a")
 
@@ -96,11 +102,6 @@ class DecodeA(Elaboratable):
             comb += self.reg_out.data.eq(ra)
             comb += self.reg_out.ok.eq(1)
 
             comb += self.reg_out.data.eq(ra)
             comb += self.reg_out.ok.eq(1)
 
-        # zero immediate requested
-        with m.If((self.sel_in == In1Sel.RA_OR_ZERO) &
-                  (self.reg_out.data == Const(0, 5))):
-            comb += self.immz_out.eq(1)
-
         # some Logic/ALU ops have RS as the 3rd arg, but no "RA".
         with m.If(self.sel_in == In1Sel.RS):
             comb += self.reg_out.data.eq(self.dec.RS)
         # some Logic/ALU ops have RS as the 3rd arg, but no "RA".
         with m.If(self.sel_in == In1Sel.RS):
             comb += self.reg_out.data.eq(self.dec.RS)
@@ -128,31 +129,34 @@ class DecodeA(Elaboratable):
             with m.Case(MicrOp.OP_MFSPR):
                 spr = Signal(10, reset_less=True)
                 comb += spr.eq(decode_spr_num(self.dec.SPR))  # from XFX
             with m.Case(MicrOp.OP_MFSPR):
                 spr = Signal(10, reset_less=True)
                 comb += spr.eq(decode_spr_num(self.dec.SPR))  # from XFX
-                with m.Switch(spr):
-                    # fast SPRs
-                    with m.Case(SPR.CTR.value):
-                        comb += self.fast_out.data.eq(FastRegs.CTR)
-                        comb += self.fast_out.ok.eq(1)
-                    with m.Case(SPR.LR.value):
-                        comb += self.fast_out.data.eq(FastRegs.LR)
-                        comb += self.fast_out.ok.eq(1)
-                    with m.Case(SPR.TAR.value):
-                        comb += self.fast_out.data.eq(FastRegs.TAR)
-                        comb += self.fast_out.ok.eq(1)
-                    with m.Case(SPR.SRR0.value):
-                        comb += self.fast_out.data.eq(FastRegs.SRR0)
-                        comb += self.fast_out.ok.eq(1)
-                    with m.Case(SPR.SRR1.value):
-                        comb += self.fast_out.data.eq(FastRegs.SRR1)
-                        comb += self.fast_out.ok.eq(1)
-                    with m.Case(SPR.XER.value):
-                        pass  # do nothing
-                    # : map to internal SPR numbers
-                    # XXX TODO: dec and tb not to go through mapping.
-                    with m.Default():
-                        comb += sprmap.spr_i.eq(spr)
-                        comb += self.spr_out.data.eq(sprmap.spr_o)
-                        comb += self.spr_out.ok.eq(1)
+                comb += sprmap.spr_i.eq(spr)
+                comb += self.spr_out.eq(sprmap.spr_o)
+                comb += self.fast_out.eq(sprmap.fast_o)
+
+        return m
+
+
+class DecodeAImm(Elaboratable):
+    """DecodeA immediate from instruction
+
+    decodes register RA, whether immediate-zero, implicit and
+    explicit CSRs
+    """
+
+    def __init__(self, dec):
+        self.dec = dec
+        self.sel_in = Signal(In1Sel, reset_less=True)
+        self.immz_out = Signal(reset_less=True)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+
+        # zero immediate requested
+        ra = Signal(5, reset_less=True)
+        comb += ra.eq(self.dec.RA)
+        with m.If((self.sel_in == In1Sel.RA_OR_ZERO) & (ra == Const(0, 5))):
+            comb += self.immz_out.eq(1)
 
         return m
 
 
         return m
 
@@ -171,7 +175,6 @@ class DecodeB(Elaboratable):
         self.sel_in = Signal(In2Sel, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(5, "reg_b")
         self.sel_in = Signal(In2Sel, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(5, "reg_b")
-        self.imm_out = Data(64, "imm_b")
         self.fast_out = Data(3, "fast_b")
 
     def elaborate(self, platform):
         self.fast_out = Data(3, "fast_b")
 
     def elaborate(self, platform):
@@ -187,6 +190,38 @@ class DecodeB(Elaboratable):
                 # for M-Form shiftrot
                 comb += self.reg_out.data.eq(self.dec.RS)
                 comb += self.reg_out.ok.eq(1)
                 # for M-Form shiftrot
                 comb += self.reg_out.data.eq(self.dec.RS)
                 comb += self.reg_out.ok.eq(1)
+
+        # decode SPR2 based on instruction type
+        op = self.dec.op
+        # BCREG implicitly uses LR or TAR for 2nd reg
+        # CTR however is already in fast_spr1 *not* 2.
+        with m.If(op.internal_op == MicrOp.OP_BCREG):
+            xo9 = self.dec.FormXL.XO[9]  # 3.0B p38 top bit of XO
+            xo5 = self.dec.FormXL.XO[5]  # 3.0B p38
+            with m.If(~xo9):
+                comb += self.fast_out.data.eq(FastRegs.LR)
+                comb += self.fast_out.ok.eq(1)
+            with m.Elif(xo5):
+                comb += self.fast_out.data.eq(FastRegs.TAR)
+                comb += self.fast_out.ok.eq(1)
+
+        return m
+
+
+class DecodeBImm(Elaboratable):
+    """DecodeB immediate from instruction
+    """
+    def __init__(self, dec):
+        self.dec = dec
+        self.sel_in = Signal(In2Sel, reset_less=True)
+        self.imm_out = Data(64, "imm_b")
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+
+        # select Register B Immediate
+        with m.Switch(self.sel_in):
             with m.Case(In2Sel.CONST_UI): # unsigned
                 comb += self.imm_out.data.eq(self.dec.UI)
                 comb += self.imm_out.ok.eq(1)
             with m.Case(In2Sel.CONST_UI): # unsigned
                 comb += self.imm_out.data.eq(self.dec.UI)
                 comb += self.imm_out.ok.eq(1)
@@ -230,20 +265,6 @@ class DecodeB(Elaboratable):
                 comb += self.imm_out.data.eq(self.dec.SH32)
                 comb += self.imm_out.ok.eq(1)
 
                 comb += self.imm_out.data.eq(self.dec.SH32)
                 comb += self.imm_out.ok.eq(1)
 
-        # decode SPR2 based on instruction type
-        op = self.dec.op
-        # BCREG implicitly uses LR or TAR for 2nd reg
-        # CTR however is already in fast_spr1 *not* 2.
-        with m.If(op.internal_op == MicrOp.OP_BCREG):
-            xo9 = self.dec.FormXL.XO[9]  # 3.0B p38 top bit of XO
-            xo5 = self.dec.FormXL.XO[5]  # 3.0B p38
-            with m.If(~xo9):
-                comb += self.fast_out.data.eq(FastRegs.LR)
-                comb += self.fast_out.ok.eq(1)
-            with m.Elif(xo5):
-                comb += self.fast_out.data.eq(FastRegs.TAR)
-                comb += self.fast_out.ok.eq(1)
-
         return m
 
 
         return m
 
 
@@ -307,33 +328,11 @@ class DecodeOut(Elaboratable):
             with m.Case(OutSel.SPR):
                 spr = Signal(10, reset_less=True)
                 comb += spr.eq(decode_spr_num(self.dec.SPR))  # from XFX
             with m.Case(OutSel.SPR):
                 spr = Signal(10, reset_less=True)
                 comb += spr.eq(decode_spr_num(self.dec.SPR))  # from XFX
-                # TODO MTSPR 1st spr (fast)
+                # MFSPR move to SPRs - needs mapping
                 with m.If(op.internal_op == MicrOp.OP_MTSPR):
                 with m.If(op.internal_op == MicrOp.OP_MTSPR):
-                    with m.Switch(spr):
-                        # fast SPRs
-                        with m.Case(SPR.CTR.value):
-                            comb += self.fast_out.data.eq(FastRegs.CTR)
-                            comb += self.fast_out.ok.eq(1)
-                        with m.Case(SPR.LR.value):
-                            comb += self.fast_out.data.eq(FastRegs.LR)
-                            comb += self.fast_out.ok.eq(1)
-                        with m.Case(SPR.TAR.value):
-                            comb += self.fast_out.data.eq(FastRegs.TAR)
-                            comb += self.fast_out.ok.eq(1)
-                        with m.Case(SPR.SRR0.value):
-                            comb += self.fast_out.data.eq(FastRegs.SRR0)
-                            comb += self.fast_out.ok.eq(1)
-                        with m.Case(SPR.SRR1.value):
-                            comb += self.fast_out.data.eq(FastRegs.SRR1)
-                            comb += self.fast_out.ok.eq(1)
-                        with m.Case(SPR.XER.value):
-                            pass  # do nothing
-                        # : map to internal SPR numbers
-                        # XXX TODO: dec and tb not to go through mapping.
-                        with m.Default():
-                            comb += sprmap.spr_i.eq(spr)
-                            comb += self.spr_out.data.eq(sprmap.spr_o)
-                            comb += self.spr_out.ok.eq(1)
+                    comb += sprmap.spr_i.eq(spr)
+                    comb += self.spr_out.eq(sprmap.spr_o)
+                    comb += self.fast_out.eq(sprmap.fast_o)
 
         with m.Switch(op.internal_op):
 
 
         with m.Switch(op.internal_op):
 
@@ -454,8 +453,10 @@ class DecodeOE(Elaboratable):
             # also rotate
             # XXX ARGH! ignoring OE causes incompatibility with microwatt
             # http://lists.libre-soc.org/pipermail/libre-soc-dev/2020-August/000302.html
             # 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,
+            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_SHL, MicrOp.OP_SHR, MicrOp.OP_RLC,
+                        MicrOp.OP_LOAD, MicrOp.OP_STORE,
                         MicrOp.OP_RLCL, MicrOp.OP_RLCR,
                         MicrOp.OP_EXTSWSLI):
                 pass
                         MicrOp.OP_RLCL, MicrOp.OP_RLCR,
                         MicrOp.OP_EXTSWSLI):
                 pass
@@ -489,7 +490,8 @@ class DecodeCRIn(Elaboratable):
 
     def elaborate(self, platform):
         m = Module()
 
     def elaborate(self, platform):
         m = Module()
-        m.submodules.ppick = ppick = PriorityPicker(8)#reverse_i=True)
+        m.submodules.ppick = ppick = PriorityPicker(8, reverse_i=True,
+                                                       reverse_o=True)
 
         comb = m.d.comb
         op = self.dec.op
 
         comb = m.d.comb
         op = self.dec.op
@@ -501,7 +503,7 @@ class DecodeCRIn(Elaboratable):
             with m.Case(CRInSel.NONE):
                 pass  # No bitfield activated
             with m.Case(CRInSel.CR0):
             with m.Case(CRInSel.NONE):
                 pass  # No bitfield activated
             with m.Case(CRInSel.CR0):
-                comb += self.cr_bitfield.data.eq(0)
+                comb += self.cr_bitfield.data.eq(0) # CR0 (MSB0 numbering)
                 comb += self.cr_bitfield.ok.eq(1)
             with m.Case(CRInSel.BI):
                 comb += self.cr_bitfield.data.eq(self.dec.BI[2:5])
                 comb += self.cr_bitfield.ok.eq(1)
             with m.Case(CRInSel.BI):
                 comb += self.cr_bitfield.data.eq(self.dec.BI[2:5])
@@ -553,7 +555,8 @@ class DecodeCROut(Elaboratable):
         m = Module()
         comb = m.d.comb
         op = self.dec.op
         m = Module()
         comb = m.d.comb
         op = self.dec.op
-        m.submodules.ppick = ppick = PriorityPicker(8)
+        m.submodules.ppick = ppick = PriorityPicker(8, reverse_i=True,
+                                                       reverse_o=True)
 
         comb += self.cr_bitfield.ok.eq(0)
         comb += self.whole_reg.ok.eq(0)
 
         comb += self.cr_bitfield.ok.eq(0)
         comb += self.whole_reg.ok.eq(0)
@@ -561,7 +564,7 @@ class DecodeCROut(Elaboratable):
             with m.Case(CROutSel.NONE):
                 pass  # No bitfield activated
             with m.Case(CROutSel.CR0):
             with m.Case(CROutSel.NONE):
                 pass  # No bitfield activated
             with m.Case(CROutSel.CR0):
-                comb += self.cr_bitfield.data.eq(0)
+                comb += self.cr_bitfield.data.eq(0) # CR0 (MSB0 numbering)
                 comb += self.cr_bitfield.ok.eq(self.rc_in)  # only when RC=1
             with m.Case(CROutSel.BF):
                 comb += self.cr_bitfield.data.eq(self.dec.FormX.BF)
                 comb += self.cr_bitfield.ok.eq(self.rc_in)  # only when RC=1
             with m.Case(CROutSel.BF):
                 comb += self.cr_bitfield.data.eq(self.dec.FormX.BF)
@@ -577,7 +580,10 @@ class DecodeCROut(Elaboratable):
                     with m.If(move_one):
                         # must one-hot the FXM field
                         comb += ppick.i.eq(self.dec.FXM)
                     with m.If(move_one):
                         # must one-hot the FXM field
                         comb += ppick.i.eq(self.dec.FXM)
-                        comb += self.whole_reg.data.eq(ppick.o)
+                        with m.If(ppick.en_o):
+                            comb += self.whole_reg.data.eq(ppick.o)
+                        with m.Else():
+                            comb += self.whole_reg.data.eq(0b00000001) # CR7
                     with m.Else():
                         comb += self.whole_reg.data.eq(self.dec.FXM)
                 with m.Else():
                     with m.Else():
                         comb += self.whole_reg.data.eq(self.dec.FXM)
                 with m.Else():
@@ -587,7 +593,132 @@ class DecodeCROut(Elaboratable):
         return m
 
 
         return m
 
 
-class PowerDecode2(Elaboratable):
+class PowerDecodeSubset(Elaboratable):
+    """PowerDecodeSubset: dynamic subset decoder
+
+    """
+
+    def __init__(self, dec, opkls=None, fn_name=None, col_subset=None):
+
+        if dec is None:
+            self.opkls = opkls
+            self.fn_name = fn_name
+            self.dec = create_pdecode(name=fn_name, col_subset=col_subset,
+                                      row_subset=self.rowsubsetfn)
+        else:
+            self.dec = dec
+            self.opkls = None
+            self.fn_name = None
+        self.e = Decode2ToExecute1Type(name=self.fn_name, opkls=self.opkls)
+
+        # state information needed by the Decoder (TODO: this as a Record)
+        self.state = CoreState("dec2")
+
+    def rowsubsetfn(self, opcode, row):
+        return row['unit'] == self.fn_name
+
+    def ports(self):
+        return self.dec.ports() + self.e.ports()
+
+    def needs_field(self, field, op_field):
+        do = self.e_tmp.do
+        return hasattr(do, field) and self.op_get(op_field)
+
+    def do_copy(self, field, val, final=False):
+        if final:
+            do = self.e.do
+        else:
+            do = self.e_tmp.do
+        if hasattr(do, field) and val is not None:
+            return getattr(do, field).eq(val)
+        return []
+
+    def op_get(self, op_field):
+        return getattr(self.dec.op, op_field, None)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+        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
+
+        # fill in for a normal instruction (not an exception)
+        # copy over if non-exception, non-privileged etc. is detected
+        self.e_tmp = e = Decode2ToExecute1Type(name=self.fn_name,
+                                               opkls=self.opkls)
+        do = e.do
+
+        # set up submodule decoders
+        m.submodules.dec = self.dec
+        m.submodules.dec_ai = dec_ai = DecodeAImm(self.dec)
+        m.submodules.dec_bi = dec_bi = DecodeBImm(self.dec)
+        m.submodules.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]:
+            comb += i.eq(self.dec.opcode_in)
+
+        # ...and subdecoders' input fields
+        comb += dec_ai.sel_in.eq(op.in1_sel)
+        comb += dec_bi.sel_in.eq(op.in2_sel)
+        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)
+        comb += self.do_copy("cia", cia)
+
+        # set up instruction, pick fn unit
+        # no op: defaults to OP_ILLEGAL
+        comb += self.do_copy("insn_type", self.op_get("internal_op"))
+        comb += self.do_copy("fn_unit", self.op_get("function_unit"))
+
+        # immediates
+        comb += self.do_copy("imm_data", dec_bi.imm_out) # imm in RB
+        comb += self.do_copy("zero_a", dec_ai.immz_out)  # RA==0 detected
+
+        # rc and oe out
+        comb += self.do_copy("rc", dec_rc.rc_out)
+        comb += self.do_copy("oe", dec_oe.oe_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)
+
+        # decoded/selected instruction flags
+        comb += self.do_copy("data_len", self.op_get("ldst_len"))
+        comb += self.do_copy("invert_in", self.op_get("inv_a"))
+        comb += self.do_copy("invert_out", self.op_get("inv_out"))
+        comb += self.do_copy("input_carry", self.op_get("cry_in"))
+        comb += self.do_copy("output_carry", self.op_get("cry_out"))
+        comb += self.do_copy("is_32bit", self.op_get("is_32b"))
+        comb += self.do_copy("is_signed", self.op_get("sgn"))
+        lk = self.op_get("lk")
+        if lk is not None:
+            with m.If(lk):
+                comb += self.do_copy("lk", self.dec.LK)  # XXX TODO: accessor
+
+        comb += self.do_copy("byte_reverse", self.op_get("br"))
+        comb += self.do_copy("sign_extend", self.op_get("sgn_ext"))
+        comb += self.do_copy("ldst_mode", self.op_get("upd"))  # LD/ST mode
+
+        # These should be removed eventually
+        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
+
+        return m
+
+
+class PowerDecode2(PowerDecodeSubset):
     """PowerDecode2: the main instruction decoder.
 
     whilst PowerDecode is responsible for decoding the actual opcode, this
     """PowerDecode2: the main instruction decoder.
 
     whilst PowerDecode is responsible for decoding the actual opcode, this
@@ -607,44 +738,28 @@ class PowerDecode2(Elaboratable):
     a suitable alternative (trap).
     """
 
     a suitable alternative (trap).
     """
 
-    def __init__(self, dec):
-
-        self.dec = dec
-        self.e = Decode2ToExecute1Type()
-
-        # state information needed by the Decoder (TODO: this as a Record)
-        self.state = CoreState("dec2")
-
-    def ports(self):
-        return self.dec.ports() + self.e.ports()
-
     def elaborate(self, platform):
     def elaborate(self, platform):
-        m = Module()
+        m = super().elaborate(platform)
         comb = m.d.comb
         comb = m.d.comb
+        state = self.state
         e_out, op, do_out = self.e, self.dec.op, self.e.do
         e_out, op, do_out = self.e, self.dec.op, self.e.do
-        msr, cia = self.state.msr, self.state.pc
+        dec_spr, msr, cia, ext_irq = state.dec, state.msr, state.pc, state.eint
+        e = self.e_tmp
+        do = e.do
 
         # fill in for a normal instruction (not an exception)
         # copy over if non-exception, non-privileged etc. is detected
 
         # fill in for a normal instruction (not an exception)
         # copy over if non-exception, non-privileged etc. is detected
-        e = Decode2ToExecute1Type()
-        do = e.do
 
         # set up submodule decoders
 
         # set up submodule decoders
-        m.submodules.dec = self.dec
         m.submodules.dec_a = dec_a = DecodeA(self.dec)
         m.submodules.dec_b = dec_b = DecodeB(self.dec)
         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_a = dec_a = DecodeA(self.dec)
         m.submodules.dec_b = dec_b = DecodeB(self.dec)
         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_rc = dec_rc = DecodeRC(self.dec)
-        m.submodules.dec_oe = dec_oe = DecodeOE(self.dec)
-        m.submodules.dec_cr_in = dec_cr_in = DecodeCRIn(self.dec)
-        m.submodules.dec_cr_out = dec_cr_out = DecodeCROut(self.dec)
 
         # copy instruction through...
         for i in [do.insn, dec_a.insn_in, dec_b.insn_in,
 
         # copy instruction through...
         for i in [do.insn, dec_a.insn_in, dec_b.insn_in,
-                  dec_c.insn_in, dec_o.insn_in, dec_o2.insn_in, dec_rc.insn_in,
-                  dec_oe.insn_in, dec_cr_in.insn_in, dec_cr_out.insn_in]:
+                  dec_c.insn_in, dec_o.insn_in, dec_o2.insn_in]:
             comb += i.eq(self.dec.opcode_in)
 
         # ...and subdecoders' input fields
             comb += i.eq(self.dec.opcode_in)
 
         # ...and subdecoders' input fields
@@ -653,21 +768,8 @@ class PowerDecode2(Elaboratable):
         comb += dec_c.sel_in.eq(op.in3_sel)
         comb += dec_o.sel_in.eq(op.out_sel)
         comb += dec_o2.sel_in.eq(op.out_sel)
         comb += dec_c.sel_in.eq(op.in3_sel)
         comb += dec_o.sel_in.eq(op.out_sel)
         comb += dec_o2.sel_in.eq(op.out_sel)
-        comb += dec_o2.lk.eq(do.lk)
-        comb += dec_rc.sel_in.eq(op.rc_sel)
-        comb += dec_oe.sel_in.eq(op.rc_sel)  # XXX should be OE sel
-        comb += dec_cr_in.sel_in.eq(op.cr_in)
-        comb += dec_cr_out.sel_in.eq(op.cr_out)
-        comb += dec_cr_out.rc_in.eq(dec_rc.rc_out.data)
-
-        # copy "state" over
-        comb += do.msr.eq(msr)
-        comb += do.cia.eq(cia)
-
-        # set up instruction, pick fn unit
-        # no op: defaults to OP_ILLEGAL
-        comb += do.insn_type.eq(op.internal_op)
-        comb += do.fn_unit.eq(op.function_unit)
+        if hasattr(do, "lk"):
+            comb += dec_o2.lk.eq(do.lk)
 
         # registers a, b, c and out and out2 (LD/ST EA)
         comb += e.read_reg1.eq(dec_a.reg_out)
 
         # registers a, b, c and out and out2 (LD/ST EA)
         comb += e.read_reg1.eq(dec_a.reg_out)
@@ -675,12 +777,6 @@ class PowerDecode2(Elaboratable):
         comb += e.read_reg3.eq(dec_c.reg_out)
         comb += e.write_reg.eq(dec_o.reg_out)
         comb += e.write_ea.eq(dec_o2.reg_out)
         comb += e.read_reg3.eq(dec_c.reg_out)
         comb += e.write_reg.eq(dec_o.reg_out)
         comb += e.write_ea.eq(dec_o2.reg_out)
-        comb += do.imm_data.eq(dec_b.imm_out)  # immediate in RB (usually)
-        comb += do.zero_a.eq(dec_a.immz_out)  # RA==0 detected
-
-        # rc and oe out
-        comb += do.rc.eq(dec_rc.rc_out)
-        comb += do.oe.eq(dec_oe.oe_out)
 
         # SPRs out
         comb += e.read_spr1.eq(dec_a.spr_out)
 
         # SPRs out
         comb += e.read_spr1.eq(dec_a.spr_out)
@@ -693,39 +789,18 @@ class PowerDecode2(Elaboratable):
         comb += e.write_fast2.eq(dec_o2.fast_out)
 
         # condition registers (CR)
         comb += e.write_fast2.eq(dec_o2.fast_out)
 
         # condition registers (CR)
-        comb += e.read_cr1.eq(dec_cr_in.cr_bitfield)
-        comb += e.read_cr2.eq(dec_cr_in.cr_bitfield_b)
-        comb += e.read_cr3.eq(dec_cr_in.cr_bitfield_o)
-        comb += e.write_cr.eq(dec_cr_out.cr_bitfield)
-
-        comb += do.read_cr_whole.eq(dec_cr_in.whole_reg)
-        comb += do.write_cr_whole.eq(dec_cr_out.whole_reg)
-        comb += do.write_cr0.eq(dec_cr_out.cr_bitfield.ok)
-
-        # decoded/selected instruction flags
-        comb += do.data_len.eq(op.ldst_len)
-        comb += do.invert_in.eq(op.inv_a)
-        comb += do.invert_out.eq(op.inv_out)
-        comb += do.input_carry.eq(op.cry_in)   # carry comes in
-        comb += do.output_carry.eq(op.cry_out)  # carry goes out
-        comb += do.is_32bit.eq(op.is_32b)
-        comb += do.is_signed.eq(op.sgn)
-        with m.If(op.lk):
-            comb += do.lk.eq(self.dec.LK)  # XXX TODO: accessor
-
-        comb += do.byte_reverse.eq(op.br)
-        comb += do.sign_extend.eq(op.sgn_ext)
-        comb += do.ldst_mode.eq(op.upd)  # LD/ST mode (update, cache-inhibit)
-
-        # These should be removed eventually
-        comb += do.input_cr.eq(op.cr_in)   # condition reg comes in
-        comb += do.output_cr.eq(op.cr_out)  # condition reg goes in
+        comb += e.read_cr1.eq(self.dec_cr_in.cr_bitfield)
+        comb += e.read_cr2.eq(self.dec_cr_in.cr_bitfield_b)
+        comb += e.read_cr3.eq(self.dec_cr_in.cr_bitfield_o)
+        comb += e.write_cr.eq(self.dec_cr_out.cr_bitfield)
 
         # sigh this is exactly the sort of thing for which the
         # decoder is designed to not need.  MTSPR, MFSPR and others need
         # access to the XER bits.  however setting e.oe is not appropriate
         with m.If(op.internal_op == MicrOp.OP_MFSPR):
 
         # sigh this is exactly the sort of thing for which the
         # decoder is designed to not need.  MTSPR, MFSPR and others need
         # access to the XER bits.  however setting e.oe is not appropriate
         with m.If(op.internal_op == MicrOp.OP_MFSPR):
-            comb += e.xer_in.eq(1)
+            comb += e.xer_in.eq(0b111) # SO, CA, OV
+        with m.If(op.internal_op == MicrOp.OP_CMP):
+            comb += e.xer_in.eq(1<<XERRegs.SO) # SO
         with m.If(op.internal_op == MicrOp.OP_MTSPR):
             comb += e.xer_out.eq(1)
 
         with m.If(op.internal_op == MicrOp.OP_MTSPR):
             comb += e.xer_out.eq(1)
 
@@ -733,11 +808,21 @@ class PowerDecode2(Elaboratable):
         with m.If(op.internal_op == MicrOp.OP_TRAP):
             # *DO NOT* call self.trap here.  that would reset absolutely
             # rverything including destroying read of RA and RB.
         with m.If(op.internal_op == MicrOp.OP_TRAP):
             # *DO NOT* call self.trap here.  that would reset absolutely
             # rverything including destroying read of RA and RB.
-            comb += do.trapaddr.eq(0x70)    # addr=0x700 (strip first nibble)
+            comb += self.do_copy("trapaddr", 0x70, True) # strip first nibble
+
+        # check if instruction is privileged
+        is_priv_insn = instr_is_priv(m, op.internal_op, e.do.insn)
+
+        # external interrupt? only if MSR.EE set
+        with m.If(ext_irq & msr[MSR.EE]): # v3.0B p944 (MSR.EE)
+            self.trap(m, TT.EINT, 0x500)
+
+        # decrement counter (v3.0B p1099): TODO 32-bit version (MSR.LPCR)
+        with m.If(dec_spr[63] & msr[MSR.EE]): # v3.0B 6.5.11 p1076
+            self.trap(m, TT.DEC, 0x900)   # v3.0B 6.5 p1065
 
 
-        # TODO: get msr, then can do privileged instruction
-        with m.If(instr_is_priv(m, op.internal_op, e.do.insn) & msr[MSR.PR]):
-            # privileged instruction trap
+        # privileged instruction trap
+        with m.Elif(is_priv_insn & msr[MSR.PR]):
             self.trap(m, TT.PRIV, 0x700)
 
         # illegal instruction must redirect to trap. this is done by
             self.trap(m, TT.PRIV, 0x700)
 
         # illegal instruction must redirect to trap. this is done by
@@ -778,17 +863,17 @@ class PowerDecode2(Elaboratable):
         """trap: this basically "rewrites" the decoded instruction as a trap
         """
         comb = m.d.comb
         """trap: this basically "rewrites" the decoded instruction as a trap
         """
         comb = m.d.comb
-        op, do, e = self.dec.op, self.e.do, self.e
+        op, e = self.dec.op, self.e
         comb += e.eq(0)  # reset eeeeeverything
 
         # start again
         comb += e.eq(0)  # reset eeeeeverything
 
         # start again
-        comb += do.insn.eq(self.dec.opcode_in)
-        comb += do.insn_type.eq(MicrOp.OP_TRAP)
-        comb += do.fn_unit.eq(Function.TRAP)
-        comb += do.trapaddr.eq(trapaddr >> 4)  # cut bottom 4 bits
-        comb += do.traptype.eq(traptype)  # request type
-        comb += do.msr.eq(self.state.msr)  # copy of MSR "state"
-        comb += do.cia.eq(self.state.pc)  # copy of PC "state"
+        comb += self.do_copy("insn", self.dec.opcode_in, True)
+        comb += self.do_copy("insn_type", MicrOp.OP_TRAP, True)
+        comb += self.do_copy("fn_unit", Function.TRAP, True)
+        comb += self.do_copy("trapaddr", trapaddr >> 4, True) # bottom 4 bits
+        comb += self.do_copy("traptype", traptype, True)  # request type
+        comb += self.do_copy("msr", self.state.msr, True) # copy of MSR "state"
+        comb += self.do_copy("cia", self.state.pc, True)  # copy of PC "state"
 
 
 def get_rdflags(e, cu):
 
 
 def get_rdflags(e, cu):