about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml21
-rw-r--r--miasm2/arch/aarch64/arch.py6
-rw-r--r--miasm2/arch/aarch64/sem.py74
-rw-r--r--miasm2/core/bin_stream_ida.py6
-rw-r--r--miasm2/expression/simplifications.py10
-rw-r--r--miasm2/expression/simplifications_common.py417
-rw-r--r--miasm2/jitter/arch/JitCore_aarch64.c8
-rw-r--r--miasm2/jitter/arch/JitCore_arm.c9
-rw-r--r--miasm2/jitter/arch/JitCore_mep.c9
-rw-r--r--miasm2/jitter/arch/JitCore_msp430.c7
-rw-r--r--miasm2/jitter/arch/JitCore_ppc32.c7
-rw-r--r--miasm2/jitter/arch/JitCore_x86.c28
-rw-r--r--miasm2/jitter/jitcore.py12
-rw-r--r--miasm2/jitter/jitcore_python.py209
-rw-r--r--miasm2/jitter/llvmconvert.py2
-rw-r--r--miasm2/jitter/vm_mngr_py.c4
-rw-r--r--test/arch/aarch64/arch.py20
-rw-r--r--test/expression/simplifications.py176
-rwxr-xr-xtest/test_all.py5
19 files changed, 851 insertions, 179 deletions
diff --git a/.travis.yml b/.travis.yml
index 8253cb24..f5c55368 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,14 +11,17 @@ addons:
 env:
   global: CXX=g++-5 LLVM_CONFIG=llvm-config-6.0
   matrix:
-    - MIASM_TEST_TAG=regression
-    - MIASM_TEST_TAG=example
-    - MIASM_TEST_TAG=long
-    - MIASM_TEST_TAG=llvm
-    - MIASM_TEST_TAG=gcc
-    - MIASM_TEST_TAG=z3
-    - MIASM_TEST_TAG=qemu
-    - MIASM_TEST_TAG=cparser
+    - MIASM_TEST_EXTRA_ARG="-o regression -t long,python,llvm,gcc,z3,qemu,cparser"
+    - MIASM_TEST_EXTRA_ARG="-o example -t long,python,llvm,gcc,z3,qemu,cparser"
+    - MIASM_TEST_EXTRA_ARG="-o long"
+    - MIASM_TEST_EXTRA_ARG="-o qemu -t llvm,gcc"
+    - MIASM_TEST_EXTRA_ARG="-o qemu -t python,gcc"
+    - MIASM_TEST_EXTRA_ARG="-o qemu -t python,llvm"
+    - MIASM_TEST_EXTRA_ARG="-o llvm -t qemu,long"
+    - MIASM_TEST_EXTRA_ARG="-o gcc -t qemu,long"
+    - MIASM_TEST_EXTRA_ARG="-o python -t qemu,long"
+    - MIASM_TEST_EXTRA_ARG="-o z3"
+    - MIASM_TEST_EXTRA_ARG="-o cparser"
 before_script:
 - pip install -r optional_requirements.txt
 # codespell
@@ -28,4 +31,4 @@ before_script:
 # install
 - python setup.py build build_ext
 - python setup.py install
