selectconcat)
from openpower.decoder.power_enums import (spr_dict, spr_byname, XER_bits,
insns, MicrOp, In1Sel, In2Sel, In3Sel,
- OutSel, CROutSel, LDSTMode,
+ OutSel, CRInSel, CROutSel, LDSTMode,
SVP64RMMode, SVP64PredMode,
SVP64PredInt, SVP64PredCR,
SVP64LDSTmode)
from openpower.decoder.power_enums import SVPtype
-from openpower.decoder.helpers import (exts, gtu, ltu, undefined)
+from openpower.decoder.helpers import (exts, gtu, ltu, undefined,
+ ISACallerHelper, ISAFPHelpers)
from openpower.consts import PIb, MSRb # big-endian (PowerISA versions)
from openpower.consts import (SVP64MODE,
SVP64CROffs,
"RB": 0,
"RC": 0,
"RS": 0,
+ "BI": 0,
"CR": 0,
"LR": 0,
"CTR": 0,
return None, False
+# TODO, really should just be using PowerDecoder2
+def get_pdecode_cr_in(dec2, name):
+ op = dec2.dec.op
+ in_sel = yield op.cr_in
+ in_bitfield = yield dec2.dec_cr_in.cr_bitfield.data
+ sv_cr_in = yield op.sv_cr_in
+ spec = yield dec2.crin_svdec.spec
+ sv_override = yield dec2.dec_cr_in.sv_override
+ # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
+ in1 = yield dec2.e.read_cr1.data
+ cr_isvec = yield dec2.cr_in_isvec
+ log ("get_pdecode_cr_in", in_sel, CROutSel.CR0.value, in1, cr_isvec)
+ log (" sv_cr_in", sv_cr_in)
+ log (" cr_bf", in_bitfield)
+ log (" spec", spec)
+ log (" override", sv_override)
+ # identify which regnames map to in / o2
+ if name == 'BI':
+ if in_sel == CRInSel.BI.value:
+ return in1, cr_isvec
+ log ("get_pdecode_cr_in not found", name)
+ return None, False
+
+
# TODO, really should just be using PowerDecoder2
def get_pdecode_cr_out(dec2, name):
op = dec2.dec.op
return None, False
-class ISACaller:
+class ISACaller(ISACallerHelper, ISAFPHelpers):
# decoder2 - an instance of power_decoder2
# regfile - a list of initial values for the registers
# initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
self.msr = SelectableInt(initial_msr, 64) # underlying reg
self.pc = PC()
# GPR FPR SPR registers
+ initial_sprs = copy(initial_sprs) # so as not to get modified
self.gpr = GPR(decoder2, self, self.svstate, regfile)
self.fpr = GPR(decoder2, self, self.svstate, fpregfile)
self.spr = SPR(decoder2, initial_sprs) # initialise SPRs before MMU
'MSR': self.msr,
'undefined': undefined,
'mode_is_64bit': True,
- 'SO': XER_bits['SO']
+ 'SO': XER_bits['SO'],
+ 'XLEN': 64 # elwidth overrides, later
})
# update pc to requested start point
fields = self.decoder.sigforms[formname]
log("prep_namespace", formname, op_fields)
for name in op_fields:
- if name == 'spr':
- sig = getattr(fields, name.upper())
- else:
+ # CR immediates. deal with separately. needs modifying
+ # pseudocode
+ if self.is_svp64_mode and name in ['BI']: # TODO, more CRs
+ # BI is a 5-bit, must reconstruct the value
+ regnum, is_vec = yield from get_pdecode_cr_in(self.dec2, name)
sig = getattr(fields, name)
- val = yield sig
+ val = yield sig
+ # low 2 LSBs (CR field selector) remain same, CR num extended
+ assert regnum <= 7, "sigh, TODO, 128 CR fields"
+ val = (val & 0b11) | (regnum<<2)
+ else:
+ if name == 'spr':
+ sig = getattr(fields, name.upper())
+ else:
+ sig = getattr(fields, name)
+ val = yield sig
# these are all opcode fields involved in index-selection of CR,
# and need to do "standard" arithmetic. CR[BA+32] for example
# would, if using SelectableInt, only be 5-bit.
bc_snz = (mode & SVP64MODE.BC_SNZ) != 0
bc_vsb = yield self.dec2.rm_dec.bc_vsb
bc_lru = yield self.dec2.rm_dec.bc_lru
+ bc_gate = yield self.dec2.rm_dec.bc_gate
sz = yield self.dec2.rm_dec.pred_sz
+ self.namespace['ALL'] = SelectableInt(bc_gate, 1)
self.namespace['VSb'] = SelectableInt(bc_vsb, 1)
self.namespace['LRu'] = SelectableInt(bc_lru, 1)
self.namespace['VLSET'] = SelectableInt(bc_vlset, 1)
if not self.respect_pc:
self.fake_pc += 4
- log("execute one, CIA NIA", self.pc.CIA.value, self.pc.NIA.value)
+ log("execute one, CIA NIA", hex(self.pc.CIA.value),
+ hex(self.pc.NIA.value))
def get_assembly_name(self):
# TODO, asmregs is from the spec, e.g. add RT,RA,RB
if not self.is_svp64_mode or not pred_src_zero:
log('reading reg %s %s' % (name, str(regnum)), is_vec)
if name in fregs:
- reg_val = self.fpr(regnum)
+ reg_val = SelectableInt(self.fpr(regnum))
elif name is not None:
- reg_val = self.gpr(regnum)
+ reg_val = SelectableInt(self.gpr(regnum))
else:
log('zero input reg %s %s' % (name, str(regnum)), is_vec)
reg_val = 0
# clear trap (trap) NIA
self.trap_nia = None
+ # check if this was an sv.bc* and create an indicator that
+ # this is the last check to be made as a loop. combined with
+ # the ALL/ANY mode we can early-exit
+ if self.is_svp64_mode and ins_name.startswith("sv.bc"):
+ no_in_vec = yield self.dec2.no_in_vec # BI is scalar
+ end_loop = no_in_vec or srcstep == vl-1 or dststep == vl-1
+ self.namespace['end_loop'] = SelectableInt(end_loop, 1)
+
# execute actual instruction here (finally)
log("inputs", inputs)
results = info.func(self, *inputs)
# this is our Sub-Program-Counter loop from 0 to VL-1
pre = False
post = False
+ nia_update = True
if self.allow_next_step_inc:
log("SVSTATE_NEXT: inc requested, mode",
self.svstate_next_mode, self.allow_next_step_inc)
else:
if self.allow_next_step_inc == 2:
log ("SVSTATE_NEXT: read")
- yield from self.svstate_post_inc()
+ nia_update = (yield from self.svstate_post_inc(ins_name))
else:
log ("SVSTATE_NEXT: post-inc")
# use actual src/dst-step here to check end, do NOT
self.svstate.vfirst = 0
elif self.is_svp64_mode:
- yield from self.svstate_post_inc()
+ nia_update = (yield from self.svstate_post_inc(ins_name))
else:
# XXX only in non-SVP64 mode!
# record state of whether the current operation was an svshape,
# to interrupt in between. sigh.
self.last_op_svshape = asmop == 'svremap'
- self.update_pc_next()
+ if nia_update:
+ self.update_pc_next()
def SVSTATE_NEXT(self, mode, submode):
"""explicitly moves srcstep/dststep on to next element, for
# nothing needs doing (TODO zeroing): just do next instruction
return srcstep == vl or dststep == vl
- def svstate_post_inc(self, vf=0):
+ def svstate_post_inc(self, insn_name, vf=0):
# check if SV "Vertical First" mode is enabled
vfirst = self.svstate.vfirst
log (" SV Vertical First", vf, vfirst)
svp64_is_vector = (out_vec or in_vec)
else:
svp64_is_vector = out_vec
+ # check if this was an sv.bc* and if so did it succeed
+ if self.is_svp64_mode and insn_name.startswith("sv.bc"):
+ end_loop = self.namespace['end_loop']
+ log("branch %s end_loop" % insn_name, end_loop)
+ if end_loop.value:
+ self.svp64_reset_loop()
+ self.update_pc_next()
+ return False
if svp64_is_vector and srcstep != vl-1 and dststep != vl-1:
self.svstate.srcstep += SelectableInt(1, 7)
self.svstate.dststep += SelectableInt(1, 7)
+ self.namespace['SVSTATE'] = self.svstate
+ # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
+ # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
+ # this way we keep repeating the same instruction (with new steps)
self.pc.NIA.value = self.pc.CIA.value
self.namespace['NIA'] = self.pc.NIA
- self.namespace['SVSTATE'] = self.svstate
log("end of sub-pc call", self.namespace['CIA'],
self.namespace['NIA'])
return False # DO NOT allow PC update whilst Sub-PC loop running
self.pc.update_nia(self.is_svp64_mode)
self.namespace['NIA'] = self.pc.NIA
+
def inject():
"""Decorator factory.
log("args[0]", args[0].namespace['CIA'],
args[0].namespace['NIA'],
args[0].namespace['SVSTATE'])
+ if 'end_loop' in func_globals:
+ log("args[0] end_loop", func_globals['end_loop'])
args[0].namespace = func_globals
#exec (func.__code__, func_globals)