about summary refs log tree commit diff stats
path: root/miasm2/arch
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/arch')
-rw-r--r--miasm2/arch/aarch64/arch.py8
-rw-r--r--miasm2/arch/aarch64/regs.py3
-rw-r--r--miasm2/arch/aarch64/sem.py535
-rw-r--r--miasm2/arch/arm/jit.py10
-rw-r--r--miasm2/arch/arm/sem.py376
-rw-r--r--miasm2/arch/mep/arch.py5
-rw-r--r--miasm2/arch/x86/sem.py484
7 files changed, 1018 insertions, 403 deletions
diff --git a/miasm2/arch/aarch64/arch.py b/miasm2/arch/aarch64/arch.py
index 529621c4..8cb681f6 100644
--- a/miasm2/arch/aarch64/arch.py
+++ b/miasm2/arch/aarch64/arch.py
@@ -1839,6 +1839,14 @@ aarch64op("bics", [sf, bs('11'), bs('01010'), shift, bs('1'), rm_sft, imm6, rn,
 aarch64op("mov",  [sf, bs('01'), bs('01010'), bs('00'), bs('0'), rmz, bs('000000'), bs('11111'), rd], [rd, rmz], alias=True)
 
 
+aarch64op("adc", [sf, bs('00'), bs('11010000'), rm, bs('000000'), rn, rd], [rd, rn, rm])
+aarch64op("adcs", [sf, bs('01'), bs('11010000'), rm, bs('000000'), rn, rd], [rd, rn, rm])
+
+
+aarch64op("sbc", [sf, bs('10'), bs('11010000'), rm, bs('000000'), rn, rd], [rd, rn, rm])
+aarch64op("sbcs", [sf, bs('11'), bs('11010000'), rm, bs('000000'), rn, rd], [rd, rn, rm])
+
+
 
 bcond = bs_mod_name(l=4, fname='cond', mn_mod=['EQ', 'NE', 'CS', 'CC',
                                                'MI', 'PL', 'VS', 'VC',
diff --git a/miasm2/arch/aarch64/regs.py b/miasm2/arch/aarch64/regs.py
index c9da0653..85c8425a 100644
--- a/miasm2/arch/aarch64/regs.py
+++ b/miasm2/arch/aarch64/regs.py
@@ -1,6 +1,7 @@
 #-*- coding:utf-8 -*-
 
-from miasm2.expression.expression import *
+from miasm2.expression.expression import ExprId, ExprInt, ExprLoc, ExprMem, \
+    ExprSlice, ExprCond, ExprCompose, ExprOp
 from miasm2.core.cpu import gen_reg, gen_regs
 
 exception_flags = ExprId('exception_flags', 32)
diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py
index 646065f4..c8077ebf 100644
--- a/miasm2/arch/aarch64/sem.py
+++ b/miasm2/arch/aarch64/sem.py
@@ -1,4 +1,5 @@
-from miasm2.expression import expression as m2_expr
+from miasm2.expression.expression import ExprId, ExprInt, ExprLoc, ExprMem, \
+    ExprSlice, ExprCond, ExprCompose, ExprOp, ExprAff
 from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock
 from miasm2.arch.aarch64.arch import mn_aarch64, conds_expr, replace_regs
 from miasm2.arch.aarch64.regs import *
@@ -10,11 +11,20 @@ from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO, EXCEPT_INT_XX
 
 
 def update_flag_zf(a):
-    return [m2_expr.ExprAff(zf, m2_expr.ExprCond(a, m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)))]
+    return [ExprAff(zf, ExprOp("FLAG_EQ", a))]
 
 
-def update_flag_nf(a):
-    return [m2_expr.ExprAff(nf, a.msb())]
+def update_flag_zf_eq(a, b):
+    return [ExprAff(zf, ExprOp("FLAG_EQ_CMP", a, b))]
+
+
+def update_flag_nf(arg):
+    return [
+        ExprAff(
+            nf,
+            ExprOp("FLAG_SIGN_SUB", arg, ExprInt(0, arg.size))
+        )
+    ]
 
 
 def update_flag_zn(a):
@@ -24,103 +34,153 @@ def update_flag_zn(a):
     return e
 
 
-def update_flag_logic(a):
+def check_ops_msb(a, b, c):
+    if not a or not b or not c or a != b or a != c:
+        raise ValueError('bad ops size %s %s %s' % (a, b, c))
+
+
+def update_flag_add_cf(op1, op2):
+    "Compute cf in @op1 + @op2"
+    return [ExprAff(cf, ExprOp("FLAG_ADD_CF", op1, op2))]
+
+
+def update_flag_add_of(op1, op2):
+    "Compute of in @op1 + @op2"
+    return [ExprAff(of, ExprOp("FLAG_ADD_OF", op1, op2))]
+
+
+def update_flag_sub_cf(op1, op2):
+    "Compote CF in @op1 - @op2"
+    return [ExprAff(cf, ExprOp("FLAG_SUB_CF", op1, op2) ^ ExprInt(1, 1))]
+
+
+def update_flag_sub_of(op1, op2):
+    "Compote OF in @op1 - @op2"
+    return [ExprAff(of, ExprOp("FLAG_SUB_OF", op1, op2))]
+
+
+def update_flag_arith_add_co(arg1, arg2):
     e = []
-    e += update_flag_zn(a)
-    # XXX TODO: set cf if ROT imm in argument
-    # e.append(m2_expr.ExprAff(cf, m2_expr.ExprInt(0, 1)))
+    e += update_flag_add_cf(arg1, arg2)
+    e += update_flag_add_of(arg1, arg2)
     return e
 
 
-def update_flag_arith(a):
+def update_flag_arith_add_zn(arg1, arg2):
+    """
+    Compute zf and nf flags for (arg1 + arg2)
+    """
     e = []
-    e += update_flag_zn(a)
+    e += update_flag_zf_eq(arg1, -arg2)
+    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, -arg2))]
     return e
 
 
-def check_ops_msb(a, b, c):
-    if not a or not b or not c or a != b or a != c:
-        raise ValueError('bad ops size %s %s %s' % (a, b, c))
+def update_flag_arith_sub_co(arg1, arg2):
+    """
+    Compute cf and of flags for (arg1 - arg2)
+    """
+    e = []
+    e += update_flag_sub_cf(arg1, arg2)
+    e += update_flag_sub_of(arg1, arg2)
+    return e
 
 
-def arith_flag(a, b, c):
-    a_s, b_s, c_s = a.size, b.size, c.size
-    check_ops_msb(a_s, b_s, c_s)
-    a_s, b_s, c_s = a.msb(), b.msb(), c.msb()
-    return a_s, b_s, c_s
+def update_flag_arith_sub_zn(arg1, arg2):
+    """
+    Compute zf and nf flags for (arg1 - arg2)
+    """
+    e = []
+    e += update_flag_zf_eq(arg1, arg2)
+    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, arg2))]
+    return e
 
-# checked: ok for adc add because b & c before +cf
 
 
-def update_flag_add_cf(op1, op2, res):
-    "Compute cf in @res = @op1 + @op2"
-    return m2_expr.ExprAff(cf, (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (~(op1 ^ op2)))).msb())
 
+def update_flag_zfaddwc_eq(arg1, arg2, arg3):
+    return [ExprAff(zf, ExprOp("FLAG_EQ_ADDWC", arg1, arg2, arg3))]
 
-def update_flag_add_of(op1, op2, res):
-    "Compute of in @res = @op1 + @op2"
-    return m2_expr.ExprAff(of, (((op1 ^ res) & (~(op1 ^ op2)))).msb())
+def update_flag_zfsubwc_eq(arg1, arg2, arg3):
+    return [ExprAff(zf, ExprOp("FLAG_EQ_SUBWC", arg1, arg2, arg3))]
 
 
-# checked: ok for sbb add because b & c before +cf
-def update_flag_sub_cf(op1, op2, res):
-    "Compote CF in @res = @op1 - @op2"
-    return m2_expr.ExprAff(cf,
-                           ((((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb()) ^ m2_expr.ExprInt(1, 1))
+def update_flag_arith_addwc_zn(arg1, arg2, arg3):
+    """
+    Compute znp flags for (arg1 + arg2 + cf)
+    """
+    e = []
+    e += update_flag_zfaddwc_eq(arg1, arg2, arg3)
+    e += [ExprAff(nf, ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))]
+    return e
 
 
-def update_flag_sub_of(op1, op2, res):
-    "Compote OF in @res = @op1 - @op2"
-    return m2_expr.ExprAff(of, (((op1 ^ res) & (op1 ^ op2))).msb())
+def update_flag_arith_subwc_zn(arg1, arg2, arg3):
+    """
+    Compute znp flags for (arg1 - (arg2 + cf))
+    """
+    e = []
+    e += update_flag_zfsubwc_eq(arg1, arg2, arg3)
+    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))]
+    return e
 
 
-# clearing cv flags for bics (see C5.6.25)
+def update_flag_addwc_cf(op1, op2, op3):
+    "Compute cf in @res = @op1 + @op2 + @op3"
+    return [ExprAff(cf, ExprOp("FLAG_ADDWC_CF", op1, op2, op3))]
 
-def update_flag_bics ():
-    "Clear CF and OF"
-    return [ExprAff(cf, ExprInt (0,1)), ExprAff(of, ExprInt (0,1))]
 
-# z = x+y (+cf?)
+def update_flag_addwc_of(op1, op2, op3):
+    "Compute of in @res = @op1 + @op2 + @op3"
+    return [ExprAff(of, ExprOp("FLAG_ADDWC_OF", op1, op2, op3))]
 
 
-def update_flag_add(x, y, z):
+def update_flag_arith_addwc_co(arg1, arg2, arg3):
     e = []
-    e.append(update_flag_add_cf(x, y, z))
-    e.append(update_flag_add_of(x, y, z))
+    e += update_flag_addwc_cf(arg1, arg2, arg3)
+    e += update_flag_addwc_of(arg1, arg2, arg3)
     return e
 
-# z = x-y (+cf?)
 
 
-def update_flag_sub(x, y, z):
+def update_flag_subwc_cf(op1, op2, op3):
+    "Compute cf in @res = @op1 + @op2 + @op3"
+    return [ExprAff(cf, ExprOp("FLAG_SUBWC_CF", op1, op2, op3) ^ ExprInt(1, 1))]
+
+
+def update_flag_subwc_of(op1, op2, op3):
+    "Compute of in @res = @op1 + @op2 + @op3"
+    return [ExprAff(of, ExprOp("FLAG_SUBWC_OF", op1, op2, op3))]
+
+
+def update_flag_arith_subwc_co(arg1, arg2, arg3):
     e = []
-    e.append(update_flag_sub_cf(x, y, z))
-    e.append(update_flag_sub_of(x, y, z))
+    e += update_flag_subwc_cf(arg1, arg2, arg3)
+    e += update_flag_subwc_of(arg1, arg2, arg3)
     return e
 
 
