convert branch pipeline to use msr/cia as immediates
[soc.git] / src / soc / fu / branch / main_stage.py
index 9d7c2a543d8eeb85480679bef826fd4f3c1f3397..39631afdca281c1b280765281cbae5cb000b35b3 100644 (file)
@@ -3,6 +3,21 @@
 This stage is intended to do most of the work of executing branch
 instructions. This is OP_B, OP_B, OP_BCREG
 
+Note: it is PARTICULARLY important to pay attention to PowerDecode2
+more specifically DecodeRA etc. as these work closely in conjunction
+with the Branch pipeline, here.
+
+The Branch pipeline itself does not and cannot read registers: it can
+only process data and produce results.  Therefore, something else needs
+to know that BC needs CTR, and that one of the outputs from here is to
+go into LR, and so on.  Encoding of which registers are read and written
+is the responsibility of PowerDecode2 and because some of those decisions
+are conditional (based on BO2 for example) PowerDecode2 has to duplicate
+some of that bitlevel operand field decoding.
+
+It us therefore quite critical to read this code in conjunction side by
+side with power_decode2.py
+
 Links:
 * https://bugs.libre-soc.org/show_bug.cgi?id=313
 * https://bugs.libre-soc.org/show_bug.cgi?id=335
@@ -13,7 +28,7 @@ from nmigen import (Module, Signal, Cat, Mux, Const, Array)
 from nmutil.pipemodbase import PipeModBase
 from nmutil.extend import exts
 from soc.fu.branch.pipe_data import BranchInputData, BranchOutputData
-from soc.decoder.power_enums import InternalOp
+from soc.decoder.power_enums import MicrOp
 
 from soc.decoder.power_fields import DecodeFields
 from soc.decoder.power_fieldsn import SignalBitRange
@@ -57,7 +72,7 @@ class BranchMainStage(PipeModBase):
         comb = m.d.comb
         op = self.i.ctx.op
         lk = op.lk # see PowerDecode2 as to why this is done
-        cr, cia, ctr, fast1 = self.i.cr, self.i.cia, self.i.ctr, self.i.fast1
+        cr, cia, ctr, fast1 = self.i.cr, op.cia, self.i.ctr, self.i.fast1
         fast2 = self.i.fast2
         nia_o, lr_o, ctr_o = self.o.nia, self.o.lr, self.o.ctr
 
@@ -70,7 +85,7 @@ class BranchMainStage(PipeModBase):
         br_taken = Signal(reset_less=True)
 
         # Handle absolute or relative branches
-        with m.If(AA | (op.insn_type == InternalOp.OP_BCREG)):
+        with m.If(AA | (op.insn_type == MicrOp.OP_BCREG)):
             comb += br_addr.eq(br_imm_addr)
         with m.Else():
             comb += br_addr.eq(br_imm_addr + cia)
@@ -121,18 +136,18 @@ class BranchMainStage(PipeModBase):
         ### Main Switch Statement ###
         with m.Switch(op.insn_type):
             #### branch ####
-            with m.Case(InternalOp.OP_B):
+            with m.Case(MicrOp.OP_B):
                 LI = i_fields.LI[0:-1]
                 comb += br_imm_addr.eq(br_ext(LI))
                 comb += br_taken.eq(1)
             #### branch conditional ####
-            with m.Case(InternalOp.OP_BC):
+            with m.Case(MicrOp.OP_BC):
                 BD = b_fields.BD[0:-1]
                 comb += br_imm_addr.eq(br_ext(BD))
                 comb += br_taken.eq(bc_taken)
                 comb += ctr_o.ok.eq(ctr_write)
             #### branch conditional reg ####
-            with m.Case(InternalOp.OP_BCREG):
+            with m.Case(MicrOp.OP_BCREG):
                 xo = self.fields.FormXL.XO[0:-1]
                 with m.If(xo[9] & ~xo[5]):
                     comb += br_imm_addr.eq(Cat(Const(0, 2), fast1[2:]))