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.py628
1 files changed, 506 insertions, 122 deletions
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):