lbzu,2P,EXTRA2,d:RT,d:RA,s:RA,0,RA_OR_ZERO,0,0,RT,0,0,RA
lhzu,2P,EXTRA2,d:RT,d:RA,s:RA,0,RA_OR_ZERO,0,0,RT,0,0,RA
lhau,2P,EXTRA2,d:RT,d:RA,s:RA,0,RA_OR_ZERO,0,0,RT,0,0,RA
-lfsu,2P,EXTRA2,d:FRT,d:RA,s:RA,0,RA_OR_ZERO,0,0,FRT,0,0,RA
-lfdu,2P,EXTRA2,d:FRT,d:RA,s:RA,0,RA_OR_ZERO,0,0,FRT,0,0,RA
+lfsu,2P,EXTRA2,d:FRT,d:RA,s:RA,0,RA,0,0,FRT,0,0,RA
+lfdu,2P,EXTRA2,d:FRT,d:RA,s:RA,0,RA,0,0,FRT,0,0,RA
ldu,2P,EXTRA2,d:RT,d:RA,s:RA,0,RA_OR_ZERO,0,0,RT,0,0,RA
stwu,2P,EXTRA2,d:RA,s:RS,s:RA,0,RA_OR_ZERO,0,RS,0,0,0,RA
stbu,2P,EXTRA2,d:RA,s:RS,s:RA,0,RA_OR_ZERO,0,RS,0,0,0,RA
sthu,2P,EXTRA2,d:RA,s:RS,s:RA,0,RA_OR_ZERO,0,RS,0,0,0,RA
-stfsu,2P,EXTRA2,d:RA,s:FRS,s:RA,0,RA_OR_ZERO,0,FRS,0,0,0,RA
-stfdu,2P,EXTRA2,d:RA,s:FRS,s:RA,0,RA_OR_ZERO,0,FRS,0,0,0,RA
+stfsu,2P,EXTRA2,d:RA,s:FRS,s:RA,0,RA,0,FRS,0,0,0,RA
+stfdu,2P,EXTRA2,d:RA,s:FRS,s:RA,0,RA,0,FRS,0,0,0,RA
stdu,2P,EXTRA2,d:RA,s:RS,s:RA,0,RA_OR_ZERO,0,RS,0,0,0,RA
ldux,2P,EXTRA2,d:RT,d:RA,s:RB,0,RA_OR_ZERO,RB,0,RT,0,0,RA
lwzux,2P,EXTRA2,d:RT,d:RA,s:RB,0,RA_OR_ZERO,RB,0,RT,0,0,RA
lhzux,2P,EXTRA2,d:RT,d:RA,s:RB,0,RA_OR_ZERO,RB,0,RT,0,0,RA
lwaux,2P,EXTRA2,d:RT,d:RA,s:RB,0,RA_OR_ZERO,RB,0,RT,0,0,RA
lhaux,2P,EXTRA2,d:RT,d:RA,s:RB,0,RA_OR_ZERO,RB,0,RT,0,0,RA
-lfsux,2P,EXTRA2,d:FRT,d:RA,s:RB,0,RA_OR_ZERO,RB,0,FRT,0,0,RA
-lfdux,2P,EXTRA2,d:FRT,d:RA,s:RB,0,RA_OR_ZERO,RB,0,FRT,0,0,RA
+lfsux,2P,EXTRA2,d:FRT,d:RA,s:RB,0,RA,RB,0,FRT,0,0,RA
+lfdux,2P,EXTRA2,d:FRT,d:RA,s:RB,0,RA,RB,0,FRT,0,0,RA
stdux,2P,EXTRA2,d:RA,s:RSs:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,RA
stwux,2P,EXTRA2,d:RA,s:RSs:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,RA
stbux,2P,EXTRA2,d:RA,s:RSs:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,RA
sthux,2P,EXTRA2,d:RA,s:RSs:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,RA
-stfsux,2P,EXTRA2,d:RA,s:FRSs:RA,s:RB,0,RA_OR_ZERO,RB,FRS,0,0,0,RA
-stfdux,2P,EXTRA2,d:RA,s:FRSs:RA,s:RB,0,RA_OR_ZERO,RB,FRS,0,0,0,RA
+stfsux,2P,EXTRA2,d:RA,s:FRSs:RA,s:RB,0,RA,RB,FRS,0,0,0,RA
+stfdux,2P,EXTRA2,d:RA,s:FRSs:RA,s:RB,0,RA,RB,FRS,0,0,0,RA
sthx,2P,EXTRA2,s:RS,s:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,0
stdbrx,2P,EXTRA2,s:RS,s:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,0
stwbrx,2P,EXTRA2,s:RS,s:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,0
-stfsx,2P,EXTRA2,s:FRS,s:RA,s:RB,0,RA_OR_ZERO,RB,FRS,0,0,0,0
+stfsx,2P,EXTRA2,s:FRS,s:RA,s:RB,0,RA,RB,FRS,0,0,0,0
stfdx,2P,EXTRA2,s:FRS,s:RA,s:RB,0,RA_OR_ZERO,RB,FRS,0,0,0,0
stwcix,2P,EXTRA2,s:RS,s:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,0
sthbrx,2P,EXTRA2,s:RS,s:RA,s:RB,0,RA_OR_ZERO,RB,RS,0,0,0,0
selectconcat)
from openpower.decoder.power_enums import (spr_dict, spr_byname, XER_bits,
insns, MicrOp, In1Sel, In2Sel, In3Sel,
- OutSel, CROutSel,
+ OutSel, CROutSel, LDSTMode,
SVP64RMMode, SVP64PredMode,
SVP64PredInt, SVP64PredCR)
OutSel.FRT.value, out, o_isvec)
if out_sel == OutSel.FRT.value:
return out, o_isvec
- print ("get_pdecode_idx_out not found", name)
+ print ("get_pdecode_idx_out not found", name, out_sel, out, o_isvec)
return None, False
-# XXX TODO
def get_pdecode_idx_out2(dec2, name):
+ # check first if register is activated for write
+ out_ok = yield dec2.e.write_ea.ok
+ if not out_ok:
+ return None, False
+
op = dec2.dec.op
- print ("TODO: get_pdecode_idx_out2", name)
+ out_sel = yield op.out_sel
+ out = yield dec2.e.write_ea.data
+ o_isvec = yield dec2.o2_isvec
+ print ("get_pdecode_idx_out2", name, out_sel, out, o_isvec)
+ if name == 'RA':
+ if hasattr(op, "upd"):
+ # update mode LD/ST uses read-reg A also as an output
+ upd = yield op.upd
+ print ("get_pdecode_idx_out2", upd, LDSTMode.update.value,
+ out_sel, OutSel.RA.value,
+ out, o_isvec)
+ if upd == LDSTMode.update.value:
+ return out, o_isvec
return None, False
# doing this is not part of svp64, it's because output
# registers, to be modified, need to be in the namespace.
regnum, is_vec = yield from get_pdecode_idx_out(self.dec2, name)
+ if regnum is None:
+ regnum, is_vec = yield from get_pdecode_idx_out2(self.dec2,
+ name)
# in case getting the register number is needed, _RA, _RB
regname = "_" + name
else:
regnum, is_vec = yield from get_pdecode_idx_out(self.dec2,
name)
+ if regnum is None:
+ regnum, is_vec = yield from get_pdecode_idx_out2(
+ self.dec2, name)
if regnum is None:
# temporary hack for not having 2nd output
regnum = yield getattr(self.decoder, name)
for i in range(32):
self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64))
- def test_sv_fpload(self):
+ def tst_sv_fpload(self):
""">>> lst = ["sv.lfsx 2.v, 0, 0.v"
]
"""
self.assertEqual(sim.fpr(2), SelectableInt(0x4040266660000000, 64))
self.assertEqual(sim.fpr(3), SelectableInt(0xC004000000000000, 64))
- def test_sv_fpadd(self):
+ def test_fp_single_ldst(self):
+ """>>> lst = ["sv.lfsx 0.v, 0, 2.v", # load fp 1/2 from mem 0/8
+ "sv.stfsu 0.v, 16(4.v)", # store fp 1/2, update RA *twice*
+ "sv.lfs 3.v, 0(4.v)", # re-load from UPDATED r4/r5
+ ]
+ """
+ lst = SVP64Asm(["sv.lfsx 0.v, 0, 4.v",
+ "sv.stfsu 0.v, 16(4.v)",
+ "sv.lfs 3.v, 0(4.v)",
+ ])
+ lst = list(lst)
+
+ # SVSTATE (in this case, VL=2)
+ svstate = SVP64State()
+ svstate.vl[0:7] = 2 # VL
+ svstate.maxvl[0:7] = 2 # MAXVL
+ print ("SVSTATE", bin(svstate.spr.asint()))
+
+ # memory addresses 0x0000 and 0x0008
+ initial_mem = {0x0000: (0x42013333, 8), # 32.3
+ 0x0008: (0xC0200000, 8), # -2.5
+ 0x0020: (0x1828384822324252, 8),
+ }
+
+ # and RB will move on from 0 for first iteration to 1 in 2nd
+ # therefore we must point GPR(4) at initial mem 0x0000
+ # and GPR(5) at initial mem 0x0008
+ initial_regs = [0] * 32
+ initial_regs[4] = 0x0000 # points at memory address 0x0000 (element 0)
+ initial_regs[5] = 0x0008 # points at memory address 0x0008 (element 1)
+
+ with Program(lst, bigendian=False) as program:
+ sim = self.run_tst_program(program, initial_regs,
+ svstate=svstate,
+ initial_mem=initial_mem)
+ print("FPR 1", sim.fpr(0))
+ print("FPR 2", sim.fpr(1))
+ print("GPR 1", sim.gpr(4)) # should be 0x10 due to update
+ print("GPR 2", sim.gpr(5)) # should be 0x18 due to update
+ self.assertEqual(sim.gpr(4), SelectableInt(0x10, 64))
+ self.assertEqual(sim.gpr(5), SelectableInt(0x18, 64))
+ self.assertEqual(sim.fpr(0), SelectableInt(0x4040266660000000, 64))
+ self.assertEqual(sim.fpr(1), SelectableInt(0xC004000000000000, 64))
+ self.assertEqual(sim.fpr(3), SelectableInt(0x4040266660000000, 64))
+ self.assertEqual(sim.fpr(4), SelectableInt(0xC004000000000000, 64))
+
+
+ def tst_sv_fpadd(self):
""">>> lst = ["sv.fadds 6.v, 2.v, 4.v"
]
"""
return "FPR"
-def decode_extra(rm, prefix='', verbose=False):
+def decode_extra(rm, prefix='', verbose=True):
# first turn the svp64 rm into a "by name" dict, recording
# which position in the RM EXTRA it goes into
# also: record if the src or dest was a CR, for sanity-checking
dest_reg_cr, src_reg_cr = False, False
svp64_srcreg_byname = {}
svp64_destreg_byname = {}
+ if verbose:
+ print ("decode_extra RM", rm)
for i in range(4):
- if verbose:
- print (rm)
rfield = rm[prefix+str(i)]
if not rfield or rfield == '0':
continue
def __init__(self, lst, bigendian=False):
self.lst = lst
self.trans = self.translate(lst)
- self.verbose = False
assert bigendian == False, "error, bigendian not supported yet"
def __iter__(self):
# now find opcode fields
fields = ''.join(ls[1:]).split(',')
fields = list(map(str.strip, fields))
- if self.verbose:
- print ("opcode, fields", ls, opcode, fields)
+ print ("opcode, fields", ls, opcode, fields)
# sigh have to do setvl here manually for now...
if opcode in ["setvl", "setvl."]:
insn |= 0b00000 << (31-30) # XO , bits 26..30
if opcode == 'setvl.':
insn |= 1 << (31-31) # Rc=1 , bit 31
- if self.verbose:
- print ("setvl", bin(insn))
+ print ("setvl", bin(insn))
yield ".long 0x%x" % insn
continue
(v30b_op, insn))
v30b_regs = isa.instr[v30b_op].regs[0] # get regs info "RT, RA, RB"
rm = svp64.instrs[v30b_op] # one row of the svp64 RM CSV
- if self.verbose:
- print ("v3.0B op", v30b_op, "Rc=1" if rc_mode else '')
- print ("v3.0B regs", opcode, v30b_regs)
- print (rm)
+ print ("v3.0B op", v30b_op, "Rc=1" if rc_mode else '')
+ print ("v3.0B regs", opcode, v30b_regs)
+ print ("RM", rm)
# right. the first thing to do is identify the ordering of
# the registers, by name. the EXTRA2/3 ordering is in
# (elwidth overrides on CRs are banned)
decode = decode_extra(rm)
dest_reg_cr, src_reg_cr, svp64_src, svp64_dest = decode
- svp64_reg_byname = {}
- svp64_reg_byname.update(svp64_src)
- svp64_reg_byname.update(svp64_dest)
- if self.verbose:
- print ("EXTRA field index, by regname", svp64_reg_byname)
+ print ("EXTRA field index, src", svp64_src)
+ print ("EXTRA field index, dest", svp64_dest)
# okaaay now we identify the field value (opcode N,N,N) with
# the pseudo-code info (opcode RT, RA, RB)
extras = OrderedDict()
for idx, (field, regname) in enumerate(opregfields):
imm, regname = decode_imm(regname)
- extra = svp64_reg_byname.get(regname, None)
rtype = get_regtype(regname)
- extras[extra] = (idx, field, regname, rtype, imm)
- if self.verbose:
- print (" ", extra, extras[extra])
+ print (" idx find", idx, field, regname, imm)
+ extra = svp64_src.get(regname, None)
+ if extra is not None:
+ extra = ('s', extra, False)
+ extras[extra] = (idx, field, regname, rtype, imm)
+ print (" idx src", idx, extra, extras[extra])
+ dextra = svp64_dest.get(regname, None)
+ print ("regname in", regname, dextra)
+ if dextra is not None:
+ dextra = ('d', dextra, extra is not None)
+ extras[dextra] = (idx, field, regname, rtype, imm)
+ print (" idx dst", idx, extra, extras[dextra])
# great! got the extra fields in their associated positions:
# also we know the register type. now to create the EXTRA encodings
immed, field = field[:-1].split("(")
field, regmode = decode_reg(field)
- if self.verbose:
- print (" ", extra_idx, rname, rtype,
- regmode, iname, field, end=" ")
+ print (" ", extra_idx, rname, rtype,
+ regmode, iname, field, end=" ")
# see Mode field https://libre-soc.org/openpower/sv/svp64/
# XXX TODO: the following is a bit of a laborious repeated
else:
# range is r0-r127 in increments of 4
assert sv_extra & 0b01 == 0, \
- "vector field %s cannot fit into EXTRA2 %s" % \
- (rname, str(extras[extra_idx]))
+ "%s: vector field %s cannot fit " \
+ "into EXTRA2 %s" % \
+ (insn, rname, str(extras[extra_idx]))
# all good: encode as vector (bit 2 set)
sv_extra = 0b10 | (sv_extra >> 1)
elif regmode == 'vector':
field = (field << 2) | cr_subfield
# capture the extra field info
- if self.verbose:
- print ("=>", "%5s" % bin(sv_extra), field)
+ print ("=>", "%5s" % bin(sv_extra), field)
extras[extra_idx] = sv_extra
# append altered field value to v3.0b, differs for LDST
+ srcdest, idx, duplicate = extra_idx
+ if duplicate: # skip adding to v3.0b fields, already added
+ continue
if ldst_imm:
v30b_newfields.append(("%s(%s)" % (immed, str(field))))
else:
v30b_newfields.append(str(field))
- if self.verbose:
- print ("new v3.0B fields", v30b_op, v30b_newfields)
- print ("extras", extras)
+ print ("new v3.0B fields", v30b_op, v30b_newfields)
+ print ("extras", extras)
# rright. now we have all the info. start creating SVP64 RM
svp64_rm = SVP64RMFields()
# begin with EXTRA fields
for idx, sv_extra in extras.items():
if idx is None: continue
+ print (idx)
+ srcdest, idx, duplicate = idx
if etype == 'EXTRA2':
svp64_rm.extra2[idx].eq(
SelectableInt(sv_extra, SVP64RM_EXTRA2_SPEC_SIZE))
# nice debug printout. (and now for something completely different)
# https://youtu.be/u0WOIwlXE9g?t=146
svp64_rm_value = svp64_rm.spr.value
- if self.verbose:
- print ("svp64_rm", hex(svp64_rm_value), bin(svp64_rm_value))
- print (" mmode 0 :", bin(mmode))
- print (" pmask 1-3 :", bin(pmask))
- print (" dstwid 4-5 :", bin(destwid))
- print (" srcwid 6-7 :", bin(srcwid))
- print (" subvl 8-9 :", bin(subvl))
- print (" mode 19-23:", bin(mode))
+ print ("svp64_rm", hex(svp64_rm_value), bin(svp64_rm_value))
+ print (" mmode 0 :", bin(mmode))
+ print (" pmask 1-3 :", bin(pmask))
+ print (" dstwid 4-5 :", bin(destwid))
+ print (" srcwid 6-7 :", bin(srcwid))
+ print (" subvl 8-9 :", bin(subvl))
+ print (" mode 19-23:", bin(mode))
offs = 2 if etype == 'EXTRA2' else 3 # 2 or 3 bits
for idx, sv_extra in extras.items():
if idx is None: continue
+ srcdest, idx, duplicate = idx
start = (10+idx*offs)
end = start + offs-1
- if self.verbose:
- print (" extra%d %2d-%2d:" % (idx, start, end),
- bin(sv_extra))
+ print (" extra%d %2d-%2d:" % (idx, start, end),
+ bin(sv_extra))
if ptype == '2P':
- if self.verbose:
- print (" smask 16-17:", bin(smask))
- if self.verbose:
- print ()
+ print (" smask 16-17:", bin(smask))
+ print ()
# first, construct the prefix from its subfields
svp64_prefix = SVP64PrefixFields()
rc = '.' if rc_mode else ''
yield ".long 0x%x" % svp64_prefix.insn.value
yield "%s %s" % (v30b_op+rc, ", ".join(v30b_newfields))
- if self.verbose:
- print ("new v3.0B fields", v30b_op, v30b_newfields)
+ print ("new v3.0B fields", v30b_op, v30b_newfields)
if __name__ == '__main__':
lst = ['slw 3, 1, 4',
'sv.ld 5.v, 4(1.v)',
'setvl. 2, 3, 4, 1, 1',
]
+ lst = [
+ "sv.stfsu 0.v, 16(4.v)",
+ ]
isa = SVP64Asm(lst)
print ("list", list(isa))
csvs = SVP64RM()