Example #1
0
 def new(cls, e1, e2):
     if isinstance(e1, ExprConst) and isinstance(e2, ExprConst):
         return ExprConst(e1.val & e2.val)
     if (e1.bmask & e2.bmask) == 0:
         return ExprConst(0)
     if isinstance(e1, ExprConst):
         e1, e2 = e2, e1
     if isinstance(e2, ExprConst):
         return ExprBigOr(super().new(e1, e2))
     return super().new(e1, e2)
Example #2
0
 def emit_logop(self, dst, src1, src2, subop):
     if subop == 4:
         res = src1 & src2
     elif subop == 5:
         res = src1 | src2
     elif subop == 6:
         res = src1 ^ src2
     self.block.set_reg(dst, res, self.name)
     if self.isa.version != 0:
         self.block.set_reg(self.isa.cf, ExprConst(0), self.name + '_cf')
         self.block.set_reg(self.isa.of, ExprConst(0), self.name + '_of')
         self.block.set_reg(self.isa.sf, res >> 31, self.name + '_sf')
         self.block.set_reg(self.isa.zf, ExprEq(res, 0), self.name + '_zf')
Example #3
0
 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')
Example #4
0
 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")
Example #5
0
 def encap(cls, val):
     if isinstance(val, Var):
         return ExprVar(val)
     elif isinstance(val, int):
         return ExprConst(val)
     else:
         assert 0
Example #6
0
 def _add(self, expr, mask, mul):
     if not mul:
         return
     if isinstance(expr, ExprSum):
         self._add(ExprConst(expr.const), mask, mul)
         for sexpr, smul in expr.parts:
             self._add(sexpr, mask, smul * mul)
         return
     if isinstance(expr, ExprAdd):
         self._add(expr.e1, mask, mul)
         self._add(expr.e2, mask, mul)
         return
     if isinstance(expr, ExprSub):
         self._add(expr.e1, mask, mul)
         self._add(expr.e2, mask, -mul)
         return
     if isinstance(expr, ExprMul) and isinstance(expr.e2, ExprConst):
         self._add(expr.e1, mask, mul * expr.e2.val)
         return
     if isinstance(expr, ExprMul) and isinstance(expr.e1, ExprConst):
         self._add(expr.e2, mask, mul * expr.e1.val)
         return
     if isinstance(expr, ExprConst):
         self.const += expr.val * mul
         self.const &= mask
         return
     self.parts.append(Part(expr.mask(mask), mul))
Example #7
0
 def __init__(self, func, block):
     self.func = func
     self.name = block.name
     self.start = block.start
     self.end = block.end
     self.inregs = block.inregs.copy()
     self.ops = block.ops[:]
     self.finalop = block.finalop or DecopJmp(block.isa, ExprConst(
         block.end))
     self.outs = block.outs[:]
     self.ins = set()
     self.localdefs = {}
     self.livevars = Counter()
     self.outregs = [regs.copy() for regs in block.outregs]
     self.loop = None
     self.join = None
     self.brk = None
     self.used = False
     self.label = False
     for reg in self.inregs:
         self.localdefs[self.inregs[reg]] = reg
     for op in self.ops:
         for out in op.outs:
             self.localdefs[out] = op
     for out in self.finalop.outs:
         self.localdefs[out] = self.finalop
Example #8
0
 def new(cls, e1, e2):
     if isinstance(e1, ExprConst) and isinstance(e2, ExprConst):
         return ExprConst(shl(e1.val, e2.val))
     if isinstance(e2, ExprConst):
         if e2.val == 0:
             return e1
         return ExprBigOr(super().new(e1, e2))
     return super().new(e1, e2)
Example #9
0
 def new(cls, e1, e2):
     if isinstance(e1, ExprConst) and isinstance(e2, ExprConst):
         return ExprConst(e1.val * e2.val)
     if isinstance(e1, ExprConst):
         e1, e2 = e2, e1
     if isinstance(e2, ExprConst):
         return ExprSum(super().new(e1, e2))
     return super().new(e1, e2)
