diff options
Diffstat (limited to 'miasm/arch/arm/arch.py')
| -rw-r--r-- | miasm/arch/arm/arch.py | 3457 |
1 files changed, 0 insertions, 3457 deletions
diff --git a/miasm/arch/arm/arch.py b/miasm/arch/arm/arch.py deleted file mode 100644 index 10551515..00000000 --- a/miasm/arch/arm/arch.py +++ /dev/null @@ -1,3457 +0,0 @@ -#-*- coding:utf-8 -*- - -from builtins import range -from future.utils import viewitems - -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.arm.regs as regs_module -from miasm.arch.arm.regs import * -from miasm.core.asm_ast import AstInt, AstId, AstMem, AstOp -from miasm.ir.ir import color_expr_html -from miasm.core import utils -from miasm.core.utils import BRACKET_O, BRACKET_C - -# A1 encoding - -log = logging.getLogger("armdis") -console_handler = logging.StreamHandler() -console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(console_handler) -log.setLevel(logging.DEBUG) - -# arm regs ############## -reg_dum = ExprId('DumReg', 32) - -PC, _ = gen_reg('PC') - -# GP -regs_str = ['R%d' % r for r in range(0x10)] -regs_str[13] = 'SP' -regs_str[14] = 'LR' -regs_str[15] = 'PC' -regs_expr = [ExprId(x, 32) for x in regs_str] - -gpregs = reg_info(regs_str, regs_expr) - -gpregs_pc = reg_info(regs_str[-1:], regs_expr[-1:]) -gpregs_sp = reg_info(regs_str[13:14], regs_expr[13:14]) - -gpregs_nosppc = reg_info(regs_str[:13] + [str(reg_dum), regs_str[14]], - regs_expr[:13] + [reg_dum, regs_expr[14]]) - -gpregs_nopc = reg_info(regs_str[:14], - regs_expr[:14]) - -gpregs_nosp = reg_info(regs_str[:13] + [str(reg_dum), regs_str[14], regs_str[15]], - regs_expr[:13] + [reg_dum, regs_expr[14], regs_expr[15]]) - - -# psr -sr_flags = "cxsf" -cpsr_regs_str = [] -spsr_regs_str = [] -for i in range(0x10): - o = "" - for j in range(4): - if i & (1 << j): - o += sr_flags[j] - cpsr_regs_str.append("CPSR_%s" % o) - spsr_regs_str.append("SPSR_%s" % o) - -# psr_regs_str = ['CPSR', 'SPSR'] -# psr_regs_expr = [ExprId(x, 32) for x in psr_regs_str] - -# psr_regs = reg_info(psr_regs_str, psr_regs_expr) - -cpsr_regs_expr = [ExprId(x, 32) for x in cpsr_regs_str] -spsr_regs_expr = [ExprId(x, 32) for x in spsr_regs_str] - -cpsr_regs = reg_info(cpsr_regs_str, cpsr_regs_expr) -spsr_regs = reg_info(spsr_regs_str, spsr_regs_expr) - -# CP -cpregs_str = ['c%d' % r for r in range(0x10)] -cpregs_expr = [ExprId(x, 32) for x in cpregs_str] - -cp_regs = reg_info(cpregs_str, cpregs_expr) - -# P -pregs_str = ['p%d' % r for r in range(0x10)] -pregs_expr = [ExprId(x, 32) for x in pregs_str] - -p_regs = reg_info(pregs_str, pregs_expr) - -conditional_branch = ["BEQ", "BNE", "BCS", "BCC", "BMI", "BPL", "BVS", - "BVC", "BHI", "BLS", "BGE", "BLT", "BGT", "BLE"] - -unconditional_branch = ["B", "BX", "BL", "BLX"] - -barrier_expr = { - 0b1111: ExprId("SY", 32), - 0b1110: ExprId("ST", 32), - 0b1101: ExprId("LD", 32), - 0b1011: ExprId("ISH", 32), - 0b1010: ExprId("ISHST", 32), - 0b1001: ExprId("ISHLD", 32), - 0b0111: ExprId("NSH", 32), - 0b0110: ExprId("NSHST", 32), - 0b0011: ExprId("OSH", 32), - 0b0010: ExprId("OSHST", 32), - 0b0001: ExprId("OSHLD", 32), -} - -barrier_info = reg_info_dct(barrier_expr) - - - -# parser helper ########### - -def cb_tok_reg_duo(tokens): - tokens = tokens[0] - i1 = gpregs.expr.index(tokens[0].name) - i2 = gpregs.expr.index(tokens[1].name) - o = [] - for i in range(i1, i2 + 1): - o.append(AstId(gpregs.expr[i])) - return o - -LPARENTHESIS = Literal("(") -RPARENTHESIS = Literal(")") - -LACC = Suppress(Literal("{")) -RACC = Suppress(Literal("}")) -MINUS = Suppress(Literal("-")) -CIRCUNFLEX = Literal("^") - - -def check_bounds(left_bound, right_bound, value): - if left_bound <= value and value <= right_bound: - return AstInt(value) - else: - raise ValueError('shift operator immediate value out of bound') - - -def check_values(values, value): - if value in values: - return AstInt(value) - else: - raise ValueError('shift operator immediate value out of bound') - -int_1_31 = str_int.copy().setParseAction(lambda v: check_bounds(1, 31, v[0])) -int_1_32 = str_int.copy().setParseAction(lambda v: check_bounds(1, 32, v[0])) - -int_8_16_24 = str_int.copy().setParseAction(lambda v: check_values([8, 16, 24], v[0])) - - -def cb_reglistparse(tokens): - tokens = tokens[0] - if tokens[-1] == "^": - return AstOp('sbit', AstOp('reglist', *tokens[:-1])) - return AstOp('reglist', *tokens) - - -allshifts = ['<<', '>>', 'a>>', '>>>', 'rrx'] -allshifts_armt = ['<<', '>>', 'a>>', '>>>', 'rrx'] - -shift2expr_dct = {'LSL': '<<', 'LSR': '>>', 'ASR': 'a>>', - 'ROR': ">>>", 'RRX': "rrx"} - -expr2shift_dct = dict((value, key) for key, value in viewitems(shift2expr_dct)) - - -def op_shift2expr(tokens): - return shift2expr_dct[tokens[0]] - -reg_duo = Group(gpregs.parser + MINUS + - gpregs.parser).setParseAction(cb_tok_reg_duo) -reg_or_duo = reg_duo | gpregs.parser -gpreg_list = Group(LACC + delimitedList( - reg_or_duo, delim=',') + RACC + Optional(CIRCUNFLEX)) -gpreg_list.setParseAction(cb_reglistparse) - -LBRACK = Suppress("[") -RBRACK = Suppress("]") -COMMA = Suppress(",") -all_binaryop_1_31_shifts_t = literal_list( - ['LSL', 'ROR']).setParseAction(op_shift2expr) -all_binaryop_1_32_shifts_t = literal_list( - ['LSR', 'ASR']).setParseAction(op_shift2expr) -all_unaryop_shifts_t = literal_list(['RRX']).setParseAction(op_shift2expr) - -ror_shifts_t = literal_list(['ROR']).setParseAction(op_shift2expr) -shl_shifts_t = literal_list(['SHL']).setParseAction(op_shift2expr) - - -allshifts_t_armt = literal_list( - ['LSL', 'LSR', 'ASR', 'ROR', 'RRX']).setParseAction(op_shift2expr) - -gpreg_p = gpregs.parser - -psr_p = cpsr_regs.parser | spsr_regs.parser - - -def cb_shift(tokens): - if len(tokens) == 1: - ret = tokens[0] - elif len(tokens) == 2: - ret = AstOp(tokens[1], tokens[0]) - elif len(tokens) == 3: - ret = AstOp(tokens[1], tokens[0], tokens[2]) - else: - raise ValueError("Bad arg") - return ret - -shift_off = (gpregs.parser + Optional( - (all_unaryop_shifts_t) | - (all_binaryop_1_31_shifts_t + (gpregs.parser | int_1_31)) | - (all_binaryop_1_32_shifts_t + (gpregs.parser | int_1_32)) -)).setParseAction(cb_shift) -shift_off |= base_expr - - -rot2_expr = (gpregs.parser + Optional( - (ror_shifts_t + (int_8_16_24)) -)).setParseAction(cb_shift) - - -rot5_expr = shift_off - -OP_LSL = Suppress("LSL") - -def cb_deref_reg_reg(tokens): - if len(tokens) != 2: - raise ValueError("Bad mem format") - return AstMem(AstOp('+', tokens[0], tokens[1]), 8) - -def cb_deref_reg_reg_lsl_1(tokens): - if len(tokens) != 3: - raise ValueError("Bad mem format") - reg1, reg2, index = tokens - if not isinstance(index, AstInt) or index.value != 1: - raise ValueError("Bad index") - ret = AstMem(AstOp('+', reg1, AstOp('<<', reg2, index)), 16) - return ret - - -deref_reg_reg = (LBRACK + gpregs.parser + COMMA + gpregs.parser + RBRACK).setParseAction(cb_deref_reg_reg) -deref_reg_reg_lsl_1 = (LBRACK + gpregs.parser + COMMA + gpregs.parser + OP_LSL + base_expr + RBRACK).setParseAction(cb_deref_reg_reg_lsl_1) - - - -(gpregs.parser + Optional( - (ror_shifts_t + (int_8_16_24)) -)).setParseAction(cb_shift) - - - -reg_or_base = gpregs.parser | base_expr - -def deref2expr_nooff(tokens): - tokens = tokens[0] - # XXX default - return ExprOp("preinc", tokens[0], ExprInt(0, 32)) - - -def cb_deref_preinc(tokens): - tokens = tokens[0] - if len(tokens) == 1: - return AstOp("preinc", tokens[0], AstInt(0)) - elif len(tokens) == 2: - return AstOp("preinc", tokens[0], tokens[1]) - else: - raise NotImplementedError('len(tokens) > 2') - - -def cb_deref_pre_mem(tokens): - tokens = tokens[0] - if len(tokens) == 1: - return AstMem(AstOp("preinc", tokens[0], AstInt(0)), 32) - elif len(tokens) == 2: - return AstMem(AstOp("preinc", tokens[0], tokens[1]), 32) - else: - raise NotImplementedError('len(tokens) > 2') - - -def cb_deref_post(tokens): - tokens = tokens[0] - return AstOp("postinc", tokens[0], tokens[1]) - - -def cb_deref_wb(tokens): - tokens = tokens[0] - if tokens[-1] == '!': - return AstMem(AstOp('wback', *tokens[:-1]), 32) - return AstMem(tokens[0], 32) - -# shift_off.setParseAction(deref_off) -deref_nooff = Group( - LBRACK + gpregs.parser + RBRACK).setParseAction(deref2expr_nooff) -deref_pre = Group(LBRACK + gpregs.parser + Optional( - COMMA + shift_off) + RBRACK).setParseAction(cb_deref_preinc) -deref_post = Group(LBRACK + gpregs.parser + RBRACK + - COMMA + shift_off).setParseAction(cb_deref_post) -deref = Group((deref_post | deref_pre | deref_nooff) - + Optional('!')).setParseAction(cb_deref_wb) - - -def cb_gpreb_wb(tokens): - assert len(tokens) == 1 - tokens = tokens[0] - if tokens[-1] == '!': - return AstOp('wback', *tokens[:-1]) - return tokens[0] - -gpregs_wb = Group(gpregs.parser + Optional('!')).setParseAction(cb_gpreb_wb) - - -cond_list_full = ['EQ', 'NE', 'CS', 'CC', 'MI', 'PL', 'VS', 'VC', - 'HI', 'LS', 'GE', 'LT', 'GT', 'LE', 'NV'] - - -cond_list = ['EQ', 'NE', 'CS', 'CC', 'MI', 'PL', 'VS', 'VC', - 'HI', 'LS', 'GE', 'LT', 'GT', 'LE', ''] # , 'NV'] -cond_dct = dict([(x[1], x[0]) for x in enumerate(cond_list)]) -bm_cond = bs_mod_name(l=4, fname='cond', mn_mod=cond_list) - - - -cond_dct_barmt = dict([(x[0], x[1]) for x in enumerate(cond_list) if x[0] & 0b1110 != 0b1110]) -bm_cond_barmt = bs_mod_name(l=4, fname='cond', mn_mod=cond_dct_barmt) - - - -def permut_args(order, args): - l = [] - for i, x in enumerate(order): - l.append((x.__class__, i)) - l = dict(l) - out = [None for x in range(len(args))] - for a in args: - out[l[a.__class__]] = a - return out - - -class additional_info(object): - - def __init__(self): - self.except_on_instr = False - self.lnk = None - self.cond = None - - -class instruction_arm(instruction): - __slots__ = [] - - def __init__(self, *args, **kargs): - super(instruction_arm, self).__init__(*args, **kargs) - - @staticmethod - def arg2str(expr, index=None, loc_db=None): - wb = False - if expr.is_id() or expr.is_int(): - return str(expr) - elif expr.is_loc(): - if loc_db is not None: - return loc_db.pretty_str(expr.loc_key) - else: - return str(expr) - if isinstance(expr, ExprOp) and expr.op in expr2shift_dct: - if len(expr.args) == 1: - return '%s %s' % (expr.args[0], expr2shift_dct[expr.op]) - elif len(expr.args) == 2: - return '%s %s %s' % (expr.args[0], expr2shift_dct[expr.op], expr.args[1]) - else: - raise NotImplementedError('zarb arg2str') - - - sb = False - if isinstance(expr, ExprOp) and expr.op == "sbit": - sb = True - expr = expr.args[0] - if isinstance(expr, ExprOp) and expr.op == "reglist": - o = [gpregs.expr.index(x) for x in expr.args] - out = reglist2str(o) - if sb: - out += "^" - return out - - - if isinstance(expr, ExprOp) and expr.op == 'wback': - wb = True - expr = expr.args[0] - if isinstance(expr, ExprId): - out = str(expr) - if wb: - out += "!" - return out - - if not isinstance(expr, ExprMem): - return str(expr) - - expr = expr.ptr - if isinstance(expr, ExprOp) and expr.op == 'wback': - wb = True - expr = expr.args[0] - - - if isinstance(expr, ExprId): - r, s = expr, None - elif len(expr.args) == 1 and isinstance(expr.args[0], ExprId): - r, s = expr.args[0], None - elif isinstance(expr.args[0], ExprId): - r, s = expr.args[0], expr.args[1] - else: - r, s = expr.args[0].args - if isinstance(s, ExprOp) and s.op in expr2shift_dct: - s = ' '.join( - str(x) - for x in (s.args[0], expr2shift_dct[s.op], s.args[1]) - ) - - if isinstance(expr, ExprOp) and expr.op == 'postinc': - o = '[' + str(r) + ']' - if s and not (isinstance(s, ExprInt) and int(s) == 0): - o += ', %s' % s - else: - if s and not (isinstance(s, ExprInt) and int(s) == 0): - o = '[' + ("%s, %s" % (r, s)) + ']' - else: - o = '[' + str(r) + ']' - - if wb: - o += "!" - return o - - @staticmethod - def arg2html(expr, index=None, loc_db=None): - wb = False - if expr.is_id() or expr.is_int() or expr.is_loc(): - return color_expr_html(expr, loc_db) - if isinstance(expr, ExprOp) and expr.op in expr2shift_dct: - if len(expr.args) == 1: - return '%s %s' % (color_expr_html(expr.args[0], loc_db), expr2shift_dct[expr.op]) - elif len(expr.args) == 2: - return '%s %s %s' % (color_expr_html(expr.args[0], loc_db), expr2shift_dct[expr.op], expr.args[1]) - else: - raise NotImplementedError('zarb arg2str') - - - sb = False - if isinstance(expr, ExprOp) and expr.op == "sbit": - sb = True - expr = expr.args[0] - if isinstance(expr, ExprOp) and expr.op == "reglist": - o = [gpregs.expr.index(x) for x in expr.args] - out = reglist2html(o) - if sb: - out += "^" - return out - - - if isinstance(expr, ExprOp) and expr.op == 'wback': - wb = True - expr = expr.args[0] - if isinstance(expr, ExprId): - out = color_expr_html(expr, loc_db) - if wb: - out += "!" - return out - - if not isinstance(expr, ExprMem): - return color_expr_html(expr, loc_db) - - expr = expr.ptr - if isinstance(expr, ExprOp) and expr.op == 'wback': - wb = True - expr = expr.args[0] - - - if isinstance(expr, ExprId): - r, s = expr, None - elif len(expr.args) == 1 and isinstance(expr.args[0], ExprId): - r, s = expr.args[0], None - elif isinstance(expr.args[0], ExprId): - r, s = expr.args[0], expr.args[1] - else: - r, s = expr.args[0].args - if isinstance(s, ExprOp) and s.op in expr2shift_dct: - s_html = ' '.join( - str(x) - for x in ( - color_expr_html(s.args[0], loc_db), - utils.set_html_text_color(expr2shift_dct[s.op], utils.COLOR_OP), - color_expr_html(s.args[1], loc_db) - ) - ) - else: - s_html = color_expr_html(s, loc_db) - - if isinstance(expr, ExprOp) and expr.op == 'postinc': - o = BRACKET_O + color_expr_html(r, loc_db) + BRACKET_C - if s and not (isinstance(s, ExprInt) and int(s) == 0): - o += ', %s' % s_html - else: - if s and not (isinstance(s, ExprInt) and int(s) == 0): - o = BRACKET_O + color_expr_html(r, loc_db) + ", " + s_html + BRACKET_C - else: - o = BRACKET_O + color_expr_html(r, loc_db) + BRACKET_C - - if wb: - o += "!" - return o - - - def dstflow(self): - if self.is_subcall(): - return True - return self.name in conditional_branch + unconditional_branch - - def dstflow2label(self, loc_db): - expr = self.args[0] - if not isinstance(expr, ExprInt): - return - if self.name == 'BLX': - addr = (int(expr) + self.offset) & int(expr.mask) - else: - addr = (int(expr) + self.offset) & int(expr.mask) - loc_key = loc_db.get_or_create_offset_location(addr) - self.args[0] = ExprLoc(loc_key, expr.size) - - def breakflow(self): - if self.is_subcall(): - return True - if self.name in conditional_branch + unconditional_branch: - return True - if self.name.startswith("LDM") and PC in self.args[1].args: - return True - if self.args and PC in self.args[0].get_r(): - return True - return False - - def is_subcall(self): - if self.name == 'BLX': - return True - return self.additional_info.lnk - - def getdstflow(self, loc_db): - return [self.args[0]] - - def splitflow(self): - if self.additional_info.lnk: - return True - if self.name == 'BLX': - return True - if self.name == 'BX': - return False - return self.breakflow() and self.additional_info.cond != 14 - - def get_symbol_size(self, symbol, loc_db): - return 32 - - def fixDstOffset(self): - e = self.args[0] - if self.offset is None: - raise ValueError('symbol not resolved %s' % l) - if not isinstance(e, ExprInt): - log.debug('dyn dst %r', e) - return - off = (int(e) - self.offset) & int(e.mask) - if int(off % 4): - raise ValueError('strange offset! %r' % off) - 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, expr): - # LDR XXX, [PC, offset] => PC is self.offset+8 - return ExprInt(self.offset+8, expr.size) - -class instruction_armt(instruction_arm): - __slots__ = [] - - def __init__(self, *args, **kargs): - super(instruction_armt, self).__init__(*args, **kargs) - - def dstflow(self): - if self.name in ["CBZ", "CBNZ"]: - return True - return self.name in conditional_branch + unconditional_branch - - def dstflow2label(self, loc_db): - if self.name in ["CBZ", "CBNZ"]: - expr = self.args[1] - else: - expr = self.args[0] - if not isinstance(expr, ExprInt): - return - if self.name == 'BLX': - addr = (int(expr) + (self.offset & 0xfffffffc)) & int(expr.mask) - elif self.name == 'BL': - addr = (int(expr) + self.offset) & int(expr.mask) - elif self.name.startswith('BP'): - addr = (int(expr) + self.offset) & int(expr.mask) - elif self.name.startswith('CB'): - addr = (int(expr) + self.offset + self.l + 2) & int(expr.mask) - else: - addr = (int(expr) + self.offset) & int(expr.mask) - - loc_key = loc_db.get_or_create_offset_location(addr) - dst = ExprLoc(loc_key, expr.size) - - if self.name in ["CBZ", "CBNZ"]: - self.args[1] = dst - else: - self.args[0] = dst - - def breakflow(self): - if self.name in conditional_branch + unconditional_branch +["CBZ", "CBNZ", 'TBB', 'TBH']: - return True - if self.name.startswith("LDM") and PC in self.args[1].args: - return True - if self.args and PC in self.args[0].get_r(): - return True - return False - - def getdstflow(self, loc_db): - if self.name in ['CBZ', 'CBNZ']: - return [self.args[1]] - return [self.args[0]] - - def splitflow(self): - if self.name in conditional_branch + ['BL', 'BLX', 'CBZ', 'CBNZ']: - return True - return False - - def is_subcall(self): - return self.name in ['BL', 'BLX'] - - def fixDstOffset(self): - e = self.args[0] - if self.offset is None: - raise ValueError('symbol not resolved %s' % l) - if not isinstance(e, ExprInt): - log.debug('dyn dst %r', e) - return - # The first +2 is to compensate instruction len, but strangely, 32 bits - # thumb2 instructions len is 2... For the second +2, didn't find it in - # the doc. - off = (int(e) - self.offset) & int(e.mask) - if int(off % 2): - raise ValueError('strange offset! %r' % off) - self.args[0] = ExprInt(off, 32) - - def get_asm_offset(self, expr): - # ADR XXX, PC, imm => PC is 4 aligned + imm - new_offset = ((self.offset + self.l) // 4) * 4 - return ExprInt(new_offset, expr.size) - - -class mn_arm(cls_mn): - delayslot = 0 - name = "arm" - regs = regs_module - bintree = {} - num = 0 - all_mn = [] - all_mn_mode = defaultdict(list) - all_mn_name = defaultdict(list) - all_mn_inst = defaultdict(list) - pc = {'l':PC, 'b':PC} - sp = {'l':SP, 'b':SP} - instruction = instruction_arm - max_instruction_len = 4 - alignment = 4 - - @classmethod - def getpc(cls, attrib = None): - return PC - - @classmethod - def getsp(cls, attrib = None): - return SP - - def additional_info(self): - info = additional_info() - info.lnk = False - if hasattr(self, "lnk"): - info.lnk = self.lnk.value != 0 - if hasattr(self, "cond"): - info.cond = self.cond.value - else: - info.cond = None - 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 == "l": - return (offset & ~3) + 3 - offset % 4 - elif 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]) - if l == 32: - return fields - return [bm_cond] + fields - - @classmethod - def gen_modes(cls, subcls, name, bases, dct, fields): - dct['mode'] = None - return [(subcls, name, bases, dct, fields)] - - def value(self, mode): - v = super(mn_arm, self).value(mode) - if mode == 'l': - return [x[::-1] for x in v] - elif 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 mn_armt(cls_mn): - name = "armt" - regs = regs_module - delayslot = 0 - bintree = {} - num = 0 - all_mn = [] - all_mn_mode = defaultdict(list) - all_mn_name = defaultdict(list) - all_mn_inst = defaultdict(list) - pc = PC - sp = SP - instruction = instruction_armt - max_instruction_len = 4 - alignment = 4 - - @classmethod - def getpc(cls, attrib = None): - return PC - - @classmethod - def getsp(cls, attrib = None): - return SP - - def additional_info(self): - info = additional_info() - info.lnk = False - if hasattr(self, "lnk"): - info.lnk = self.lnk.value != 0 - info.cond = 14 # COND_ALWAYS - 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 == "l": - return (offset & ~1) + 1 - offset % 2 - elif 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 in [16, 32], "len %r" % l - - @classmethod - def getmn(cls, name): - return name.upper() - - @classmethod - def mod_fields(cls, fields): - return list(fields) - - @classmethod - def gen_modes(cls, subcls, name, bases, dct, fields): - dct['mode'] = None - return [(subcls, name, bases, dct, fields)] - - def value(self, mode): - v = super(mn_armt, self).value(mode) - if mode == 'l': - out = [] - for x in v: - if len(x) == 2: - out.append(x[::-1]) - elif len(x) == 4: - out.append(x[:2][::-1] + x[2:4][::-1]) - return out - elif mode == 'b': - return [x for x in v] - else: - raise NotImplementedError('bad attrib') - - def get_args_expr(self): - args = [a.expr for a in self.args] - return args - - def get_symbol_size(self, symbol, loc_db, mode): - return 32 - - -class arm_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 - if arg.op == "-": - assert len(args) == 2 - return args[0] - args[1] - 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 arm_reg(reg_noarg, arm_arg): - pass - - -class arm_gpreg_noarg(reg_noarg): - reg_info = gpregs - parser = reg_info.parser - - -class arm_gpreg(arm_reg): - reg_info = gpregs - parser = reg_info.parser - - -class arm_reg_wb(arm_reg): - reg_info = gpregs - parser = gpregs_wb - - def decode(self, v): - v = v & self.lmask - e = self.reg_info.expr[v] - if self.parent.wback.value: - e = ExprOp('wback', e) - self.expr = e - return True - - def encode(self): - e = self.expr - self.parent.wback.value = 0 - if isinstance(e, ExprOp) and e.op == 'wback': - self.parent.wback.value = 1 - e = e.args[0] - if isinstance(e, ExprId): - self.value = self.reg_info.expr.index(e) - else: - self.parent.wback.value = 1 - self.value = self.reg_info.expr.index(e.args[0]) - return True - - -class arm_psr(arm_arg): - parser = psr_p - - def decode(self, v): - v = v & self.lmask - if self.parent.psr.value == 0: - e = cpsr_regs.expr[v] - else: - e = spsr_regs.expr[v] - self.expr = e - return True - - def encode(self): - e = self.expr - if e in spsr_regs.expr: - self.parent.psr.value = 1 - v = spsr_regs.expr.index(e) - elif e in cpsr_regs.expr: - self.parent.psr.value = 0 - v = cpsr_regs.expr.index(e) - else: - return False - self.value = v - return True - - -class arm_cpreg(arm_reg): - reg_info = cp_regs - parser = reg_info.parser - - -class arm_preg(arm_reg): - reg_info = p_regs - parser = reg_info.parser - - -class arm_imm(imm_noarg, arm_arg): - parser = base_expr - - -class arm_offs(arm_imm): - parser = base_expr - - def int2expr(self, v): - if v & ~self.intmask != 0: - return None - return ExprInt(v, self.intsize) - - def decodeval(self, v): - v <<= 2 - # Add pipeline offset - v += 8 - return v - - def encodeval(self, v): - if v%4 != 0: - return False - # Remove pipeline offset - v -= 8 - return v >> 2 - - def decode(self, v): - v = v & self.lmask - if (1 << (self.l - 1)) & v: - v |= ~0 ^ self.lmask - v = self.decodeval(v) - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) - if (1 << (self.l - 1)) & v: - v = -((0xffffffff ^ v) + 1) - v = self.encodeval(v) - if v is False: - return False - self.value = (v & 0xffffffff) & self.lmask - return True - - -class arm_imm8_12(arm_arg): - parser = deref - - def decode(self, v): - v = v & self.lmask - if self.parent.updown.value: - e = ExprInt(v << 2, 32) - else: - e = ExprInt(-v << 2, 32) - if self.parent.ppi.value: - e = ExprOp('preinc', self.parent.rn.expr, e) - else: - e = ExprOp('postinc', self.parent.rn.expr, e) - if self.parent.wback.value == 1: - e = ExprOp('wback', e) - self.expr = ExprMem(e, 32) - return True - - def encode(self): - self.parent.updown.value = 1 - e = self.expr - if not isinstance(e, ExprMem): - return False - e = e.ptr - if isinstance(e, ExprOp) and e.op == 'wback': - self.parent.wback.value = 1 - e = e.args[0] - else: - self.parent.wback.value = 0 - if e.op == "postinc": - self.parent.ppi.value = 0 - elif e.op == "preinc": - self.parent.ppi.value = 1 - else: - # XXX default - self.parent.ppi.value = 1 - self.parent.rn.expr = e.args[0] - if len(e.args) == 1: - self.value = 0 - return True - e = e.args[1] - if not isinstance(e, ExprInt): - log.debug('should be int %r', e) - return False - v = int(e) - if v < 0 or v & (1 << 31): - self.parent.updown.value = 0 - v = -v & 0xFFFFFFFF - if v & 0x3: - log.debug('arg should be 4 aligned') - return False - v >>= 2 - self.value = v - return True - - -class arm_imm_4_12(arm_arg): - parser = reg_or_base - - def decode(self, v): - v = v & self.lmask - imm = (self.parent.imm4.value << 12) | v - self.expr = ExprInt(imm, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) - if v > 0xffff: - return False - self.parent.imm4.value = v >> 12 - self.value = v & 0xfff - return True - - -class arm_imm_12_4(arm_arg): - parser = base_expr - - def decode(self, v): - v = v & self.lmask - imm = (self.parent.imm.value << 4) | v - self.expr = ExprInt(imm, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) - if v > 0xffff: - return False - self.parent.imm.value = (v >> 4) & 0xfff - self.value = v & 0xf - return True - - -class arm_op2(arm_arg): - parser = shift_off - - def str_to_imm_rot_form(self, s, neg=False): - if neg: - s = -s & 0xffffffff - for i in range(0, 32, 2): - v = myrol32(s, i) - if 0 <= v < 0x100: - return ((i // 2) << 8) | v - return None - - def decode(self, v): - val = v & self.lmask - if self.parent.immop.value: - rot = val >> 8 - imm = val & 0xff - imm = myror32(imm, rot * 2) - self.expr = ExprInt(imm, 32) - return True - rm = val & 0xf - shift = val >> 4 - shift_kind = shift & 1 - shift_type = (shift >> 1) & 3 - shift >>= 3 - if shift_kind: - # shift kind is reg - if shift & 1: - return False - rs = shift >> 1 - if rs == 0xf: - return False - shift_op = regs_expr[rs] - else: - # shift kind is imm - amount = shift - shift_op = ExprInt(amount, 32) - a = regs_expr[rm] - if shift_op == ExprInt(0, 32): - #rrx - if shift_type == 3: - self.expr = ExprOp(allshifts[4], a) - #asr, lsr - elif shift_type == 1 or shift_type == 2: - self.expr = ExprOp(allshifts[shift_type], a, ExprInt(32, 32)) - else: - self.expr = a - else: - self.expr = ExprOp(allshifts[shift_type], a, shift_op) - return True - - def encode(self): - e = self.expr - # pure imm - if isinstance(e, ExprInt): - val = self.str_to_imm_rot_form(int(e)) - if val is None: - return False - self.parent.immop.value = 1 - self.value = val - return True - - self.parent.immop.value = 0 - # pure reg - if isinstance(e, ExprId): - rm = gpregs.expr.index(e) - shift_kind = 0 - shift_type = 0 - amount = 0 - self.value = ( - ((((amount << 2) | shift_type) << 1) | shift_kind) << 4) | rm - return True - # rot reg - if not isinstance(e, ExprOp): - log.debug('bad reg rot1 %r', e) - return False - rm = gpregs.expr.index(e.args[0]) - shift_type = allshifts.index(e.op) - if e.op == 'rrx': - shift_kind = 0 - amount = 0 - shift_type = 3 - elif isinstance(e.args[1], ExprInt): - shift_kind = 0 - amount = int(e.args[1]) - # LSR/ASR of 32 => 0 - if amount == 32 and e.op in ['>>', 'a>>']: - amount = 0 - else: - shift_kind = 1 - amount = gpregs.expr.index(e.args[1]) << 1 - self.value = ( - ((((amount << 2) | shift_type) << 1) | shift_kind) << 4) | rm - return True - -# op2imm + rn - - -class arm_op2imm(arm_imm8_12): - parser = deref - - def str_to_imm_rot_form(self, s, neg=False): - if neg: - s = -s & 0xffffffff - if 0 <= s < (1 << 12): - return s - return None - - def decode(self, v): - val = v & self.lmask - if self.parent.immop.value == 0: - imm = val - if self.parent.updown.value == 0: - imm = -imm - if self.parent.ppi.value: - e = ExprOp('preinc', self.parent.rn.expr, ExprInt(imm, 32)) - else: - e = ExprOp('postinc', self.parent.rn.expr, ExprInt(imm, 32)) - if self.parent.wback.value == 1: - e = ExprOp('wback', e) - self.expr = ExprMem(e, 32) - return True - rm = val & 0xf - shift = val >> 4 - shift_kind = shift & 1 - shift_type = (shift >> 1) & 3 - shift >>= 3 - # print self.parent.immop.value, hex(shift), hex(shift_kind), - # hex(shift_type) - if shift_kind: - # log.debug('error in disasm xx') - return False - else: - # shift kind is imm - amount = shift - shift_op = ExprInt(amount, 32) - a = regs_expr[rm] - if shift_op == ExprInt(0, 32): - pass - else: - a = ExprOp(allshifts[shift_type], a, shift_op) - if self.parent.ppi.value: - e = ExprOp('preinc', self.parent.rn.expr, a) - else: - e = ExprOp('postinc', self.parent.rn.expr, a) - if self.parent.wback.value == 1: - e = ExprOp('wback', e) - self.expr = ExprMem(e, 32) - return True - - def encode(self): - self.parent.immop.value = 1 - self.parent.updown.value = 1 - - e = self.expr - assert(isinstance(e, ExprMem)) - e = e.ptr - if e.op == 'wback': - self.parent.wback.value = 1 - e = e.args[0] - else: - self.parent.wback.value = 0 - if e.op == "postinc": - self.parent.ppi.value = 0 - elif e.op == "preinc": - self.parent.ppi.value = 1 - else: - # XXX default - self.parent.ppi.value = 1 - - # if len(v) <1: - # raise ValueError('cannot parse', s) - self.parent.rn.expr = e.args[0] - if len(e.args) == 1: - self.parent.immop.value = 0 - self.value = 0 - return True - # pure imm - if isinstance(e.args[1], ExprInt): - self.parent.immop.value = 0 - val = self.str_to_imm_rot_form(int(e.args[1])) - if val is None: - val = self.str_to_imm_rot_form(int(e.args[1]), True) - if val is None: - log.debug('cannot encode inm') - return False - self.parent.updown.value = 0 - self.value = val - return True - # pure reg - if isinstance(e.args[1], ExprId): - rm = gpregs.expr.index(e.args[1]) - shift_kind = 0 - shift_type = 0 - amount = 0 - self.value = ( - ((((amount << 2) | shift_type) << 1) | shift_kind) << 4) | rm - return True - # rot reg - if not isinstance(e.args[1], ExprOp): - log.debug('bad reg rot2 %r', e) - return False - e = e.args[1] - rm = gpregs.expr.index(e.args[0]) - shift_type = allshifts.index(e.op) - if isinstance(e.args[1], ExprInt): - shift_kind = 0 - amount = int(e.args[1]) - else: - shift_kind = 1 - amount = gpregs.expr.index(e.args[1]) << 1 - self.value = ( - ((((amount << 2) | shift_type) << 1) | shift_kind) << 4) | rm - return True - - -def reglist2str(rlist): - out = [] - i = 0 - while i < len(rlist): - j = i + 1 - while j < len(rlist) and rlist[j] < 13 and rlist[j] == rlist[j - 1] + 1: - j += 1 - j -= 1 - if j < i + 2: - out.append(regs_str[rlist[i]]) - i += 1 - else: - out.append(regs_str[rlist[i]] + '-' + regs_str[rlist[j]]) - i = j + 1 - return "{" + ", ".join(out) + '}' - -def reglist2html(rlist): - out = [] - i = 0 - while i < len(rlist): - j = i + 1 - while j < len(rlist) and rlist[j] < 13 and rlist[j] == rlist[j - 1] + 1: - j += 1 - j -= 1 - if j < i + 2: - out.append(color_expr_html(regs_expr[rlist[i]], None)) - i += 1 - else: - out.append(color_expr_html(regs_expr[rlist[i]], None) + '-' + color_expr_html(regs_expr[rlist[j]], None)) - i = j + 1 - out = utils.fix_html_chars("{") + ", ".join(out) + utils.fix_html_chars("}") - return out - - -class arm_rlist(arm_arg): - parser = gpreg_list - - def encode(self): - self.parent.sbit.value = 0 - e = self.expr - if isinstance(e, ExprOp) and e.op == "sbit": - e = e.args[0] - self.parent.sbit.value = 1 - rlist = [gpregs.expr.index(x) for x in e.args] - v = 0 - for r in rlist: - v |= 1 << r - self.value = v - return True - - def decode(self, v): - v = v & self.lmask - out = [] - for i in range(0x10): - if 1 << i & v: - out.append(gpregs.expr[i]) - if not out: - return False - e = ExprOp('reglist', *out) - if self.parent.sbit.value == 1: - e = ExprOp('sbit', e) - self.expr = e - return True - - -class updown_b_nosp_mn(bs_mod_name): - mn_mod = ['D', 'I'] - - def modname(self, name, f_i): - return name + self.args['mn_mod'][f_i] - - -class ppi_b_nosp_mn(bs_mod_name): - prio = 5 - mn_mod = ['A', 'B'] - - -class updown_b_sp_mn(bs_mod_name): - mn_mod = ['A', 'D'] - - def modname(self, name, f_i): - if name.startswith("STM"): - f_i = [1, 0][f_i] - return name + self.args['mn_mod'][f_i] - - -class ppi_b_sp_mn(bs_mod_name): - mn_mod = ['F', 'E'] - - def modname(self, name, f_i): - if name.startswith("STM"): - f_i = [1, 0][f_i] - return name + self.args['mn_mod'][f_i] - - -class arm_reg_wb_nosp(arm_reg_wb): - - def decode(self, v): - v = v & self.lmask - if v == 13: - return False - e = self.reg_info.expr[v] - if self.parent.wback.value: - e = ExprOp('wback', e) - self.expr = e - return True - - -class arm_offs_blx(arm_imm): - - def decode(self, v): - v = v & self.lmask - v = (v << 2) + (self.parent.lowb.value << 1) - v = sign_ext(v, 26, 32) - # Add pipeline offset - v += 8 - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - # Remove pipeline offset - v = (int(self.expr) - 8) & int(self.expr.mask) - if v & 0x80000000: - v &= (1 << 26) - 1 - self.parent.lowb.value = (v >> 1) & 1 - self.value = v >> 2 - return True - - -class bs_lnk(bs_mod_name): - - def modname(self, name, i): - return name[:1] + self.args['mn_mod'][i] + name[1:] - - -class armt_rm_cp(bsi): - - def decode(self, v): - if v != gpregs.expr.index(self.parent.rm.expr): - return False - return True - - def encode(self): - self.value = gpregs.expr.index(self.parent.rm.expr) - return True - - -accum = bs(l=1) -scc = bs_mod_name(l=1, fname='scc', mn_mod=['', 'S']) -dumscc = bs("1") -rd = bs(l=4, cls=(arm_gpreg,)) -rdl = bs(l=4, cls=(arm_gpreg,)) - -rn = bs(l=4, cls=(arm_gpreg,), fname="rn") -rs = bs(l=4, cls=(arm_gpreg,)) -rm = bs(l=4, cls=(arm_gpreg,), fname='rm') -ra = bs(l=4, cls=(arm_gpreg,)) -rt = bs(l=4, cls=(arm_gpreg,), fname='rt') -rt2 = bs(l=4, cls=(arm_gpreg,)) - -rm_cp = bs(l=4, cls=(armt_rm_cp,)) - -op2 = bs(l=12, cls=(arm_op2,)) -lnk = bs_lnk(l=1, fname='lnk', mn_mod=['', 'L']) -offs = bs(l=24, cls=(arm_offs,), fname="offs") - -rn_noarg = bs(l=4, cls=(arm_gpreg_noarg,), fname="rn") -rm_noarg = bs(l=4, cls=(arm_gpreg_noarg,), fname="rm", order = -1) - -immop = bs(l=1, fname='immop') -dumr = bs(l=4, default_val="0000", fname="dumr") -# psr = bs(l=1, cls=(arm_psr,), fname="psr") - -psr = bs(l=1, fname="psr") -psr_field = bs(l=4, cls=(arm_psr,)) - -ppi = bs(l=1, fname='ppi') -updown = bs(l=1, fname='updown') -trb = bs_mod_name(l=1, fname='trb', mn_mod=['', 'B']) -wback = bs_mod_name(l=1, fname="wback", mn_mod=['', 'T']) -wback_no_t = bs(l=1, fname="wback") - -op2imm = bs(l=12, cls=(arm_op2imm,)) - -updown_b_nosp = updown_b_nosp_mn(l=1, mn_mod=['D', 'I'], fname='updown') -ppi_b_nosp = ppi_b_nosp_mn(l=1, mn_mod=['A', 'B'], fname='ppi') -updown_b_sp = updown_b_sp_mn(l=1, mn_mod=['A', 'D'], fname='updown') -ppi_b_sp = ppi_b_sp_mn(l=1, mn_mod=['F', 'E'], fname='ppi') - -sbit = bs(l=1, fname="sbit") -rn_sp = bs("1101", cls=(arm_reg_wb,), fname='rnsp') -rn_wb = bs(l=4, cls=(arm_reg_wb_nosp,), fname='rn') -rlist = bs(l=16, cls=(arm_rlist,), fname='rlist') - -swi_i = bs(l=24, cls=(arm_imm,), fname="swi_i") - -opc = bs(l=4, cls=(arm_imm, m_arg), fname='opc') -crn = bs(l=4, cls=(arm_cpreg,), fname='crn') -crd = bs(l=4, cls=(arm_cpreg,), fname='crd') -crm = bs(l=4, cls=(arm_cpreg,), fname='crm') -cpnum = bs(l=4, cls=(arm_preg,), fname='cpnum') -cp = bs(l=3, cls=(arm_imm, m_arg), fname='cp') - -imm8_12 = bs(l=8, cls=(arm_imm8_12, m_arg), fname='imm') -tl = bs_mod_name(l=1, fname="tl", mn_mod=['', 'L']) - -cpopc = bs(l=3, cls=(arm_imm, m_arg), fname='cpopc') -imm20 = bs(l=20, cls=(arm_imm, m_arg)) -imm4 = bs(l=4, cls=(arm_imm, m_arg)) -imm12 = bs(l=12, cls=(arm_imm, m_arg)) -imm16 = bs(l=16, cls=(arm_imm, m_arg)) - -imm12_off = bs(l=12, fname="imm") - -imm2_noarg = bs(l=2, fname="imm") -imm4_noarg = bs(l=4, fname="imm4") - - -imm_4_12 = bs(l=12, cls=(arm_imm_4_12,)) - -imm12_noarg = bs(l=12, fname="imm") -imm_12_4 = bs(l=4, cls=(arm_imm_12_4,)) - -lowb = bs(l=1, fname='lowb') -offs_blx = bs(l=24, cls=(arm_offs_blx,), fname="offs") - -fix_cond = bs("1111", fname="cond") - -class mul_part_x(bs_mod_name): - prio = 5 - mn_mod = ['B', 'T'] - -class mul_part_y(bs_mod_name): - prio = 6 - mn_mod = ['B', 'T'] - -mul_x = mul_part_x(l=1, fname='x', mn_mod=['B', 'T']) -mul_y = mul_part_y(l=1, fname='y', mn_mod=['B', 'T']) - -class arm_immed(arm_arg): - parser = deref - - def decode(self, v): - if self.parent.immop.value == 1: - imm = ExprInt((self.parent.immedH.value << 4) | v, 32) - else: - imm = gpregs.expr[v] - if self.parent.updown.value == 0: - imm = -imm - if self.parent.ppi.value: - e = ExprOp('preinc', self.parent.rn.expr, imm) - else: - e = ExprOp('postinc', self.parent.rn.expr, imm) - if self.parent.wback.value == 1: - e = ExprOp('wback', e) - self.expr = ExprMem(e, 32) - - return True - - def encode(self): - self.parent.immop.value = 1 - self.parent.updown.value = 1 - e = self.expr - if not isinstance(e, ExprMem): - return False - e = e.ptr - if isinstance(e, ExprOp) and e.op == 'wback': - self.parent.wback.value = 1 - e = e.args[0] - else: - self.parent.wback.value = 0 - if e.op == "postinc": - self.parent.ppi.value = 0 - elif e.op == "preinc": - self.parent.ppi.value = 1 - else: - # XXX default - self.parent.ppi.value = 1 - self.parent.rn.expr = e.args[0] - if len(e.args) == 1: - self.value = 0 - self.parent.immedH.value = 0 - return True - e = e.args[1] - if isinstance(e, ExprInt): - v = int(e) - if v < 0 or v & (1 << 31): - self.parent.updown.value = 0 - v = (-v) & 0xFFFFFFFF - if v > 0xff: - log.debug('cannot encode imm XXX') - return False - self.value = v & 0xF - self.parent.immedH.value = v >> 4 - return True - - self.parent.immop.value = 0 - if isinstance(e, ExprOp) and len(e.args) == 1 and e.op == "-": - self.parent.updown.value = 0 - e = e.args[0] - if e in gpregs.expr: - self.value = gpregs.expr.index(e) - self.parent.immedH.value = 0x0 - return True - else: - raise ValueError('e should be int: %r' % e) - -immedH = bs(l=4, fname='immedH') -immedL = bs(l=4, cls=(arm_immed, m_arg), fname='immedL') -hb = bs(l=1) - - -class armt2_rot_rm(arm_arg): - parser = shift_off - def decode(self, v): - r = self.parent.rm.expr - if v == 00: - e = r - else: - raise NotImplementedError('rotation') - self.expr = e - return True - def encode(self): - e = self.expr - if isinstance(e, ExprId): - self.value = 0 - else: - raise NotImplementedError('rotation') - return True - -rot_rm = bs(l=2, cls=(armt2_rot_rm,), fname="rot_rm") - - -class arm_mem_rn_imm(arm_arg): - parser = deref - def decode(self, v): - value = self.parent.imm.value - if self.parent.rw.value == 0: - value = -value - imm = ExprInt(value, 32) - reg = gpregs.expr[v] - if value: - expr = ExprMem(reg + imm, 32) - else: - expr = ExprMem(reg, 32) - self.expr = expr - return True - - def encode(self): - self.parent.add_imm.value = 1 - self.parent.imm.value = 0 - expr = self.expr - if not isinstance(expr, ExprMem): - return False - ptr = expr.ptr - if ptr in gpregs.expr: - self.value = gpregs.expr.index(ptr) - elif (isinstance(ptr, ExprOp) and - len(ptr.args) == 2 and - ptr.op == 'preinc'): - reg, imm = ptr.args - if not reg in gpregs.expr: - return False - self.value = gpregs.expr.index(reg) - if not isinstance(imm, ExprInt): - return False - value = int(imm) - if value & 0x80000000: - value = -value - self.parent.add_imm.value = 0 - self.parent.imm.value = value - else: - return False - return True - -mem_rn_imm = bs(l=4, cls=(arm_mem_rn_imm,), order=1) - -def armop(name, fields, args=None, alias=False): - dct = {"fields": fields} - dct["alias"] = alias - if args is not None: - dct['args'] = args - type(name, (mn_arm,), dct) - - -def armtop(name, fields, args=None, alias=False): - dct = {"fields": fields} - dct["alias"] = alias - if args is not None: - dct['args'] = args - type(name, (mn_armt,), dct) - - -op_list = ['AND', 'EOR', 'SUB', 'RSB', 'ADD', 'ADC', 'SBC', 'RSC', - 'TST', 'TEQ', 'CMP', 'CMN', 'ORR', 'MOV', 'BIC', 'MVN'] -data_mov_name = {'MOV': 13, 'MVN': 15} -data_test_name = {'TST': 8, 'TEQ': 9, 'CMP': 10, 'CMN': 11} - -data_name = {} -for i, n in enumerate(op_list): - if n in list(data_mov_name) + list(data_test_name): - continue - data_name[n] = i -bs_data_name = bs_name(l=4, name=data_name) - -bs_data_mov_name = bs_name(l=4, name=data_mov_name) - -bs_data_test_name = bs_name(l=4, name=data_test_name) - - -transfer_name = {'STR': 0, 'LDR': 1} -bs_transfer_name = bs_name(l=1, name=transfer_name) - -transferh_name = {'STRH': 0, 'LDRH': 1} -bs_transferh_name = bs_name(l=1, name=transferh_name) - - -transfer_ldr_name = {'LDRD': 0, 'LDRSB': 1} -bs_transfer_ldr_name = bs_name(l=1, name=transfer_ldr_name) - -btransfer_name = {'STM': 0, 'LDM': 1} -bs_btransfer_name = bs_name(l=1, name=btransfer_name) - -ctransfer_name = {'STC': 0, 'LDC': 1} -bs_ctransfer_name = bs_name(l=1, name=ctransfer_name) - -mr_name = {'MCR': 0, 'MRC': 1} -bs_mr_name = bs_name(l=1, name=mr_name) - - -bs_addi = bs(l=1, fname="add_imm") -bs_rw = bs_mod_name(l=1, fname='rw', mn_mod=['W', '']) - -class armt_barrier_option(reg_noarg, arm_arg): - reg_info = barrier_info - parser = reg_info.parser - - def decode(self, v): - v = v & self.lmask - if v not in self.reg_info.dct_expr: - return False - self.expr = self.reg_info.dct_expr[v] - return True - - def encode(self): - if not self.expr in self.reg_info.dct_expr_inv: - log.debug("cannot encode reg %r", self.expr) - return False - self.value = self.reg_info.dct_expr_inv[self.expr] - return True - - def check_fbits(self, v): - return v & self.fmask == self.fbits - -barrier_option = bs(l=4, cls=(armt_barrier_option,)) - -armop("mul", [bs('000000'), bs('0'), scc, rd, bs('0000'), rs, bs('1001'), rm], [rd, rm, rs]) -armop("umull", [bs('000010'), bs('0'), scc, rd, rdl, rs, bs('1001'), rm], [rdl, rd, rm, rs]) -armop("umlal", [bs('000010'), bs('1'), scc, rd, rdl, rs, bs('1001'), rm], [rdl, rd, rm, rs]) -armop("smull", [bs('000011'), bs('0'), scc, rd, rdl, rs, bs('1001'), rm], [rdl, rd, rm, rs]) -armop("smlal", [bs('000011'), bs('1'), scc, rd, rdl, rs, bs('1001'), rm], [rdl, rd, rm, rs]) -armop("mla", [bs('000000'), bs('1'), scc, rd, rn, rs, bs('1001'), rm], [rd, rm, rs, rn]) -armop("mrs", [bs('00010'), psr, bs('00'), psr_field, rd, bs('000000000000')], [rd, psr]) -armop("msr", [bs('00010'), psr, bs('10'), psr_field, bs('1111'), bs('0000'), bs('0000'), rm], [psr_field, rm]) -armop("data", [bs('00'), immop, bs_data_name, scc, rn, rd, op2], [rd, rn, op2]) -armop("data_mov", [bs('00'), immop, bs_data_mov_name, scc, bs('0000'), rd, op2], [rd, op2]) -armop("data_test", [bs('00'), immop, bs_data_test_name, dumscc, rn, dumr, op2]) -armop("b", [bs('101'), lnk, offs]) - -armop("smul", [bs('00010110'), rd, bs('0000'), rs, bs('1'), mul_y, mul_x, bs('0'), rm], [rd, rm, rs]) - -# TODO TEST -#armop("und", [bs('011'), imm20, bs('1'), imm4]) -armop("transfer", [bs('01'), immop, ppi, updown, trb, wback_no_t, bs_transfer_name, rn_noarg, rd, op2imm], [rd, op2imm]) -armop("transferh", [bs('000'), ppi, updown, immop, wback_no_t, bs_transferh_name, rn_noarg, rd, immedH, bs('1011'), immedL], [rd, immedL]) -armop("ldrd", [bs('000'), ppi, updown, immop, wback_no_t, bs_transfer_ldr_name, rn_noarg, rd, immedH, bs('1101'), immedL], [rd, immedL]) -armop("ldrsh", [bs('000'), ppi, updown, immop, wback_no_t, bs('1'), rn_noarg, rd, immedH, bs('1'), bs('1'), bs('1'), bs('1'), immedL], [rd, immedL]) -armop("strd", [bs('000'), ppi, updown, immop, wback_no_t, bs('0'), rn_noarg, rd, immedH, bs('1'), bs('1'), bs('1'), bs('1'), immedL], [rd, immedL]) -armop("btransfersp", [bs('100'), ppi_b_sp, updown_b_sp, sbit, wback_no_t, bs_btransfer_name, rn_sp, rlist]) -armop("btransfer", [bs('100'), ppi_b_nosp, updown_b_nosp, sbit, wback_no_t, bs_btransfer_name, rn_wb, rlist]) -# TODO: TEST -armop("swp", [bs('00010'), trb, bs('00'), rn, rd, bs('0000'), bs('1001'), rm]) -armop("svc", [bs('1111'), swi_i]) -armop("cdp", [bs('1110'), opc, crn, crd, cpnum, cp, bs('0'), crm], [cpnum, opc, crd, crn, crm, cp]) -armop("cdata", [bs('110'), ppi, updown, tl, wback_no_t, bs_ctransfer_name, rn_noarg, crd, cpnum, imm8_12], [cpnum, crd, imm8_12]) -armop("mr", [bs('1110'), cpopc, bs_mr_name, crn, rd, cpnum, cp, bs('1'), crm], [cpnum, cpopc, rd, crn, crm, cp]) -armop("bkpt", [bs('00010010'), imm12_noarg, bs('0111'), imm_12_4]) -armop("bx", [bs('000100101111111111110001'), rn]) -armop("mov", [bs('00110000'), imm4_noarg, rd, imm_4_12], [rd, imm_4_12]) -armop("movt", [bs('00110100'), imm4_noarg, rd, imm_4_12], [rd, imm_4_12]) -armop("blx", [bs('00010010'), bs('1111'), bs('1111'), bs('1111'), bs('0011'), rm], [rm]) -armop("blx", [fix_cond, bs('101'), lowb, offs_blx], [offs_blx]) -armop("clz", [bs('00010110'), bs('1111'), rd, bs('1111'), bs('0001'), rm], [rd, rm]) -armop("qadd", [bs('00010000'), rn, rd, bs('0000'), bs('0101'), rm], [rd, rm, rn]) - -armop("uxtb", [bs('01101110'), bs('1111'), rd, rot_rm, bs('00'), bs('0111'), rm_noarg]) -armop("uxth", [bs('01101111'), bs('1111'), rd, rot_rm, bs('00'), bs('0111'), rm_noarg]) -armop("sxtb", [bs('01101010'), bs('1111'), rd, rot_rm, bs('00'), bs('0111'), rm_noarg]) -armop("sxth", [bs('01101011'), bs('1111'), rd, rot_rm, bs('00'), bs('0111'), rm_noarg]) - -armop("rev", [bs('01101011'), bs('1111'), rd, bs('1111'), bs('0011'), rm]) -armop("rev16", [bs('01101011'), bs('1111'), rd, bs('1111'), bs('1011'), rm]) - -armop("pld", [bs8(0xF5), bs_addi, bs_rw, bs('01'), mem_rn_imm, bs('1111'), imm12_off]) - -armop("dsb", [bs('111101010111'), bs('1111'), bs('1111'), bs('0000'), bs('0100'), barrier_option]) -armop("isb", [bs('111101010111'), bs('1111'), bs('1111'), bs('0000'), bs('0110'), barrier_option]) -armop("nop", [bs8(0xE3), bs8(0x20), bs8(0xF0), bs8(0)]) - -class arm_widthm1(arm_imm, m_arg): - def decode(self, v): - self.expr = ExprInt(v+1, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) + -1 - self.value = v - return True - - -class arm_rm_rot2(arm_arg): - parser = rot2_expr - def decode(self, v): - expr = gpregs.expr[v] - shift_value = self.parent.rot2.value - if shift_value: - expr = ExprOp(allshifts[3], expr, ExprInt(shift_value * 8, 32)) - self.expr = expr - return True - def encode(self): - if self.expr in gpregs.expr: - self.value = gpregs.expr.index(self.expr) - self.parent.rot2.value = 0 - elif (isinstance(self.expr, ExprOp) and - self.expr.op == allshifts[3]): - reg, value = self.expr.args - if reg not in gpregs.expr: - return False - self.value = gpregs.expr.index(reg) - if not isinstance(value, ExprInt): - return False - value = int(value) - if not value in [8, 16, 24]: - return False - self.parent.rot2.value = value // 8 - return True - - - -class arm_rm_rot5_lsl(arm_arg): - parser = rot5_expr - index_op = 0 - def decode(self, v): - expr = gpregs.expr[v] - shift_value = self.parent.rot5.value - if shift_value: - expr = ExprOp(allshifts[self.index_op], expr, ExprInt(shift_value, 32)) - self.expr = expr - return True - def encode(self): - if self.expr in gpregs.expr: - self.value = gpregs.expr.index(self.expr) - self.parent.rot5.value = 0 - elif (isinstance(self.expr, ExprOp) and - self.expr.op == allshifts[self.index_op]): - reg, value = self.expr.args - if reg not in gpregs.expr: - return False - self.value = gpregs.expr.index(reg) - if not isinstance(value, ExprInt): - return False - value = int(value) - if not 0 <= value < 32: - return False - self.parent.rot5.value = value - return True - -class arm_rm_rot5_asr(arm_rm_rot5_lsl): - parser = rot5_expr - index_op = 2 - def decode(self, v): - expr = gpregs.expr[v] - shift_value = self.parent.rot5.value - if shift_value == 0: - expr = ExprOp(allshifts[self.index_op], expr, ExprInt(32, 32)) - else: - expr = ExprOp(allshifts[self.index_op], expr, ExprInt(shift_value, 32)) - self.expr = expr - return True - def encode(self): - if (isinstance(self.expr, ExprOp) and - self.expr.op == allshifts[self.index_op]): - reg, value = self.expr.args - if reg not in gpregs.expr: - return False - self.value = gpregs.expr.index(reg) - if not isinstance(value, ExprInt): - return False - value = int(value) - if not 0 < value <= 32: - return False - if value == 32: - value = 0 - self.parent.rot5.value = value - else: - return False - return True - - -class arm_gpreg_nopc(reg_noarg): - reg_info = gpregs_nopc - parser = reg_info.parser - - - def decode(self, v): - ret = super(arm_gpreg_nopc, self).decode(v) - if ret is False: - return False - if self.expr == reg_dum: - return False - return True - - -class arm_gpreg_nosp(reg_noarg): - reg_info = gpregs_nosp - parser = reg_info.parser - - def decode(self, v): - ret = super(arm_gpreg_nosp, self).decode(v) - if ret is False: - return False - if self.expr == reg_dum: - return False - return True - - -rm_rot2 = bs(l=4, cls=(arm_rm_rot2,), fname="rm") -rot2 = bs(l=2, fname="rot2") - -rm_rot5_lsl = bs(l=4, cls=(arm_rm_rot5_lsl,), fname="rm") -rm_rot5_asr = bs(l=4, cls=(arm_rm_rot5_asr,), fname="rm") -rot5 = bs(l=5, fname="rot5") - -widthm1 = bs(l=5, cls=(arm_widthm1, m_arg)) -lsb = bs(l=5, cls=(arm_imm, m_arg)) - -rd_nopc = bs(l=4, cls=(arm_gpreg_nopc, arm_arg), fname="rd") -rn_nopc = bs(l=4, cls=(arm_gpreg_nopc, arm_arg), fname="rn") -ra_nopc = bs(l=4, cls=(arm_gpreg_nopc, arm_arg), fname="ra") -rt_nopc = bs(l=4, cls=(arm_gpreg_nopc, arm_arg), fname="rt") - -rn_nosp = bs(l=4, cls=(arm_gpreg_nosp, arm_arg), fname="rn") - -rn_nopc_noarg = bs(l=4, cls=(arm_gpreg_nopc,), fname="rn") - -armop("ubfx", [bs('0111111'), widthm1, rd, lsb, bs('101'), rn], [rd, rn, lsb, widthm1]) - -armop("bfc", [bs('0111110'), widthm1, rd, lsb, bs('001'), bs('1111')], [rd, lsb, widthm1]) - -armop("uxtab", [bs('01101110'), rn_nopc, rd, rot2, bs('000111'), rm_rot2], [rd, rn_nopc, rm_rot2]) - -armop("pkhbt", [bs('01101000'), rn, rd, rot5, bs('001'), rm_rot5_lsl], [rd, rn, rm_rot5_lsl]) -armop("pkhtb", [bs('01101000'), rn, rd, rot5, bs('101'), rm_rot5_asr], [rd, rn, rm_rot5_asr]) - - - -# -# thumnb ####################### -# -# ARM7-TDMI-manual-pt3 -gpregs_l = reg_info(regs_str[:8], regs_expr[:8]) -gpregs_h = reg_info(regs_str[8:], regs_expr[8:]) - -gpregs_sppc = reg_info(regs_str[-1:] + regs_str[13:14], - regs_expr[-1:] + regs_expr[13:14]) - -deref_reg_imm = Group(LBRACK + gpregs.parser + Optional( - COMMA + shift_off) + RBRACK).setParseAction(cb_deref_pre_mem) -deref_low = Group(LBRACK + gpregs_l.parser + Optional( - COMMA + shift_off) + RBRACK).setParseAction(cb_deref_pre_mem) -deref_pc = Group(LBRACK + gpregs_pc.parser + Optional( - COMMA + shift_off) + RBRACK).setParseAction(cb_deref_pre_mem) -deref_sp = Group(LBRACK + gpregs_sp.parser + COMMA + - shift_off + RBRACK).setParseAction(cb_deref_pre_mem) - -gpregs_l_wb = Group( - gpregs_l.parser + Optional('!')).setParseAction(cb_gpreb_wb) - - -gpregs_l_13 = reg_info(regs_str[:13], regs_expr[:13]) - - -class arm_offreg(arm_arg): - parser = deref_pc - - def decodeval(self, v): - return v - - def encodeval(self, v): - return v - - def decode(self, v): - v = v & self.lmask - v = self.decodeval(v) - if v: - self.expr = self.off_reg + ExprInt(v, 32) - else: - self.expr = self.off_reg - - e = self.expr - if isinstance(e, ExprOp) and e.op == 'wback': - self.parent.wback.value = 1 - e = e.args[0] - return True - - def encode(self): - e = self.expr - if not (isinstance(e, ExprOp) and e.op == "preinc"): - log.debug('cannot encode %r', e) - return False - if e.args[0] != self.off_reg: - log.debug('cannot encode reg %r', e.args[0]) - return False - v = int(e.args[1]) - v = self.encodeval(v) - self.value = v - return True - - -class arm_offpc(arm_offreg): - off_reg = regs_expr[15] - - def decode(self, v): - v = v & self.lmask - v <<= 2 - if v: - self.expr = ExprMem(self.off_reg + ExprInt(v, 32), 32) - else: - self.expr = ExprMem(self.off_reg, 32) - - e = self.expr.ptr - if isinstance(e, ExprOp) and e.op == 'wback': - self.parent.wback.value = 1 - e = e.args[0] - return True - - def encode(self): - e = self.expr - if not isinstance(e, ExprMem): - return False - e = e.ptr - if not (isinstance(e, ExprOp) and e.op == "preinc"): - log.debug('cannot encode %r', e) - return False - if e.args[0] != self.off_reg: - log.debug('cannot encode reg %r', e.args[0]) - return False - v = int(e.args[1]) - if v & 3: - return False - v >>= 2 - self.value = v - return True - - - - -class arm_offsp(arm_offpc): - parser = deref_sp - off_reg = regs_expr[13] - - -class arm_offspc(arm_offs): - - def decodeval(self, v): - v = v << 1 - # Add pipeline offset - v += 2 + 2 - return v - - def encodeval(self, v): - # Remove pipeline offset - v -= 2 + 2 - if v % 2 != 0: - return False - if v > (1 << (self.l - 1)) - 1: - return False - return v >> 1 - - -class arm_off8sppc(arm_imm): - - def decodeval(self, v): - return v << 2 - - def encodeval(self, v): - return v >> 2 - - -class arm_off7(arm_imm): - - def decodeval(self, v): - return v << 2 - - def encodeval(self, v): - return v >> 2 - -class arm_deref_reg_imm(arm_arg): - parser = deref_reg_imm - - def decode(self, v): - v = v & self.lmask - rbase = regs_expr[v] - e = ExprOp('preinc', rbase, self.parent.off.expr) - self.expr = ExprMem(e, 32) - return True - - def encode(self): - self.parent.off.expr = None - e = self.expr - if not isinstance(e, ExprMem): - return False - e = e.ptr - if not (isinstance(e, ExprOp) and e.op == 'preinc'): - log.debug('cannot encode %r', e) - return False - off = e.args[1] - if isinstance(off, ExprId): - self.parent.off.expr = off - elif isinstance(off, ExprInt): - self.parent.off.expr = off - else: - log.debug('cannot encode off %r', off) - return False - self.value = gpregs.expr.index(e.args[0]) - if self.value >= 1 << self.l: - log.debug('cannot encode reg %r', off) - return False - return True - -class arm_derefl(arm_deref_reg_imm): - parser = deref_low - - -class arm_offbw(imm_noarg): - - def decode(self, v): - v = v & self.lmask - if self.parent.trb.value == 0: - v <<= 2 - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) - if self.parent.trb.value == 0: - if v & 3: - log.debug('off must be aligned %r', v) - return False - v >>= 2 - self.value = v - return True - - - -class arm_off(imm_noarg): - - def decode(self, v): - v = v & self.lmask - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) - self.value = v - return True - - -class arm_offh(imm_noarg): - - def decode(self, v): - v = v & self.lmask - v <<= 1 - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) - if v & 1: - log.debug('off must be aligned %r', v) - return False - v >>= 1 - self.value = v - return True - - -class armt_rlist(arm_arg): - parser = gpreg_list - - def encode(self): - e = self.expr - rlist = [gpregs_l.expr.index(x) for x in e.args] - v = 0 - for r in rlist: - v |= 1 << r - self.value = v - return True - - def decode(self, v): - v = v & self.lmask - out = [] - for i in range(0x10): - if 1 << i & v: - out.append(gpregs.expr[i]) - if not out: - return False - e = ExprOp('reglist', *out) - self.expr = e - return True - - -class armt_rlist13(armt_rlist): - parser = gpreg_list - - def encode(self): - e = self.expr - rlist = [] - reg_l = list(e.args) - - self.parent.pclr.value = 0 - if self.parent.name.startswith('PUSH'): - if regs_expr[14] in reg_l: - reg_l.remove(regs_expr[14]) - self.parent.pclr.value = 1 - else: - if regs_expr[15] in reg_l: - reg_l.remove(regs_expr[15]) - self.parent.pclr.value = 1 - - for reg in reg_l: - if reg not in gpregs_l_13.expr: - return False - rlist.append(gpregs_l_13.expr.index(reg)) - v = 0 - for r in rlist: - v |= 1 << r - self.value = v - return True - - def decode(self, v): - v = v & self.lmask - out = [] - for i in range(13): - if 1 << i & v: - out.append(gpregs_l_13.expr[i]) - - if self.parent.pclr.value == 1: - if self.parent.name.startswith("PUSH"): - out += [regs_expr[14]] - else: - out += [regs_expr[15]] - - if not out: - return False - e = ExprOp('reglist', *out) - self.expr = e - return True - - - -class armt_rlist13_pc_lr(armt_rlist): - parser = gpreg_list - - def encode(self): - e = self.expr - rlist = [] - reg_l = list(e.args) - - self.parent.pc_in.value = 0 - self.parent.lr_in.value = 0 - if regs_expr[14] in reg_l: - reg_l.remove(regs_expr[14]) - self.parent.lr_in.value = 1 - if regs_expr[15] in reg_l: - reg_l.remove(regs_expr[15]) - self.parent.pc_in.value = 1 - - for reg in reg_l: - if reg not in gpregs_l_13.expr: - return False - rlist.append(gpregs_l_13.expr.index(reg)) - v = 0 - for r in rlist: - v |= 1 << r - self.value = v - return True - - def decode(self, v): - v = v & self.lmask - out = [] - for i in range(13): - if 1 << i & v: - out.append(gpregs_l_13.expr[i]) - - if self.parent.lr_in.value == 1: - out += [regs_expr[14]] - if self.parent.pc_in.value == 1: - out += [regs_expr[15]] - - if not out: - return False - e = ExprOp('reglist', *out) - self.expr = e - return True - - - -class armt_rlist_pclr(armt_rlist): - - def encode(self): - e = self.expr - reg_l = list(e.args) - self.parent.pclr.value = 0 - if self.parent.pp.value == 0: - if regs_expr[14] in reg_l: - reg_l.remove(regs_expr[14]) - self.parent.pclr.value = 1 - else: - if regs_expr[15] in reg_l: - reg_l.remove(regs_expr[15]) - self.parent.pclr.value = 1 - rlist = [gpregs.expr.index(x) for x in reg_l] - v = 0 - for r in rlist: - v |= 1 << r - self.value = v - return True - - def decode(self, v): - v = v & self.lmask - out = [] - for i in range(0x10): - if 1 << i & v: - out.append(gpregs.expr[i]) - - if self.parent.pclr.value == 1: - if self.parent.pp.value == 0: - out += [regs_expr[14]] - else: - out += [regs_expr[15]] - if not out: - return False - e = ExprOp('reglist', *out) - self.expr = e - return True - - -class armt_reg_wb(arm_reg_wb): - reg_info = gpregs_l - parser = gpregs_l_wb - - def decode(self, v): - v = v & self.lmask - e = self.reg_info.expr[v] - if not e in self.parent.trlist.expr.args: - e = ExprOp('wback', e) - self.expr = e - return True - - def encode(self): - e = self.expr - if isinstance(e, ExprOp): - if e.op != 'wback': - return False - e = e.args[0] - self.value = self.reg_info.expr.index(e) - return True - - -class arm_gpreg_l(arm_reg): - reg_info = gpregs_l - parser = reg_info.parser - - -class arm_gpreg_h(arm_reg): - reg_info = gpregs_h - parser = reg_info.parser - - -class arm_gpreg_l_noarg(arm_gpreg_noarg): - reg_info = gpregs_l - parser = reg_info.parser - - -class arm_sppc(arm_reg): - reg_info = gpregs_sppc - parser = reg_info.parser - - -class arm_sp(arm_reg): - reg_info = gpregs_sp - parser = reg_info.parser - -off5 = bs(l=5, cls=(arm_imm,), fname="off") -off3 = bs(l=3, cls=(arm_imm,), fname="off") -off8 = bs(l=8, cls=(arm_imm,), fname="off") -off7 = bs(l=7, cls=(arm_off7,), fname="off") - -rdl = bs(l=3, cls=(arm_gpreg_l,), fname="rd") -rnl = bs(l=3, cls=(arm_gpreg_l,), fname="rn") -rsl = bs(l=3, cls=(arm_gpreg_l,), fname="rs") -rml = bs(l=3, cls=(arm_gpreg_l,), fname="rm") -rol = bs(l=3, cls=(arm_gpreg_l,), fname="ro") -rbl = bs(l=3, cls=(arm_gpreg_l,), fname="rb") -rbl_deref = bs(l=3, cls=(arm_derefl,), fname="rb") -dumrh = bs(l=3, default_val="000") - -rdh = bs(l=3, cls=(arm_gpreg_h,), fname="rd") -rsh = bs(l=3, cls=(arm_gpreg_h,), fname="rs") - -offpc8 = bs(l=8, cls=(arm_offpc,), fname="offs") -offsp8 = bs(l=8, cls=(arm_offsp,), fname="offs") -rol_noarg = bs(l=3, cls=(arm_gpreg_l_noarg,), fname="off") - -off5bw = bs(l=5, cls=(arm_offbw,), fname="off") -off5h = bs(l=5, cls=(arm_offh,), fname="off") -sppc = bs(l=1, cls=(arm_sppc,)) - -off12 = bs(l=12, cls=(arm_off,), fname="off", order=-1) -rn_deref = bs(l=4, cls=(arm_deref_reg_imm,), fname="rt") - - - -pclr = bs(l=1, fname='pclr', order=-2) - - -pc_in = bs(l=1, fname='pc_in', order=-2) -lr_in = bs(l=1, fname='lr_in', order=-2) - - -sp = bs(l=0, cls=(arm_sp,)) - - -off8s = bs(l=8, cls=(arm_offs,), fname="offs") -trlistpclr = bs(l=8, cls=(armt_rlist_pclr,)) -trlist = bs(l=8, cls=(armt_rlist,), fname="trlist", order = -1) -trlist13 = bs(l=13, cls=(armt_rlist13,), fname="trlist", order = -1) -trlist13pclr = bs(l=13, cls=(armt_rlist13_pc_lr,), fname="trlist", order = -1) - - -rbl_wb = bs(l=3, cls=(armt_reg_wb,), fname='rb') - -offs8 = bs(l=8, cls=(arm_offspc,), fname="offs") -offs11 = bs(l=11, cls=(arm_offspc,), fname="offs") - -hl = bs(l=1, prio=default_prio + 1, fname='hl') -off8sppc = bs(l=8, cls=(arm_off8sppc,), fname="off") - -imm8_d1 = bs(l=8, default_val="00000001") -imm8 = bs(l=8, cls=(arm_imm,), default_val = "00000001") - - -mshift_name = {'LSLS': 0, 'LSRS': 1, 'ASRS': 2} -bs_mshift_name = bs_name(l=2, name=mshift_name) - - -addsub_name = {'ADDS': 0, 'SUBS': 1} -bs_addsub_name = bs_name(l=1, name=addsub_name) - -mov_cmp_add_sub_name = {'MOVS': 0, 'CMP': 1, 'ADDS': 2, 'SUBS': 3} -bs_mov_cmp_add_sub_name = bs_name(l=2, name=mov_cmp_add_sub_name) - -alu_name = {'ANDS': 0, 'EORS': 1, 'LSLS': 2, 'LSRS': 3, - 'ASRS': 4, 'ADCS': 5, 'SBCS': 6, 'RORS': 7, - 'TST': 8, 'NEGS': 9, 'CMP': 10, 'CMN': 11, - 'ORRS': 12, 'MULS': 13, 'BICS': 14, 'MVNS': 15} -bs_alu_name = bs_name(l=4, name=alu_name) - -hiregop_name = {'ADDS': 0, 'CMP': 1, 'MOV': 2} -bs_hiregop_name = bs_name(l=2, name=hiregop_name) - -ldr_str_name = {'STR': 0, 'LDR': 1} -bs_ldr_str_name = bs_name(l=1, name=ldr_str_name) - -ldrh_strh_name = {'STRH': 0, 'LDRH': 1} -bs_ldrh_strh_name = bs_name(l=1, name=ldrh_strh_name) - -ldstsp_name = {'STR': 0, 'LDR': 1} -bs_ldstsp_name = bs_name(l=1, name=ldstsp_name) - -addsubsp_name = {'ADD': 0, 'SUB': 1} -bs_addsubsp_name = bs_name(l=1, name=addsubsp_name) - -pushpop_name = {'PUSH': 0, 'POP': 1} -bs_pushpop_name = bs_name(l=1, name=pushpop_name, fname='pp') - -tbtransfer_name = {'STMIA': 0, 'LDMIA': 1} -bs_tbtransfer_name = bs_name(l=1, name=tbtransfer_name) - -br_name = {'BEQ': 0, 'BNE': 1, 'BCS': 2, 'BCC': 3, 'BMI': 4, - 'BPL': 5, 'BVS': 6, 'BVC': 7, 'BHI': 8, 'BLS': 9, - 'BGE': 10, 'BLT': 11, 'BGT': 12, 'BLE': 13} -bs_br_name = bs_name(l=4, name=br_name) - - -armtop("mshift", [bs('000'), bs_mshift_name, off5, rsl, rdl], [rdl, rsl, off5]) -armtop("addsubr", [bs('000110'), bs_addsub_name, rnl, rsl, rdl], [rdl, rsl, rnl]) -armtop("addsubi", [bs('000111'), bs_addsub_name, off3, rsl, rdl], [rdl, rsl, off3]) -armtop("mcas", [bs('001'), bs_mov_cmp_add_sub_name, rnl, off8]) -armtop("alu", [bs('010000'), bs_alu_name, rsl, rdl], [rdl, rsl]) - # should not be used ?? -armtop("hiregop00", [bs('010001'), bs_hiregop_name, bs('00'), rsl, rdl], [rdl, rsl]) -armtop("hiregop01", [bs('010001'), bs_hiregop_name, bs('01'), rsh, rdl], [rdl, rsh]) -armtop("hiregop10", [bs('010001'), bs_hiregop_name, bs('10'), rsl, rdh], [rdh, rsl]) -armtop("hiregop11", [bs('010001'), bs_hiregop_name, bs('11'), rsh, rdh], [rdh, rsh]) -armtop("bx", [bs('010001'), bs('11'), bs('00'), rsl, dumrh]) -armtop("bx", [bs('010001'), bs('11'), bs('01'), rsh, dumrh]) -armtop("ldr", [bs('01001'), rdl, offpc8]) -armtop("ldrstr", [bs('0101'), bs_ldr_str_name, trb, bs('0'), rol_noarg, rbl_deref, rdl], [rdl, rbl_deref]) -armtop("strh", [bs('0101'), bs('00'), bs('1'), rol_noarg, rbl_deref, rdl], [rdl, rbl_deref]) -armtop("ldrh", [bs('0101'), bs('10'), bs('1'), rol_noarg, rbl_deref, rdl], [rdl, rbl_deref]) -armtop("ldsb", [bs('0101'), bs('01'), bs('1'), rol_noarg, rbl_deref, rdl], [rdl, rbl_deref]) -armtop("ldsh", [bs('0101'), bs('11'), bs('1'), rol_noarg, rbl_deref, rdl], [rdl, rbl_deref]) -armtop("ldst", [bs('011'), trb, bs_ldr_str_name, off5bw, rbl_deref, rdl], [rdl, rbl_deref]) -armtop("ldhsth", [bs('1000'), bs_ldrh_strh_name, off5h, rbl_deref, rdl], [rdl, rbl_deref]) -armtop("ldstsp", [bs('1001'), bs_ldstsp_name, rdl, offsp8], [rdl, offsp8]) -armtop("add", [bs('1010'), sppc, rdl, off8sppc], [rdl, sppc, off8sppc]) -armtop("addsp", [bs('10110000'), bs_addsubsp_name, sp, off7], [sp, off7]) -armtop("pushpop", [bs('1011'), bs_pushpop_name, bs('10'), pclr, trlistpclr], [trlistpclr]) -armtop("btransfersp", [bs('1100'), bs_tbtransfer_name, rbl_wb, trlist]) -armtop("br", [bs('1101'), bs_br_name, offs8]) -armtop("blx", [bs("01000111"), bs('1'), rm, bs('000')]) -armtop("svc", [bs('11011111'), imm8]) -armtop("b", [bs('11100'), offs11]) -armtop("und", [bs('1101'), bs('1110'), imm8_d1]) - -armtop("rev", [bs('10111010'), bs('00'), rsl, rdl], [rdl, rsl]) -armtop("rev16", [bs('10111010'), bs('01'), rsl, rdl], [rdl, rsl]) - -armtop("uxtb", [bs('10110010'), bs('11'), rml, rdl], [rdl, rml]) -armtop("uxth", [bs('10110010'), bs('10'), rml, rdl], [rdl, rml]) -armtop("sxtb", [bs('10110010'), bs('01'), rml, rdl], [rdl, rml]) -armtop("sxth", [bs('10110010'), bs('00'), rml, rdl], [rdl, rml]) - -armtop("uxtab", [bs('111110100'), bs('101'), rn_nopc, bs('1111'), rd, bs('10'), rot2, rm_rot2], [rd, rn_nopc, rm_rot2]) -armtop("uxtah", [bs('111110100'), bs('001'), rn_nopc, bs('1111'), rd, bs('10'), rot2, rm_rot2], [rd, rn_nopc, rm_rot2]) - -# thumb2 ###################### -# -# ARM Architecture Reference Manual Thumb-2 Supplement - -armt_gpreg_shift_off = (gpregs_nosppc.parser + allshifts_t_armt + (gpregs.parser | int_1_31)).setParseAction(cb_shift) - - -armt_gpreg_shift_off |= gpregs_nosppc.parser - - -class arm_gpreg_nosppc(arm_reg): - reg_info = gpregs_nosppc - parser = reg_info.parser - - def decode(self, v): - ret = super(arm_gpreg_nosppc, self).decode(v) - if ret is False: - return False - if self.expr == reg_dum: - return False - return True - - -class armt_gpreg_rm_shift_off(arm_reg): - parser = armt_gpreg_shift_off - - def decode(self, v): - v = v & self.lmask - if v >= len(gpregs_nosppc.expr): - return False - r = gpregs_nosppc.expr[v] - if r == reg_dum: - return False - - i = int(self.parent.imm5_3.value) << 2 - i |= int(self.parent.imm5_2.value) - - if self.parent.stype.value < 3 or i != 0: - shift = allshifts_armt[self.parent.stype.value] - else: - shift = allshifts_armt[4] - self.expr = ExprOp(shift, r, ExprInt(i, 32)) - return True - - def encode(self): - e = self.expr - if isinstance(e, ExprId): - if e not in gpregs_nosppc.expr: - return False - self.value = gpregs_nosppc.expr.index(e) - self.parent.stype.value = 0 - self.parent.imm5_3.value = 0 - self.parent.imm5_2.value = 0 - return True - if not e.is_op(): - return False - shift = e.op - r = gpregs_nosppc.expr.index(e.args[0]) - self.value = r - i = int(e.args[1]) - if shift == 'rrx': - if i != 1: - log.debug('rrx shift must be 1') - return False - self.parent.imm5_3.value = 0 - self.parent.imm5_2.value = 0 - self.parent.stype.value = 3 - return True - self.parent.stype.value = allshifts_armt.index(shift) - self.parent.imm5_2.value = i & 3 - self.parent.imm5_3.value = i >> 2 - return True - -rn_nosppc = bs(l=4, cls=(arm_gpreg_nosppc,), fname="rn") -rd_nosppc = bs(l=4, cls=(arm_gpreg_nosppc,), fname="rd") -rm_sh = bs(l=4, cls=(armt_gpreg_rm_shift_off,), fname="rm") - - -class armt2_imm12(arm_imm): - - def decode(self, v): - v = v & self.lmask - v |= int(self.parent.imm12_3.value) << 8 - v |= int(self.parent.imm12_1.value) << 11 - - # simple encoding - if 0 <= v < 0x100: - self.expr = ExprInt(v, 32) - return True - # 00XY00XY form - if v >> 8 == 1: - v &= 0xFF - self.expr = ExprInt((v << 16) | v, 32) - return True - # XY00XY00 form - if v >> 8 == 2: - v &= 0xFF - self.expr = ExprInt((v << 24) | (v << 8), 32) - return True - # XYXYXYXY - if v >> 8 == 3: - v &= 0xFF - self.expr = ExprInt((v << 24) | (v << 16) | (v << 8) | v, 32) - return True - r = v >> 7 - v = 0x80 | (v & 0x7F) - self.expr = ExprInt(myror32(v, r), 32) - return True - - def encode(self): - if not self.expr.is_int(): - return False - v = int(self.expr) - value = None - # simple encoding - if 0 <= v < 0x100: - value = v - elif v & 0xFF00FF00 == 0 and v & 0xFF == (v >> 16) & 0xff: - # 00XY00XY form - value = (1 << 8) | (v & 0xFF) - elif v & 0x00FF00FF == 0 and (v >> 8) & 0xff == (v >> 24) & 0xff: - # XY00XY00 form - value = (2 << 8) | ((v >> 8) & 0xff) - elif (v & 0xFF == - (v >> 8) & 0xFF == - (v >> 16) & 0xFF == - (v >> 24) & 0xFF): - # XYXYXYXY form - value = (3 << 8) | ((v >> 16) & 0xff) - else: - # rol encoding - for i in range(32): - o = myrol32(v, i) - if 0x80 <= o <= 0xFF: - value = (i << 7) | (o & 0x7F) - break - if value is None: - log.debug('cannot encode imm12') - return False - self.value = value & self.lmask - self.parent.imm12_3.value = (value >> 8) & self.parent.imm12_3.lmask - self.parent.imm12_1.value = (value >> 11) & self.parent.imm12_1.lmask - return True - - - - -class armt4_imm12(arm_imm): - - def decode(self, v): - v = v & self.lmask - v |= int(self.parent.imm12_3.value) << 8 - v |= int(self.parent.imm12_1.value) << 11 - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not self.expr.is_int(): - return False - value = int(self.expr) - if value >= (1 << 16): - return False - self.value = value & self.lmask - self.parent.imm12_3.value = (value >> 8) & self.parent.imm12_3.lmask - self.parent.imm12_1.value = (value >> 11) & self.parent.imm12_1.lmask - return True - - - -class armt2_imm16(arm_imm): - - def decode(self, v): - v = v & self.lmask - v |= int(self.parent.imm16_3.value) << 8 - v |= int(self.parent.imm16_1.value) << 11 - v |= int(self.parent.imm16_4.value) << 12 - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not self.expr.is_int(): - return False - value = int(self.expr) - if value >= (1 << 16): - return False - self.value = value & self.lmask - self.parent.imm16_3.value = (value >> 8) & self.parent.imm16_3.lmask - self.parent.imm16_1.value = (value >> 11) & self.parent.imm16_1.lmask - self.parent.imm16_4.value = (value >> 12) & self.parent.imm16_4.lmask - return True - - -class armt2_lsb5(arm_imm): - - def decode(self, v): - v = v & self.lmask - v |= int(self.parent.lsb5_3.value) << 2 - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not self.expr.is_int(): - return False - value = int(self.expr) - self.value = value & self.lmask - self.parent.lsb5_3.value = (value >> 2) & self.parent.lsb5_3.lmask - return True - - -class armt_widthm1(arm_imm): - parser = base_expr - - def decodeval(self, v): - return v + 1 - - def encodeval(self, v): - if v <= 0: - return False - return v - 1 - - - - -class armt2_off20(arm_imm): - - def decode(self, v): - v = v & self.lmask - v <<= 1 - v |= int(self.parent.off20_6.value) << 12 - v |= int(self.parent.off20_j1.value) << 18 - v |= int(self.parent.off20_j2.value) << 19 - v |= int(self.parent.off20_s.value) << 20 - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not self.expr.is_int(): - return False - value = int(self.expr) - if value & 1: - return False - self.value = (value >> 1) & self.lmask - self.parent.off20_6.value = (value >> 12) & self.parent.off20_6.lmask - self.parent.off20_j1.value = (value >> 18) & self.parent.off20_j1.lmask - self.parent.off20_j2.value = (value >> 19) & self.parent.off20_j2.lmask - self.parent.off20_s.value = (value >> 20) & self.parent.off20_s.lmask - return True - - - -class armt2_imm10l(arm_imm): - - def decode(self, v): - v = v & self.lmask - s = self.parent.sign.value - j1 = self.parent.j1.value - j2 = self.parent.j2.value - imm10h = self.parent.imm10h.value - imm10l = v - - i1, i2 = j1 ^ s ^ 1, j2 ^ s ^ 1 - - v = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10h << 12) | (imm10l << 2) - v = sign_ext(v, 25, 32) - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) - s = 0 - if v & 0x80000000: - s = 1 - v &= (1<<26) - 1 - if v >= (1 << 26): - return False - i1, i2, imm10h, imm10l = (v >> 23) & 1, (v >> 22) & 1, (v >> 12) & 0x3ff, (v >> 2) & 0x3ff - j1, j2 = i1 ^ s ^ 1, i2 ^ s ^ 1 - self.parent.sign.value = s - self.parent.j1.value = j1 - self.parent.j2.value = j2 - self.parent.imm10h.value = imm10h - self.value = imm10l - return True - - -class armt2_imm11l(arm_imm): - - def decode(self, v): - v = v & self.lmask - s = self.parent.sign.value - j1 = self.parent.j1.value - j2 = self.parent.j2.value - imm10h = self.parent.imm10h.value - imm11l = v - - i1, i2 = j1 ^ s ^ 1, j2 ^ s ^ 1 - - v = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10h << 12) | (imm11l << 1) - v = sign_ext(v, 25, 32) - self.expr = ExprInt(v + 4, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = (int(self.expr) - 4) & int(self.expr.mask) - s = 0 - if v & 0x80000000: - s = 1 - v &= (1<<26) - 1 - if v >= (1 << 26): - return False - if v & 1: - return False - i1, i2, imm10h, imm11l = (v >> 23) & 1, (v >> 22) & 1, (v >> 12) & 0x3ff, (v >> 1) & 0x7ff - j1, j2 = i1 ^ s ^ 1, i2 ^ s ^ 1 - self.parent.sign.value = s - self.parent.j1.value = j1 - self.parent.j2.value = j2 - self.parent.imm10h.value = imm10h - self.value = imm11l - return True - - - -class armt2_imm6_11l(arm_imm): - - def decode(self, v): - v = v & self.lmask - s = self.parent.sign.value - j1 = self.parent.j1.value - j2 = self.parent.j2.value - imm6h = self.parent.imm6h.value - imm11l = v - - v = (s << 20) | (j2 << 19) | (j1 << 18) | (imm6h << 12) | (imm11l << 1) - v = sign_ext(v, 21, 32) - self.expr = ExprInt(v + 4, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = (int(self.expr) - 4) & int(self.expr.mask) - s = 0 - if v != sign_ext(v & ((1 << 22) - 1), 21, 32): - return False - if v & 0x80000000: - s = 1 - v &= (1<<22) - 1 - if v & 1: - return False - i2, i1, imm6h, imm11l = (v >> 19) & 1, (v >> 18) & 1, (v >> 12) & 0x3f, (v >> 1) & 0x7ff - self.parent.sign.value = s - self.parent.j1.value = i1 - self.parent.j2.value = i2 - self.parent.imm6h.value = imm6h - self.value = imm11l - return True - - - -imm12_1 = bs(l=1, fname="imm12_1", order=1) -imm12_3 = bs(l=3, fname="imm12_3", order=1) -imm12_8 = bs(l=8, cls=(armt2_imm12,), fname="imm", order=2) - - -imm12_8_t4 = bs(l=8, cls=(armt4_imm12,), fname="imm", order=2) - - -imm16_1 = bs(l=1, fname="imm16_1", order=1) -imm16_3 = bs(l=3, fname="imm16_3", order=1) -imm16_4 = bs(l=4, fname="imm16_4", order=1) -imm16_8 = bs(l=8, cls=(armt2_imm16,), fname="imm", order=2) - - -imm5_3 = bs(l=3, fname="imm5_3") -imm5_2 = bs(l=2, fname="imm5_2") -imm_stype = bs(l=2, fname="stype") - -imm_stype_00 = bs('00', fname="stype") -imm_stype_01 = bs('01', fname="stype") -imm_stype_11 = bs('11', fname="stype") - - -imm1 = bs(l=1, fname="imm1") - - - -off20_6 = bs(l=6, fname="off20_6", order=1) -off20_11 = bs(l=11, cls=(armt2_off20,), fname="imm", order=2) - - - -lsb5_3 = bs(l=3, fname="lsb5_3", order=1) -lsb5_2 = bs(l=2, cls=(armt2_lsb5,), fname="imm", order=2) - -widthm1 = bs(l=5, cls=(armt_widthm1,), fname="imm", order=2) - - - -class armt_imm5_1(arm_imm): - - def decode(self, v): - v = ((self.parent.imm1.value << 5) | v) << 1 - self.expr = ExprInt(v, 32) - return True - - def encode(self): - if not isinstance(self.expr, ExprInt): - return False - v = int(self.expr) - if v & 0x1: - return False - self.parent.imm1.value = (v >> 6) & 1 - self.value = (v >> 1) & 0x1f - return True - -aif_str = ["X", "F", "I", "IF", "A", "AF", "AI", "AIF"] -aif_expr = [ExprId(x, 32) if x != None else None for x in aif_str] - -aif_reg = reg_info(aif_str, aif_expr) - -class armt_aif(reg_noarg, arm_arg): - reg_info = aif_reg - parser = reg_info.parser - - def decode(self, v): - if v == 0: - return False - return super(armt_aif, self).decode(v) - - def encode(self): - ret = super(armt_aif, self).encode() - if not ret: - return ret - return self.value != 0 - - def fromstring(self, text, loc_db, parser_result=None): - start, stop = super(armt_aif, self).fromstring(text, loc_db, parser_result) - if self.expr.name == "X": - return None, None - return start, stop - - -class armt_it_arg(arm_arg): - arg_E = ExprId('E', 1) - arg_NE = ExprId('NE', 1) - - def decode(self, v): - if v: - return self.arg_E - else: - return self.arg_NE - - def encode(self): - if self.expr == self.arg_E: - return 1 - elif self.expr == self.arg_NE: - return 0 - -class armt_itmask(bs_divert): - prio = 2 - - def divert(self, i, candidates): - out = [] - for cls, _, bases, dct, fields in candidates: - for value in range(1, 0x10): - nfields = fields[:] - s = int2bin(value, self.args['l']) - args = dict(self.args) - args.update({'strbits': s}) - f = bs(**args) - nfields[i] = f - inv = nfields[-2].value - ndct = dict(dct) - ndct['name'] = self.modname(ndct['name'], value, inv) - out.append((cls, ndct['name'], bases, ndct, nfields)) - return out - - def modname(self, name, value, inv): - count = 0 - while value & (1 << count) == 0: - count += 1 - out = [] - values = ['E', 'T'] - if inv== 1: - values.reverse() - for index in range(3 - count): - if value & (1 << (3 - index)): - out.append(values[0]) - else: - out.append(values[1]) - return name + "".join(out) - - - -class armt_cond_lsb(bs_divert): - prio = 2 - - def divert(self, i, candidates): - out = [] - for cls, _, bases, dct, fields in candidates: - for value in range(2): - nfields = fields[:] - s = int2bin(value, self.args['l']) - args = dict(self.args) - args.update({'strbits': s}) - f = bs(**args) - nfields[i] = f - ndct = dict(dct) - out.append((cls, ndct['name'], bases, ndct, nfields)) - return out - - -cond_expr = [ExprId(x, 32) for x in cond_list_full] -cond_info = reg_info(cond_list_full, cond_expr) - -class armt_cond_arg(arm_arg): - parser = cond_info.parser - - def decode(self, v): - v = (v << 1) | self.parent.condlsb.value - self.expr = ExprId(cond_list_full[v], 32) - return True - - def encode(self): - index = cond_list_full.index(self.expr.name) - self.value = index >> 1 - if index & 1 != self.parent.condlsb.value: - return False - return True - - -class armt_op2imm(arm_imm8_12): - parser = deref - - def str_to_imm_rot_form(self, s, neg=False): - if neg: - s = -s & 0xffffffff - if 0 <= s < (1 << 12): - return s - return None - - def decodeval(self, v): - return v - - def encodeval(self, v): - return v - - def decode(self, v): - val = v & self.lmask - val = self.decodeval(val) - if val is False: - return False - imm = val - if self.parent.updown.value == 0: - imm = -imm - if self.parent.ppi.value == 0 and self.parent.wback.value == 0: - return False - if self.parent.ppi.value: - e = ExprOp('preinc', self.parent.rn.expr, ExprInt(imm, 32)) - if self.parent.wback.value == 1: - e = ExprOp('wback', e) - else: - e = ExprOp('postinc', self.parent.rn.expr, ExprInt(imm, 32)) - self.expr = ExprMem(e, 32) - return True - - def encode(self): - self.parent.updown.value = 1 - self.parent.wback.value = 0 - - e = self.expr - assert(isinstance(e, ExprMem)) - e = e.ptr - if e.op == 'wback': - self.parent.wback.value = 1 - e = e.args[0] - if e.op == "postinc": - self.parent.ppi.value = 0 - self.parent.wback.value = 1 - elif e.op == "preinc": - self.parent.ppi.value = 1 - else: - # XXX default - self.parent.ppi.value = 1 - - self.parent.rn.expr = e.args[0] - - if len(e.args) == 1: - self.value = 0 - return True - # pure imm - if isinstance(e.args[1], ExprInt): - val = self.str_to_imm_rot_form(int(e.args[1])) - if val is None: - val = self.str_to_imm_rot_form(int(e.args[1]), True) - if val is None: - log.debug('cannot encode inm') - return False - self.parent.updown.value = 0 - val = self.encodeval(val) - if val is False: - return False - self.value = val - return True - # pure reg - if isinstance(e.args[1], ExprId): - rm = gpregs.expr.index(e.args[1]) - shift_kind = 0 - shift_type = 0 - amount = 0 - val = (((((amount << 2) | shift_type) << 1) | shift_kind) << 4) | rm - val = self.encodeval(val) - if val is False: - return False - self.value = val - return True - return False - - -class armt_op2imm00(armt_op2imm): - - def decodeval(self, v): - return v << 2 - - def encodeval(self, v): - if v & 3: - return False - return v >> 2 - - -class armt_deref_reg(arm_imm8_12): - parser = deref - - def decode(self, v): - base = self.parent.rn.expr - off = gpregs.expr[v] - if self.parent.imm.value != 0: - off = off << ExprInt(self.parent.imm.value, 32) - e = ExprMem(ExprOp('preinc', base, off), 8) - self.expr = e - return True - - def encode(self): - if not isinstance(self.expr, ExprMem): - return False - ptr = self.expr.ptr - if not ptr.is_op('preinc'): - return False - if len(ptr.args) != 2: - return False - base, off = ptr.args - if base.is_id() and off.is_id(): - self.parent.rn.expr = base - self.parent.imm.value = 0 - self.value = gpregs.expr.index(off) - elif off.is_int(): - return False - elif off.is_op('<<'): - if len(off.args) != 2: - return False - reg, off = off.args - self.parent.rn.expr = base - self.parent.imm.value = 0 - self.value = gpregs.expr.index(reg) - off = int(off) - if off > self.parent.imm.lmask: - return False - self.parent.imm.value = off - return True - - -class armt_deref_reg_reg(arm_arg): - parser = deref_reg_reg - reg_info = gpregs - - def decode(self, v): - expr = self.reg_info.expr[v] - expr = ExprMem(self.parent.rn.expr + expr, 8) - self.expr = expr - return True - - def encode(self): - expr = self.expr - if not expr.is_mem(): - return False - ptr = expr.ptr - if not ptr.is_op('+') or len(ptr.args) != 2: - return False - reg1, reg2 = ptr.args - self.parent.rn.expr = reg1 - self.value = self.reg_info.expr.index(reg2) - return True - - -class armt_deref_reg_reg_lsl_1(arm_reg): - parser = deref_reg_reg_lsl_1 - reg_info = gpregs - - def decode(self, v): - expr = self.reg_info.expr[v] - expr = ExprMem(self.parent.rn.expr + (expr << ExprInt(1, 32)), 16) - self.expr = expr - return True - - def encode(self): - expr = self.expr - if not expr.is_mem(): - return False - ptr = expr.ptr - if not ptr.is_op('+') or len(ptr.args) != 2: - return False - reg1, reg_shift = ptr.args - self.parent.rn.expr = reg1 - if not reg_shift.is_op('<<') or len(reg_shift.args) != 2: - return False - if reg_shift.args[1] != ExprInt(1, 32): - return False - self.value = self.reg_info.expr.index(reg_shift.args[0]) - return True - - -aif = bs(l=3, cls=(armt_aif,)) - - -imm5_off = bs(l=5, cls=(armt_imm5_1,), fname="imm5_off") - -tsign = bs(l=1, fname="sign") -tj1 = bs(l=1, fname="j1") -tj2 = bs(l=1, fname="j2") - -timm6h = bs(l=6, fname="imm6h") -timm10H = bs(l=10, fname="imm10h") -timm10L = bs(l=10, cls=(armt2_imm10l,), fname="imm10l") -timm11L = bs(l=11, cls=(armt2_imm11l,), fname="imm11l") - -timm6h11l = bs(l=11, cls=(armt2_imm6_11l,), fname="imm6h11l") - -itcond = bs(l=4, fname="itcond") -itmask = armt_itmask(l=4, fname="itmask") -bs_cond_arg_msb = bs(l=3, cls=(armt_cond_arg,)) - - -condlsb = armt_cond_lsb(l=1, fname="condlsb") - -deref_immpuw = bs(l=8, cls=(armt_op2imm,)) -deref_immpuw00 = bs(l=8, cls=(armt_op2imm00,)) - - -rm_deref_reg = bs(l=4, cls=(armt_deref_reg,)) - -bs_deref_reg_reg = bs(l=4, cls=(armt_deref_reg_reg,)) -bs_deref_reg_reg_lsl_1 = bs(l=4, cls=(armt_deref_reg_reg_lsl_1,)) - - -armtop("adc", [bs('11110'), imm12_1, bs('0'), bs('1010'), scc, rn_nosppc, bs('0'), imm12_3, rd_nosppc, imm12_8]) -armtop("adc", [bs('11101'), bs('01'), bs('1010'), scc, rn_nosppc, bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh]) -armtop("bl", [bs('11110'), tsign, timm10H, bs('11'), tj1, bs('1'), tj2, timm11L]) -armtop("blx", [bs('11110'), tsign, timm10H, bs('11'), tj1, bs('0'), tj2, timm10L, bs('0')]) -armtop("cbz", [bs('101100'), imm1, bs('1'), imm5_off, rnl], [rnl, imm5_off]) -armtop("cbnz", [bs('101110'), imm1, bs('1'), imm5_off, rnl], [rnl, imm5_off]) - -armtop("bkpt", [bs('1011'), bs('1110'), imm8]) - - -armtop("it", [bs('10111111'), bs_cond_arg_msb, condlsb, itmask]) - - -armtop("nop", [bs8(0xBF),bs8(0x0)]) -armtop("wfi", [bs8(0xBF),bs8(0x30)]) -armtop("cpsid", [bs8(0xB6),bs('0111'), bs('0'), aif], [aif]) -armtop("cpsie", [bs8(0xB6),bs('0110'), bs('0'), aif], [aif]) - -armtop("push", [bs('1110100'), bs('10'), bs('0'), bs('1'), bs('0'), bs('1101'), bs('0'), pclr, bs('0'), trlist13], [trlist13]) -armtop("pop", [bs('1110100'), bs('01'), bs('0'), bs('1'), bs('1'), bs('1101'), pc_in, lr_in, bs('0'), trlist13pclr], [trlist13pclr]) -armtop("mov", [bs('11110'), imm12_1, bs('00010'), scc, bs('1111'), bs('0'), imm12_3, rd_nosppc, imm12_8]) -armtop("asr", [bs('11111010'), bs('0100'), rm, bs('1111'), rd, bs('0000'), rs], [rd, rm, rs]) -armtop("lsl", [bs('11111010'), bs('0000'), rm, bs('1111'), rd, bs('0000'), rs], [rd, rm, rs]) -armtop("sel", [bs('11111010'), bs('1010'), rm, bs('1111'), rd, bs('1000'), rs], [rd, rm, rs]) -armtop("rev", [bs('11111010'), bs('1001'), rm, bs('1111'), rd, bs('1000'), rm_cp], [rd, rm]) -armtop("uadd8", [bs('111110101000'), rn, bs('1111'), rd, bs('0100'), rm], [rd, rn, rm]) -armtop("mvn", [bs('11101010011'), scc, bs('11110'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh] ) -armtop("and", [bs('11101010000'), scc, rn_nosppc, bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh], [rd_nosppc, rn_nosppc, rm_sh] ) -armtop("orr", [bs('11101010010'), scc, rn_nosppc, bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh], [rd_nosppc, rn_nosppc, rm_sh] ) -armtop("bic", [bs('11101010001'), scc, rn_nosppc, bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh], [rd_nosppc, rn_nosppc, rm_sh] ) -armtop("add", [bs('11101011000'), scc, rn_nosppc, bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh], [rd_nosppc, rn_nosppc, rm_sh] ) -armtop("sub", [bs('11101011101'), scc, rn_nosppc, bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh], [rd_nosppc, rn_nosppc, rm_sh] ) -armtop("eor", [bs('11101010100'), scc, rn_nosppc, bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh], [rd_nosppc, rn_nosppc, rm_sh] ) -armtop("rsb", [bs('11101011110'), scc, rn, bs('0'), imm5_3, rd, imm5_2, imm_stype, rm_sh], [rd, rn, rm_sh] ) -armtop("orn", [bs('11101010011'), scc, rn_nopc, bs('0'), imm5_3, rd, imm5_2, imm_stype, rm_sh], [rd, rn_nopc, rm_sh] ) -# lsl -armtop("mov", [bs('11101010010'), scc, bs('1111'), bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype_00, rm_sh], [rd_nosppc, rm_sh] ) -armtop("mov", [bs('11101010010'), scc, bs('1111'), bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype_01, rm_sh], [rd_nosppc, rm_sh] ) -armtop("mov", [bs('11101010010'), scc, bs('1111'), bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype_11, rm_sh], [rd_nosppc, rm_sh] ) - - -armtop("orr", [bs('11110'), imm12_1, bs('00010'), scc, rn_nosppc, bs('0'), imm12_3, rd, imm12_8] ) -armtop("add", [bs('11110'), imm12_1, bs('01000'), bs('0'), rn, bs('0'), imm12_3, rd_nopc, imm12_8], [rd_nopc, rn, imm12_8]) -armtop("adds",[bs('11110'), imm12_1, bs('01000'), bs('1'), rn, bs('0'), imm12_3, rd_nopc, imm12_8], [rd_nopc, rn, imm12_8]) -armtop("bic", [bs('11110'), imm12_1, bs('00001'), scc, rn_nosppc, bs('0'), imm12_3, rd, imm12_8], [rd, rn_nosppc, imm12_8]) -armtop("and", [bs('11110'), imm12_1, bs('00000'), scc, rn, bs('0'), imm12_3, rd_nopc, imm12_8], [rd_nopc, rn, imm12_8]) -armtop("sub", [bs('11110'), imm12_1, bs('01101'), scc, rn, bs('0'), imm12_3, rd_nopc, imm12_8], [rd_nopc, rn, imm12_8]) -armtop("eor", [bs('11110'), imm12_1, bs('00100'), scc, rn, bs('0'), imm12_3, rd_nopc, imm12_8], [rd_nopc, rn, imm12_8]) -armtop("add", [bs('11110'), imm12_1, bs('10000'), scc, rn_nosppc, bs('0'), imm12_3, rd, imm12_8_t4], [rd, rn_nosppc, imm12_8_t4]) -armtop("cmp", [bs('11110'), imm12_1, bs('01101'), bs('1'), rn, bs('0'), imm12_3, bs('1111'), imm12_8] ) - -armtop("cmp", [bs('11101011101'), bs('1'), rn, bs('0'), imm5_3, bs('1111'), imm5_2, imm_stype, rm_sh], [rn, rm_sh] ) - -armtop("cmn", [bs('11110'), imm12_1, bs('01000'), bs('1'), rn, bs('0'), imm12_3, bs('1111'), imm12_8], [rn, imm12_8]) - - -armtop("mvn", [bs('11110'), imm12_1, bs('00011'), scc, bs('1111'), bs('0'), imm12_3, rd, imm12_8]) -armtop("rsb", [bs('11110'), imm12_1, bs('01110'), scc, rn_nosppc, bs('0'), imm12_3, rd, imm12_8], [rd, rn_nosppc, imm12_8]) -armtop("sub", [bs('11110'), imm12_1, bs('101010'), rn_nosppc, bs('0'), imm12_3, rd, imm12_8_t4], [rd, rn_nosppc, imm12_8_t4]) -armtop("tst", [bs('11110'), imm12_1, bs('000001'), rn, bs('0'), imm12_3, bs('1111'), imm12_8], [rn, imm12_8]) - -armtop("mov", [bs('11110'), imm16_1, bs('100100'), imm16_4, bs('0'), imm16_3, rd, imm16_8] ) -armtop("movt", [bs('11110'), imm16_1, bs('101100'), imm16_4, bs('0'), imm16_3, rd, imm16_8] ) - -armtop("sdiv", [bs('111110111001'), rn, bs('1111'), rd, bs('1111'), rm], [rd, rn, rm] ) -armtop("udiv", [bs('111110111011'), rn, bs('1111'), rd, bs('1111'), rm], [rd, rn, rm] ) -armtop("mls", [bs('111110110000'), rn, ra, rd, bs('0001'), rm], [rd, rn, rm, ra] ) -armtop("mla", [bs('111110110000'), rn, ra_nopc, rd, bs('0000'), rm], [rd, rn, rm, ra_nopc] ) -armtop("mul", [bs('111110110000'), rn, bs('1111'), rd, bs('0000'), rm], [rd, rn, rm] ) - -armtop("smlabb", [bs('111110110001'), rn, ra_nopc, rd, bs('00'), bs('00'), rm], [rd, rn, rm, ra_nopc]) -armtop("smlabt", [bs('111110110001'), rn, ra_nopc, rd, bs('00'), bs('01'), rm], [rd, rn, rm, ra_nopc]) -armtop("smlatb", [bs('111110110001'), rn, ra_nopc, rd, bs('00'), bs('10'), rm], [rd, rn, rm, ra_nopc]) -armtop("smlatt", [bs('111110110001'), rn, ra_nopc, rd, bs('00'), bs('11'), rm], [rd, rn, rm, ra_nopc]) - -armtop("b", [bs('11110'), tsign, bm_cond_barmt, timm6h, bs('10'), tj1, bs('0'), tj2, timm6h11l], [timm6h11l]) -armtop("b", [bs('11110'), tsign, timm10H, bs('10'), tj1, bs('1'), tj2, timm11L], [timm11L]) - -armtop("ubfx", [bs('111100111100'), rn, bs('0'), lsb5_3, rd, lsb5_2, bs('0'), widthm1], [rd, rn, lsb5_2, widthm1]) -armtop("uxth", [bs('111110100001'), bs('1111'), bs('1111'), rd, bs('10'), rot2, rm_rot2], [rd, rm_rot2]) - - - -armtop("str", [bs('111110001100'), rn_deref, rt, off12], [rt, rn_deref]) -armtop("str", [bs('111110000100'), rn_noarg, rt, bs('000000'), imm2_noarg, rm_deref_reg], [rt, rm_deref_reg]) -armtop("str", [bs('111110000100'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) -armtop("strb", [bs('111110001000'), rn_deref, rt, off12], [rt, rn_deref]) -armtop("strb", [bs('111110000000'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) -armtop("strh", [bs('111110001010'), rn_deref, rt, off12], [rt, rn_deref]) -armtop("strh", [bs('111110000010'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) - -armtop("strd", [bs('1110100'), ppi, updown, bs('1'), wback_no_t, bs('0'), rn_nopc_noarg, rt, rt2, deref_immpuw00], [rt, rt2, deref_immpuw00]) -armtop("ldrd", [bs('1110100'), ppi, updown, bs('1'), wback_no_t, bs('1'), rn_nopc_noarg, rt, rt2, deref_immpuw00], [rt, rt2, deref_immpuw00]) - - -armtop("ldr", [bs('111110001101'), rn_deref, rt, off12], [rt, rn_deref]) -armtop("ldr", [bs('111110000101'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) -armtop("ldr", [bs('111110000101'), rn_noarg, rt, bs('000000'), imm2_noarg, rm_deref_reg], [rt, rm_deref_reg]) -armtop("ldrb", [bs('111110000001'), rn_noarg, rt, bs('000000'), imm2_noarg, rm_deref_reg], [rt, rm_deref_reg]) -armtop("ldrb", [bs('111110000001'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) -armtop("ldrb", [bs('111110001001'), rn_deref, rt_nopc, off12], [rt_nopc, rn_deref]) -armtop("ldrsb",[bs('111110011001'), rn_deref, rt, off12], [rt, rn_deref]) -armtop("ldrsh",[bs('111110011011'), rn_deref, rt, off12], [rt, rn_deref]) -armtop("ldrh", [bs('111110001011'), rn_deref, rt, off12], [rt, rn_deref]) -armtop("ldrh", [bs('111110000011'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) - -armtop("pld", [bs('111110001001'), rn_deref, bs('1111'), off12], [rn_deref]) -armtop("pldw", [bs('111110001011'), rn_deref, bs('1111'), off12], [rn_deref]) - -armtop("clz", [bs('111110101011'), rm, bs('1111'), rd, bs('1000'), rm_cp], [rd, rm]) -armtop("tbb", [bs('111010001101'), rn_noarg, bs('11110000000'), bs('0'), bs_deref_reg_reg], [bs_deref_reg_reg]) -armtop("tbh", [bs('111010001101'), rn_noarg, bs('11110000000'), bs('1'), bs_deref_reg_reg_lsl_1], [bs_deref_reg_reg_lsl_1]) -armtop("dsb", [bs('111100111011'), bs('1111'), bs('1000'), bs('1111'), bs('0100'), barrier_option]) - -armtop("adr", [bs('11110'), imm12_1, bs('100000'), bs('1111'), bs('0'), imm12_3, rd, imm12_8_t4], [rd, imm12_8_t4]) |