-cond2expr = {'EQ': zf,
-             'NE': zf ^ m2_expr.ExprInt(1, 1),
-             'CS': cf,
-             'CC': cf ^ m2_expr.ExprInt(1, 1),
-             'MI': nf,
-             'PL': nf ^ m2_expr.ExprInt(1, 1),
-             'VS': of,
-             'VC': of ^ m2_expr.ExprInt(1, 1),
-             'HI': cf & (zf ^ m2_expr.ExprInt(1, 1)),
-             'LS': (cf ^ m2_expr.ExprInt(1, 1)) | zf,
-             'GE': nf ^ of ^ m2_expr.ExprInt(1, 1),
-             'LT': nf ^ of,
-             'GT': ((zf ^ m2_expr.ExprInt(1, 1)) &
-                    (nf ^ of ^ m2_expr.ExprInt(1, 1))),
-             'LE': zf | (nf ^ of),
-             'AL': m2_expr.ExprInt(1, 1),
-             'NV': m2_expr.ExprInt(0, 1)
+cond2expr = {'EQ': ExprOp("CC_EQ", zf),
+             'NE': ExprOp("CC_NE", zf),
+             'CS': ExprOp("CC_U>=", cf ^ ExprInt(1, 1)), # inv cf
+             'CC': ExprOp("CC_U<", cf ^ ExprInt(1, 1)), # inv cf
+             'MI': ExprOp("CC_NEG", nf),
+             'PL': ExprOp("CC_POS", nf),
+             'VS': ExprOp("CC_sOVR", of),
+             'VC': ExprOp("CC_sNOOVR", of),
+             'HI': ExprOp("CC_U>", cf ^ ExprInt(1, 1), zf), # inv cf
+             'LS': ExprOp("CC_U<=", cf ^ ExprInt(1, 1), zf), # inv cf
+             'GE': ExprOp("CC_S>=", nf, of),
+             'LT': ExprOp("CC_S<", nf, of),
+             'GT': ExprOp("CC_S>", nf, of, zf),
+             'LE': ExprOp("CC_S<=", nf, of, zf),
+             'AL': ExprInt(1, 1),
+             'NV': ExprInt(0, 1)
              }
 
 
 def extend_arg(dst, arg):
-    if not isinstance(arg, m2_expr.ExprOp):
+    if not isinstance(arg, ExprOp):
         return arg
 
     op, (reg, shift) = arg.op, arg.args
@@ -156,7 +216,7 @@ def extend_arg(dst, arg):
         raise NotImplementedError('Unknown shifter operator')
 
     out = ExprOp(op, base, (shift.zeroExtend(dst.size)
-                            & m2_expr.ExprInt(dst.size - 1, dst.size)))
+                            & ExprInt(dst.size - 1, dst.size)))
     return out
 
 
@@ -169,7 +229,7 @@ ctx = {"PC": PC,
        "of": of,
        "cond2expr": cond2expr,
        "extend_arg": extend_arg,
-       "m2_expr":m2_expr,
+       "ExprId":ExprId,
        "exception_flags": exception_flags,
        "interrupt_num": interrupt_num,
        "EXCEPT_DIV_BY_ZERO": EXCEPT_DIV_BY_ZERO,
@@ -228,9 +288,14 @@ def bic(arg1, arg2, arg3):
 
 def bics(ir, instr, arg1, arg2, arg3):
     e = []
-    arg1 = arg2 & (~extend_arg(arg2, arg3))
-    e += update_flag_logic (arg1)
-    e += update_flag_bics ()
+    tmp1, tmp2 = arg2, (~extend_arg(arg2, arg3))
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', tmp1, tmp2))]
+    e += update_flag_nf(res)
+
+    e.append(ExprAff(arg1, res))
+
+    e += null_flag_co()
     return e, []
 
 
@@ -243,9 +308,12 @@ def adds(ir, instr, arg1, arg2, arg3):
     e = []
     arg3 = extend_arg(arg2, arg3)
     res = arg2 + arg3
-    e += update_flag_arith(res)
-    e += update_flag_add(arg2, arg3, res)
-    e.append(m2_expr.ExprAff(arg1, res))
+
+    e += update_flag_arith_add_zn(arg2, arg3)
+    e += update_flag_arith_add_co(arg2, arg3)
+
+    e.append(ExprAff(arg1, res))
+
     return e, []
 
 
@@ -253,18 +321,22 @@ def subs(ir, instr, arg1, arg2, arg3):
     e = []
     arg3 = extend_arg(arg2, arg3)
     res = arg2 - arg3
-    e += update_flag_arith(res)
-    e += update_flag_sub(arg2, arg3, res)
-    e.append(m2_expr.ExprAff(arg1, res))
+
+
+    e += update_flag_arith_sub_zn(arg2, arg3)
+    e += update_flag_arith_sub_co(arg2, arg3)
+
+    e.append(ExprAff(arg1, res))
     return e, []
 
 
 def cmp(ir, instr, arg1, arg2):
     e = []
     arg2 = extend_arg(arg1, arg2)
-    res = arg1 - arg2
-    e += update_flag_arith(res)
-    e += update_flag_sub(arg1, arg2, res)
+
+    e += update_flag_arith_sub_zn(arg1, arg2)
+    e += update_flag_arith_sub_co(arg1, arg2)
+
     return e, []
 
 
@@ -272,8 +344,11 @@ def cmn(ir, instr, arg1, arg2):
     e = []
     arg2 = extend_arg(arg1, arg2)
     res = arg1 + arg2
-    e += update_flag_arith(res)
-    e += update_flag_add(arg1, arg2, res)
+
+
+    e += update_flag_arith_add_zn(arg1, arg2)
+    e += update_flag_arith_add_co(arg1, arg2)
+
     return e, []
 
 
@@ -281,32 +356,38 @@ def ands(ir, instr, arg1, arg2, arg3):
     e = []
     arg3 = extend_arg(arg2, arg3)
     res = arg2 & arg3
-    e += update_flag_logic(res)
-    e.append(m2_expr.ExprAff(arg1, res))
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', arg2, arg3))]
+    e += update_flag_nf(res)
+
+    e.append(ExprAff(arg1, res))
     return e, []
 
 def tst(ir, instr, arg1, arg2):
     e = []
     arg2 = extend_arg(arg1, arg2)
     res = arg1 & arg2
-    e += update_flag_logic(res)
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', arg1, arg2))]
+    e += update_flag_nf(res)
+
     return e, []
 
 
 @sbuild.parse
 def lsl(arg1, arg2, arg3):
-    arg1 = arg2 << (arg3 & m2_expr.ExprInt(arg3.size - 1, arg3.size))
+    arg1 = arg2 << (arg3 & ExprInt(arg3.size - 1, arg3.size))
 
 
 @sbuild.parse
 def lsr(arg1, arg2, arg3):
-    arg1 = arg2 >> (arg3 & m2_expr.ExprInt(arg3.size - 1, arg3.size))
+    arg1 = arg2 >> (arg3 & ExprInt(arg3.size - 1, arg3.size))
 
 
 @sbuild.parse
 def asr(arg1, arg2, arg3):
-    arg1 = m2_expr.ExprOp(
-        'a>>', arg2, (arg3 & m2_expr.ExprInt(arg3.size - 1, arg3.size)))
+    arg1 = ExprOp(
+        'a>>', arg2, (arg3 & ExprInt(arg3.size - 1, arg3.size)))
 
 
 @sbuild.parse
@@ -316,15 +397,15 @@ def mov(arg1, arg2):
 
 def movk(ir, instr, arg1, arg2):
     e = []
-    if isinstance(arg2, m2_expr.ExprOp):
+    if isinstance(arg2, ExprOp):
         assert(arg2.op == 'slice_at' and
-               isinstance(arg2.args[0], m2_expr.ExprInt) and
-               isinstance(arg2.args[1], m2_expr.ExprInt))
+               isinstance(arg2.args[0], ExprInt) and
+               isinstance(arg2.args[1], ExprInt))
         value, shift = int(arg2.args[0].arg), int(arg2.args[1])
         e.append(
-            m2_expr.ExprAff(arg1[shift:shift + 16], m2_expr.ExprInt(value, 16)))
+            ExprAff(arg1[shift:shift + 16], ExprInt(value, 16)))
     else:
-        e.append(m2_expr.ExprAff(arg1[:16], m2_expr.ExprInt(int(arg2), 16)))
+        e.append(ExprAff(arg1[:16], ExprInt(int(arg2), 16)))
 
     return e, []
 
@@ -343,7 +424,7 @@ def movn(arg1, arg2):
 def bl(arg1):
     PC = arg1
     ir.IRDst = arg1
-    LR = m2_expr.ExprInt(instr.offset + instr.l, 64)
+    LR = ExprInt(instr.offset + instr.l, 64)
 
 @sbuild.parse
 def csel(arg1, arg2, arg3, arg4):
@@ -353,7 +434,7 @@ def csel(arg1, arg2, arg3, arg4):
 def ccmp(ir, instr, arg1, arg2, arg3, arg4):
     e = []
     if(arg2.is_int):
-        arg2=m2_expr.ExprInt(arg2.arg.arg,arg1.size)
+        arg2=ExprInt(arg2.arg.arg,arg1.size)
     default_nf = arg3[0:1]
     default_zf = arg3[1:2]
     default_cf = arg3[2:3]
@@ -365,71 +446,102 @@ def ccmp(ir, instr, arg1, arg2, arg3, arg4):
     new_cf = update_flag_sub_cf(arg1, arg2, res).src
     new_of = update_flag_sub_of(arg1, arg2, res).src
 
-    e.append(m2_expr.ExprAff(nf, m2_expr.ExprCond(cond_expr,
+    e.append(ExprAff(nf, ExprCond(cond_expr,
                                                     new_nf,
                                                     default_nf)))
-    e.append(m2_expr.ExprAff(zf, m2_expr.ExprCond(cond_expr,
+    e.append(ExprAff(zf, ExprCond(cond_expr,
                                                     new_zf,
                                                     default_zf)))
-    e.append(m2_expr.ExprAff(cf, m2_expr.ExprCond(cond_expr,
+    e.append(ExprAff(cf, ExprCond(cond_expr,
                                                     new_cf,
                                                     default_cf)))
-    e.append(m2_expr.ExprAff(of, m2_expr.ExprCond(cond_expr,
+    e.append(ExprAff(of, ExprCond(cond_expr,
                                                     new_of,
                                                     default_of)))
     return e, []
 
-    
+
 def csinc(ir, instr, arg1, arg2, arg3, arg4):
     e = []
     cond_expr = cond2expr[arg4.name]
-    e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr,
-                                                    arg2,
-                                                    arg3 + m2_expr.ExprInt(1, arg3.size))))
+    e.append(
+        ExprAff(
+            arg1,
+            ExprCond(
+                cond_expr,
+                arg2,
+                arg3 + ExprInt(1, arg3.size)
+            )
+        )
+    )
     return e, []
 
 
 def csinv(ir, instr, arg1, arg2, arg3, arg4):
     e = []
     cond_expr = cond2expr[arg4.name]
-    e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr,
-                                                    arg2,
-                                                    ~arg3)))
+    e.append(
+        ExprAff(
+            arg1,
+            ExprCond(
+                cond_expr,
+                arg2,
+                ~arg3)
+        )
+    )
     return e, []
 
 
 def csneg(ir, instr, arg1, arg2, arg3, arg4):
     e = []
     cond_expr = cond2expr[arg4.name]
-    e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr,
-                                                    arg2,
-                                                    -arg3)))
+    e.append(
+        ExprAff(
+            arg1,
+            ExprCond(
+                cond_expr,
+                arg2,
+                -arg3)
+        )
+    )
     return e, []
 
 
 def cset(ir, instr, arg1, arg2):
     e = []
     cond_expr = cond2expr[arg2.name]
-    e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr,
-                                                    m2_expr.ExprInt(
-                                                        1, arg1.size),
-                                                    m2_expr.ExprInt(0, arg1.size))))
+    e.append(
+        ExprAff(
+            arg1,
+            ExprCond(
+                cond_expr,
+                ExprInt(1, arg1.size),
+                ExprInt(0, arg1.size)
+            )
+        )
+    )
     return e, []
 
 
 def csetm(ir, instr, arg1, arg2):
     e = []
     cond_expr = cond2expr[arg2.name]
