*read_regs, *uninit_regs, *write_regs, *special_regs], extra=extra)
+def is_ffirst_mode(dec2):
+ rm_mode = yield dec2.rm_dec.mode
+ return rm_mode == SVP64RMMode.FFIRST.value
+
+
class GPR(dict):
def __init__(self, decoder, isacaller, svstate, regfile):
dict.__init__(self)
rnum = rnum.value
dict.__setitem__(self, rnum, value)
- def getz(self, rnum):
+ def getz(self, rnum, rvalue=None):
# rnum = rnum.value # only SelectableInt allowed
- log("GPR getzero?", rnum)
+ log("GPR getzero?", rnum, rvalue)
+ if rvalue is not None:
+ if rnum == 0:
+ return SelectableInt(0, rvalue.bits)
+ return rvalue
if rnum == 0:
return SelectableInt(0, 64)
return self[rnum]
cr_field = selectconcat(negative, positive, zero, SO)
log("handle_comparison cr_field", self.cr, cr_idx, cr_field)
self.crl[cr_idx].eq(cr_field)
+ return cr_field
def set_pc(self, pc_val):
self.namespace['NIA'] = SelectableInt(pc_val, 64)
"brh", "brw", "brd",
'setvl', 'svindex', 'svremap', 'svstep',
'svshape', 'svshape2',
- 'ternlogi', 'bmask', 'cprop',
+ 'ternlogi', 'bmask', 'cprop', 'gbbd',
'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
"dsld", "dsrd", "maddedus",
ins_name = dotstrp
# match against instructions treated as nop, see nop below
- if asmop.startswith("dc"):
+ if asmop.startswith("dcbt"):
illegal = False
ins_name = "nop"
ew_src = 8 << (3-int(ew_src)) # convert to bitlength
ew_dst = 8 << (3-int(ew_dst)) # convert to bitlength
xlen = max(ew_src, ew_dst)
- log("elwdith", ew_src, ew_dst)
+ log("elwidth", ew_src, ew_dst)
log("XLEN:", self.is_svp64_mode, xlen)
# look up instruction in ISA.instrs, prepare namespace
remap_active = yield self.dec2.remap_active
else:
remap_active = False
- log("remap active", bin(remap_active))
+ log("remap active", bin(remap_active), self.is_svp64_mode)
+
+ # LDST does *not* allow elwidth overrides on RA (Effective Address).
+ # this has to be detected. XXX TODO: RB for ldst-idx *may* need
+ # conversion (to 64-bit) also.
+ # see write reg this *HAS* to also override XLEN to 64 on LDST/Update
+ sv_mode = yield self.dec2.rm_dec.sv_mode
+ is_ldst = (sv_mode in [SVMode.LDST_IDX.value, SVMode.LDST_IMM.value] \
+ and self.is_svp64_mode)
+ log("is_ldst", sv_mode, is_ldst)
# main input registers (RT, RA ...)
for name in input_names:
inputs[name] = self.crl[0]
elif name in spr_byname:
inputs[name] = self.spr[name]
+ elif is_ldst and name == 'RA':
+ regval = (yield from self.get_input(name, ew_src, 64))
+ log("EA (RA) regval name", name, regval)
+ inputs[name] = regval
else:
- regval = (yield from self.get_input(name, ew_src))
+ regval = (yield from self.get_input(name, ew_src, xlen))
log("regval name", name, regval)
inputs[name] = regval
log(" vli", vli_)
log(" cr_bit", cr_bit)
log(" rc_en", rc_en)
- if not rc_en or rm_mode != SVP64RMMode.FFIRST.value:
+ if not rc_en or not is_ffirst_mode(self.dec2):
return False, False
# get the CR vevtor, do BO-test
crf = "CR0"
elif cr0 is None:
# if there was not an explicit CR0 in the pseudocode,
# do implicit Rc=1
- self.handle_comparison(result, regnum, overflow, no_so=is_setvl)
+ c = self.handle_comparison(result, regnum, overflow, no_so=is_setvl)
+ log("implicit cr0", c)
else:
# otherwise we just blat CR0 into the required regnum
- log("explicit rc0", cr0)
+ log("explicit cr0", cr0)
self.crl[regnum].eq(cr0)
def do_outregs(self, info, outs, ca_en, ffirst_hit, ew_dst, outs_ok):
else:
self.namespace['D'] = imm
- def get_input(self, name, ew_src):
+ def get_input(self, name, ew_src, xlen):
# using PowerDecoder2, first, find the decoder index.
# (mapping name RA RB RC RS to in1, in2, in3)
regnum, is_vec = yield from get_idx_in(self.dec2, name, True)
regname = "_" + name
if not self.is_svp64_mode or ew_src == 64:
self.namespace[regname] = regnum
- elif regname in self.namespace:
- del self.namespace[regname]
+ else:
+ # FIXME: we're trying to access a sub-register, plain register
+ # numbers don't work for that. for now, just pass something that
+ # can be compared to 0 and probably will cause an error if misused.
+ # see https://bugs.libre-soc.org/show_bug.cgi?id=1221
+ self.namespace[regname] = regnum * 10000
if not self.is_svp64_mode or not self.pred_src_zero:
log('reading reg %s %s' % (name, str(regnum)), is_vec)
if name in fregs:
- reg_val = SelectableInt(self.fpr(base, is_vec, offs, ew_src))
- log("read reg %d/%d: 0x%x" % (base, offs, reg_val.value),
- kind=LogType.InstrInOuts)
+ fval = self.fpr(base, is_vec, offs, ew_src)
+ reg_val = SelectableInt(fval)
+ assert ew_src == XLEN, "TODO fix elwidth conversion"
self.trace("r:FPR:%d:%d:%d " % (base, offs, ew_src))
+ log("read fp reg %d/%d: 0x%x" % (base, offs, reg_val.value),
+ kind=LogType.InstrInOuts)
elif name is not None:
- reg_val = SelectableInt(self.gpr(base, is_vec, offs, ew_src))
+ gval = self.gpr(base, is_vec, offs, ew_src)
+ reg_val = SelectableInt(gval.value, bits=xlen)
self.trace("r:GPR:%d:%d:%d " % (base, offs, ew_src))
- log("read reg %d/%d: 0x%x" % (base, offs, reg_val.value),
+ log("read int reg %d/%d: 0x%x" % (base, offs, reg_val.value),
kind=LogType.InstrInOuts)
else:
log('zero input reg %s %s' % (name, str(regnum)), is_vec)
if name in fregs:
self.fpr.write(regnum, output, is_vec, ew_dst)
self.trace("w:FPR:%d:%d:%d " % (rnum, offset, ew_dst))
- else:
- self.gpr.write(regnum, output, is_vec, ew_dst)
- self.trace("w:GPR:%d:%d:%d " % (rnum, offset, ew_dst))
+ return
+
+ # LDST/Update does *not* allow elwidths on RA (Effective Address).
+ # this has to be detected, and overridden. see get_input (related)
+ sv_mode = yield self.dec2.rm_dec.sv_mode
+ is_ldst = (sv_mode in [SVMode.LDST_IDX.value, SVMode.LDST_IMM.value] \
+ and self.is_svp64_mode)
+ if is_ldst and name in ['EA', 'RA']:
+ op = self.dec2.dec.op
+ if hasattr(op, "upd"):
+ # update mode LD/ST uses read-reg A also as an output
+ upd = yield op.upd
+ log("write is_ldst is_update", sv_mode, is_ldst, upd)
+ if upd == LDSTMode.update.value:
+ ew_dst = 64 # override for RA (EA) to 64-bit
+
+ self.gpr.write(regnum, output, is_vec, ew_dst)
+ self.trace("w:GPR:%d:%d:%d " % (rnum, offset, ew_dst))
def check_step_increment(self, rc_en, asmop, ins_name):
# check if it is the SVSTATE.src/dest step that needs incrementing
vfirst = self.svstate.vfirst
log(" SV Vertical First", vf, vfirst)
if not vf and vfirst == 1:
- if insn_name.startswith("sv.bc"):
+ # SV Branch-Conditional required to be as-if-vector
+ # because there *is* no destination register
+ # (SV normally only terminates on 1st scalar reg written
+ # except in [slightly-misnamed] mapreduce mode)
+ if insn_name.startswith("sv.bc") or ffirst:
self.update_pc_next()
return False
self.update_nia()
sv_ptype = yield self.dec2.dec.op.SV_Ptype
out_vec = not (yield self.dec2.no_out_vec)
in_vec = not (yield self.dec2.no_in_vec)
+ rm_mode = yield self.dec2.rm_dec.mode
log(" svstate.vl", vl)
log(" svstate.mvl", mvl)
log(" rm.subvl", subvl)
log(" out_vec", out_vec)
log(" in_vec", in_vec)
log(" sv_ptype", sv_ptype, sv_ptype == SVPType.P2.value)
+ log(" rm_mode", rm_mode)
# 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']
svp64_is_vector = (out_vec or in_vec)
else:
svp64_is_vector = out_vec
+ # also if data-dependent fail-first is used, only in_vec is tested,
+ # allowing *scalar destinations* to be used as an accumulator.
+ # effectively this implies /mr (mapreduce mode) is 100% on with ddffirst
+ # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c16
+ if is_ffirst_mode(self.dec2):
+ svp64_is_vector = in_vec
+
# loops end at the first "hit" (source or dest)
yield from self.advance_svstate_steps()
loopend = self.loopend