-script: cd test && python test_all.py -o=$MIASM_TEST_TAG && git ls-files -o --exclude-standard
+script: cd test && python test_all.py $MIASM_TEST_EXTRA_ARG && git ls-files -o --exclude-standard
diff --git a/miasm2/arch/aarch64/arch.py b/miasm2/arch/aarch64/arch.py
index 38cffc47..91554233 100644
--- a/miasm2/arch/aarch64/arch.py
+++ b/miasm2/arch/aarch64/arch.py
@@ -2155,3 +2155,9 @@ aarch64op("stlxp", [bs('1'), sf, bs('001000'), bs('0'), bs('0'), bs('1'), rs32,
 aarch64op("dsb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('00'), bs('11111')], [crm])
 aarch64op("dmb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('01'), bs('11111')], [crm])
 aarch64op("isb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('10'), bs('11111')], [crm])
+
+stacctype = bs_mod_name(l=1, fname='order', mn_mod=['', 'L'])
+ltacctype = bs_mod_name(l=1, fname='order', mn_mod=['', 'A'])
+
+
+aarch64op("casp",   [bs('0'), sf, bs('001000'), bs('0'), ltacctype, bs('1'), rs, stacctype, bs('11111'), rn64_deref_nooff, rt], [rs, rt, rn64_deref_nooff])
diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py
index 0a03a151..e4702a4f 100644
--- a/miasm2/arch/aarch64/sem.py
+++ b/miasm2/arch/aarch64/sem.py
@@ -1200,6 +1200,74 @@ def clz(ir, instr, arg1, arg2):
     e.append(ExprAssign(arg1, ExprOp('cntleadzeros', arg2)))
     return e, []
 
+def casp(ir, instr, arg1, arg2, arg3):
+    # XXX TODO: memory barrier
+    e = []
+    if arg1.size == 32:
+        regs = gpregs32_expr
+    else:
+        regs = gpregs64_expr
+    index1 = regs.index(arg1)
+    index2 = regs.index(arg2)
+
+    # TODO endianness
+    comp_value = ExprCompose(regs[index1], regs[index1 + 1])
+    new_value = ExprCompose(regs[index2], regs[index2 + 1])
+    assert arg3.is_op('preinc')
+    ptr = arg3.args[0]
+    data = ExprMem(ptr, comp_value.size)
+
+    loc_store = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
+    loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
+    loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size)
+
+    e.append(ExprAssign(ir.IRDst, ExprCond(ExprOp("FLAG_EQ_CMP", data, comp_value), loc_do, loc_store)))
+
+    e_store = []
+    e_store.append(ExprAssign(data, new_value))
+    e_store.append(ExprAssign(ir.IRDst, loc_do))
+    blk_store = IRBlock(loc_store.loc_key, [AssignBlock(e_store, instr)])
+
+    e_do = []
+    e_do.append(ExprAssign(regs[index1], data[:data.size / 2]))
+    e_do.append(ExprAssign(regs[index1 + 1], data[data.size / 2:]))
+    e_do.append(ExprAssign(ir.IRDst, loc_next))
+    blk_do = IRBlock(loc_do.loc_key, [AssignBlock(e_do, instr)])
+
+    return e, [blk_store, blk_do]
+
+
+@sbuild.parse
+def umaddl(arg1, arg2, arg3, arg4):
+    arg1 = arg2.zeroExtend(arg1.size) * arg3.zeroExtend(arg1.size) + arg4
+
+
+@sbuild.parse
+def umsubbl(arg1, arg2, arg3, arg4):
+    arg1 = arg2.zeroExtend(arg1.size) * arg3.zeroExtend(arg1.size) + arg4
+
+
+@sbuild.parse
+def umull(arg1, arg2, arg3):
+    arg1 = (arg2.zeroExtend(64) * arg3.zeroExtend(64))
+
+
+@sbuild.parse
+def umulh(arg1, arg2, arg3):
+    arg1 = (arg2.zeroExtend(128) * arg3.zeroExtend(128))[64:]
+
+
+@sbuild.parse
+def smulh(arg1, arg2, arg3):
+    arg1 = (arg2.signExtend(128) * arg3.signExtend(128))[64:]
+
+
+@sbuild.parse
+def smull(arg1, arg2, arg3):
+    arg1 = (arg2.signExtend(64) * arg3.signExtend(64))[64:]
+
+
+
 mnemo_func = sbuild.functions
 mnemo_func.update({
     'and': and_l,
@@ -1292,6 +1360,12 @@ mnemo_func.update({
     'fcmpe': fcmpe,
     'clz': clz,
 
+    # XXX TODO: memory barrier
+    'casp':casp,
+    'caspl':casp,
+    'caspa':casp,
+    'caspal':casp,
+
 
 })
 
diff --git a/miasm2/core/bin_stream_ida.py b/miasm2/core/bin_stream_ida.py
index de7bc971..f63077bf 100644
--- a/miasm2/core/bin_stream_ida.py
+++ b/miasm2/core/bin_stream_ida.py
@@ -1,5 +1,6 @@
 from idc import Byte, SegEnd
 from idautils import Segments
+from idaapi import is_mapped
 
 from miasm2.core.bin_stream import bin_stream_str
 
@@ -14,7 +15,10 @@ class bin_stream_ida(bin_stream_str):
     def _getbytes(self, start, l=1):
         o = ""
         for ad in xrange(l):
-            o += chr(Byte(ad + start - self.shift))
+            offset = ad + start - self.shift
+            if not is_mapped(offset):
+                raise IOError("not enough bytes")
+            o += chr(Byte(offset))
         return o
 
     def readbs(self, l=1):
diff --git a/miasm2/expression/simplifications.py b/miasm2/expression/simplifications.py
index 3f50fc1a..8ea9c41f 100644
--- a/miasm2/expression/simplifications.py
+++ b/miasm2/expression/simplifications.py
@@ -49,24 +49,32 @@ class ExpressionSimplifier(object):
             simplifications_common.simp_ext_eq_ext,
 
             simplifications_common.simp_cmp_int,
+            simplifications_common.simp_sign_inf_zeroext,
             simplifications_common.simp_cmp_int_int,
             simplifications_common.simp_ext_cst,
+            simplifications_common.simp_zeroext_and_cst_eq_cst,
+            simplifications_common.simp_test_signext_inf,
+            simplifications_common.simp_test_zeroext_inf,
 
         ],
 
         m2_expr.ExprSlice: [
             simplifications_common.simp_slice,
             simplifications_common.simp_slice_of_ext,
+            simplifications_common.simp_slice_of_op_ext,
         ],
         m2_expr.ExprCompose: [simplifications_common.simp_compose],
         m2_expr.ExprCond: [
             simplifications_common.simp_cond,
+            simplifications_common.simp_cond_zeroext,
             # CC op
             simplifications_common.simp_cond_flag,
             simplifications_common.simp_cmp_int_arg,
 
             simplifications_common.simp_cond_eq_zero,
-
+            simplifications_common.simp_x_and_cst_eq_cst,
+            simplifications_common.simp_cond_logic_ext,
+            simplifications_common.simp_cond_sign_bit,
         ],
         m2_expr.ExprMem: [simplifications_common.simp_mem],
 
diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py
index ab0f7ad9..f7171091 100644
--- a/miasm2/expression/simplifications_common.py
+++ b/miasm2/expression/simplifications_common.py
@@ -382,7 +382,7 @@ def simp_cst_propagation(e_s, expr):
     return ExprOp(op_name, *args)
 
 
-def simp_cond_op_int(e_s, expr):
+def simp_cond_op_int(_, expr):
     "Extract conditions from operations"
 
 
@@ -606,10 +606,11 @@ def simp_compose(e_s, expr):
     return ExprCompose(*args)
 
 
-def simp_cond(e_s, expr):
-    "Common simplifications on ExprCond"
-    # eval exprcond src1/src2 with satifiable/unsatisfiable condition
-    # propagation
+def simp_cond(_, expr):
+    """
+    Common simplifications on ExprCond.
+    Eval exprcond src1/src2 with satifiable/unsatisfiable condition propagation
+    """
     if (not expr.cond.is_int()) and expr.cond.size == 1:
         src1 = expr.src1.replace_expr({expr.cond: ExprInt(1, 1)})
         src2 = expr.src2.replace_expr({expr.cond: ExprInt(0, 1)})
@@ -666,10 +667,11 @@ def simp_cond(e_s, expr):
     return expr
 
 
-def simp_mem(e_s, expr):
-    "Common simplifications on ExprMem"
-
-    # @32[x?a:b] => x?@32[a]:@32[b]
+def simp_mem(_, expr):
+    """
+    Common simplifications on ExprMem:
+    @32[x?a:b] => x?@32[a]:@32[b]
+    """
     if expr.ptr.is_cond():
         cond = expr.ptr
         ret = ExprCond(cond.cond,
@@ -682,6 +684,15 @@ def simp_mem(e_s, expr):
 
 
 def test_cc_eq_args(expr, *sons_op):
+    """
+    Return True if expression's arguments match the list in sons_op, and their
+    sub arguments are identical. Ex:
+    CC_S<=(
+              FLAG_SIGN_SUB(A, B),
+              FLAG_SUB_OF(A, B),
+              FLAG_EQ_CMP(A, B)
+    )
+    """
     if not expr.is_op():
         return False
     if len(expr.args) != len(sons_op):
@@ -694,7 +705,11 @@ def test_cc_eq_args(expr, *sons_op):
     return len(all_args) == 1
 
 
-def simp_cc_conds(expr_simp, expr):
+def simp_cc_conds(_, expr):
+    """
+    High level simplifications. Example:
+    CC_U<(FLAG_SUB_CF(A, B) => A <u B
+    """
     if (expr.is_op("CC_U>=") and
           test_cc_eq_args(
               expr,
@@ -702,8 +717,8 @@ def simp_cc_conds(expr_simp, expr):
           )):
         expr = ExprCond(
             ExprOp(TOK_INF_UNSIGNED, *expr.args[0].args),
-            ExprInt(0, 1),
-            ExprInt(1, 1))
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size))
 
     elif (expr.is_op("CC_U<") and
           test_cc_eq_args(
@@ -726,8 +741,8 @@ def simp_cc_conds(expr_simp, expr):
           )):
         expr = ExprCond(
             ExprOp(TOK_INF_SIGNED, *expr.args[0].args),
-            ExprInt(0, 1),
-            ExprInt(1, 1)
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size)
         )
 
     elif (expr.is_op("CC_EQ") and
@@ -746,8 +761,8 @@ def simp_cc_conds(expr_simp, expr):
         arg = expr.args[0].args[0]
         expr = ExprCond(
             ExprOp(TOK_EQUAL,arg, ExprInt(0, arg.size)),
-            ExprInt(0, 1),
-            ExprInt(1, 1)
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size)
         )
     elif (expr.is_op("CC_NE") and
           test_cc_eq_args(
@@ -756,8 +771,8 @@ def simp_cc_conds(expr_simp, expr):
           )):
         expr = ExprCond(
             ExprOp(TOK_EQUAL, *expr.args[0].args),
-            ExprInt(0, 1),
-            ExprInt(1, 1)
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size)
         )
 
     elif (expr.is_op("CC_EQ") and
@@ -781,8 +796,8 @@ def simp_cc_conds(expr_simp, expr):
           )):
         expr = ExprCond(
             ExprOp("&", *expr.args[0].args),
-            ExprInt(0, 1),
-            ExprInt(1, 1)
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size)
         )
 
     elif (expr.is_op("CC_S>") and
@@ -794,8 +809,8 @@ def simp_cc_conds(expr_simp, expr):
           )):
         expr = ExprCond(
             ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args),
-            ExprInt(0, 1),
-            ExprInt(1, 1)
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size)
         )
 
     elif (expr.is_op("CC_S>") and
@@ -806,8 +821,8 @@ def simp_cc_conds(expr_simp, expr):
           expr.args[1].is_int(0)):
         expr = ExprCond(
             ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args),
-            ExprInt(0, 1),
-            ExprInt(1, 1)
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size)
         )
 
 