Example #10
0
 def emit_extr(self, dst, src1, src2, subop):
     low = src2 & 0x1f
     size = (src2 >> 5 & 0x1f) + 1
     res = src1 >> low & ((ExprConst(1) << size) - 1)
     if subop == 3:
         # XXX doesn't match hw if low+size > 0x20
         res = ExprSext(res, size - 1)
     self.block.set_reg(dst, res, self.name)
     self.block.set_reg(self.isa.sf, res >> 31, self.name + '_sf')
     self.block.set_reg(self.isa.zf, ExprEq(res, 0), self.name + '_zf')
Example #11
0
 def get_csrc2(self):
     if self.csrc2 == 0:
         return ExprConst(0)
     elif self.csrc2 == 1:
         return self.block.get_reg(isa.cacc)
     elif self.csrc2 == 2:
         return self.block.get_reg(isa.dacc)
     elif self.csrc2 == 3:
         return self.get_csrc1()
     else:
         assert 0
Example #12
0
 def simplify(self):
     self.bmask = self.const
     for expr in self.exprs:
         self.bmask |= expr.bmask
     if not self.exprs:
         return ExprConst(self.const)
     if self.const == 1:
         for expr in list(self.exprs):
             if isinstance(expr, ExprBinBool):
                 self.const = 0
                 self.exprs ^= {expr, expr.negate()}
     if not self.const and len(self.exprs) == 1:
         return list(self.exprs)[0]
     return self
Example #13
0
 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))
Example #14
0
 def simplify(self, mask=-1):
     newparts = []
     for part in self.parts:
         newparts.append(Part(part.expr.mask(mask), part.mul))
     self.parts = newparts
     self.const &= mask
     self.bmask = highmask(self.const)
     for part in self.parts:
         self.bmask |= highmask(part.expr.bmask * part.mul)
     if not self.parts:
         return ExprConst(self.const)
     if not self.const and len(self.parts) == 1:
         part = self.parts[0]
         if part.mul == 1:
             return part.expr
     return self
Example #15
0
 def _add(self, expr, mask):
     if isinstance(expr, ExprBigXor):
         self._add(ExprConst(expr.const), mask)
         for sexpr in expr.exprs:
             self._add(sexpr, mask)
         return
     if isinstance(expr, ExprXor):
         self._add(expr.e1, mask)
         self._add(expr.e2, mask)
         return
     if isinstance(expr, ExprConst):
         self.const ^= expr.val
         return
     expr = expr.mask(mask)
     if not expr.bmask & mask:
         return
     self.exprs ^= {expr}
Example #16
0
 def simplify(self, mask):
     newbitfields = []
     for bf in self.bitfields:
         if (bf.mask | self.const) == self.const:
             pass
         elif ((mask & shl(sext(bf.expr.bmask, bf.sign), bf.shift))
               | bf.mask) == bf.mask:
             newbitfields.append(Bitfield(bf.expr, bf.sign, bf.shift, -1))
         else:
             newbitfields.append(bf)
     self.bitfields = newbitfields
     if not self.bitfields:
         return ExprConst(self.const)
     if not self.const and len(self.bitfields) == 1:
         bf = self.bitfields[0]
         if bf.mask == -1 and bf.sign is None and bf.shift == 0:
             return bf.expr
     return self
Example #17
0
 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')
Example #18
0
 def __new__(cls, e1, e2):
     if isinstance(e1, int):
         e1 = ExprConst(e1)
     if isinstance(e2, int):
         e2 = ExprConst(e2)
     return cls.new(e1, e2)
Example #19
0
    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()
