+class StepLoop:
+ """deals with svstate looping.
+ """
+
+ def __init__(self, svstate):
+ self.svstate = svstate
+ self.new_iterators()
+
+ def new_iterators(self):
+ self.src_it = self.src_iterator()
+ self.dst_it = self.dst_iterator()
+ self.loopend = False
+ self.new_srcstep = 0
+ self.new_dststep = 0
+ self.new_ssubstep = 0
+ self.new_dsubstep = 0
+ self.pred_dst_zero = 0
+ self.pred_src_zero = 0
+
+ def src_iterator(self):
+ """source-stepping iterator
+ """
+ pack = self.svstate.pack
+
+ # source step
+ if pack:
+ # pack advances subvl in *outer* loop
+ 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)
+ # but they *can* be done as while-loops as long as every SVSTATE
+ # "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
+ 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 # 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
+ self.loopend = True
+ return
+ self.svstate.srcstep += SelectableInt(1, 7) # advance srcstep
+
+ def dst_iterator(self):
+ """dest-stepping iterator
+ """
+ unpack = self.svstate.unpack
+
+ # dest step
+ if unpack:
+ # pack advances subvl in *outer* loop
+ 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)
+ # but they *can* be done as while-loops as long as every SVSTATE
+ # "thing" is re-read every single time a yield gives indices
+ while True: # outer vl loop
+ while True: # inner subvl loop
+ 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, self.svstate.vl,
+ self.svstate.dsubstep, subvl)
+ # yield actual substep/dststep
+ yield (self.svstate.dsubstep, dststep)
+ if self.svstate.dsubstep == subvl: # end-point
+ 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
+ return
+ self.svstate.dststep += SelectableInt(1, 7) # advance dststep
+
+ def src_iterate(self):
+ """source-stepping iterator
+ """
+ subvl = self.subvl
+ vl = self.svstate.vl
+ pack = self.svstate.pack
+ unpack = self.svstate.unpack
+ ssubstep = self.svstate.ssubstep
+ end_ssub = ssubstep == subvl
+ end_src = self.svstate.srcstep == vl-1
+ log(" pack/unpack/subvl", pack, unpack, subvl,
+ "end", end_src,
+ "sub", end_ssub)
+ # first source step
+ srcstep = self.svstate.srcstep
+ srcmask = self.srcmask
+ if pack:
+ # pack advances subvl in *outer* loop
+ while True:
+ assert srcstep <= vl-1
+ end_src = srcstep == vl-1
+ if end_src:
+ if end_ssub:
+ self.loopend = True
+ else:
+ self.svstate.ssubstep += SelectableInt(1, 2)
+ srcstep = 0 # reset
+ break
+ else:
+ srcstep += 1 # advance srcstep
+ if not self.srcstep_skip:
+ break
+ if ((1 << srcstep) & srcmask) != 0:
+ break
+ else:
+ log(" sskip", bin(srcmask), bin(1 << srcstep))
+ else:
+ # advance subvl in *inner* loop
+ if end_ssub:
+ while True:
+ assert srcstep <= vl-1
+ end_src = srcstep == vl-1
+ if end_src: # end-point
+ self.loopend = True
+ srcstep = 0
+ break
+ else:
+ srcstep += 1
+ if not self.srcstep_skip:
+ break
+ if ((1 << srcstep) & srcmask) != 0:
+ break
+ else:
+ log(" sskip", bin(srcmask), bin(1 << srcstep))
+ self.svstate.ssubstep = SelectableInt(0, 2) # reset
+ else:
+ # advance ssubstep
+ self.svstate.ssubstep += SelectableInt(1, 2)
+
+ self.svstate.srcstep = SelectableInt(srcstep, 7)
+ log(" advance src", self.svstate.srcstep, self.svstate.ssubstep,
+ self.loopend)
+
+ def dst_iterate(self):
+ """dest step iterator
+ """
+ vl = self.svstate.vl
+ subvl = self.subvl
+ pack = self.svstate.pack
+ unpack = self.svstate.unpack
+ dsubstep = self.svstate.dsubstep
+ end_dsub = dsubstep == subvl
+ dststep = self.svstate.dststep
+ end_dst = dststep == vl-1
+ dstmask = self.dstmask
+ log(" pack/unpack/subvl", pack, unpack, subvl,
+ "end", end_dst,
+ "sub", end_dsub)
+ # now dest step
+ if unpack:
+ # unpack advances subvl in *outer* loop
+ while True:
+ assert dststep <= vl-1
+ end_dst = dststep == vl-1
+ if end_dst:
+ if end_dsub:
+ self.loopend = True
+ else:
+ self.svstate.dsubstep += SelectableInt(1, 2)
+ dststep = 0 # reset
+ break
+ else:
+ dststep += 1 # advance dststep
+ if not self.dststep_skip:
+ break
+ if ((1 << dststep) & dstmask) != 0:
+ break
+ else:
+ log(" dskip", bin(dstmask), bin(1 << dststep))
+ else:
+ # advance subvl in *inner* loop
+ if end_dsub:
+ while True:
+ assert dststep <= vl-1
+ end_dst = dststep == vl-1
+ if end_dst: # end-point
+ self.loopend = True
+ dststep = 0
+ break
+ else:
+ dststep += 1
+ if not self.dststep_skip:
+ break
+ if ((1 << dststep) & dstmask) != 0:
+ break
+ else:
+ log(" dskip", bin(dstmask), bin(1 << dststep))
+ self.svstate.dsubstep = SelectableInt(0, 2) # reset
+ else:
+ # advance ssubstep
+ self.svstate.dsubstep += SelectableInt(1, 2)
+
+ self.svstate.dststep = SelectableInt(dststep, 7)
+ log(" advance dst", self.svstate.dststep, self.svstate.dsubstep,
+ self.loopend)
+
+ def at_loopend(self):
+ """tells if this is the last possible element. uses the cached values
+ for src/dst-step and sub-steps
+ """
+ subvl = self.subvl
+ vl = self.svstate.vl
+ srcstep, dststep = self.new_srcstep, self.new_dststep
+ ssubstep, dsubstep = self.new_ssubstep, self.new_dsubstep
+ end_ssub = ssubstep == subvl
+ end_dsub = dsubstep == subvl
+ if srcstep == vl-1 and end_ssub:
+ return True
+ if dststep == vl-1 and end_dsub:
+ return True
+ return False
+
+ def advance_svstate_steps(self):
+ """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
+ TODO when Pack/Unpack is set, substep becomes the *outer* loop
+ """
+ self.subvl = yield self.dec2.rm_dec.rm_in.subvl
+ if self.loopend: # huhn??
+ return
+ self.src_iterate()
+ self.dst_iterate()
+
+ def read_src_mask(self):
+ """read/update pred_sz and src mask
+ """
+ # get SVSTATE VL (oh and print out some debug stuff)
+ vl = self.svstate.vl
+ srcstep = self.svstate.srcstep
+ ssubstep = self.svstate.ssubstep
+
+ # get predicate mask (all 64 bits)
+ srcmask = 0xffff_ffff_ffff_ffff
+
+ pmode = yield self.dec2.rm_dec.predmode
+ sv_ptype = yield self.dec2.dec.op.SV_Ptype
+ srcpred = yield self.dec2.rm_dec.srcpred
+ dstpred = yield self.dec2.rm_dec.dstpred
+ pred_sz = yield self.dec2.rm_dec.pred_sz
+ if pmode == SVP64PredMode.INT.value:
+ srcmask = dstmask = get_predint(self.gpr, dstpred)
+ if sv_ptype == SVPType.P2.value:
+ srcmask = get_predint(self.gpr, srcpred)
+ elif pmode == SVP64PredMode.CR.value:
+ srcmask = dstmask = get_predcr(self.crl, dstpred, vl)
+ if sv_ptype == SVPType.P2.value:
+ srcmask = get_predcr(self.crl, srcpred, vl)
+ # work out if the ssubsteps are completed
+ ssubstart = ssubstep == 0
+ log(" pmode", pmode)
+ log(" ptype", sv_ptype)
+ log(" srcpred", bin(srcpred))
+ log(" srcmask", bin(srcmask))
+ log(" pred_sz", bin(pred_sz))
+ log(" ssubstart", ssubstart)
+
+ # store all that above
+ self.srcstep_skip = False
+ self.srcmask = srcmask
+ self.pred_sz = pred_sz
+ self.new_ssubstep = ssubstep
+ log(" new ssubstep", ssubstep)
+ # until the predicate mask has a "1" bit... or we run out of VL
+ # let srcstep==VL be the indicator to move to next instruction
+ if not pred_sz:
+ self.srcstep_skip = True
+
+ def read_dst_mask(self):
+ """same as read_src_mask - check and record everything needed
+ """
+ # get SVSTATE VL (oh and print out some debug stuff)
+ # yield Delay(1e-10) # make changes visible
+ vl = self.svstate.vl
+ dststep = self.svstate.dststep
+ dsubstep = self.svstate.dsubstep
+
+ # get predicate mask (all 64 bits)
+ dstmask = 0xffff_ffff_ffff_ffff
+
+ pmode = yield self.dec2.rm_dec.predmode
+ reverse_gear = yield self.dec2.rm_dec.reverse_gear
+ sv_ptype = yield self.dec2.dec.op.SV_Ptype
+ dstpred = yield self.dec2.rm_dec.dstpred
+ pred_dz = yield self.dec2.rm_dec.pred_dz
+ if pmode == SVP64PredMode.INT.value:
+ dstmask = get_predint(self.gpr, dstpred)
+ elif pmode == SVP64PredMode.CR.value:
+ dstmask = get_predcr(self.crl, dstpred, vl)
+ # work out if the ssubsteps are completed
+ dsubstart = dsubstep == 0
+ log(" pmode", pmode)
+ log(" ptype", sv_ptype)
+ log(" dstpred", bin(dstpred))
+ log(" dstmask", bin(dstmask))
+ log(" pred_dz", bin(pred_dz))
+ log(" dsubstart", dsubstart)
+
+ self.dststep_skip = False
+ self.dstmask = dstmask
+ self.pred_dz = pred_dz
+ self.new_dsubstep = dsubstep
+ log(" new dsubstep", dsubstep)
+ if not pred_dz:
+ self.dststep_skip = True
+
+ def svstate_pre_inc(self):
+ """check if srcstep/dststep need to skip over masked-out predicate bits
+ note that this is not supposed to do anything to substep,
+ it is purely for skipping masked-out bits
+ """
+
+ self.subvl = yield self.dec2.rm_dec.rm_in.subvl
+ yield from self.read_src_mask()
+ yield from self.read_dst_mask()
+
+ self.skip_src()
+ self.skip_dst()
+
+ def skip_src(self):
+
+ srcstep = self.svstate.srcstep
+ srcmask = self.srcmask
+ pred_src_zero = self.pred_sz
+ vl = self.svstate.vl
+ # srcstep-skipping opportunity identified
+ if self.srcstep_skip:
+ # cannot do this with sv.bc - XXX TODO
+ if srcmask == 0:
+ self.loopend = True
+ while (((1 << srcstep) & srcmask) == 0) and (srcstep != vl):
+ log(" sskip", bin(1 << srcstep))
+ srcstep += 1
+
+ # now work out if the relevant mask bits require zeroing
+ if pred_src_zero:
+ pred_src_zero = ((1 << srcstep) & srcmask) == 0
+
+ # store new srcstep / dststep
+ self.new_srcstep = srcstep
+ self.pred_src_zero = pred_src_zero
+ log(" new srcstep", srcstep)
+
+ def skip_dst(self):
+ # dststep-skipping opportunity identified
+ dststep = self.svstate.dststep
+ dstmask = self.dstmask
+ pred_dst_zero = self.pred_dz
+ vl = self.svstate.vl
+ if self.dststep_skip:
+ # cannot do this with sv.bc - XXX TODO
+ if dstmask == 0:
+ self.loopend = True
+ while (((1 << dststep) & dstmask) == 0) and (dststep != vl):
+ log(" dskip", bin(1 << dststep))
+ dststep += 1
+
+ # now work out if the relevant mask bits require zeroing
+ if pred_dst_zero:
+ pred_dst_zero = ((1 << dststep) & dstmask) == 0
+
+ # store new srcstep / dststep
+ self.new_dststep = dststep
+ self.pred_dst_zero = pred_dst_zero
+ log(" new dststep", dststep)
+
+
+class ExitSyscallCalled(Exception):
+ pass
+
+
+class SyscallEmulator(openpower.syscalls.Dispatcher):
+ def __init__(self, isacaller):
+ self.__isacaller = isacaller
+
+ host = os.uname().machine
+ bits = (64 if (sys.maxsize > (2**32)) else 32)
+ host = openpower.syscalls.architecture(arch=host, bits=bits)
+
+ return super().__init__(guest="ppc64", host=host)
+
+ def __call__(self, identifier, *arguments):
+ (identifier, *arguments) = map(int, (identifier, *arguments))
+ return super().__call__(identifier, *arguments)
+
+ def sys_exit_group(self, status, *rest):
+ self.__isacaller.halted = True
+ raise ExitSyscallCalled(status)
+
+ def sys_write(self, fd, buf, count, *rest):
+ buf = self.__isacaller.mem.get_ctypes(buf, count, is_write=False)
+ try:
+ return os.write(fd, buf)
+ except OSError as e:
+ return -e.errno
+
+
+class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):