-    e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr,
-                                                    m2_expr.ExprInt(
-                                                        -1, arg1.size),
-                                                    m2_expr.ExprInt(0, arg1.size))))
+    e.append(
+        ExprAff(
+            arg1,
+            ExprCond(
+                cond_expr,
+                ExprInt(-1, arg1.size),
+                ExprInt(0, arg1.size)
+            )
+        )
+    )
     return e, []
 
 
 def get_mem_access(mem):
     updt = None
-    if isinstance(mem, m2_expr.ExprOp):
+    if isinstance(mem, ExprOp):
         if mem.op == 'preinc':
             addr = mem.args[0] + mem.args[1]
         elif mem.op == 'segm':
@@ -442,7 +554,7 @@ def get_mem_access(mem):
                 off = reg.zeroExtend(base.size) << shift.zeroExtend(base.size)
                 addr = base + off
             elif op == 'LSL':
-                if isinstance(shift, m2_expr.ExprInt) and int(shift) == 0:
+                if isinstance(shift, ExprInt) and int(shift) == 0:
                     addr = base + reg.zeroExtend(base.size)
                 else:
                     addr = base + \
@@ -452,11 +564,11 @@ def get_mem_access(mem):
                 raise NotImplementedError('bad op')
         elif mem.op == "postinc":
             addr, off = mem.args
-            updt = m2_expr.ExprAff(addr, addr + off)
+            updt = ExprAff(addr, addr + off)
         elif mem.op == "preinc_wb":
             base, off = mem.args
             addr = base + off
-            updt = m2_expr.ExprAff(base, base + off)
+            updt = ExprAff(base, base + off)
         else:
             raise NotImplementedError('bad op')
     else:
@@ -468,7 +580,7 @@ def get_mem_access(mem):
 def ldr(ir, instr, arg1, arg2):
     e = []
     addr, updt = get_mem_access(arg2)
-    e.append(m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, arg1.size)))
+    e.append(ExprAff(arg1, ExprMem(addr, arg1.size)))
     if updt:
         e.append(updt)
     return e, []
@@ -478,7 +590,7 @@ def ldr_size(ir, instr, arg1, arg2, size):
     e = []
     addr, updt = get_mem_access(arg2)
     e.append(
-        m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, size).zeroExtend(arg1.size)))
+        ExprAff(arg1, ExprMem(addr, size).zeroExtend(arg1.size)))
     if updt:
         e.append(updt)
     return e, []
@@ -496,7 +608,7 @@ def ldrs_size(ir, instr, arg1, arg2, size):
     e = []
     addr, updt = get_mem_access(arg2)
     e.append(
-        m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, size).signExtend(arg1.size)))
+        ExprAff(arg1, ExprMem(addr, size).signExtend(arg1.size)))
     if updt:
         e.append(updt)
     return e, []
@@ -518,7 +630,7 @@ def ldrsw(ir, instr, arg1, arg2):
 def l_str(ir, instr, arg1, arg2):
     e = []
     addr, updt = get_mem_access(arg2)
-    e.append(m2_expr.ExprAff(m2_expr.ExprMem(addr, arg1.size), arg1))
+    e.append(ExprAff(ExprMem(addr, arg1.size), arg1))
     if updt:
         e.append(updt)
     return e, []
@@ -527,7 +639,7 @@ def l_str(ir, instr, arg1, arg2):
 def strb(ir, instr, arg1, arg2):
     e = []
     addr, updt = get_mem_access(arg2)
-    e.append(m2_expr.ExprAff(m2_expr.ExprMem(addr, 8), arg1[:8]))
+    e.append(ExprAff(ExprMem(addr, 8), arg1[:8]))
     if updt:
         e.append(updt)
     return e, []
@@ -536,7 +648,7 @@ def strb(ir, instr, arg1, arg2):
 def strh(ir, instr, arg1, arg2):
     e = []
     addr, updt = get_mem_access(arg2)
-    e.append(m2_expr.ExprAff(m2_expr.ExprMem(addr, 16), arg1[:16]))
+    e.append(ExprAff(ExprMem(addr, 16), arg1[:16]))
     if updt:
         e.append(updt)
     return e, []
@@ -545,9 +657,9 @@ def strh(ir, instr, arg1, arg2):
 def stp(ir, instr, arg1, arg2, arg3):
     e = []
     addr, updt = get_mem_access(arg3)
-    e.append(m2_expr.ExprAff(m2_expr.ExprMem(addr, arg1.size), arg1))
+    e.append(ExprAff(ExprMem(addr, arg1.size), arg1))
     e.append(
-        m2_expr.ExprAff(m2_expr.ExprMem(addr + m2_expr.ExprInt(arg1.size / 8, addr.size), arg2.size), arg2))
+        ExprAff(ExprMem(addr + ExprInt(arg1.size / 8, addr.size), arg2.size), arg2))
     if updt:
         e.append(updt)
     return e, []
@@ -556,9 +668,9 @@ def stp(ir, instr, arg1, arg2, arg3):
 def ldp(ir, instr, arg1, arg2, arg3):
     e = []
     addr, updt = get_mem_access(arg3)
-    e.append(m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, arg1.size)))
+    e.append(ExprAff(arg1, ExprMem(addr, arg1.size)))
     e.append(
-        m2_expr.ExprAff(arg2, m2_expr.ExprMem(addr + m2_expr.ExprInt(arg1.size / 8, addr.size), arg2.size)))
+        ExprAff(arg2, ExprMem(addr + ExprInt(arg1.size / 8, addr.size), arg2.size)))
     if updt:
         e.append(updt)
     return e, []
@@ -570,9 +682,9 @@ def sbfm(ir, instr, arg1, arg2, arg3, arg4):
     if sim > rim:
         res = arg2[rim:sim].signExtend(arg1.size)
     else:
-        shift = m2_expr.ExprInt(arg2.size - rim, arg2.size)
+        shift = ExprInt(arg2.size - rim, arg2.size)
         res = (arg2[:sim].signExtend(arg1.size) << shift)
-    e.append(m2_expr.ExprAff(arg1, res))
+    e.append(ExprAff(arg1, res))
     return e, []
 
 
@@ -582,9 +694,9 @@ def ubfm(ir, instr, arg1, arg2, arg3, arg4):
     if sim > rim:
         res = arg2[rim:sim].zeroExtend(arg1.size)
     else:
-        shift = m2_expr.ExprInt(arg2.size - rim, arg2.size)
+        shift = ExprInt(arg2.size - rim, arg2.size)
         res = (arg2[:sim].zeroExtend(arg1.size) << shift)
-    e.append(m2_expr.ExprAff(arg1, res))
+    e.append(ExprAff(arg1, res))
     return e, []
 
 def bfm(ir, instr, arg1, arg2, arg3, arg4):
@@ -592,12 +704,77 @@ def bfm(ir, instr, arg1, arg2, arg3, arg4):
     rim, sim = int(arg3.arg), int(arg4) + 1
     if sim > rim:
         res = arg2[rim:sim]
-        e.append(m2_expr.ExprAff(arg1[:sim-rim], res))
+        e.append(ExprAff(arg1[:sim-rim], res))
     else:
         shift_i = arg2.size - rim
-        shift = m2_expr.ExprInt(shift_i, arg2.size)
+        shift = ExprInt(shift_i, arg2.size)
         res = arg2[:sim]
-        e.append(m2_expr.ExprAff(arg1[shift_i:shift_i+sim], res))
+        e.append(ExprAff(arg1[shift_i:shift_i+sim], res))
+    return e, []
+
+
+
+def mrs(ir, insr, arg1, arg2, arg3, arg4, arg5):
+    e = []
+    if arg2.is_int(3) and arg3.is_id("c4") and arg4.is_id("c2") and arg5.is_int(0):
+        out = []
+        out.append(ExprInt(0x0, 28))
+        out.append(of)
+        out.append(cf)
+        out.append(zf)
+        out.append(nf)
+        e.append(ExprAff(arg1, ExprCompose(*out).zeroExtend(arg1.size)))
+    else:
+        raise NotImplementedError("MSR not implemented")
+    return e, []
+
+def msr(ir, instr, arg1, arg2, arg3, arg4, arg5):
+
+    e = []
+    if arg1.is_int(3) and arg2.is_id("c4") and arg3.is_id("c2") and arg4.is_int(0):
+        e.append(ExprAff(nf, arg5[31:32]))
+        e.append(ExprAff(zf, arg5[30:31]))
+        e.append(ExprAff(cf, arg5[29:30]))
+        e.append(ExprAff(of, arg5[28:29]))
+    else:
+        raise NotImplementedError("MRS not implemented")
+    return e, []
+
+
+
+def adc(ir, instr, arg1, arg2, arg3):
+    arg3 = extend_arg(arg2, arg3)
+    e = []
+    r = arg2 + arg3 + cf.zeroExtend(arg3.size)
+    e.append(ExprAff(arg1, r))
+    return e, []
+
+
+def adcs(ir, instr, arg1, arg2, arg3):
+    arg3 = extend_arg(arg2, arg3)
+    e = []
+    r = arg2 + arg3 + cf.zeroExtend(arg3.size)
+    e.append(ExprAff(arg1, r))
+    e += update_flag_arith_addwc_zn(arg2, arg3, cf)
+    e += update_flag_arith_addwc_co(arg2, arg3, cf)
+    return e, []
+
+
+def sbc(ir, instr, arg1, arg2, arg3):
+    arg3 = extend_arg(arg2, arg3)
+    e = []
+    r = arg2 - (arg3 + (~cf).zeroExtend(arg3.size))
+    e.append(ExprAff(arg1, r))
+    return e, []
+
+
+def sbcs(ir, instr, arg1, arg2, arg3):
+    arg3 = extend_arg(arg2, arg3)
+    e = []
+    r = arg2 - (arg3 + (~cf).zeroExtend(arg3.size))
+    e.append(ExprAff(arg1, r))
+    e += update_flag_arith_subwc_zn(arg2, arg3, ~cf)
+    e += update_flag_arith_subwc_co(arg2, arg3, ~cf)
     return e, []
 
 
@@ -614,30 +791,30 @@ def msub(arg1, arg2, arg3, arg4):
 @sbuild.parse
 def udiv(arg1, arg2, arg3):
     if arg3:
-        arg1 = m2_expr.ExprOp('udiv', arg2, arg3)
+        arg1 = ExprOp('udiv', arg2, arg3)
     else:
