about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--README.md47
-rw-r--r--example/expression/get_read_write.py11
-rw-r--r--example/ida/graph_ir.py4
-rw-r--r--example/ida/utils.py2
-rw-r--r--miasm2/analysis/machine.py5
-rw-r--r--miasm2/analysis/sandbox.py70
-rw-r--r--miasm2/arch/aarch64/regs.py32
-rw-r--r--miasm2/arch/aarch64/sem.py25
-rw-r--r--miasm2/arch/arm/arch.py1044
-rw-r--r--miasm2/arch/arm/ira.py4
-rw-r--r--miasm2/arch/arm/jit.py58
-rw-r--r--miasm2/arch/arm/regs.py19
-rw-r--r--miasm2/arch/arm/sem.py628
-rw-r--r--miasm2/arch/x86/arch.py6
-rw-r--r--miasm2/core/cpu.py28
-rw-r--r--miasm2/ir/ir.py23
-rw-r--r--miasm2/jitter/arch/JitCore_arm.c35
-rw-r--r--miasm2/jitter/arch/JitCore_arm.h13
-rw-r--r--miasm2/jitter/codegen.py2
-rw-r--r--miasm2/jitter/jitload.py3
-rw-r--r--miasm2/jitter/llvmconvert.py4
-rw-r--r--miasm2/os_dep/win_api_x86_32.py52
-rw-r--r--test/arch/arm/arch.py218
23 files changed, 2000 insertions, 333 deletions
diff --git a/README.md b/README.md
index 8b1c371e..51890054 100644
--- a/README.md
+++ b/README.md
@@ -108,8 +108,8 @@ Add instruction to the pool:
 
 Print current pool:
 ```
->>> for lbl, b in ira.blocs.items():
-...     print b
+>>> for lbl, irblock in ira.blocks.items():
+...     print irblock
 ...
 loc_0000000000000000:0x00000000
 
@@ -119,19 +119,19 @@ loc_0000000000000000:0x00000000
 ```
 Working with IR, for instance by getting side effects:
 ```
->>> from miasm2.expression.expression import get_rw
->>> for lbl, b in ira.blocs.items():
-...     for irs in b.irs:
-...         o_r, o_w = get_rw(irs)
-...         print 'read:   ', [str(x) for x in o_r]
-...         print 'written:', [str(x) for x in o_w]
-...         print
+>>> for lbl, irblock in ira.blocks.iteritems():
+...     for assignblk in irblock:
+...         rw = assignblk.get_rw()
+...         for dst, reads in rw.iteritems():
+...             print 'read:   ', [str(x) for x in reads]
+...             print 'written:', dst
+...             print
 ...
 read:    ['R8', 'R0']
-written: ['R2']
+written: R2
 
 read:    ['loc_0000000000000004:0x00000004']
-written: ['IRDst']
+written: IRDst
 ```
 
 Emulation
@@ -165,9 +165,9 @@ Disassembling the shellcode at address `0`:
 >>> from miasm2.analysis.machine import Machine
 >>> machine = Machine('x86_32')
 >>> mdis = machine.dis_engine(c.bin_stream)
->>> blocs = mdis.dis_multiblock(0)
->>> for b in blocs:
-...  print b
+>>> blocks = mdis.dis_multiblock(0)
+>>> for block in blocks:
+...  print block
 ...
 loc_0000000000000000:0x00000000
 LEA        ECX, DWORD PTR [ECX+0x4]
@@ -198,7 +198,8 @@ Initializing the Jit engine with a stack:
 Add the shellcode in an arbitrary memory location:
 ```
 >>> run_addr = 0x40000000
->>> myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, s)
+>>> from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
+>>> jitter.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, s)
 ```
 
 Create a sentinelle to catch the return of the shellcode:
@@ -268,22 +269,22 @@ Initializing the IR pool:
 
 ```
 >>> ira = machine.ira()
->>> for b in blocs:
-...    ira.add_bloc(b)
+>>> for block in blocks:
+...    ira.add_block(block)
 ...
 ```
 
 Initializing the engine with default symbolic values:
 
 ```
->>> from miasm2.ir.symbexec import symbexec
->>> sb = symbexec(ira, machine.mn.regs.regs_init)
+>>> from miasm2.ir.symbexec import SymbolicExecutionEngine
+>>> sb = SymbolicExecutionEngine(ira, machine.mn.regs.regs_init)
 ```
 
 Launching the execution:
 
 ```
->>> symbolic_pc = sb.emul_ir_blocs(ira, 0)
+>>> symbolic_pc = sb.run_at(0)
 >>> print symbolic_pc
 ((ECX_init+0x4)[0:8]+0xFF)?(0xB,0x10)
 ```
@@ -291,8 +292,8 @@ Launching the execution:
 Same, with step logs (only changes are displayed):
 
 ```
->>> sb = symbexec(ira, machine.mn.regs.regs_init)
->>> symbolic_pc = sb.emul_ir_blocs(ira, 0, step=True)
+>>> sb = SymbolicExecutionEngine(ira, machine.mn.regs.regs_init)
+>>> symbolic_pc = sb.run_at(0, step=True)
 ________________________________________________________________________________
 ECX (ECX_init+0x4)
 ________________________________________________________________________________
@@ -326,7 +327,7 @@ Retry execution with a concrete ECX. Here, the symbolic / concolic execution rea
 ```
 >>> from miasm2.expression.expression import ExprInt32
 >>> sb.symbols[machine.mn.regs.ECX] = ExprInt32(-3)
->>> symbolic_pc = sb.emul_ir_blocs(ira, 0, step=True)
+>>> symbolic_pc = sb.run_at(0, step=True)
 ________________________________________________________________________________
 ECX 0x1
 ________________________________________________________________________________
diff --git a/example/expression/get_read_write.py b/example/expression/get_read_write.py
index b4a0773b..d107cfa2 100644
--- a/example/expression/get_read_write.py
+++ b/example/expression/get_read_write.py
@@ -16,12 +16,13 @@ l.offset, l.l = 0, 15
 ir_arch.add_instr(l)
 
 print '*' * 80
-for lbl, irblock in ir_arch.blocks.items():
+for lbl, irblock in ir_arch.blocks.iteritems():
     print irblock
     for assignblk in irblock:
-        o_r, o_w = get_rw(assignblk)
-        print 'read:   ', [str(x) for x in o_r]
-        print 'written:', [str(x) for x in o_w]
-        print
+        rw = assignblk.get_rw()
+        for dst, reads in rw.iteritems():
+            print 'read:   ', [str(x) for x in reads]
+            print 'written:', dst
+            print
 
 open('graph_instr.dot', 'w').write(ir_arch.graph.dot())
diff --git a/example/ida/graph_ir.py b/example/ida/graph_ir.py
index 7e303aac..6dfa1f7d 100644
--- a/example/ida/graph_ir.py
+++ b/example/ida/graph_ir.py
@@ -121,6 +121,10 @@ def build_graph(verbose=False, simplify=False):
         # print hex(ad), repr(name)
         if name is None:
             continue
+        if (mdis.symbol_pool.getby_offset(addr) or
+            mdis.symbol_pool.getby_name(name)):
+            # Symbol alias
+            continue
         mdis.symbol_pool.add_label(name, addr)
 
     if verbose:
diff --git a/example/ida/utils.py b/example/ida/utils.py
index 585d86a9..e026f2fc 100644
--- a/example/ida/utils.py
+++ b/example/ida/utils.py
@@ -40,7 +40,7 @@ def guess_machine():
                         (False, 64, False): "aarch64l",
                         }
         is_armt = globals().get('armt', False)
-        is_bigendian = globals().get('bigendian', False)
+        is_bigendian = info.is_be()
         infos = (is_armt, size, is_bigendian)
         if not infos in info2machine:
             raise NotImplementedError('not fully functional')
diff --git a/miasm2/analysis/machine.py b/miasm2/analysis/machine.py
index f361b412..73b90aef 100644
--- a/miasm2/analysis/machine.py
+++ b/miasm2/analysis/machine.py
@@ -79,6 +79,11 @@ class Machine(object):
             mn = arch.mn_armt
             from miasm2.arch.arm.ira import ir_a_armtl as ira
             from miasm2.arch.arm.sem import ir_armtl as ir
+            try:
+                from miasm2.arch.arm import jit
+                jitter = jit.jitter_armtl
+            except ImportError:
+                pass
         elif machine_name == "armtb":
             from miasm2.arch.arm.disasm import dis_armtb as dis_engine
             from miasm2.arch.arm import arch
diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py
index 8ffdb4ac..00865311 100644
--- a/miasm2/analysis/sandbox.py
+++ b/miasm2/analysis/sandbox.py
@@ -415,6 +415,20 @@ class Arch_armb(Arch):
         self.jitter.init_stack()
 
 
+class Arch_armtl(Arch):
+    _ARCH_ = "armtl"
+    STACK_SIZE = 0x100000
+    STACK_BASE = 0x100000
+
+    def __init__(self, **kwargs):
+        super(Arch_armtl, self).__init__(**kwargs)
+
+        # Init stack
+        self.jitter.stack_size = self.STACK_SIZE
+        self.jitter.stack_base = self.STACK_BASE
+        self.jitter.init_stack()
+
+
 class Arch_aarch64l(Arch):
     _ARCH_ = "aarch64l"
     STACK_SIZE = 0x100000
@@ -647,6 +661,9 @@ class Sandbox_Linux_arml(Sandbox, Arch_arml, OS_Linux):
                 self.jitter.vm.set_mem(ptr, arg)
                 argv_ptrs.append(ptr)
 
+            # Round SP to 4
+            self.jitter.cpu.SP = self.jitter.cpu.SP & ~ 3
+
             self.jitter.push_uint32_t(0)
             for ptr in reversed(env_ptrs):
                 self.jitter.push_uint32_t(ptr)
@@ -675,6 +692,59 @@ class Sandbox_Linux_arml(Sandbox, Arch_arml, OS_Linux):
         super(self.__class__, self).call(prepare_cb, addr, *args)
 
 