@@ -820,8 +835,8 @@ def simp_cc_conds(expr_simp, expr):
           )):
         expr = ExprCond(
             ExprOp(TOK_INF_SIGNED, *expr.args[0].args),
-            ExprInt(0, 1),
-            ExprInt(1, 1)
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size)
         )
 
     elif (expr.is_op("CC_S<") and
@@ -865,8 +880,8 @@ def simp_cc_conds(expr_simp, expr):
           )):
         expr = ExprCond(
             ExprOp(TOK_INF_EQUAL_UNSIGNED, *expr.args[0].args),
-            ExprInt(0, 1),
-            ExprInt(1, 1)
+            ExprInt(0, expr.size),
+            ExprInt(1, expr.size)
         )
 
     elif (expr.is_op("CC_S<") and
@@ -882,8 +897,8 @@ def simp_cc_conds(expr_simp, expr):
 
 
 
-def simp_cond_flag(expr_simp, expr):
-    # FLAG_EQ_CMP(X, Y)?A:B => (X == Y)?A:B
+def simp_cond_flag(_, expr):
+    """FLAG_EQ_CMP(X, Y)?A:B => (X == Y)?A:B"""
     cond = expr.cond
     if cond.is_op("FLAG_EQ_CMP"):
         return ExprCond(ExprOp(TOK_EQUAL, *cond.args), expr.src1, expr.src2)
@@ -891,8 +906,10 @@ def simp_cond_flag(expr_simp, expr):
 
 
 def simp_cmp_int(expr_simp, expr):
-    # ({X, 0} == int) => X == int[:]
-    # X + int1 == int2 => X == int2-int1
+    """
+    ({X, 0} == int) => X == int[:]
+    X + int1 == int2 => X == int2-int1
+    """
     if (expr.is_op(TOK_EQUAL) and
           expr.args[1].is_int() and
           expr.args[0].is_compose() and
@@ -931,7 +948,7 @@ def simp_cmp_int(expr_simp, expr):
 
 
 
-def simp_cmp_int_arg(expr_simp, expr):
+def simp_cmp_int_arg(_, expr):
     """
     (0x10 <= R0) ? A:B
     =>
@@ -971,10 +988,8 @@ def simp_cmp_int_arg(expr_simp, expr):
     return ExprCond(ExprOp(op, arg1, arg2), src1, src2)
 
 
-
-
-def simp_subwc_cf(expr_s, expr):
-    # SUBWC_CF(A, B, SUB_CF(C, D)) => SUB_CF({A, C}, {B, D})
+def simp_subwc_cf(_, expr):
+    """SUBWC_CF(A, B, SUB_CF(C, D)) => SUB_CF({A, C}, {B, D})"""
     if not expr.is_op('FLAG_SUBWC_CF'):
         return expr
     op3 = expr.args[2]
@@ -987,8 +1002,8 @@ def simp_subwc_cf(expr_s, expr):
     return ExprOp("FLAG_SUB_CF", op1, op2)
 
 
-def simp_subwc_of(expr_s, expr):
-    # SUBWC_OF(A, B, SUB_CF(C, D)) => SUB_OF({A, C}, {B, D})
+def simp_subwc_of(_, expr):
+    """SUBWC_OF(A, B, SUB_CF(C, D)) => SUB_OF({A, C}, {B, D})"""
     if not expr.is_op('FLAG_SUBWC_OF'):
         return expr
     op3 = expr.args[2]
@@ -1001,8 +1016,8 @@ def simp_subwc_of(expr_s, expr):
     return ExprOp("FLAG_SUB_OF", op1, op2)
 
 
-def simp_sign_subwc_cf(expr_s, expr):
-    # SIGN_SUBWC(A, B, SUB_CF(C, D)) => SIGN_SUB({A, C}, {B, D})
+def simp_sign_subwc_cf(_, expr):
+    """SIGN_SUBWC(A, B, SUB_CF(C, D)) => SIGN_SUB({A, C}, {B, D})"""
     if not expr.is_op('FLAG_SIGN_SUBWC'):
         return expr
     op3 = expr.args[2]
@@ -1014,8 +1029,8 @@ def simp_sign_subwc_cf(expr_s, expr):
 
     return ExprOp("FLAG_SIGN_SUB", op1, op2)
 
-def simp_double_zeroext(expr_s, expr):
-    # A.zeroExt(X).zeroExt(Y) => A.zeroExt(Y)
+def simp_double_zeroext(_, expr):
+    """A.zeroExt(X).zeroExt(Y) => A.zeroExt(Y)"""
     if not (expr.is_op() and expr.op.startswith("zeroExt")):
         return expr
     arg1 = expr.args[0]
@@ -1024,8 +1039,8 @@ def simp_double_zeroext(expr_s, expr):
     arg2 = arg1.args[0]
     return ExprOp(expr.op, arg2)
 
-def simp_double_signext(expr_s, expr):
-    # A.signExt(X).signExt(Y) => A.signExt(Y)
+def simp_double_signext(_, expr):
+    """A.signExt(X).signExt(Y) => A.signExt(Y)"""
     if not (expr.is_op() and expr.op.startswith("signExt")):
         return expr
     arg1 = expr.args[0]
@@ -1034,8 +1049,8 @@ def simp_double_signext(expr_s, expr):
     arg2 = arg1.args[0]
     return ExprOp(expr.op, arg2)
 
-def simp_zeroext_eq_cst(expr_s, expr):
-    # A.zeroExt(X) == int => A == int[:A.size]
+def simp_zeroext_eq_cst(_, expr):
+    """A.zeroExt(X) == int => A == int[:A.size]"""
     if not expr.is_op(TOK_EQUAL):
         return expr
     arg1, arg2 = expr.args
@@ -1046,12 +1061,31 @@ def simp_zeroext_eq_cst(expr_s, expr):
     src = arg1.args[0]
     if int(arg2) > (1 << src.size):
         # Always false
-        return ExprInt(0, 1)
+        return ExprInt(0, expr.size)
     return ExprOp(TOK_EQUAL, src, ExprInt(int(arg2), src.size))
 
-def simp_ext_eq_ext(expr_s, expr):
-    # A.zeroExt(X) == B.zeroExt(X) => A == B
-    # A.signExt(X) == B.signExt(X) => A == B
+def simp_cond_zeroext(_, expr):
+    """
+    X.zeroExt()?(A:B) => X ? A:B
+    X.signExt()?(A:B) => X ? A:B
+    """
+    if not (
+            expr.cond.is_op() and
+            (
+                expr.cond.op.startswith("zeroExt") or
+                expr.cond.op.startswith("signExt")
+            )
+    ):
+        return expr
+
+    ret = ExprCond(expr.cond.args[0], expr.src1, expr.src2)
+    return ret
+
+def simp_ext_eq_ext(_, expr):
+    """
+    A.zeroExt(X) == B.zeroExt(X) => A == B
+    A.signExt(X) == B.signExt(X) => A == B
+    """
     if not expr.is_op(TOK_EQUAL):
         return expr
     arg1, arg2 = expr.args
@@ -1064,8 +1098,8 @@ def simp_ext_eq_ext(expr_s, expr):
         return expr
     return ExprOp(TOK_EQUAL, arg1.args[0], arg2.args[0])
 
-def simp_cond_eq_zero(expr_s, expr):
-    # (X == 0)?(A:B) => X?(B:A)
+def simp_cond_eq_zero(_, expr):
+    """(X == 0)?(A:B) => X?(B:A)"""
     cond = expr.cond
     if not cond.is_op(TOK_EQUAL):
         return expr
@@ -1075,13 +1109,122 @@ def simp_cond_eq_zero(expr_s, expr):
     new_expr = ExprCond(arg1, expr.src2, expr.src1)
     return new_expr
 
+def simp_sign_inf_zeroext(expr_s, expr):
+    """
+    /!\ Ensure before: X.zeroExt(X.size) => X
+
+    X.zeroExt() <s 0 => 0
+    X.zeroExt() <=s 0 => X == 0
 
-def simp_cmp_int_int(expr_s, expr):
-    # IntA <s IntB => int
-    # IntA <u IntB => int
-    # IntA <=s IntB => int
-    # IntA <=u IntB => int
-    # IntA == IntB => int
+    X.zeroExt() <s cst => X.zeroExt() <u cst (cst positive)
+    X.zeroExt() <=s cst => X.zeroExt() <=u cst (cst positive)
+
+    X.zeroExt() <s cst => 0 (cst negative)
+    X.zeroExt() <=s cst => 0 (cst negative)
+
+    """
+    if not (expr.is_op(TOK_INF_SIGNED) or expr.is_op(TOK_INF_EQUAL_SIGNED)):
+        return expr
+    arg1, arg2 = expr.args
+    if not arg2.is_int():
+        return expr
+    if not (arg1.is_op() and arg1.op.startswith("zeroExt")):
+        return expr
+    src = arg1.args[0]
+    assert src.size < arg1.size
+
+    # If cst is zero
+    if arg2.is_int(0):
+        if expr.is_op(TOK_INF_SIGNED):
+            # X.zeroExt() <s 0 => 0
+            return ExprInt(0, expr.size)
+        else:
+            # X.zeroExt() <=s 0 => X == 0
+            return ExprOp(TOK_EQUAL, src, ExprInt(0, src.size))
+
+    # cst is not zero
+    cst = int(arg2)
+    if cst & (1 << (arg2.size - 1)):
+        # cst is negative
+        return ExprInt(0, expr.size)
+    # cst is positive
+    if expr.is_op(TOK_INF_SIGNED):
+        # X.zeroExt() <s cst => X.zeroExt() <u cst (cst positive)
+        return ExprOp(TOK_INF_UNSIGNED, src, expr_s(arg2[:src.size]))
+    # X.zeroExt() <=s cst => X.zeroExt() <=u cst (cst positive)
+    return ExprOp(TOK_INF_EQUAL_UNSIGNED, src, expr_s(arg2[:src.size]))
+
+
+def simp_zeroext_and_cst_eq_cst(expr_s, expr):
+    """
+    A.zeroExt(X) & ... & int == int => A & ... & int[:A.size] == int[:A.size]
+    """
+    if not expr.is_op(TOK_EQUAL):
+        return expr
+    arg1, arg2 = expr.args
+    if not arg2.is_int():
+        return expr
+    if not arg1.is_op('&'):
+        return expr
+    is_ok = True
+    sizes = set()
+    for arg in arg1.args:
+        if arg.is_int():
+            continue
+        if (arg.is_op() and
+            arg.op.startswith("zeroExt")):
+            sizes.add(arg.args[0].size)
+            continue
+        is_ok = False
+        break
+    if not is_ok:
+        return expr
+    if len(sizes) != 1:
+        return expr
+    size = list(sizes)[0]
+    if int(arg2) > ((1 << size) - 1):
+        return expr
+    args = [expr_s(arg[:size]) for arg in arg1.args]
+    left = ExprOp('&', *args)
+    right = expr_s(arg2[:size])
+    ret = ExprOp(TOK_EQUAL, left, right)
+    return ret
+
+
+def test_one_bit_set(arg):
+    """
+    Return True if arg has form 1 << X
+    """
+    return arg != 0  and ((arg & (arg - 1)) == 0)
+
+def simp_x_and_cst_eq_cst(_, expr):
+    """
+    (x & ... & onebitmask == onebitmask) ? A:B => (x & ... & onebitmask) ? A:B
+    """
+    cond = expr.cond
+    if not cond.is_op(TOK_EQUAL):
+        return expr
+    arg1, mask2 = cond.args
+    if not mask2.is_int():
+        return expr
+    if not test_one_bit_set(int(mask2)):
+        return expr
+    if not arg1.is_op('&'):
+        return expr
+    mask1 = arg1.args[-1]
+    if mask1 != mask2:
+        return expr
+    cond = ExprOp('&', *arg1.args)
+    return ExprCond(cond, expr.src1, expr.src2)
+
+def simp_cmp_int_int(_, expr):
+    """
+    IntA <s IntB => int
+    IntA <u IntB => int
+    IntA <=s IntB => int
+    IntA <=u IntB => int
+    IntA == IntB => int
+    """
     if expr.op not in [
             TOK_EQUAL,
             TOK_INF_SIGNED, TOK_INF_UNSIGNED,
@@ -1094,8 +1237,7 @@ def simp_cmp_int_int(expr_s, expr):
     if expr.is_op(TOK_EQUAL):
         if int_a == int_b:
             return ExprInt(1, 1)
-        else:
-            return ExprInt(0, 1)
+        return ExprInt(0, expr.size)
 
     if expr.op in [TOK_INF_SIGNED, TOK_INF_EQUAL_SIGNED]:
         int_a = int(mod_size2int[int_a.size](int(int_a)))
@@ -1116,9 +1258,11 @@ def simp_cmp_int_int(expr_s, expr):
     return ExprInt(ret, 1)
 
 
-def simp_ext_cst(expr_s, expr):
-    # Int.zeroExt(X) => Int
-    # Int.signExt(X) => Int
+def simp_ext_cst(_, expr):
+    """
+    Int.zeroExt(X) => Int
+    Int.signExt(X) => Int
+    """
     if not (expr.op.startswith("zeroExt") or expr.op.startswith("signExt")):
         return expr
     arg = expr.args[0]
@@ -1132,31 +1276,150 @@ def simp_ext_cst(expr_s, expr):
     return ret
 
 
-def simp_slice_of_ext(expr_s, expr):
-    # zeroExt(X)[0:size(X)] => X
-    if expr.start != 0:
-        return expr
+def simp_slice_of_ext(_, expr):
+    """
+    C.zeroExt(X)[A:B] => 0 if A >= size(C)
+    C.zeroExt(X)[A:B] => C[A:B] if B <= size(C)
+    A.zeroExt(X)[0:Y] => A.zeroExt(Y)
+    """
     if not expr.arg.is_op():
         return expr
     if not expr.arg.op.startswith("zeroExt"):
         return expr
     arg = expr.arg.args[0]
-    if arg.size != expr.size:
+
+    if expr.start >= arg.size:
+        # C.zeroExt(X)[A:B] => 0 if A >= size(C)
+        return ExprInt(0, expr.size)
+    if expr.stop <= arg.size:
+        # C.zeroExt(X)[A:B] => C[A:B] if B <= size(C)
+        return arg[expr.start:expr.stop]
+    if expr.start == 0:
+        # A.zeroExt(X)[0:Y] => A.zeroExt(Y)
+        return arg.zeroExtend(expr.stop)
+    return expr
+
+def simp_slice_of_op_ext(expr_s, expr):
+    """(X.zeroExt() + ... + Int)[0:8] => X + ... + int[:]"""
+    if expr.start != 0:
+        return expr
+    src = expr.arg
+    if not src.is_op("+"):
+        return expr
+    is_ok = True
+    for arg in src.args:
+        if arg.is_int():
+            continue
+        if (arg.is_op() and
+            arg.op.startswith("zeroExt") and
+            arg.args[0].size == expr.stop):
+            continue
+        is_ok = False
+        break
+    if not is_ok:
+        return expr
+    args = [expr_s(arg[:expr.stop]) for arg in src.args]
+    return ExprOp("+", *args)
+
+
+def simp_cond_logic_ext(expr_s, expr):
+    """(X.zeroExt() + ... + Int) ? A:B => X + ... + int[:] ? A:B"""
+    cond = expr.cond
+    if not cond.is_op():
+        return expr
+    if cond.op not in ["&", "^", "|"]:
+        return expr
+    is_ok = True
+    sizes = set()
+    for arg in cond.args:
+        if arg.is_int():
+            continue
+        if (arg.is_op() and
+            arg.op.startswith("zeroExt")):
+            sizes.add(arg.args[0].size)
+            continue
+        is_ok = False
+        break
+    if not is_ok:
+        return expr
+    if len(sizes) != 1:
+        return expr
+    size = list(sizes)[0]
+    args = [expr_s(arg[:size]) for arg in cond.args]
+    cond = ExprOp(cond.op, *args)
+    return ExprCond(cond, expr.src1, expr.src2)
+
+
+def simp_cond_sign_bit(_, expr):
+    """(a & .. & 0x80000000) ? A:B => (a & ...) <s 0 ? A:B"""
+    cond = expr.cond
+    if not cond.is_op('&'):
+        return expr
+    last = cond.args[-1]
+    if not last.is_int(1 << (last.size - 1)):
+        return expr
+    zero = ExprInt(0, expr.cond.size)
+    if len(cond.args) == 2:
+        args = [cond.args[0], zero]
+    else:
+        args = [ExprOp('&', *list(cond.args[:-1])), zero]
+    cond = ExprOp(TOK_INF_SIGNED, *args)
+    return ExprCond(cond, expr.src1, expr.src2)
+
+
+def simp_test_signext_inf(expr_s, expr):
+    """A.signExt() <s int => A <s int[:]"""
+    if not (expr.is_op(TOK_INF_SIGNED) or expr.is_op(TOK_INF_EQUAL_SIGNED)):
+        return expr
+    arg, cst = expr.args
+    if not (arg.is_op() and arg.op.startswith("signExt")):
         return expr
-    return arg
+    if not cst.is_int():
+        return expr
+    base = arg.args[0]
+    tmp = int(mod_size2int[cst.size](int(cst)))
+    if -(1 << (base.size - 1)) <= tmp < (1 << (base.size - 1)):
+        # Can trunc integer
+        return ExprOp(expr.op, base, expr_s(cst[:base.size]))
+    if (tmp >= (1 << (base.size - 1)) or
+        tmp < -(1 << (base.size - 1)) ):
+        return ExprInt(1, 1)
+    return expr
 
-def simp_add_multiple(expr_s, expr):
-    # X + X => 2 * X
-    # X + X * int1 => X * (1 + int1)
-    # X * int1 + (- X) => X * (int1 - 1)
-    # X + (X << int1) => X * (1 + 2 ** int1)
-    # Correct even if addition overflow/underflow
+
+def simp_test_zeroext_inf(expr_s, expr):
+    """A.zeroExt() <u int => A <u int[:]"""
+    if not (expr.is_op(TOK_INF_UNSIGNED) or expr.is_op(TOK_INF_EQUAL_UNSIGNED)):
+        return expr
+    arg, cst = expr.args
+    if not (arg.is_op() and arg.op.startswith("zeroExt")):
+        return expr
+    if not cst.is_int():
+        return expr
+    base = arg.args[0]
+    tmp = int(mod_size2uint[cst.size](int(cst)))
+    if 0 <= tmp < (1 << base.size):
+        # Can trunc integer
+        return ExprOp(expr.op, base, expr_s(cst[:base.size]))
+    if tmp >= (1 << base.size):
+        return ExprInt(1, 1)
+    return expr
+
+
+def simp_add_multiple(_, expr):
+    """
+    X + X => 2 * X
+    X + X * int1 => X * (1 + int1)
+    X * int1 + (- X) => X * (int1 - 1)
+    X + (X << int1) => X * (1 + 2 ** int1)
+    Correct even if addition overflow/underflow
+    """
     if not expr.is_op('+'):
         return expr
 
     # Extract each argument and its counter
     operands = {}
-    for i, arg in enumerate(expr.args):
+    for arg in expr.args:
         if arg.is_op('*') and arg.args[1].is_int():
             base_expr, factor = arg.args
             operands[base_expr] = operands.get(base_expr, 0) + int(factor)
diff --git a/miasm2/jitter/arch/JitCore_aarch64.c b/miasm2/jitter/arch/JitCore_aarch64.c
index fc51848a..d8b6d0f9 100644
--- a/miasm2/jitter/arch/JitCore_aarch64.c
+++ b/miasm2/jitter/arch/JitCore_aarch64.c
@@ -194,6 +194,12 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args)
 }
 
 
+PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args)
+{
+	return cpu_dump_gpregs(self, args);
+}
+
+
 PyObject* cpu_set_exception(JitCpu* self, PyObject* args)
 {
 	PyObject *item1;
@@ -294,6 +300,8 @@ static PyMethodDef JitCpu_methods[] = {
 	 "X"},
 	{"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS,
 	 "X"},
+	{"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS,
+	 "X"},
 	{"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS,
 	 "X"},
 	{"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS,
diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c
index 4f1fd254..dca341d3 100644
--- a/miasm2/jitter/arch/JitCore_arm.c
+++ b/miasm2/jitter/arch/JitCore_arm.c
@@ -157,6 +157,13 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args)
 }
 
 
+PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args)
+{
+	return cpu_dump_gpregs(self, args);
+}
+
+
+
 PyObject* cpu_set_exception(JitCpu* self, PyObject* args)
 {
 	PyObject *item1;
@@ -276,6 +283,8 @@ static PyMethodDef JitCpu_methods[] = {
 	 "X"},
 	{"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS,
 	 "X"},
+	{"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS,
+	 "X"},
 	{"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS,
 	 "X"},
 	{"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS,
diff --git a/miasm2/jitter/arch/JitCore_mep.c b/miasm2/jitter/arch/JitCore_mep.c
index 44f36290..a089e84f 100644
--- a/miasm2/jitter/arch/JitCore_mep.c
+++ b/miasm2/jitter/arch/JitCore_mep.c
@@ -223,6 +223,10 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args)
     return Py_None;
 }
 
+PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args)
+{
+	return cpu_dump_gpregs(self, args);
+}
 
 PyObject* cpu_set_exception(JitCpu* self, PyObject* args)
 {
@@ -244,10 +248,6 @@ PyObject* cpu_get_exception(JitCpu* self, PyObject* args)
     return PyLong_FromUnsignedLongLong((uint64_t)(((vm_cpu_t*)self->cpu)->exception_flags));
 }
 
-
-
-
-
 void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size)
 {
     PyObject *result;
@@ -322,6 +322,7 @@ static PyMemberDef JitCpu_members[] = {
 static PyMethodDef JitCpu_methods[] = {
     {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"},
     {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"},
+    {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, "X"},
     {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"},
     {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"},
     {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"},
diff --git a/miasm2/jitter/arch/JitCore_msp430.c b/miasm2/jitter/arch/JitCore_msp430.c
index 12a42782..69f179a4 100644
--- a/miasm2/jitter/arch/JitCore_msp430.c
+++ b/miasm2/jitter/arch/JitCore_msp430.c
@@ -158,6 +158,11 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args)
 	return Py_None;
 }
 
+PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args)
+{
+	return cpu_dump_gpregs(self, args);
+}
+
 
 PyObject* cpu_set_exception(JitCpu* self, PyObject* args)
 {
@@ -259,6 +264,8 @@ static PyMethodDef JitCpu_methods[] = {
 	 "X"},
 	{"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS,
 	 "X"},
+	{"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS,
+	 "X"},
 	{"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS,
 	 "X"},
 	{"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS,
diff --git a/miasm2/jitter/arch/JitCore_ppc32.c b/miasm2/jitter/arch/JitCore_ppc32.c
index dfc46c91..e1a3fcd5 100644
--- a/miasm2/jitter/arch/JitCore_ppc32.c
+++ b/miasm2/jitter/arch/JitCore_ppc32.c
@@ -109,6 +109,12 @@ cpu_dump_gpregs(JitCpu *self, PyObject *args) {
 }
 
 PyObject *
+cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args)
+{
+	return cpu_dump_gpregs(self, args);
+}
+
+PyObject *
 cpu_set_exception(JitCpu *self, PyObject *args) {
     PyObject *item1;
     uint64_t i;
@@ -208,6 +214,7 @@ static PyMemberDef JitCpu_members[] = {
 static PyMethodDef JitCpu_methods[] = {
     {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"},
     {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"},
+    {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, "X"},
     {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"},
     {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"},
     {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"},
diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c
index b711f40b..fa47b324 100644
--- a/miasm2/jitter/arch/JitCore_x86.c
+++ b/miasm2/jitter/arch/JitCore_x86.c
@@ -349,6 +349,32 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args)
 }
 
 
+PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args)
+{
+	vm_cpu_t* vmcpu;
+	PyObject *item1;
+	uint64_t attrib;
+
+	if (!PyArg_ParseTuple(args, "O", &item1))
+		RAISE(PyExc_TypeError,"Cannot parse arguments");
+
+	PyGetInt(item1, attrib);
+
+	vmcpu = self->cpu;
+	if (attrib == 16 || attrib == 32)
+		dump_gpregs_32(vmcpu);
+	else if (attrib == 64)
+		dump_gpregs_64(vmcpu);
+	else {
+		RAISE(PyExc_TypeError,"Bad attrib");
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+
 PyObject* cpu_set_exception(JitCpu* self, PyObject* args)
 {
 	PyObject *item1;
@@ -484,6 +510,8 @@ static PyMethodDef JitCpu_methods[] = {
 	 "X"},
 	{"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS,
 	 "X"},
+	{"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS,
+	 "X"},
 	{"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS,
 	 "X"},
 	{"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS,
diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py
index fc5cf35e..78e27244 100644
--- a/miasm2/jitter/jitcore.py
+++ b/miasm2/jitter/jitcore.py
@@ -114,21 +114,11 @@ class JitCore(object):
         for a, b in self.blocks_mem_interval:
             vm.add_code_bloc(a, b + 1)
 
-    def jit_irblocks(self, label, irblocks):
-        """JiT a group of irblocks.
-        @label: the label of the irblocks
-        @irblocks: a group of irblocks
-        """
-
-        raise NotImplementedError("Abstract class")
-
     def add_block(self, block):
         """Add a block to JiT and JiT it.
         @block: asm_bloc to add
         """
-        irblocks = self.ir_arch.add_asmblock_to_ircfg(block, self.ircfg, gen_pc_updt = True)
-        block.blocks = irblocks
-        self.jit_irblocks(block.loc_key, irblocks)
+        raise NotImplementedError("Abstract class")
 
     def disasm_and_jit_block(self, addr, vm):
         """Disassemble a new block and JiT it
diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py
index dd4c543e..fdd5c2ae 100644
--- a/miasm2/jitter/jitcore_python.py
+++ b/miasm2/jitter/jitcore_python.py
@@ -1,5 +1,5 @@
 import miasm2.jitter.jitcore as jitcore
-import miasm2.expression.expression as m2_expr
+from miasm2.expression.expression import ExprInt, ExprLoc
 import miasm2.jitter.csts as csts
 from miasm2.expression.simplifications import expr_simp_explicit
 from miasm2.jitter.emulatedsymbexec import EmulatedSymbExec
@@ -36,12 +36,38 @@ class JitCore_Python(jitcore.JitCore):
         "Preload symbols according to current architecture"
         self.symbexec.reset_regs()
 
-    def jit_irblocks(self, loc_key, irblocks):
-        """Create a python function corresponding to an irblocks' group.
-        @loc_key: the loc_key of the irblocks
-        @irblocks: a group of irblocks
+    def arch_specific(self):
+        """Return arch specific information for the current architecture"""
+        arch = self.ir_arch.arch
+        has_delayslot = False
+        if arch.name == "mips32":
+            from miasm2.arch.mips32.jit import mipsCGen
+            cgen_class = mipsCGen
+            has_delayslot = True
+        elif arch.name == "arm":
+            from miasm2.arch.arm.jit import arm_CGen
+            cgen_class = arm_CGen
+        else:
+            from miasm2.jitter.codegen import CGen
+            cgen_class = CGen
+        return cgen_class(self.ir_arch), has_delayslot
+
+    def add_block(self, asmblock):
+        """Create a python function corresponding to an AsmBlock
+        @asmblock: AsmBlock
         """
 
+        # TODO: merge duplicate code with CGen, llvmconvert
+        codegen, has_delayslot = self.arch_specific()
+        irblocks_list = codegen.block2assignblks(asmblock)
+        instr_offsets = [line.offset for line in asmblock.lines]
+
+        loc_db = self.ir_arch.loc_db
+        local_loc_keys = []
+        for irblocks in irblocks_list:
+            for irblock in irblocks:
+                local_loc_keys.append(irblock.loc_key)
+
         def myfunc(cpu):
             """Execute the function according to cpu and vmmngr states
             @cpu: JitCpu instance
@@ -49,86 +75,131 @@ class JitCore_Python(jitcore.JitCore):
             # Get virtual memory handler
             vmmngr = cpu.vmmngr
 
-            # Keep current location in irblocks
-            cur_loc_key = loc_key
-
-            # Required to detect new instructions
-            offsets_jitted = set()
-
-            # Get exec engine
+            # Get execution engine (EmulatedSymbExec instance)
             exec_engine = self.symbexec
-            expr_simp = exec_engine.expr_simp
 
-            # For each irbloc inside irblocks
-            while True:
-                # Get the current bloc
-                for irb in irblocks:
-                    if irb.loc_key == cur_loc_key:
-                        break
+            # Refresh CPU values according to @cpu instance
+            exec_engine.update_engine_from_cpu()
 
-                else:
-                    raise RuntimeError("Irblocks must end with returning an "
-                                       "ExprInt instance")
-
-                # Refresh CPU values according to @cpu instance
-                exec_engine.update_engine_from_cpu()
-
-                # Execute current ir bloc
-                for assignblk in irb:
-                    instr = assignblk.instr
-                    # For each new instruction (in assembly)
-                    if instr is not None and instr.offset not in offsets_jitted:
-                        # Test exceptions
-                        vmmngr.check_invalid_code_blocs()
-                        vmmngr.check_memory_breakpoint()
-                        if vmmngr.get_exception():
-                            exec_engine.update_cpu_from_engine()
-                            return instr.offset
+            # Get initial loc_key
+            cur_loc_key = asmblock.loc_key
 
-                        offsets_jitted.add(instr.offset)
+            # Update PC helper
+            update_pc = lambda value: setattr(cpu, self.ir_arch.pc.name, value)
 
-                        # Log registers values
-                        if self.log_regs:
-                            exec_engine.update_cpu_from_engine()
-                            exec_engine.cpu.dump_gpregs()
+            while True:
+                # Retrieve the expected irblock
+                for instr, irblocks in zip(asmblock.lines, irblocks_list):
+                    for index, irblock in enumerate(irblocks):
+                        if irblock.loc_key == cur_loc_key:
+                            break
+                    else:
+                        continue
+                    break
+                else:
+                    raise RuntimeError("Unable to find the block for %r" % cur_loc_key)
+
+                instr_attrib, irblocks_attributes = codegen.get_attributes(
+                    instr, irblocks, self.log_mn, self.log_regs
+                )
+                irblock_attributes = irblocks_attributes[index]
+
+                # Do IRBlock
+                new_irblock = self.ir_arch.irbloc_fix_regs_for_mode(
+                    irblock, self.ir_arch.attrib
+                )
+                if index == 0:
+                    # Pre code
+                    if instr_attrib.log_mn:
+                        print "%.8X %s" % (
+                            instr_attrib.instr.offset,
+                            instr_attrib.instr.to_string(loc_db)
+                        )
+
+                # Exec IRBlock
+                instr = instr_attrib.instr
+
+                for index, assignblk in enumerate(irblock):
+                    attributes = irblock_attributes[index]
 
-                        # Log instruction
-                        if self.log_mn:
-                            print "%08x %s" % (instr.offset, instr)
+                    # Eval current instruction (in IR)
+                    exec_engine.eval_updt_assignblk(assignblk)
 
-                        # Check for exception
-                        if (vmmngr.get_exception() != 0 or
-                            cpu.get_exception() != 0):
-                            exec_engine.update_cpu_from_engine()
+                    # Check memory access / write exception
+                    # TODO: insert a check between memory reads and writes
+                    if attributes.mem_read or attributes.mem_write:
+                        # Restricted exception
+                        flag = ~csts.EXCEPT_CODE_AUTOMOD & csts.EXCEPT_DO_NOT_UPDATE_PC
+                        if (vmmngr.get_exception() & flag != 0):
+                            # Do not update registers
+                            update_pc(instr.offset)
                             return instr.offset
 
-                    # Eval current instruction (in IR)
-                    exec_engine.eval_updt_assignblk(assignblk)
-                    # Check for exceptions which do not update PC
+                    # Update registers values
                     exec_engine.update_cpu_from_engine()
-                    if (vmmngr.get_exception() & csts.EXCEPT_DO_NOT_UPDATE_PC != 0 or
-                        cpu.get_exception() > csts.EXCEPT_NUM_UPDT_EIP):
-                        return instr.offset
-
-                vmmngr.check_invalid_code_blocs()
-                vmmngr.check_memory_breakpoint()
 
-                # Get next bloc address
-                ad = expr_simp(exec_engine.eval_expr(self.ir_arch.IRDst))
+                    # Check post assignblk exception flags
+                    if attributes.set_exception:
+                        # Restricted exception
+                        if cpu.get_exception() > csts.EXCEPT_NUM_UPDT_EIP:
+                            # Update PC
+                            update_pc(instr.offset)
+                            return instr.offset
 
-                # Updates @cpu instance according to new CPU values
-                exec_engine.update_cpu_from_engine()
+                dst = exec_engine.eval_expr(self.ir_arch.IRDst)
+                if dst.is_int():
+                    loc_key = loc_db.get_or_create_offset_location(int(dst))
+                    dst = ExprLoc(loc_key, dst.size)
+
+                assert dst.is_loc()
+                loc_key = dst.loc_key
+                offset = loc_db.get_location_offset(loc_key)
+                if offset is None:
+                    # Avoid checks on generated label
+                    cur_loc_key = loc_key
+                    continue
+
+                if instr_attrib.log_regs:
+                    update_pc(offset)
+                    cpu.dump_gpregs_with_attrib(self.ir_arch.attrib)
+
+                # Post-instr checks
+                if instr_attrib.mem_read | instr_attrib.mem_write:
+                    vmmngr.check_memory_breakpoint()
+                    vmmngr.check_invalid_code_blocs()
+                    if vmmngr.get_exception():
+                        update_pc(offset)
+                        return offset
+
+                if instr_attrib.set_exception:
+                    if cpu.get_exception():
+                        update_pc(offset)
+                        return offset
+
+                if instr_attrib.mem_read | instr_attrib.mem_write:
+                    vmmngr.reset_memory_access()
 
                 # Manage resulting address
-                if isinstance(ad, m2_expr.ExprInt):
-                    return ad.arg.arg
-                elif isinstance(ad, m2_expr.ExprLoc):
-                    cur_loc_key = ad.loc_key
-                else:
-                    raise NotImplementedError("Type not handled: %s" % ad)
+                if (loc_key in local_loc_keys and
+                    offset > instr.offset):
+                    # Forward local jump
+                    # Note: a backward local jump has to be promoted to extern,
+                    # for max_exec_per_call support
+                    cur_loc_key = loc_key
+                    continue
+
+                # Delay slot
+                if has_delayslot:
+                    delay_slot_set = exec_engine.eval_expr(codegen.delay_slot_set)
+                    if delay_slot_set.is_int() and int(delay_slot_set) != 0:
+                        return int(exec_engine.eval_expr(codegen.delay_slot_dst))
+
+                # Extern of asmblock, must have an offset
+                assert offset is not None
+                return offset
 
         # Associate myfunc with current loc_key
-        offset = self.ir_arch.loc_db.get_location_offset(loc_key)
+        offset = loc_db.get_location_offset(asmblock.loc_key)
         assert offset is not None
         self.offset_to_jitted_func[offset] = myfunc
 
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
index 5230bdbe..41461c3a 100644
--- a/miasm2/jitter/llvmconvert.py
+++ b/miasm2/jitter/llvmconvert.py
@@ -1297,7 +1297,7 @@ class LLVMFunction(object):
             # Update PC for dump_gpregs
             PC = self.llvm_context.PC
             t_size = LLVMType.IntType(PC.size)
-            dst = self.builder.zext(t_size(pc_value), LLVMType.IntType(PC.size))
+            dst = self.builder.zext(t_size(pc_value), t_size)
             self.affect(dst, PC)
 
             fc_ptr = self.mod.get_global(self.llvm_context.logging_func)
diff --git a/miasm2/jitter/vm_mngr_py.c b/miasm2/jitter/vm_mngr_py.c
index 5ff436bf..93de9bb4 100644
--- a/miasm2/jitter/vm_mngr_py.c
+++ b/miasm2/jitter/vm_mngr_py.c
@@ -248,7 +248,6 @@ PyObject* vm_get_u8(VmMngr* self, PyObject* args)
        PyObject *py_addr;
 
        uint64_t addr;
-       uint64_t size;
        PyObject *obj_out;
        char * buf_out;
        int ret;
@@ -276,7 +275,6 @@ PyObject* vm_get_u16(VmMngr* self, PyObject* args)
        PyObject *py_addr;
 
        uint64_t addr;
-       uint64_t size;
        PyObject *obj_out;
        char * buf_out;
        int ret;
@@ -304,7 +302,6 @@ PyObject* vm_get_u32(VmMngr* self, PyObject* args)
        PyObject *py_addr;
 
        uint64_t addr;
-       uint64_t size;
        PyObject *obj_out;
        char * buf_out;
        int ret;
@@ -333,7 +330,6 @@ PyObject* vm_get_u64(VmMngr* self, PyObject* args)
        PyObject *py_addr;
 
        uint64_t addr;
-       uint64_t size;
        PyObject *obj_out;
        char * buf_out;
        int ret;
diff --git a/test/arch/aarch64/arch.py b/test/arch/aarch64/arch.py
index cba175e6..46a4514b 100644
--- a/test/arch/aarch64/arch.py
+++ b/test/arch/aarch64/arch.py
@@ -7,6 +7,7 @@ from miasm2.core.locationdb import LocationDB
 loc_db = LocationDB()
 
 reg_tests_aarch64 = [
+
     ("XXXXXXXX    MOV        W1, WZR",
      "E1031F2A"),
     ("XXXXXXXX    TST        W5, W3",
@@ -1794,6 +1795,25 @@ reg_tests_aarch64 = [
     ("XXXXXXXX    ORR        X8, 0x0, 0x1000100010001",
      "E88300B2"),
 
+
+    ("XXXXXXXX    CASP       X0, X2, [X4]",
+     "827C2048"),
+    ("XXXXXXXX    CASPL      X0, X2, [X4]",
+     "82FC2048"),
+    ("XXXXXXXX    CASPA      X0, X2, [X4]",
+     "827C6048"),
+    ("XXXXXXXX    CASPAL     X0, X2, [X4]",
+     "82FC6048"),
+
+    ("XXXXXXXX    CASP       W0, W2, [X4]",
+     "827C2008"),
+    ("XXXXXXXX    CASPL      W0, W2, [X4]",
+     "82FC2008"),
+    ("XXXXXXXX    CASPA      W0, W2, [X4]",
+     "827C6008"),
+    ("XXXXXXXX    CASPAL     W0, W2, [X4]",
+     "82FC6008"),
+
 ]
 
 
diff --git a/test/expression/simplifications.py b/test/expression/simplifications.py
index cc3606e4..5bca3fa9 100644
--- a/test/expression/simplifications.py
+++ b/test/expression/simplifications.py
@@ -446,6 +446,9 @@ to_test = [(ExprInt(1, 32) - ExprInt(1, 32), ExprInt(0, 32)),
     (ExprOp("signExt_16", ExprInt(0x8, 8)), ExprInt(0x8, 16)),
     (ExprOp("signExt_16", ExprInt(-0x8, 8)), ExprInt(-0x8, 16)),
 
+    (ExprCond(a8.zeroExtend(32), a, b), ExprCond(a8, a, b)),
+
+
     (- (i2*a), a * im2),
     (a + a, a * i2),
     (ExprOp('+', a, a), a * i2),
@@ -516,6 +519,179 @@ to_test = [
     (ExprOp(TOK_EQUAL, a8.zeroExtend(32), b8.zeroExtend(32)), ExprOp(TOK_EQUAL, a8, b8)),
     (ExprOp(TOK_EQUAL, a8.signExtend(32), b8.signExtend(32)), ExprOp(TOK_EQUAL, a8, b8)),
 
+    (ExprOp(TOK_INF_EQUAL_SIGNED, a8.zeroExtend(32), i0), ExprOp(TOK_EQUAL, a8, ExprInt(0, 8))),
+
+    ((a8.zeroExtend(32) + b8.zeroExtend(32) + ExprInt(1, 32))[0:8], a8 + b8 + ExprInt(1, 8)),
+
+    (ExprCond(a8.zeroExtend(32), a, b), ExprCond(a8, a, b)),
+    (ExprCond(a8.signExtend(32), a, b), ExprCond(a8, a, b)),
+
+
+    (
+        ExprOp(
+            TOK_EQUAL,
+            a8.zeroExtend(32) & b8.zeroExtend(32) & ExprInt(0x12, 32),
+            i1
+        ),
+        ExprOp(
+            TOK_EQUAL,
+            a8 & b8 & ExprInt(0x12, 8),
+            ExprInt(1, 8)
+        )
+    ),
+
+    (
+        ExprCond(
+            ExprOp(
+                TOK_EQUAL,
+                a & b & ExprInt(0x80, 32),
+                ExprInt(0x80, 32)
+            ), a, b
+        ),
+        ExprCond(a & b & ExprInt(0x80, 32), a, b)
+    ),
+
+
+
+    (
+        ExprCond(
+            a8.zeroExtend(32) & b8.zeroExtend(32) & ExprInt(0x12, 32),
+            a, b
+        ),
+        ExprCond(
+            a8 & b8 & ExprInt(0x12, 8),
+            a, b
+        ),
+    ),
+
+
+    (a8.zeroExtend(32)[:8], a8),
+    (a.zeroExtend(64)[:32], a),
+    (a.zeroExtend(64)[:8], a[:8]),
+    (a8.zeroExtend(32)[:16], a8.zeroExtend(16)),
+
+    (
+        ExprCond(
+            a & ExprInt(0x80000000, 32),
+            a, b
+        ),
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a, ExprInt(0, 32) ),
+            a, b
+        )
+    ),
+
+
+
+    (
+        ExprCond(
+            a8.signExtend(32) & ExprInt(0x80000000, 32),
+            a, b
+        ),
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a8, ExprInt(0, 8) ),
+            a, b
+        )
+    ),
+
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a8.signExtend(32), ExprInt(0x10, 32) ),
+            a, b
+        ),
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a8, ExprInt(0x10, 8) ),
+            a, b
+        )
+    ),
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a8.signExtend(32), ExprInt(-0x10, 32) ),
+            a, b
+        ),
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a8, ExprInt(-0x10, 8) ),
+            a, b
+        )
+    ),
+
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_UNSIGNED, a8.zeroExtend(32), ExprInt(0x10, 32) ),
+            a, b
+        ),
+        ExprCond(
+            ExprOp(TOK_INF_UNSIGNED, a8, ExprInt(0x10, 8) ),
+            a, b
+        )
+    ),
+
+
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a8.signExtend(32), ExprInt(0x200, 32) ),
+            a, b
+        ),
+        a
+    ),
+
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_UNSIGNED, a8.zeroExtend(32), ExprInt(0x200, 32) ),
+            a, b
+        ),
+        a
+    ),
+
+
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a8.zeroExtend(32), ExprInt(0x10, 32) ),
+            a, b
+        ),
+        ExprCond(
+            ExprOp(TOK_INF_UNSIGNED, a8, ExprInt(0x10, 8) ),
+            a, b
+        )
+    ),
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_EQUAL_SIGNED, a8.zeroExtend(32), ExprInt(0x10, 32) ),
+            a, b
+        ),
+        ExprCond(
+            ExprOp(TOK_INF_EQUAL_UNSIGNED, a8, ExprInt(0x10, 8) ),
+            a, b
+        )
+    ),
+
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_SIGNED, a8.zeroExtend(32), ExprInt(-1, 32) ),
+            a, b
+        ),
+        b
+    ),
+
+    (
+        ExprCond(
+            ExprOp(TOK_INF_EQUAL_SIGNED, a8.zeroExtend(32), ExprInt(-1, 32) ),
+            a, b
+        ),
+        b
+    ),
+
+
+    (a8.zeroExtend(32)[2:5], a8[2:5]),
+
 ]
 
 for e_input, e_check in to_test:
