def set_reg(self, reg, expr, name): assert self.finalop is None if isinstance(reg, (IsaReg, IsaVisibleReg)): val = self.make_temp(expr, name, reg.dmask) if reg in self.inregs and reg not in self.regs and self.inregs[ reg] == val: pass elif reg in self.regs and self.regs[reg] == val: pass else: if isinstance(reg, IsaVisibleReg): self.ops.append(DecopWrite(reg, self.encap(val))) self.regs[reg] = val elif isinstance(reg, IsaSplitReg): for start, len_, field in reg.fields: if isinstance(field, int): pass else: self.set_reg(field, expr >> start & bflmask(len_), name + '_' + field.name) elif isinstance(reg, IsaSubReg): mask = bflmask(reg.len_) << reg.start res = (self.get_reg(reg.reg) & ~mask) | (expr << reg.start & mask) self.set_reg(reg.reg, res, name) else: raise DecodeError("unk reg")
def emit_not(self, size, dst, src): size = 8 << size res = src ^ bflmask(size) self.block.set_reg(dst, res, self.name) self.block.set_reg(self.isa.of, ExprConst(0), self.name + '_of') self.block.set_reg(self.isa.sf, res >> (size - 1), self.name + '_sf') self.block.set_reg(self.isa.zf, ExprEq(res, 0), self.name + '_zf')
def emit_ld(self, name, space, sz, addr): #addr = self.make_temp(addr, name + '_addr', space.amask) res = TempVar(name + '_data', bflmask(space.bsz * sz)) self.locals.add(res) #self.ops.append(DecopLd(space, sz, res, self.encap(addr))) self.ops.append(DecopLd(space, sz, res, addr)) return self.encap(res)
def get_reg(self, reg): assert self.finalop is None if isinstance(reg, (IsaReg, IsaVisibleReg)): if reg in self.regs: return self.encap(self.regs[reg]) elif reg not in self.inregs: val = InVar(self.name + '_in_' + reg.name, reg.mask) self.locals.add(val) self.inregs[reg] = val return self.encap(val) else: return self.encap(self.inregs[reg]) elif isinstance(reg, IsaSplitReg): res = ExprConst(0) for start, len_, field in reg.fields: if isinstance(field, int): res |= field << start else: res |= self.get_reg(field) << start return res elif isinstance(reg, IsaSubReg): res = self.get_reg(reg.reg) res >>= reg.start res &= bflmask(reg.len_) return res else: raise DecodeError("unk reg")
def findlivemasks(self, vars_, mask): for bf in self.bitfields: imask = shl(mask & bf.mask, -bf.shift) if bf.sign is not None: if imask & -1 << bf.sign: imask |= 1 << bf.sign imask &= bflmask(bf.sign + 1) bf.expr.findlivemasks(vars_, imask)
def __init__(self, name, fields): self.name = name self.mask = 0 self.dmask = 0 self.fields = fields for start, len_, field in fields: mask = bflmask(len_) << start if isinstance(field, (IsaReg, IsaVisibleReg)): self.dmask |= mask self.mask |= mask elif isinstance(field, int): self.mask |= field << start else: raise TypeError("Unknown field type")
def _add(self, expr, sign, shift, mask): if sign is not None and not (mask & shl(-1, shift + sign + 1)): sign = None if not mask: return imask = shl(mask, -shift) if sign is not None: if imask & -1 << sign: imask |= 1 << sign imask &= bflmask(sign + 1) if isinstance(expr, ExprBigOr): self._add(ExprConst(expr.const), sign, shift, mask) for sexpr, ssign, sshift, smask in expr.bitfields: self._add( sexpr, *self._reduce(ssign, sshift, smask, sign, shift, mask)) return if isinstance(expr, ExprAnd): e1 = expr.e1.mask(imask) e2 = expr.e2.mask(imask) if isinstance(e1, ExprConst): e2, e1 = e1, e2 if isinstance(e2, ExprConst): self._add(e1, *self._reduce(None, 0, e2.val, sign, shift, mask)) return if isinstance(expr, ExprOr): self._add(expr.e1, sign, shift, mask) self._add(expr.e2, sign, shift, mask) return if isinstance(expr, ExprConst): val = shl(sext(expr.val, sign), shift) & mask self.const |= val self.bmask |= val return if isinstance(expr, ExprShl) and isinstance(expr.e2, ExprConst): self._add(expr.e1, *self._reduce(None, expr.e2.val, -1, sign, shift, mask)) return if isinstance(expr, ExprSext) and isinstance(expr.e2, ExprConst): self._add(expr.e1, *self._reduce(expr.e2.val, 0, -1, sign, shift, mask)) return expr = expr.mask(imask) if not expr.bmask & imask: return self.bmask |= shl(sext(expr.bmask, sign), shift) & mask self.bitfields.append(Bitfield(expr, sign, shift, mask))
def emit_add(self, size, dst, src1, src2, subop): size = 8 << size s2 = src2 if subop in [1, 3]: s2 += self.isa.cf if subop in [2, 3]: s2 = -src2 res = src1 + s2 if dst is not None: self.block.set_reg(dst, res, self.name) self.block.set_reg(self.isa.cf, res >> size, self.name + '_cf') sign = self.block.encap(self.block.make_temp(res >> (size - 1), self.name + '_sign', 1)) self.block.set_reg(self.isa.of, sign ^ ExprLt(ExprSext(src1, size - 1), ExprSext(-s2, size - 1)), self.name + '_of') self.block.set_reg(self.isa.sf, sign, self.name + '_sf') if subop == 2: self.block.set_reg(self.isa.zf, ExprEq(src1, src2), self.name + '_zf') else: self.block.set_reg(self.isa.zf, ExprEq(res & bflmask(size), 0), self.name + '_zf')
def emit_shift(self, size, dst, src1, src2, subop): shcnt = src2 & bflmask(size + 3) size = 8 << size if subop in [4, 0xc]: res = src1 << shcnt if subop == 0xc: res |= self.block.get_reg(self.isa.cf) << (shcnt - 1) cf = res >> size else: cf = src1 >> (shcnt - 1) if subop == 7: src1 = ExprSext(src1, size - 1) elif subop == 0xd: src1 |= self.block.get_reg(self.isa.cf) << size res = src1 >> shcnt self.block.set_reg(dst, res, self.name) self.block.set_reg(self.isa.cf, cf, self.name + '_cf') if self.isa.version != 0: self.block.set_reg(self.isa.of, ExprConst(0), self.name + '_of') self.block.set_reg(self.isa.sf, res >> (size - 1), self.name + '_sf') self.block.set_reg(self.isa.zf, ExprEq(res, 0), self.name + '_zf')
def __init__(self, version): self.r = [IsaReg('r{}'.format(idx), bflmask(32)) for idx in range(16)] self.rh = [IsaSubReg(self.r[idx], 0, 16) for idx in range(16)] self.rb = [IsaSubReg(self.r[idx], 0, 8) for idx in range(16)] self.rs = [self.rb, self.rh, self.r] self.sp = IsaReg('sp', bflmask(32) & ~3) self.iv0 = IsaVisibleReg('iv0', bflmask(32)) self.iv1 = IsaVisibleReg('iv1', bflmask(32)) self.tv = IsaVisibleReg('tv', bflmask(32)) flags = [] self.cf = IsaReg('cf', 1) self.of = IsaReg('of', 1) self.sf = IsaReg('sf', 1) self.zf = IsaReg('zf', 1) for idx in range(8): flags.append((idx, 1, IsaReg('p{}'.format(idx), 1))) flags.append((8, 1, self.cf)) flags.append((9, 1, self.of)) flags.append((10, 1, self.sf)) flags.append((11, 1, self.zf)) flags.append((16, 1, IsaVisibleReg('ie0', 1))) flags.append((17, 1, IsaVisibleReg('ie1', 1))) flags.append((20, 1, IsaReg('is0', 1))) flags.append((21, 1, IsaReg('is1', 1))) flags.append((24, 1, IsaVisibleReg('ta', 1))) self.flags = IsaSplitReg('flags', flags) self.xtargets = IsaReg('xtargets', 0x7707) self.xdbase = IsaReg('xdbase', bflmask(32)) self.xcbase = IsaReg('xdbase', bflmask(32)) self.version = version self.sr = [ self.iv0, self.iv1, None, self.tv, self.sp, None, self.xcbase, self.xdbase, # XXX PC self.flags, None, None, self.xtargets, # XXX crypto crap None, None, None, None, # XXX tstatus ] self.data = IsaMem('D', 8, bflmask(32), ISA_MEM_RW) self.iowr = IsaExec('iowr', [], [bflmask(32), bflmask(32)]) self.iowrs = IsaExec('iowrs', [], [bflmask(32), bflmask(32)]) self.iord = IsaExec('iord', [bflmask(32)], [bflmask(32)]) self.sleep = IsaExec('sleep', [], [1]) self.xcwait = IsaExec('xcwait', [], []) self.xdwait = IsaExec('xdwait', [], []) self.xcld = IsaExec('xcld', [], [bflmask(3), bflmask(32), bflmask(32), bflmask(16), bflmask(3)]) self.xdld = IsaExec('xdld', [], [bflmask(3), bflmask(32), bflmask(32), bflmask(16), bflmask(3)]) self.xdst = IsaExec('xdst', [], [bflmask(3), bflmask(32), bflmask(32), bflmask(16), bflmask(3)]) if version < 4: self.codemem = IsaMem('C', 8, bflmask(16), ISA_MEM_RO) else: self.codemem = IsaMem('C', 8, bflmask(24), ISA_MEM_RO) self.stackptr = self.sp self.stackmem = self.data
def fold(self, vars_, reason): return DecopSt( self.space, self.sz, self.addr.fold(vars_, reason).mask(self.space.amask), self.src.fold(vars_, reason).mask(bflmask(self.space.bsz * self.sz)))
def findlivemasks(self, vars_): self.addr.findlivemasks(vars_, self.space.amask) self.src.findlivemasks(vars_, bflmask(self.space.bsz * self.sz))
def __init__(self): self.cacc = IsaReg('cacc', bflmask(32)) self.cmd = IsaReg('cmd', 0x1fffc) self.lutidx = IsaReg('lutidx', bflmask(5)) self.datahi = IsaReg('datahi', bflmask(8)) self.dacc = IsaReg('dacc', bflmask(32)) self.data = IsaReg('data', bflmask(32)) self.csr = [self.cacc, self.cmd, self.lutidx, self.datahi] self.dsr = [self.dacc, self.data] self.r = [IsaReg('r{}'.format(idx), bflmask(32)) for idx in range(8)] self.g = [IsaReg('g{}'.format(idx), bflmask(32)) for idx in range(6)] self.p = [1] + [ IsaReg('p{}'.format(idx), bflmask(1)) for idx in range(1, 4) ] self.pred = IsaSplitReg('pred', [(idx, 1, self.p[idx]) for idx in range(4)]) self.gpr = self.r + self.g + [None, self.pred] self.lut = IsaMem('lut', 32, bflmask(5), ISA_MEM_RO) self.submit = IsaExec('submit', (), (0x1fffc, bflmask(32), bflmask(8))) self.codemem = IsaMem('C', 64, 0x1ff, ISA_MEM_RO)
def decode(self): if self.pred or self.pnot: # XXX raise DecodeError('predicate') if self.submit: cmd = self.block.get_reg(isa.cmd) data = self.block.get_reg(isa.data) datahi = self.block.get_reg(isa.datahi) self.block.emit_exec(self.name, isa.submit, [cmd, data, datahi]) # XXX auto-increment if self.cbfend >= self.cbfstart: cbfmask = (2 << self.cbfend) - (1 << self.cbfstart) else: cbfmask = 0 pres = ExprConst(0) if self.cop == CINSRT_R: if self.cshdir == 0: ssrc = self.get_csrc1() << self.cshift else: ssrc = self.get_csrc1() >> self.cshift tmp = ssrc & cbfmask c2d = cres = tmp | (self.get_csrc2() & ~cbfmask) pres = ExprEq(tmp, 0) elif self.cop == CINSRT_I: c2d = cres = (self.get_csrc2() & ~cbfmask) | (self.cimm6 << self.cbfstart & cbfmask) elif self.cop == CMOV_I: c2d = cres = ExprConst(self.cimm18) elif self.cop == CEXTRADD8: c2d = (self.get_csrc1() & cbfmask) >> self.cbfstart cres = ((c2d + self.cimm8) & 0xff) | (c2d & ~0xff) else: assert 0 if self.dbfend >= self.dbfstart: dbfmask = (2 << self.dbfend) - (1 << self.dbfstart) else: dbfmask = 0 ddst_skip = False if self.dop == DINSRT_R: if self.dshdir == 0: ssrc = self.get_dsrc1() << self.dshift else: ssrc = ExprSext(self.get_dsrc1(), 31) >> self.dshift tmp = ssrc & dbfmask dres = tmp | (self.get_dsrc2() & ~dbfmask) if self.c2den: dres = (c2d & cbfmask) | (dres & ~cbfmask) pres = ExprEq(tmp, 0) elif self.dop == DINSRT_I: dres = (self.get_dsrc2() & ~dbfmask) | (self.dimm6 << self.dbfstart & dbfmask) if self.c2den: dres = (c2d & cbfmask) | (dres & ~cbfmask) elif self.dop == DMOV_I: dres = ExprConst(self.dimm23) elif self.dop == DADD16_I: src1 = (self.get_dsrc1() >> (self.dhi * 16)) & 0xffff sum_ = (src1 + self.dimm16) & 0xffff dres = (self.get_dsrc1() & ~(0xffff << 16 * self.dhi)) | (sum_ << (16 * self.dhi)) pres = sum_ >> 15 & 1 ddst_skip = self.ddstskip elif self.dop == DLOGOP16_I: src = self.get_dsrc1() if self.dhi: src = src >> 16 src = src & 0xffff if self.dlogop == 0: res = ExprConst(self.dimm16) elif self.dlogop == 1: res = src & self.dimm16 elif self.dlogop == 2: res = src | self.dimm16 elif self.dlogop == 3: res = src ^ self.dimm16 if self.dhi: dres = (self.get_dsrc1() & ~0xffff0000) | (res << 16) else: dres = (self.get_dsrc1() & ~0xffff) | res pres = ExprEq(res, 0) elif self.dop == DSHIFT_R: shift = self.get_csrc1() & 0x1f if self.dshdir == 0: dres = self.get_dsrc1() << shift else: dres = ExprSext(self.get_dsrc1(), 31) >> shift elif self.dop == DSEXT: bfstart = max(self.dbfstart, self.dshift) if self.dbfend >= bfstart: dbfmask = (2 << self.dbfend) - (1 << bfstart) else: dbfmask = 0 pres = self.get_dsrc2() >> self.dshift & 1 dres = (self.get_dsrc2() & ~dbfmask) | ( ExprSext(self.get_dsrc2(), self.dshift) & dbfmask) elif self.dop == DADD16_R: src1 = (self.get_dsrc1() >> (self.dhi * 16)) & 0xffff src2 = (self.get_csrc1() >> (self.dhi2 * 16)) & 0xffff if self.dsub == 0: sum_ = (src1 + src2) & 0xffff else: sum_ = (src2 - src2) & 0xffff dres = (self.get_dsrc1() & ~(0xffff << 16 * self.dhi)) | (sum_ << (16 * self.dhi)) pres = sum_ >> 15 & 1 else: assert 0 self.block.set_reg(isa.csr[self.cdst], cres, self.name + '_cres') dres = self.block.encap( self.block.make_temp(dres, self.name + '_dres', bflmask(32))) if not ddst_skip: self.block.set_reg(isa.dsr[self.ddst], dres, self.name + '_dres_dsr') if self.drdst != 14: self.block.set_reg(isa.gpr[self.drdst], dres, self.name + '_dres_gpr') if self.pdst: self.block.set_reg(isa.p[self.pdst], pres, self.name + '_pres') if self.exit: self.block.emit_exit()