+class Sandbox_Linux_armtl(Sandbox, Arch_armtl, OS_Linux):
+
+    def __init__(self, *args, **kwargs):
+        Sandbox.__init__(self, *args, **kwargs)
+
+        # Pre-stack some arguments
+        if self.options.mimic_env:
+            env_ptrs = []
+            for env in self.envp:
+                env += "\x00"
+                self.jitter.cpu.SP -= len(env)
+                ptr = self.jitter.cpu.SP
+                self.jitter.vm.set_mem(ptr, env)
+                env_ptrs.append(ptr)
+            argv_ptrs = []
+            for arg in self.argv:
+                arg += "\x00"
+                self.jitter.cpu.SP -= len(arg)
+                ptr = self.jitter.cpu.SP
+                self.jitter.vm.set_mem(ptr, arg)
+                argv_ptrs.append(ptr)
+
+            # Round SP to 4
+            self.jitter.cpu.SP = self.jitter.cpu.SP & ~ 3
+
+            self.jitter.push_uint32_t(0)
+            for ptr in reversed(env_ptrs):
+                self.jitter.push_uint32_t(ptr)
+            self.jitter.push_uint32_t(0)
+            for ptr in reversed(argv_ptrs):
+                self.jitter.push_uint32_t(ptr)
+            self.jitter.push_uint32_t(len(self.argv))
+
+        self.jitter.cpu.LR = self.CALL_FINISH_ADDR
+
+        # Set the runtime guard
+        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle)
+
+    def run(self, addr=None):
+        if addr is None and self.options.address is None:
+            addr = self.entry_point
+        super(Sandbox_Linux_armtl, self).run(addr)
+
+    def call(self, addr, *args, **kwargs):
+        """
+        Direct call of the function at @addr, with arguments @args
+        @addr: address of the target function
+        @args: arguments
+        """
+        prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv)
+        super(self.__class__, self).call(prepare_cb, addr, *args)
+
+
 class Sandbox_Linux_armb_str(Sandbox, Arch_armb, OS_Linux_str):
 
     def __init__(self, *args, **kwargs):
diff --git a/miasm2/arch/aarch64/regs.py b/miasm2/arch/aarch64/regs.py
index f2655ea7..bf1c5cef 100644
--- a/miasm2/arch/aarch64/regs.py
+++ b/miasm2/arch/aarch64/regs.py
@@ -45,9 +45,13 @@ simd128_expr, simd128_init, simd128_info = gen_regs(
     simd128_str, globals(), 128)
 
 
-PC, PC_init = gen_reg("PC", globals(), 64)
-WZR, WZR_init = gen_reg("WZR", globals(), 32)
-XZR, XZR_init = gen_reg("XZR", globals(), 64)
+gen_reg("PC", globals(), 64)
+gen_reg("WZR", globals(), 32)
+gen_reg("XZR", globals(), 64)
+
+PC_init = ExprId("PC_init", 64)
+WZR_init = ExprId("WZR_init", 32)
+XZR_init = ExprId("XZR_init", 64)
 
 reg_zf = 'zf'
 reg_nf = 'nf'
@@ -87,11 +91,12 @@ all_regs_ids = [
     X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16,
     X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, LR, SP,
 
-    exception_flags, interrupt_num,
+    exception_flags,
+    interrupt_num,
     PC,
     WZR,
+    XZR,
     zf, nf, of, cf,
-    XZR
 
 ]
 
@@ -105,22 +110,7 @@ attrib_to_regs = {
 
 all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids])
 
-all_regs_ids_init = (simd08_init +
-                     simd16_init +
-                     simd32_init +
-                     simd64_init +
-                     simd128_init +
-                     gpregs32_init +
-                     gpregs64_init +
-                     [
-                         ExprInt(0, 32),
-                         PC_init,
-                         WZR_init,
-                         XZR_init,
-                         zf_init, nf_init, of_init, cf_init,
-                         ExprInt(0, 64), ExprInt(0, 32),
-                     ]
-                     )
+all_regs_ids_init = [ExprId("%s_init" % x.name, x.size) for x in all_regs_ids]
 
 regs_init = {}
 for i, r in enumerate(all_regs_ids):
diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py
index 2799df7a..88b0d0a7 100644
--- a/miasm2/arch/aarch64/sem.py
+++ b/miasm2/arch/aarch64/sem.py
@@ -124,9 +124,32 @@ def extend_arg(dst, arg):
         return arg
 
     op, (reg, shift) = arg.op, arg.args
-    if op == 'SXTW':
+    if op == "SXTB":
+        base = reg[:8].signExtend(dst.size)
+        op = "<<"
+    elif op == "SXTH":
+        base = reg[:16].signExtend(dst.size)
+        op = "<<"
+    elif op == 'SXTW':
+        base = reg[:32].signExtend(dst.size)
+        op = "<<"
+    elif op == "SXTX":
         base = reg.signExtend(dst.size)
         op = "<<"
+
+    elif op == "UXTB":
+        base = reg[:8].zeroExtend(dst.size)
+        op = "<<"
+    elif op == "UXTH":
+        base = reg[:16].zeroExtend(dst.size)
+        op = "<<"
+    elif op == 'UXTW':
+        base = reg[:32].zeroExtend(dst.size)
+        op = "<<"
+    elif op == "UXTX":
+        base = reg.zeroExtend(dst.size)
+        op = "<<"
+
     elif op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>']:
         base = reg.zeroExtend(dst.size)
     else:
diff --git a/miasm2/arch/arm/arch.py b/miasm2/arch/arm/arch.py
index 39b4cb14..f4ea36a6 100644
--- a/miasm2/arch/arm/arch.py
+++ b/miasm2/arch/arm/arch.py
@@ -40,6 +40,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,6 +84,24 @@ 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):
@@ -168,11 +189,14 @@ psr_p = cpsr_regs.parser | spsr_regs.parser
 
 def shift2expr(t):
     if len(t) == 1:
-        return t[0]
+        ret = t[0]
     elif len(t) == 2:
-        return ExprOp(t[1], t[0])
+        ret = ExprOp(t[1], t[0])
     elif len(t) == 3:
-        return ExprOp(t[1], t[0], t[2])
+        ret = ExprOp(t[1], t[0], t[2])
+    else:
+        raise ValueError("Bad arg")
+    return ret
 
 variable, operand, base_expr = gen_base_expr()
 
@@ -204,6 +228,33 @@ rot2_expr = (gpregs.parser + Optional(
 )).setParseAction(shift2expr)
 
 
+OP_LSL = Suppress("LSL")
+
+def expr_deref_reg_reg(t):
+    if len(t) != 2:
+        raise ValueError("Bad mem format")
+    return ExprMem(t[0] + t[1], 8)
+
+def expr_deref_reg_reg_lsl_1(t):
+    if len(t) != 3:
+        raise ValueError("Bad mem format")
+    reg1, reg2, index = t
+    if index != ExprInt(1, 32):
+        raise ValueError("Bad index")
+    ret = ExprMem(reg1 + (reg2 << index), 16)
+    return ret
+
+
+deref_reg_reg = (LBRACK + gpregs.parser + COMMA + gpregs.parser + RBRACK).setParseAction(expr_deref_reg_reg)
+deref_reg_reg_lsl_1 = (LBRACK + gpregs.parser + COMMA + gpregs.parser + OP_LSL + base_expr + RBRACK).setParseAction(expr_deref_reg_reg_lsl_1)
+
+
+
+(gpregs.parser + Optional(
+    (ror_shifts_t + (int_8_16_24))
+)).setParseAction(shift2expr)
+
+
 
 def deref2expr_nooff(s, l, t):
     t = t[0]
