https://bugs.libre-soc.org/show_bug.cgi?id=476
[soc.git] / src / soc / fu / shift_rot / main_stage.py
index f237528397b0cea040266eaca4b21e1b66b1cad6..1a3b8eff0aadf54ade1b3d8819b5f0b0843103a7 100644 (file)
@@ -1,14 +1,18 @@
+# License: LGPLv3
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
 # This stage is intended to do most of the work of executing shift
 # instructions, as well as carry and overflow generation. This module
 # however should not gate the carry or overflow, that's up to the
 # output stage
 from nmigen import (Module, Signal, Cat, Repl, Mux, Const)
 from nmutil.pipemodbase import PipeModBase
-from soc.alu.pipe_data import ALUOutputData
-from soc.shift_rot.pipe_data import ShiftRotInputData
+from soc.fu.shift_rot.pipe_data import (ShiftRotOutputData,
+                                       ShiftRotInputData)
 from ieee754.part.partsig import PartitionedSignal
-from soc.decoder.power_enums import InternalOp
-from soc.shift_rot.rotator import Rotator
+from soc.decoder.power_enums import MicrOp
+from soc.fu.shift_rot.rotator import Rotator
 
 from soc.decoder.power_fields import DecodeFields
 from soc.decoder.power_fieldsn import SignalBitRange
@@ -24,11 +28,17 @@ class ShiftRotMainStage(PipeModBase):
         return ShiftRotInputData(self.pspec)
 
     def ospec(self):
-        return ALUOutputData(self.pspec) # TODO: ALUIntermediateData
+        return ShiftRotOutputData(self.pspec)
 
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
+        op = self.i.ctx.op
+        o = self.o.o
+
+        # NOTE: the sh field immediate is read in by PowerDecode2
+        # (actually DecodeRB), whereupon by way of rb "immediate" mode
+        # it ends up in self.i.rb.
 
         # obtain me and mb fields from instruction.
         m_fields = self.fields.instrs['M']
@@ -47,32 +57,38 @@ class ShiftRotMainStage(PipeModBase):
             rotator.mb.eq(mb),
             rotator.mb_extra.eq(mb_extra),
             rotator.rs.eq(self.i.rs),
-            rotator.ra.eq(self.i.ra),
-            rotator.shift.eq(self.i.rb),
-            rotator.is_32bit.eq(self.i.ctx.op.is_32bit),
-            rotator.arith.eq(self.i.ctx.op.is_signed),
+            rotator.ra.eq(self.i.a),
+            rotator.shift.eq(self.i.rb), # can also be sh (in immediate mode)
+            rotator.is_32bit.eq(op.is_32bit),
+            rotator.arith.eq(op.is_signed),
         ]
 
+        comb += o.ok.eq(1) # defaults to enabled
+
         # instruction rotate type
-        mode = Signal(3, reset_less=True)
-        with m.Switch(self.i.ctx.op.insn_type):
-            with m.Case(InternalOp.OP_SHL):  comb += mode.eq(0b000)
-            with m.Case(InternalOp.OP_SHR):  comb += mode.eq(0b001) # R-shift
-            with m.Case(InternalOp.OP_RLC):  comb += mode.eq(0b110) # clear LR
-            with m.Case(InternalOp.OP_RLCL): comb += mode.eq(0b010) # clear L
-            with m.Case(InternalOp.OP_RLCR): comb += mode.eq(0b100) # clear R
+        mode = Signal(4, reset_less=True)
+        with m.Switch(op.insn_type):
+            with m.Case(MicrOp.OP_SHL):  comb += mode.eq(0b0000) # L-shift
+            with m.Case(MicrOp.OP_SHR):  comb += mode.eq(0b0001) # R-shift
+            with m.Case(MicrOp.OP_RLC):  comb += mode.eq(0b0110) # clear LR
+            with m.Case(MicrOp.OP_RLCL): comb += mode.eq(0b0010) # clear L
+            with m.Case(MicrOp.OP_RLCR): comb += mode.eq(0b0100) # clear R
+            with m.Case(MicrOp.OP_EXTSWSLI): comb += mode.eq(0b1000) # L-ext
+            with m.Default():
+                comb += o.ok.eq(0) # otherwise disable
 
         comb += Cat(rotator.right_shift,
                     rotator.clear_left,
-                    rotator.clear_right).eq(mode)
-                
+                    rotator.clear_right,
+                    rotator.sign_ext_rs).eq(mode)
+
         # outputs from the microwatt rotator module
-        comb += [self.o.o.eq(rotator.result_o),
-                 self.o.carry_out.eq(rotator.carry_out_o)]
+        comb += [o.data.eq(rotator.result_o),
+                 self.o.xer_ca.data.eq(Repl(rotator.carry_out_o, 2))]
 
         ###### sticky overflow and context, both pass-through #####
 
-        comb += self.o.so.eq(self.i.so)
+        comb += self.o.xer_so.data.eq(self.i.xer_so)
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m