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,
+from openpower.consts import (SVP64MODE, SVP64MODEb,
SVP64CROffs,
)
from openpower.decoder.power_svp64 import SVP64RM, decode_extra
'VRSAVE': 256}
+# rrright. this is here basically because the compiler pywriter returns
+# results in a specific priority order. to make sure regs match up they
+# need partial sorting. sigh.
REG_SORT_ORDER = {
# TODO (lkcl): adjust other registers that should be in a particular order
# probably CA, CA32, and CR
_cr = FieldSelectableInt(self.cr, bits)
self.crl.append(_cr)
-# decode SVP64 predicate integer to reg number and invert
-
+# decode SVP64 predicate integer to reg number and invert
def get_predint(gpr, mask):
+ r3 = gpr(3)
r10 = gpr(10)
r30 = gpr(30)
log("get_predint", mask, SVP64PredInt.ALWAYS.value)
if mask == SVP64PredInt.ALWAYS.value:
return 0xffff_ffff_ffff_ffff # 64 bits of 1
if mask == SVP64PredInt.R3_UNARY.value:
- return 1 << (gpr(3).value & 0b111111)
+ return 1 << (r3.value & 0b111111)
if mask == SVP64PredInt.R3.value:
- return gpr(3).value
+ return r3.value
if mask == SVP64PredInt.R3_N.value:
- return ~gpr(3).value
+ return ~r3.value
if mask == SVP64PredInt.R10.value:
- return gpr(10).value
+ return r10.value
if mask == SVP64PredInt.R10_N.value:
- return ~gpr(10).value
+ return ~r10.value
if mask == SVP64PredInt.R30.value:
- return gpr(30).value
+ return r30.value
if mask == SVP64PredInt.R30_N.value:
- return ~gpr(30).value
-
-# decode SVP64 predicate CR to reg number and invert status
+ return ~r30.value
+# decode SVP64 predicate CR to reg number and invert status
def _get_predcr(mask):
if mask == SVP64PredCR.LT.value:
return 0, 1
if mask == SVP64PredCR.NS.value:
return 3, 0
+
# read individual CR fields (0..VL-1), extract the required bit
# and construct the mask
-
-
def get_predcr(crl, mask, vl):
idx, noninv = _get_predcr(mask)
mask = 0
def __init__(self, svstate):
self.svstate = svstate
- self.loopend = False
self.new_iterators()
def new_iterators(self):
self.src_it = self.src_iterator()
self.dst_it = self.dst_iterator()
- self.end_src = False
- self.end_dst = False
+ self.loopend = False
self.new_srcstep = 0
self.new_dststep = 0
self.new_ssubstep = 0
# source step
if pack:
# pack advances subvl in *outer* loop
- if end_src:
- if not end_ssub:
- self.svstate.ssubstep += SelectableInt(1, 2)
- self.svstate.srcstep = SelectableInt(0, 7) # reset
- else:
- self.svstate.srcstep += SelectableInt(1, 7) # advance srcstep
+ while True: # outer subvl loop
+ while True: # inner vl loop
+ vl = self.svstate.vl
+ subvl = self.subvl
+ srcmask = self.srcmask
+ srcstep = self.svstate.srcstep
+ pred_src_zero = ((1 << srcstep) & srcmask) != 0
+ if self.pred_sz or pred_src_zero:
+ self.pred_src_zero = not pred_src_zero
+ log(" advance src", srcstep, vl,
+ self.svstate.ssubstep, subvl)
+ # yield actual substep/srcstep
+ yield (self.svstate.ssubstep, srcstep)
+ # the way yield works these could have been modified.
+ vl = self.svstate.vl
+ subvl = self.subvl
+ srcstep = self.svstate.srcstep
+ log(" advance src check", srcstep, vl,
+ self.svstate.ssubstep, subvl, srcstep == vl-1,
+ self.svstate.ssubstep == subvl)
+ if srcstep == vl-1: # end-point
+ self.svstate.srcstep = SelectableInt(0, 7) # reset
+ if self.svstate.ssubstep == subvl: # end-point
+ log(" advance pack stop")
+ return
+ break # exit inner loop
+ self.svstate.srcstep += SelectableInt(1, 7) # advance ss
+ subvl = self.subvl
+ if self.svstate.ssubstep == subvl: # end-point
+ self.svstate.ssubstep = SelectableInt(0, 2) # reset
+ log(" advance pack stop")
+ return
+ self.svstate.ssubstep += SelectableInt(1, 2)
+
else:
# these cannot be done as for-loops because SVSTATE may change
# (srcstep/substep may be modified, interrupted, subvl/vl change)
# "thing" is re-read every single time a yield gives indices
while True: # outer vl loop
while True: # inner subvl loop
+ vl = self.svstate.vl
subvl = self.subvl
srcmask = self.srcmask
srcstep = self.svstate.srcstep
- if self.pred_sz or ((1 << srcstep) & srcmask) != 0:
- log(" advance src", srcstep, self.svstate.vl,
+ pred_src_zero = ((1 << srcstep) & srcmask) != 0
+ if self.pred_sz or pred_src_zero:
+ self.pred_src_zero = not pred_src_zero
+ log(" advance src", srcstep, vl,
self.svstate.ssubstep, subvl)
# yield actual substep/srcstep
yield (self.svstate.ssubstep, srcstep)
if self.svstate.ssubstep == subvl: # end-point
self.svstate.ssubstep = SelectableInt(0, 2) # reset
- break
+ break # exit inner loop
self.svstate.ssubstep += SelectableInt(1, 2)
vl = self.svstate.vl
if srcstep == vl-1: # end-point
self.svstate.srcstep = SelectableInt(0, 7) # reset
- break # trigger StopIteration
+ self.loopend = True
+ return
self.svstate.srcstep += SelectableInt(1, 7) # advance srcstep
def dst_iterator(self):
# dest step
if unpack:
# pack advances subvl in *outer* loop
- pass # TODO
+ while True: # outer subvl loop
+ while True: # inner vl loop
+ vl = self.svstate.vl
+ subvl = self.subvl
+ dstmask = self.dstmask
+ dststep = self.svstate.dststep
+ pred_dst_zero = ((1 << dststep) & dstmask) != 0
+ if self.pred_dz or pred_dst_zero:
+ self.pred_dst_zero = not pred_dst_zero
+ log(" advance dst", dststep, vl,
+ self.svstate.dsubstep, subvl)
+ # yield actual substep/dststep
+ yield (self.svstate.dsubstep, dststep)
+ # the way yield works these could have been modified.
+ vl = self.svstate.vl
+ dststep = self.svstate.dststep
+ log(" advance dst check", dststep, vl,
+ self.svstate.ssubstep, subvl)
+ if dststep == vl-1: # end-point
+ self.svstate.dststep = SelectableInt(0, 7) # reset
+ if self.svstate.dsubstep == subvl: # end-point
+ log(" advance unpack stop")
+ return
+ break
+ self.svstate.dststep += SelectableInt(1, 7) # advance ds
+ subvl = self.subvl
+ if self.svstate.dsubstep == subvl: # end-point
+ self.svstate.dsubstep = SelectableInt(0, 2) # reset
+ log(" advance unpack stop")
+ return
+ self.svstate.dsubstep += SelectableInt(1, 2)
else:
# these cannot be done as for-loops because SVSTATE may change
# (dststep/substep may be modified, interrupted, subvl/vl change)
subvl = self.subvl
dstmask = self.dstmask
dststep = self.svstate.dststep
- if self.pred_dz or ((1 << dststep) & dstmask) != 0:
+ pred_dst_zero = ((1 << dststep) & dstmask) != 0
+ if self.pred_dz or pred_dst_zero:
+ self.pred_dst_zero = not pred_dst_zero
log(" advance dst", dststep, self.svstate.vl,
self.svstate.dsubstep, subvl)
# yield actual substep/dststep
self.svstate.dsubstep = SelectableInt(0, 2) # reset
break
self.svstate.dsubstep += SelectableInt(1, 2)
+ subvl = self.subvl
vl = self.svstate.vl
if dststep == vl-1: # end-point
self.svstate.dststep = SelectableInt(0, 7) # reset
- break # trigger StopIteration
+ return
self.svstate.dststep += SelectableInt(1, 7) # advance dststep
def src_iterate(self):
end_src = srcstep == vl-1
if end_src: # end-point
self.loopend = True
+ srcstep = 0
break
else:
srcstep += 1
end_dst = dststep == vl-1
if end_dst: # end-point
self.loopend = True
+ dststep = 0
break
else:
dststep += 1
# set up 4 dummy SVSHAPEs if they aren't already set up
for i in range(4):
sname = 'SVSHAPE%d' % i
- if sname not in self.spr:
- val = 0
- else:
- val = self.spr[sname].value
+ val = self.spr.get(sname, 0)
# make sure it's an SVSHAPE
self.spr[sname] = SVSHAPE(val, self.gpr)
self.last_op_svshape = False
if self.is_svp64_mode and insn_name.startswith("sv.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_snz = (mode & SVP64MODE.BC_SNZ) != 0
+ mode = SelectableInt(mode, 5) # convert to SelectableInt before test
+ bc_vlset = mode[SVP64MODEb.BC_VLSET] != 0
+ bc_vli = mode[SVP64MODEb.BC_VLI] != 0
+ bc_snz = mode[SVP64MODEb.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['mode'] = SelectableInt(mode, 5)
self.namespace['ALL'] = SelectableInt(bc_gate, 1)
self.namespace['VSb'] = SelectableInt(bc_vsb, 1)
self.namespace['LRu'] = SelectableInt(bc_lru, 1)
self.namespace['sz'] = SelectableInt(sz, 1)
self.namespace['SNZ'] = SelectableInt(bc_snz, 1)
- def handle_carry_(self, inputs, outputs, already_done):
+ def handle_carry_(self, inputs, output, ca, ca32):
inv_a = yield self.dec2.e.do.invert_in
if inv_a:
inputs[0] = ~inputs[0]
if imm_ok:
imm = yield self.dec2.e.do.imm_data.data
inputs.append(SelectableInt(imm, 64))
- assert len(outputs) >= 1
- log("outputs", repr(outputs))
- if isinstance(outputs, list) or isinstance(outputs, tuple):
- output = outputs[0]
- else:
- output = outputs
gts = []
for x in inputs:
log("gt input", x, output)
log(gts)
cy = 1 if any(gts) else 0
log("CA", cy, gts)
- if not (1 & already_done):
+ if ca is None: # already written
self.spr['XER'][XER_bits['CA']] = cy
- log("inputs", already_done, inputs)
# 32 bit carry
# ARGH... different for OP_ADD... *sigh*...
op = yield self.dec2.e.do.insn_type
gts.append(gt)
cy32 = 1 if any(gts) else 0
log("CA32", cy32, gts)
- if not (2 & already_done):
+ if ca32 is None: # already written
self.spr['XER'][XER_bits['CA32']] = cy32
- def handle_overflow(self, inputs, outputs, div_overflow):
+ def handle_overflow(self, inputs, output, div_overflow):
if hasattr(self.dec2.e.do, "invert_in"):
inv_a = yield self.dec2.e.do.invert_in
if inv_a:
if imm_ok:
imm = yield self.dec2.e.do.imm_data.data
inputs.append(SelectableInt(imm, 64))
- assert len(outputs) >= 1
- log("handle_overflow", inputs, outputs, div_overflow)
+ log("handle_overflow", inputs, output, div_overflow)
if len(inputs) < 2 and div_overflow is None:
return
ov, ov32 = div_overflow, div_overflow
# arithmetic overflow can be done by analysing the input and output
elif len(inputs) >= 2:
- output = outputs[0]
-
# OV (64-bit)
input_sgn = [exts(x.value, x.bits) < 0 for x in inputs]
output_sgn = exts(output.value, output.bits) < 0
self.spr['XER'][XER_bits['SO']] = new_so
log(" set overflow", ov, ov32, so, new_so)
- def handle_comparison(self, outputs, cr_idx=0, overflow=None, no_so=False):
- out = outputs[0]
+ def handle_comparison(self, out, cr_idx=0, overflow=None, no_so=False):
assert isinstance(out, SelectableInt), \
"out zero not a SelectableInt %s" % repr(outputs)
log("handle_comparison", out.bits, hex(out.value))
"""execute one instruction
"""
# get the disassembly code for this instruction
- if self.is_svp64_mode:
- if not self.disassembly:
- code = yield from self.get_assembly_name()
- else:
- code = self.disassembly[self._pc+4]
- log(" svp64 sim-execute", hex(self._pc), code)
+ if not self.disassembly:
+ code = yield from self.get_assembly_name()
else:
- if not self.disassembly:
- code = yield from self.get_assembly_name()
- else:
- code = self.disassembly[self._pc]
- log("sim-execute", hex(self._pc), code)
+ offs, dbg = 0, ""
+ if self.is_svp64_mode:
+ offs, dbg = 4, "svp64 "
+ code = self.disassembly[self._pc+offs]
+ log(" %s sim-execute" % dbg, hex(self._pc), code)
opname = code.split(' ')[0]
try:
yield from self.call(opname) # execute the instruction
# execute actual instruction here (finally)
log("inputs", inputs)
results = info.func(self, *inputs)
- log("results", results)
+ output_names = create_args(info.write_regs)
+ outs = {}
+ for out, n in zip(results or [], output_names):
+ outs[n] = out
+ log("results", outs)
# "inject" decorator takes namespace from function locals: we need to
# overwrite NIA being overwritten (sigh)
self.last_st_addr, self.last_ld_addr)
# detect if CA/CA32 already in outputs (sra*, basically)
- already_done = 0
- output_names = []
- if info.write_regs:
- output_names = create_args(info.write_regs)
- for name in output_names:
- if name == 'CA':
- already_done |= 1
- if name == 'CA32':
- already_done |= 2
-
- log("carry already done?", bin(already_done), output_names)
+ ca = outs.get("CA")
+ ca32 = outs.get("CA32 ")
+
+ log("carry already done?", ca, ca32, output_names)
carry_en = yield self.dec2.e.do.output_carry
if carry_en:
- yield from self.handle_carry_(inputs, results, already_done)
+ yield from self.handle_carry_(inputs, results[0], ca, ca32)
# check if one of the regs was named "overflow"
- overflow = None
- if info.write_regs:
- for name, output in zip(output_names, results):
- if name == 'overflow':
- overflow = output
-
+ overflow = outs.get('overflow')
# and one called CR0
- cr0 = None
- if info.write_regs:
- for name, output in zip(output_names, results):
- if name == 'CR0':
- cr0 = output
+ cr0 = outs.get('CR0')
if not self.is_svp64_mode: # yeah just no. not in parallel processing
# detect if overflow was in return result
ov_ok = yield self.dec2.e.do.oe.ok
log("internal overflow", ins_name, overflow, "en?", ov_en, ov_ok)
if ov_en & ov_ok:
- yield from self.handle_overflow(inputs, results, overflow)
+ yield from self.handle_overflow(inputs, results[0], overflow)
# only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
rc_en = False
# XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
# to write directly to CR0 instead of in ISACaller. hooyahh.
if rc_en and ins_name not in ['svstep']:
- yield from self.do_rc_ov(ins_name, results, overflow, cr0)
+ yield from self.do_rc_ov(ins_name, results[0], overflow, cr0)
# check failfirst
ffirst_hit = False
ffirst_hit = (yield from self.check_ffirst(rc_en, srcstep))
# any modified return results?
- yield from self.do_outregs_nia(asmop, ins_name, info,
- output_names, results,
+ yield from self.do_outregs_nia(asmop, ins_name, info, outs,
carry_en, rc_en, ffirst_hit)
def check_ffirst(self, rc_en, srcstep):
yield Settle() # let decoder update
return True
- def do_rc_ov(self, ins_name, results, overflow, cr0):
+ def do_rc_ov(self, ins_name, result, overflow, cr0):
if ins_name.startswith("f"):
rc_reg = "CR1" # not calculated correctly yet (not FP compares)
else:
rc_reg = "CR0"
regnum, is_vec = yield from get_pdecode_cr_out(self.dec2, rc_reg)
- cmps = results
# hang on... for `setvl` actually you want to test SVSTATE.VL
is_setvl = ins_name == 'setvl'
if is_setvl:
- vl = results[0].vl
- cmps = (SelectableInt(vl, 64), overflow,)
+ result = SelectableInt(result.vl, 64)
else:
overflow = None # do not override overflow except in setvl
# if there was not an explicit CR0 in the pseudocode, do implicit Rc=1
if cr0 is None:
- self.handle_comparison(cmps, regnum, overflow, no_so=is_setvl)
+ self.handle_comparison(result, regnum, overflow, no_so=is_setvl)
else:
# otherwise we just blat CR0 into the required regnum
log("explicit rc0", cr0)
self.crl[regnum].eq(cr0)
- def do_outregs_nia(self, asmop, ins_name, info, output_names, results,
+ def do_outregs_nia(self, asmop, ins_name, info, outs,
carry_en, rc_en, ffirst_hit):
# write out any regs for this instruction
- if info.write_regs:
- for name, output in zip(output_names, results):
- yield from self.check_write(info, name, output, carry_en)
+ for name, output in outs.items():
+ yield from self.check_write(info, name, output, carry_en)
if ffirst_hit:
self.svp64_reset_loop()
nia_update = True
else:
# check advancement of src/dst/sub-steps and if PC needs updating
- nia_update = (yield from self.check_step_increment(results, rc_en,
+ nia_update = (yield from self.check_step_increment(rc_en,
asmop, ins_name))
if nia_update:
self.update_pc_next()
else:
self.gpr[regnum] = output
- def check_step_increment(self, results, rc_en, asmop, ins_name):
+ def check_step_increment(self, rc_en, asmop, ins_name):
# check if it is the SVSTATE.src/dest step that needs incrementing
# this is our Sub-Program-Counter loop from 0 to VL-1
if not self.allow_next_step_inc:
self.update_nia()
if not rc_en:
return True
- results = [SelectableInt(0, 64)]
- self.handle_comparison(results) # CR0
+ self.handle_comparison(SelectableInt(0, 64)) # CR0
return True
if self.allow_next_step_inc == 2:
log("SVSTATE_NEXT: read")