@@ -262,15 +313,20 @@ def parsegpreg_wb(s, l, t):
 gpregs_wb = Group(gpregs.parser + Optional('!')).setParseAction(parsegpreg_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 +513,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 +528,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
@@ -1272,6 +1332,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 +1352,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 +1411,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")
@@ -1550,25 +1630,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 +1647,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,6 +1689,8 @@ 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
 
@@ -1662,18 +1722,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,m_arg), fname="rd")
+rn_nopc = bs(l=4, cls=(arm_gpreg_nopc,m_arg), fname="rn")
+ra_nopc = bs(l=4, cls=(arm_gpreg_nopc,m_arg), fname="ra")
+rt_nopc = bs(l=4, cls=(arm_gpreg_nopc,m_arg), fname="rt")
+
+rn_nosp = bs(l=4, cls=(arm_gpreg_nosp,m_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,6 +1782,8 @@ gpregs_h = reg_info(regs_str[8:], regs_expr[8:])
 gpregs_sppc = reg_info(regs_str[-1:] + regs_str[13:14],
                        regs_expr[-1:] + regs_expr[13:14])
 
+deref_reg_imm = Group(LBRACK + gpregs.parser + Optional(
+    COMMA + shift_off) + RBRACK).setParseAction(deref2expr_pre_mem)
 deref_low = Group(LBRACK + gpregs_l.parser + Optional(
     COMMA + shift_off) + RBRACK).setParseAction(deref2expr_pre_mem)
 deref_pc = Group(LBRACK + gpregs_pc.parser + Optional(
@@ -1704,6 +1795,9 @@ gpregs_l_wb = Group(
     gpregs_l.parser + Optional('!')).setParseAction(parsegpreg_wb)
 
 
+gpregs_l_13 = reg_info(regs_str[:13], regs_expr[:13])
+
+
 class arm_offreg(m_arg):
     parser = deref_pc
 
@@ -1815,9 +1909,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(m_arg):
+    parser = deref_reg_imm
 
     def decode(self, v):
         v = v & self.lmask
@@ -1827,6 +1920,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 +1942,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 +1964,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,6 +2004,8 @@ 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
 
@@ -1916,6 +2035,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 +2151,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 +2233,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 +2247,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 +2265,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 +2325,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 +2355,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 +2364,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(shift2expr)
+
+
 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 +2393,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 +2409,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 +2467,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 +2495,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 +2507,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 +2621,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 +2636,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 +2658,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
-        i1, i2, imm10h, imm11l = (v >> 23) & 1, (
-            v >> 22) & 1, (v >> 12) & 0x3ff, (v >> 1) & 0x7ff
+        if v & 1:
+            return False
+        i1, i2, imm10h, imm11l = (v >> 23) & 1, (v >> 22) & 1, (v >> 12) & 0x3ff, (v >> 1) & 0x7ff
         j1, j2 = i1 ^ s ^ 1, i2 ^ s ^ 1
         self.parent.sign.value = s
         self.parent.j1.value = j1
@@ -2355,22 +2685,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 +2772,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
@@ -2410,6 +2804,285 @@ class armt_aif(reg_noarg, m_arg):
             return None, None
         return start, stop
 
+
+class armt_it_arg(m_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(m_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.fromstring(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(m_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 +3092,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, m_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])
diff --git a/miasm2/arch/arm/ira.py b/miasm2/arch/arm/ira.py
index bfa9bad2..cfcb294c 100644
--- a/miasm2/arch/arm/ira.py
+++ b/miasm2/arch/arm/ira.py
@@ -47,11 +47,11 @@ class ir_a_armb(ir_a_armb_base, ir_a_arml):
 
 
 class ir_a_armtl(ir_armtl, ir_a_arml):
-    def __init__(self, symbol_pool):
+    def __init__(self, symbol_pool=None):
         ir_armtl.__init__(self, symbol_pool)
         self.ret_reg = self.arch.regs.R0
 
 class ir_a_armtb(ir_a_armtl, ir_armtb, ir_a_armb):
-    def __init__(self, symbol_pool):
+    def __init__(self, symbol_pool=None):
         ir_armtb.__init__(self, symbol_pool)
         self.ret_reg = self.arch.regs.R0
diff --git a/miasm2/arch/arm/jit.py b/miasm2/arch/arm/jit.py
index b07f2a38..1a37b7f1 100644
--- a/miasm2/arch/arm/jit.py
+++ b/miasm2/arch/arm/jit.py
@@ -3,7 +3,10 @@ import logging
 from miasm2.jitter.jitload import jitter, named_arguments
 from miasm2.core import asmblock
 from miasm2.core.utils import pck32, upck32
-from miasm2.arch.arm.sem import ir_armb, ir_arml
+from miasm2.arch.arm.sem import ir_armb, ir_arml, ir_armtl, ir_armtb, cond_dct_inv, tab_cond
+from miasm2.jitter.codegen import CGen
+from miasm2.expression.expression import ExprId, ExprAff, ExprCond
+from miasm2.ir.ir import IRBlock, AssignBlock
 
 log = logging.getLogger('jit_arm')
 hnd = logging.StreamHandler()
@@ -11,7 +14,49 @@ hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
 log.addHandler(hnd)
 log.setLevel(logging.CRITICAL)
 
+
+
+class arm_CGen(CGen):
+    def __init__(self, ir_arch):
+        self.ir_arch = ir_arch
+        self.PC = self.ir_arch.arch.regs.PC
+        self.init_arch_C()
+
+
+    def block2assignblks(self, block):
+        """
+        Return the list of irblocks for a native @block
+        @block: AsmBlock
+        """
+        irblocks_list = []
+        index = -1
+        while index + 1 < len(block.lines):
+            index += 1
+            instr = block.lines[index]
+
+            if instr.name.startswith("IT"):
+                assignments = []
+                label = self.ir_arch.get_instr_label(instr)
+                irblocks = []
+                index, irblocks = self.ir_arch.do_it_block(label, index, block, assignments, True)
+                irblocks_list += irblocks
+                continue
+
+
+            assignblk_head, assignblks_extra = self.ir_arch.instr2ir(instr)
+            # Keep result in ordered list as first element is the assignblk head
+            # The remainings order is not really important
+            irblock_head = self.assignblk_to_irbloc(instr, assignblk_head)
+            irblocks = [irblock_head] + assignblks_extra
+
+            for irblock in irblocks:
+                assert irblock.dst is not None
+            irblocks_list.append(irblocks)
+        return irblocks_list
+
+
 class jitter_arml(jitter):
+    C_Gen = arm_CGen
 
     def __init__(self, *args, **kwargs):
         sp = asmblock.AsmSymbolPool()
@@ -69,9 +114,20 @@ class jitter_arml(jitter):
         jitter.init_run(self, *args, **kwargs)
         self.cpu.PC = self.pc
 
+
 class jitter_armb(jitter_arml):
+    C_Gen = arm_CGen
 
     def __init__(self, *args, **kwargs):
         sp = asmblock.AsmSymbolPool()
         jitter.__init__(self, ir_armb(sp), *args, **kwargs)
         self.vm.set_big_endian()
+
+
+class jitter_armtl(jitter_arml):
+    C_Gen = arm_CGen
+
+    def __init__(self, *args, **kwargs):
+        sp = asmblock.AsmSymbolPool()
+        jitter.__init__(self, ir_armtl(sp), *args, **kwargs)
+        self.vm.set_little_endian()
diff --git a/miasm2/arch/arm/regs.py b/miasm2/arch/arm/regs.py
index 8587d7c2..dce4cb98 100644
--- a/miasm2/arch/arm/regs.py
+++ b/miasm2/arch/arm/regs.py
@@ -63,9 +63,27 @@ of_init = ExprId("of_init", size=1)
 cf_init = ExprId("cf_init", size=1)
 
 
+reg_ge0 = 'ge0'
+reg_ge1 = 'ge1'
+reg_ge2 = 'ge2'
+reg_ge3 = 'ge3'
+
+ge0 = ExprId(reg_ge0, size=1)
+ge1 = ExprId(reg_ge1, size=1)
+ge2 = ExprId(reg_ge2, size=1)
+ge3 = ExprId(reg_ge3, size=1)
+
+ge0_init = ExprId("ge0_init", size=1)
+ge1_init = ExprId("ge1_init", size=1)
+ge2_init = ExprId("ge2_init", size=1)
+ge3_init = ExprId("ge3_init", size=1)
+
+ge_regs = [ge0, ge1, ge2, ge3]
+
 all_regs_ids = [
     R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, SP, LR, PC,
     zf, nf, of, cf,
+    ge0, ge1, ge2, ge3,
     exception_flags, bp_num
 ]
 
@@ -83,6 +101,7 @@ all_regs_ids_init = [R0_init, R1_init, R2_init, R3_init,
                      R8_init, R9_init, R10_init, R11_init,
                      R12_init, SP_init, LR_init, PC_init,
                      zf_init, nf_init, of_init, cf_init,
+                     ge0_init, ge1_init, ge2_init, ge3_init,
                      ExprInt(0, 32), ExprInt(0, 32)
                      ]
 
diff --git a/miasm2/arch/arm/sem.py b/miasm2/arch/arm/sem.py
index 395eb1cb..9e4da3f6 100644
--- a/miasm2/arch/arm/sem.py
+++ b/miasm2/arch/arm/sem.py
@@ -3,6 +3,7 @@ from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock
 from miasm2.arch.arm.arch import mn_arm, mn_armt
 from miasm2.arch.arm.regs import *
 
+from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO
 
 # liris.cnrs.fr/~mmrissa/lib/exe/fetch.php?media=armv7-a-r-manual.pdf
 EXCEPT_SOFT_BP = (1 << 1)
@@ -114,7 +115,7 @@ def adc(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def add(ir, instr, a, b, c=None):
@@ -129,7 +130,7 @@ def add(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def l_and(ir, instr, a, b, c=None):
@@ -143,7 +144,7 @@ def l_and(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def sub(ir, instr, a, b, c=None):
@@ -155,7 +156,7 @@ def sub(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def subs(ir, instr, a, b, c=None):
@@ -169,7 +170,7 @@ def subs(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def eor(ir, instr, a, b, c=None):
@@ -181,7 +182,7 @@ def eor(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def eors(ir, instr, a, b, c=None):
@@ -194,7 +195,7 @@ def eors(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def rsb(ir, instr, a, b, c=None):
@@ -206,7 +207,7 @@ def rsb(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def rsbs(ir, instr, a, b, c=None):
@@ -220,7 +221,7 @@ def rsbs(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def sbc(ir, instr, a, b, c=None):
@@ -232,7 +233,7 @@ def sbc(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def sbcs(ir, instr, a, b, c=None):
@@ -246,7 +247,7 @@ def sbcs(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def rsc(ir, instr, a, b, c=None):
@@ -258,7 +259,7 @@ def rsc(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def rscs(ir, instr, a, b, c=None):
@@ -273,16 +274,14 @@ def rscs(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
-def tst(ir, instr, a, b, c=None):
+def tst(ir, instr, a, b):
     e = []
-    if c is None:
-        b, c = a, b
-    r = b & c
+    r = a & b
     e += update_flag_logic(r)
-    return e
+    return e, []
 
 
 def teq(ir, instr, a, b, c=None):
@@ -291,7 +290,7 @@ def teq(ir, instr, a, b, c=None):
         b, c = a, b
     r = b ^ c
     e += update_flag_logic(r)
-    return e
+    return e, []
 
 
 def l_cmp(ir, instr, a, b, c=None):
@@ -301,7 +300,7 @@ def l_cmp(ir, instr, a, b, c=None):
     r = b - c
     e += update_flag_arith(r)
     e += update_flag_sub(b, c, r)
-    return e
+    return e, []
 
 
 def cmn(ir, instr, a, b, c=None):
@@ -311,7 +310,7 @@ def cmn(ir, instr, a, b, c=None):
     r = b + c
     e += update_flag_arith(r)
     e += update_flag_add(b, c, r)
-    return e
+    return e, []
 
 
 def orr(ir, instr, a, b, c=None):
@@ -323,7 +322,19 @@ def orr(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
+
+
+def orn(ir, instr, a, b, c=None):
+    e = []
+    if c is None:
+        b, c = a, b
+    r = ~(b | c)
+    e.append(ExprAff(a, r))
+    dst = get_dst(a)
+    if dst is not None:
+        e.append(ExprAff(ir.IRDst, r))
+    return e, []
 
 
 def orrs(ir, instr, a, b, c=None):
@@ -336,7 +347,7 @@ def orrs(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def mov(ir, instr, a, b):
@@ -344,7 +355,7 @@ def mov(ir, instr, a, b):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, b))
-    return e
+    return e, []
 
 
 def movt(ir, instr, a, b):
@@ -353,7 +364,7 @@ def movt(ir, instr, a, b):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def movs(ir, instr, a, b):
@@ -364,7 +375,7 @@ def movs(ir, instr, a, b):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, b))
-    return e
+    return e, []
 
 
 def mvn(ir, instr, a, b):
@@ -373,7 +384,7 @@ def mvn(ir, instr, a, b):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def mvns(ir, instr, a, b):
@@ -385,7 +396,7 @@ def mvns(ir, instr, a, b):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def neg(ir, instr, a, b):
@@ -395,11 +406,10 @@ def neg(ir, instr, a, b):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 def negs(ir, instr, a, b):
-    e = subs(ir, instr, a, ExprInt(0, b.size), b)
-    return e
+    return subs(ir, instr, a, ExprInt(0, b.size), b)
 
 def bic(ir, instr, a, b, c=None):
     e = []
@@ -410,7 +420,7 @@ def bic(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def bics(ir, instr, a, b, c=None):
@@ -423,7 +433,70 @@ def bics(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
+
+
+def sdiv(ir, instr, a, b, c=None):
+    e = []
+    if c is None:
+        b, c = a, b
+
+    lbl_div = ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_except = ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_next = ExprId(ir.get_next_label(instr), ir.IRDst.size)
+
+    e.append(ExprAff(ir.IRDst, ExprCond(c, lbl_div, lbl_except)))
+
+    do_except = []
+    do_except.append(ExprAff(exception_flags, ExprInt(EXCEPT_DIV_BY_ZERO, exception_flags.size)))
+    do_except.append(ExprAff(ir.IRDst, lbl_next))
+    blk_except = IRBlock(lbl_except.name, [AssignBlock(do_except, instr)])
+
+
+
+    r = ExprOp("idiv", b, c)
+    do_div = []
+    do_div.append(ExprAff(a, r))
+    dst = get_dst(a)
+    if dst is not None:
+        do_div.append(ExprAff(ir.IRDst, r))
+
+    do_div.append(ExprAff(ir.IRDst, lbl_next))
+    blk_div = IRBlock(lbl_div.name, [AssignBlock(do_div, instr)])
+
+    return e, [blk_div, blk_except]
+
+
+def udiv(ir, instr, a, b, c=None):
+    e = []
+    if c is None:
+        b, c = a, b
+
+
+
+    lbl_div = ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_except = ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_next = ExprId(ir.get_next_label(instr), ir.IRDst.size)
+
+    e.append(ExprAff(ir.IRDst, ExprCond(c, lbl_div, lbl_except)))
+
+    do_except = []
+    do_except.append(ExprAff(exception_flags, ExprInt(EXCEPT_DIV_BY_ZERO, exception_flags.size)))
+    do_except.append(ExprAff(ir.IRDst, lbl_next))
+    blk_except = IRBlock(lbl_except.name, [AssignBlock(do_except, instr)])
+
+
+    r = ExprOp("udiv", b, c)
+    do_div = []
+    do_div.append(ExprAff(a, r))
+    dst = get_dst(a)
+    if dst is not None:
+        do_div.append(ExprAff(ir.IRDst, r))
+
+    do_div.append(ExprAff(ir.IRDst, lbl_next))
+    blk_div = IRBlock(lbl_div.name, [AssignBlock(do_div, instr)])
+
+    return e, [blk_div, blk_except]
 
 
 def mla(ir, instr, a, b, c, d):
@@ -433,7 +506,7 @@ def mla(ir, instr, a, b, c, d):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def mlas(ir, instr, a, b, c, d):
@@ -444,10 +517,20 @@ def mlas(ir, instr, a, b, c, d):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
+
+
+def mls(ir, instr, a, b, c, d):
+    e = []
+    r = d - (b * c)
+    e.append(ExprAff(a, r))
+    dst = get_dst(a)
+    if dst is not None:
+        e.append(ExprAff(ir.IRDst, r))
+    return e, []
 
 
-def mul(ir, instr, a, b, c = None):
+def mul(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
@@ -456,10 +539,10 @@ def mul(ir, instr, a, b, c = None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
-def muls(ir, instr, a, b, c = None):
+def muls(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
@@ -469,7 +552,7 @@ def muls(ir, instr, a, b, c = None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 def umull(ir, instr, a, b, c, d):
     e = []
@@ -477,7 +560,7 @@ def umull(ir, instr, a, b, c, d):
     e.append(ExprAff(a, r[0:32]))
     e.append(ExprAff(b, r[32:64]))
     # r15/IRDst not allowed as output
-    return e
+    return e, []
 
 def umlal(ir, instr, a, b, c, d):
     e = []
@@ -485,7 +568,7 @@ def umlal(ir, instr, a, b, c, d):
     e.append(ExprAff(a, r[0:32]))
     e.append(ExprAff(b, r[32:64]))
     # r15/IRDst not allowed as output
-    return e
+    return e, []
 
 def smull(ir, instr, a, b, c, d):
     e = []
@@ -493,7 +576,7 @@ def smull(ir, instr, a, b, c, d):
     e.append(ExprAff(a, r[0:32]))
     e.append(ExprAff(b, r[32:64]))
     # r15/IRDst not allowed as output
-    return e
+    return e, []
 
 def smlal(ir, instr, a, b, c, d):
     e = []
@@ -501,13 +584,13 @@ def smlal(ir, instr, a, b, c, d):
     e.append(ExprAff(a, r[0:32]))
     e.append(ExprAff(b, r[32:64]))
     # r15/IRDst not allowed as output
-    return e
+    return e, []
 
 def b(ir, instr, a):
     e = []
     e.append(ExprAff(PC, a))
     e.append(ExprAff(ir.IRDst, a))
-    return e
+    return e, []
 
 
 def bl(ir, instr, a):
@@ -516,14 +599,14 @@ def bl(ir, instr, a):
     e.append(ExprAff(PC, a))
     e.append(ExprAff(ir.IRDst, a))
     e.append(ExprAff(LR, l))
-    return e
+    return e, []
 
 
 def bx(ir, instr, a):
     e = []
     e.append(ExprAff(PC, a))
     e.append(ExprAff(ir.IRDst, a))
-    return e
+    return e, []
 
 
 def blx(ir, instr, a):
@@ -532,10 +615,10 @@ def blx(ir, instr, a):
     e.append(ExprAff(PC, a))
     e.append(ExprAff(ir.IRDst, a))
     e.append(ExprAff(LR, l))
-    return e
+    return e, []
 
 
-def st_ld_r(ir, instr, a, b, store=False, size=32, s_ext=False, z_ext=False):
+def st_ld_r(ir, instr, a, a2, b, store=False, size=32, s_ext=False, z_ext=False):
     e = []
     wb = False
     b = b.copy()
@@ -558,6 +641,9 @@ def st_ld_r(ir, instr, a, b, store=False, size=32, s_ext=False, z_ext=False):
     else:
         ad = base + off
 
+    # PC base lookup uses PC 4 byte alignemnt
+    ad = ad.replace_expr({PC: PC & ExprInt(0xFFFFFFFC, 32)})
+
     dmem = False
     if size in [8, 16]:
         if store:
@@ -573,9 +659,9 @@ def st_ld_r(ir, instr, a, b, store=False, size=32, s_ext=False, z_ext=False):
         m = ExprMem(ad, size=size)
         pass
     elif size == 64:
+        assert a2 is not None
         m = ExprMem(ad, size=32)
         dmem = True
-        a2 = ir.arch.regs.all_regs_ids[ir.arch.regs.all_regs_ids.index(a) + 1]
         size = 32
     else:
         raise ValueError('the size DOES matter')
@@ -596,55 +682,53 @@ def st_ld_r(ir, instr, a, b, store=False, size=32, s_ext=False, z_ext=False):
     # XXX TODO check multiple write cause by wb
     if wb or postinc:
         e.append(ExprAff(base, base + off))
-    return e
+    return e, []
 
 
 def ldr(ir, instr, a, b):
-    return st_ld_r(ir, instr, a, b, store=False)
+    return st_ld_r(ir, instr, a, None, b, store=False)
 
 
-def ldrd(ir, instr, a, b):
-    e = st_ld_r(ir, instr, a, b, store=False, size=64)
-    return e
+def ldrd(ir, instr, a, b, c=None):
+    if c is None:
+        a2 = ir.arch.regs.all_regs_ids[ir.arch.regs.all_regs_ids.index(a) + 1]
+    else:
+        a2 = b
+        b = c
+    return st_ld_r(ir, instr, a, a2, b, store=False, size=64)
 
 
 def l_str(ir, instr, a, b):
-    return st_ld_r(ir, instr, a, b, store=True)
+    return st_ld_r(ir, instr, a, None, b, store=True)
 
 
-def l_strd(ir, instr, a, b):
-    e = st_ld_r(ir, instr, a, b, store=True, size=64)
-    return e
-
+def l_strd(ir, instr, a, b, c=None):
+    if c is None:
+        a2 = ir.arch.regs.all_regs_ids[ir.arch.regs.all_regs_ids.index(a) + 1]
+    else:
+        a2 = b
+        b = c
+    return st_ld_r(ir, instr, a, a2, b, store=True, size=64)
 
 def ldrb(ir, instr, a, b):
-    e = st_ld_r(ir, instr, a, b, store=False, size=8, z_ext=True)
-    return e
+    return st_ld_r(ir, instr, a, None, b, store=False, size=8, z_ext=True)
 
 def ldrsb(ir, instr, a, b):
-    e = st_ld_r(
-        ir, instr, a, b, store=False, size=8, s_ext=True, z_ext=False)
-    return e
+    return st_ld_r(ir, instr, a, None, b, store=False, size=8, s_ext=True, z_ext=False)
 
 def strb(ir, instr, a, b):
-    e = st_ld_r(ir, instr, a, b, store=True, size=8)
-    return e
-
+    return st_ld_r(ir, instr, a, None, b, store=True, size=8)
 
 def ldrh(ir, instr, a, b):
-    e = st_ld_r(ir, instr, a, b, store=False, size=16, z_ext=True)
-    return e
+    return st_ld_r(ir, instr, a, None, b, store=False, size=16, z_ext=True)
 
 
 def strh(ir, instr, a, b):
-    e = st_ld_r(ir, instr, a, b, store=True, size=16, z_ext=True)
-    return e
+    return st_ld_r(ir, instr, a, None, b, store=True, size=16, z_ext=True)
 
 
 def ldrsh(ir, instr, a, b):
-    e = st_ld_r(
-        ir, instr, a, b, store=False, size=16, s_ext=True, z_ext=False)
-    return e
+    return st_ld_r(ir, instr, a, None, b, store=False, size=16, s_ext=True, z_ext=False)
 
 
 def st_ld_m(ir, instr, a, b, store=False, postinc=False, updown=False):
@@ -688,7 +772,7 @@ def st_ld_m(ir, instr, a, b, store=False, postinc=False, updown=False):
     else:
         assert(isinstance(b, ExprOp) and b.op == "reglist")
 
-    return e
+    return e, []
 
 
 def ldmia(ir, instr, a, b):
@@ -727,16 +811,16 @@ def svc(ir, instr, a):
     # XXX TODO implement
     e = [
         ExprAff(exception_flags, ExprInt(EXCEPT_PRIV_INSN, 32))]
-    return e
+    return e, []
 
 
 def und(ir, instr, a, b):
     # XXX TODO implement
     e = []
-    return e
+    return e, []
 
 # TODO XXX implement correct CF for shifters
-def lsr(ir, instr, a, b, c = None):
+def lsr(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
@@ -745,10 +829,10 @@ def lsr(ir, instr, a, b, c = None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
-def lsrs(ir, instr, a, b, c = None):
+def lsrs(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
@@ -758,7 +842,7 @@ def lsrs(ir, instr, a, b, c = None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 def asr(ir, instr, a, b, c=None):
     e = []
@@ -769,9 +853,9 @@ def asr(ir, instr, a, b, c=None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
-def asrs(ir, instr, a, b, c):
+def asrs(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
@@ -781,9 +865,9 @@ def asrs(ir, instr, a, b, c):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
-def lsl(ir, instr, a, b, c = None):
+def lsl(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
@@ -792,10 +876,10 @@ def lsl(ir, instr, a, b, c = None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
-def lsls(ir, instr, a, b, c = None):
+def lsls(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
@@ -805,18 +889,29 @@ def lsls(ir, instr, a, b, c = None):
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
+
+
+def rors(ir, instr, a, b):
+    e = []
+    r = ExprOp(">>>", a, b)
+    e.append(ExprAff(a, r))
+    e += update_flag_logic(r)
+    dst = get_dst(a)
+    if dst is not None:
+        e.append(ExprAff(ir.IRDst, r))
+    return e, []
 
 
 def push(ir, instr, a):
     e = []
     regs = list(a.args)
     for i in xrange(len(regs)):
-        r = SP + ExprInt(-4 * (i + 1), 32)
+        r = SP + ExprInt(-4 * len(regs) + 4 * i, 32)
         e.append(ExprAff(ExprMem(r, 32), regs[i]))
     r = SP + ExprInt(-4 * len(regs), 32)
     e.append(ExprAff(SP, r))
-    return e
+    return e, []
 
 
 def pop(ir, instr, a):
@@ -832,21 +927,21 @@ def pop(ir, instr, a):
     e.append(ExprAff(SP, r))
     if dst is not None:
         e.append(ExprAff(ir.IRDst, dst))
-    return e
+    return e, []
 
 
 def cbz(ir, instr, a, b):
     e = []
     lbl_next = ExprId(ir.get_next_label(instr), 32)
     e.append(ExprAff(ir.IRDst, ExprCond(a, lbl_next, b)))
-    return e
+    return e, []
 
 
 def cbnz(ir, instr, a, b):
     e = []
     lbl_next = ExprId(ir.get_next_label(instr), 32)
-    e.append(ir.IRDst, ExprCond(a, b, lbl_next))
-    return e
+    e.append(ExprAff(ir.IRDst, ExprCond(a, b, lbl_next)))
+    return e, []
 
 
 
@@ -858,7 +953,7 @@ def uxtb(ir, instr, a, b):
     if PC in a.get_r():
         dst = PC
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 def uxth(ir, instr, a, b):
     e = []
@@ -868,7 +963,7 @@ def uxth(ir, instr, a, b):
     if PC in a.get_r():
         dst = PC
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 def sxtb(ir, instr, a, b):
     e = []
@@ -878,7 +973,7 @@ def sxtb(ir, instr, a, b):
     if PC in a.get_r():
         dst = PC
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 def sxth(ir, instr, a, b):
     e = []
@@ -888,7 +983,7 @@ def sxth(ir, instr, a, b):
     if PC in a.get_r():
         dst = PC
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 
 def ubfx(ir, instr, a, b, c, d):
@@ -901,7 +996,7 @@ def ubfx(ir, instr, a, b, c, d):
     if PC in a.get_r():
         dst = PC
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 def bfc(ir, instr, a, b, c):
     e = []
@@ -923,34 +1018,41 @@ def bfc(ir, instr, a, b, c):
     if PC in a.get_r():
         dst = PC
         e.append(ExprAff(ir.IRDst, r))
-    return e
+    return e, []
 
 def rev(ir, instr, a, b):
     e = []
     c = ExprCompose(b[24:32], b[16:24], b[8:16], b[:8])
     e.append(ExprAff(a, c))
-    return e
+    return e, []
 
 def pld(ir, instr, a):
-    return []
+    e = []
+    return e, []
+
+
+def pldw(ir, instr, a):
+    e = []
+    return e, []
 
 
 def clz(ir, instr, a, b):
     e = []
     e.append(ExprAff(a, ExprOp('clz', b)))
-    return e
+    return e, []
 
 def uxtab(ir, instr, a, b, c):
     e = []
     e.append(ExprAff(a, b + (c & ExprInt(0xff, 32))))
-    return e
+    return e, []
 
 
 def bkpt(ir, instr, a):
     e = []
     e.append(ExprAff(exception_flags, ExprInt(EXCEPT_SOFT_BP, 32)))
     e.append(ExprAff(bp_num, a))
-    return e
+    return e, []
+
 
 def _extract_s16(arg, part):
     if part == 'B': # bottom 16 bits
@@ -958,12 +1060,131 @@ def _extract_s16(arg, part):
     elif part == 'T': # top 16 bits
         return arg[16:32]
 
+
 def smul(ir, instr, a, b, c):
-    return [ExprAff(a, _extract_s16(b, instr.name[4]).signExtend(32) * _extract_s16(c, instr.name[5]).signExtend(32))]
+    e = []
+    e.append(ExprAff(a, _extract_s16(b, instr.name[4]).signExtend(32) * _extract_s16(c, instr.name[5]).signExtend(32)))
+    return e, []
+
 
 def smulw(ir, instr, a, b, c):
+    e = []
     prod = b.signExtend(48) * _extract_s16(c, instr.name[5]).signExtend(48)
-    return [ExprAff(a, prod[16:48])] # signed most significant 32 bits of the 48-bit result
+    e.append(ExprAff(a, prod[16:48]))
+    return e, [] # signed most significant 32 bits of the 48-bit result
+
+
+def tbb(ir, instr, a):
+    e = []
+    dst = PC + ExprInt(2, 32) * a.zeroExtend(32)
+    e.append(ExprAff(PC, dst))
+    e.append(ExprAff(ir.IRDst, dst))
+    return e, []
+
+
+def tbh(ir, instr, a):
+    e = []
+    dst = PC + ExprInt(2, 32) * a.zeroExtend(32)
+    e.append(ExprAff(PC, dst))
+    e.append(ExprAff(ir.IRDst, dst))
+    return e, []
+
+
+def smlabb(ir, instr, a, b, c, d):
+    e = []
+    result = (b[:16].signExtend(32) * c[:16].signExtend(32)) + d
+    e.append(ExprAff(a, result))
+    return e, []
+
+
+def smlabt(ir, instr, a, b, c, d):
+    e = []
+    result = (b[:16].signExtend(32) * c[16:32].signExtend(32)) + d
+    e.append(ExprAff(a, result))
+    return e, []
+
+
+def smlatb(ir, instr, a, b, c, d):
+    e = []
+    result = (b[16:32].signExtend(32) * c[:16].signExtend(32)) + d
+    e.append(ExprAff(a, result))
+    return e, []
+
+
+def smlatt(ir, instr, a, b, c, d):
+    e = []
+    result = (b[16:32].signExtend(32) * c[16:32].signExtend(32)) + d
+    e.append(ExprAff(a, result))
+    return e, []
+
+
+def uadd8(ir, instr, a, b, c):
+    e = []
+    sums = []
+    ges = []
+    for i in xrange(0, 32, 8):
+        sums.append(b[i:i+8] + c[i:i+8])
+        ges.append((b[i:i+8].zeroExtend(9) + c[i:i+8].zeroExtend(9))[8:9])
+
+    e.append(ExprAff(a, ExprCompose(*sums)))
+
+    for i, value in enumerate(ges):
+        e.append(ExprAff(ge_regs[i], value))
+    return e, []
+
+
+def sel(ir, instr, a, b, c):
+    e = []
+    cond = nf ^ of ^ ExprInt(1, 1)
+    parts = []
+    for i in xrange(4):
+        parts.append(ExprCond(ge_regs[i], b[i*8:(i+1)*8], c[i*8:(i+1)*8]))
+    result = ExprCompose(*parts)
+    e.append(ExprAff(a, result))
+    return e, []
+
+
+def rev(ir, instr, a, b):
+    e = []
+    result = ExprCompose(b[24:32], b[16:24], b[8:16], b[:8])
+    e.append(ExprAff(a, result))
+    return e, []
+
+
+def nop(ir, instr):
+    e = []
+    return e, []
+
+
+def dsb(ir, instr, a):
+    # XXX TODO
+    e = []
+    return e, []
+
+
+def cpsie(ir, instr, a):
+    # XXX TODO
+    e = []
+    return e, []
+
+
+def cpsid(ir, instr, a):
+    # XXX TODO
+    e = []
+    return e, []
+
+
+def wfe(ir, instr):
+    # XXX TODO
+    e = []
+    return e, []
+
+
+def wfi(ir, instr):
+    # XXX TODO
+    e = []
+    return e, []
+
 
 COND_EQ = 0
 COND_NE = 1
@@ -1001,6 +1222,7 @@ cond_dct = {
     # COND_NV: "NV",
 }
 
+cond_dct_inv = dict((name, num) for num, name in cond_dct.iteritems())
 
 tab_cond = {COND_EQ: zf,
             COND_NE: ExprCond(zf, ExprInt(0, 1), ExprInt(1, 1)),
@@ -1035,9 +1257,9 @@ def is_pc_written(ir, instr_ir):
     return False, None
 
 
-def add_condition_expr(ir, instr, cond, instr_ir):
+def add_condition_expr(ir, instr, cond, instr_ir, extra_ir):
     if cond == COND_AL:
-        return instr_ir, []
+        return instr_ir, extra_ir
     if not cond in tab_cond:
         raise ValueError('unknown condition %r' % cond)
     cond = tab_cond[cond]
@@ -1057,7 +1279,7 @@ def add_condition_expr(ir, instr, cond, instr_ir):
         instr_ir.append(ExprAff(ir.IRDst, lbl_next))
     e_do = IRBlock(lbl_do.name, [AssignBlock(instr_ir, instr)])
     e = [ExprAff(ir.IRDst, dst_cond)]
-    return e, [e_do]
+    return e, [e_do] + extra_ir
 
 mnemo_func = {}
 mnemo_func_cond = {}
@@ -1081,6 +1303,9 @@ mnemo_condm0 = {'add': add,
                 'mvn': mvn,
                 'neg': neg,
 
+                'sdiv': sdiv,
+                'udiv': udiv,
+
                 'mul': mul,
                 'umull': umull,
                 'umlal': umlal,
@@ -1134,6 +1359,7 @@ mnemo_condm1 = {'adds': add,
                 'negs': negs,
 
                 'muls': muls,
+                'mls': mls,
                 'mlas': mlas,
                 'blx': blx,
 
@@ -1170,6 +1396,7 @@ mnemo_nocond = {'lsr': lsr,
                 'lsrs': lsrs,
                 'lsl': lsl,
                 'lsls': lsls,
+                'rors': rors,
                 'push': push,
                 'pop': pop,
                 'asr': asr,
@@ -1177,7 +1404,24 @@ mnemo_nocond = {'lsr': lsr,
                 'cbz': cbz,
                 'cbnz': cbnz,
                 'pld': pld,
+                'pldw': pldw,
+                'tbb': tbb,
+                'tbh': tbh,
+                'nop': nop,
+                'dsb': dsb,
+                'cpsie': cpsie,
+                'cpsid': cpsid,
+                'wfe': wfe,
+                'wfi': wfi,
+                'orn': orn,
+                'smlabb': smlabb,
+                'smlabt': smlabt,
+                'smlatb': smlatb,
+                'smlatt': smlatt,
+                'uadd8': uadd8,
+                'sel': sel,
                 }
+
 mn_cond_x = [mnemo_condm0,
              mnemo_condm1,
              mnemo_condm2]
@@ -1215,8 +1459,8 @@ def get_mnemo_expr(ir, instr, *args):
     if not instr.name.lower() in mnemo_func_cond:
         raise ValueError('unknown mnemo %s' % instr)
     cond, mf = mnemo_func_cond[instr.name.lower()]
-    instr_ir = mf(ir, instr, *args)
-    instr, extra_ir = add_condition_expr(ir, instr, cond, instr_ir)
+    instr_ir, extra_ir = mf(ir, instr, *args)
+    instr, extra_ir = add_condition_expr(ir, instr, cond, instr_ir, extra_ir)
     return instr, extra_ir
 
 get_arm_instr_expr = get_mnemo_expr
@@ -1235,6 +1479,24 @@ class ir_arml(IntermediateRepresentation):
         self.IRDst = ExprId('IRDst', 32)
         self.addrsize = 32
 
+
+
+    def mod_pc(self, instr, instr_ir, extra_ir):
+        # fix PC (+8 for arm)
+        pc_fixed = {self.pc: ExprInt(instr.offset + 8, 32)}
+
+        for i, expr in enumerate(instr_ir):
+            dst, src = expr.dst, expr.src
+            if dst != self.pc:
+                dst = dst.replace_expr(pc_fixed)
+            src = src.replace_expr(pc_fixed)
+            instr_ir[i] = ExprAff(dst, src)
+
+        for idx, irblock in enumerate(extra_ir):
+            extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \
+                                                 if expr != self.pc else expr,
+                                                 lambda expr: expr.replace_expr(pc_fixed))
+
     def get_ir(self, instr):
         args = instr.args
         # ir = get_mnemo_expr(self, self.name.lower(), *args)
@@ -1248,14 +1510,120 @@ class ir_arml(IntermediateRepresentation):
                                   args[-1].args[-1][:8].zeroExtend(32))
         instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
 
-        pc_fixed = {self.pc: ExprInt(instr.offset + 8, 32)}
-        for i, expr in enumerate(instr_ir):
-            instr_ir[i] = ExprAff(expr.dst, expr.src.replace_expr(pc_fixed))
-
-        new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(pc_fixed))
-                        for irblock in extra_ir]
+        self.mod_pc(instr, instr_ir, extra_ir)
+        return instr_ir, extra_ir
+
+    def parse_itt(self, instr):
+        name = instr.name
+        assert name.startswith('IT')
+        name = name[1:]
+        out = []
+        for hint in name:
+            if hint == 'T':
+                out.append(0)
+            elif hint == "E":
+                out.append(1)
+            else:
+                raise ValueError("IT name invalid %s" % instr)
+        return out, instr.args[0]
+
+    def do_it_block(self, label, index, block, assignments, gen_pc_updt):
+        instr = block.lines[index]
+        it_hints, it_cond = self.parse_itt(instr)
+        cond_num = cond_dct_inv[it_cond.name]
+        cond_eq = tab_cond[cond_num]
+
+        if not index + len(it_hints) <= len(block.lines):
+            raise NotImplementedError("Splitted IT block non supported yet")
+
+        ir_blocks_all = []
+
+        # Gen dummy irblock for IT instr
+        label_next = self.get_next_label(instr)
+        dst = ExprAff(self.IRDst, ExprId(label_next, 32))
+        dst_blk = AssignBlock([dst], instr)
+        assignments.append(dst_blk)
+        irblock = IRBlock(label, assignments)
+        ir_blocks_all.append([irblock])
+
+        label = label_next
+        assignments = []
+        for hint in it_hints:
+            irblocks = []
+            index += 1
+            instr = block.lines[index]
+
+            # Add conditionnal jump to current irblock
+            label_do = self.symbol_pool.gen_label()
+            label_next = self.get_next_label(instr)
+
+            if hint:
+                local_cond = ~cond_eq
+            else:
+                local_cond = cond_eq
+            dst = ExprAff(self.IRDst, ExprCond(local_cond, ExprId(label_do, 32), ExprId(label_next, 32)))
+            dst_blk = AssignBlock([dst], instr)
+            assignments.append(dst_blk)
+            irblock = IRBlock(label, assignments)
+
+            irblocks.append(irblock)
+
+            assignments = []
+            label = label_do
+            split = self.add_instr_to_irblock(block, instr, assignments,
+                                              irblocks, gen_pc_updt)
+            if split:
+                raise NotImplementedError("Unsupported instr in IT block (%s)" % instr)
+
+            dst = ExprAff(self.IRDst, ExprId(label_next, 32))
+            dst_blk = AssignBlock([dst], instr)
+            assignments.append(dst_blk)
+            irblock = IRBlock(label, assignments)
+            irblocks.append(irblock)
+            label = label_next
+            assignments = []
+            ir_blocks_all.append(irblocks)
+        return index, ir_blocks_all
+
+    def add_block(self, block, gen_pc_updt=False):
+        """
+        Add a native block to the current IR
+        @block: native assembly block
+        @gen_pc_updt: insert PC update effects between instructions
+        """
+
+        it_hints = None
+        it_cond = None
+        label = None
+        ir_blocks_all = []
+        index = -1
+        while index + 1 < len(block.lines):
+            index += 1
+            instr = block.lines[index]
+            if label is None:
+                assignments = []
+                label = self.get_instr_label(instr)
+            if instr.name.startswith("IT"):
+                index, irblocks_it = self.do_it_block(label, index, block, assignments, gen_pc_updt)
+                for irblocks in irblocks_it:
+                    ir_blocks_all += irblocks
+                label = None
+                continue
+
+            split = self.add_instr_to_irblock(block, instr, assignments,
+                                              ir_blocks_all, gen_pc_updt)
+            if split:
+                ir_blocks_all.append(IRBlock(label, assignments))
+                label = None
+                assignments = []
+        if label is not None:
+            ir_blocks_all.append(IRBlock(label, assignments))
+
+        new_ir_blocks_all = self.post_add_block(block, ir_blocks_all)
+        for irblock in new_ir_blocks_all:
+            self.blocks[irblock.label] = irblock
+        return new_ir_blocks_all
 
-        return instr_ir, new_extra_ir
 
 
 class ir_armb(ir_arml):
@@ -1266,7 +1634,8 @@ class ir_armb(ir_arml):
         self.IRDst = ExprId('IRDst', 32)
         self.addrsize = 32
 
-class ir_armtl(IntermediateRepresentation):
+
+class ir_armtl(ir_arml):
     def __init__(self, symbol_pool=None):
         IntermediateRepresentation.__init__(self, mn_armt, "l", symbol_pool)
         self.pc = PC
@@ -1274,8 +1643,23 @@ class ir_armtl(IntermediateRepresentation):
         self.IRDst = ExprId('IRDst', 32)
         self.addrsize = 32
 
-    def get_ir(self, instr):
-        return get_mnemo_expr(self, instr, *instr.args)
+
+    def mod_pc(self, instr, instr_ir, extra_ir):
+        # fix PC (+4 for thumb)
+        pc_fixed = {self.pc: ExprInt(instr.offset + 4, 32)}
+
+        for i, expr in enumerate(instr_ir):
+            dst, src = expr.dst, expr.src
+            if dst != self.pc:
+                dst = dst.replace_expr(pc_fixed)
+            src = src.replace_expr(pc_fixed)
+            instr_ir[i] = ExprAff(dst, src)
+
+        for idx, irblock in enumerate(extra_ir):
+            extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \
+                                                 if expr != self.pc else expr,
+                                                 lambda expr: expr.replace_expr(pc_fixed))
+
 
 class ir_armtb(ir_armtl):
     def __init__(self, symbol_pool=None):
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index 29303fdf..be3dbd94 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -1065,10 +1065,12 @@ class x86_imm_fix_08(imm_noarg):
     def decodeval(self, v):
         return self.ival
 
-    def encodeval(self, v):
+    def encode(self):
+        v = self.expr2int(self.expr)
         if v != self.ival:
             return False
-        return self.ival
+        self.value = 0
+        return True
 
 
 class x86_08(x86_imm):
diff --git a/miasm2/core/cpu.py b/miasm2/core/cpu.py
index aa94773f..57057a85 100644
--- a/miasm2/core/cpu.py
+++ b/miasm2/core/cpu.py
@@ -100,6 +100,24 @@ class reg_info:
         return self.expr.index(e)
 
 
+
+class reg_info_dct:
+
+    def __init__(self, reg_expr):
+        self.dct_str_inv = dict((v.name, k) for k, v in reg_expr.iteritems())
+        self.dct_expr = reg_expr
+        self.dct_expr_inv = dict((v, k) for k, v in reg_expr.iteritems())
+        reg_str = [v.name for v in reg_expr.itervalues()]
+        self.parser = literal_list(reg_str).setParseAction(self.reg2expr)
+
+    def reg2expr(self, s):
+        i = self.dct_str_inv[s[0]]
+        return self.dct_expr[i]
+
+    def expr2regi(self, e):
+        return self.dct_expr_inv[e]
+
+
 def gen_reg(rname, env, sz=32):
     """
     Gen reg expr and parser
@@ -431,13 +449,14 @@ class bs(object):
         self.cls = cls
         self.fname = fname
         self.order = order
-        self.lmask = lmask
         self.fbits = fbits
         self.fmask = fmask
         self.flen = flen
         self.value = value
         self.kargs = kargs
 
+    lmask = property(lambda self:(1 << self.l) - 1)
+
     def __getitem__(self, item):
         return getattr(self, item)
 
@@ -502,7 +521,6 @@ class bsi(object):
         self.cls = cls
         self.fname = fname
         self.order = order
-        self.lmask = lmask
         self.fbits = fbits
         self.fmask = fmask
         self.flen = flen
@@ -510,6 +528,8 @@ class bsi(object):
         self.kargs = kargs
         self.__dict__.update(self.kargs)
 
+    lmask = property(lambda self:(1 << self.l) - 1)
+
     def decode(self, v):
         self.value = v & self.lmask
         return True
@@ -1393,7 +1413,9 @@ class cls_mn(object):
                     log.debug('cannot encode %r', f)
                     can_encode = False
                     break
+
                 if f.value is not None and f.l:
+                    assert f.value <= f.lmask
                     cur_len += f.l
                 index += 1
                 if ret is True:
@@ -1557,6 +1579,8 @@ class imm_noarg(object):
         v = self.encodeval(v)
         if v is False:
             return False
+        if v > self.lmask:
+            return False
         self.value = v
         return True
 
diff --git a/miasm2/ir/ir.py b/miasm2/ir/ir.py
index 64eb3463..982399da 100644
--- a/miasm2/ir/ir.py
+++ b/miasm2/ir/ir.py
@@ -240,15 +240,18 @@ class AssignBlock(object):
         return m2_expr.ExprAff(dst, self[dst])
 
     def simplify(self, simplifier):
-        """Return a new AssignBlock with expression simplified
-        @simplifier: ExpressionSimplifier instance"""
+        """
+        Return a new AssignBlock with expression simplified
+
+        @simplifier: ExpressionSimplifier instance
+        """
         new_assignblk = {}
         for dst, src in self.iteritems():
             if dst == src:
                 continue
-            src = simplifier(src)
-            dst = simplifier(dst)
-            new_assignblk[dst] = src
+            new_src = simplifier(src)
+            new_dst = simplifier(dst)
+            new_assignblk[new_dst] = new_src
         return AssignBlock(irs=new_assignblk, instr=self.instr)
 
 
@@ -687,12 +690,16 @@ class IntermediateRepresentation(object):
         Simplify expressions in each irblocks
         @simplifier: ExpressionSimplifier instance
         """
+        modified = False
         for label, block in self.blocks.iteritems():
             assignblks = []
             for assignblk in block:
                 new_assignblk = assignblk.simplify(simplifier)
+                if assignblk != new_assignblk:
+                    modified = True
                 assignblks.append(new_assignblk)
             self.blocks[label] = IRBlock(label, assignblks)
+        return modified
 
     def replace_expr_in_ir(self, bloc, rep):
         for assignblk in bloc:
@@ -808,6 +815,10 @@ class IntermediateRepresentation(object):
                 continue
             if not expr_is_label(assignblk[self.IRDst]):
                 continue
+            dst = assignblk[self.IRDst].name
+            if dst == block.label:
+                # Infinite loop block
+                continue
             jmp_blocks.add(block.label)
 
         # Remove them, relink graph
@@ -844,7 +855,7 @@ class IntermediateRepresentation(object):
                         self.graph.add_uniq_edge(lbl, dst_label)
                         modified = True
                     if dst.src1 == dst.src2:
-                        dst = src1
+                        dst = dst.src1
                 else:
                     continue
                 new_parent = parent.set_dst(dst)
diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c
index 6b167da5..cce0997d 100644
--- a/miasm2/jitter/arch/JitCore_arm.c
+++ b/miasm2/jitter/arch/JitCore_arm.c
@@ -31,6 +31,11 @@ reg_dict gpreg_dict[] = { {.name = "R0", .offset = offsetof(vm_cpu_t, R0)},
 			  {.name = "nf", .offset = offsetof(vm_cpu_t, nf)},
 			  {.name = "of", .offset = offsetof(vm_cpu_t, of)},
 			  {.name = "cf", .offset = offsetof(vm_cpu_t, cf)},
+
+			  {.name = "ge0", .offset = offsetof(vm_cpu_t, ge0)},
+			  {.name = "ge1", .offset = offsetof(vm_cpu_t, ge1)},
+			  {.name = "ge2", .offset = offsetof(vm_cpu_t, ge2)},
+			  {.name = "ge3", .offset = offsetof(vm_cpu_t, ge3)},
 };
 
 /************************** JitCpu object **************************/
@@ -65,6 +70,11 @@ PyObject* cpu_get_gpreg(JitCpu* self)
     get_reg(of);
     get_reg(cf);
 
+    get_reg(ge0);
+    get_reg(ge1);
+    get_reg(ge2);
+    get_reg(ge3);
+
     return dict;
 }
 
@@ -176,6 +186,16 @@ void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size)
 
 }
 
+
+UDIV(32)
+
+UMOD(32)
+
+IDIV(32)
+
+IMOD(32)
+
+
 void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src)
 {
 	vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src);
@@ -304,6 +324,11 @@ getset_reg_u32(nf);
 getset_reg_u32(of);
 getset_reg_u32(cf);
 
+getset_reg_u32(ge0);
+getset_reg_u32(ge1);
+getset_reg_u32(ge2);
+getset_reg_u32(ge3);
+
 
 PyObject* get_gpreg_offset_all(void)
 {
@@ -335,6 +360,11 @@ PyObject* get_gpreg_offset_all(void)
     get_reg_off(of);
     get_reg_off(cf);
 
+    get_reg_off(ge0);
+    get_reg_off(ge1);
+    get_reg_off(ge2);
+    get_reg_off(ge3);
+
     return dict;
 }
 
@@ -374,6 +404,11 @@ static PyGetSetDef JitCpu_getseters[] = {
     {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL},
     {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL},
 
+    {"ge0", (getter)JitCpu_get_ge0, (setter)JitCpu_set_ge0, "ge0", NULL},
+    {"ge1", (getter)JitCpu_get_ge1, (setter)JitCpu_set_ge0, "ge1", NULL},
+    {"ge2", (getter)JitCpu_get_ge2, (setter)JitCpu_set_ge0, "ge2", NULL},
+    {"ge3", (getter)JitCpu_get_ge3, (setter)JitCpu_set_ge0, "ge3", NULL},
+
     {NULL}  /* Sentinel */
 };
 
diff --git a/miasm2/jitter/arch/JitCore_arm.h b/miasm2/jitter/arch/JitCore_arm.h
index 66d17604..445ac44a 100644
--- a/miasm2/jitter/arch/JitCore_arm.h
+++ b/miasm2/jitter/arch/JitCore_arm.h
@@ -26,12 +26,25 @@ typedef struct {
 	uint32_t of;
 	uint32_t cf;
 
+	/* ge */
+	uint32_t ge0;
+	uint32_t ge1;
+	uint32_t ge2;
+	uint32_t ge3;
+
 	uint32_t bp_num;
 }vm_cpu_t;
 
 
 void dump_gpregs(vm_cpu_t* vmcpu);
 
+
+uint32_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b);
+uint32_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b);
+int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b);
+int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b);
+
+
 #define RETURN_PC return BlockDst;
 
 uint32_t clz(uint32_t arg);
diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py
index 9ed55f37..2c546be8 100644
--- a/miasm2/jitter/codegen.py
+++ b/miasm2/jitter/codegen.py
@@ -572,7 +572,7 @@ class CGen(object):
         irblocks_list = self.block2assignblks(block)
 
         out, instr_offsets = self.gen_init(block)
-
+        assert len(block.lines) == len(irblocks_list)
         for instr, irblocks in zip(block.lines, irblocks_list):
             instr_attrib, irblocks_attributes = self.get_attributes(instr, irblocks, log_mn, log_regs)
 
diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py
index 499d6c47..8eb7659e 100644
--- a/miasm2/jitter/jitload.py
+++ b/miasm2/jitter/jitload.py
@@ -182,6 +182,9 @@ class jitter(object):
                 from miasm2.jitter.arch import JitCore_x86 as jcore
             elif arch_name == "arm":
                 from miasm2.jitter.arch import JitCore_arm as jcore
+            elif arch_name == "armt":
+                from miasm2.jitter.arch import JitCore_arm as jcore
+                ir_arch.arch.name = 'arm'
             elif arch_name == "aarch64":
                 from miasm2.jitter.arch import JitCore_aarch64 as jcore
             elif arch_name == "msp430":
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
index 0e4368a8..35db1538 100644
--- a/miasm2/jitter/llvmconvert.py
+++ b/miasm2/jitter/llvmconvert.py
@@ -180,6 +180,10 @@ class LLVMContext_JIT(LLVMContext):
             from miasm2.arch.mips32.jit import mipsCGen
             self.cgen_class = mipsCGen
             self.has_delayslot = True
+        elif arch.name == "arm":
+            from miasm2.arch.arm.jit import arm_CGen
+            self.cgen_class = arm_CGen
+            self.has_delayslot = False
         else:
             self.cgen_class = CGen
             self.has_delayslot = False
diff --git a/miasm2/os_dep/win_api_x86_32.py b/miasm2/os_dep/win_api_x86_32.py
index c90d7939..a88f4a8a 100644
--- a/miasm2/os_dep/win_api_x86_32.py
+++ b/miasm2/os_dep/win_api_x86_32.py
@@ -1024,22 +1024,20 @@ def kernel32_IsWow64Process(jitter):
     jitter.func_ret_stdcall(ret_ad, 1)
 
 
-def kernel32_GetCommandLineA(jitter):
+def kernel32_GetCommandLine(jitter, set_str):
     ret_ad, _ = jitter.func_args_stdcall(0)
-    s = winobjs.module_path + '\x00'
-    s = '"%s"' % s
     alloc_addr = winobjs.heap.alloc(jitter, 0x1000)
+    s = set_str('"%s"' % winobjs.module_path)
     jitter.vm.set_mem(alloc_addr, s)
     jitter.func_ret_stdcall(ret_ad, alloc_addr)
 
 
+def kernel32_GetCommandLineA(jitter):
+    kernel32_GetCommandLine(jitter, set_str_ansi)
+
+
 def kernel32_GetCommandLineW(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    s = winobjs.module_path + '\x00'
-    s = jitter.set_str_unic('"%s"' % s)
-    alloc_addr = winobjs.heap.alloc(jitter, 0x1000)
-    jitter.vm.set_mem(alloc_addr, s)
-    jitter.func_ret_stdcall(ret_ad, alloc_addr)
+    kernel32_GetCommandLine(jitter, set_str_unic)
 
 
 def shell32_CommandLineToArgvW(jitter):
@@ -1051,10 +1049,9 @@ def shell32_CommandLineToArgvW(jitter):
     addr_ret = winobjs.heap.alloc(jitter, 4 * (len(tks) + 1))
     o = 0
     for i, t in enumerate(tks):
-        x = jitter.set_str_unic(t) + "\x00\x00"
+        jitter.set_str_unic(addr + o, t)
         jitter.vm.set_mem(addr_ret + 4 * i, pck32(addr + o))
-        jitter.vm.set_mem(addr + o, x)
-        o += len(x) + 2
+        o += len(t)*2 + 2
 
     jitter.vm.set_mem(addr_ret + 4 * i, pck32(0))
     jitter.vm.set_mem(args.pnumargs, pck32(len(tks)))
@@ -1442,8 +1439,7 @@ def my_strcpy(jitter, funcname, get_str, set_str):
 
 
 def kernel32_lstrcpyW(jitter):
-    my_strcpy(jitter, whoami(), jitter.get_str_unic,
-              jitter.set_str_unic)
+    my_strcpy(jitter, whoami(), jitter.get_str_unic, jitter.set_str_unic)
 
 
 def kernel32_lstrcpyA(jitter):
@@ -1591,6 +1587,20 @@ def my_GetEnvironmentVariable(jitter, funcname, get_str, set_str, mylen):
     jitter.func_ret_stdcall(ret_ad, mylen(v))
 
 
+def kernel32_GetEnvironmentVariableA(jitter):
+    my_GetEnvironmentVariable(jitter, whoami(),
+                              jitter.get_str_ansi,
+                              jitter.set_str_ansi,
+                              len)
+
+
+def kernel32_GetEnvironmentVariableW(jitter):
+    my_GetEnvironmentVariable(jitter, whoami(),
+                              jitter.get_str_unic,
+                              jitter.set_str_ansi,
+                              len)
+
+
 def my_GetSystemDirectory(jitter, funcname, set_str):
     ret_ad, args = jitter.func_args_stdcall(["lpbuffer", "usize"])
     s = "c:\\windows\\system32"
@@ -1599,6 +1609,7 @@ def my_GetSystemDirectory(jitter, funcname, set_str):
     jitter.func_ret_stdcall(ret_ad, l)
 
 
+
 def kernel32_GetSystemDirectoryA(jitter):
     my_GetSystemDirectory(jitter, whoami(), jitter.set_str_ansi)
 
@@ -1621,19 +1632,6 @@ def kernel32_CreateDirectoryA(jitter):
     my_CreateDirectory(jitter, whoami(), jitter.get_str_ansi)
 
 
-def kernel32_GetEnvironmentVariableA(jitter):
-    my_GetEnvironmentVariable(jitter, whoami(),
-                              jitter.get_str_ansi,
-                              jitter.set_str_ansi,
-                              len)
-
-
-def kernel32_GetEnvironmentVariableW(jitter):
-    my_GetEnvironmentVariable(jitter, whoami(),
-                              jitter.get_str_unic,
-                              jitter.set_str_ansi,
-                              len)
-
 
 def my_CreateEvent(jitter, funcname, get_str):
     ret_ad, args = jitter.func_args_stdcall(["lpeventattributes",
diff --git a/test/arch/arm/arch.py b/test/arch/arm/arch.py
index 3ba2dbd4..7f3b321e 100644
--- a/test/arch/arm/arch.py
+++ b/test/arch/arm/arch.py
@@ -1,5 +1,6 @@
 import time
 from miasm2.arch.arm.arch import *
+from pdb import pm
 
 if 0:
     a = bs('00')
@@ -314,6 +315,9 @@ reg_tests_armt = [
     # adcs
     # sbcs
     # rors
+    ("003258b6    RORS       R3, R2",
+     "D341"),
+
     ("0017b754    TST        R0, R2",
      "1042"),
     ("0006e3fc    NEGS       R5, R5",
@@ -401,6 +405,8 @@ reg_tests_armt = [
      "0cb0"),
     ("0006c1b0    SUB        SP, 0x18",
      "86b0"),
+    ("0006ff5c    SUB        SP, SP, 0x670",
+     "ADF5CE6D"),
 
 
     ("0006aeee    POP        {R4, PC}",
@@ -435,7 +441,7 @@ reg_tests_armt = [
      "f2e7"),
     ("C010163C    BLX        0x1F916C",
      "F9F1B6E8"),
-    ("C01015E8    BL         0x1F8D5C",
+    ("C01015E8    BL         0x1F8D60",
      "F8F1AEFE"),
 
 
@@ -489,6 +495,215 @@ reg_tests_armt = [
     ("xxxxxxxx    WFI        ",
      "30bf"),
 
+
+    ("xxxxxxxx    PUSH       {R4-R8, LR}",
+     "2DE9F041"),
+    ("xxxxxxxx    POP        {R4-R8, PC}",
+     "BDE8F081"),
+    ("xxxxxxxx    MOV        R12, 0x3",
+     "4FF0030C"),
+    ("xxxxxxxx    MOVS       R12, 0x3",
+     "5FF0030C"),
+    ("xxxxxxxx    ASR        R7, R3, R6",
+     "43FA06F7"),
+    ("xxxxxxxx    LSL        LR, R12, R7",
+     "0CFA07FE"),
+    ("xxxxxxxx    MVN        LR, LR",
+     "6FEA0E0E"),
+    ("xxxxxxxx    AND        R5, LR, R5",
+     "0EEA0505"),
+    ("xxxxxxxx    ORR        R5, R8, R5",
+     "48EA0505"),
+    ("xxxxxxxx    ORR        R5, R8, R5",
+     "48EA0505"),
+    ("xxxxxxxx    MOV        R0, 0x600",
+     "4FF4C060"),
+    ("xxxxxxxx    MOV        R0, 0x811",
+     "40F61100"),
+    ("xxxxxxxx    MOV        R1, R1 LSL 0x10",
+     "4FEA0141"),
+
+
+    ("xxxxxxxx    ADD        R1, R4, 0x30",
+     "04F13001"),
+
+    ("xxxxxxxx    SDIV       R3, R5, R2",
+     "95FBF2F3"),
+
+    ("xxxxxxxx    MLS        R5, R2, R3, R5",
+     "02FB1355"),
+
+    ("xxxxxxxx    SMLABB     R2, R2, R3, R1",
+     "12FB0312"),
+    ("xxxxxxxx    SMLABT     R2, R2, R3, R1",
+     "12FB1312"),
+    ("xxxxxxxx    SMLATB     R2, R2, R3, R1",
+     "12FB2312"),
+    ("xxxxxxxx    SMLATT     R2, R2, R3, R1",
+     "12FB3312"),
+
+    ("xxxxxxxx    BIC        R1, R1, R3",
+     "21EA0301"),
+    ("xxxxxxxx    BIC        R4, R0, 0x400",
+     "20F48064"),
+    ("xxxxxxxx    ADD        R3, R1, R3 LSL 0x1",
+     "01EB4303"),
+    ("xxxxxxxx    SUB        R3, R0, 0x22",
+     "A0F12203"),
+    ("xxxxxxxx    UDIV       R3, R3, R1",
+     "B3FBF1F3"),
+    ("xxxxxxxx    MLA        R2, R6, R3, R2",
+     "06FB0322"),
+
+    ("xxxxxxxx    SUB        LR, R3, R2",
+     "A3EB020E"),
+
+    ("xxxxxxxx    ADD        R3, R3, 0x908",
+     "03F60813"),
+
+    ("xxxxxxxx    ADD        R3, R3, 0x23800",
+     "03F50E33"),
+
+
+
+
+    ("xxxxxxxx    B          0x4",
+     "00F000B8"),
+    #("xxxxxxxx    BEQ        0x4",
+    # "00F000A8"),
+    ("xxxxxxxx    BEQ        0x1D4",
+     "00F0E880"),
+
+
+    ("xxxxxxxx    UBFX       R1, R1, 0x0, 0x9",
+     "C1F30801"),
+    ("xxxxxxxx    UXTH       R9, R8",
+     "1FFA88F9"),
+
+    ("xxxxxxxx    AND        R2, R0, 0x1F",
+     "00F01F02"),
+    ("xxxxxxxx    RSB        R3, R3, 0x4",
+     "C3F10403"),
+    ("xxxxxxxx    RSB        R9, R9, R9 LSL 0x4",
+     "C9EB0919"),
+
+
+    ("xxxxxxxx    ITT        EQ",
+     "04BF"),
+    ("xxxxxxxx    ITE        EQ",
+     "0CBF"),
+    ("xxxxxxxx    ITT        HI",
+     "84BF"),
+    ("xxxxxxxx    ITTT       LT",
+     "BEBF"),
+    ("xxxxxxxx    ITE        NE",
+     "14BF"),
+
+    ("xxxxxxxx    STR        R5, [R0, 0xDC]",
+     "C0F8DC50"),
+    ("xxxxxxxx    STRB       R1, [R5, 0x4C]",
+     "85F84C10"),
+    ("xxxxxxxx    STRB       R2, [R3], 0x1",
+     "03F8012B"),
+    ("xxxxxxxx    STRH       R3, [R0, 0xE0]",
+     "A0F8E030"),
+    ("xxxxxxxx    STRH       R3, [R0], 0x2",
+     "20F8023B"),
+
+
+    ("xxxxxxxx    LDR        R3, [R0, 0xDC]",
+     "D0F8DC30"),
+    ("xxxxxxxx    LDR        R4, [SP], 0x4",
+     "5DF8044B"),
+    ("xxxxxxxx    LDRH       R3, [SP, 0x20]",
+     "BDF82030"),
+
+    ("xxxxxxxx    LDRB       R3, [R3, 0xFFFFFFF8]",
+     "13F8083C"),
+    ("xxxxxxxx    LDRB       R2, [R3, 0x30]",
+     "93F83020"),
+    ("xxxxxxxx    LDRB       R5, [R8, R6]",
+     "18F80650"),
+    ("xxxxxxxx    LDR        R3, [R4, R3 LSL 0x2]",
+     "54F82330"),
+    ("xxxxxxxx    LDRSB      R2, [R4, 0x30]",
+     "94F93020"),
+    ("xxxxxxxx    LDRH       R3, [R1], 0x2",
+     "31F8023B"),
+    ("xxxxxxxx    LDRH       R9, [SP, 0x14]",
+     "BDF81490"),
+
+    ("xxxxxxxx    STR        R3, [R2, 0xFFFFFFE4]",
+     "42F81C3C"),
+
+
+
+    ("xxxxxxxx    STR        R1, [R0, R3 LSL 0x2]",
+     "40F82310"),
+
+    ("xxxxxxxx    CLZ        R3, R3",
+     "B3FA83F3"),
+
+    ("xxxxxxxx    MOV        R0, 0x603",
+     "40F20360"),
+    ("xxxxxxxx    TBB        [PC, R0]",
+     "DFE800F0"),
+    ("xxxxxxxx    TBH        [PC, R0 LSL 0x1]",
+     "DFE810F0"),
+
+
+    ("xxxxxxxx    STRD       R5, R5, [R2, 0xFFFFFFF0]",
+     "42E90455"),
+
+    ("xxxxxxxx    MOV        R3, R3 ROR 0x19",
+     "4FEA7363"),
+    ("xxxxxxxx    MOV        R5, R5 LSL 0x3",
+     "4FEAC505"),
+
+
+    ("xxxxxxxx    SUB        R3, R3, 0x6BE",
+     "A3F2BE63"),
+
+    ("xxxxxxxx    PLD        [R0]",
+     "90F800F0"),
+
+    ("xxxxxxxx    LDRD       R2, R3, [R1]",
+     "D1E90023"),
+
+    ("xxxxxxxx    TST        R4, 0x4",
+     "14F0040F"),
+
+    ("xxxxxxxx    ORN        R2, R2, R5",
+     "62EA0502"),
+
+    ("xxxxxxxx    UADD8      R2, R2, R12",
+     "82FA4CF2"),
+
+    ("xxxxxxxx    SEL        R2, R4, R12",
+     "A4FA8CF2"),
+
+    ("xxxxxxxx    REV        R2, R2",
+     "12BA"),
+
+    ("xxxxxxxx    ADD        R8, SP, 0xC8",
+     "0DF1C808"),
+
+    ("xxxxxxxx    CMP        R9, 0x80",
+     "B9F1800F"),
+
+    ("xxxxxxxx    MUL        R2, R1, R2",
+     "01FB02F2"),
+
+    ("xxxxxxxx    LDRSH      R3, [R4, 0xC]",
+     "B4F90C30"),
+
+    ("xxxxxxxx    EOR        R3, R3, R1",
+     "83EA0103"),
+
+    ("xxxxxxxx    DSB        SY",
+     "bff34f8f"),
+
+
 ]
 print "#" * 40, 'armthumb', '#' * 40
 
@@ -507,6 +722,7 @@ for s, l in reg_tests_armt:
     l = mn_armt.fromstring(s, 'l')
     # print l
     assert(str(l) == s)
+    print 'Asm..', l
     a = mn_armt.asm(l)
     print [x for x in a]
     print repr(b)