about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorserpilliere <serpilliere@users.noreply.github.com>2015-11-17 14:18:16 +0100
committerserpilliere <serpilliere@users.noreply.github.com>2015-11-17 14:18:16 +0100
commita49419dd5e16283b1663181a47cdc85b7eff14dc (patch)
treeeed2791c9c96039c6603d0173646eb4265a85366
parentc0826fefbbcd00c60f0e9f27dcac92c98fcb9d8e (diff)
parentbf4c21011c8396b939e147615d12998a11c91dcd (diff)
downloadmiasm-a49419dd5e16283b1663181a47cdc85b7eff14dc.tar.gz
miasm-a49419dd5e16283b1663181a47cdc85b7eff14dc.zip
Merge pull request #277 from commial/fix-x86-xchg
Fix x86 xchg
Diffstat (limited to '')
-rw-r--r--miasm2/arch/x86/arch.py4
-rw-r--r--miasm2/arch/x86/sem.py173
-rw-r--r--miasm2/core/sembuilder.py122
-rw-r--r--miasm2/ir/symbexec.py11
-rw-r--r--miasm2/jitter/jitcore_python.py11
-rw-r--r--test/arch/x86/arch.py8
-rw-r--r--test/arch/x86/qemu/testqemu.py6
-rw-r--r--test/core/sembuilder.py11
-rw-r--r--test/test_all.py3
9 files changed, 213 insertions, 136 deletions
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index 2b9b3cb1..74ac0939 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -3252,6 +3252,10 @@ addop("cmpsq", [bs8(0xa7), bs_opmode64])
 
 addop("cmpxchg", [bs8(0x0f), bs('1011000'), w8]
       + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg])