-        exception_flags = m2_expr.ExprInt(EXCEPT_DIV_BY_ZERO,
+        exception_flags = ExprInt(EXCEPT_DIV_BY_ZERO,
                                           exception_flags.size)
 
 
 @sbuild.parse
 def cbz(arg1, arg2):
-    dst = m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64) if arg1 else arg2
+    dst = ExprLoc(ir.get_next_loc_key(instr), 64) if arg1 else arg2
     PC = dst
     ir.IRDst = dst
 
 
 @sbuild.parse
 def cbnz(arg1, arg2):
-    dst = arg2 if arg1 else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg2 if arg1 else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
 
 @sbuild.parse
 def tbz(arg1, arg2, arg3):
-    bitmask = m2_expr.ExprInt(1, arg1.size) << arg2
-    dst = m2_expr.ExprLoc(
+    bitmask = ExprInt(1, arg1.size) << arg2
+    dst = ExprLoc(
         ir.get_next_loc_key(instr),
         64
     ) if arg1 & bitmask else arg3
@@ -647,8 +824,8 @@ def tbz(arg1, arg2, arg3):
 
 @sbuild.parse
 def tbnz(arg1, arg2, arg3):
-    bitmask = m2_expr.ExprInt(1, arg1.size) << arg2
-    dst = arg3 if arg1 & bitmask else m2_expr.ExprLoc(
+    bitmask = ExprInt(1, arg1.size) << arg2
+    dst = arg3 if arg1 & bitmask else ExprLoc(
         ir.get_next_loc_key(instr),
         64
     )
@@ -658,14 +835,16 @@ def tbnz(arg1, arg2, arg3):
 
 @sbuild.parse
 def b_ne(arg1):
-    dst = m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64) if zf else arg1
+    cond = cond2expr['NE']
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
 
 @sbuild.parse
 def b_eq(arg1):
-    dst = arg1 if zf else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    cond = cond2expr['EQ']
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -673,7 +852,7 @@ def b_eq(arg1):
 @sbuild.parse
 def b_ge(arg1):
     cond = cond2expr['GE']
-    dst = arg1 if cond else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -681,7 +860,7 @@ def b_ge(arg1):
 @sbuild.parse
 def b_gt(arg1):
     cond = cond2expr['GT']
-    dst = arg1 if cond else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -689,7 +868,7 @@ def b_gt(arg1):
 @sbuild.parse
 def b_cc(arg1):
     cond = cond2expr['CC']
-    dst = arg1 if cond else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -697,7 +876,7 @@ def b_cc(arg1):
 @sbuild.parse
 def b_cs(arg1):
     cond = cond2expr['CS']
-    dst = arg1 if cond else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -705,7 +884,7 @@ def b_cs(arg1):
 @sbuild.parse
 def b_hi(arg1):
     cond = cond2expr['HI']
-    dst = arg1 if cond else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -713,7 +892,7 @@ def b_hi(arg1):
 @sbuild.parse
 def b_le(arg1):
     cond = cond2expr['LE']
-    dst = arg1 if cond else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -721,7 +900,7 @@ def b_le(arg1):
 @sbuild.parse
 def b_ls(arg1):
     cond = cond2expr['LS']
-    dst = arg1 if cond else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -729,7 +908,7 @@ def b_ls(arg1):
 @sbuild.parse
 def b_lt(arg1):
     cond = cond2expr['LT']
-    dst = arg1 if cond else m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
     PC = dst
     ir.IRDst = dst
 
@@ -742,7 +921,7 @@ def ret(arg1):
 
 @sbuild.parse
 def adrp(arg1, arg2):
-    arg1 = (PC & m2_expr.ExprInt(0xfffffffffffff000, 64)) + arg2
+    arg1 = (PC & ExprInt(0xfffffffffffff000, 64)) + arg2
 
 
 @sbuild.parse
@@ -765,24 +944,34 @@ def br(arg1):
 def blr(arg1):
     PC = arg1
     ir.IRDst = arg1
-    LR = m2_expr.ExprLoc(ir.get_next_loc_key(instr), 64)
+    LR = ExprLoc(ir.get_next_loc_key(instr), 64)
 
 @sbuild.parse
 def nop():
     """Do nothing"""
 
 
+def rev(ir, instr, arg1, arg2):
+    out = []
+    for i in xrange(0, arg2.size, 8):
+        out.append(arg2[i:i+8])
+    out.reverse()
+    e = []
+    result = ExprCompose(*out)
+    e.append(ExprAff(arg1, result))
+    return e, []
+
 
 @sbuild.parse
 def extr(arg1, arg2, arg3, arg4):
-    compose = m2_expr.ExprCompose(arg2, arg3)
+    compose = ExprCompose(arg2, arg3)
     arg1 = compose[int(arg4.arg):int(arg4)+arg1.size]
 
 
 @sbuild.parse
 def svc(arg1):
-    exception_flags = m2_expr.ExprInt(EXCEPT_INT_XX, exception_flags.size)
-    interrupt_num = m2_expr.ExprInt(int(arg1), interrupt_num.size)
+    exception_flags = ExprInt(EXCEPT_INT_XX, exception_flags.size)
+    interrupt_num = ExprInt(int(arg1), interrupt_num.size)
 
 mnemo_func = sbuild.functions
 mnemo_func.update({
@@ -847,6 +1036,16 @@ mnemo_func.update({
     'ubfm': ubfm,
 
     'extr': extr,
+    'rev': rev,
+
+    'msr': msr,
+    'mrs': mrs,
+
+    'adc': adc,
+    'adcs': adcs,
+    'sbc': sbc,
+    'sbcs': sbcs,
+
 
 })
 
@@ -869,15 +1068,15 @@ class ir_aarch64l(IntermediateRepresentation):
         IntermediateRepresentation.__init__(self, mn_aarch64, "l", loc_db)
         self.pc = PC
         self.sp = SP
-        self.IRDst = m2_expr.ExprId('IRDst', 64)
+        self.IRDst = ExprId('IRDst', 64)
         self.addrsize = 64
 
     def get_ir(self, instr):
         args = instr.args
-        if len(args) and isinstance(args[-1], m2_expr.ExprOp):
+        if len(args) and isinstance(args[-1], ExprOp):
             if (args[-1].op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>'] and
-               isinstance(args[-1].args[-1], m2_expr.ExprId)):
-                args[-1] = m2_expr.ExprOp(args[-1].op,
+               isinstance(args[-1].args[-1], ExprId)):
+                args[-1] = ExprOp(args[-1].op,
                                           args[-1].args[0],
                                           args[-1].args[-1][:8].zeroExtend(32))
         instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
@@ -891,7 +1090,7 @@ class ir_aarch64l(IntermediateRepresentation):
     def expraff_fix_regs_for_mode(self, e):
         dst = self.expr_fix_regs_for_mode(e.dst)
         src = self.expr_fix_regs_for_mode(e.src)
-        return m2_expr.ExprAff(dst, src)
+        return ExprAff(dst, src)
 
     def irbloc_fix_regs_for_mode(self, irblock, mode=64):
         irs = []
@@ -901,7 +1100,7 @@ class ir_aarch64l(IntermediateRepresentation):
                 del(new_assignblk[dst])
                 # Special case for 64 bits:
                 # If destination is a 32 bit reg, zero extend the 64 bit reg
-                if (isinstance(dst, m2_expr.ExprId) and
+                if (isinstance(dst, ExprId) and
                     dst.size == 32 and
                     dst in replace_regs):
                     src = src.zeroExtend(64)
@@ -915,14 +1114,14 @@ class ir_aarch64l(IntermediateRepresentation):
 
     def mod_pc(self, instr, instr_ir, extra_ir):
         "Replace PC by the instruction's offset"
-        cur_offset = m2_expr.ExprInt(instr.offset, 64)
+        cur_offset = ExprInt(instr.offset, 64)
         pc_fixed = {self.pc: cur_offset}
         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] = m2_expr.ExprAff(dst, src)
+            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) \
@@ -953,4 +1152,4 @@ class ir_aarch64b(ir_aarch64l):
         IntermediateRepresentation.__init__(self, mn_aarch64, "b", loc_db)
         self.pc = PC
         self.sp = SP
-        self.IRDst = m2_expr.ExprId('IRDst', 64)
+        self.IRDst = ExprId('IRDst', 64)
diff --git a/miasm2/arch/arm/jit.py b/miasm2/arch/arm/jit.py
index 267bcea6..716a8826 100644
--- a/miasm2/arch/arm/jit.py
+++ b/miasm2/arch/arm/jit.py
@@ -8,6 +8,7 @@ from miasm2.jitter.codegen import CGen
 from miasm2.expression.expression import ExprId, ExprAff, ExprCond
 from miasm2.ir.ir import IRBlock, AssignBlock
 from miasm2.ir.translators.C import TranslatorC
+from miasm2.expression.simplifications import expr_simp_high_to_explicit
 
 log = logging.getLogger('jit_arm')
 hnd = logging.StreamHandler()
@@ -45,6 +46,15 @@ class arm_CGen(CGen):
             irblock_head = self.assignblk_to_irbloc(instr, assignblk_head)
             irblocks = [irblock_head] + assignblks_extra
 
+
+            # Simplify high level operators
+            out = []
+            for irblock in irblocks:
+                new_irblock = irblock.simplify(expr_simp_high_to_explicit)[1]
+                out.append(new_irblock)
+            irblocks = out
+
+
             for irblock in irblocks:
                 assert irblock.dst is not None
             irblocks_list.append(irblocks)
diff --git a/miasm2/arch/arm/sem.py b/miasm2/arch/arm/sem.py
index d9c2d6cd..4e99e720 100644
--- a/miasm2/arch/arm/sem.py
+++ b/miasm2/arch/arm/sem.py
@@ -14,11 +14,20 @@ EXCEPT_PRIV_INSN = (1 << 17)
 
 
 def update_flag_zf(a):
-    return [ExprAff(zf, ExprCond(a, ExprInt(0, 1), ExprInt(1, 1)))]
+    return [ExprAff(zf, ExprOp("FLAG_EQ", a))]
 
 
-def update_flag_nf(a):
-    return [ExprAff(nf, a.msb())]
+def update_flag_zf_eq(a, b):
+    return [ExprAff(zf, ExprOp("FLAG_EQ_CMP", a, b))]
+
+
+def update_flag_nf(arg):
+    return [
+        ExprAff(
+            nf,
+            ExprOp("FLAG_SIGN_SUB", arg, ExprInt(0, arg.size))
+        )
+    ]
 
 
 def update_flag_zn(a):
@@ -28,73 +37,136 @@ def update_flag_zn(a):
     return e
 
 
-def update_flag_logic(a):
+
+# XXX TODO: set cf if ROT imm in argument
+
+
+def check_ops_msb(a, b, c):
+    if not a or not b or not c or a != b or a != c:
+        raise ValueError('bad ops size %s %s %s' % (a, b, c))
+
+def update_flag_add_cf(op1, op2):
+    "Compute cf in @op1 + @op2"
+    return [ExprAff(cf, ExprOp("FLAG_ADD_CF", op1, op2))]
+
+
+def update_flag_add_of(op1, op2):
+    "Compute of in @op1 + @op2"
+    return [ExprAff(of, ExprOp("FLAG_ADD_OF", op1, op2))]
+
+
+def update_flag_sub_cf(op1, op2):
+    "Compote CF in @op1 - @op2"
+    return [ExprAff(cf, ExprOp("FLAG_SUB_CF", op1, op2) ^ ExprInt(1, 1))]
+
+
+def update_flag_sub_of(op1, op2):
+    "Compote OF in @op1 - @op2"
+    return [ExprAff(of, ExprOp("FLAG_SUB_OF", op1, op2))]
+
+
+def update_flag_arith_add_co(arg1, arg2):
     e = []
-    e += update_flag_zn(a)
-    # XXX TODO: set cf if ROT imm in argument
-    #e.append(ExprAff(cf, ExprInt(0, 1)))
+    e += update_flag_add_cf(arg1, arg2)
+    e += update_flag_add_of(arg1, arg2)
     return e
 
 
-def update_flag_arith(a):
+def update_flag_arith_add_zn(arg1, arg2):
+    """
+    Compute zf and nf flags for (arg1 + arg2)
+    """
     e = []
-    e += update_flag_zn(a)
+    e += update_flag_zf_eq(arg1, -arg2)
+    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, -arg2))]
     return e
 
 
