about summary refs log tree commit diff stats
path: root/miasm2/arch/x86/sem.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--miasm2/arch/x86/sem.py1327
1 files changed, 787 insertions, 540 deletions
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index f99d2d9d..c0dff4fd 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -54,18 +54,6 @@ OF(A-B) = ((A XOR D) AND (A XOR B)) < 0
 """
 
 
-float_list = [
-    m2_expr.ExprId("ST", 64),
-    m2_expr.ExprId("ST(0)", 64),
-    m2_expr.ExprId("ST(1)", 64),
-    m2_expr.ExprId("ST(2)", 64),
-    m2_expr.ExprId("ST(3)", 64),
-    m2_expr.ExprId("ST(4)", 64),
-    m2_expr.ExprId("ST(5)", 64),
-    m2_expr.ExprId("ST(6)", 64),
-    m2_expr.ExprId("ST(7)", 64),
-]
-
 
 # XXX TODO make default check against 0 or not 0 (same eq as in C)
 
@@ -176,6 +164,92 @@ def set_float_cs_eip(instr):
     e.append(m2_expr.ExprAff(float_cs, CS))
     return e
 
+def mem2double(arg):
+    """
+    Add float convertion if argument is an ExprMem
+    @arg: argument to tranform
+    """
+    if isinstance(arg, m2_expr.ExprMem):
+        if arg.size > 64:
+            raise NotImplementedError('float to long')
+        return m2_expr.ExprOp('mem_%.2d_to_double' % arg.size, arg)
+    else:
+        return arg
+
+def float_implicit_st0(arg1, arg2):
+    """
+    Generate full float operators if one argument is implicit (float_st0)
+    """
+    if arg2 is None:
+        arg2 = arg1
+        arg1 = float_st0
+    return arg1, arg2
+
+
+def gen_jcc(ir, instr, cond, dst, jmp_if):
+    """
+    Macro to generate jcc semantic
+    @ir: ir instance
+    @instr: instruction
+    @cond: condtion of the jcc
+    @dst: the dstination if jcc is taken
+    @jmp_if: jump if/notif cond
+    """
+
+    e = []
+    meip = mRIP[instr.mode]
+    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))
+    e.append(m2_expr.ExprAff(meip, mn_dst))
+    e.append(m2_expr.ExprAff(ir.IRDst, mn_dst))
+    return e, []
+
+
+def gen_fcmov(ir, instr, cond, arg1, arg2, mov_if):
+    """Generate fcmov
+    @ir: ir instance
+    @instr: instruction instance
+    @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)
+    if mov_if:
+        dstA, dstB = lbl_do, lbl_skip
+    else:
+        dstA, dstB = lbl_skip, lbl_do
+    e = []
+    e_do, extra_irs = [m2_expr.ExprAff(arg1, arg2)], []
+    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
+    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB)))
+    return e, [irbloc(lbl_do.name, [e_do])]
+
+
+def gen_cmov(ir, instr, cond, arg1, arg2, mov_if):
+    """Generate cmov
+    @ir: ir instance
+    @instr: instruction instance
+    @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)
+    if mov_if:
+        dstA, dstB = lbl_do, lbl_skip
+    else:
+        dstA, dstB = lbl_skip, lbl_do
+    e = []
+    e_do, extra_irs = mov(ir, instr, arg1, arg2)
+    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
+    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB)))
+    return e, [irbloc(lbl_do.name, [e_do])]
+
 
 def mov(ir, instr, a, b):
     if a in [ES, CS, SS, DS, FS, GS]:
@@ -305,10 +379,6 @@ def xor(ir, instr, a, b):
 
 def pxor(ir, instr, a, b):
     e = []
-    if isinstance(a, m2_expr.ExprMem):
-        a = m2_expr.ExprMem(a.arg, b.size)
-    if isinstance(b, m2_expr.ExprMem):
-        b = m2_expr.ExprMem(b.arg, a.size)
     c = a ^ b
     e.append(m2_expr.ExprAff(a, c))
     return e, []
@@ -945,6 +1015,8 @@ def compose_eflag(s=32):
 def pushfd(ir, instr):
     return push(ir, instr, compose_eflag())
 
+def pushfq(ir, instr):
+    return push(ir, instr, compose_eflag().zeroExtend(64))
 
 def pushfw(ir, instr):
     return pushw(ir, instr, compose_eflag(16))
@@ -971,7 +1043,7 @@ def popfd(ir, instr):
     e.append(m2_expr.ExprAff(vip, m2_expr.ExprSlice(tmp, 20, 21)))
     e.append(m2_expr.ExprAff(i_d, m2_expr.ExprSlice(tmp, 21, 22)))
     e.append(m2_expr.ExprAff(mRSP[instr.mode],
-                             mRSP[instr.mode] + m2_expr.ExprInt32(4)))
+                             mRSP[instr.mode] + m2_expr.ExprInt_from(mRSP[instr.mode], instr.mode/8)))
     e.append(m2_expr.ExprAff(exception_flags,
                      m2_expr.ExprCond(m2_expr.ExprSlice(tmp, 8, 9),
                               m2_expr.ExprInt32(EXCEPT_SOFT_BP),
@@ -1210,232 +1282,79 @@ def jmpf(ir, instr, a):
 
 
 def jz(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(zf,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
-    e = [m2_expr.ExprAff(meip, dst_o),
-         m2_expr.ExprAff(ir.IRDst, dst_o),
-     ]
-    return e, []
+    return gen_jcc(ir, instr, zf, dst, True)
 
 
 def jcxz(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(mRCX[instr.mode][:16],
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, mRCX[instr.mode][:16], dst, False)
 
 
 def jecxz(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(mRCX[instr.mode][:32],
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, mRCX[instr.mode][:32], dst, False)
 
 
 def jrcxz(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(mRCX[instr.mode],
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, mRCX[instr.mode], dst, False)
 
 
 def jnz(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(zf,
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, zf, dst, False)
 
 
 def jp(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(pf,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, pf, dst, True)
 
 
 def jnp(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(pf,
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, pf, dst, False)
 
 
 def ja(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(cf | zf,
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, cf|zf, dst, False)
 
 
 def jae(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(cf,
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, cf, dst, False)
 
 
 def jb(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(cf,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, cf, dst, True)
 
 
 def jbe(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(cf | zf,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, cf|zf, dst, True)
 
 
 def jge(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(nf - of,
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, nf-of, dst, False)
 
 
 def jg(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(zf | (nf - of),
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, zf|(nf-of), dst, False)
 
 
 def jl(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(nf - of,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, nf-of, dst, True)
 
 
 def jle(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(zf | (nf - of),
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, zf|(nf-of), dst, True)
 
 
 def js(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(nf,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, nf, dst, True)
 
 
 def jns(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(nf,
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, nf, dst, False)
 
 
 def jo(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(of,
-                             dst.zeroExtend(instr.mode),
-                             n.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, of, dst, True)
 
 
 def jno(ir, instr, dst):
-    e = []
-    meip = mRIP[instr.mode]
-    n = m2_expr.ExprId(ir.get_next_label(instr), dst.size)
-    dst_o = m2_expr.ExprCond(of,
-                             n.zeroExtend(instr.mode),
-                             dst.zeroExtend(instr.mode))
-    e.append(m2_expr.ExprAff(meip, dst_o))
-    e.append(m2_expr.ExprAff(ir.IRDst, dst_o))
-    return e, []
+    return gen_jcc(ir, instr, of, dst, False)
 
 
 def loop(ir, instr, dst):
@@ -1680,7 +1599,7 @@ def cqo(ir, instr):
     tempRDX = mRDX[instr.mode][:64]
     c = tempRAX.signExtend(128)
     e.append(m2_expr.ExprAff(tempRAX, c[:64]))
-    e.append(m2_expr.ExprAff(tempRDX, c[64:127]))
+    e.append(m2_expr.ExprAff(tempRDX, c[64:128]))
     return e, []
 
 
@@ -1813,56 +1732,64 @@ def movsd_dispatch(ir, instr, a = None, b = None):
         return movsd(ir, instr, a, b)
 
 
-def float_prev(flt):
+def float_prev(flt, popcount=1):
     if not flt in float_list:
         return None
     i = float_list.index(flt)
-    if i == 0:
+    if i < popcount:
         raise ValueError('broken index')
-    flt = float_list[i - 1]
+    flt = float_list[i - popcount]
     return flt
 
 
-def float_pop(avoid_flt=None):
-    avoid_flt = float_prev(avoid_flt)
-    e = []
-    if avoid_flt != float_st0:
-        e.append(m2_expr.ExprAff(float_st0, float_st1))
-    if avoid_flt != float_st1:
-        e.append(m2_expr.ExprAff(float_st1, float_st2))
-    if avoid_flt != float_st2:
-        e.append(m2_expr.ExprAff(float_st2, float_st3))
-    if avoid_flt != float_st3:
-        e.append(m2_expr.ExprAff(float_st3, float_st4))
-    if avoid_flt != float_st4:
-        e.append(m2_expr.ExprAff(float_st4, float_st5))
-    if avoid_flt != float_st5:
-        e.append(m2_expr.ExprAff(float_st5, float_st6))
-    if avoid_flt != float_st6:
-        e.append(m2_expr.ExprAff(float_st6, float_st7))
-    if avoid_flt != float_st7:
-        e.append(m2_expr.ExprAff(float_st7, m2_expr.ExprInt_from(float_st7, 0)))
+def float_pop(avoid_flt=None, popcount=1):
+    """
+    Generate floatpop semantic (@popcount times), avoiding the avoid_flt@ float
+    @avoid_flt: float avoided in the generated semantic
+    @popcount: pop count
+    """
+    avoid_flt = float_prev(avoid_flt, popcount)
+    e = []
+    for i in xrange(8-popcount):
+        if avoid_flt != float_list[i]:
+            e.append(m2_expr.ExprAff(float_list[i],
+                                     float_list[i+popcount]))
+    for i in xrange(8-popcount, 8):
+        e.append(m2_expr.ExprAff(float_list[i],
+                                 m2_expr.ExprInt_from(float_list[i], 0)))
     e.append(
         m2_expr.ExprAff(float_stack_ptr,
-                        float_stack_ptr - m2_expr.ExprInt_fromsize(3, 1)))
+                        float_stack_ptr - m2_expr.ExprInt_fromsize(3, popcount)))
     return e
 
 # XXX TODO
 
 
-def fcom(ir, instr, a, b = None):
+def fcom(ir, instr, a=None, b=None):
 
-    if b is None:
+    if a is None and b is None:
+        a, b = float_st0, float_st1
+    elif b is None:
         b = a
         a = float_st0
 
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        b = m2_expr.ExprOp('mem_%.2d_to_double'%b.size, b)
+    b = mem2double(b)
+
+    e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', a, b)))
+    e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', a, b)))
+    e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', a, b)))
+    e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fcom_c3', a, b)))
+
+    e += set_float_cs_eip(instr)
+    return e, []
 
 
+def ftst(ir, instr):
+    a = float_st0
+
+    e = []
+    b = m2_expr.ExprOp('int_32_to_double', m2_expr.ExprInt32(0))
     e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', a, b)))
     e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', a, b)))
     e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', a, b)))
@@ -1872,11 +1799,21 @@ def fcom(ir, instr, a, b = None):
     return e, []
 
 
+def fxam(ir, instr):
+    a = float_st0
+
+    e = []
+    e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fxam_c0', a)))
+    e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fxam_c2', a)))
+    e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fxam_c3', a)))
+
+    e += set_float_cs_eip(instr)
+    return e, []
+
+
 def ficom(ir, instr, a, b = None):
 
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
 
     e = []
 
@@ -1898,38 +1835,58 @@ def ficom(ir, instr, a, b = None):
 
 
 
-def fcomi(ir, instr, a):
-    raise NotImplementedError("Invalid emulation")
-
-
-def fcomip(ir, instr, a):
-    raise NotImplementedError("Invalid emulation")
-
-
-def fucomi(ir, instr, a):
-    raise NotImplementedError("Invalid emulation")
-
+def fcomi(ir, instr, a=None, b=None):
+    # TODO unordered float
+    if a is None and b is None:
+        a, b = float_st0, float_st1
+    elif b is None:
+        b = a
+        a = float_st0
 
-def fucomip(ir, instr, a, b):
     e = []
-    # XXX TODO add exception on NaN
+
     e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', a, b)))
-    #e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', a, b)))
     e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', a, b)))
     e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', a, b)))
 
-    e += float_pop()
+    e.append(m2_expr.ExprAff(of, m2_expr.ExprInt1(0)))
+    e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt1(0)))
+    e.append(m2_expr.ExprAff(af, m2_expr.ExprInt1(0)))
 
     e += set_float_cs_eip(instr)
     return e, []
 
 
-def fcomp(ir, instr, a, b = None):
+def fcomip(ir, instr, a=None, b=None):
+    e, extra = fcomi(ir, instr, a, b)
+    e += float_pop()
+    e += set_float_cs_eip(instr)
+    return e, extra
+
+
+def fucomi(ir, instr, a=None, b=None):
+    # TODO unordered float
+    return fcomi(ir, instr, a, b)
+
+def fucomip(ir, instr, a=None, b=None):
+    # TODO unordered float
+    return fcomip(ir, instr, a, b)
+
+
+def fcomp(ir, instr, a=None, b=None):
     e, extra = fcom(ir, instr, a, b)
     e += float_pop()
     e += set_float_cs_eip(instr)
     return e, extra
 
+
+def fcompp(ir, instr, a=None, b=None):
+    e, extra = fcom(ir, instr, a, b)
+    e += float_pop(popcount=2)
+    e += set_float_cs_eip(instr)
+    return e, extra
+
+
 def ficomp(ir, instr, a, b = None):
     e, extra = ficom(ir, instr, a, b)
     e += float_pop()
@@ -1937,13 +1894,63 @@ def ficomp(ir, instr, a, b = None):
     return e, extra
 
 
+def fucom(ir, instr, a=None, b=None):
+    # TODO unordered float
+    return fcom(ir, instr, a, b)
+
+
+def fucomp(ir, instr, a=None, b=None):
+    # TODO unordered float
+    return fcomp(ir, instr, a, b)
+
+
+def fucompp(ir, instr, a=None, b=None):
+    # TODO unordered float
+    return fcompp(ir, instr, a, b)
+
+
+def comiss(ir, instr, a, b):
+    # TODO unordered float
+
+    e = []
+
+    a = m2_expr.ExprOp('int_32_to_float', a[:32])
+    b = m2_expr.ExprOp('int_32_to_float', b[:32])
+
+    e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', a, b)))
+    e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', a, b)))
+    e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', a, b)))
+
+    e.append(m2_expr.ExprAff(of, m2_expr.ExprInt1(0)))
+    e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt1(0)))
+    e.append(m2_expr.ExprAff(af, m2_expr.ExprInt1(0)))
+
+    e += set_float_cs_eip(instr)
+    return e, []
+
+
+def comisd(ir, instr, a, b):
+    # TODO unordered float
+
+    e = []
+
+    a = m2_expr.ExprOp('int_64_to_double', a[:64])
+    b = m2_expr.ExprOp('int_64_to_double', b[:64])
+
+    e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', a, b)))
+    e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', a, b)))
+    e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', a, b)))
+
+    e.append(m2_expr.ExprAff(of, m2_expr.ExprInt1(0)))
+    e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt1(0)))
+    e.append(m2_expr.ExprAff(af, m2_expr.ExprInt1(0)))
+
+    e += set_float_cs_eip(instr)
+    return e, []
+
+
 def fld(ir, instr, a):
-    if isinstance(a, m2_expr.ExprMem):
-        if a.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % a.size, a)
-    else:
-        src = a
+    src = mem2double(a)
 
     e = []
     e.append(m2_expr.ExprAff(float_st7, float_st6))
@@ -1964,14 +1971,15 @@ def fld(ir, instr, a):
 
 def fst(ir, instr, a):
     e = []
+
     if isinstance(a, m2_expr.ExprMem):
         if a.size > 64:
             raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('double_to_mem_%2d' % a.size, float_st0)
+        src = m2_expr.ExprOp('double_to_mem_%.2d' % a.size, a)
     else:
-        src = float_st0
-    e.append(m2_expr.ExprAff(a, src))
+        src = a
 
+    e.append(m2_expr.ExprAff(a, src))
     e += set_float_cs_eip(instr)
     return e, []
 
@@ -2034,6 +2042,27 @@ def fld1(ir, instr):
                                          m2_expr.ExprInt32(1)))
 
 
+def fldl2t(ir, instr):
+    value_f = math.log(10)/math.log(2)
+    value = struct.unpack('I', struct.pack('f', value_f))[0]
+    return fld(ir, instr, m2_expr.ExprOp('int_32_to_double',
+                                         m2_expr.ExprInt32(value)))
+
+
+def fldpi(ir, instr):
+    value_f = math.pi
+    value = struct.unpack('I', struct.pack('f', value_f))[0]
+    return fld(ir, instr, m2_expr.ExprOp('int_32_to_double',
+                                         m2_expr.ExprInt32(value)))
+
+
+def fldln2(ir, instr):
+    value_f = math.log(2)
+    value = struct.unpack('I', struct.pack('f', value_f))[0]
+    return fld(ir, instr, m2_expr.ExprOp('int_32_to_double',
+                                         m2_expr.ExprInt32(value)))
+
+
 def fldl2e(ir, instr):
     x = struct.pack('d', 1 / math.log(2))
     x = struct.unpack('Q', x)[0]
@@ -2049,48 +2078,68 @@ def fldlg2(ir, instr):
 
 
 def fadd(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fadd', a, src)))
 
     e += set_float_cs_eip(instr)
     return e, []
 
 def fiadd(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fiadd', a, src)))
     e += set_float_cs_eip(instr)
     return e, []
 
 
+def fisub(ir, instr, a, b=None):
+    a, b = float_implicit_st0(a, b)
+    e = []
+    src = mem2double(b)
+    e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fisub', a, src)))
+    e += set_float_cs_eip(instr)
+    return e, []
+
+
+def fisubr(ir, instr, a, b=None):
+    a, b = float_implicit_st0(a, b)
+    e = []
+    src = mem2double(b)
+    e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fisub', src, a)))
+    e += set_float_cs_eip(instr)
+    return e, []
+
+
+def fpatan(ir, instr):
+    e = []
+    a = float_st1
+    e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fpatan', float_st0, float_st1)))
+    e += set_float_cs_eip(instr)
+    e += float_pop(a)
+    return e, []
+
+
+def fprem(ir, instr):
+    e = []
+    e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fprem', float_st0, float_st1)))
+    e += set_float_cs_eip(instr)
+    return e, []
+
+
+def fprem1(ir, instr):
+    e = []
+    e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fprem1', float_st0, float_st1)))
+    e += set_float_cs_eip(instr)
+    return e, []
+
+
 def faddp(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fadd', a, src)))
     e += set_float_cs_eip(instr)
     e += float_pop(a)
@@ -2103,6 +2152,15 @@ def fninit(ir, instr):
     return e, []
 
 
+def fyl2x(ir, instr):
+    e = []
+    a = float_st1
+    e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fyl2x', float_st0, float_st1)))
+    e += set_float_cs_eip(instr)
+    e += float_pop(a)
+    return e, []
+
+
 def fnstenv(ir, instr, a):
     e = []
     # XXX TODO tag word, ...
@@ -2140,31 +2198,17 @@ def fnstenv(ir, instr, a):
 
 
 def fsub(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fsub', a, src)))
     e += set_float_cs_eip(instr)
     return e, []
 
 def fsubp(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fsub', a, src)))
     e += set_float_cs_eip(instr)
     e += float_pop(a)
@@ -2172,110 +2216,81 @@ def fsubp(ir, instr, a, b=None):
 
 
 def fsubr(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fsub', src, a)))
     e += set_float_cs_eip(instr)
     return e, []
 
 
+def fsubrp(ir, instr, a, b=None):
+    a, b = float_implicit_st0(a, b)
+    e = []
+    src = mem2double(b)
+    e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fsub', src, a)))
+    e += set_float_cs_eip(instr)
+    e += float_pop(a)
+    return e, []
+
+
 def fmul(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fmul', a, src)))
     e += set_float_cs_eip(instr)
     return e, []
 
 def fimul(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fimul', a, src)))
     e += set_float_cs_eip(instr)
     return e, []
 
 
 def fdiv(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fdiv', a, src)))
     e += set_float_cs_eip(instr)
     return e, []
 
 def fdivr(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fdiv', src, a)))
     e += set_float_cs_eip(instr)
     return e, []
 
 
+def fdivrp(ir, instr, a, b=None):
+    a, b = float_implicit_st0(a, b)
+    e = []
+    src = mem2double(b)
+    e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fdiv', src, a)))
+    e += set_float_cs_eip(instr)
+    e += float_pop(a)
+    return e, []
+
+
 def fidiv(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fidiv', a, src)))
     e += set_float_cs_eip(instr)
     return e, []
 
 
 def fidivr(ir, instr, a, b=None):
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fidiv', src, a)))
     e += set_float_cs_eip(instr)
     return e, []
@@ -2283,16 +2298,9 @@ def fidivr(ir, instr, a, b=None):
 
 def fdivp(ir, instr, a, b=None):
     # Invalid emulation
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fdiv', a, src)))
     e += set_float_cs_eip(instr)
     e += float_pop(a)
@@ -2301,16 +2309,9 @@ def fdivp(ir, instr, a, b=None):
 
 def fmulp(ir, instr, a, b=None):
     # Invalid emulation
-    if b is None:
-        b = a
-        a = float_st0
+    a, b = float_implicit_st0(a, b)
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        if b.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % b.size, b)
-    else:
-        src = b
+    src = mem2double(b)
     e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fmul', a, src)))
     e += set_float_cs_eip(instr)
     e += float_pop(a)
@@ -2319,12 +2320,7 @@ def fmulp(ir, instr, a, b=None):
 
 def ftan(ir, instr, a):
     e = []
-    if isinstance(a, m2_expr.ExprMem):
-        if a.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % a.size, a)
-    else:
-        src = a
+    src = mem2double(a)
     e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('ftan', src)))
     e += set_float_cs_eip(instr)
     return e, []
@@ -2332,12 +2328,7 @@ def ftan(ir, instr, a):
 
 def fxch(ir, instr, a):
     e = []
-    if isinstance(a, m2_expr.ExprMem):
-        if a.size > 64:
-            raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('mem_%.2d_to_double' % a.size, a)
-    else:
-        src = a
+    src = mem2double(a)
     e.append(m2_expr.ExprAff(float_st0, src))
     e.append(m2_expr.ExprAff(src, float_st0))
     e += set_float_cs_eip(instr)
@@ -2383,6 +2374,22 @@ def fcos(ir, instr):
     return e, []
 
 
+def fsincos(ir, instr):
+    e = []
+    e.append(m2_expr.ExprAff(float_st7, float_st6))
+    e.append(m2_expr.ExprAff(float_st6, float_st5))
+    e.append(m2_expr.ExprAff(float_st5, float_st4))
+    e.append(m2_expr.ExprAff(float_st4, float_st3))
+    e.append(m2_expr.ExprAff(float_st3, float_st2))
+    e.append(m2_expr.ExprAff(float_st2, float_st1))
+    e.append(m2_expr.ExprAff(float_st1, m2_expr.ExprOp('fsin', float_st0)))
+    e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fcos', float_st0)))
+    e.append(
+        m2_expr.ExprAff(float_stack_ptr,
+                        float_stack_ptr + m2_expr.ExprInt_fromsize(3, 1)))
+    return e, []
+
+
 def fscale(ir, instr):
     e = []
     e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fscale', float_st0,
@@ -2397,6 +2404,12 @@ def f2xm1(ir, instr):
     e += set_float_cs_eip(instr)
     return e, []
 
+def fchs(ir, instr):
+    e = []
+    e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fchs', float_st0)))
+    e += set_float_cs_eip(instr)
+    return e, []
+
 
 def fsqrt(ir, instr):
     e = []
@@ -2440,6 +2453,38 @@ def fwait(ir, instr):
     return [], None
 
 
+def fcmovb(ir, instr, arg1, arg2):
+    return gen_fcmov(ir, instr, cf, arg1, arg2, True)
+
+
+def fcmove(ir, instr, arg1, arg2):
+    return gen_fcmov(ir, instr, zf, arg1, arg2, True)
+
+
+def fcmovbe(ir, instr, arg1, arg2):
+    return gen_fcmov(ir, instr, cf|zf, arg1, arg2, True)
+
+
+def fcmovu(ir, instr, arg1, arg2):
+    return gen_fcmov(ir, instr, pf, arg1, arg2, True)
+
+
+def fcmovnb(ir, instr, arg1, arg2):
+    return gen_fcmov(ir, instr, cf, arg1, arg2, False)
+
+
+def fcmovne(ir, instr, arg1, arg2):
+    return gen_fcmov(ir, instr, zf, arg1, arg2, False)
+
+
+def fcmovnbe(ir, instr, arg1, arg2):
+    return gen_fcmov(ir, instr, cf|zf, arg1, arg2, False)
+
+
+def fcmovnu(ir, instr, arg1, arg2):
+    return gen_fcmov(ir, instr, pf, arg1, arg2, False)
+
+
 def nop(ir, instr, a=None):
     return [], []
 
@@ -2675,150 +2720,67 @@ def sldt(ir, instr, a):
     return e, []
 
 
-def cmovz(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(zf, lbl_do, lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
+def cmovz(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, zf, arg1, arg2, True)
 
+def cmovnz(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, zf, arg1, arg2, False)
 
-def cmovnz(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(zf, lbl_skip, lbl_do)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovpe(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, pf, arg1, arg2, True)
 
-def cmovge(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(nf ^ of, lbl_skip,
-                                                        lbl_do)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovnp(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, pf, arg1, arg2, False)
 
-def cmovg(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(zf | (nf ^ of),
-                                                        lbl_skip, lbl_do)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovge(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, nf^of, arg1, arg2, False)
 
-def cmovl(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(nf ^ of, lbl_do,
-                                                        lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovg(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, zf|(nf^of), arg1, arg2, False)
 
-def cmovle(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(zf | (nf ^ of), lbl_do,
-                                                        lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovl(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, nf^of, arg1, arg2, True)
 
-def cmova(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cf | zf, lbl_skip,
-                                                        lbl_do)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovle(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, zf|(nf^of), arg1, arg2, True)
 
-def cmovae(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cf, lbl_skip, lbl_do)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmova(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, cf|zf, arg1, arg2, False)
 
-def cmovbe(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cf | zf, lbl_do,
-                                                        lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovae(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, cf, arg1, arg2, False)
 
-def cmovb(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cf, lbl_do, lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovbe(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, cf|zf, arg1, arg2, True)
 
-def cmovo(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(of, lbl_do, lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovb(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, cf, arg1, arg2, True)
 
-def cmovno(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(of, lbl_skip, lbl_do)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovo(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, of, arg1, arg2, True)
 
-def cmovs(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(nf, lbl_do, lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
 
+def cmovno(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, of, arg1, arg2, False)
 
-def cmovns(ir, instr, a, b):
-    e = []
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-    e_do, extra_irs = mov(ir, instr, a, b)
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(nf, lbl_skip, lbl_do)))
-    return e, [irbloc(lbl_do.name, [e_do])]
+
+def cmovs(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, nf, arg1, arg2, True)
+
+
+def cmovns(ir, instr, arg1, arg2):
+    return gen_cmov(ir, instr, nf, arg1, arg2, False)
 
 
 def icebp(ir, instr):
@@ -2881,16 +2843,16 @@ def cpuid(ir, instr):
     e = []
     e.append(
         m2_expr.ExprAff(mRAX[instr.mode],
-        m2_expr.ExprOp('cpuid', mRAX[instr.mode], m2_expr.ExprInt32(0))))
+        m2_expr.ExprOp('cpuid', mRAX[instr.mode], m2_expr.ExprInt_fromsize(instr.mode, 0))))
     e.append(
         m2_expr.ExprAff(mRBX[instr.mode],
-        m2_expr.ExprOp('cpuid', mRAX[instr.mode], m2_expr.ExprInt32(1))))
+        m2_expr.ExprOp('cpuid', mRAX[instr.mode], m2_expr.ExprInt_fromsize(instr.mode, 1))))
     e.append(
         m2_expr.ExprAff(mRCX[instr.mode],
-        m2_expr.ExprOp('cpuid', mRAX[instr.mode], m2_expr.ExprInt32(2))))
+        m2_expr.ExprOp('cpuid', mRAX[instr.mode], m2_expr.ExprInt_fromsize(instr.mode, 2))))
     e.append(
         m2_expr.ExprAff(mRDX[instr.mode],
-        m2_expr.ExprOp('cpuid', mRAX[instr.mode], m2_expr.ExprInt32(3))))
+        m2_expr.ExprOp('cpuid', mRAX[instr.mode], m2_expr.ExprInt_fromsize(instr.mode, 3))))
     return e, []
 
 
@@ -3083,54 +3045,108 @@ def l_str(ir, instr, a):
 
 def movd(ir, instr, a, b):
     e = []
-    if a.size == 64:
-        value = m2_expr.ExprCompose([(m2_expr.ExprInt32(0), 32, 64),
-                                     (b, 0, 32)])
-        e.append(m2_expr.ExprAff(a, value))
+    if a in regs_mm_expr:
+        e.append(m2_expr.ExprAff(a, m2_expr.ExprCompose([(b, 0, 32),
+                                                         (m2_expr.ExprInt32(0), 32, 64)])))
+    elif a in regs_xmm_expr:
+        e.append(m2_expr.ExprAff(a, m2_expr.ExprCompose([(b, 0, 32),
+                                                         (m2_expr.ExprInt_fromsize(96, 0), 32, 128)])))
     else:
-        e.append(m2_expr.ExprAff(a, b[0:32]))
+        e.append(m2_expr.ExprAff(a, b[:32]))
     return e, []
 
 def movdqu(ir, instr, a, b):
+    # XXX TODO alignement check
+    return [m2_expr.ExprAff(a, b)], []
+
+
+def movapd(ir, instr, a, b):
+    # XXX TODO alignement check
+    return [m2_expr.ExprAff(a, b)], []
+
+
+def andps(ir, instr, a, b):
     e = []
-    if isinstance(a, m2_expr.ExprMem):
-        a = m2_expr.ExprMem(a.arg, b.size)
-    elif isinstance(b, m2_expr.ExprMem):
-        b = m2_expr.ExprMem(b.arg, a.size)
-    e.append(m2_expr.ExprAff(a, b))
+    e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('&', a, b)))
+    return e, []
+
+
+def orps(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('|', a, b)))
     return e, []
 
 
 def xorps(ir, instr, a, b):
     e = []
-    if isinstance(b, m2_expr.ExprMem):
-        b = m2_expr.ExprMem(b.arg, a.size)
     e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('^', a, b)))
     return e, []
 
+
+def rdmsr(ir, instr):
+    msr_addr = m2_expr.ExprId('MSR') + m2_expr.ExprInt32(8) * mRCX[instr.mode][:32]
+    e = []
+    e.append(m2_expr.ExprAff(mRAX[instr.mode][:32], m2_expr.ExprMem(msr_addr, 32)))
+    e.append(m2_expr.ExprAff(mRDX[instr.mode][:32], m2_expr.ExprMem(msr_addr + m2_expr.ExprInt_from(msr_addr, 4), 32)))
+    return e, []
+
+def wrmsr(ir, instr):
+    msr_addr = m2_expr.ExprId('MSR') + m2_expr.ExprInt32(8) * mRCX[instr.mode][:32]
+    e = []
+    src = m2_expr.ExprCompose([(mRAX[instr.mode][:32], 0, 32),
+                               (mRDX[instr.mode][:32], 32, 64)])
+    e.append(m2_expr.ExprAff(m2_expr.ExprMem(msr_addr, 64), src))
+    return e, []
+
 ### MMX/SSE/AVX operations
 ###
 
+def vec_op_clip(op, size):
+    """
+    Generate simd operations
+    @op: the operator
+    @size: size of an element
+    """
+    def vec_op_clip_instr(ir, instr, a, b):
+        if op == '-':
+            return [m2_expr.ExprAff(a[:size], a[:size] - b[:size])], []
+        else:
+            return [m2_expr.ExprAff(a[:size], m2_expr.ExprOp(op, a[:size], b[:size]))], []
+    return vec_op_clip_instr
+
 # Generic vertical operation
 def vec_vertical_sem(op, elt_size, reg_size, a, b):
     assert(reg_size % elt_size == 0)
     n = reg_size/elt_size
-    ops = [(m2_expr.ExprOp(op, a[i*elt_size:(i+1)*elt_size],
-                   b[i*elt_size:(i+1)*elt_size]),
-            i*elt_size,
-            (i+1)*elt_size) for i in xrange(0, n)]
+    if op == '-':
+        ops = [((a[i*elt_size:(i+1)*elt_size] - b[i*elt_size:(i+1)*elt_size]),
+               i*elt_size, (i+1)*elt_size) for i in xrange(0, n)]
+    else:
+        ops = [(m2_expr.ExprOp(op, a[i*elt_size:(i+1)*elt_size],
+                               b[i*elt_size:(i+1)*elt_size]),
+                i*elt_size,
+                (i+1)*elt_size) for i in xrange(0, n)]
+
     return m2_expr.ExprCompose(ops)
 
 def float_vec_vertical_sem(op, elt_size, reg_size, a, b):
     assert(reg_size % elt_size == 0)
     n = reg_size/elt_size
-    ops = [(m2_expr.ExprOp('double_to_int_%d' % elt_size, m2_expr.ExprOp(op,
-                   m2_expr.ExprOp('int_%d_to_double' % elt_size,
-                          a[i*elt_size:(i+1)*elt_size]),
-                   m2_expr.ExprOp('int_%d_to_double' % elt_size,
-                          b[i*elt_size:(i+1)*elt_size]))
-                  ),
-            i*elt_size, (i+1)*elt_size) for i in xrange(0, n)]
+
+    x_to_int, int_to_x = {32: ('float_to_int_%d', 'int_%d_to_float'),
+                          64: ('double_to_int_%d', 'int_%d_to_double')}[elt_size]
+    if op == '-':
+        ops = [(m2_expr.ExprOp(x_to_int % elt_size,
+                               m2_expr.ExprOp(int_to_x % elt_size, a[i*elt_size:(i+1)*elt_size]) -
+                               m2_expr.ExprOp(int_to_x % elt_size, b[i*elt_size:(i+1)*elt_size])),
+                i*elt_size, (i+1)*elt_size) for i in xrange(0, n)]
+    else:
+        ops = [(m2_expr.ExprOp(x_to_int % elt_size,
+                               m2_expr.ExprOp(op,
+                                              m2_expr.ExprOp(int_to_x % elt_size, a[i*elt_size:(i+1)*elt_size]),
+                                              m2_expr.ExprOp(int_to_x % elt_size, b[i*elt_size:(i+1)*elt_size]))),
+                i*elt_size, (i+1)*elt_size) for i in xrange(0, n)]
+
     return m2_expr.ExprCompose(ops)
 
 def __vec_vertical_instr_gen(op, elt_size, sem):
@@ -3174,12 +3190,20 @@ psubq = vec_vertical_instr('-', 64)
 ###
 
 # SSE
+addss = vec_op_clip('+', 32)
+addsd = vec_op_clip('+', 64)
 addps = float_vec_vertical_instr('+', 32)
 addpd = float_vec_vertical_instr('+', 64)
+subss = vec_op_clip('-', 32)
+subsd = vec_op_clip('-', 64)
 subps = float_vec_vertical_instr('-', 32)
 subpd = float_vec_vertical_instr('-', 64)
+mulss = vec_op_clip('*', 32)
+mulsd = vec_op_clip('*', 64)
 mulps = float_vec_vertical_instr('*', 32)
 mulpd = float_vec_vertical_instr('*', 64)
+divss = vec_op_clip('/', 32)
+divsd = vec_op_clip('/', 64)
 divps = float_vec_vertical_instr('/', 32)
 divpd = float_vec_vertical_instr('/', 64)
 
@@ -3194,13 +3218,11 @@ def pand(ir, instr, a, b):
     e.append(m2_expr.ExprAff(a, c))
     return e, []
 
-def movaps(ir, instr, a, b):
+
+def por(ir, instr, a, b):
     e = []
-    if isinstance(a, m2_expr.ExprMem):
-        a = m2_expr.ExprMem(a.arg, b.size)
-    if isinstance(b, m2_expr.ExprMem):
-        b = m2_expr.ExprMem(b.arg, a.size)
-    e.append(m2_expr.ExprAff(a, b))
+    c = a | b
+    e.append(m2_expr.ExprAff(a, c))
     return e, []
 
 
@@ -3209,16 +3231,151 @@ def pminsw(ir, instr, a, b):
     e.append(m2_expr.ExprAff(a, m2_expr.ExprCond((a - b).msb(), a, b)))
     return e, []
 
+def cvtdq2pd(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:64], m2_expr.ExprOp('int_32_to_double', b[:32])))
+    e.append(m2_expr.ExprAff(a[64:128], m2_expr.ExprOp('int_32_to_double', b[32:64])))
+    return e, []
+
+def cvtdq2ps(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('int_32_to_float', b[:32])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('int_32_to_float', b[32:64])))
+    e.append(m2_expr.ExprAff(a[64:96], m2_expr.ExprOp('int_32_to_float', b[64:96])))
+    e.append(m2_expr.ExprAff(a[96:128], m2_expr.ExprOp('int_32_to_float', b[96:128])))
+    return e, []
+
+def cvtpd2dq(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('double_to_int_32', b[:64])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('double_to_int_32', b[64:128])))
+    e.append(m2_expr.ExprAff(a[64:128], m2_expr.ExprInt64(0)))
+    return e, []
+
+def cvtpd2pi(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('double_to_int_32', b[:64])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('double_to_int_32', b[64:128])))
+    return e, []
+
+def cvtpd2ps(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('double_to_float', b[:64])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('double_to_float', b[64:128])))
+    e.append(m2_expr.ExprAff(a[64:128], m2_expr.ExprInt64(0)))
+    return e, []
+
+def cvtpi2pd(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:64], m2_expr.ExprOp('int_32_to_double', b[:32])))
+    e.append(m2_expr.ExprAff(a[64:128], m2_expr.ExprOp('int_32_to_double', b[32:64])))
+    return e, []
+
+def cvtpi2ps(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('int_32_to_float', b[:32])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('int_32_to_float', b[32:64])))
+    return e, []
+
+def cvtps2dq(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('float_to_int_32', b[:32])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('float_to_int_32', b[32:64])))
+    e.append(m2_expr.ExprAff(a[64:96], m2_expr.ExprOp('float_to_int_32', b[64:96])))
+    e.append(m2_expr.ExprAff(a[96:128], m2_expr.ExprOp('float_to_int_32', b[96:128])))
+    return e, []
+
+def cvtps2pd(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:64], m2_expr.ExprOp('float_to_double', b[:32])))
+    e.append(m2_expr.ExprAff(a[64:128], m2_expr.ExprOp('float_to_double', b[32:64])))
+    return e, []
+
+def cvtps2pi(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('float_to_int_32', b[:32])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('float_to_int_32', b[32:64])))
+    return e, []
+
+def cvtsd2si(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('double_to_int_32', b[:64])))
+    return e, []
+
+def cvtsd2ss(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('double_to_float', b[:64])))
+    return e, []
 
 def cvtsi2sd(ir, instr, a, b):
     e = []
-    e.append(m2_expr.ExprAff(a[:b.size], m2_expr.ExprOp('cvtsi2sd', b)))
+    e.append(m2_expr.ExprAff(a[:64], m2_expr.ExprOp('int_32_to_double', b[:32])))
     return e, []
 
+def cvtsi2ss(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('int_32_to_float', b[:32])))
+    return e, []
+
+def cvtss2sd(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:64], m2_expr.ExprOp('float_to_double', b[:32])))
+    return e, []
+
+def cvtss2si(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('float_to_int_32', b[:32])))
+    return e, []
+
+def cvttpd2pi(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('double_trunc_to_int_32', b[:64])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('double_trunc_to_int_32', b[64:128])))
+    return e, []
+
+def cvttpd2dq(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('double_trunc_to_int_32', b[:64])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('double_trunc_to_int_32', b[64:128])))
+    e.append(m2_expr.ExprAff(a[64:128], m2_expr.ExprInt64(0)))
+    return e, []
+
+def cvttps2dq(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('float_trunc_to_int_32', b[:32])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('float_trunc_to_int_32', b[32:64])))
+    e.append(m2_expr.ExprAff(a[64:96], m2_expr.ExprOp('float_trunc_to_int_32', b[64:96])))
+    e.append(m2_expr.ExprAff(a[96:128], m2_expr.ExprOp('float_trunc_to_int_32', b[96:128])))
+    return e, []
+
+def cvttps2pi(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('float_trunc_to_int_32', b[:32])))
+    e.append(m2_expr.ExprAff(a[32:64], m2_expr.ExprOp('float_trunc_to_int_32', b[32:64])))
+    return e, []
+
+def cvttsd2si(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('double_trunc_to_int_32', b[:64])))
+    return e, []
+
+def cvttss2si(ir, instr, a, b):
+    e = []
+    e.append(m2_expr.ExprAff(a[:32], m2_expr.ExprOp('float_trunc_to_int_32', b[:32])))
+    return e, []
 
 def movss(ir, instr, a, b):
     e = []
-    e.append(m2_expr.ExprAff(a[:b.size], m2_expr.ExprOp('movss', b)))
+    if not isinstance(a, m2_expr.ExprMem) and not isinstance(b, m2_expr.ExprMem):
+        # Source and Destination xmm
+        e.append(m2_expr.ExprAff(a[:32], b[:32]))
+    elif not isinstance(b, m2_expr.ExprMem) and isinstance(a, m2_expr.ExprMem):
+        # Source XMM Destination Mem
+        e.append(m2_expr.ExprAff(a, b[:32]))
+    else:
+        # Source Mem Destination XMM
+        e.append(m2_expr.ExprAff(a, m2_expr.ExprCompose([(b, 0, 32),
+                                                         (m2_expr.ExprInt_fromsize(96, 0), 32, 128)])))
     return e, []
 
 
@@ -3318,8 +3475,10 @@ mnemo_func = {'mov': mov,
               'scasw': lambda ir, instr: scas(ir, instr, 16),
               'scasd': lambda ir, instr: scas(ir, instr, 32),
               'pushfd': pushfd,
+              'pushfq': pushfq,
               'pushfw': pushfw,
               'popfd': popfd,
+              'popfq': popfd,
               'popfw': popfw,
               'pushad': pushad,
               'pusha': pushad,
@@ -3392,7 +3551,15 @@ mnemo_func = {'mov': mov,
               'movsd': movsd_dispatch,
               'movsq': lambda ir, instr: movs(ir, instr, 64),
               'fcomp': fcomp,
+              'fcompp': fcompp,
               'ficomp': ficomp,
+              'fucom': fucom,
+              'fucomp': fucomp,
+              'fucompp': fucompp,
+              'comiss': comiss,
+              'comisd': comisd,
+              'fcomi': fcomi,
+              'fcomip': fcomip,
               'nop': nop,
               'fnop': nop,  # XXX
               'hlt': hlt,
@@ -3405,21 +3572,32 @@ mnemo_func = {'mov': mov,
               'fld': fld,
               'fldz': fldz,
               'fld1': fld1,
+              'fldl2t': fldl2t,
+              'fldpi': fldpi,
+              'fldln2': fldln2,
               'fldl2e': fldl2e,
               'fldlg2': fldlg2,
               'fild': fild,
               'fadd': fadd,
               'fiadd': fiadd,
+              'fisub': fisub,
+              'fisubr': fisubr,
+              'fpatan': fpatan,
+              'fprem': fprem,
+              'fprem1': fprem1,
               'fninit': fninit,
+              'fyl2x': fyl2x,
               'faddp': faddp,
               'fsub': fsub,
               'fsubp': fsubp,
               'fsubr': fsubr,
+              'fsubrp': fsubrp,
               'fmul': fmul,
               'fimul': fimul,
               'fmulp': fmulp,
               'fdiv': fdiv,
               'fdivr': fdivr,
+              'fdivrp': fdivrp,
               'fidiv': fidiv,
               'fidivr': fidivr,
               'fdivp': fdivp,
@@ -3428,14 +3606,24 @@ mnemo_func = {'mov': mov,
               'frndint': frndint,
               'fsin': fsin,
               'fcos': fcos,
+              'fsincos': fsincos,
               'fscale': fscale,
               'f2xm1': f2xm1,
+              'fchs': fchs,
               'fsqrt': fsqrt,
               'fabs': fabs,
               'fnstsw': fnstsw,
               'fnstcw': fnstcw,
               'fldcw': fldcw,
               'fwait': fwait,
+              'fcmovb':   fcmovb,
+              'fcmove':   fcmove,
+              'fcmovbe':  fcmovbe,
+              'fcmovu':   fcmovu,
+              'fcmovnb':  fcmovnb,
+              'fcmovne':  fcmovne,
+              'fcmovnbe': fcmovnbe,
+              'fcmovnu':  fcmovnu,
               'fnstenv': fnstenv,
               'sidt': sidt,
               'sldt': sldt,
@@ -3443,6 +3631,8 @@ mnemo_func = {'mov': mov,
               'cmovz': cmovz,
               'cmove': cmovz,
               'cmovnz': cmovnz,
+              'cmovpe':cmovpe,
+              'cmovnp':cmovnp,
               'cmovge': cmovge,
               'cmovnl': cmovge,
               'cmovg': cmovg,
@@ -3465,6 +3655,8 @@ mnemo_func = {'mov': mov,
               'cpuid': cpuid,
               'jo': jo,
               'fcom': fcom,
+              'ftst': ftst,
+              'fxam': fxam,
               'ficom': ficom,
               'fcomi': fcomi,
               'fcomip': fcomip,
@@ -3499,11 +3691,50 @@ mnemo_func = {'mov': mov,
               "str": l_str,
               "movd": movd,
               "movdqu":movdqu,
-              "movaps": movaps,
+              "movdqa":movdqu,
+              "movapd": movapd, # XXX TODO alignement check
+              "movupd": movapd, # XXX TODO alignement check
+              "movaps": movapd, # XXX TODO alignement check
+              "movups": movapd, # XXX TODO alignement check
+              "andps": andps,
+              "andpd": andps,
+              "orps": orps,
+              "orpd": orps,
               "xorps": xorps,
+              "xorpd": xorps,
 
               "pminsw": pminsw,
+              "cvtdq2pd": cvtdq2pd,
+              "cvtdq2ps": cvtdq2ps,
+              "cvtpd2dq": cvtpd2dq,
+              "cvtpd2pi": cvtpd2pi,
+              "cvtpd2ps": cvtpd2ps,
+              "cvtpi2pd": cvtpi2pd,
+              "cvtpi2ps": cvtpi2ps,
+              "cvtps2dq": cvtps2dq,
+              "cvtps2pd": cvtps2pd,
+              "cvtps2pi": cvtps2pi,
+              "cvtsd2si": cvtsd2si,
+              "cvtsd2ss": cvtsd2ss,
               "cvtsi2sd": cvtsi2sd,
+              "cvtsi2ss": cvtsi2ss,
+              "cvtss2sd": cvtss2sd,
+              "cvtss2si": cvtss2si,
+              "cvttpd2pi": cvttpd2pi,
+              "cvttpd2dq": cvttpd2dq,
+              "cvttps2dq": cvttps2dq,
+              "cvttps2pi": cvttps2pi,
+              "cvttsd2si": cvttsd2si,
+              "cvttss2si": cvttss2si,
+
+
+
+
+
+
+
+
+
               "movss": movss,
 
               "ucomiss": ucomiss,
@@ -3533,28 +3764,40 @@ mnemo_func = {'mov': mov,
 
               ## Additions
               # SSE
+              "addss": addss,
+              "addsd": addsd,
               "addps": addps,
               "addpd": addpd,
 
               ## Substractions
               # SSE
+              "subss": subss,
+              "subsd": subsd,
               "subps": subps,
               "subpd": subpd,
 
               ## Multiplications
               # SSE
+              "mulss": mulss,
+              "mulsd": mulsd,
               "mulps": mulps,
               "mulpd": mulpd,
 
               ## Divisions
               # SSE
+              "divss": divss,
+              "divsd": divsd,
               "divps": divps,
               "divpd": divpd,
 
               ### Logical (floating-point)
               ###
 
-              "pand": pand
+              "pand": pand,
+              "por": por,
+
+              "rdmsr": rdmsr,
+              "wrmsr": wrmsr,
 
               }
 
@@ -3576,6 +3819,7 @@ class ir_x86_16(ir):
 
     def get_ir(self, instr):
         args = instr.args[:]
+        args = [arg.replace_expr(float_replace) for arg in args]
         my_ss = None
         if self.do_ds_segm:
             my_ss = DS
@@ -3588,6 +3832,9 @@ class ir_x86_16(ir):
                     args[i] = m2_expr.ExprMem(m2_expr.ExprOp('segm', my_ss,
                                                              a.arg), a.size)
 
+        if not instr.name.lower() in mnemo_func:
+            raise NotImplementedError("Mnemonic %s not implemented" % instr.name)
+
         instr_ir, extra_ir = mnemo_func[
             instr.name.lower()](self, instr, *args)
         self.mod_pc(instr, instr_ir, extra_ir)