+addop("cmpxchg8b", [bs8(0x0f), bs8(0xc7), bs_opmode16] + rmmod(d1, rm_arg_m64))
+addop("cmpxchg8b", [bs8(0x0f), bs8(0xc7), bs_opmode32] + rmmod(d1, rm_arg_m64))
+addop("cmpxchg16b", [bs8(0x0f), bs8(0xc7), bs_opmode64] + rmmod(d1, rm_arg_m64))
+
 # XXX TODO CMPXCHG8/16
 
 addop("comiss", [bs8(0x0f), bs8(0x2f), no_xmm_pref] +
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index f1784692..c39d2583 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -22,9 +22,20 @@ from miasm2.arch.x86.regs import *
 from miasm2.arch.x86.arch import mn_x86, repeat_mn, replace_regs
 from miasm2.expression.expression_helper import expr_cmps, expr_cmpu
 from miasm2.ir.ir import ir, irbloc
+from miasm2.core.sembuilder import SemBuilder
 import math
 import struct
 
+
+# SemBuilder context
+ctx = {'mRAX': mRAX,
+       'mRBX': mRBX,
+       'mRCX': mRCX,
+       'mRDX': mRDX,
+       'zf': zf,
+       }
+sbuild = SemBuilder(ctx)
+
 # interrupt with eip update after instr
 EXCEPT_SOFT_BP = (1 << 1)
 EXCEPT_INT_XX = (1 << 2)
@@ -195,15 +206,15 @@ def gen_jcc(ir, instr, cond, dst, jmp_if):
     """
 
     e = []
-    meip = mRIP[instr.mode]
+    meip = mRIP[ir.IRDst.size]
     next_lbl = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
     if jmp_if:
         dstA, dstB = dst, next_lbl
     else:
         dstA, dstB = next_lbl, dst
     mn_dst = m2_expr.ExprCond(cond,
-                              dstA.zeroExtend(instr.mode),
-                              dstB.zeroExtend(instr.mode))
+                              dstA.zeroExtend(ir.IRDst.size),
+                              dstB.zeroExtend(ir.IRDst.size))
     e.append(m2_expr.ExprAff(meip, mn_dst))
     e.append(m2_expr.ExprAff(ir.IRDst, mn_dst))
     return e, []
@@ -216,8 +227,8 @@ def gen_fcmov(ir, instr, cond, arg1, arg2, mov_if):
     @cond: condition
     @mov_if: invert condition if False"""
 
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_do = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
     if mov_if:
         dstA, dstB = lbl_do, lbl_skip
     else:
@@ -236,8 +247,8 @@ def gen_cmov(ir, instr, cond, arg1, arg2, mov_if):
     @cond: condition
     @mov_if: invert condition if False"""
 
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_do = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
     if mov_if:
         dstA, dstB = lbl_do, lbl_skip
     else:
@@ -258,11 +269,10 @@ def mov(ir, instr, a, b):
     return e, []
 
 
-def xchg(ir, instr, a, b):
-    e = []
-    e.append(m2_expr.ExprAff(a, b))
-    e.append(m2_expr.ExprAff(b, a))
-    return e, []
+@sbuild.parse
+def xchg(arg1, arg2):
+    arg1 = arg2
+    arg2 = arg1
 
 
 def movzx(ir, instr, a, b):
@@ -452,8 +462,8 @@ def _rotate_tpl(ir, instr, a, b, op, left=False, include_cf=False):
             return [], []
 
     e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_do = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
     e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
     e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(shifter, lbl_do,
                                                         lbl_skip)))
@@ -548,8 +558,8 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False,
             return [], []
 
     e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_do = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
     e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
     e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(shifter, lbl_do,
                                                         lbl_skip)))
@@ -914,10 +924,10 @@ def bswap(ir, instr, a):
 
 
 def cmps(ir, instr, size):
-    lbl_cmp = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_cmp = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
 
     s = instr.v_admode()
     a = m2_expr.ExprMem(mRDI[instr.mode][:s], size)
@@ -947,10 +957,10 @@ def cmps(ir, instr, size):
 
 
 def scas(ir, instr, size):
-    lbl_cmp = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_cmp = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
 
     s = instr.v_admode()
     a = m2_expr.ExprMem(mRDI[instr.mode][:s], size)
@@ -1107,10 +1117,10 @@ def call(ir, instr, dst):
     e = []
     # opmode, admode = instr.opmode, instr.admode
     s = dst.size
-    meip = mRIP[instr.mode]
+    meip = mRIP[ir.IRDst.size]
     opmode, admode = s, instr.v_admode()
     myesp = mRSP[instr.mode][:opmode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    n = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
 
 
     if (isinstance(dst, m2_expr.ExprOp) and dst.op == "segm"):
@@ -1144,8 +1154,8 @@ def call(ir, instr, dst):
     if ir.do_stk_segm:
         c = m2_expr.ExprOp('segm', SS, c)
     e.append(m2_expr.ExprAff(m2_expr.ExprMem(c, size=s), n))
-    e.append(m2_expr.ExprAff(meip, dst.zeroExtend(instr.mode)))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst.zeroExtend(instr.mode)))
+    e.append(m2_expr.ExprAff(meip, dst.zeroExtend(ir.IRDst.size)))
+    e.append(m2_expr.ExprAff(ir.IRDst, dst.zeroExtend(ir.IRDst.size)))
     #if not expr_is_int_or_label(dst):
     #    dst = meip
     return e, []
@@ -1154,7 +1164,7 @@ def call(ir, instr, dst):
 def ret(ir, instr, a=None):
     e = []
     s = instr.mode
-    meip = mRIP[instr.mode]
+    meip = mRIP[ir.IRDst.size]
     opmode, admode = instr.v_opmode(), instr.v_admode()
     s = opmode
     myesp = mRSP[instr.mode][:s]
@@ -1179,7 +1189,7 @@ def ret(ir, instr, a=None):
 def retf(ir, instr, a=None):
     e = []
     s = instr.mode
-    meip = mRIP[instr.mode]
+    meip = mRIP[ir.IRDst.size]
     opmode, admode = instr.v_opmode(), instr.v_admode()
     if a is None:
         a = m2_expr.ExprInt(0, s)
@@ -1238,9 +1248,9 @@ def enter(ir, instr, a, b):
 
 def jmp(ir, instr, dst):
     e = []
-    meip = mRIP[instr.mode]
-    e.append(m2_expr.ExprAff(meip, dst))  # dst.zeroExtend(instr.mode)))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst))  # dst.zeroExtend(instr.mode)))
+    meip = mRIP[ir.IRDst.size]
+    e.append(m2_expr.ExprAff(meip, dst))  # dst.zeroExtend(ir.IRDst.size)))
+    e.append(m2_expr.ExprAff(ir.IRDst, dst))  # dst.zeroExtend(ir.IRDst.size)))
 
     if isinstance(dst, m2_expr.ExprMem):
         dst = meip
@@ -1249,7 +1259,7 @@ def jmp(ir, instr, dst):
 
 def jmpf(ir, instr, a):
     e = []
-    meip = mRIP[instr.mode]
+    meip = mRIP[ir.IRDst.size]
     s = instr.mode
     if (isinstance(a, m2_expr.ExprOp) and a.op == "segm"):
         segm = a.args[0]
@@ -1344,15 +1354,15 @@ def jno(ir, instr, dst):
 
 def loop(ir, instr, dst):
     e = []
-    meip = mRIP[instr.mode]
+    meip = mRIP[ir.IRDst.size]
     admode = instr.v_admode()
     myecx = mRCX[instr.mode][:admode]
 
-    n = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    n = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
     c = myecx - m2_expr.ExprInt_from(myecx, 1)
     dst_o = m2_expr.ExprCond(c,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
+                             dst.zeroExtend(ir.IRDst.size),
+                             n.zeroExtend(ir.IRDst.size))
     e.append(m2_expr.ExprAff(myecx, c))
     e.append(m2_expr.ExprAff(meip, dst_o))
     e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
@@ -1361,11 +1371,11 @@ def loop(ir, instr, dst):
 
 def loopne(ir, instr, dst):
     e = []
-    meip = mRIP[instr.mode]
+    meip = mRIP[ir.IRDst.size]
     admode = instr.v_admode()
     myecx = mRCX[instr.mode][:admode]
 
-    n = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    n = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
 
     c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size),
                  m2_expr.ExprInt1(1),
@@ -1374,8 +1384,8 @@ def loopne(ir, instr, dst):
 
     e.append(m2_expr.ExprAff(myecx, myecx - m2_expr.ExprInt_from(myecx, 1)))
     dst_o = m2_expr.ExprCond(c,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
+                             dst.zeroExtend(ir.IRDst.size),
+                             n.zeroExtend(ir.IRDst.size))
     e.append(m2_expr.ExprAff(meip, dst_o))
     e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
     return e, []
@@ -1383,19 +1393,19 @@ def loopne(ir, instr, dst):
 
 def loope(ir, instr, dst):
     e = []
-    meip = mRIP[instr.mode]
+    meip = mRIP[ir.IRDst.size]
     admode = instr.v_admode()
     myecx = mRCX[instr.mode][:admode]
 
-    n = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    n = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
     c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size),
                  m2_expr.ExprInt1(1),
                  m2_expr.ExprInt1(0))
     c &= zf
     e.append(m2_expr.ExprAff(myecx, myecx - m2_expr.ExprInt_from(myecx, 1)))
     dst_o = m2_expr.ExprCond(c,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
+                             dst.zeroExtend(ir.IRDst.size),
+                             n.zeroExtend(ir.IRDst.size))
     e.append(m2_expr.ExprAff(meip, dst_o))
     e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
     return e, []
@@ -1586,9 +1596,9 @@ def cqo(ir, instr):
 
 
 def stos(ir, instr, size):
-    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
 
     s = instr.v_admode()
 
@@ -1622,9 +1632,9 @@ def stos(ir, instr, size):
 
 
 def lods(ir, instr, size):
-    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
     e = []
     s = instr.v_admode()
 
@@ -1659,9 +1669,9 @@ def lods(ir, instr, size):
 
 
 def movs(ir, instr, size):
-    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_df_0 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_df_1 = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
 
     s = instr.v_admode()
     # a = m2_expr.ExprMem(mRDI[instr.mode][:s], size)
@@ -2681,9 +2691,9 @@ def bsr_bsf(ir, instr, a, b, op_name):
         ZF = 0
         DEST = @op_name(SRC)
     """
-    lbl_src_null = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_src_not_null = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    lbl_src_null = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_src_not_null = m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
 
     aff_dst = m2_expr.ExprAff(ir.IRDst, lbl_next)
     e = [m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(b,
@@ -2948,25 +2958,27 @@ def l_in(ir, instr, a, b):
     return e, []
 
 
-def cmpxchg(ir, instr, a, b):
-    e = []
+@sbuild.parse
+def cmpxchg(arg1, arg2):
+    accumulator = mRAX[instr.mode][:arg1.size]
+    if (accumulator - arg1):
+        zf = i1(0)
+        accumulator = arg1
+    else:
+        zf = i1(1)
+        arg1 = arg2
 
-    c = mRAX[instr.mode][:a.size]
-    cond = c - a
-    e.append(
-        m2_expr.ExprAff(zf,
-                        m2_expr.ExprCond(cond,
-                                         m2_expr.ExprInt_from(zf, 0),
-                                         m2_expr.ExprInt_from(zf, 1))))
-    e.append(m2_expr.ExprAff(a, m2_expr.ExprCond(cond,
-                                 b,
-                                 a)
-                     ))
-    e.append(m2_expr.ExprAff(c, m2_expr.ExprCond(cond,
-                                 a,
-                                 c)
-                     ))
-    return e, []
+
+@sbuild.parse
+def cmpxchg8b(arg1):
+    accumulator = {mRAX[instr.mode], mRDX[instr.mode]}
+    if accumulator - arg1:
+        zf = i1(0)
+        mRAX[instr.mode] = arg1[:instr.mode]
+        mRDX[instr.mode] = arg1[instr.mode:]
+    else:
+        zf = i1(1)
+        arg1 = {mRBX[instr.mode], mRCX[instr.mode]}
 
 
 def lds(ir, instr, a, b):
@@ -3700,6 +3712,7 @@ mnemo_func = {'mov': mov,
               'out': l_out,
               "sysenter": l_sysenter,
               "cmpxchg": cmpxchg,
+              "cmpxchg8b": cmpxchg8b,
               "lds": lds,
               "les": les,
               "lss": lss,
@@ -3895,10 +3908,10 @@ class ir_x86_16(ir):
             c_cond = cond_dec | (zf ^ m2_expr.ExprInt1(1))
 
         # gen while
-        lbl_do = m2_expr.ExprId(self.gen_label(), instr.mode)
-        lbl_end = m2_expr.ExprId(self.gen_label(), instr.mode)
-        lbl_skip = m2_expr.ExprId(self.get_next_label(instr), instr.mode)
-        lbl_next = m2_expr.ExprId(self.get_next_label(instr), instr.mode)
+        lbl_do = m2_expr.ExprId(self.gen_label(), self.IRDst.size)
+        lbl_end = m2_expr.ExprId(self.gen_label(), self.IRDst.size)
+        lbl_skip = m2_expr.ExprId(self.get_next_label(instr), self.IRDst.size)
+        lbl_next = m2_expr.ExprId(self.get_next_label(instr), self.IRDst.size)
 
         for b in extra_ir:
             for ir in b.irs:
diff --git a/miasm2/core/sembuilder.py b/miasm2/core/sembuilder.py
index 8be3fb12..83981919 100644
--- a/miasm2/core/sembuilder.py
+++ b/miasm2/core/sembuilder.py
@@ -16,6 +16,7 @@ class MiasmTransformer(ast.NodeTransformer):
     X if Y else Z -> ExprCond(Y, X, Z)
     'X'(Y)        -> ExprOp('X', Y)
     ('X' % Y)(Z)  -> ExprOp('X' % Y, Z)
+    {a, b}        -> ExprCompose([a, 0, a.size], [b, a.size, a.size + b.size])
     """
 
     # Parsers
@@ -93,6 +94,32 @@ class MiasmTransformer(ast.NodeTransformer):
                         keywords=[], starargs=None, kwargs=None)
         return call
 
+    def visit_Set(self, node):
+        "{a, b} -> ExprCompose([a, 0, a.size], [b, a.size, a.size + b.size])"
+        if len(node.elts) == 0:
+            return node
+
+        # Recursive visit
+        node = self.generic_visit(node)
+
+        new_elts = []
+        index = ast.Num(n=0)
+        for elt in node.elts:
+            new_index = ast.BinOp(op=ast.Add(), left=index,
+                                  right=ast.Attribute(value=elt,
+                                                      attr='size',
+                                                      ctx=ast.Load()))
+            new_elts.append(ast.List(elts=[elt, index, new_index],
+                                     ctx=ast.Load()))
+            index = new_index
+        return ast.Call(func=ast.Name(id='ExprCompose',
+                                      ctx=ast.Load()),
+                               args=[ast.List(elts=new_elts,
+                                              ctx=ast.Load())],
+                               keywords=[],
+                               starargs=None,
+                               kwargs=None)
+
 
 class SemBuilder(object):
     """Helper for building instruction's semantic side effects method
@@ -121,10 +148,14 @@ class SemBuilder(object):
         return self._functions.copy()
 
     @staticmethod
-    def _create_labels():
-        """Return the AST standing for label creations"""
-        out = ast.parse("lbl_end = ExprId(ir.get_next_instr(instr))").body
-        out += ast.parse("lbl_if = ExprId(ir.gen_label())").body
+    def _create_labels(lbl_else=False):
+        """Return the AST standing for label creations
+        @lbl_else (optional): if set, create a label 'lbl_else'"""
+        lbl_end = "lbl_end = ExprId(ir.get_next_label(instr), ir.IRDst.size)"
+        out = ast.parse(lbl_end).body
+        out += ast.parse("lbl_if = ExprId(ir.gen_label(), ir.IRDst.size)").body
+        if lbl_else:
+            out += ast.parse("lbl_else = ExprId(ir.gen_label(), ir.IRDst.size)").body
         return out
 
     def _parse_body(self, body, argument_names):
@@ -147,11 +178,13 @@ class SemBuilder(object):
 
                 if (isinstance(dst, ast.Name) and
                     dst.id not in argument_names and
-                    dst.id not in self._ctx):
+                    dst.id not in self._ctx and
+                    dst.id not in self._local_ctx):
 
                     # Real variable declaration
                     statement.value = src
                     real_body.append(statement)
+                    self._local_ctx[dst.id] = src
                     continue
 
                 dst.ctx = ast.Load()
@@ -170,19 +203,21 @@ class SemBuilder(object):
                 # String (docstring, comment, ...) -> keep it
                 real_body.append(statement)
 
-            elif (isinstance(statement, ast.If) and
-                  not statement.orelse):
+            elif isinstance(statement, ast.If):
                 # Create jumps : ir.IRDst = lbl_if if cond else lbl_end
+                # if .. else .. are also handled
                 cond = statement.test
-                real_body += self._create_labels()
+                real_body += self._create_labels(lbl_else=True)
 
                 lbl_end = ast.Name(id='lbl_end', ctx=ast.Load())
                 lbl_if = ast.Name(id='lbl_if', ctx=ast.Load())
+                lbl_else = ast.Name(id='lbl_else', ctx=ast.Load()) \
+                           if statement.orelse else lbl_end
                 dst = ast.Call(func=ast.Name(id='ExprCond',
                                              ctx=ast.Load()),
                                args=[cond,
                                      lbl_if,
-                                     lbl_end],
+                                     lbl_else],
                                keywords=[],
                                starargs=None,
                                kwargs=None)
@@ -204,38 +239,42 @@ class SemBuilder(object):
                                                kwargs=None))
 
                 # Create the new blocks
