class PC:
def __init__(self, pc_init=0):
self.CIA = SelectableInt(pc_init, 64)
- self.NIA = self.CIA + SelectableInt(4, 64)
+ self.NIA = self.CIA + SelectableInt(4, 64) # only true for v3.0B!
- def update(self, namespace):
+ def update_nia(self, is_svp64):
+ increment = 8 if is_svp64 else 4
+ self.NIA = self.CIA + SelectableInt(increment, 64)
+
+ def update(self, namespace, is_svp64):
+ """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
+ """
self.CIA = namespace['NIA'].narrow(64)
- self.NIA = self.CIA + SelectableInt(4, 64)
+ self.update_nia(is_svp64)
namespace['CIA'] = self.CIA
namespace['NIA'] = self.NIA
elif name == 'RT':
if out_sel == OutSel.RT.value:
return out, o_isvec
+ print ("get_pdecode_idx_out not found", name)
return None, False
# set up registers, instruction memory, data memory, PC, SPRs, MSR
self.svp64rm = SVP64RM()
- self.svstate = SVP64State(initial_svstate)
+ if isinstance(initial_svstate, int):
+ initial_svstate = SVP64State(initial_svstate)
+ self.svstate = initial_svstate
self.gpr = GPR(decoder2, self, self.svstate, regfile)
self.mem = Mem(row_bytes=8, initial_mem=initial_mem)
self.imem = Mem(row_bytes=4, initial_mem=initial_insns)
def set_pc(self, pc_val):
self.namespace['NIA'] = SelectableInt(pc_val, 64)
- self.pc.update(self.namespace)
+ self.pc.update(self.namespace, self.is_svp64_mode)
def setup_one(self):
"""set up one instruction
# SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
yield Settle()
opcode = yield self.dec2.dec.opcode_in
- pfx = SVP64PrefixFields()
+ pfx = SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
pfx.insn.value = opcode
major = pfx.major.asint(msb0=True) # MSB0 inversion
print ("prefix test: opcode:", major, bin(major),
self.is_svp64_mode = ((major == 0b000001) and
pfx.insn[7].value == 0b1 and
pfx.insn[9].value == 0b1)
+ self.pc.update_nia(self.is_svp64_mode)
if not self.is_svp64_mode:
return
# in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
print ("svp64.rm", bin(pfx.rm.asint(msb0=True)))
+ print (" svstate.vl", self.svstate.vl.asint(msb0=True))
+ print (" svstate.mvl", self.svstate.maxvl.asint(msb0=True))
sv_rm = pfx.rm.asint()
ins = self.imem.ld(pc+4, 4, False, True)
print(" svsetup: 0x%x 0x%x %s" % (pc+4, ins & 0xffffffff, bin(ins)))
opname = code.split(' ')[0]
yield from self.call(opname)
+ # don't use this except in special circumstances
if not self.respect_pc:
self.fake_pc += 4
+
print("execute one, CIA NIA", self.pc.CIA.value, self.pc.NIA.value)
def get_assembly_name(self):
if instr_is_privileged and self.msr[MSRb.PR] == 1:
self.TRAP(0x700, PIb.PRIV)
self.namespace['NIA'] = self.trap_nia
- self.pc.update(self.namespace)
+ self.pc.update(self.namespace, self.is_svp64_mode)
return
# check halted condition
print("illegal", name, asmop)
self.TRAP(0x700, PIb.ILLEG)
self.namespace['NIA'] = self.trap_nia
- self.pc.update(self.namespace)
+ self.pc.update(self.namespace, self.is_svp64_mode)
print("name %s != %s - calling ILLEGAL trap, PC: %x" %
(name, asmop, self.pc.CIA.value))
return
dest_cr, src_cr, src_byname, dest_byname = False, False, {}, {}
print ("sv rm", sv_rm, dest_cr, src_cr, src_byname, dest_byname)
+ # get SVSTATE srcstep. TODO: dststep (twin predication)
+ srcstep = self.svstate.srcstep.asint(msb0=True)
+
# main input registers (RT, RA ...)
inputs = []
for name in input_names:
# (mapping name RA RB RC RS to in1, in2, in3)
regnum, is_vec = yield from get_pdecode_idx_in(self.dec2, name)
if regnum is None:
+ # 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)
- #regnum = yield getattr(self.decoder, name)
+ # here's where we go "vector". TODO: zero-testing (RA_IS_ZERO)
+ if is_vec:
+ regnum += srcstep # TODO, elwidth overrides
+
+ # in case getting the register number is needed, _RA, _RB
regname = "_" + name
self.namespace[regname] = regnum
print('reading reg %s %d' % (name, regnum), is_vec)
if rc_en:
self.handle_comparison(results)
+ # svp64 loop can end early if the dest is scalar
+ svp64_dest_vector = False
+
# any modified return results?
if info.write_regs:
for name, output in zip(output_names, results):
if name == 'MSR':
print('msr written', hex(self.msr.value))
else:
- regnum = yield getattr(self.decoder, name)
- print('writing reg %d %s' % (regnum, str(output)))
+ regnum, is_vec = yield from get_pdecode_idx_out(self.dec2,
+ name)
+ if regnum is None:
+ # temporary hack for not having 2nd output
+ regnum = yield getattr(self.decoder, name)
+ is_vec = False
+ # here's where we go "vector".
+ if is_vec:
+ regnum += srcstep # TODO, elwidth overrides
+ svp64_dest_vector = True
+ print('writing reg %d %s' % (regnum, str(output)), is_vec)
if output.bits > 64:
output = SelectableInt(output.value, 64)
self.gpr[regnum] = output
- print("end of call", self.namespace['CIA'], self.namespace['NIA'])
+ # 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 self.is_svp64_mode:
+ # XXX twin predication TODO
+ vl = self.svstate.vl.asint(msb0=True)
+ mvl = self.svstate.maxvl.asint(msb0=True)
+ srcstep = self.svstate.srcstep.asint(msb0=True)
+ print (" svstate.vl", vl)
+ print (" svstate.mvl", mvl)
+ print (" svstate.srcstep", srcstep)
+ # check if srcstep needs incrementing by one, stop PC advancing
+ if svp64_dest_vector and srcstep != vl-1:
+ self.svstate.srcstep += SelectableInt(1, 7)
+ self.pc.NIA.value = self.pc.CIA.value
+ self.namespace['NIA'] = self.pc.NIA
+ print("end of sub-pc call", self.namespace['CIA'],
+ self.namespace['NIA'])
+ return # DO NOT allow PC to update whilst Sub-PC loop running
+ # reset to zero
+ self.svstate.srcstep[0:7] = 0
+ print (" svstate.srcstep loop end (PC to update)")
+ self.pc.update_nia(self.is_svp64_mode)
+ self.namespace['NIA'] = self.pc.NIA
+
# UPDATE program counter
- self.pc.update(self.namespace)
+ self.pc.update(self.namespace, self.is_svp64_mode)
+ print("end of call", self.namespace['CIA'], self.namespace['NIA'])
def inject():