diff options
Diffstat (limited to 'src/miasm/arch/ppc')
| -rw-r--r-- | src/miasm/arch/ppc/__init__.py | 1 | ||||
| -rw-r--r-- | src/miasm/arch/ppc/arch.py | 826 | ||||
| -rw-r--r-- | src/miasm/arch/ppc/disasm.py | 7 | ||||
| -rw-r--r-- | src/miasm/arch/ppc/jit.py | 70 | ||||
| -rw-r--r-- | src/miasm/arch/ppc/lifter_model_call.py | 87 | ||||
| -rw-r--r-- | src/miasm/arch/ppc/regs.py | 77 | ||||
| -rw-r--r-- | src/miasm/arch/ppc/sem.py | 981 |
7 files changed, 2049 insertions, 0 deletions
diff --git a/src/miasm/arch/ppc/__init__.py b/src/miasm/arch/ppc/__init__.py new file mode 100644 index 00000000..bbad893b --- /dev/null +++ b/src/miasm/arch/ppc/__init__.py @@ -0,0 +1 @@ +__all__ = ["arch", "disasm", "regs", "sem"] diff --git a/src/miasm/arch/ppc/arch.py b/src/miasm/arch/ppc/arch.py new file mode 100644 index 00000000..a1bde2a6 --- /dev/null +++ b/src/miasm/arch/ppc/arch.py @@ -0,0 +1,826 @@ +from builtins import range + +import logging +from pyparsing import * +from miasm.expression.expression import * +from miasm.core.cpu import * +from collections import defaultdict +from miasm.core.bin_stream import bin_stream +import miasm.arch.ppc.regs as regs_module +from miasm.arch.ppc.regs import * +from miasm.core.asm_ast import AstInt, AstId, AstMem, AstOp +from miasm.ir.ir import color_expr_html + +log = logging.getLogger("ppcdis") +console_handler = logging.StreamHandler() +console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) +log.addHandler(console_handler) +log.setLevel(logging.DEBUG) + +LPARENTHESIS = Suppress(Literal("(")) +RPARENTHESIS = Suppress(Literal(")")) + +def cb_deref_imm_reg(tokens): + if len(tokens) == 1: + return AstMem(tokens[0], 32) + elif len(tokens) == 2: + return AstMem(tokens[1] + tokens[0], 32) + else: + raise NotImplementedError('len(tokens) > 2') + + +deref_reg_disp = (Optional(base_expr) + LPARENTHESIS + gpregs.parser + RPARENTHESIS).setParseAction(cb_deref_imm_reg) +deref_reg = (LPARENTHESIS + gpregs.parser + RPARENTHESIS).setParseAction(cb_deref_imm_reg) + +deref = deref_reg | deref_reg_disp + + +class ppc_arg(m_arg): + def asm_ast_to_expr(self, arg, loc_db): + if isinstance(arg, AstId): + if isinstance(arg.name, ExprId): + return arg.name + if arg.name in gpregs.str: + return None + loc_key = loc_db.get_or_create_name_location(arg.name) + return ExprLoc(loc_key, 32) + if isinstance(arg, AstOp): + args = [self.asm_ast_to_expr(tmp, loc_db) for tmp in arg.args] + if None in args: + return None + return ExprOp(arg.op, *args) + if isinstance(arg, AstInt): + return ExprInt(arg.value, 32) + if isinstance(arg, AstMem): + ptr = self.asm_ast_to_expr(arg.ptr, loc_db) + if ptr is None: + return None + return ExprMem(ptr, arg.size) + return None + + +class additional_info(object): + + def __init__(self): + self.except_on_instr = False + self.bo_bi_are_defined = False + self.bi = 0 + self.bo = 0 + + +class instruction_ppc(instruction): + + def __init__(self, *args, **kargs): + super(instruction_ppc, self).__init__(*args, **kargs) + + @staticmethod + def arg2str(e, pos = None, loc_db=None): + if isinstance(e, ExprId) or isinstance(e, ExprInt): + return str(e) + elif isinstance(e, ExprMem): + addr = e.ptr + if isinstance(addr, ExprInt) or isinstance(addr, ExprId): + out = '(%s)'%addr + elif isinstance(addr, ExprOp): + if len(addr.args) == 1: + out = '(%s)'%addr + elif len(addr.args) == 2: + out = '%s(%s)'%(addr.args[1], addr.args[0]) + else: + raise NotImplementedError('More than two args to ExprOp of address') + else: + raise NotImplementedError('Invalid memory expression') + return out + + return str(e) + + + @staticmethod + def arg2html(e, pos = None, loc_db=None): + if isinstance(e, ExprId) or isinstance(e, ExprInt) or isinstance(e, ExprLoc): + return color_expr_html(e, loc_db) + elif isinstance(e, ExprMem): + addr = e.ptr + if isinstance(addr, ExprInt) or isinstance(addr, ExprId): + out = '(%s)'%color_expr_html(addr, loc_db) + elif isinstance(addr, ExprOp): + if len(addr.args) == 1: + out = '(%s)'%color_expr_html(addr, loc_db) + elif len(addr.args) == 2: + out = '%s(%s)'%(color_expr_html(addr.args[1], loc_db), color_expr_html(addr.args[0], loc_db)) + else: + raise NotImplementedError('More than two args to ExprOp of address') + else: + raise NotImplementedError('Invalid memory expression') + return out + + return color_expr_html(e, loc_db) + + @staticmethod + def is_conditional_jump(s): + return (s[0] == 'B' and + s[1:3] in { 'DN', 'DZ', 'LT', 'GT', 'EQ', 'SO', + 'GE', 'LE', 'NE', 'NS' }) + + def dstflow(self): + name = self.name + if name[-1] == '+' or name[-1] == '-': + name = name[:-1] + return (name[0] == 'B' and + name[-2:] != 'LR' and + name[-3:] != 'LRL' and + name[-3:] != 'CTR' and + name[-4:] != 'CTRL') + + def dstflow2label(self, loc_db): + name = self.name + if name[-1] == '+' or name[-1] == '-': + name = name[:-1] + + if name[-1] == 'L': + name = name[:-1] + elif name[-2:] == 'LA': + name = name[:-2] + 'A' + + if name[-2:] != 'LR' and name[-3:] != 'CTR': + if len(self.args) == 2: + address_index = 1 + else: + address_index = 0 + e = self.args[address_index] + if not isinstance(e, ExprInt): + return + if name[-1] != 'A': + ad = (int(e) + self.offset) & 0xFFFFFFFF + else: + ad = int(e) + loc_key = loc_db.get_or_create_offset_location(ad) + s = ExprLoc(loc_key, e.size) + self.args[address_index] = s + + def breakflow(self): + return self.name[0] == 'B' + + def is_subcall(self): + name = self.name + if name[-1] == '+' or name[-1] == '-': + name = name[0:-1] + return name[0] == 'B' and (name[-1] == 'L' or name[-2:-1] == 'LA') + + def getdstflow(self, loc_db): + if 'LR' in self.name: + return [ LR ] + elif 'CTR' in self.name: + return [ CTR ] + elif len(self.args) == 2: + address_index = 1 + else: + address_index = 0 + return [ self.args[address_index] ] + + def splitflow(self): + ret = False + if self.is_conditional_jump(self.name): + if self.additional_info.bo & 0b10100 != 0b10100: + ret = True + ret = ret or self.is_subcall() + return ret + + def get_symbol_size(self, symbol, loc_db): + return 32 + + def fixDstOffset(self): + e = self.args[0] + if not isinstance(e, ExprInt): + log.debug('Dynamic destination offset %r' % e) + return + if self.name[-1] != 'A': + if self.offset is None: + raise ValueError('symbol not resolved %s' % self.l) + off = (int(e) + 0x100000000 - (self.offset + self.l)) & 0xFFFFFFFF + if int(off % 4): + raise ValueError('Offset %r must be a multiple of four' % off) + else: + off = int(e) + self.args[0] = ExprInt(off, 32) + + def get_args_expr(self): + args = [a for a in self.args] + return args + + def get_asm_offset(self, x): + return ExprInt_from(x, self.offset) + + +class mn_ppc(cls_mn): + delayslot = 0 + name = "ppc32" + regs = regs_module + bintree = {} + num = 0 + all_mn = [] + all_mn_mode = defaultdict(list) + all_mn_name = defaultdict(list) + all_mn_inst = defaultdict(list) + instruction = instruction_ppc + max_instruction_len = 4 + + @classmethod + def getpc(cls, attrib = None): + return PC + + @classmethod + def getsp(cls, attrib = None): + return R1 + + def additional_info(self): + info = additional_info() + info.bo_bi_are_defined = False + if hasattr(self, "bo"): + info.bo_bi_are_defined = True + info.bi = int(self.bi.strbits, 2) + info.bo = int(self.bo.strbits, 2) + return info + + @classmethod + def getbits(cls, bs, attrib, start, n): + if not n: + return 0 + o = 0 + if n > bs.getlen() * 8: + raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8)) + while n: + offset = start // 8 + n_offset = cls.endian_offset(attrib, offset) + c = cls.getbytes(bs, n_offset, 1) + if not c: + raise IOError + c = ord(c) + r = 8 - start % 8 + c &= (1 << r) - 1 + l = min(r, n) + c >>= (r - l) + o <<= l + o |= c + n -= l + start += l + return o + + @classmethod + def endian_offset(cls, attrib, offset): + if attrib == "b": + return offset + else: + raise NotImplementedError("bad attrib") + + @classmethod + def check_mnemo(cls, fields): + l = sum([x.l for x in fields]) + assert l == 32, "len %r" % l + + @classmethod + def getmn(cls, name): + return name.upper() + + @classmethod + def mod_fields(cls, fields): + l = sum([x.l for x in fields]) + return fields + + @classmethod + def gen_modes(cls, subcls, name, bases, dct, fields): + dct['mode'] = None + return [(subcls, name, bases, dct, fields)] + + def post_dis(self): + return self + + def value(self, mode): + v = super(mn_ppc, self).value(mode) + if mode == 'b': + return [x for x in v] + else: + raise NotImplementedError("bad attrib") + + def get_symbol_size(self, symbol, loc_db, mode): + return 32 + + +class ppc_reg(reg_noarg, ppc_arg): + pass + + +class ppc_gpreg_noarg(reg_noarg): + reg_info = gpregs + parser = reg_info.parser + +class ppc_gpreg_or_0_noarg(reg_noarg): + reg_info = gpregs + parser = reg_info.parser + + def decode(self, v): + ret = super(ppc_gpreg_or_0_noarg, self).decode(v) + if ret == False: + return False + reg = self.expr + if reg == R0: + self.expr = ExprInt(0, 32) + return ret + +class ppc_gpreg(ppc_reg): + reg_info = gpregs + parser = reg_info.parser + +class ppc_gpreg_or_0(ppc_reg): + reg_info = gpregs + parser = reg_info.parser + + def decode(self, v): + ret = super(ppc_gpreg_or_0, self).decode(v) + if ret == False: + return False + reg = self.expr + if reg == R0: + self.expr = ExprInt(0, 32) + return ret + +class ppc_crfreg_noarg(reg_noarg): + reg_info = crfregs + parser = reg_info.parser + +class ppc_crfreg(ppc_reg): + reg_info = crfregs + parser = reg_info.parser + +class ppc_imm(imm_noarg, ppc_arg): + parser = base_expr + +class ppc_s14imm_branch(ppc_imm): + + def decode(self, v): + v = sign_ext(v << 2, 16, 32) + self.expr = ExprInt(v, 32) + return True + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = int(self.expr) + if v & 0x3: + return False + v = v >> 2 + if sign_ext(v & self.lmask, 14, 32) != v: + return False + self.value = v & self.lmask + return True + +class ppc_s24imm_branch(ppc_imm): + + def decode(self, v): + v = sign_ext(v << 2, 26, 32) + self.expr = ExprInt(v, 32) + return True + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = int(self.expr) + if v & 0x3: + return False + v = v >> 2 + if sign_ext(v & self.lmask, 24, 32) != v: + return False + self.value = v & self.lmask + return True + +class ppc_s16imm(ppc_imm): + + def decode(self, v): + v = sign_ext(v, 16, 32) + self.expr = ExprInt(v, 32) + return True + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = int(self.expr) + if sign_ext(v & self.lmask, 16, 32) != v: + return False + self.value = v & self.lmask + return True + +class ppc_u16imm(ppc_imm): + + def decode(self, v): + if v & self.lmask != v: + return False + self.expr = ExprInt(v, 32) + return True + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = int(self.expr) + if v & self.lmask != v: + return False + self.value = v & self.lmask + return True + +def ppc_swap_10(v): + return ((v & 0b11111) << 5) | ((v & 0b1111100000) >> 5) + +class ppc_spr(ppc_imm): + + def decode(self, v): + self.expr = ExprInt(ppc_swap_10(v), 32) + return True + + def encode(self, e): + if not isinstance(e, ExprInt): + return False + self.value = ppc_swap_10(int(e)) + return True + +class ppc_tbr(ppc_imm): + + def decode(self, v): + self.expr = ExprInt(ppc_swap_10(v), 32) + return True + + def encode(self, e): + if not isinstance(e, ExprInt): + return False + self.value = ppc_swap_10(int(e)) + return True + +class ppc_u08imm(ppc_u16imm): + pass + +class ppc_u05imm(ppc_u16imm): + pass + +class ppc_u04imm(ppc_u16imm): + pass + +class ppc_u02imm_noarg(imm_noarg): + pass + +class ppc_float(ppc_reg): + reg_info = floatregs + parser = reg_info.parser + +class ppc_vex(ppc_reg): + reg_info = vexregs + parser = reg_info.parser + +def ppc_bo_bi_to_mnemo(bo, bi, prefer_taken=True, default_taken=True): + bo2mnemo = { 0: 'DNZF', 2: 'DZF', 4: 'F', 8: 'DNZT', + 10: 'DZT', 12: 'T', 16: 'DNZ', 18: 'DZ', + 20: '' } + bi2cond = { 0b00: 'LT', 0b01: 'GT', 0b10: 'EQ', 0b11: 'SO' } + bi2ncond = { 0b00: 'GE', 0b01: 'LE', 0b10: 'NE', 0b11: 'NS' } + n = bo & 0b11110 + if not n in bo2mnemo: + raise NotImplementedError("Unknown BO field") + mnem = 'B' + bo2mnemo[n] + if mnem[-1] == 'T': + mnem = mnem[:-1] + bi2cond[bi & 0b11] + if mnem[-1] == 'F': + mnem = mnem[:-1] + bi2ncond[bi & 0b11] + + if prefer_taken != default_taken: + if prefer_taken: + mnem += '+' + else: + mnem += '-' + + return mnem + +def ppc_all_bo_bi(): + for bo in [0, 2, 4, 8, 10, 12, 16, 18, 20]: + for bi in range(4): + yield bo, bi + +class ppc_divert_conditional_branch(bs_divert): + prio=3 + def divert(self, i, candidates): + out = [] + for cls, _, bases, dct, fields in candidates: + bi_i = getfieldindexby_name(fields, 'bi')[1] + bo_i = getfieldindexby_name(fields, 'bo')[1] + + for bo, bi in ppc_all_bo_bi(): + nfields = fields[:] + nfields[bi_i] = bs(int2bin(bi, 2), fname="bi") + nfields[bo_i] = bs(int2bin(bo, 5), fname="bo") + ndct = dict(dct) + ndct['name'] = ppc_bo_bi_to_mnemo(bo, bi) + out.append((cls, ndct['name'], bases, ndct, nfields)) + + nfields = fields[:] + nfields[bi_i] = bs(int2bin(bi, 2), fname="bi") + nfields[bo_i] = bs(int2bin(bo+1, 5), fname="bo") + ndct = dict(dct) + ndct['name'] = ppc_bo_bi_to_mnemo(bo, bi) + out.append((cls, ndct['name'], bases, ndct, nfields)) + + return out + +class ppc_deref32(ppc_arg): + parser = deref + + def decode(self, v): + v = sign_ext(v, 16, 32) + e = self.parent.ra.expr + ExprInt(v, 32) + self.expr = ExprMem(e, size=32) + return True + + def encode(self): + e = self.expr + if not isinstance(e, ExprMem): + return False + addr = e.ptr + if isinstance(addr, ExprId) or isinstance(addr, ExprInt): + addr = addr + ExprInt(0, 32) + elif not isinstance(addr, ExprOp): + return False + if addr.op != '+': + return False + if len(addr.args) != 2: + return False + reg, disp = addr.args[0], addr.args[1] + v = int(disp) + if sign_ext(v & 0xFFFF, 16, 32) != v: + return False + v &= 0xFFFF + self.value = v + self.parent.ra.expr = reg + return True + + +def ppcop(name, fields, args=None, alias=False): + dct = {"fields": fields} + dct["alias"] = alias + if args is not None: + dct['args'] = args + type(name, (mn_ppc,), dct) + +rd = bs(l=5, cls=(ppc_gpreg,)) +ra = bs(l=5, cls=(ppc_gpreg,)) +ra_or_0 = bs(l=5, cls=(ppc_gpreg_or_0,)) +rb = bs(l=5, cls=(ppc_gpreg,)) +rs = bs(l=5, cls=(ppc_gpreg,)) +crfd = bs(l=3, cls=(ppc_crfreg,)) +crfs = bs(l=3, cls=(ppc_crfreg,)) +sh = bs(l=5, cls=(ppc_u05imm,)) +mb = bs(l=5, cls=(ppc_u05imm,)) +me = bs(l=5, cls=(ppc_u05imm,)) +nb = bs(l=5, cls=(ppc_u05imm,)) +crm = bs(l=8, cls=(ppc_u08imm,)) +sr = bs(l=4, cls=(ppc_u04imm,)) +spr = bs(l=10, cls=(ppc_spr,)) +tbr = bs(l=10, cls=(ppc_tbr,)) +u05imm = bs(l=5, cls=(ppc_u05imm,)) + +s24imm_branch = bs(l=24, cls=(ppc_s24imm_branch,), fname="imm") +s14imm_branch = bs(l=14, cls=(ppc_s14imm_branch,), fname="imm") +s16imm = bs(l=16, cls=(ppc_s16imm,), fname="imm") +u16imm = bs(l=16, cls=(ppc_u16imm,), fname="imm") +u08imm = bs(l=5, cls=(ppc_u08imm,), fname="imm") +u02imm_noarg = bs(l=2, cls=(ppc_u02imm_noarg,), fname="imm") + +ra_noarg = bs(l=5, cls=(ppc_gpreg_noarg,), fname="ra") +ra_or_0_noarg = bs(l=5, cls=(ppc_gpreg_or_0_noarg,), fname="ra") +dregimm = bs(l=16, cls=(ppc_deref32,)) + +rc_mod = bs_mod_name(l=1, mn_mod=['', '.'], fname='rc') + +frd = bs(l=5, cls=(ppc_float,)) +frb = bs(l=5, cls=(ppc_float,)) +frs = bs(l=5, cls=(ppc_float,)) +fm = bs(l=8, cls=(ppc_u08imm,)) + +va = bs(l=5, cls=(ppc_vex,)) +vb = bs(l=5, cls=(ppc_vex,)) +vd = bs(l=5, cls=(ppc_vex,)) +rb_noarg = bs(l=5, cls=(ppc_gpreg_noarg,), fname="rb") + +arith1_name = {"MULLI": 0b000111, "SUBFIC": 0b001000, "ADDIC": 0b001100, + "ADDIC.": 0b001101 } + +logic2_name = {"ORI": 0b011000, "XORI": 0b011010, "ANDI.": 0b011100 } +slogic2_name = {"ORIS": 0b011001, "XORIS": 0b011011, "ANDIS.": 0b011101 } + +arith3_name = {"SUBFC": 0b0000001000, "ADDC": 0b0000001010, + "MULHWU": 0b0000001011, "SUBF": 0b0000101000, + "MULHW": 0b0001001011, "SUBFE": 0b0010001000, + "ADDE": 0b0010001010, "MULLW": 0b0011101011, + "ADD": 0b0100001010, "DIVWU": 0b0111001011, + "DIVW": 0b0111101011, "SUBFCO": 0b1000001000, + "ADDCO": 0b1000001010, "SUBFO": 0b1000101000, + "SUBFEO": 0b1010001000, "ADDEO": 0b1010001010, + "MULLWO": 0b1011101011, "ADDO": 0b1100001010, + "DIVWUO": 0b1111001011, "DIVWO": 0b1111101011 } + +xor_name = { "EQV": 0b0100011100, "XOR": 0b0100111100 } + +arith4_name = {"NEG": 0b0001101000, "SUBFZE": 0b0011001000, + "ADDZE": 0b0011001010, "SUBFME": 0b0011101000, + "ADDME": 0b0011101010, "NEGO": 0b1001101000, + "SUBFZEO": 0b1011001000, "ADDZEO": 0b1011001010, + "SUBFMEO": 0b1011101000, "ADDMEO": 0b1011101010 } + +arith5_name = {"CNTLZW": 0b00000, "EXTSH": 0b11100, "EXTSB": 0b11101 } + +crlogic_name = {"CRAND": 0b1000, "CRANDC": 0b0100, "CREQV": 0b1001, + "CRNAND": 0b0111, "CRNOR": 0b0001, "CROR": 0b1110, + "CRORC": 0b1101, "CRXOR": 0b0110 } + +rotins_name = {"RLWIMI": 0b010100, "RLWINM": 0b010101 } + +bs_arith1_name = bs_name(l=6, name=arith1_name) + +load1_name = {"LWARX": 0b0000010100, "LWZX": 0b0000010111, + "LBZX": 0b0001010111, "LHZX": 0b0100010111, + "ECIWX": 0b0100110110, "LHAX": 0b0101010111, + "LSWX": 0b1000010101, "LWBRX": 0b1000010110, + "LHBRX": 0b1100010110 } + +load1_name_u = {"LWZUX": 0b0000110111, "LBZUX": 0b0001110111, + "LHZUX": 0b0100110111, "LHAUX": 0b0101110111 } + +load2_name = {"LWZ": 0b0000, "LBZ": 0b0010, "LHZ": 0b1000, "LHA": 0b1010, + "LMW": 0b1110 } + +load2_name_u = {"LWZU": 0b0001, "LBZU": 0b0011, "LHZU": 0b1001, "LHAU": 0b1011} + +store1_name = { "STWCX.": 0b00100101101, "STWX": 0b00100101110, + "STBX": 0b00110101110, "STHX": 0b01100101110, + "ECOWX": 0b01101101100, "STSWX": 0b10100101010, + "STWBRX": 0b10100101100, "STHBRX": 0b11100101100 } +store1_name_u = { "STWUX": 0b00101101110, "STBUX": 0b00111101110, + "STHUX": 0b01101101110 } + +store2_name = { "STW": 0b0100, "STB": 0b0110, "STH": 0b1100, "STMW": 0b1111 } +store2_name_u = { "STWU": 0b0101, "STBU": 0b0111, "STHU": 0b1101 } + +logic1_name = {"SLW": 0b0000011000, "AND": 0b0000011100, + "ANDC": 0b0000111100, "NOR": 0b0001111100, + "ORC": 0b0110011100, "OR": 0b0110111100, + "NAND": 0b0111011100, "SRW": 0b1000011000, + "SRAW": 0b1100011000 } + +dcb_name = {"DCBST": 0b00001, "DCBF": 0b00010, + "DCBTST": 0b00111, "DCBT": 0b01000, + "DCBI": 0b01110, "DCBA": 0b10111, + "ICBI": 0b11110, "DCBZ": 0b11111 } + + +load1_name_float = {"LFS": 0b110000, "LFD": 0b110010 } +load1_name_float_u = {"LFSU": 0b110001, "LFDU": 0b110011 } +store1_name_float = {"STFS": 0b110100, "STFD": 0b110110 } +store1_name_float_u = {"STFSU": 0b110101, "STFDU": 0b110111 } + +load1_name_vex = {"LVEBX": 0b0000000111, "LVEHX": 0b0000100111, + "LVEWX": 0b0001000111, "LVSL": 0b0000000110, + "LVSR": 0b0000100110, "LVX": 0b0001100111, + "LVXL": 0b0101100111 } + +class bs_mod_name_prio4(bs_mod_name): + prio = 4 + +class bs_mod_name_prio5(bs_mod_name): + prio = 5 + +class bs_mod_name_prio6(bs_mod_name): + prio = 6 + +branch_to_reg = bs_mod_name_prio4(l=1, mn_mod=['LR', 'CTR'], fname='btoreg') +branch_lk = bs_mod_name_prio5(l=1, mn_mod=['', 'L'], fname='lk') +branch_aa = bs_mod_name_prio6(l=1, mn_mod=['', 'A'], fname='aa') + +ppcop("arith1", [bs_arith1_name, rd, ra, s16imm]) +ppcop("ADDIS", [bs('001111'), rd, ra_or_0, u16imm]) +ppcop("ADDI", [bs('001110'), rd, ra_or_0, s16imm]) + +ppcop("logic2", [bs_name(l=6, name=logic2_name), rs, ra, u16imm], + [ra, rs, u16imm]) +ppcop("slogic2", [bs_name(l=6, name=slogic2_name), rs, ra, u16imm], + [ra, rs, u16imm]) + +ppcop("store1", [bs('011111'), rs, ra_or_0, rb, + bs_name(l=11, name=store1_name)]) +ppcop("store1u", [bs('011111'), rs, ra, rb, + bs_name(l=11, name=store1_name_u)]) + +ppcop("store2", [bs('10'), bs_name(l=4, name=store2_name), rs, + ra_noarg, dregimm]) +ppcop("store2u", [bs('10'), bs_name(l=4, name=store2_name_u), rs, + ra_or_0_noarg, dregimm]) + +ppcop("arith3", [bs('011111'), rd, ra, rb, bs_name(l=10, name=arith3_name), + rc_mod]) + +ppcop("xor", [bs('011111'), rs, ra, rb, bs_name(l=10, name=xor_name), + rc_mod], [ra, rs, rb]) + +ppcop("arith4", [bs('011111'), rd, ra, bs('00000'), + bs_name(l=10, name=arith4_name), rc_mod]) + +ppcop("arith5", [bs('011111'), rs, ra, bs('00000'), + bs_name(l=5, name=arith5_name), + bs('11010'), rc_mod], [ra, rs]) + +ppcop("load1", [bs('011111'), rd, ra_or_0, rb, + bs_name(l=10, name=load1_name), bs('0')]) +ppcop("load1u", [bs('011111'), rd, ra, rb, + bs_name(l=10, name=load1_name_u), bs('0')]) +ppcop("load2", [bs('10'), bs_name(l=4, name=load2_name), + rd, ra_or_0_noarg, dregimm]) +ppcop("load2u", [bs('10'), bs_name(l=4, name=load2_name_u), + rd, ra_noarg, dregimm]) + +ppcop("logic1", [bs('011111'), rs, ra, rb, bs_name(l=10, name=logic1_name), + rc_mod], + [ra, rs, rb]) + +ppcop("TWI", [bs('000011'), u05imm, ra, s16imm]) +ppcop("TW", [bs('011111'), u05imm, ra, rb, bs('00000001000')]) + +ppcop("CMPW", [bs('011111'), crfd, bs('00'), ra, rb, bs('00000000000')]) +ppcop("CMPLW", [bs('011111'), crfd, bs('00'), ra, rb, bs('00001000000')]) +ppcop("CMPLWI", [bs('001010'), crfd, bs('00'), ra, u16imm]) +ppcop("CMPWI", [bs('001011'), crfd, bs('00'), ra, s16imm]) + +ppcop("BC", [bs('010000'), bs(l=5, cls=(ppc_u05imm,), fname='bo'), + crfs, + ppc_divert_conditional_branch(l=2, fname='bi'), + s14imm_branch, branch_aa, branch_lk]) +ppcop("SC", [bs('01000100000000000000000000000010')]) +ppcop("B", [bs('010010'), s24imm_branch, branch_aa, branch_lk]) +ppcop("MCRF", [bs('010011'), crfd, bs('00'), crfs, bs('000000000000000000')]) + +ppcop("BCXXX", [bs('010011'), bs(l=5, cls=(ppc_u05imm,), fname='bo'), + crfs, + ppc_divert_conditional_branch(l=2, fname='bi'), + bs('00000'), branch_to_reg, + bs('000010000'), branch_lk]) + +ppcop("crlogic", [bs('010011'), + bs(l=5, cls=(ppc_u05imm,), fname='crbd'), + bs(l=5, cls=(ppc_u05imm,), fname='crba'), + bs(l=5, cls=(ppc_u05imm,), fname='crbb'), + bs('0'), + bs_name(l=4, name=crlogic_name), + bs('000010')]) + +ppcop("rotins", [bs_name(l=6, name=rotins_name), + rs, ra, sh, mb, me, rc_mod], + [ ra, rs, sh, mb, me ]) +ppcop("RLWNM", [bs('010111'), rs, ra, rb, mb, me, rc_mod], + [ ra, rs, rb, mb, me ]) +ppcop("MFXXX", [bs('011111'), rd, bs('0000000000'), + bs('000'), + bs_name(l=1, name={'MFCR':0, 'MFMSR':1}), + bs('0100110')]) + +ppcop("dcb", [bs('01111100000'), ra, rb, bs_name(l=5, name=dcb_name), + bs('101100')]) + +ppcop("MTCRF", [bs('011111'), rs, bs('0'), crm, bs('000100100000')], [crm, rs]) +ppcop("MTMSR", [bs('011111'), rs, bs('0000000000'), bs('00100100100')]) +ppcop("MTSR", [bs('011111'), rs, bs('0'), sr, bs('0000000110100100')], [sr, rs]) +ppcop("MTSRIN", [bs('011111'), rs, bs('00000'), rb, bs('00111100100')]) + +ppcop("TLBIE", [bs('011111'), bs('0000000000'), rb, bs('01001100100')]) +ppcop("MFSPR", [bs('011111'), rd, spr, bs('01010100110')]) +ppcop("TLBIA", [bs('01111100000000000000001011100100')]) +ppcop("MFTB", [bs('011111'), rd, tbr, bs('01011100110')]) +ppcop("RFI", [bs('01001100000000000000000001100100')]) +ppcop("ISYNC", [bs('01001100000000000000000100101100')]) +ppcop("MTSPR", [bs('011111'), rs, spr, bs('01110100110')], [spr, rs]) +ppcop("MCRXR", [bs('011111'), crfd, bs('000000000000'), + bs('10000000000')]) +ppcop("TLBSYNC", [bs('01111100000000000000010001101100')]) +ppcop("MFSR", [bs('011111'), rd, bs('0'), sr, bs('00000'), bs('10010100110')]) +ppcop("LSWI", [bs('011111'), rd, ra, nb, bs('10010101010')]) +ppcop("STSWI", [bs('011111'), rs, ra, nb, bs('10110101010')]) +ppcop("SYNC", [bs('011111'), bs('000000000000000'), bs('10010101100')]) +ppcop("MFSRIN", [bs('011111'), rd, bs('00000'), rb, bs('10100100110')]) + +ppcop("SRAWI", [bs('011111'), rs, ra, sh, bs('1100111000'), rc_mod], + [ra, rs, sh]) + +ppcop("EIEIO", [bs('011111'), bs('000000000000000'), bs('11010101100')]) + +ppcop("load1f", [bs_name(l=6, name=load1_name_float), frd, ra_noarg, dregimm]) +ppcop("load1fu", [bs_name(l=6, name=load1_name_float_u), frd, ra_noarg, dregimm]) +ppcop("store1f", [bs_name(l=6, name=store1_name_float), frd, ra_noarg, dregimm]) +ppcop("store1fu", [bs_name(l=6, name=store1_name_float_u), frd, ra_noarg, dregimm]) +ppcop("MTFSF", [bs('111111'), bs('0'), fm, bs('0'), frb, bs('10110001110')]) +ppcop("MTFSF.", [bs('111111'), bs('0'), fm, bs('0'), frb, bs('10110001111')]) +ppcop("MFFS", [bs('111111'), frd, bs('00000000001001000111'), bs('0')]) +ppcop("MFFS.", [bs('111111'), frd, bs('00000000001001000111'), bs('1')]) + +ppcop("load1vex", [bs('011111'), vd, ra, rb, bs_name(l=10, name=load1_name_vex), bs('0')]) +ppcop("mtvscr", [bs('0001000000000000'), vb, bs('11001000100')]) diff --git a/src/miasm/arch/ppc/disasm.py b/src/miasm/arch/ppc/disasm.py new file mode 100644 index 00000000..b91d96bf --- /dev/null +++ b/src/miasm/arch/ppc/disasm.py @@ -0,0 +1,7 @@ +from miasm.arch.ppc.arch import mn_ppc +from miasm.core.asmblock import disasmEngine + +class dis_ppc32b(disasmEngine): + def __init__(self, bs=None, **kwargs): + super(dis_ppc32b, self).__init__(mn_ppc, None, bs, **kwargs) + self.attrib = 'b' diff --git a/src/miasm/arch/ppc/jit.py b/src/miasm/arch/ppc/jit.py new file mode 100644 index 00000000..dcaff82c --- /dev/null +++ b/src/miasm/arch/ppc/jit.py @@ -0,0 +1,70 @@ +from builtins import range +from miasm.jitter.jitload import Jitter, named_arguments +from miasm.arch.ppc.sem import Lifter_PPC32b +import struct + +import logging + +log = logging.getLogger('jit_ppc') +hnd = logging.StreamHandler() +hnd.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) +log.addHandler(hnd) +log.setLevel(logging.CRITICAL) + +class jitter_ppc32b(Jitter): + max_reg_arg = 8 + + def __init__(self, loc_db, *args, **kwargs): + super(jitter_ppc32b, self).__init__(Lifter_PPC32b(loc_db), + *args, **kwargs) + self.vm.set_big_endian() + + def push_uint32_t(self, v): + self.cpu.R1 -= 4 + self.vm.set_mem(self.cpu.R1, struct.pack(">I", v)) + + def pop_uint32_t(self): + x = struct.unpack(">I", self.vm.get_mem(self.cpu.R1, 4))[0] + self.cpu.R1 += 4 + return x + + def get_stack_arg(self, n): + x = struct.unpack(">I", self.vm.get_mem(self.cpu.R1 + 8 + 4 * n, 4))[0] + return x + + @named_arguments + def func_args_systemv(self, n_args): + args = [self.get_arg_n_systemv(i) for i in range(n_args)] + ret_ad = self.cpu.LR + return ret_ad, args + + def func_ret_systemv(self, ret_addr, ret_value1=None, ret_value2=None): + self.pc = self.cpu.PC = ret_addr + if ret_value1 is not None: + self.cpu.R3 = ret_value1 + if ret_value2 is not None: + self.cpu.R4 = ret_value2 + return True + + def func_prepare_systemv(self, ret_addr, *args): + for index in range(min(len(args), self.max_reg_arg)): + setattr(self.cpu, 'R%d' % (index + 3), args[index]) + for index in range(len(args) - 1, self.max_reg_arg - 1, -1): + self.push_uint32_t(args[index]) + + # reserve room for LR save word and backchain + self.cpu.R1 -= 8 + + self.cpu.LR = ret_addr + + def get_arg_n_systemv(self, index): + if index < self.max_reg_arg: + arg = getattr(self.cpu, 'R%d' % (index + 3)) + else: + arg = self.get_stack_arg(index - self.max_reg_arg) + return arg + + + def init_run(self, *args, **kwargs): + Jitter.init_run(self, *args, **kwargs) + self.cpu.PC = self.pc diff --git a/src/miasm/arch/ppc/lifter_model_call.py b/src/miasm/arch/ppc/lifter_model_call.py new file mode 100644 index 00000000..06691190 --- /dev/null +++ b/src/miasm/arch/ppc/lifter_model_call.py @@ -0,0 +1,87 @@ +from miasm.expression.expression import ExprAssign, ExprOp +from miasm.ir.ir import AssignBlock +from miasm.ir.analysis import LifterModelCall +from miasm.arch.ppc.sem import Lifter_PPC32b + + +class LifterModelCallPpc32b(Lifter_PPC32b, LifterModelCall): + + def __init__(self, loc_db, *args): + super(LifterModelCallPpc32b, self).__init__(loc_db, *args) + self.ret_reg = self.arch.regs.R3 + + # for test XXX TODO + def set_dead_regs(self, irblock): + pass + + def get_out_regs(self, _): + return set([self.ret_reg, self.sp]) + + def add_unused_regs(self): + leaves = [self.blocks[label] for label in self.g.leafs()] + for irblock in leaves: + self.set_dead_regs(irblock) + + def call_effects(self, ad, instr): + call_assignblks = AssignBlock( + [ + ExprAssign( + self.ret_reg, + ExprOp( + 'call_func_ret', + ad, + self.sp, + self.arch.regs.R3, + self.arch.regs.R4, + self.arch.regs.R5, + ) + ), + ExprAssign(self.sp, ExprOp('call_func_stack', ad, self.sp)), + ], + instr + ) + return [call_assignblks], [] + + def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt): + """ + Add the IR effects of an instruction to the current state. + + @instr: native instruction + @block: native block source + @assignments: list of current AssignBlocks + @ir_blocks_all: list of additional effects + @gen_pc_updt: insert PC update effects between instructions + """ + if instr.is_subcall(): + call_assignblks, extra_irblocks = self.call_effects( + instr.getdstflow(None)[0], + instr + ) + assignments += call_assignblks + ir_blocks_all += extra_irblocks + return True + + if gen_pc_updt is not False: + self.gen_pc_update(assignments, instr) + + assignblk, ir_blocks_extra = self.instr2ir(instr) + assignments.append(assignblk) + ir_blocks_all += ir_blocks_extra + if ir_blocks_extra: + return True + return False + + def sizeof_char(self): + return 8 + + def sizeof_short(self): + return 16 + + def sizeof_int(self): + return 32 + + def sizeof_long(self): + return 32 + + def sizeof_pointer(self): + return 32 diff --git a/src/miasm/arch/ppc/regs.py b/src/miasm/arch/ppc/regs.py new file mode 100644 index 00000000..00781d6a --- /dev/null +++ b/src/miasm/arch/ppc/regs.py @@ -0,0 +1,77 @@ + +from builtins import range +from miasm.expression.expression import * +from miasm.core.cpu import gen_reg, gen_regs + +exception_flags = ExprId('exception_flags', 32) +spr_access = ExprId('spr_access', 32) + +reserve = ExprId('reserve', 1) +reserve_address = ExprId('reserve_address', 32) + +SPR_ACCESS_IS_WRITE = 0x80000000 +SPR_ACCESS_SPR_MASK = 0x000003FF +SPR_ACCESS_SPR_OFF = 0 +SPR_ACCESS_GPR_MASK = 0x0001F000 +SPR_ACCESS_GPR_OFF = 12 + +gpregs_str = ["R%d" % i for i in range(32)] +gpregs_expr, gpregs_init, gpregs = gen_regs(gpregs_str, globals(), 32) + +crfregs_str = ["CR%d" % i for i in range(8)] +crfregs_expr, crfregs_init, crfregs = gen_regs(crfregs_str, globals(), 4) + +crfbitregs_str = ["CR%d_%s" % (i, flag) for i in range(8) + for flag in ['LT', 'GT', 'EQ', 'SO'] ] +crfbitregs_expr, crfbitregs_init, crfbitregs = gen_regs(crfbitregs_str, + globals(), 1) + +xerbitregs_str = ["XER_%s" % field for field in ['SO', 'OV', 'CA'] ] +xerbitregs_expr, xerbitregs_init, xerbitregs = gen_regs(xerbitregs_str, + globals(), 1) + +xerbcreg_str = ["XER_BC"] +xerbcreg_expr, xerbcreg_init, xerbcreg = gen_regs(xerbcreg_str, + globals(), 7) + + +otherregs_str = ["PC", "CTR", "LR", "FPSCR", "VRSAVE", "VSCR" ] +otherregs_expr, otherregs_init, otherregs = gen_regs(otherregs_str, + globals(), 32) + +superregs_str = (["SPRG%d" % i for i in range(4)] + + ["SRR%d" % i for i in range(2)] + + ["DAR", "DSISR", "MSR", "PIR", "PVR", + "DEC", "TBL", "TBU"]) +superregs_expr, superregs_init, superregs = gen_regs(superregs_str, + globals(), 32) + +mmuregs_str = (["SR%d" % i for i in range(16)] + + ["IBAT%dU" % i for i in range(4)] + + ["IBAT%dL" % i for i in range(4)] + + ["DBAT%dU" % i for i in range(4)] + + ["DBAT%dL" % i for i in range(4)] + + ["SDR1"]) +mmuregs_expr, mmuregs_init, mmuregs = gen_regs(mmuregs_str, + globals(), 32) + +floatregs_str = (["FPR%d" % i for i in range(32)]) +floatregs_expr, floatregs_init, floatregs = gen_regs(floatregs_str, + globals(), 64) + +vexregs_str = (["VR%d" % i for i in range(32)]) +vexregs_expr, vexregs_init, vexregs = gen_regs(vexregs_str, + globals(), 128) + +regs_flt_expr = [] + +all_regs_ids = (gpregs_expr + crfbitregs_expr + xerbitregs_expr + + xerbcreg_expr + otherregs_expr + superregs_expr + mmuregs_expr + floatregs_expr + vexregs_expr + + [ exception_flags, spr_access, reserve, reserve_address ]) +all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids]) +all_regs_ids_init = [ExprId("%s_init" % x.name, x.size) for x in all_regs_ids] +all_regs_ids_no_alias = all_regs_ids[:] + +regs_init = {} +for i, r in enumerate(all_regs_ids): + regs_init[r] = all_regs_ids_init[i] diff --git a/src/miasm/arch/ppc/sem.py b/src/miasm/arch/ppc/sem.py new file mode 100644 index 00000000..7fbf61e6 --- /dev/null +++ b/src/miasm/arch/ppc/sem.py @@ -0,0 +1,981 @@ +from __future__ import print_function +from builtins import range + +import miasm.expression.expression as expr +from miasm.ir.ir import AssignBlock, Lifter, IRBlock +from miasm.arch.ppc.arch import mn_ppc +from miasm.arch.ppc.regs import * +from miasm.core.sembuilder import SemBuilder +from miasm.jitter.csts import * + +spr_dict = { + 8: LR, 9: CTR, 18: DSISR, 19: DAR, + 22: DEC, 25: SDR1, 26: SRR0, 27: SRR1, + 272: SPRG0, 273: SPRG0, 274: SPRG1, 275: SPRG2, 276: SPRG3, + 284: TBL, 285: TBU, 287: PVR, + 528: IBAT0U, 529: IBAT0L, 530: IBAT1U, 531: IBAT1L, 532: IBAT2U, 533: IBAT2L, 534: IBAT3U, 535: IBAT3L, + 536: DBAT0U, 537: DBAT0L, 538: DBAT1U, 539: DBAT1L, 540: DBAT2U, 541: DBAT2L, 542: DBAT3U, 543: DBAT3L, + 1023: PIR +} + +sr_dict = { + 0: SR0, 1: SR1, 2: SR2, 3: SR3, + 4: SR4, 5: SR5, 6: SR6, 7: SR7, + 8: SR8, 9: SR9, 10: SR10, 11: SR11, + 12: SR12, 13: SR13, 14: SR14, 15: SR15 +} + +float_dict = { + 0: FPR0, 1: FPR1, 2: FPR2, 3: FPR3, 4: FPR4, 5: FPR5, 6: FPR6, 7: FPR7, 8: FPR8, + 9: FPR9, 10: FPR10, 11: FPR11, 12: FPR12, 13: FPR13, 14: FPR14, 15: FPR15, 16: FPR16, + 17: FPR17, 18: FPR18, 19: FPR19, 20: FPR20, 21: FPR21, 22: FPR22, 23: FPR23, 24: FPR24, + 25: FPR25, 26: FPR26, 27: FPR27, 28: FPR28, 29: FPR29, 30: FPR30, 31: FPR31 +} + +vex_dict = { + 0: VR0, 1: VR1, 2: VR2, 3: VR3, 4: VR4, 5: VR5, 6: VR6, 7: VR7, 8: VR8, + 9: VR9, 10: VR10, 11: VR11, 12: VR12, 13: VR13, 14: VR14, 15: VR15, 16: VR16, + 17: VR17, 18: VR18, 19: VR19, 20: VR20, 21: VR21, 22: VR22, 23: VR23, 24: VR24, + 25: VR25, 26: VR26, 27: VR27, 28: VR28, 29: VR29, 30: VR30, 31: VR31, +} + +crf_dict = dict((ExprId("CR%d" % i, 4), + dict( (bit, ExprId("CR%d_%s" % (i, bit), 1)) + for bit in ['LT', 'GT', 'EQ', 'SO' ] )) + for i in range(8) ) + +ctx = { + 'crf_dict': crf_dict, + 'spr_dict': spr_dict, + 'sr_dict': sr_dict, + 'float_dict': float_dict, + 'vex_dict': vex_dict, + 'expr': expr, +} + +ctx.update(all_regs_ids_byname) +sbuild = SemBuilder(ctx) + +def mn_compute_flags(rvalue, overflow_expr=None): + ret = [] + ret.append(ExprAssign(CR0_LT, rvalue.msb())) + ret.append(ExprAssign(CR0_GT, (ExprCond(rvalue, ExprInt(1, 1), + ExprInt(0, 1)) & ~rvalue.msb()))) + ret.append(ExprAssign(CR0_EQ, ExprCond(rvalue, ExprInt(0, 1), + ExprInt(1, 1)))) + if overflow_expr != None: + ret.append(ExprAssign(CR0_SO, XER_SO | overflow_expr)) + else: + ret.append(ExprAssign(CR0_SO, XER_SO)) + + return ret + +def mn_do_add(ir, instr, arg1, arg2, arg3): + assert instr.name[0:3] == 'ADD' + + flags_update = [] + + has_dot = False + has_c = False + has_e = False + has_o = False + + for l in instr.name[3:]: + if l == '.': + has_dot = True + elif l == 'C': + has_c = True + elif l == 'E': + has_e = True + elif l == 'O': + has_o = True + elif l == 'I' or l == 'M' or l == 'S' or l == 'Z': + pass # Taken care of earlier + else: + assert False + + rvalue = arg2 + arg3 + + if has_e: + rvalue = rvalue + XER_CA.zeroExtend(32) + + over_expr = None + if has_o: + msb1 = arg2.msb() + msb2 = arg3.msb() + msba = rvalue.msb() + over_expr = ~(msb1 ^ msb2) & (msb1 ^ msba) + flags_update.append(ExprAssign(XER_OV, over_expr)) + flags_update.append(ExprAssign(XER_SO, XER_SO | over_expr)) + + if has_dot: + flags_update += mn_compute_flags(rvalue, over_expr) + + if has_c or has_e: + carry_expr = (((arg2 ^ arg3) ^ rvalue) ^ + ((arg2 ^ rvalue) & (~(arg2 ^ arg3)))).msb() + flags_update.append(ExprAssign(XER_CA, carry_expr)) + + return ([ ExprAssign(arg1, rvalue) ] + flags_update), [] + +def mn_do_and(ir, instr, ra, rs, arg2): + if len(instr.name) > 3 and instr.name[3] == 'C': + oarg = ~arg2 + else: + oarg = arg2 + + rvalue = rs & oarg + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_cntlzw(ir, instr, ra, rs): + ret = [ ExprAssign(ra, ExprOp('cntleadzeros', rs)) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def crbit_to_reg(bit): + bit = int(bit) + crid = bit // 4 + bitname = [ 'LT', 'GT', 'EQ', 'SO' ][bit % 4] + return all_regs_ids_byname["CR%d_%s" % (crid, bitname)] + +def mn_do_cr(ir, instr, crd, cra, crb): + a = crbit_to_reg(cra) + b = crbit_to_reg(crb) + d = crbit_to_reg(crd) + + op = instr.name[2:] + + if op == 'AND': + r = a & b + elif op == 'ANDC': + r = a & ~b + elif op == 'EQV': + r = ~(a ^ b) + elif op == 'NAND': + r = ~(a & b) + elif op == 'NOR': + r = ~(a | b) + elif op == 'OR': + r = a | b + elif op == 'ORC': + r = a | ~b + elif op == 'XOR': + r = a ^ b + else: + raise RuntimeError("Unknown operation on CR") + return [ ExprAssign(d, r) ], [] + +def mn_do_div(ir, instr, rd, ra, rb): + assert instr.name[0:4] == 'DIVW' + + flags_update = [] + + has_dot = False + has_c = False + has_o = False + has_u = False + + for l in instr.name[3:]: + if l == '.': + has_dot = True + elif l == 'C': + has_c = True + elif l == 'O': + has_o = True + elif l == 'U': + has_u = True + elif l == 'W': + pass + else: + assert False + + if has_u: + op = 'udiv' + else: + op = 'sdiv' + + rvalue = ExprOp(op, ra, rb) + + over_expr = None + if has_o: + over_expr = ExprCond(rb, ExprInt(0, 1), ExprInt(1, 1)) + if not has_u: + over_expr = over_expr | (ExprCond(ra ^ 0x80000000, ExprInt(0, 1), + ExprInt(1, 1)) & + ExprCond(rb ^ 0xFFFFFFFF, ExprInt(0, 1), + ExprInt(1, 1))) + flags_update.append(ExprAssign(XER_OV, over_expr)) + flags_update.append(ExprAssign(XER_SO, XER_SO | over_expr)) + + if has_dot: + flags_update += mn_compute_flags(rvalue, over_expr) + + return ([ ExprAssign(rd, rvalue) ] + flags_update), [] + + +def mn_do_eqv(ir, instr, ra, rs, rb): + rvalue = ~(rs ^ rb) + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_exts(ir, instr, ra, rs): + if instr.name[4] == 'B': + size = 8 + elif instr.name[4] == 'H': + size = 16 + else: + assert False + + rvalue = rs[0:size].signExtend(32) + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def byte_swap(expr): + nbytes = expr.size // 8 + lbytes = [ expr[i*8:i*8+8] for i in range(nbytes - 1, -1, -1) ] + return ExprCompose(*lbytes) + +def mn_do_load(ir, instr, arg1, arg2, arg3=None): + assert instr.name[0] == 'L' + + ret = [] + + if instr.name[1] == 'M': + return mn_do_lmw(ir, instr, arg1, arg2) + elif instr.name[1] == 'S': + raise RuntimeError("LSWI, and LSWX need implementing") + elif instr.name[1] == 'F': + print("Warning, instruction %s implemented as NOP" % instr) + return [], [] + elif instr.name[1] == 'V': + print("Warning, instruction %s implemented as NOP" % instr) + return [], [] + + size = {'B': 8, 'H': 16, 'W': 32}[instr.name[1]] + + has_a = False + has_b = False + has_u = False + is_lwarx = False + + for l in instr.name[2:]: + if l == 'A': + has_a = True + elif l == 'B': + has_b = True + elif l == 'U': + has_u = True + elif l == 'X' or l == 'Z': + pass # Taken care of earlier + elif l == 'R' and not has_b: + is_lwarx = True + else: + assert False + + if arg3 is None: + assert isinstance(arg2, ExprMem) + + address = arg2.ptr + else: + address = arg2 + arg3 + + src = ExprMem(address, size) + + if has_b: + src = byte_swap(src) + + if has_a: + src = src.signExtend(32) + else: + src = src.zeroExtend(32) + + ret.append(ExprAssign(arg1, src)) + if has_u: + if arg3 is None: + ret.append(ExprAssign(arg2.ptr.args[0], address)) + else: + ret.append(ExprAssign(arg2, address)) + + if is_lwarx: + ret.append(ExprAssign(reserve, ExprInt(1, 1))) + ret.append(ExprAssign(reserve_address, address)) # XXX should be the PA + + return ret, [] + +def mn_do_lmw(ir, instr, rd, src): + ret = [] + address = src.ptr + ri = int(rd.name[1:],10) + i = 0 + while ri <= 31: + ret.append(ExprAssign(all_regs_ids_byname["R%d" % ri], + ExprMem(address + ExprInt(i, 32), 32))) + ri += 1 + i += 4 + + return ret, [] + +def mn_do_lswi(ir, instr, rd, ra, nb): + if nb == 0: + nb = 32 + i = 32 + raise RuntimeError("%r not implemented" % instr) + +def mn_do_lswx(ir, instr, rd, ra, nb): + raise RuntimeError("%r not implemented" % instr) + +def mn_do_mcrf(ir, instr, crfd, crfs): + ret = [] + + for bit in [ 'LT', 'GT', 'EQ', 'SO' ]: + d = all_regs_ids_byname["%s_%s" % (crfd, bit)] + s = all_regs_ids_byname["%s_%s" % (crfs, bit)] + ret.append(ExprAssign(d, s)) + + return ret, [] + +def mn_do_mcrxr(ir, instr, crfd): + ret = [] + + for (bit, val) in [ ('LT', XER_SO), ('GT', XER_OV), ('EQ', XER_CA), + ('SO', ExprInt(0, 1)) ]: + ret.append(ExprAssign(all_regs_ids_byname["%s_%s" % (crfd, bit)], val)) + + return ret, [] + +def mn_do_mfcr(ir, instr, rd): + return ([ ExprAssign(rd, ExprCompose(*[ all_regs_ids_byname["CR%d_%s" % (i, b)] + for i in range(7, -1, -1) + for b in ['SO', 'EQ', 'GT', 'LT']]))], + []) + +@sbuild.parse +def mn_mfmsr(rd): + rd = MSR + +def mn_mfspr(ir, instr, arg1, arg2): + sprid = int(arg2) + gprid = int(arg1.name[1:]) + if sprid in spr_dict: + return [ ExprAssign(arg1, spr_dict[sprid]) ], [] + elif sprid == 1: # XER + return [ ExprAssign(arg1, ExprCompose(XER_BC, ExprInt(0, 22), + XER_CA, XER_OV, XER_SO)) ], [] + else: + return [ ExprAssign(spr_access, + ExprInt(((sprid << SPR_ACCESS_SPR_OFF) | + (gprid << SPR_ACCESS_GPR_OFF)), 32)), + ExprAssign(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], [] + +def mn_mtcrf(ir, instr, crm, rs): + ret = [] + + for i in range(8): + if int(crm) & (1 << (7 - i)): + j = (28 - 4 * i) + 3 + for b in ['LT', 'GT', 'EQ', 'SO']: + ret.append(ExprAssign(all_regs_ids_byname["CR%d_%s" % (i, b)], + rs[j:j+1])) + j -= 1 + + return ret, [] + +def mn_mtmsr(ir, instr, rs): + print("%08x: MSR assigned" % instr.offset) + return [ ExprAssign(MSR, rs) ], [] + +def mn_mtspr(ir, instr, arg1, arg2): + sprid = int(arg1) + gprid = int(arg2.name[1:]) + if sprid in spr_dict: + return [ ExprAssign(spr_dict[sprid], arg2) ], [] + elif sprid == 1: # XER + return [ ExprAssign(XER_SO, arg2[31:32]), + ExprAssign(XER_OV, arg2[30:31]), + ExprAssign(XER_CA, arg2[29:30]), + ExprAssign(XER_BC, arg2[0:7]) ], [] + else: + return [ ExprAssign(spr_access, + ExprInt(((sprid << SPR_ACCESS_SPR_OFF) | + (gprid << SPR_ACCESS_GPR_OFF) | + SPR_ACCESS_IS_WRITE), 32)), + ExprAssign(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], [] + +def mn_mtsr(ir, instr, sr, rs): + srid = sr.arg + return [ ExprAssign(sr_dict[srid], rs) ], [] + +# TODO +#def mn_mtsrin(ir, instr, rs, rb): +# return [ ExprAssign(sr_dict[rb[0:3]], rs) ], [] + +def mn_mfsr(ir, instr, rd, sr): + srid = sr.arg + return [ ExprAssign(rd, sr_dict[srid]) ], [] + +# TODO +#def mn_mfsrin(ir, instr, rd, rb): +# return [ ExprAssign(rd, sr_dict[rb[0:3]]) ], [] + +def mn_do_mul(ir, instr, rd, ra, arg2): + variant = instr.name[3:] + if variant[-1] == '.': + variant = variant[:-2] + + if variant == 'HW': + v1 = ra.signExtend(64) + v2 = arg2.signExtend(64) + shift = 32 + elif variant == 'HWU': + v1 = ra.zeroExtend(64) + v2 = arg2.zeroExtend(64) + shift = 32 + else: + v1 = ra + v2 = arg2 + shift = 0 + + rvalue = ExprOp('*', v1, v2) + if shift != 0: + rvalue = rvalue[shift : shift + 32] + + ret = [ ExprAssign(rd, rvalue) ] + + over_expr = None + if variant[-1] == 'O': + over_expr = ExprCond((rvalue.signExtend(64) ^ + ExprOp('*', v1.signExtend(64), + v2.signExtend(64))), + ExprInt(1, 1), ExprInt(0, 1)) + ret.append(ExprAssign(XER_OV, over_expr)) + ret.append(ExprAssign(XER_SO, XER_SO | over_expr)) + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue, over_expr) + + return ret, [] + +def mn_do_nand(ir, instr, ra, rs, rb): + rvalue = ~(rs & rb) + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_neg(ir, instr, rd, ra): + rvalue = -ra + ret = [ ExprAssign(rd, rvalue) ] + has_o = False + + over_expr = None + if instr.name[-1] == 'O' or instr.name[-2] == 'O': + has_o = True + over_expr = ExprCond(ra ^ ExprInt(0x80000000, 32), + ExprInt(0, 1), ExprInt(1, 1)) + ret.append(ExprAssign(XER_OV, over_expr)) + ret.append(ExprAssign(XER_SO, XER_SO | over_expr)) + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue, over_expr) + + return ret, [] + +def mn_do_nor(ir, instr, ra, rs, rb): + + rvalue = ~(rs | rb) + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_or(ir, instr, ra, rs, arg2): + if len(instr.name) > 2 and instr.name[2] == 'C': + oarg = ~arg2 + else: + oarg = arg2 + + rvalue = rs | oarg + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_rfi(ir, instr): + dest = ExprCompose(ExprInt(0, 2), SRR0[2:32]) + ret = [ ExprAssign(MSR, (MSR & + ~ExprInt(0b1111111101110011, 32) | + ExprCompose(SRR1[0:2], ExprInt(0, 2), + SRR1[4:7], ExprInt(0, 1), + SRR1[8:16], ExprInt(0, 16)))), + ExprAssign(PC, dest), + ExprAssign(ir.IRDst, dest) ] + return ret, [] + +def mn_do_rotate(ir, instr, ra, rs, shift, mb, me): + r = ExprOp('<<<', rs, shift) + if mb <= me: + m = ExprInt(((1 << (32 - mb)) - 1) & ~((1 << (32 - me - 1)) - 1), 32) + else: + m = ExprInt(((1 << (32 - mb)) - 1) | ~((1 << (32 - me - 1)) - 1), 32) + rvalue = r & m + if instr.name[0:6] == 'RLWIMI': + rvalue = rvalue | (ra & ~m) + + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_slw(ir, instr, ra, rs, rb): + + rvalue = ExprCond(rb[5:6], ExprInt(0, 32), + ExprOp('<<', rs, rb & ExprInt(0b11111, 32))) + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_sraw(ir, instr, ra, rs, rb): + rvalue = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), + ExprOp('a>>', rs, rb & ExprInt(0b11111, 32))) + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + mask = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), + (ExprInt(0xFFFFFFFF, 32) >> + (ExprInt(32, 32) - (rb & ExprInt(0b11111, 32))))) + ret.append(ExprAssign(XER_CA, rs.msb() & + ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) + + return ret, [] + +def mn_do_srawi(ir, instr, ra, rs, imm): + rvalue = ExprOp('a>>', rs, imm) + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + mask = ExprInt(0xFFFFFFFF >> (32 - int(imm)), 32) + + ret.append(ExprAssign(XER_CA, rs.msb() & + ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) + + return ret, [] + +def mn_do_srw(ir, instr, ra, rs, rb): + rvalue = rs >> (rb & ExprInt(0b11111, 32)) + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_stmw(ir, instr, rs, dest): + ret = [] + address = dest.ptr + ri = int(rs.name[1:],10) + i = 0 + while ri <= 31: + ret.append(ExprAssign(ExprMem(address + ExprInt(i,32), 32), + all_regs_ids_byname["R%d" % ri])) + ri += 1 + i += 4 + + return ret, [] + +def mn_do_store(ir, instr, arg1, arg2, arg3=None): + assert instr.name[0:2] == 'ST' + + ret = [] + additional_ir = [] + + if instr.name[2] == 'S': + raise RuntimeError("STSWI, and STSWX need implementing") + elif instr.name[2] == 'F': + print("Warning, instruction %s implemented as NOP" % instr) + return [], [] + + size = {'B': 8, 'H': 16, 'W': 32}[instr.name[2]] + + has_b = False + has_u = False + is_stwcx = False + + for l in instr.name[3:]: + if l == 'B' or l == 'R': + has_b = True + elif l == 'U': + has_u = True + elif l == 'X' or l == 'Z': + pass # Taken care of earlier + elif l == 'C' or l == '.': + is_stwcx = True + else: + assert False + + if arg3 is None: + assert isinstance(arg2, ExprMem) + + address = arg2.ptr + else: + address = arg2 + arg3 + + dest = ExprMem(address, size) + + src = arg1[0:size] + if has_b: + src = byte_swap(src) + + ret.append(ExprAssign(dest, src)) + if has_u: + if arg3 is None: + ret.append(ExprAssign(arg2.ptr.args[0], address)) + else: + ret.append(ExprAssign(arg2, address)) + + if is_stwcx: + loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) + loc_dont = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) + loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) + flags = [ ExprAssign(CR0_LT, ExprInt(0,1)), + ExprAssign(CR0_GT, ExprInt(0,1)), + ExprAssign(CR0_SO, XER_SO)] + ret += flags + ret.append(ExprAssign(CR0_EQ, ExprInt(1,1))) + ret.append(ExprAssign(ir.IRDst, loc_next)) + dont = flags + [ ExprAssign(CR0_EQ, ExprInt(0,1)), + ExprAssign(ir.IRDst, loc_next) ] + additional_ir = [ IRBlock(ir.loc_db, loc_do.loc_key, [ AssignBlock(ret) ]), + IRBlock(ir.loc_db, loc_dont.loc_key, [ AssignBlock(dont) ]) ] + ret = [ ExprAssign(reserve, ExprInt(0, 1)), + ExprAssign(ir.IRDst, ExprCond(reserve, loc_do, loc_dont)) ] + + return ret, additional_ir + +def mn_do_sub(ir, instr, arg1, arg2, arg3): + assert instr.name[0:4] == 'SUBF' + + flags_update = [] + + has_dot = False + has_c = False + has_e = False + has_o = False + + for l in instr.name[4:]: + if l == '.': + has_dot = True + elif l == 'C': + has_c = True + elif l == 'E': + has_e = True + elif l == 'O': + has_o = True + elif l == 'I' or l == 'M' or l == 'S' or l == 'Z': + pass # Taken care of earlier + else: + assert False + + if has_e: + arg3 = arg3 + XER_CA.zeroExtend(32) + arg2 = arg2 + ExprInt(1, 32) + + rvalue = arg3 - arg2 + + over_expr = None + if has_o: + msb1 = arg2.msb() + msb2 = arg3.msb() + msba = rvalue.msb() + over_expr = (msb1 ^ msb2) & (msb1 ^ msba) + flags_update.append(ExprAssign(XER_OV, over_expr)) + flags_update.append(ExprAssign(XER_SO, XER_SO | over_expr)) + + if has_dot: + flags_update += mn_compute_flags(rvalue, over_expr) + + if has_c or has_e: + carry_expr = ((((arg3 ^ arg2) ^ rvalue) ^ + ((arg3 ^ rvalue) & (arg3 ^ arg2))).msb()) + flags_update.append(ExprAssign(XER_CA, ~carry_expr)) + + return ([ ExprAssign(arg1, rvalue) ] + flags_update), [] + +def mn_do_xor(ir, instr, ra, rs, rb): + rvalue = rs ^ rb + ret = [ ExprAssign(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_b(ir, instr, arg1, arg2 = None): + if arg2 is not None: + arg1 = arg2 + return [ ExprAssign(PC, arg1), ExprAssign(ir.IRDst, arg1) ], [] + +def mn_bl(ir, instr, arg1, arg2 = None): + if arg2 is not None: + arg1 = arg2 + dst = ir.get_next_instr(instr) + return [ ExprAssign(LR, ExprLoc(dst, 32)), + ExprAssign(PC, arg1), + ExprAssign(ir.IRDst, arg1) ], [] + +def mn_get_condition(instr): + bit = instr.additional_info.bi & 0b11 + cr = instr.args[0].name + return all_regs_ids_byname[cr + '_' + ['LT', 'GT', 'EQ', 'SO'][bit]] + +def mn_do_cond_branch(ir, instr, dest): + bo = instr.additional_info.bo + bi = instr.additional_info.bi + ret = [] + + if bo & 0b00100: + ctr_cond = True + else: + ret.append(ExprAssign(CTR, CTR - ExprInt(1, 32))) + ctr_cond = ExprCond(CTR ^ ExprInt(1, 32), ExprInt(1, 1), ExprInt(0, 1)) + if bo & 0b00010: + ctr_cond = ~ctr_cond + + if (bo & 0b10000): + cond_cond = True + else: + cond_cond = mn_get_condition(instr) + if not (bo & 0b01000): + cond_cond = ~cond_cond + + if ctr_cond != True or cond_cond != True: + if ctr_cond != True: + condition = ctr_cond + if cond_cond != True: + condition = condition & cond_cond + else: + condition = cond_cond + dst = ir.get_next_instr(instr) + dest_expr = ExprCond(condition, dest, + ExprLoc(dst, 32)) + else: + dest_expr = dest + + if instr.name[-1] == 'L' or instr.name[-2:-1] == 'LA': + dst = ir.get_next_instr(instr) + ret.append(ExprAssign(LR, ExprLoc(dst, 32))) + + ret.append(ExprAssign(PC, dest_expr)) + ret.append(ExprAssign(ir.IRDst, dest_expr)) + + return ret, [] + +def mn_do_nop_warn(ir, instr, *args): + print("Warning, instruction %s implemented as NOP" % instr) + return [], [] + +@sbuild.parse +def mn_cmp_signed(arg1, arg2, arg3): + crf_dict[arg1]['LT'] = expr.ExprOp(expr.TOK_INF_SIGNED, arg2, arg3) + crf_dict[arg1]['GT'] = expr.ExprOp(expr.TOK_INF_SIGNED, arg3, arg2) + crf_dict[arg1]['EQ'] = expr.ExprOp(expr.TOK_EQUAL, arg2, arg3) + crf_dict[arg1]['SO'] = XER_SO + +@sbuild.parse +def mn_cmp_unsigned(arg1, arg2, arg3): + crf_dict[arg1]['LT'] = expr.ExprOp(expr.TOK_INF_UNSIGNED, arg2, arg3) + crf_dict[arg1]['GT'] = expr.ExprOp(expr.TOK_INF_UNSIGNED, arg3, arg2) + crf_dict[arg1]['EQ'] = expr.ExprOp(expr.TOK_EQUAL, arg2, arg3) + crf_dict[arg1]['SO'] = XER_SO + +def mn_nop(ir, instr, *args): + return [], [] + +@sbuild.parse +def mn_or(arg1, arg2, arg3): + arg1 = arg2 | arg3 + +@sbuild.parse +def mn_assign(arg1, arg2): + arg2 = arg1 + +def mn_stb(ir, instr, arg1, arg2): + dest = ExprMem(arg2.arg, 8) + return [ExprAssign(dest, ExprSlice(arg1, 0, 8))], [] + +@sbuild.parse +def mn_stwu(arg1, arg2): + arg2 = arg1 + arg1 = arg2.arg + +sem_dir = { + 'B': mn_b, + 'BA': mn_b, + 'BL': mn_bl, + 'BLA': mn_bl, + 'CMPLW': mn_cmp_unsigned, + 'CMPLWI': mn_cmp_unsigned, + 'CMPW': mn_cmp_signed, + 'CMPWI': mn_cmp_signed, + 'CNTLZW': mn_do_cntlzw, + 'CNTLZW.': mn_do_cntlzw, + 'ECIWX': mn_do_nop_warn, + 'ECOWX': mn_do_nop_warn, + 'EIEIO': mn_do_nop_warn, + 'EQV': mn_do_eqv, + 'EQV.': mn_do_eqv, + 'ICBI': mn_do_nop_warn, + 'ISYNC': mn_do_nop_warn, + 'MCRF': mn_do_mcrf, + 'MCRXR': mn_do_mcrxr, + 'MFCR': mn_do_mfcr, + 'MFFS': mn_do_nop_warn, + 'MFFS.': mn_do_nop_warn, + 'MFMSR': mn_mfmsr, + 'MFSPR': mn_mfspr, + 'MFSR': mn_mfsr, + 'MFSRIN': mn_do_nop_warn, + 'MTFSF': mn_do_nop_warn, + 'MTFSF.': mn_do_nop_warn, + 'MFTB': mn_mfspr, + 'MTCRF': mn_mtcrf, + 'MTMSR': mn_mtmsr, + 'MTSPR': mn_mtspr, + 'MTSR': mn_mtsr, + 'MTSRIN': mn_do_nop_warn, + 'MTVSCR': mn_do_nop_warn, + 'NAND': mn_do_nand, + 'NAND.': mn_do_nand, + 'NOR': mn_do_nor, + 'NOR.': mn_do_nor, + 'RFI': mn_do_rfi, + 'SC': mn_do_nop_warn, + 'SLW': mn_do_slw, + 'SLW.': mn_do_slw, + 'SRAW': mn_do_sraw, + 'SRAW.': mn_do_sraw, + 'SRAWI': mn_do_srawi, + 'SRAWI.': mn_do_srawi, + 'SRW': mn_do_srw, + 'SRW.': mn_do_srw, + 'SYNC': mn_do_nop_warn, + 'TLBIA': mn_do_nop_warn, + 'TLBIE': mn_do_nop_warn, + 'TLBSYNC': mn_do_nop_warn, + 'TW': mn_do_nop_warn, + 'TWI': mn_do_nop_warn, +} + + +class Lifter_PPC32b(Lifter): + + def __init__(self, loc_db): + super(Lifter_PPC32b, self).__init__(mn_ppc, 'b', loc_db) + self.pc = mn_ppc.getpc() + self.sp = mn_ppc.getsp() + self.IRDst = expr.ExprId('IRDst', 32) + self.addrsize = 32 + + def get_ir(self, instr): + args = instr.args[:] + if instr.name[0:5] in [ 'ADDIS', 'ORIS', 'XORIS', 'ANDIS' ]: + args[2] = ExprInt(int(args[2]) << 16, 32) + if instr.name[0:3] == 'ADD': + if instr.name[0:4] == 'ADDZ': + last_arg = ExprInt(0, 32) + elif instr.name[0:4] == 'ADDM': + last_arg = ExprInt(0xFFFFFFFF, 32) + else: + last_arg = args[2] + instr_ir, extra_ir = mn_do_add(self, instr, args[0], args[1], + last_arg) + elif instr.name[0:3] == 'AND': + instr_ir, extra_ir = mn_do_and(self, instr, *args) + elif instr.additional_info.bo_bi_are_defined: + name = instr.name + if name[-1] == '+' or name[-1] == '-': + name = name[0:-1] + if name[-3:] == 'CTR' or name[-4:] == 'CTRL': + arg1 = ExprCompose(ExprInt(0, 2), CTR[2:32]) + elif name[-2:] == 'LR' or name[-3:] == 'LRL': + arg1 = ExprCompose(ExprInt(0, 2), LR[2:32]) + else: + arg1 = args[1] + instr_ir, extra_ir = mn_do_cond_branch(self, instr, arg1) + elif instr.name[0:2] == 'CR': + instr_ir, extra_ir = mn_do_cr(self, instr, *args) + elif instr.name[0:3] == 'DCB': + instr_ir, extra_ir = mn_do_nop_warn(self, instr, *args) + elif instr.name[0:3] == 'DIV': + instr_ir, extra_ir = mn_do_div(self, instr, *args) + elif instr.name[0:4] == 'EXTS': + instr_ir, extra_ir = mn_do_exts(self, instr, *args) + elif instr.name[0] == 'L': + instr_ir, extra_ir = mn_do_load(self, instr, *args) + elif instr.name[0:3] == 'MUL': + instr_ir, extra_ir = mn_do_mul(self, instr, *args) + elif instr.name[0:3] == 'NEG': + instr_ir, extra_ir = mn_do_neg(self, instr, *args) + elif instr.name[0:2] == 'OR': + instr_ir, extra_ir = mn_do_or(self, instr, *args) + elif instr.name[0:2] == 'RL': + instr_ir, extra_ir = mn_do_rotate(self, instr, args[0], args[1], + args[2], int(args[3]), + int(args[4])) + elif instr.name == 'STMW': + instr_ir, extra_ir = mn_do_stmw(self, instr, *args) + elif instr.name[0:2] == 'ST': + instr_ir, extra_ir = mn_do_store(self, instr, *args) + elif instr.name[0:4] == 'SUBF': + if instr.name[0:5] == 'SUBFZ': + last_arg = ExprInt(0, 32) + elif instr.name[0:5] == 'SUBFM': + last_arg = ExprInt(0xFFFFFFFF, 32) + else: + last_arg = args[2] + instr_ir, extra_ir = mn_do_sub(self, instr, args[0], args[1], + last_arg) + elif instr.name[0:3] == 'XOR': + instr_ir, extra_ir = mn_do_xor(self, instr, *args) + else: + instr_ir, extra_ir = sem_dir[instr.name](self, instr, *args) + + return instr_ir, extra_ir + + def get_next_instr(self, instr): + l = self.loc_db.get_or_create_offset_location(instr.offset + 4) + return l + + def get_next_break_loc_key(self, instr): + l = self.loc_db.get_or_create_offset_location(instr.offset + 4) + return l |