-                sub_blocks, sub_body = self._parse_body(statement.body,
-                                                        argument_names)
-                if len(sub_blocks) > 1:
-                    raise RuntimeError("Imbricated if unimplemented")
-
-                ## Close the last block
-                jmp_end = ast.Call(func=ast.Name(id='ExprAff',
-                                                 ctx=ast.Load()),
-                                   args=[IRDst, lbl_end],
-                                   keywords=[],
-                                   starargs=None,
-                                   kwargs=None)
-                sub_blocks[-1][-1].append(jmp_end)
-                sub_blocks[-1][-1] = ast.List(elts=sub_blocks[-1][-1],
+                elements = [(statement.body, 'lbl_if')]
+                if statement.orelse:
+                    elements.append((statement.orelse, 'lbl_else'))
+                for content, lbl_name in elements:
+                    sub_blocks, sub_body = self._parse_body(content,
+                                                            argument_names)
+                    if len(sub_blocks) > 1:
+                        raise RuntimeError("Imbricated if unimplemented")
+
+                    ## Close the last block
+                    jmp_end = ast.Call(func=ast.Name(id='ExprAff',
+                                                     ctx=ast.Load()),
+                                       args=[IRDst, lbl_end],
+                                       keywords=[],
+                                       starargs=None,
+                                       kwargs=None)
+                    sub_blocks[-1][-1].append(jmp_end)
+                    sub_blocks[-1][-1] = ast.List(elts=sub_blocks[-1][-1],
+                                                  ctx=ast.Load())
+                    sub_blocks[-1] = ast.List(elts=sub_blocks[-1],
                                               ctx=ast.Load())
-                sub_blocks[-1] = ast.List(elts=sub_blocks[-1],
-                                          ctx=ast.Load())
-
-                ## Replace the block with a call to 'irbloc'
-                lbl_if_name = ast.Attribute(value=ast.Name(id='lbl_if',
-                                                           ctx=ast.Load()),
-                                            attr='name', ctx=ast.Load())
-
-                sub_blocks[-1] = ast.Call(func=ast.Name(id='irbloc',
-                                                        ctx=ast.Load()),
-                                          args=[lbl_if_name,
-                                                sub_blocks[-1]],
-                                          keywords=[],
-                                          starargs=None,
-                                          kwargs=None)
-                blocks += sub_blocks
-                real_body += sub_body
+
+                    ## Replace the block with a call to 'irbloc'
+                    lbl_if_name = ast.Attribute(value=ast.Name(id=lbl_name,
+                                                               ctx=ast.Load()),
+                                                attr='name', ctx=ast.Load())
+
+                    sub_blocks[-1] = ast.Call(func=ast.Name(id='irbloc',
+                                                            ctx=ast.Load()),
+                                              args=[lbl_if_name,
+                                                    sub_blocks[-1]],
+                                              keywords=[],
+                                              starargs=None,
+                                              kwargs=None)
+                    blocks += sub_blocks
+                    real_body += sub_body
 
                 # Prepare a new block for following statement
                 blocks.append([[]])
@@ -255,6 +294,9 @@ class SemBuilder(object):
         fc_ast = parsed.body[0]
         argument_names = [name.id for name in fc_ast.args.args]
 
+        # Init local cache
+        self._local_ctx = {}
+
         # Translate (blocks[0][0] is the current instr)
         blocks, body = self._parse_body(fc_ast.body, argument_names)
 
diff --git a/miasm2/ir/symbexec.py b/miasm2/ir/symbexec.py
index f51baf9f..9ac79b1f 100644
--- a/miasm2/ir/symbexec.py
+++ b/miasm2/ir/symbexec.py
@@ -384,10 +384,7 @@ class symbexec(object):
                 # test if mem lookup is known
                 tmp = m2_expr.ExprMem(a, e.dst.size)
                 dst = tmp
-                if self.func_write and isinstance(dst.arg, m2_expr.ExprInt):
-                    self.func_write(self, dst, src, pool_out)
-                else:
-                    pool_out[dst] = src
+                pool_out[dst] = src
 
             elif isinstance(e.dst, m2_expr.ExprId):
                 pool_out[e.dst] = src
@@ -398,7 +395,6 @@ class symbexec(object):
 
     def eval_ir(self, ir):
         mem_dst = []
-        # src_dst = [(x.src, x.dst) for x in ir]
         src_dst = self.eval_ir_expr(ir)
         eval_cache = dict(self.symbols.items())
         for dst, src in src_dst:
@@ -411,10 +407,11 @@ class symbexec(object):
                         new_val.is_term = True
                         self.symbols[new_mem] = new_val
             src_o = self.expr_simp(src)
-            # print 'SRCo', src_o
-            # src_o.is_term = True
             self.symbols[dst] = src_o
             if isinstance(dst, m2_expr.ExprMem):
+                if self.func_write and isinstance(dst.arg, m2_expr.ExprInt):
+                    self.func_write(self, dst, src_o)
+                    del self.symbols[dst]
                 mem_dst.append(dst)
         return mem_dst
 
diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py
index 96db3a2b..e29c81c0 100644
--- a/miasm2/jitter/jitcore_python.py
+++ b/miasm2/jitter/jitcore_python.py
@@ -57,10 +57,8 @@ class JitCore_Python(jitcore.JitCore):
     def load(self):
         "Preload symbols according to current architecture"
 
-        symbols_init =  {}
-        for r in self.ir_arch.arch.regs.all_regs_ids_no_alias:
-            symbols_init[r] = self.ir_arch.arch.regs.regs_init[r]
-
+        symbols_init = {r:m2_expr.ExprInt(0, size=r.size)
+                        for r in self.ir_arch.arch.regs.all_regs_ids_no_alias}
         self.symbexec = symbexec(self.ir_arch, symbols_init,
                                  func_read = self.func_read,
                                  func_write = self.func_write)
@@ -76,12 +74,11 @@ class JitCore_Python(jitcore.JitCore):
         return m2_expr.ExprInt(int(value[::-1].encode("hex"), 16),
                                expr_mem.size)
 
-    def func_write(self, symb_exec, dest, data, mem_cache):
+    def func_write(self, symb_exec, dest, data):
         """Memory read wrapper for symbolic execution
         @symb_exec: symbexec instance
         @dest: ExprMem instance
-        @data: Expr instance
-        @mem_cache: dict"""
+        @data: Expr instance"""
 
         # Get the content to write
         data = expr_simp(data)
diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py
index 5721d72a..7d6260a2 100644
--- a/test/arch/x86/arch.py
+++ b/test/arch/x86/arch.py
@@ -832,6 +832,14 @@ reg_tests = [
      "0fb000"),
     (m32, "00000000    CMPXCHG    DWORD PTR [EAX], EAX",
      "0fb100"),
+    (m16, "00000000    CMPXCHG8B  QWORD PTR [SI+0x24]",
+     "0fc74c24"),
+    (m32, "00000000    CMPXCHG8B  QWORD PTR [ESP+0x8]",
+     "0fc74c2408"),
+    (m64, "00000000    CMPXCHG8B  QWORD PTR [RSP+0x8]",
+     "0fc74c2408"),
+    (m64, "00000000    CMPXCHG16B QWORD PTR [RSP+0x8]",
+     "480fc74c2408"),
 
     (m32, "00000000    CDQ",
      "99"),
diff --git a/test/arch/x86/qemu/testqemu.py b/test/arch/x86/qemu/testqemu.py
index 7cf2ab75..a7df4fe4 100644
--- a/test/arch/x86/qemu/testqemu.py
+++ b/test/arch/x86/qemu/testqemu.py
@@ -45,6 +45,7 @@ def xxx___printf_chk(jitter):
     fmt = get_str_ansi(jitter, args.format)
     # Manage llx
     fmt = fmt.replace("llx", "lx")
+    fmt = fmt.replace("%016lx", "%016z")
 
     fmt_a = parse_fmt(fmt)
     esp = jitter.cpu.ESP
@@ -61,11 +62,16 @@ def xxx___printf_chk(jitter):
             a2 = upck32(jitter.vm.get_mem(esp + 8 + 4*(i+1), 4))
             a = struct.unpack("d", struct.pack("Q", a2 << 32 | a))[0]
             i += 1
+        elif x.lower() == 'z':
+            a2 = upck32(jitter.vm.get_mem(esp + 8 + 4*(i+1), 4))
+            a = a2 << 32 | a
+            i += 1
         else:
             raise RuntimeError("Not implemented format")
         args.append(a)
         i += 1
 
+    fmt = fmt.replace("%016z", "%016lx")
     output = fmt%(tuple(args))
     # NaN bad repr in Python
     output = output.replace("nan", "-nan")
diff --git a/test/core/sembuilder.py b/test/core/sembuilder.py
index 468e3ef5..15fa67a4 100644
--- a/test/core/sembuilder.py
+++ b/test/core/sembuilder.py
@@ -13,9 +13,15 @@ class IR(object):
     def get_next_instr(self, _):
         return asm_label("NEXT")
 
+    def get_next_label(self, _):
+        return asm_label("NEXT")
+
     def gen_label(self):
         return asm_label("GEN")
 
+class Instr(object):
+    mode = 32
+
 # Test
 sb = SemBuilder(m2_expr.__dict__)
 
@@ -28,15 +34,18 @@ def test(Arg1, Arg2, Arg3):
     Arg3 = Arg3 if Arg2 else i32(0)
     tmpvar = 'myop'(i32(2))
     Arg2 = ('myopsize%d' % Arg1.size)(tmpvar, Arg1)
+    alias = Arg1[:24]
 
     if not Arg1:
         Arg2 = Arg3
+    else:
+        alias = {i16(4), i8(5)}
 
 a = m2_expr.ExprId('A')
 b = m2_expr.ExprId('B')
 c = m2_expr.ExprId('C')
 ir = IR()
-instr = None
+instr = Instr()
 res = test(ir, instr, a, b, c)
 
 print "[+] Returned:"
diff --git a/test/test_all.py b/test/test_all.py
index fe9c6880..94f3d8ca 100644
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -108,8 +108,9 @@ QEMU_TESTS = {
     "self_modifying_code": ("tcc", "python"),
     "conv": ("tcc", "python"),
     "bcd": ("tcc", "python"),
+    "xchg": ("tcc", "python"),
     # Unsupported
-    # "floats", "xchg", "string", "misc", "segs", "code16", "exceptions",
+    # "floats", "string", "misc", "segs", "code16", "exceptions",
     # "single_step"
 }