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
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
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
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)
### 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:]))