-def check_ops_msb(a, b, c):
-    if not a or not b or not c or a != b or a != c:
-        raise ValueError('bad ops size %s %s %s' % (a, b, c))
+def update_flag_arith_sub_co(arg1, arg2):
+    """
+    Compute cf and of flags for (arg1 - arg2)
+    """
+    e = []
+    e += update_flag_sub_cf(arg1, arg2)
+    e += update_flag_sub_of(arg1, arg2)
+    return e
+
+
+def update_flag_arith_sub_zn(arg1, arg2):
+    """
+    Compute zf and nf flags for (arg1 - arg2)
+    """
+    e = []
+    e += update_flag_zf_eq(arg1, arg2)
+    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, arg2))]
+    return e
 
 
-def arith_flag(a, b, c):
-    a_s, b_s, c_s = a.size, b.size, c.size
-    check_ops_msb(a_s, b_s, c_s)
-    a_s, b_s, c_s = a.msb(), b.msb(), c.msb()
-    return a_s, b_s, c_s
 
-# checked: ok for adc add because b & c before +cf
 
-def update_flag_add_cf(op1, op2, res):
-    "Compute cf in @res = @op1 + @op2"
-    return ExprAff(cf, (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (~(op1 ^ op2)))).msb())
+def update_flag_zfaddwc_eq(arg1, arg2, arg3):
+    return [ExprAff(zf, ExprOp("FLAG_EQ_ADDWC", arg1, arg2, arg3))]
 
+def update_flag_zfsubwc_eq(arg1, arg2, arg3):
+    return [ExprAff(zf, ExprOp("FLAG_EQ_SUBWC", arg1, arg2, arg3))]
+
+
+def update_flag_arith_addwc_zn(arg1, arg2, arg3):
+    """
+    Compute znp flags for (arg1 + arg2 + cf)
+    """
+    e = []
+    e += update_flag_zfaddwc_eq(arg1, arg2, arg3)
+    e += [ExprAff(nf, ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))]
+    return e
 
-def update_flag_add_of(op1, op2, res):
-    "Compute of in @res = @op1 + @op2"
-    return ExprAff(of, (((op1 ^ res) & (~(op1 ^ op2)))).msb())
 
+def update_flag_arith_subwc_zn(arg1, arg2, arg3):
+    """
+    Compute znp flags for (arg1 - (arg2 + cf))
+    """
+    e = []
+    e += update_flag_zfsubwc_eq(arg1, arg2, arg3)
+    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))]
+    return e
 