diff --git a/test/test_all.py b/test/test_all.py
index 4b97ffba..f3bcc477 100755
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -21,6 +21,7 @@ TAGS = {"regression": "REGRESSION", # Regression tests
         "long": "LONG", # Very time consumming tests
         "llvm": "LLVM", # LLVM dependency is required
         "gcc": "GCC", # GCC based tests
+        "python": "PYTHON", # Python jitted tests
         "z3": "Z3", # Z3 dependency is needed
         "qemu": "QEMU", # QEMU tests (several tests)
         "cparser": "CPARSER", # pycparser is needed
@@ -109,7 +110,7 @@ for script in ["x86/sem.py",
             continue
         testset += ArchUnitTest(script, jitter, base_dir="arch", tags=tags)
 
-testset += ArchUnitTest("x86/unit/access_xmm.py", "python", base_dir="arch")
+testset += ArchUnitTest("x86/unit/access_xmm.py", "python", base_dir="arch", tags=[TAGS["python"]])
 
 ### QEMU regression tests
 class QEMUTest(RegressionTest):
@@ -750,7 +751,7 @@ class ExampleJitterNoPython(ExampleJitter):
 
 for jitter in ExampleJitter.jitter_engines:
     # Take 5 min on a Core i5
-    tags = {"python": [TAGS["long"]],
+    tags = {"python": [TAGS["long"], TAGS["python"]],
             "llvm": [TAGS["llvm"]],
             "gcc": [TAGS["gcc"]],
             }