about summary refs log tree commit diff stats
path: root/miasm2/arch/arm/sem.py
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/arch/arm/sem.py')
-rw-r--r--miasm2/arch/arm/sem.py1040
1 files changed, 1040 insertions, 0 deletions
diff --git a/miasm2/arch/arm/sem.py b/miasm2/arch/arm/sem.py
new file mode 100644
index 00000000..d40c86eb
--- /dev/null
+++ b/miasm2/arch/arm/sem.py
@@ -0,0 +1,1040 @@
+from miasm2.expression.expression import *
+from miasm2.ir.ir import ir, irbloc
+from miasm2.arch.arm.arch import mn_arm, mn_armt
+
+# liris.cnrs.fr/~mmrissa/lib/exe/fetch.php?media=armv7-a-r-manual.pdf
+
+EXCEPT_PRIV_INSN = (1 << 17)
+
+# CPSR: N Z C V
+
+reg_r0 = 'R0'
+reg_r1 = 'R1'
+reg_r2 = 'R2'
+reg_r3 = 'R3'
+reg_r4 = 'R4'
+reg_r5 = 'R5'
+reg_r6 = 'R6'
+reg_r7 = 'R7'
+reg_r8 = 'R8'
+reg_r9 = 'R9'
+reg_r10 = 'R10'
+reg_r11 = 'R11'
+reg_r12 = 'R12'
+reg_sp = 'SP'
+reg_lr = 'LR'
+reg_pc = 'PC'
+
+reg_zf = 'zf'
+reg_nf = 'nf'
+reg_of = 'of'
+reg_cf = 'cf'
+
+zf = ExprId(reg_zf, size=1)
+nf = ExprId(reg_nf, size=1)
+of = ExprId(reg_of, size=1)
+cf = ExprId(reg_cf, size=1)
+
+R0 = ExprId(reg_r0)
+R1 = ExprId(reg_r1)
+R2 = ExprId(reg_r2)
+R3 = ExprId(reg_r3)
+R4 = ExprId(reg_r4)
+R5 = ExprId(reg_r5)
+R6 = ExprId(reg_r6)
+R7 = ExprId(reg_r7)
+R8 = ExprId(reg_r8)
+R9 = ExprId(reg_r9)
+R10 = ExprId(reg_r10)
+R11 = ExprId(reg_r11)
+R12 = ExprId(reg_r12)
+SP = ExprId(reg_sp)
+LR = ExprId(reg_lr)
+PC = ExprId(reg_pc)
+
+
+all_registers = [
+    R0,
+    R1,
+    R2,
+    R3,
+    R4,
+    R5,
+    R6,
+    R7,
+    R8,
+    R9,
+    R10,
+    R11,
+    R12,
+    SP,
+    LR,
+    PC,
+]
+
+
+def update_flag_zf(a):
+    return [ExprAff(zf, ExprCond(a, ExprInt_from(zf, 0), ExprInt_from(zf, 1)))]
+
+
+def update_flag_nf(a):
+    return [ExprAff(nf, a.msb())]
+
+
+def update_flag_pf(a):
+    return [ExprAff(pf, ExprOp('parity', a))]
+
+
+def update_flag_af(a):
+    return [ExprAff(af, ExprCond(a & ExprInt_from(a, 0x10),
+                                 ExprInt_from(af, 1), ExprInt_from(af, 0)))]
+
+
+def update_flag_zn(a):
+    e = []
+    e += update_flag_zf(a)
+    e += update_flag_nf(a)
+    return e
+
+
+def update_flag_logic(a):
+    e = []
+    e += update_flag_zn(a)
+    e.append(ExprAff(cf, ExprInt1(0)))
+    return e
+
+
+def update_flag_arith(a):
+    e = []
+    e += update_flag_zn(a)
+    return e
+
+
+def check_ops_msb(a, b, c):
+    if not a or not b or not c or a != b or a != c:
+        raise ValueError('bad ops size %s %s %s' % (a, b, c))
+
+
+def arith_flag(a, b, c):
+    a_s, b_s, c_s = a.size, b.size, c.size
+    check_ops_msb(a_s, b_s, c_s)
+    a_s, b_s, c_s = a.msb(), b.msb(), c.msb()
+    return a_s, b_s, c_s
+
+# checked: ok for adc add because b & c before +cf
+
+
+def update_flag_add_cf(a, b, c):
+    return ExprAff(cf,
+        ((((a ^ b) ^ c) ^ ((a ^ c) & (~(a ^ b)))).msb()) ^ ExprInt1(1))
+
+
+def update_flag_add_of(a, b, c):
+    return ExprAff(of, (((a ^ c) & (~(a ^ b)))).msb())
+
+
+# checked: ok for sbb add because b & c before +cf
+def update_flag_sub_cf(a, b, c):
+    return ExprAff(cf,
+        ((((a ^ b) ^ c) ^ ((a ^ c) & (a ^ b))).msb()) ^ ExprInt1(1))
+
+
+def update_flag_sub_of(a, b, c):
+    return ExprAff(of, (((a ^ c) & (a ^ b))).msb())
+
+# z = x+y (+cf?)
+
+
+def update_flag_add(x, y, z):
+    e = []
+    e.append(update_flag_add_cf(x, y, z))
+    e.append(update_flag_add_of(x, y, z))
+    return e
+
+# z = x-y (+cf?)
+
+
+def update_flag_sub(x, y, z):
+    e = []
+    e.append(update_flag_sub_cf(x, y, z))
+    e.append(update_flag_sub_of(x, y, z))
+    return e
+
+
+def get_dst(a):
+    if a == PC:
+        return PC
+    return None
+
+# instruction definition ##############
+
+
+def adc(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b + x + cf.zeroExtend(32)
+    if instr.name == 'ADCS' and a != PC:
+        e += update_flag_arith(c)
+        e += update_flag_add(b, x, c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def add(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b + x
+    if instr.name == 'ADDS' and a != PC:
+        e += update_flag_arith(c)
+        e += update_flag_add(b, x, c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def l_and(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b & x
+    if instr.name == 'ANDS' and a != PC:
+        e += update_flag_logic(c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def sub(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b - x
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def subs(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b - x
+    e += update_flag_arith(c)
+    e += update_flag_sub(b, x, c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def eor(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b ^ x
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def eors(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b ^ x
+    e += update_flag_logic(c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def rsb(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = x - b
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def rsbs(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = x - b
+    e += update_flag_arith(c)
+    e += update_flag_sub(b, x, c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def sbc(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = (b + cf.zeroExtend(32)) - (x + ExprInt32(1))
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def sbcs(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = (b + cf.zeroExtend(32)) - (x + ExprInt32(1))
+    e += update_flag_arith(c)
+    e += update_flag_sub(b, x, c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def rsc(ir, instr, x, a, b):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = (x + cf.zeroExtend(32)) - (b + ExprInt32(1))
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def rscs(ir, instr, x, a, b):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = (x + cf.zeroExtend(32)) - (b + ExprInt32(1))
+    e.append(ExprAff(a, c))
+    e += update_flag_arith(c)
+    e += update_flag_sub(x, b, c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def tst(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b & x
+    e += update_flag_logic(c)
+    return None, e
+
+
+def teq(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b ^ x
+    e += update_flag_logic(c)
+    return None, e
+
+
+def l_cmp(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b - x
+    e += update_flag_arith(c)
+    e += update_flag_sub(x, b, c)
+    return None, e
+
+
+def cmn(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b + x
+    e += update_flag_arith(c)
+    e += update_flag_add(b, x, c)
+    return None, e
+
+
+def orr(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b | x
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def orrs(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b | x
+    e += update_flag_logic(c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def mov(ir, instr, a, b):
+    e = [ExprAff(a, b)]
+    dst = get_dst(a)
+    return dst, e
+
+
+def movt(ir, instr, a, b):
+    e = [ExprAff(a, a | b << ExprInt32(16))]
+    dst = get_dst(a)
+    return dst, e
+
+
+def movs(ir, instr, a, b):
+    e = []
+    e.append(ExprAff(a, b))
+    # XXX TODO check
+    e += update_flag_logic(b)
+    dst = get_dst(a)
+    return dst, e
+
+
+def mvn(ir, instr, a, b):
+    e = [ExprAff(a, b ^ ExprInt32(-1))]
+    dst = get_dst(a)
+    return dst, e
+
+
+def mvns(ir, instr, a, b):
+    e = []
+    c = b ^ ExprInt32(-1)
+    e.append(ExprAff(a, c))
+    # XXX TODO check
+    e += update_flag_logic(c)
+    dst = get_dst(a)
+    return dst, e
+
+
+def bic(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b & (x ^ ExprInt(uint32(-1)))
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def bics(ir, instr, a, b, x=None):
+    e = []
+    if x is None:
+        b, x = a, b
+    c = b & (x ^ ExprInt(uint32(-1)))
+    e += update_flag_logic(c)
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def mla(ir, instr, x, a, b, c):
+    e = []
+    d = (a * b) + c
+    e.append(ExprAff(x, d))
+    dst = get_dst(x)
+    return dst, e
+
+
+def mlas(ir, instr, x, a, b, c):
+    e = []
+    d = (a * b) + c
+    e += update_flag_zn(d)
+    e.append(ExprAff(x, d))
+    dst = get_dst(x)
+    return dst, e
+
+
+def mul(ir, instr, x, a, b):
+    e = []
+    c = a * b
+    e.append(ExprAff(x, c))
+    dst = get_dst(x)
+    return dst, e
+
+
+def muls(ir, instr, x, a, b):
+    e = []
+    c = a * b
+    e += update_flag_zn(c)
+    e.append(ExprAff(x, c))
+    dst = get_dst(x)
+    return dst, e
+
+
+def b(ir, instr, a):
+    e = []
+    e.append(ExprAff(PC, a))
+    return a, e
+
+
+def bl(ir, instr, a):
+    e = []
+    l = ExprInt32(instr.offset + instr.l)
+    e.append(ExprAff(PC, a))
+    e.append(ExprAff(LR, l))
+    return a, e
+
+
+def bx(ir, instr, a):
+    e = []
+    e.append(ExprAff(PC, a))
+    return a, e
+
+
+def blx(ir, instr, a):
+    e = []
+    l = ExprInt32(instr.offset + instr.l)
+    e.append(ExprAff(PC, a))
+    e.append(ExprAff(LR, l))
+    return a, e
+
+
+def st_ld_r(ir, instr, a, b, store=False, size=32, s_ext=False, z_ext=False):
+    e = []
+    wb = False
+    b = b.copy()
+    postinc = False
+    if isinstance(b, ExprOp):
+        if b.op == "wback":
+            wb = True
+            b = b.args[0]
+        if b.op == "postinc":
+            postinc = True
+    if isinstance(b, ExprOp) and b.op in ["postinc", 'preinc']:
+        # XXX TODO CHECK
+        base, off = b.args[0],  b.args[1]  # ExprInt32(size/8)
+    else:
+        base, off = b, ExprInt32(0)
+    # print a, wb, base, off, postinc
+    if postinc:
+        ad = base
+    else:
+        ad = base + off
+
+    dmem = False
+    if size in [8, 16]:
+        if store:
+            a = a[:size]
+            m = ExprMem(ad, size=size)
+        elif s_ext:
+            m = ExprMem(ad, size=size).signExtend(a.size)
+        elif z_ext:
+            m = ExprMem(ad, size=size).zeroExtend(a.size)
+        else:
+            raise ValueError('unhandled case')
+    elif size == 32:
+        m = ExprMem(ad, size=size)
+        pass
+    elif size == 64:
+        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')
+    dst = None
+
+    if store:
+        e.append(ExprAff(m, a))
+        if dmem:
+            e.append(ExprAff(ExprMem(ad + ExprInt32(4), size=size), a2))
+    else:
+        if a == PC:
+            dst = PC
+        e.append(ExprAff(a, m))
+        if dmem:
+            e.append(ExprAff(a2, ExprMem(ad + ExprInt32(4), size=size)))
+
+    # XXX TODO check multiple write cause by wb
+    if wb or postinc:
+        e.append(ExprAff(base, base + off))
+    return dst, e
+
+
+def ldr(ir, instr, a, b):
+    return st_ld_r(ir, instr, a, b, store=False)
+
+
+def ldrd(ir, instr, a, b):
+    dst, e = st_ld_r(ir, instr, a, b, store=False, size=64)
+    return dst, e
+
+
+def l_str(ir, instr, a, b):
+    return st_ld_r(ir, instr, a, b, store=True)
+
+
+def l_strd(ir, instr, a, b):
+    dst, e = st_ld_r(ir, instr, a, b, store=True, size=64)
+    return dst, e
+
+
+def ldrb(ir, instr, a, b):
+    dst, e = st_ld_r(ir, instr, a, b, store=False, size=8, z_ext=True)
+    return dst, e
+
+
+def strb(ir, instr, a, b):
+    dst, e = st_ld_r(ir, instr, a, b, store=True, size=8)
+    return dst, e
+
+
+def ldrh(ir, instr, a, b):
+    dst, e = st_ld_r(ir, instr, a, b, store=False, size=16, z_ext=True)
+    return dst, e
+
+
+def strh(ir, instr, a, b):
+    dst, e = st_ld_r(ir, instr, a, b, store=True, size=16, z_ext=True)
+    return dst, e
+
+
+def ldrsh(ir, instr, a, b):
+    dst, e = st_ld_r(
+        ir, instr, a, b, store=False, size=16, s_ext=True, z_ext=False)
+    return dst, e
+
+
+def st_ld_m(ir, instr, a, b, store=False, postinc=False, updown=False):
+    e = []
+    wb = False
+    # sb = False
+    dst = None
+    if isinstance(a, ExprOp) and a.op == 'wback':
+        wb = True
+        a = a.args[0]
+    if isinstance(b, ExprOp) and b.op == 'sbit':
+        # sb = True
+        b = b.args[0]
+    regs = b.args
+    base = a
+    if updown:
+        step = 4
+    else:
+        step = -4
+        regs = regs[::-1]
+    if postinc:
+        pass
+    else:
+        base += ExprInt32(step)
+    for i, r in enumerate(regs):
+        ad = base + ExprInt32(i * step)
+        if store:
+            e.append(ExprAff(ExprMem(ad), r))
+        else:
+            e.append(ExprAff(r, ExprMem(ad)))
+    # XXX TODO check multiple write cause by wb
+    if wb:
+        if postinc:
+            e.append(ExprAff(a, base + ExprInt32(len(regs) * step)))
+        else:
+            e.append(ExprAff(a, base + ExprInt32((len(regs) - 1) * step)))
+    if store:
+        pass
+    else:
+        assert(isinstance(b, ExprOp) and b.op == "reglist")
+        if PC in b.args:
+            dst = PC
+
+    return dst, e
+
+
+def ldmia(ir, instr, a, b):
+    return st_ld_m(ir, instr, a, b, store=False, postinc=True, updown=True)
+
+
+def ldmib(ir, instr, a, b):
+    return st_ld_m(ir, instr, a, b, store=False, postinc=False, updown=True)
+
+
+def ldmda(ir, instr, a, b):
+    return st_ld_m(ir, instr, a, b, store=False, postinc=True, updown=False)
+
+
+def ldmdb(ir, instr, a, b):
+    return st_ld_m(ir, instr, a, b, store=False, postinc=False, updown=False)
+
+
+def stmia(ir, instr, a, b):
+    return st_ld_m(ir, instr, a, b, store=True, postinc=True, updown=True)
+
+
+def stmib(ir, instr, a, b):
+    return st_ld_m(ir, instr, a, b, store=True, postinc=False, updown=True)
+
+
+def stmda(ir, instr, a, b):
+    return st_ld_m(ir, instr, a, b, store=True, postinc=True, updown=False)
+
+
+def stmdb(ir, instr, a, b):
+    return st_ld_m(ir, instr, a, b, store=True, postinc=False, updown=False)
+
+
+def svc(ir, instr, a):
+    # XXX TODO implement
+    e = [
+        ExprAff(ExprId('vmmngr.exception_flags'), ExprInt32(EXCEPT_PRIV_INSN))]
+    return None, e
+
+
+def und(ir, instr, a, b):
+    # XXX TODO implement
+    e = []
+    return None, e
+
+
+def lsr(ir, instr, a, b, x):
+    e = []
+    c = b >> x
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def lsrs(ir, instr, a, b, x):
+    e = []
+    c = b >> x
+    e.append(ExprAff(a, c))
+    e += update_flag_logic(c)
+    dst = get_dst(a)
+    return dst, e
+
+
+def lsl(ir, instr, a, b, x):
+    e = []
+    c = b << x
+    e.append(ExprAff(a, c))
+    dst = get_dst(a)
+    return dst, e
+
+
+def lsls(ir, instr, a, b, x):
+    e = []
+    c = b << x
+    e.append(ExprAff(a, c))
+    e += update_flag_logic(c)
+    dst = get_dst(a)
+    return dst, e
+
+
+def push(ir, instr, a):
+    e = []
+    regs = list(a.args)
+    for i in xrange(len(regs)):
+        c = SP + ExprInt32(-4 * (i + 1))
+        e.append(ExprAff(regs[i], ExprMem(c)))
+    c = SP + ExprInt32(-4 * len(regs))
+    e.append(ExprAff(SP, c))
+    return None, e
+
+
+def pop(ir, instr, a):
+    e = []
+    regs = list(a.args)
+    for i in xrange(len(regs)):
+        c = SP + ExprInt32(4 * i)
+        e.append(ExprAff(regs[i], ExprMem(c)))
+    c = SP + ExprInt32(4 * len(regs))
+    e.append(ExprAff(SP, c))
+    dst = None
+    if PC in a.get_r():
+        dst = PC
+    return dst, e
+
+
+def cbz(ir, instr, a, b):
+    e = []
+    lbl_next = ExprId(ir.get_next_label(instr), 32)
+    dst = ExprCond(a, lbl_next, b)
+    return dst, e
+
+
+def cbnz(ir, instr, a, b):
+    e = []
+    lbl_next = ExprId(ir.get_next_label(instr), 32)
+    dst = ExprCond(a, b, lbl_next)
+    return dst, e
+
+
+COND_EQ = 0
+COND_NE = 1
+COND_CS = 2
+COND_CC = 3
+COND_MI = 4
+COND_PL = 5
+COND_VS = 6
+COND_VC = 7
+COND_HI = 8
+COND_LS = 9
+COND_GE = 10
+COND_LT = 11
+COND_GT = 12
+COND_LE = 13
+COND_AL = 14
+COND_NV = 15
+
+cond_dct = {
+    COND_EQ: "EQ",
+    COND_NE: "NE",
+    COND_CS: "CS",
+    COND_CC: "CC",
+    COND_MI: "MI",
+    COND_PL: "PL",
+    COND_VS: "VS",
+    COND_VC: "VC",
+    COND_HI: "HI",
+    COND_LS: "LS",
+    COND_GE: "GE",
+    COND_LT: "LT",
+    COND_GT: "GT",
+    COND_LE: "LE",
+    COND_AL: "AL",
+    # COND_NV: "NV",
+}
+
+
+tab_cond = {COND_EQ: zf,
+            COND_NE: ExprOp('==', zf, ExprInt1(0)),
+            COND_CS: cf,
+            COND_CC: ExprOp('==', cf, ExprInt1(0)),
+            COND_MI: nf,
+            COND_PL: ExprOp('==', nf, ExprInt1(0)),
+            COND_VS: of,
+            COND_VC: ExprOp('==', of, ExprInt1(0)),
+            COND_HI: cf & ExprOp('==', zf, ExprInt1(0)),
+            # COND_HI: cf,
+            # COND_HI: ExprOp('==',
+            #                ExprOp('|', cf, zf),
+            #                ExprInt1(0)),
+            COND_LS: ExprOp('==', cf, ExprInt1(0)) | zf,
+            COND_GE: ExprOp('==', nf, of),
+            COND_LT: nf ^ of,
+            # COND_GT: ExprOp('|',
+            #                ExprOp('==', zf, ExprInt1(0)) & (nf | of),
+            # ExprOp('==', nf, ExprInt1(0)) & ExprOp('==', of, ExprInt1(0))),
+            COND_GT: ExprOp('==', zf, ExprInt1(0)) & ExprOp('==', nf, of),
+            COND_LE: zf | (nf ^ of),
+            }
+
+
+def is_pc_written(ir, instr_ir):
+    all_pc = ir.mn.pc.values()
+    for ir in instr_ir:
+        if ir.dst in all_pc:
+            return True, ir.dst
+    return False, None
+
+
+def add_condition_expr(ir, instr, cond, instr_ir, dst):
+    # print "XXX", hex(instr.offset), instr
+    if cond == COND_AL:
+        return dst, instr_ir, []
+    if not cond in tab_cond:
+        raise ValueError('unknown condition %r' % cond)
+    cond = tab_cond[cond]
+
+    lbl_next = ExprId(ir.get_next_label(instr), 32)
+    lbl_do = ExprId(ir.gen_label(), 32)
+
+    dst_cond = ExprCond(cond, lbl_do, lbl_next)
+    assert(isinstance(instr_ir, list))
+
+    if dst is None:
+        dst = lbl_next
+    e_do = irbloc(lbl_do.name, dst, [instr_ir])
+    return dst_cond, [], [e_do]
+
+mnemo_func = {}
+mnemo_func_cond = {}
+mnemo_condm0 = {'add': add,
+                'sub': sub,
+                'eor': eor,
+                'and': l_and,
+                'rsb': rsb,
+                'adc': adc,
+                'sbc': sbc,
+                'rsc': rsc,
+
+                'tst': tst,
+                'teq': teq,
+                'cmp': l_cmp,
+                'cmn': cmn,
+                'orr': orr,
+                'mov': mov,
+                'movt': movt,
+                'bic': bic,
+                'mvn': mvn,
+
+                'mul': mul,
+                'mla': mla,
+                'ldr': ldr,
+                'ldrd': ldrd,
+                'str': l_str,
+                'strd': l_strd,
+                'b': b,
+                'bl': bl,
+                'svc': svc,
+                'und': und,
+                'bx': bx,
+                'ldrh': ldrh,
+                'strh': strh,
+                'ldrsh': ldrsh,
+                }
+
+mnemo_condm1 = {'adds': add,
+                'subs': subs,
+                'eors': eors,
+                'ands': l_and,
+                'rsbs': rsbs,
+                'adcs': adc,
+                'sbcs': sbcs,
+                'rscs': rscs,
+
+                'orrs': orrs,
+                'movs': movs,
+                'bics': bics,
+                'mvns': mvns,
+
+                'muls': muls,
+                'mlas': mlas,
+                'blx': blx,
+
+                'ldrb': ldrb,
+                'strb': strb,
+
+                }
+
+mnemo_condm2 = {'ldmia': ldmia,
+                'ldmib': ldmib,
+                'ldmda': ldmda,
+                'ldmdb': ldmdb,
+
+                'ldmfa': ldmda,
+                'ldmfd': ldmia,
+                'ldmea': ldmdb,
+                'ldmed': ldmib,  # XXX
+
+
+                'stmia': stmia,
+                'stmib': stmib,
+                'stmda': stmda,
+                'stmdb': stmdb,
+
+                'stmfa': stmib,
+                'stmed': stmda,
+                'stmfd': stmdb,
+                'stmea': stmia,
+                }
+
+
+mnemo_nocond = {'lsr': lsr,
+                'lsrs': lsrs,
+                'lsl': lsl,
+                'lsls': lsls,
+                'push': push,
+                'pop': pop,
+                'cbz': cbz,
+                'cbnz': cbnz,
+                }
+mn_cond_x = [mnemo_condm0,
+             mnemo_condm1,
+             mnemo_condm2]
+
+for index, mn_base in enumerate(mn_cond_x):
+    for mn, mf in mn_base.items():
+        for cond, cn in cond_dct.items():
+            if cond == COND_AL:
+                cn = ""
+            cn = cn.lower()
+            if index == 0:
+                mn_mod = mn + cn
+            else:
+                mn_mod = mn[:-index] + cn + mn[-index:]
+            # print mn_mod
+            mnemo_func_cond[mn_mod] = cond, mf
+
+for name, mf in mnemo_nocond.items():
+    mnemo_func_cond[name] = COND_AL, mf
+
+
+def split_expr_dst(ir, instr_ir):
+    out = []
+    dst = None
+    for i in instr_ir:
+        if i.dst == ir.pc:
+            out.append(i)
+            dst = ir.pc  # i.src
+        else:
+            out.append(i)
+    return out, dst
+
+
+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()]
+    dst, instr_ir = mf(ir, instr, *args)
+    dst, instr, extra_ir = add_condition_expr(ir, instr, cond, instr_ir, dst)
+    return dst, instr, extra_ir
+
+get_arm_instr_expr = get_mnemo_expr
+
+
+class arminfo:
+    mode = "arm"
+    # offset
+
+
+class ir_arm(ir):
+
+    def __init__(self, symbol_pool=None):
+        ir.__init__(self, mn_arm, "arm", symbol_pool)
+        self.pc = PC
+        self.sp = SP
+
+    def get_ir(self, instr):
+        args = instr.args
+        # ir = get_mnemo_expr(self, self.name.lower(), *args)
+        if len(args) and isinstance(args[-1], ExprOp):
+            if args[-1].op == 'rrx':
+                args[-1] = ExprCompose(
+                    [(args[-1].args[0][1:], 0, 31), (cf, 31, 32)])
+            elif (args[-1].op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>'] and
+                  isinstance(args[-1].args[-1], ExprId)):
+                args[-1].args = args[-1].args[:-1] + (
+                    args[-1].args[-1][:8].zeroExtend(32),)
+        dst, instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
+        # if self.name.startswith('B'):
+        #    return instr_ir, extra_ir
+        for i, x in enumerate(instr_ir):
+            x = ExprAff(x.dst, x.src.replace_expr(
+                {self.pc: ExprInt32(instr.offset + 8)}))
+            instr_ir[i] = x
+        for b in extra_ir:
+            for irs in b.irs:
+                for i, x in enumerate(irs):
+                    x = ExprAff(x.dst, x.src.replace_expr(
+                        {self.pc: ExprInt32(instr.offset + 8)}))
+                    irs[i] = x
+        # return out_ir, extra_ir
+        return dst, instr_ir, extra_ir
+
+
+class ir_armt(ir):
+
+    def __init__(self, symbol_pool=None):
+        ir.__init__(self, mn_armt, "armt", symbol_pool)
+        self.pc = PC
+        self.sp = SP
+
+    def get_ir(self, instr):
+        return get_mnemo_expr(self, instr, *instr.args)
+