diff options
Diffstat (limited to 'miasm2/arch/arm/arch.py')
| -rw-r--r-- | miasm2/arch/arm/arch.py | 1244 |
1 files changed, 1032 insertions, 212 deletions
diff --git a/miasm2/arch/arm/arch.py b/miasm2/arch/arm/arch.py index 39b4cb14..35574a84 100644 --- a/miasm2/arch/arm/arch.py +++ b/miasm2/arch/arm/arch.py @@ -8,6 +8,7 @@ from collections import defaultdict from miasm2.core.bin_stream import bin_stream import miasm2.arch.arm.regs as regs_module from miasm2.arch.arm.regs import * +from miasm2.core.asm_ast import AstInt, AstId, AstMem, AstOp # A1 encoding @@ -20,7 +21,7 @@ log.setLevel(logging.DEBUG) # arm regs ############## reg_dum = ExprId('DumReg', 32) -gen_reg('PC', globals()) +PC, _ = gen_reg('PC') # GP regs_str = ['R%d' % r for r in xrange(0x10)] @@ -40,6 +41,9 @@ gpregs_nosppc = reg_info(regs_str[:13] + [str(reg_dum), regs_str[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" @@ -81,15 +85,33 @@ conditional_branch = ["BEQ", "BNE", "BCS", "BCC", "BMI", "BPL", "BVS", 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 tok_reg_duo(s, l, t): - t = t[0] - i1 = gpregs.expr.index(t[0]) - i2 = gpregs.expr.index(t[1]) +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 xrange(i1, i2 + 1): - o.append(gpregs.expr[i]) + o.append(AstId(gpregs.expr[i])) return o LPARENTHESIS = Literal("(") @@ -103,14 +125,14 @@ CIRCUNFLEX = Literal("^") def check_bounds(left_bound, right_bound, value): if left_bound <= value and value <= right_bound: - return ExprInt(value, 32) + return AstInt(value) else: raise ValueError('shift operator immediate value out of bound') def check_values(values, value): if value in values: - return ExprInt(value, 32) + return AstInt(value) else: raise ValueError('shift operator immediate value out of bound') @@ -120,11 +142,11 @@ 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 reglistparse(s, l, t): - t = t[0] - if t[-1] == "^": - return ExprOp('sbit', ExprOp('reglist', *t[:-1])) - return ExprOp('reglist', *t) +def cb_reglistparse(tokens): + tokens = tokens[0] + if tokens[-1] == "^": + return AstOp('sbit', AstOp('reglist', *tokens[:-1])) + return AstOp('reglist', *tokens) allshifts = ['<<', '>>', 'a>>', '>>>', 'rrx'] @@ -136,15 +158,15 @@ shift2expr_dct = {'LSL': '<<', 'LSR': '>>', 'ASR': 'a>>', expr2shift_dct = dict([(x[1], x[0]) for x in shift2expr_dct.items()]) -def op_shift2expr(s, l, t): - return shift2expr_dct[t[0]] +def op_shift2expr(tokens): + return shift2expr_dct[tokens[0]] reg_duo = Group(gpregs.parser + MINUS + - gpregs.parser).setParseAction(tok_reg_duo) + 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(reglistparse) +gpreg_list.setParseAction(cb_reglistparse) LBRACK = Suppress("[") RBRACK = Suppress("]") @@ -166,111 +188,132 @@ gpreg_p = gpregs.parser psr_p = cpsr_regs.parser | spsr_regs.parser -def shift2expr(t): - if len(t) == 1: - return t[0] - elif len(t) == 2: - return ExprOp(t[1], t[0]) - elif len(t) == 3: - return ExprOp(t[1], t[0], t[2]) +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 -variable, operand, base_expr = gen_base_expr() +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 -int_or_expr = base_expr +rot2_expr = (gpregs.parser + Optional( + (ror_shifts_t + (int_8_16_24)) +)).setParseAction(cb_shift) -def ast_id2expr(t): - return mn_arm.regs.all_regs_ids_byname.get(t, t) +OP_LSL = Suppress("LSL") -def ast_int2expr(a): - return ExprInt(a, 32) +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 -my_var_parser = ParseAst(ast_id2expr, ast_int2expr) -base_expr.setParseAction(my_var_parser) +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) -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(shift2expr) -shift_off |= base_expr -rot2_expr = (gpregs.parser + Optional( +(gpregs.parser + Optional( (ror_shifts_t + (int_8_16_24)) -)).setParseAction(shift2expr) +)).setParseAction(cb_shift) -def deref2expr_nooff(s, l, t): - t = t[0] +reg_or_base = gpregs.parser | base_expr + +def deref2expr_nooff(tokens): + tokens = tokens[0] # XXX default - return ExprOp("preinc", t[0], ExprInt(0, 32)) + return ExprOp("preinc", tokens[0], ExprInt(0, 32)) -def deref2expr_pre(s, l, t): - t = t[0] - if len(t) == 1: - return ExprOp("preinc", t[0], ExprInt(0, 32)) - elif len(t) == 2: - return ExprOp("preinc", t[0], t[1]) +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(t) > 2') + raise NotImplementedError('len(tokens) > 2') -def deref2expr_pre_mem(s, l, t): - t = t[0] - if len(t) == 1: - return ExprMem(ExprOp("preinc", t[0], ExprInt(0, 32)), 32) - elif len(t) == 2: - return ExprMem(ExprOp("preinc", t[0], t[1]), 32) +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(t) > 2') + raise NotImplementedError('len(tokens) > 2') -def deref2expr_post(s, l, t): - t = t[0] - return ExprOp("postinc", t[0], t[1]) +def cb_deref_post(tokens): + tokens = tokens[0] + return AstOp("postinc", tokens[0], tokens[1]) -def deref_wb(s, l, t): - t = t[0] - if t[-1] == '!': - return ExprMem(ExprOp('wback', *t[:-1]), 32) - return ExprMem(t[0], 32) +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(deref2expr_pre) + COMMA + shift_off) + RBRACK).setParseAction(cb_deref_preinc) deref_post = Group(LBRACK + gpregs.parser + RBRACK + - COMMA + shift_off).setParseAction(deref2expr_post) + COMMA + shift_off).setParseAction(cb_deref_post) deref = Group((deref_post | deref_pre | deref_nooff) - + Optional('!')).setParseAction(deref_wb) + + Optional('!')).setParseAction(cb_deref_wb) -def parsegpreg_wb(s, l, t): - t = t[0] - if t[-1] == '!': - return ExprOp('wback', *t[:-1]) - return t[0] +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(parsegpreg_wb) +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)]) -# default_prio = 0x1337 +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) -bm_cond = bs_mod_name(l=4, fname='cond', mn_mod=cond_list) # cond_dct) def permut_args(order, args): @@ -457,7 +500,11 @@ class instruction_armt(instruction_arm): if self.name == 'BLX': ad = e.arg + (self.offset & 0xfffffffc) elif self.name == 'BL': - ad = e.arg + self.offset + self.l + ad = e.arg + self.offset + elif self.name.startswith('BP'): + ad = e.arg + self.offset + elif self.name.startswith('CB'): + ad = e.arg + self.offset + self.l + 2 else: ad = e.arg + self.offset l = symbol_pool.getby_offset_create(ad) @@ -468,7 +515,7 @@ class instruction_armt(instruction_arm): self.args[0] = s def breakflow(self): - if self.name in conditional_branch + unconditional_branch +["CBZ", "CBNZ"]: + 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 @@ -720,7 +767,31 @@ class mn_armt(cls_mn): return 32 -class arm_reg(reg_noarg, m_arg): +class arm_arg(m_arg): + def asm_ast_to_expr(self, arg, symbol_pool): + if isinstance(arg, AstId): + if isinstance(arg.name, ExprId): + return arg.name + if arg.name in gpregs.str: + return None + label = symbol_pool.getby_name_create(arg.name) + return ExprId(label, 32) + if isinstance(arg, AstOp): + args = [self.asm_ast_to_expr(tmp, symbol_pool) for tmp in arg.args] + if None in args: + return None + return ExprOp(arg.op, *args) + if isinstance(arg, AstInt): + return ExprInt(arg.value, 32) + if isinstance(arg, AstMem): + ptr = self.asm_ast_to_expr(arg.ptr, symbol_pool) + if ptr is None: + return None + return ExprMem(ptr, arg.size) + return None + + +class arm_reg(reg_noarg, arm_arg): pass @@ -760,7 +831,7 @@ class arm_reg_wb(arm_reg): return True -class arm_psr(m_arg): +class arm_psr(arm_arg): parser = psr_p def decode(self, v): @@ -796,7 +867,7 @@ class arm_preg(arm_reg): parser = reg_info.parser -class arm_imm(imm_noarg, m_arg): +class arm_imm(imm_noarg, arm_arg): parser = base_expr @@ -840,7 +911,7 @@ class arm_offs(arm_imm): return True -class arm_imm8_12(m_arg): +class arm_imm8_12(arm_arg): parser = deref def decode(self, v): @@ -896,8 +967,8 @@ class arm_imm8_12(m_arg): return True -class arm_imm_4_12(m_arg): - parser = base_expr +class arm_imm_4_12(arm_arg): + parser = reg_or_base def decode(self, v): v = v & self.lmask @@ -916,7 +987,7 @@ class arm_imm_4_12(m_arg): return True -class arm_imm_12_4(m_arg): +class arm_imm_12_4(arm_arg): parser = base_expr def decode(self, v): @@ -936,7 +1007,7 @@ class arm_imm_12_4(m_arg): return True -class arm_op2(m_arg): +class arm_op2(arm_arg): parser = shift_off def str_to_imm_rot_form(self, s, neg=False): @@ -1108,7 +1179,7 @@ class arm_op2imm(arm_imm8_12): # if len(v) <1: # raise ValueError('cannot parse', s) - self.parent.rn.fromstring(e.args[0]) + self.parent.rn.expr = e.args[0] if len(e.args) == 1: self.parent.immop.value = 0 self.value = 0 @@ -1169,7 +1240,7 @@ def reglist2str(rlist): return "{" + ", ".join(out) + '}' -class arm_rlist(m_arg): +class arm_rlist(arm_arg): parser = gpreg_list def encode(self): @@ -1272,6 +1343,18 @@ class bs_lnk(bs_mod_name): 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") @@ -1280,7 +1363,13 @@ 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,)) +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") @@ -1333,8 +1422,10 @@ 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") @@ -1356,7 +1447,7 @@ class mul_part_y(bs_mod_name): 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(m_arg): +class arm_immed(arm_arg): parser = deref def decode(self, v): @@ -1429,7 +1520,7 @@ immedL = bs(l=4, cls=(arm_immed, m_arg), fname='immedL') hb = bs(l=1) -class armt2_rot_rm(m_arg): +class armt2_rot_rm(arm_arg): parser = shift_off def decode(self, v): r = self.parent.rm.expr @@ -1450,7 +1541,7 @@ class armt2_rot_rm(m_arg): rot_rm = bs(l=2, cls=(armt2_rot_rm,), fname="rot_rm") -class arm_mem_rn_imm(m_arg): +class arm_mem_rn_imm(arm_arg): parser = deref def decode(self, v): value = self.parent.imm.value @@ -1550,25 +1641,16 @@ 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', '']) -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("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_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]) @@ -1576,40 +1658,27 @@ armop("smul", [bs('00010110'), rd, bs('0000'), rs, bs('1'), mul_y, mul_x, bs('0' # 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]) +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("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", [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("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]) @@ -1631,11 +1700,13 @@ class arm_widthm1(arm_imm, m_arg): if not isinstance(self.expr, ExprInt): return False v = int(self.expr) + -1 + if v > self.lmask: + return False self.value = v return True -class arm_rm_rot2(m_arg): +class arm_rm_rot2(arm_arg): parser = rot2_expr def decode(self, v): expr = gpregs.expr[v] @@ -1662,18 +1733,47 @@ class arm_rm_rot2(m_arg): self.parent.rot2.value = value / 8 return True -class arm_gpreg_nopc(arm_reg): +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") widthm1 = bs(l=5, cls=(arm_widthm1, m_arg)) lsb = bs(l=5, cls=(arm_imm, m_arg)) -rn_nopc = bs(l=4, cls=(arm_gpreg_nopc,), fname="rn") +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]) @@ -1693,18 +1793,23 @@ 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(deref2expr_pre_mem) + COMMA + shift_off) + RBRACK).setParseAction(cb_deref_pre_mem) deref_pc = Group(LBRACK + gpregs_pc.parser + Optional( - COMMA + shift_off) + RBRACK).setParseAction(deref2expr_pre_mem) + COMMA + shift_off) + RBRACK).setParseAction(cb_deref_pre_mem) deref_sp = Group(LBRACK + gpregs_sp.parser + COMMA + - shift_off + RBRACK).setParseAction(deref2expr_pre_mem) + shift_off + RBRACK).setParseAction(cb_deref_pre_mem) gpregs_l_wb = Group( - gpregs_l.parser + Optional('!')).setParseAction(parsegpreg_wb) + gpregs_l.parser + Optional('!')).setParseAction(cb_gpreb_wb) -class arm_offreg(m_arg): +gpregs_l_13 = reg_info(regs_str[:13], regs_expr[:13]) + + +class arm_offreg(arm_arg): parser = deref_pc def decodeval(self, v): @@ -1815,9 +1920,8 @@ class arm_off7(arm_imm): def encodeval(self, v): return v >> 2 - -class arm_deref(m_arg): - parser = deref_low +class arm_deref_reg_imm(arm_arg): + parser = deref_reg_imm def decode(self, v): v = v & self.lmask @@ -1827,6 +1931,7 @@ class arm_deref(m_arg): return True def encode(self): + self.parent.off.expr = None e = self.expr if not isinstance(e, ExprMem): return False @@ -1848,6 +1953,9 @@ class arm_deref(m_arg): return False return True +class arm_derefl(arm_deref_reg_imm): + parser = deref_low + class arm_offbw(imm_noarg): @@ -1867,6 +1975,26 @@ class arm_offbw(imm_noarg): log.debug('off must be aligned %r', v) return False v >>= 2 + if v > self.lmask: + return False + 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) + if v > self.lmask: + return False self.value = v return True @@ -1887,11 +2015,13 @@ class arm_offh(imm_noarg): log.debug('off must be aligned %r', v) return False v >>= 1 + if v > self.lmask: + return False self.value = v return True -class armt_rlist(m_arg): +class armt_rlist(arm_arg): parser = gpreg_list def encode(self): @@ -1916,6 +2046,102 @@ class armt_rlist(m_arg): 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 xrange(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 xrange(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): @@ -1936,6 +2162,8 @@ class armt_rlist_pclr(armt_rlist): v = 0 for r in rlist: v |= 1 << r + if v > self.lmask: + return False self.value = v return True @@ -2016,7 +2244,7 @@ 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_deref,), 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") @@ -2030,8 +2258,16 @@ 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') + +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,)) @@ -2040,6 +2276,9 @@ 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') @@ -2097,43 +2336,29 @@ 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("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("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("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("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('10'), rnl, bs('000')]) @@ -2141,6 +2366,7 @@ 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("uxtb", [bs('10110010'), bs('11'), rml, rdl], [rdl, rml]) armtop("uxth", [bs('10110010'), bs('10'), rml, rdl], [rdl, rml]) @@ -2149,18 +2375,25 @@ armtop("sxth", [bs('10110010'), bs('00'), rml, rdl], [rdl, rml]) # thumb2 ###################### # - # ARM Architecture Reference Manual Thumb-2 Supplement -armt_gpreg_shift_off = Group( - gpregs_nosppc.parser + allshifts_t_armt + base_expr -).setParseAction(shift2expr) +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): @@ -2171,6 +2404,8 @@ class armt_gpreg_rm_shift_off(arm_reg): 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) @@ -2185,11 +2420,15 @@ class armt_gpreg_rm_shift_off(arm_reg): def encode(self): e = self.expr if isinstance(e, ExprId): - self.value = gpregs_nosppc.index(e) + 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 @@ -2239,11 +2478,13 @@ class armt2_imm12(arm_imm): self.expr = ExprInt((v << 24) | (v << 16) | (v << 8) | v, 32) return True r = v >> 7 - v = v & 0xFF + 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 @@ -2265,8 +2506,8 @@ class armt2_imm12(arm_imm): # rol encoding for i in xrange(32): o = myrol32(v, i) - if 0 <= o < 0x100 and o & 0x80: - value = (i << 7) | o + if 0x80 <= o <= 0xFF: + value = (i << 7) | (o & 0x7F) break if value is None: log.debug('cannot encode imm12') @@ -2277,6 +2518,108 @@ class armt2_imm12(arm_imm): 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) + 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) + 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): @@ -2289,8 +2632,7 @@ class armt2_imm10l(arm_imm): i1, i2 = j1 ^ s ^ 1, j2 ^ s ^ 1 - v = (s << 24) | (i1 << 23) | ( - i2 << 22) | (imm10h << 12) | (imm10l << 2) + v = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10h << 12) | (imm10l << 2) v = sign_ext(v, 25, 32) self.expr = ExprInt(v, 32) return True @@ -2305,8 +2647,7 @@ class armt2_imm10l(arm_imm): v = (-v) & 0xffffffff if v > (1 << 26): return False - i1, i2, imm10h, imm10l = (v >> 23) & 1, ( - v >> 22) & 1, (v >> 12) & 0x3ff, (v >> 2) & 0x3ff + 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 @@ -2328,24 +2669,24 @@ class armt2_imm11l(arm_imm): i1, i2 = j1 ^ s ^ 1, j2 ^ s ^ 1 - v = (s << 24) | (i1 << 23) | ( - i2 << 22) | (imm10h << 12) | (imm11l << 1) + v = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10h << 12) | (imm11l << 1) v = sign_ext(v, 25, 32) - self.expr = ExprInt(v, 32) + self.expr = ExprInt(v + 4, 32) return True def encode(self): if not isinstance(self.expr, ExprInt): return False - v = self.expr.arg.arg + v = self.expr.arg.arg - 4 s = 0 if v & 0x80000000: s = 1 v = (-v) & 0xffffffff - if v > (1 << 26): + 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 + 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 @@ -2355,22 +2696,86 @@ class armt2_imm11l(arm_imm): 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 = self.expr.arg.arg - 4 + s = 0 + if v & 0x80000000: + s = 1 + v = (-v) & 0xffffffff + if v >= (1 << 22): + return False + 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_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 = sign_ext(((self.parent.imm1.value << 5) | v) << 1, 7, 32) + v = ((self.parent.imm1.value << 5) | v) << 1 self.expr = ExprInt(v, 32) return True @@ -2378,8 +2783,8 @@ class armt_imm5_1(arm_imm): if not isinstance(self.expr, ExprInt): return False v = self.expr.arg.arg - if v & 0x80000000: - v &= (1 << 7) - 1 + if v & 0x1: + return False self.parent.imm1.value = (v >> 6) & 1 self.value = (v >> 1) & 0x1f return True @@ -2389,7 +2794,7 @@ 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, m_arg): +class armt_aif(reg_noarg, arm_arg): reg_info = aif_reg parser = reg_info.parser @@ -2404,12 +2809,292 @@ class armt_aif(reg_noarg, m_arg): return ret return self.value != 0 - def fromstring(self, s, parser_result=None): - start, stop = super(armt_aif, self).fromstring(s, parser_result) + def fromstring(self, text, symbol_pool, parser_result=None): + start, stop = super(armt_aif, self).fromstring(text, symbol_pool, 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 xrange(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 xrange(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 xrange(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.arg + 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.arg + 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.arg + 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.arg + 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,)) @@ -2419,25 +3104,160 @@ 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,)) + -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')]) +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,)) + + +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] + if self.value > self.lmask: + log.debug("cannot encode field value %x %x", + self.value, self.lmask) + return False + return True + + def check_fbits(self, v): + return v & self.fmask == self.fbits + +barrier_option = bs(l=4, cls=(armt_barrier_option,)) + +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_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'), scc, rn, bs('0'), imm12_3, rd, imm12_8], [rd, 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("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("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]) |