about summary refs log tree commit diff stats
path: root/miasm2/arch/arm/arch.py
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/arch/arm/arch.py')
-rw-r--r--miasm2/arch/arm/arch.py1244
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])