-# checked: ok for sbb add because b & c before +cf
-def update_flag_sub_cf(op1, op2, res):
-    "Compote CF in @res = @op1 - @op2"
-    return ExprAff(cf,
-        ((((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb()) ^ ExprInt(1, 1))
 
+def update_flag_addwc_cf(op1, op2, op3):
+    "Compute cf in @res = @op1 + @op2 + @op3"
+    return [ExprAff(cf, ExprOp("FLAG_ADDWC_CF", op1, op2, op3))]
 
-def update_flag_sub_of(op1, op2, res):
-    "Compote OF in @res = @op1 - @op2"
-    return ExprAff(of, (((op1 ^ res) & (op1 ^ op2))).msb())
 
-# z = x+y (+cf?)
+def update_flag_addwc_of(op1, op2, op3):
+    "Compute of in @res = @op1 + @op2 + @op3"
+    return [ExprAff(of, ExprOp("FLAG_ADDWC_OF", op1, op2, op3))]
 
 
-def update_flag_add(x, y, z):
+def update_flag_arith_addwc_co(arg1, arg2, arg3):
     e = []
-    e.append(update_flag_add_cf(x, y, z))
-    e.append(update_flag_add_of(x, y, z))
+    e += update_flag_addwc_cf(arg1, arg2, arg3)
+    e += update_flag_addwc_of(arg1, arg2, arg3)
     return e
 
-# z = x-y (+cf?)
 
 
-def update_flag_sub(x, y, z):
+def update_flag_subwc_cf(op1, op2, op3):
+    "Compute cf in @res = @op1 + @op2 + @op3"
+    return [ExprAff(cf, ExprOp("FLAG_SUBWC_CF", op1, op2, op3) ^ ExprInt(1, 1))]
+
+
+def update_flag_subwc_of(op1, op2, op3):
+    "Compute of in @res = @op1 + @op2 + @op3"
+    return [ExprAff(of, ExprOp("FLAG_SUBWC_OF", op1, op2, op3))]
+
+
+def update_flag_arith_subwc_co(arg1, arg2, arg3):
     e = []
-    e.append(update_flag_sub_cf(x, y, z))
-    e.append(update_flag_sub_of(x, y, z))
+    e += update_flag_subwc_cf(arg1, arg2, arg3)
+    e += update_flag_subwc_of(arg1, arg2, arg3)
     return e
 
 
+
 def get_dst(a):
     if a == PC:
         return PC
@@ -107,10 +179,11 @@ def adc(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
+    arg1, arg2 = b, c
     r = b + c + cf.zeroExtend(32)
     if instr.name == 'ADCS' and a != PC:
-        e += update_flag_arith(r)
-        e += update_flag_add(b, c, r)
+        e += update_flag_arith_addwc_zn(arg1, arg2, cf)
+        e += update_flag_arith_addwc_co(arg1, arg2, cf)
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -122,10 +195,11 @@ def add(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
+    arg1, arg2 = b, c
     r = b + c
     if instr.name == 'ADDS' and a != PC:
-        e += update_flag_arith(r)
-        e += update_flag_add(b, c, r)
+        e += update_flag_arith_add_zn(arg1, arg2)
+        e += update_flag_arith_add_co(arg1, arg2)
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -139,7 +213,9 @@ def l_and(ir, instr, a, b, c=None):
         b, c = a, b
     r = b & c
     if instr.name == 'ANDS' and a != PC:
-        e += update_flag_logic(r)
+        e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', b, c))]
+        e += update_flag_nf(r)
+
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -163,9 +239,10 @@ def subs(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
+    arg1, arg2 = b, c
     r = b - c
-    e += update_flag_arith(r)
-    e += update_flag_sub(b, c, r)
+    e += update_flag_arith_sub_zn(arg1, arg2)
+    e += update_flag_arith_sub_co(arg1, arg2)
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -189,8 +266,12 @@ def eors(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
-    r = b ^ c
-    e += update_flag_logic(r)
+    arg1, arg2 = b, c
+    r = arg1 ^ arg2
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ_CMP', arg1, arg2))]
+    e += update_flag_nf(r)
+
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -214,9 +295,12 @@ def rsbs(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
-    r = c - b
-    e += update_flag_arith(r)
-    e += update_flag_sub(c, b, r)
+    arg1, arg2 = c, b
+    r = arg1 - arg2
+
+    e += update_flag_arith_sub_zn(arg1, arg2)
+    e += update_flag_arith_sub_co(arg1, arg2)
+
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -228,7 +312,8 @@ def sbc(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
-    r = (b + cf.zeroExtend(32)) - (c + ExprInt(1, 32))
+    arg1, arg2 = b, c
+    r = arg1 - (arg2 + (~cf).zeroExtend(32))
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -240,9 +325,12 @@ def sbcs(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
-    r = (b + cf.zeroExtend(32)) - (c + ExprInt(1, 32))
-    e += update_flag_arith(r)
-    e += update_flag_sub(b, c, r)
+    arg1, arg2 = b, c
+    r = arg1 - (arg2 + (~cf).zeroExtend(32))
+
+    e += update_flag_arith_subwc_zn(arg1, arg2, ~cf)
+    e += update_flag_arith_subwc_co(arg1, arg2, ~cf)
+
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -254,7 +342,8 @@ def rsc(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
-    r = (c + cf.zeroExtend(32)) - (b + ExprInt(1, 32))
+    arg1, arg2 = c, b
+    r = arg1 - (arg2 + (~cf).zeroExtend(32))
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -266,11 +355,14 @@ def rscs(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
-    r = (c + cf.zeroExtend(32)) - (b + ExprInt(1, 32))
-    e.append(ExprAff(a, r))
-    e += update_flag_arith(r)
-    e += update_flag_sub(c, b, r)
+    arg1, arg2 = c, b
+    r = arg1 - (arg2 + (~cf).zeroExtend(32))
+
+    e += update_flag_arith_subwc_zn(arg1, arg2, ~cf)
+    e += update_flag_arith_subwc_co(arg1, arg2, ~cf)
+
     e.append(ExprAff(a, r))
+
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
@@ -279,8 +371,12 @@ def rscs(ir, instr, a, b, c=None):
 
 def tst(ir, instr, a, b):
     e = []
-    r = a & b
-    e += update_flag_logic(r)
+    arg1, arg2 = a, b
+    r = arg1 & arg2
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', arg1, arg2))]
+    e += update_flag_nf(r)
+
     return e, []
 
 
@@ -288,8 +384,12 @@ def teq(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
-    r = b ^ c
-    e += update_flag_logic(r)
+    arg1, arg2 = b, c
+    r = arg1 ^ arg2
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ_CMP', arg1, arg2))]
+    e += update_flag_nf(r)
+
     return e, []
 
 
@@ -297,9 +397,12 @@ def l_cmp(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
+    arg1, arg2 = b, c
     r = b - c
-    e += update_flag_arith(r)
-    e += update_flag_sub(b, c, r)
+
+    e += update_flag_arith_sub_zn(arg1, arg2)
+    e += update_flag_arith_sub_co(arg1, arg2)
+
     return e, []
 
 
@@ -307,9 +410,12 @@ def cmn(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
+    arg1, arg2 = b, c
     r = b + c
-    e += update_flag_arith(r)
-    e += update_flag_add(b, c, r)
+
+    e += update_flag_arith_add_zn(arg1, arg2)
+    e += update_flag_arith_add_co(arg1, arg2)
+
     return e, []
 
 
@@ -341,8 +447,12 @@ def orrs(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
+    arg1, arg2 = b, c
     r = b | c
-    e += update_flag_logic(r)
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ', r))]
+    e += update_flag_nf(r)
+
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -371,7 +481,9 @@ def movs(ir, instr, a, b):
     e = []
     e.append(ExprAff(a, b))
     # XXX TODO check
-    e += update_flag_logic(b)
+    e += [ExprAff(zf, ExprOp('FLAG_EQ', b))]
+    e += update_flag_nf(b)
+
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, b))
@@ -392,13 +504,42 @@ def mvns(ir, instr, a, b):
     r = b ^ ExprInt(-1, 32)
     e.append(ExprAff(a, r))
     # XXX TODO check
-    e += update_flag_logic(r)
+    e += [ExprAff(zf, ExprOp('FLAG_EQ', r))]
+    e += update_flag_nf(r)
+
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
     return e, []
 
 
+
+def mrs(ir, instr, a, b):
+    e = []
+    if b.is_id('CPSR_cxsf'):
+        out = []
+        out.append(ExprInt(0x10, 28))
+        out.append(of)
+        out.append(cf)
+        out.append(zf)
+        out.append(nf)
+        e.append(ExprAff(a, ExprCompose(*out)))
+    else:
+        raise NotImplementedError("MSR not implemented")
+    return e, []
+
+def msr(ir, instr, a, b):
+    e = []
+    if a.is_id('CPSR_cf'):
+        e.append(ExprAff(nf, b[31:32]))
+        e.append(ExprAff(zf, b[30:31]))
+        e.append(ExprAff(cf, b[29:30]))
+        e.append(ExprAff(of, b[28:29]))
+    else:
+        raise NotImplementedError("MRS not implemented")
+    return e, []
+
+
 def neg(ir, instr, a, b):
     e = []
     r = - b
@@ -427,8 +568,12 @@ def bics(ir, instr, a, b, c=None):
     e = []
     if c is None:
         b, c = a, b
-    r = b & (c ^ ExprInt(-1, 32))
-    e += update_flag_logic(r)
+    tmp1, tmp2 = b, ~c
+    r = tmp1 & tmp2
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', tmp1, tmp2))]
+    e += update_flag_nf(r)
+
     e.append(ExprAff(a, r))
     dst = get_dst(a)
     if dst is not None:
@@ -836,7 +981,10 @@ def lsrs(ir, instr, a, b, c=None):
         b, c = a, b
     r = b >> c
     e.append(ExprAff(a, r))
-    e += update_flag_logic(r)
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ', r))]
+    e += update_flag_nf(r)
+
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
@@ -859,7 +1007,10 @@ def asrs(ir, instr, a, b, c=None):
         b, c = a, b
     r = ExprOp("a>>", b, c)
     e.append(ExprAff(a, r))
-    e += update_flag_logic(r)
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ', r))]
+    e += update_flag_nf(r)
+
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
@@ -883,7 +1034,10 @@ def lsls(ir, instr, a, b, c=None):
         b, c = a, b
     r = b << c
     e.append(ExprAff(a, r))
-    e += update_flag_logic(r)
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ', r))]
+    e += update_flag_nf(r)
+
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
@@ -894,7 +1048,10 @@ def rors(ir, instr, a, b):
     e = []
     r = ExprOp(">>>", a, b)
     e.append(ExprAff(a, r))
-    e += update_flag_logic(r)
+
+    e += [ExprAff(zf, ExprOp('FLAG_EQ', r))]
+    e += update_flag_nf(r)
+
     dst = get_dst(a)
     if dst is not None:
         e.append(ExprAff(ir.IRDst, r))
@@ -1223,31 +1380,46 @@ cond_dct = {
 
 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)),
-            COND_CS: cf,
-            COND_CC: ExprCond(cf, ExprInt(0, 1), ExprInt(1, 1)),
-            COND_MI: nf,
-            COND_PL: ExprCond(nf, ExprInt(0, 1), ExprInt(1, 1)),
-            COND_VS: of,
-            COND_VC: ExprCond(of, ExprInt(0, 1), ExprInt(1, 1)),
-            COND_HI: cf & ExprCond(zf, ExprInt(0, 1), ExprInt(1, 1)),
-            # COND_HI: cf,
-            # COND_HI: ExprOp('==',
-            #                ExprOp('|', cf, zf),
-            #                ExprInt(0, 1)),
-            COND_LS: ExprCond(cf, ExprInt(0, 1), ExprInt(1, 1)) | zf,
-            COND_GE: ExprCond(nf - of, ExprInt(0, 1), ExprInt(1, 1)),
-            COND_LT: nf ^ of,
-            # COND_GT: ExprOp('|',
-            #                ExprOp('==', zf, ExprInt(0, 1)) & (nf | of),
-            # ExprOp('==', nf, ExprInt(0, 1)) & ExprOp('==', of, ExprInt(0, 1))),
-            COND_GT: (ExprCond(zf, ExprInt(0, 1), ExprInt(1, 1)) &
-                      ExprCond(nf - of, ExprInt(0, 1), ExprInt(1, 1))),
-            COND_LE: zf | (nf ^ of),
+
+"""
+Code            Meaning (for cmp or subs)                                  Flags Tested
+eq              Equal.                                                     Z==1
+ne              Not equal.                                                 Z==0
+cs or hs        Unsigned higher or same (or carry set).                    C==1
+cc or lo        Unsigned lower (or carry clear).                           C==0
+mi              Negative. The mnemonic stands for "minus".                 N==1
+pl              Positive or zero. The mnemonic stands for "plus".          N==0
+vs              Signed overflow. The mnemonic stands for "V set".          V==1
+vc              No signed overflow. The mnemonic stands for "V clear".     V==0
+hi              Unsigned higher.                                           (C==1) && (Z==0)
+ls              Unsigned lower or same.                                    (C==0) || (Z==1)
+ge              Signed greater than or equal.                              N==V
+lt              Signed less than.                                          N!=V
+gt              Signed greater than.                                       (Z==0) && (N==V)
+le              Signed less than or equal.                                 (Z==1) || (N!=V)
+al (or omitted) Always executed.        None tested.
+"""
+
+tab_cond = {COND_EQ: ExprOp("CC_EQ", zf),
+            COND_NE: ExprOp("CC_NE", zf),
+            COND_CS: ExprOp("CC_U>=", cf ^ ExprInt(1, 1)), # inv cf
+            COND_CC: ExprOp("CC_U<", cf ^ ExprInt(1, 1)), # inv cf
+            COND_MI: ExprOp("CC_NEG", nf),
+            COND_PL: ExprOp("CC_POS", nf),
+            COND_VS: ExprOp("CC_sOVR", of),
+            COND_VC: ExprOp("CC_sNOOVR", of),
+            COND_HI: ExprOp("CC_U>", cf ^ ExprInt(1, 1), zf), # inv cf
+            COND_LS: ExprOp("CC_U<=", cf ^ ExprInt(1, 1), zf), # inv cf
+            COND_GE: ExprOp("CC_S>=", nf, of),
+            COND_LT: ExprOp("CC_S<", nf, of),
+            COND_GT: ExprOp("CC_S>", nf, of, zf),
+            COND_LE: ExprOp("CC_S<=", nf, of, zf),
             }
 
 
+
+
+
 def is_pc_written(ir, instr_ir):
     all_pc = ir.mn.pc.values()
     for ir in instr_ir:
@@ -1359,6 +1531,10 @@ mnemo_condm1 = {'adds': add,
                 'movs': movs,
                 'bics': bics,
                 'mvns': mvns,
+
+                'mrs': mrs,
+                'msr': msr,
+
                 'negs': negs,
 
                 'muls': muls,
diff --git a/miasm2/arch/mep/arch.py b/miasm2/arch/mep/arch.py
index 3f844c06..a4c7182a 100644
--- a/miasm2/arch/mep/arch.py
+++ b/miasm2/arch/mep/arch.py
@@ -939,7 +939,8 @@ class mep_target24_signed(mep_target24):
 
         mep_target24.decode(self, v)
         v = int(self.expr.arg)
-        self.expr = ExprInt(v, 24).signExtend(32)
+        self.expr = ExprInt(sign_ext(v, 24, 32), 32)
+
         return True
 
 
@@ -1160,7 +1161,7 @@ class mep_disp12_align2_signed(mep_disp12_align2):
         mep_disp12_align2.decode(self, v)
         v = int(self.expr.arg)
 
-        self.expr = ExprInt(v, 12).signExtend(32)
+        self.expr = ExprInt(sign_ext(v, 12, 32), 32)
         return True
 
 
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index 00bdd6d7..8c140d7b 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -59,16 +59,30 @@ OF(A-B) = ((A XOR D) AND (A XOR B)) < 0
 
 
 # XXX TODO make default check against 0 or not 0 (same eq as in C)
+def update_flag_zf_eq(a, b):
+    return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_CMP", a, b))]
 
 
 def update_flag_zf(a):
-    return [m2_expr.ExprAff(
-        zf, m2_expr.ExprCond(a, m2_expr.ExprInt(0, zf.size),
-                             m2_expr.ExprInt(1, zf.size)))]
+    return [
+        m2_expr.ExprAff(
+            zf,
+            m2_expr.ExprCond(
+                a,
+                m2_expr.ExprInt(0, zf.size),
+                m2_expr.ExprInt(1, zf.size)
+            )
+        )
+    ]
 
 
-def update_flag_nf(a):
-    return [m2_expr.ExprAff(nf, a.msb())]
+def update_flag_nf(arg):
+    return [
+        m2_expr.ExprAff(
+            nf,
+            m2_expr.ExprOp("FLAG_SIGN_SUB", arg, m2_expr.ExprInt(0, arg.size))
+        )
+    ]
 
 
 def update_flag_pf(a):
@@ -89,9 +103,15 @@ def update_flag_znp(a):
     return e
 
 
-def update_flag_logic(a):
+def update_flag_np(result):
+    e = []
+    e += update_flag_nf(result)
+    e += update_flag_pf(result)
+    return e
+
+
+def null_flag_co():
     e = []
-    e += update_flag_znp(a)
     e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, of.size)))
     e.append(m2_expr.ExprAff(cf, m2_expr.ExprInt(0, cf.size)))
     return e
@@ -103,6 +123,59 @@ def update_flag_arith(a):
     return e
 
 
+def update_flag_zfaddwc_eq(arg1, arg2, arg3):
+    return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_ADDWC", arg1, arg2, arg3))]
+
+def update_flag_zfsubwc_eq(arg1, arg2, arg3):
+    return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_SUBWC", arg1, arg2, arg3))]
+
+
+def update_flag_arith_add_znp(arg1, arg2):
+    """
+    Compute znp flags for (arg1 + arg2)
+    """
+    e = []
+    e += update_flag_zf_eq(arg1, -arg2)
+    e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg1, -arg2))]
+    e += update_flag_pf(arg1+arg2)
+    return e
+
+
+def update_flag_arith_addwc_znp(arg1, arg2, arg3):
+    """
+    Compute znp flags for (arg1 + arg2 + cf)
+    """
+    e = []
+    e += update_flag_zfaddwc_eq(arg1, arg2, arg3)
+    e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))]
+    e += update_flag_pf(arg1+arg2+arg3.zeroExtend(arg2.size))
+    return e
+
+
+
+
+def update_flag_arith_sub_znp(arg1, arg2):
+    """
+    Compute znp flags for (arg1 - arg2)
+    """
+    e = []
+    e += update_flag_zf_eq(arg1, arg2)
+    e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg1, arg2))]
+    e += update_flag_pf(arg1 - arg2)
+    return e
+
+
+def update_flag_arith_subwc_znp(arg1, arg2, arg3):
+    """
+    Compute znp flags for (arg1 - (arg2 + cf))
+    """
+    e = []
+    e += update_flag_zfsubwc_eq(arg1, arg2, arg3)
+    e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))]
+    e += update_flag_pf(arg1 - (arg2+arg3.zeroExtend(arg2.size)))
+    return e
+
+
 def check_ops_msb(a, b, c):
     if not a or not b or not c or a != b or a != c:
         raise ValueError('bad ops size %s %s %s' % (a, b, c))
