--- /dev/null
+<!-- Instructions here part of Draft SVP64 Vectorised Branch -->
+
+<!-- Section 2.4 Branch Instructions. Pages 33 - 39 -->
+
+<!-- The sequence of instruction execution can be changed by the Branch -->
+<!-- instructions. Because all instructions are on word boundaries, bits 62 and 63 -->
+<!-- of the generated branch target address are ignored by the processor in -->
+<!-- performing the branch. -->
+
+<!-- target_addr specifies the branch target address. -->
+
+<!-- If AA=0 then the branch target address is the sum of LI || 0b00 sign-extended -->
+<!-- and the address of this instruction, with the high-order 32 bits of the branch -->
+<!-- target address set to 0 in 32-bit mode. -->
+
+<!-- If AA=1 then the branch target address is the value LI || 0b00 sign-extended, -->
+<!-- with the high-order 32 bits of the branch target address set to 0 in 32-bit -->
+<!-- mode. -->
+
+<!-- If LK=1 then the effective address of the instruction following the Branch -->
+<!-- instruction is placed into the Link Register. -->
+
+# Branch Conditional
+
+B-Form
+
+* sv.bc BO,BI,target_addr (AA=0 LK=0)
+* sv.bca BO,BI,target_addr (AA=1 LK=0)
+* sv.bcl BO,BI,target_addr (AA=0 LK=1)
+* sv.bcla BO,BI,target_addr (AA=1 LK=1)
+
+Pseudo-code:
+
+ # get SVP64 extended CR field 0..127
+ # SVCRf = sVP64EXTRA(BI>>2)
+ # if svstep_mode then
+ # new_srcstep, CRbits = SVSTATE_NEXT(srcstep)
+ # else
+ # CRbits = CR{SVCRf}
+ # select predicate bit or zero/one
+ # XXX if predicate[srcstep] then
+ # XXX if BRc = 1 then # CR0 vectorised
+ # XXX CR{SVCRf+srcstep} = CRbits
+ # XXX testbit = CRbits[BI & 0b11]
+ if sz then
+ testbit = SNZ
+ else
+ testbit <- CR[BI+32]
+ # actual element test here
+ cond_ok <- BO[0] | ¬(testbit ^ BO[1])
+ # test for VL to be set (and exit)
+ if VLSET & (cond_ok = VSb) then
+ if VLI then
+ SVSTATE[7:13] <- (srcstep+1)
+ else
+ SVSTATE[7:13] <- srcstep+1
+ # XXX if svstep_mode then
+ # XXX SVSTATE.srcstep = new_srcstep
+ # actual branch
+ if (mode_is_64bit) then M <- 0
+ else M <- 32
+ if ¬BO[2] then CTR <- CTR - 1
+ ctr_ok <- BO[2] | ((CTR[M:63] != 0) ^ BO[3])
+ lr_ok <- LRu
+ if ctr_ok & cond_ok then
+ if AA then NIA <-iea EXTS(BD || 0b00)
+ else NIA <-iea CIA + EXTS(BD || 0b00)
+ lr_ok <- 0b1
+ if LK & lr_ok then LR <-iea CIA + 4
+
+Special Registers Altered:
+
+ CTR (if BO2=0)
+ LR (if LK=1)
+
+# Branch Conditional to Link Register
+
+XL-Form
+
+* sv.bclr BO,BI,BH (LK=0)
+* sv.bclrl BO,BI,BH (LK=1)
+
+Pseudo-code:
+
+ if (mode_is_64bit) then M <- 0
+ else M <- 32
+ if ¬BO[2] then CTR <- CTR - 1
+ ctr_ok <- BO[2] | ((CTR[M:63] != 0) ^ BO[3])
+ cond_ok <- BO[0] | ¬(CR[BI+32] ^ BO[1])
+ lr_ok <- LRu
+ if ctr_ok & cond_ok then
+ NIA <-iea LR[0:61] || 0b00
+ lr_ok <- 0b1
+ if LK & lr_ok then LR <-iea CIA + 4
+
+Special Registers Altered:
+
+ CTR (if BO2=0)
+ LR (if LK=1)
+
from openpower.decoder.helpers import (exts, gtu, ltu, undefined)
from openpower.consts import PIb, MSRb # big-endian (PowerISA versions)
-from openpower.consts import SVP64CROffs
+from openpower.consts import (SVP64MODE,
+ SVP64CROffs,
+ )
from openpower.decoder.power_svp64 import SVP64RM, decode_extra
from openpower.decoder.isa.radixmmu import RADIX
def memassign(self, ea, sz, val):
self.mem.memassign(ea, sz, val)
- def prep_namespace(self, formname, op_fields):
+ def prep_namespace(self, insn_name, formname, op_fields):
# TODO: get field names from form in decoder*1* (not decoder2)
# decoder2 is hand-created, and decoder1.sigform is auto-generated
# from spec
self.namespace['VL'] = vl
self.namespace['srcstep'] = srcstep
+ # sv.bc* need some extra fields
+ if self.is_svp64_mode and insn_name.startswith("bc"):
+ # blegh grab bits manually
+ mode = yield self.dec2.rm_dec.rm_in.mode
+ bc_vlset = (mode & SVP64MODE.BC_VLSET) != 0
+ bc_vli = (mode & SVP64MODE.BC_VLI) != 0
+ bc_vsb = yield self.dec2.rm_dec.bc_vsb
+ bc_lru = yield self.dec2.rm_dec.bc_lru
+ self.namespace['VSb'] = SelectableInt(bc_vsb, 1)
+ self.namespace['LRu'] = SelectableInt(bc_lru, 1)
+ self.namespace['VLSET'] = SelectableInt(bc_vlset, 1)
+ self.namespace['VLI'] = SelectableInt(bc_vli, 1)
+
def handle_carry_(self, inputs, outputs, already_done):
inv_a = yield self.dec2.e.do.invert_in
if inv_a:
return
info = self.instrs[ins_name]
- yield from self.prep_namespace(info.form, info.op_fields)
+ yield from self.prep_namespace(ins_name, info.form, info.op_fields)
# preserve order of register names
input_names = create_args(list(info.read_regs) +