Example #20
0
 def __init__(self, isa, name, block, pos):
     self.isa = isa
     self.name = name
     self.block = block
     self.pos = pos
     self.origpos = pos
     op = op0 = self.get_byte()
     if op < 0xc0:
         size = op >> 6
         op = op & 0x3f
         if op < 0x30:
             subop = op & 0xf
             op >>= 4
             if op == 0 and self.isa.version < 5:
                 op1 = self.get_byte()
                 reg1 = self.isa.rs[size][op1 & 0xf]
                 reg2 = self.isa.r[op1 >> 4]
                 imm = self.get_imm(0, 0)
                 if subop == 0:
                     block.emit_st(self.name, self.isa.data, 1 << size, block.get_reg(reg2) + (imm << size), block.get_reg(reg1))
                 else:
                     raise DecodeError('sized low {:x}/{:x}'.format(op, subop))
             elif op == 0 and self.isa.version >= 5:
                 reg0 = isa.r[subop]
                 imm = self.get_fimm(size + 1)
                 block.set_reg(reg0, ExprConst(imm), self.name)
             elif op == 1 or (op == 2 and self.isa.version < 5):
                 op1 = self.get_byte()
                 reg1 = self.isa.rs[size][op1 & 0xf]
                 reg2 = self.isa.rs[size][op1 >> 4]
                 imm = self.get_imm(op == 2, 0)
                 if subop in [0, 1, 2, 3]:
                     self.emit_add(size, reg1, block.get_reg(reg2), ExprConst(imm), subop)
                 elif subop in [4, 5, 7, 0xc, 0xd] and op == 1:
                     self.emit_shift(size, reg1, block.get_reg(reg2), ExprConst(imm), subop)
                 elif subop == 8 and op == 1:
                     reg2 = self.isa.r[op1 >> 4]
                     res = block.emit_ld(self.name, self.isa.data, 1 << size, block.get_reg(reg2) + (imm << size))
                     block.set_reg(reg1, res, self.name)
                 else:
                     raise DecodeError('sized low {:x}/{:x}'.format(op, subop))
             elif op == 2 and self.isa.version >= 5:
                 reg1 = self.isa.rs[size][op1 & 0xf]
                 reg2 = self.isa.rs[size][op1 >> 4]
                 # XXX st, st[sp], cmpu, cmps, cmp
                 raise DecodeError('sized low {:x}/{:x}'.format(op, subop))
             else:
                 raise DecodeError('sized low {:x}/{:x}'.format(op, subop))
         else:
             if op in [0x30, 0x31]:
                 op1 = self.get_byte()
                 subop = op1 & 0xf
                 reg2 = self.isa.rs[size][op1 >> 4]
                 imm = self.get_imm(op & 1, 0)
                 if subop == 1:
                     block.emit_st(self.name, self.isa.data, 1 << size, block.get_reg(self.isa.sp) + (imm << size), block.get_reg(reg2))
                 elif subop == 6 and self.isa.version >= 3:
                     self.emit_add(size, None, block.get_reg(reg2), ExprConst(imm), 2)
                 else:
                     # XXX st, cmpu, cmps
                     raise DecodeError('sized high {:x}/{:x}'.format(op, subop))
             elif op == 0x34:
                 op1 = self.get_byte()
                 subop = op1 & 0xf
                 reg2 = self.isa.rs[size][op1 >> 4]
                 imm = self.get_imm(0, 0)
                 if subop == 0:
                     res = block.emit_ld(self.name, self.isa.data, 1 << size, block.get_reg(self.isa.sp) + (imm << size))
                     block.set_reg(reg2, res, self.name)
                 else:
                     raise DecodeError('sized high {:x}/{:x}'.format(op, subop))
             elif op in [0x36, 0x37]:
                 op1 = self.get_byte()
                 subop = op1 & 0xf
                 reg2 = self.isa.rs[size][op1 >> 4]
                 imm = self.get_imm(op & 1, 0)
                 if subop in [0, 1, 2, 3]:
                     self.emit_add(size, reg2, self.block.get_reg(reg2), ExprConst(imm), subop)
                 elif subop in [4, 5, 7, 0xc, 0xd] and op == 0x36:
                     self.emit_shift(size, reg2, self.block.get_reg(reg2), ExprConst(imm), subop)
                 else:
                     raise DecodeError('sized high {:x}/{:x}'.format(op, subop))
             elif op == 0x38 and self.isa.version < 5:
                 op1 = self.get_byte()
                 reg1 = self.isa.rs[size][op1 & 0xf]
                 reg2 = self.isa.rs[size][op1 >> 4]
                 op2 = self.get_byte()
                 subop = op2 & 0xf
                 if subop == 6 and self.isa.version >= 3:
                     self.emit_add(size, None, block.get_reg(reg2), block.get_reg(reg1), 2)
                 else:
                     # XXX st, st[sp], cmpu, cmps
                     raise DecodeError('sized high {:x}/{:x}'.format(op, subop))
             elif op == 0x39:
                 op1 = self.get_byte()
                 reg1 = self.isa.rs[size][op1 & 0xf]
                 reg2 = self.isa.rs[size][op1 >> 4]
                 op2 = self.get_byte()
                 subop = op2 & 0xf
                 if subop == 0:
                     self.emit_not(size, reg1, block.get_reg(reg2))
                 else:
                     # XXX neg, mov/movf, hwswap
                     raise DecodeError('sized high {:x}/{:x}'.format(op, subop))
             elif op == 0x3b:
                 op1 = self.get_byte()
                 reg1 = self.isa.rs[size][op1 & 0xf]
                 reg2 = self.isa.rs[size][op1 >> 4]
                 op2 = self.get_byte()
                 subop = op2 & 0xf
                 if subop in [0, 1, 2, 3]:
                     self.emit_add(size, reg2, block.get_reg(reg2), block.get_reg(reg1), subop)
                 elif subop in [4, 5, 7, 0xc, 0xd]:
                     self.emit_shift(size, reg2, block.get_reg(reg2), block.get_reg(reg1), subop)
                 else:
                     raise DecodeError('sized high {:x}/{:x}'.format(op, subop))
             elif op == 0x3c:
                 op1 = self.get_byte()
                 reg1 = self.isa.rs[size][op1 & 0xf]
                 reg2 = self.isa.rs[size][op1 >> 4]
                 op2 = self.get_byte()
                 subop = op2 & 0xf
                 reg3 = self.isa.rs[size][op2 >> 4]
                 if subop in [0, 1, 2, 3]:
                     self.emit_add(size, reg3, block.get_reg(reg2), block.get_reg(reg1), subop)
                 elif subop in [4, 5, 7, 0xc, 0xd]:
                     self.emit_shift(size, reg3, block.get_reg(reg2), block.get_reg(reg1), subop)
                 else:
                     raise DecodeError('sized high {:x}/{:x}'.format(op, subop))
             elif op == 0x3d:
                 op1 = self.get_byte()
                 subop = op1 & 0xf
                 reg2 = self.isa.rs[size][op1 >> 4]
                 if subop == 4:
                     block.set_reg(reg2, ExprConst(0), self.name)
                 else:
                     # XXX not, neg, mov/movf, hswap, setf
                     raise DecodeError('sized high {:x}/{:x}'.format(op, subop))
             else:
                 # XXX 32, 33, 35, 38[v5], 3a, 3e, 3f
                 raise DecodeError('sized high {:x}'.format(op))
     else:
         if op < 0xf0:
             subop = op & 0xf
             op >>= 4
             if op in [0xc, 0xe]:
                 op1 = self.get_byte()
                 reg1 = self.isa.r[op1 & 0xf]
                 reg2 = self.isa.r[op1 >> 4]
                 imm = self.get_imm(op == 0xe, subop == 1)
                 if subop in [3, 7] and self.isa.version >= 3:
                     self.emit_extr(reg1, block.get_reg(reg2), imm, subop)
                 elif subop in [4, 5, 6]:
                     self.emit_logop(reg1, block.get_reg(reg2), imm, subop)
                 elif subop == 0xf:
                     self.emit_iord(reg1, block.get_reg(reg2) + imm * 4)
                 else:
                     # XXX other
                     raise DecodeError('unsized low {:x}/{:x}'.format(op, subop))
             elif op == 0xd and self.isa.version < 5:
                 op1 = self.get_byte()
                 reg1 = self.isa.r[op1 & 0xf]
                 reg2 = self.isa.r[op1 >> 4]
                 imm = self.get_imm(0, 0)
                 block.emit_exec(self.name, self.isa.iowr, [block.get_reg(reg2) + imm * 4, block.get_reg(reg1)])
             else:
                 # XXX 0xd[old], 0xd[v5]
                 raise DecodeError('unsized low {:x}/{:x}'.format(op, subop))
         else:
             if op in [0xf0, 0xf1]:
                 op1 = self.get_byte()
                 reg2 = self.isa.r[op1 >> 4]
                 subop = op1 & 0xf
                 imm = self.get_imm(op & 1, subop in [1, 7])
                 if subop == 0:
                     block.set_reg(reg2, isa.mulu(block.get_reg(reg2), imm), self.name)
                 elif subop == 1:
                     block.set_reg(reg2, isa.muls(block.get_reg(reg2), imm), self.name)
                 #elif subop == 2 and op == 0xf0:
                 #    block.set_reg(reg2, ExprSext(block.get_reg(reg2), imm & 0x1f), self.name)
                 elif subop == 3:
                     block.set_reg(reg2, block.get_reg(reg2) & 0xffff | imm << 16, self.name)
                 elif subop in [4, 5, 6]:
                     self.emit_logop(reg2, block.get_reg(reg2), imm, subop)
                 elif subop == 7:
                     block.set_reg(reg2, ExprConst(imm), self.name)
                 elif subop == 0xc and op == 0xf0:
                     self.emit_xbit(reg2, block.get_reg(self.isa.flags), imm)
                 else:
                     # XXX 2, 9-11
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             elif op in [0xf4, 0xf5]:
                 op1 = self.get_byte()
                 subop = op1 & 0x3f
                 imm = self.get_imm(op & 1, subop < 0x20 or subop == 0x30)
                 if subop < 0x20:
                     target = ExprConst(imm + self.origpos)
                     if subop == 0xe:
                         block.emit_jmp(self.name, target)
                     else:
                         if subop in range(0x00, 0x0c):
                             pred = block.get_reg(self.isa.flags.fields[subop][2])
                         elif subop in range(0x0c, 0x0e):
                             pred = block.get_reg(self.isa.cf) | block.get_reg(self.isa.zf)
                             if subop == 0xc:
                                 pred = pred ^ 1
                         elif subop in range(0x10, 0x1c):
                             pred = block.get_reg(self.isa.flags.fields[subop - 0x10][2]) ^ 1
                         elif subop in range(0x1c, 0x20):
                             pred = block.get_reg(self.isa.sf) ^ block.get_reg(self.isa.of)
                             if subop in [0x1c, 0x1d]:
                                 pred |= block.get_reg(self.isa.zf)
                             if subop in [0x1c, 0x1f]:
                                 pred ^= 1
                         else:
                             raise DecodeError('bra pred {}'.format(subop))
                         block.emit_bra(self.name, pred, target)
                 elif subop == 0x20:
                     block.emit_jmp(self.name, ExprConst(imm))
                 elif subop == 0x21:
                     block.emit_call(self.name, ExprConst(imm))
                 elif subop == 0x28 and op == 0xf4:
                     block.emit_exec(self.name, self.isa.sleep, [block.get_reg(self.isa.flags) >> (imm & 0x1f)])
                 elif subop == 0x30:
                     block.set_reg(isa.sp, block.get_reg(isa.sp) + imm, self.name)
                 elif subop == 0x31 and op == 0xf4:
                     block.set_reg(isa.flags, block.get_reg(isa.flags) | 1 << imm, self.name)
                 elif subop == 0x32 and op == 0xf4:
                     block.set_reg(isa.flags, block.get_reg(isa.flags) & ~(1 << imm), self.name)
                 elif subop == 0x33 and op == 0xf4:
                     block.set_reg(isa.flags, block.get_reg(isa.flags) ^ 1 << imm, self.name)
                 else:
                     # XXX 3c
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             elif op == 0xf8:
                 op1 = self.get_byte()
                 subop = op1 & 0xf
                 if subop == 0:
                     block.emit_ret()
                 elif subop == 1:
                     block.emit_iret()
                 elif subop == 2:
                     block.emit_exit()
                 elif subop == 3:
                     block.emit_exec(self.name, self.isa.xdwait, [])
                 elif subop == 7:
                     block.emit_exec(self.name, self.isa.xcwait, [])
                 else:
                     # XXX iret, f8/6, trap
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             elif op == 0xf9:
                 op1 = self.get_byte()
                 subop = op1 & 0xf
                 reg2 = isa.r[op1 >> 4]
                 if subop == 0:
                     block.set_reg(isa.sp, block.get_reg(isa.sp) - 4, self.name)
                     block.emit_st(self.name, self.isa.data, 4, block.get_reg(isa.sp), block.get_reg(reg2))
                 elif subop == 5:
                     block.emit_call(self.name, block.get_reg(reg2))
                 else:
                     # XXX add[sp], mpush, bra, itlb, bset, bclr, btgl
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             elif op == 0xfa:
                 op1 = self.get_byte()
                 op2 = self.get_byte()
                 subop = op2 & 0xf
                 reg1 = isa.r[op1 & 0xf]
                 reg2 = isa.r[op1 >> 4]
                 if subop == 0:
                     block.emit_exec(self.name, self.isa.iowr, [block.get_reg(reg2), block.get_reg(reg1)])
                 elif subop == 1:
                     block.emit_exec(self.name, self.isa.iowrs, [block.get_reg(reg2), block.get_reg(reg1)])
                 elif subop in [4, 5, 6]:
                     if subop == 4:
                         pshift = 0
                         spec = self.isa.xcld
                         base = self.isa.xcbase
                     elif subop == 5:
                         pshift = 8
                         spec = self.isa.xdld
                         base = self.isa.xdbase
                     elif subop == 6:
                         pshift = 12
                         spec = self.isa.xdst
                         base = self.isa.xdbase
                     port = block.get_reg(self.isa.xtargets) >> pshift
                     base = block.get_reg(base)
                     offs = block.get_reg(reg2)
                     p2 = block.get_reg(reg1)
                     addr = p2 & 0xffff
                     size = p2 >> 16
                     block.emit_exec(self.name, spec, [port, base, offs, addr, size])
                 else:
                     # XXX xcld, xdld. xdst, setp
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             elif op == 0xfc:
                 op1 = self.get_byte()
                 subop = op1 & 0xf
                 reg2 = isa.r[op1 >> 4]
                 if subop == 0:
                     tmp = block.emit_ld(self.name, self.isa.data, 4, block.get_reg(isa.sp))
                     block.set_reg(isa.sp, block.get_reg(isa.sp) + 4, self.name + '_sp')
                     block.set_reg(reg2, tmp, self.name)
                 else:
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             elif op == 0xfd:
                 op1 = self.get_byte()
                 op2 = self.get_byte()
                 subop = op2 & 0xf
                 reg1 = isa.r[op1 & 0xf]
                 reg2 = isa.r[op1 >> 4]
                 if subop in [0, 1]:
                     self.emit_mul(reg2, block.get_reg(reg2), block.get_reg(reg1), subop)
                 elif subop in [4, 5, 6]:
                     self.emit_logop(reg2, block.get_reg(reg2), block.get_reg(reg1), subop)
                 else:
                     # XXX sext, bit*
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             elif op == 0xfe:
                 op1 = self.get_byte()
                 op2 = self.get_byte()
                 reg1 = self.isa.r[op1 & 0xf]
                 reg2 = self.isa.r[op1 >> 4]
                 subop = op2 & 0xf
                 if subop == 0:
                     sr = isa.sr[op1 & 0xf]
                     if sr is None:
                         raise DecodeError('mov to $sr{}'.format(op1 & 0xf))
                     block.set_reg(sr, block.get_reg(reg2), self.name)
                 elif subop == 1:
                     sr = isa.sr[op1 >> 4]
                     if sr is None:
                         raise DecodeError('mov from $sr{}'.format(op1 >> 4))
                     block.set_reg(reg1, block.get_reg(sr), self.name)
                 else:
                     # XXX ptlb, vtlb, xbit
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             elif op == 0xff:
                 op1 = self.get_byte()
                 reg1 = self.isa.r[op1 & 0xf]
                 reg2 = self.isa.r[op1 >> 4]
                 op2 = self.get_byte()
                 subop = op2 & 0xf
                 reg3 = self.isa.r[op2 >> 4]
                 if subop in [0, 1]:
                     self.emit_mul(reg3, block.get_reg(reg2), block.get_reg(reg1), subop)
                 elif subop in [4, 5, 6]:
                     self.emit_logop(reg3, block.get_reg(reg2), block.get_reg(reg1), subop)
                 elif subop == 0xf:
                     self.emit_iord(reg3, block.get_reg(reg2) + block.get_reg(reg1) * 4)
                 else:
                     # XXX sext, extr*, xbit, div/mod, 0xe
                     raise DecodeError('unsized high {:x}/{:x}'.format(op, subop))
             else:
                 # XXX f2, f6, f7, fb
                 raise DecodeError('unsized high {:x}'.format(op))
Example #21
0
 def new(cls, e1, e2):
     if isinstance(e1, ExprConst) and isinstance(e2, ExprConst):
         return ExprConst(e1.val >= e2.val)
     return super().new(e1, e2)