adjust how register copy/setup is done in PowerDecoder2
[soc.git] / src / soc / decoder / power_decoder2.py
index 32cd73321f8c07d59578229a97be261a33b2da2a..579b56e06afad6c02402a1262f2a6e6e905fc901 100644 (file)
@@ -623,6 +623,8 @@ record_names = {'insn_type': 'internal_op',
 
 class PowerDecodeSubset(Elaboratable):
     """PowerDecodeSubset: dynamic subset decoder
+
+    only fields actually requested are copied over. hence, "subset" (duh).
     """
     def __init__(self, dec, opkls=None, fn_name=None, final=False, state=None):
 
@@ -722,10 +724,24 @@ class PowerDecodeSubset(Elaboratable):
         comb += self.do_copy("msr", msr)
         comb += self.do_copy("cia", cia)
 
-        # set up instruction, pick fn unit
+        # set up instruction type
         # 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"))
+
+        # function unit for decoded instruction: requires minor redirect
+        # for SPR set/get
+        fn = self.op_get("function_unit")
+        spr = Signal(10, reset_less=True)
+        comb += spr.eq(decode_spr_num(self.dec.SPR)) # from XFX
+
+        # for first test only forward SPRs 18 and 19 to MMU, when
+        # operation is MTSPR or MFSPR.  TODO: add other MMU SPRs
+        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))):
+            comb += self.do_copy("fn_unit", Function.MMU)
+        with m.Else():
+            comb += self.do_copy("fn_unit",fn)
 
         # immediates
         if self.needs_field("zero_a", "in1_sel"):
@@ -850,11 +866,14 @@ class PowerDecode2(PowerDecodeSubset):
             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)
-        comb += e.read_reg2.eq(dec_b.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)
+        for to_reg, fromreg in (
+            (e.read_reg1, dec_a.reg_out),
+            (e.read_reg2, dec_b.reg_out),
+            (e.read_reg3, dec_c.reg_out),
+            (e.write_reg, dec_o.reg_out),
+            (e.write_ea, dec_o2.reg_out)):
+            comb += to_reg.data.eq(fromreg.data)
+            comb += to_reg.ok.eq(fromreg.ok)
 
         # SPRs out
         comb += e.read_spr1.eq(dec_a.spr_out)