@@ -119,45 +192,80 @@ def arith_flag(a, b, c):
 
 def update_flag_add_cf(op1, op2, res):
     "Compute cf in @res = @op1 + @op2"
-    ret = (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (~(op1 ^ op2)))).msb()
-    return m2_expr.ExprAff(cf, ret)
+    #return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUB_CF", op1, -op2))]
+    return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_ADD_CF", op1, op2))]
 
 
 def update_flag_add_of(op1, op2, res):
     "Compute of in @res = @op1 + @op2"
-    return m2_expr.ExprAff(of, (((op1 ^ res) & (~(op1 ^ op2)))).msb())
+    return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_ADD_OF", op1, op2))]
 
 
 # checked: ok for sbb add because b & c before +cf
 def update_flag_sub_cf(op1, op2, res):
     "Compote CF in @res = @op1 - @op2"
-    ret = (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb()
-    return m2_expr.ExprAff(cf, ret)
+    return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUB_CF", op1, op2))]
 
 
 def update_flag_sub_of(op1, op2, res):
     "Compote OF in @res = @op1 - @op2"
-    return m2_expr.ExprAff(of, (((op1 ^ res) & (op1 ^ op2))).msb())
+    return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_SUB_OF", op1, op2))]
+
+
+def update_flag_addwc_cf(op1, op2, op3):
+    "Compute cf in @res = @op1 + @op2 + @op3"
+    return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_ADDWC_CF", op1, op2, op3))]
+
+
+def update_flag_addwc_of(op1, op2, op3):
+    "Compute of in @res = @op1 + @op2 + @op3"
+    return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_ADDWC_OF", op1, op2, op3))]
 
-# z = x+y (+cf?)
 
 
-def update_flag_add(x, y, z):
+def update_flag_subwc_cf(op1, op2, op3):
+    "Compute cf in @res = @op1 + @op2 + @op3"
+    return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUBWC_CF", op1, op2, op3))]
+
+
+def update_flag_subwc_of(op1, op2, op3):
+    "Compute of in @res = @op1 + @op2 + @op3"
+    return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_SUBWC_OF", op1, op2, op3))]
+
+
+
+
+def update_flag_arith_add_co(x, y, z):
     e = []
-    e.append(update_flag_add_cf(x, y, z))
-    e.append(update_flag_add_of(x, y, z))
+    e += update_flag_add_cf(x, y, z)
+    e += update_flag_add_of(x, y, z)
     return e
 
-# z = x-y (+cf?)
+
+def update_flag_arith_sub_co(x, y, z):
+    e = []
+    e += update_flag_sub_cf(x, y, z)
+    e += update_flag_sub_of(x, y, z)
+    return e
+
+
 
 
-def update_flag_sub(x, y, z):
+def update_flag_arith_addwc_co(arg1, arg2, arg3):
     e = []
-    e.append(update_flag_sub_cf(x, y, z))
-    e.append(update_flag_sub_of(x, y, z))
+    e += update_flag_addwc_cf(arg1, arg2, arg3)
+    e += update_flag_addwc_of(arg1, arg2, arg3)
     return e
 
 
+def update_flag_arith_subwc_co(arg1, arg2, arg3):
+    e = []
+    e += update_flag_subwc_cf(arg1, arg2, arg3)
+    e += update_flag_subwc_of(arg1, arg2, arg3)
+    return e
+
+
+
 def set_float_cs_eip(instr):
     e = []
     # XXX TODO check float updt
@@ -344,20 +452,23 @@ def lea(_, instr, dst, src):
 
 def add(_, instr, dst, src):
     e = []
+
     result = dst + src
-    e += update_flag_arith(result)
+
+    e += update_flag_arith_add_znp(dst, src)
+    e += update_flag_arith_add_co(dst, src, result)
     e += update_flag_af(dst, src, result)
-    e += update_flag_add(dst, src, result)
     e.append(m2_expr.ExprAff(dst, result))
     return e, []
 
 
 def xadd(_, instr, dst, src):
     e = []
+
     result = dst + src
-    e += update_flag_arith(result)
+    e += update_flag_arith_add_znp(dst, src)
+    e += update_flag_arith_add_co(src, dst, result)
     e += update_flag_af(dst, src, result)
-    e += update_flag_add(src, dst, result)
     if dst != src:
         e.append(m2_expr.ExprAff(src, dst))
     e.append(m2_expr.ExprAff(dst, result))
@@ -366,21 +477,27 @@ def xadd(_, instr, dst, src):
 
 def adc(_, instr, dst, src):
     e = []
-    result = dst + (src + m2_expr.ExprCompose(cf,
-                                              m2_expr.ExprInt(0, dst.size - 1)))
-    e += update_flag_arith(result)
-    e += update_flag_af(dst, src, result)
-    e += update_flag_add(dst, src, result)
+
+    arg1 = dst
+    arg2 = src
+    result = arg1 + (arg2 + cf.zeroExtend(src.size))
+
+    e += update_flag_arith_addwc_znp(arg1, arg2, cf)
+    e += update_flag_arith_addwc_co(arg1, arg2, cf)
+    e += update_flag_af(arg1, arg2, result)
     e.append(m2_expr.ExprAff(dst, result))
     return e, []
 
 
 def sub(_, instr, dst, src):
     e = []
+    arg1, arg2 = dst, src
     result = dst - src
-    e += update_flag_arith(result)
+
+    e += update_flag_arith_sub_znp(arg1, arg2)
+    e += update_flag_arith_sub_co(arg1, arg2, result)
     e += update_flag_af(dst, src, result)
-    e += update_flag_sub(dst, src, result)
+
     e.append(m2_expr.ExprAff(dst, result))
     return e, []
 
@@ -389,11 +506,13 @@ def sub(_, instr, dst, src):
 
 def sbb(_, instr, dst, src):
     e = []
-    result = dst - (src + m2_expr.ExprCompose(cf,
-                                              m2_expr.ExprInt(0, dst.size - 1)))
-    e += update_flag_arith(result)
-    e += update_flag_af(dst, src, result)
-    e += update_flag_sub(dst, src, result)
+    arg1 = dst
+    arg2 = src
+    result = arg1 - (arg2 + cf.zeroExtend(src.size))
+
+    e += update_flag_arith_subwc_znp(arg1, arg2, cf)
+    e += update_flag_af(arg1, arg2, result)
+    e += update_flag_arith_subwc_co(arg1, arg2, cf)
     e.append(m2_expr.ExprAff(dst, result))
     return e, []
 
@@ -401,10 +520,12 @@ def sbb(_, instr, dst, src):
 def neg(_, instr, src):
     e = []
     dst = m2_expr.ExprInt(0, src.size)
-    result = dst - src
-    e += update_flag_arith(result)
-    e += update_flag_sub(dst, src, result)
-    e += update_flag_af(dst, src, result)
+    arg1, arg2 = dst, src
+    result = arg1 - arg2
+
+    e += update_flag_arith_sub_znp(arg1, arg2)
+    e += update_flag_arith_sub_co(arg1, arg2, result)
+    e += update_flag_af(arg1, arg2, result)
     e.append(m2_expr.ExprAff(src, result))
     return (e, [])
 
@@ -418,9 +539,11 @@ def l_not(_, instr, dst):
 
 def l_cmp(_, instr, dst, src):
     e = []
+    arg1, arg2 = dst, src
     result = dst - src
-    e += update_flag_arith(result)
-    e += update_flag_sub(dst, src, result)
+
+    e += update_flag_arith_sub_znp(arg1, arg2)
+    e += update_flag_arith_sub_co(arg1, arg2, result)
     e += update_flag_af(dst, src, result)
     return (e, [])
 
@@ -428,7 +551,9 @@ def l_cmp(_, instr, dst, src):
 def xor(_, instr, dst, src):
     e = []
     result = dst ^ src
-    e += update_flag_logic(result)
+    e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_CMP', dst, src))]
+    e += update_flag_np(result)
+    e += null_flag_co()
     e.append(m2_expr.ExprAff(dst, result))
     return (e, [])
 
@@ -443,7 +568,9 @@ def pxor(_, instr, dst, src):
 def l_or(_, instr, dst, src):
     e = []
     result = dst | src
-    e += update_flag_logic(result)
+    e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ', dst | src))]
+    e += update_flag_np(result)
+    e += null_flag_co()
     e.append(m2_expr.ExprAff(dst, result))
     return (e, [])
 
@@ -451,7 +578,10 @@ def l_or(_, instr, dst, src):
 def l_and(_, instr, dst, src):
     e = []
     result = dst & src
-    e += update_flag_logic(result)
+    e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_AND', dst, src))]
+    e += update_flag_np(result)
+    e += null_flag_co()
+
     e.append(m2_expr.ExprAff(dst, result))
     return (e, [])
 
@@ -459,7 +589,12 @@ def l_and(_, instr, dst, src):
 def l_test(_, instr, dst, src):
     e = []
     result = dst & src
-    e += update_flag_logic(result)
+
+    e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_CMP', result, m2_expr.ExprInt(0, result.size)))]
+    e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", result, m2_expr.ExprInt(0, result.size)))]
+    e += update_flag_pf(result)
+    e += null_flag_co()
+
     return (e, [])
 
 
@@ -717,23 +852,27 @@ def sti(_, instr):
 def inc(_, instr, dst):
     e = []
     src = m2_expr.ExprInt(1, dst.size)
+    arg1, arg2 = dst, src
     result = dst + src
-    e += update_flag_arith(result)
-    e += update_flag_af(dst, src, result)
 
-    e.append(update_flag_add_of(dst, src, result))
+    e += update_flag_arith_add_znp(arg1, arg2)
+    e += update_flag_af(arg1, arg2, result)
+    e += update_flag_add_of(arg1, arg2, result)
+
     e.append(m2_expr.ExprAff(dst, result))
     return e, []
 
 
 def dec(_, instr, dst):
     e = []
-    src = m2_expr.ExprInt(-1, dst.size)
-    result = dst + src
-    e += update_flag_arith(result)
-    e += update_flag_af(dst, src, ~result)
+    src = m2_expr.ExprInt(1, dst.size)
+    arg1, arg2 = dst, src
+    result = dst - src
+
+    e += update_flag_arith_sub_znp(arg1, arg2)
+    e += update_flag_af(arg1, arg2, result)
+    e += update_flag_sub_of(arg1, arg2, result)
 
-    e.append(update_flag_add_of(dst, src, result))
     e.append(m2_expr.ExprAff(dst, result))
     return e, []
 
@@ -796,16 +935,22 @@ def popw(ir, instr, src):
 def sete(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(zf, m2_expr.ExprInt(1, dst.size),
-                                              m2_expr.ExprInt(0, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_EQ", zf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setnz(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(zf, m2_expr.ExprInt(0, dst.size),
-                                              m2_expr.ExprInt(1, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_EQ", ~zf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
@@ -813,17 +958,21 @@ def setl(_, instr, dst):
     e = []
     e.append(
         m2_expr.ExprAff(
-            dst, m2_expr.ExprCond(nf - of, m2_expr.ExprInt(1, dst.size),
-                                  m2_expr.ExprInt(0, dst.size))))
+            dst,
+            m2_expr.ExprOp("CC_S<", nf, of).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setg(_, instr, dst):
     e = []
-    a0 = m2_expr.ExprInt(0, dst.size)
-    a1 = m2_expr.ExprInt(1, dst.size)
-    ret = m2_expr.ExprCond(zf, a0, a1) & m2_expr.ExprCond(nf - of, a0, a1)
-    e.append(m2_expr.ExprAff(dst, ret))
+    e.append(
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_S>", nf, of, zf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
@@ -831,128 +980,172 @@ def setge(_, instr, dst):
     e = []
     e.append(
         m2_expr.ExprAff(
-            dst, m2_expr.ExprCond(nf - of, m2_expr.ExprInt(0, dst.size),
-                                  m2_expr.ExprInt(1, dst.size))))
+            dst,
+            m2_expr.ExprOp("CC_S>=", nf, of).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def seta(_, instr, dst):
     e = []
-    e.append(m2_expr.ExprAff(dst, m2_expr.ExprCond(cf | zf,
-                                                   m2_expr.ExprInt(
-                                                       0, dst.size),
-                                                   m2_expr.ExprInt(1, dst.size))))
-
+    e.append(
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_U>", cf, zf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setae(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(cf, m2_expr.ExprInt(0, dst.size),
-                                              m2_expr.ExprInt(1, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_U>=", cf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setb(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(cf, m2_expr.ExprInt(1, dst.size),
-                                              m2_expr.ExprInt(0, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_U<", cf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setbe(_, instr, dst):
     e = []
-    e.append(m2_expr.ExprAff(dst, m2_expr.ExprCond(cf | zf,
-                                                   m2_expr.ExprInt(
-                                                       1, dst.size),
-                                                   m2_expr.ExprInt(0, dst.size)))
-             )
+    e.append(
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_U<=", cf, zf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setns(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(nf, m2_expr.ExprInt(0, dst.size),
-                                              m2_expr.ExprInt(1, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_NEG", ~nf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def sets(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(nf, m2_expr.ExprInt(1, dst.size),
-                                              m2_expr.ExprInt(0, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_NEG", nf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def seto(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(of, m2_expr.ExprInt(1, dst.size),
-                                              m2_expr.ExprInt(0, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            of.zeroExtend(dst.size)
+        )
+    )
     return e, []
 
 
 def setp(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(pf, m2_expr.ExprInt(1, dst.size),
-                                              m2_expr.ExprInt(0, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            pf.zeroExtend(dst.size)
+        )
+    )
     return e, []
 
 
 def setnp(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(pf, m2_expr.ExprInt(0, dst.size),
-                                              m2_expr.ExprInt(1, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprCond(
+                pf,
+                m2_expr.ExprInt(0, dst.size),
+                m2_expr.ExprInt(1, dst.size)
+            )
+        )
+    )
     return e, []
 
 
 def setle(_, instr, dst):
     e = []
-    a0 = m2_expr.ExprInt(0, dst.size)
-    a1 = m2_expr.ExprInt(1, dst.size)
-    ret = m2_expr.ExprCond(zf, a1, a0) | m2_expr.ExprCond(nf ^ of, a1, a0)
-    e.append(m2_expr.ExprAff(dst, ret))
+    e.append(
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_S<=", nf, of, zf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setna(_, instr, dst):
     e = []
-    a0 = m2_expr.ExprInt(0, dst.size)
-    a1 = m2_expr.ExprInt(1, dst.size)
-    ret = m2_expr.ExprCond(cf, a1, a0) & m2_expr.ExprCond(zf, a1, a0)
-    e.append(m2_expr.ExprAff(dst, ret))
+    e.append(
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_U<=", cf, zf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setnbe(_, instr, dst):
     e = []
-    e.append(m2_expr.ExprAff(dst, m2_expr.ExprCond(cf | zf,
-                                                   m2_expr.ExprInt(
-                                                       0, dst.size),
-                                                   m2_expr.ExprInt(1, dst.size)))
-             )
+    e.append(
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_U>", cf, zf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
 def setno(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(of, m2_expr.ExprInt(0, dst.size),
-                                              m2_expr.ExprInt(1, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprCond(
+                of,
+                m2_expr.ExprInt(0, dst.size),
+                m2_expr.ExprInt(1, dst.size)
+            )
+        )
+    )
     return e, []
 
 
 def setnb(_, instr, dst):
     e = []
     e.append(
-        m2_expr.ExprAff(dst, m2_expr.ExprCond(cf, m2_expr.ExprInt(0, dst.size),
-                                              m2_expr.ExprInt(1, dst.size))))
+        m2_expr.ExprAff(
+            dst,
+            m2_expr.ExprOp("CC_U>=", cf).zeroExtend(dst.size),
+        )
+    )
     return e, []
 
 
@@ -1358,7 +1551,8 @@ def jmp(ir, instr, dst):
 
 
 def jz(ir, instr, dst):
-    return gen_jcc(ir, instr, zf, dst, True)
+    #return gen_jcc(ir, instr, zf, dst, True)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, True)
 
 
 def jcxz(ir, instr, dst):
@@ -1374,7 +1568,9 @@ def jrcxz(ir, instr, dst):
 
 
 def jnz(ir, instr, dst):
-    return gen_jcc(ir, instr, zf, dst, False)
+    #return gen_jcc(ir, instr, zf, dst, False)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, False)
+
 
 
 def jp(ir, instr, dst):
@@ -1386,43 +1582,55 @@ def jnp(ir, instr, dst):
 
 
 def ja(ir, instr, dst):
-    return gen_jcc(ir, instr, cf | zf, dst, False)
+    #return gen_jcc(ir, instr, cf | zf, dst, False)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U>", cf, zf), dst, True)
 
 
 def jae(ir, instr, dst):
-    return gen_jcc(ir, instr, cf, dst, False)
+    #return gen_jcc(ir, instr, cf, dst, False)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U>=", cf), dst, True)
 
 
 def jb(ir, instr, dst):
-    return gen_jcc(ir, instr, cf, dst, True)
+    #return gen_jcc(ir, instr, cf, dst, True)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U<", cf), dst, True)
 
 
 def jbe(ir, instr, dst):
-    return gen_jcc(ir, instr, cf | zf, dst, True)
+    #return gen_jcc(ir, instr, cf | zf, dst, True)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U<=", cf, zf), dst, True)
 
 
 def jge(ir, instr, dst):
-    return gen_jcc(ir, instr, nf - of, dst, False)
+    #return gen_jcc(ir, instr, nf - of, dst, False)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S>=", nf, of), dst, True)
 
 
 def jg(ir, instr, dst):
-    return gen_jcc(ir, instr, zf | (nf - of), dst, False)
+    #return gen_jcc(ir, instr, zf | (nf - of), dst, False)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S>", nf, of, zf), dst, True)
 
 
 def jl(ir, instr, dst):
-    return gen_jcc(ir, instr, nf - of, dst, True)
+    #return gen_jcc(ir, instr, nf - of, dst, True)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S<", nf, of), dst, True)
 
 
 def jle(ir, instr, dst):
-    return gen_jcc(ir, instr, zf | (nf - of), dst, True)
+    #return gen_jcc(ir, instr, zf | (nf - of), dst, True)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S<=", nf, of, zf), dst, True)
+
 
 
 def js(ir, instr, dst):
-    return gen_jcc(ir, instr, nf, dst, True)
+    #return gen_jcc(ir, instr, nf, dst, True)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, True)
+
 
 
 def jns(ir, instr, dst):
-    return gen_jcc(ir, instr, nf, dst, False)
+    #return gen_jcc(ir, instr, nf, dst, False)
+    return gen_jcc(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, False)
 
 
 def jo(ir, instr, dst):
@@ -2957,11 +3165,13 @@ def sldt(_, instr, dst):
 
 
 def cmovz(ir, instr, dst, src):
-    return gen_cmov(ir, instr, zf, dst, src, True)
+    #return gen_cmov(ir, instr, zf, dst, src, True)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, src, True)
 
 
 def cmovnz(ir, instr, dst, src):
-    return gen_cmov(ir, instr, zf, dst, src, False)
+    #return gen_cmov(ir, instr, zf, dst, src, False)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, src, False)
 
 
 def cmovpe(ir, instr, dst, src):
@@ -2973,35 +3183,43 @@ def cmovnp(ir, instr, dst, src):
 
 
 def cmovge(ir, instr, dst, src):
-    return gen_cmov(ir, instr, nf ^ of, dst, src, False)
+    #return gen_cmov(ir, instr, nf ^ of, dst, src, False)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S>=", nf, of), dst, src, True)
 
 
 def cmovg(ir, instr, dst, src):
-    return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, False)
+    #return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, False)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S>", nf, of, zf), dst, src, True)
 
 
 def cmovl(ir, instr, dst, src):
-    return gen_cmov(ir, instr, nf ^ of, dst, src, True)
+    #return gen_cmov(ir, instr, nf ^ of, dst, src, True)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S<", nf, of), dst, src, True)
 
 
 def cmovle(ir, instr, dst, src):
-    return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, True)
+    #return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, True)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S<=", nf, of, zf), dst, src, True)
 
 
 def cmova(ir, instr, dst, src):
-    return gen_cmov(ir, instr, cf | zf, dst, src, False)
+    #return gen_cmov(ir, instr, cf | zf, dst, src, False)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U>", cf, zf), dst, src, True)
 
 
 def cmovae(ir, instr, dst, src):
-    return gen_cmov(ir, instr, cf, dst, src, False)
+    #return gen_cmov(ir, instr, cf, dst, src, False)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U>=", cf), dst, src, True)
 
 
 def cmovbe(ir, instr, dst, src):
-    return gen_cmov(ir, instr, cf | zf, dst, src, True)
+    #return gen_cmov(ir, instr, cf | zf, dst, src, True)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U<=", cf, zf), dst, src, True)
 
 
 def cmovb(ir, instr, dst, src):
-    return gen_cmov(ir, instr, cf, dst, src, True)
+    #return gen_cmov(ir, instr, cf, dst, src, True)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U<", cf), dst, src, True)
 
 
 def cmovo(ir, instr, dst, src):
@@ -3013,11 +3231,13 @@ def cmovno(ir, instr, dst, src):
 
 
 def cmovs(ir, instr, dst, src):
-    return gen_cmov(ir, instr, nf, dst, src, True)
+    #return gen_cmov(ir, instr, nf, dst, src, True)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, src, True)
 
 
 def cmovns(ir, instr, dst, src):
-    return gen_cmov(ir, instr, nf, dst, src, False)
+    #return gen_cmov(ir, instr, nf, dst, src, False)
+    return gen_cmov(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, src, False)
 
 
 def icebp(_, instr):