about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAjax <commial@gmail.com>2018-02-09 14:51:30 +0100
committerAjax <commial@gmail.com>2018-02-09 17:36:31 +0100
commit971b683a5f068068a2d775d5807deacd13918cf9 (patch)
tree88f1d24475dbcbd6f4d06d07910b156e6e98a9e6
parent8d6b88e240f860b5d41244b5d1f16ea88a2d1cb0 (diff)
downloadmiasm-971b683a5f068068a2d775d5807deacd13918cf9.tar.gz
miasm-971b683a5f068068a2d775d5807deacd13918cf9.zip
Add MASKMOVQ/MASKMOVDQU instruction
-rw-r--r--miasm2/arch/x86/arch.py6
-rw-r--r--miasm2/arch/x86/sem.py49
-rw-r--r--test/arch/x86/arch.py5
3 files changed, 59 insertions, 1 deletions
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index 4707fde3..40cd4e9c 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -4548,6 +4548,12 @@ addop("pavgw", [bs8(0x0f), bs8(0xe3), no_xmm_pref] +
 addop("pavgw", [bs8(0x0f), bs8(0xe3), pref_66] +
       rmmod(xmm_reg, rm_arg_xmm_m128))
 
+addop("maskmovq", [bs8(0x0f), bs8(0xf7), no_xmm_pref] +
+      rmmod(mm_reg, rm_arg_mm_reg))
+addop("maskmovdqu", [bs8(0x0f), bs8(0xf7), pref_66] +
+      rmmod(xmm_reg, rm_arg_xmm_reg))
+
+
 mn_x86.bintree = factor_one_bit(mn_x86.bintree)
 # mn_x86.bintree = factor_fields_all(mn_x86.bintree)
 """
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index 5a0f1b6b..becee84e 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -4401,6 +4401,52 @@ paddsb = vec_vertical_instr('+', 8, _saturation_add_signed)
 paddsw = vec_vertical_instr('+', 16, _saturation_add_signed)
 
 
+# Others SSE operations
+
+def maskmovq(ir, instr, src, mask):
+    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size)
+    blks = []
+
+    # For each possibility, check if a write is necessary
+    check_labels = [m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+                    for _ in xrange(0, mask.size, 8)]
+    # If the write has to be done, do it (otherwise, nothing happen)
+    write_labels = [m2_expr.ExprId(ir.gen_label(), ir.IRDst.size)
+                    for _ in xrange(0, mask.size, 8)]
+
+    # Build check blocks
+    for i, start in enumerate(xrange(0, mask.size, 8)):
+        bit = mask[start + 7: start + 8]
+        cur_label = check_labels[i]
+        next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else lbl_next
+        write_label = write_labels[i]
+        check = m2_expr.ExprAff(ir.IRDst,
+                                m2_expr.ExprCond(bit,
+                                                 write_label,
+                                                 next_check_label))
+        blks.append(IRBlock(cur_label.name, [AssignBlock([check], instr)]))
+
+    # Build write blocks
+    dst_addr = mRDI[instr.mode]
+    for i, start in enumerate(xrange(0, mask.size, 8)):
+        bit = mask[start + 7: start + 8]
+        cur_label = write_labels[i]
+        next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else lbl_next
+        write_addr = dst_addr + m2_expr.ExprInt(i, dst_addr.size)
+
+        # @8[DI/EDI/RDI + i] = src[byte i]
+        write_mem = m2_expr.ExprAff(m2_expr.ExprMem(write_addr, 8),
+                                    src[start: start + 8])
+        jump = m2_expr.ExprAff(ir.IRDst, next_check_label)
+        blks.append(IRBlock(cur_label.name, [AssignBlock([write_mem, jump], instr)]))
+
+    # If mask is null, bypass all
+    e = [m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(mask,
+                                                    check_labels[0],
+                                                    lbl_next))]
+    return e, blks
+
+
 mnemo_func = {'mov': mov,
               'xchg': xchg,
               'movzx': movzx,
@@ -4936,7 +4982,8 @@ mnemo_func = {'mov': mov,
               "paddsw": paddsw,
 
               "smsw": smsw,
-
+              "maskmovq": maskmovq,
+              "maskmovdqu": maskmovq,
               }
 
 
diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py
index 68bc1304..f491c19a 100644
--- a/test/arch/x86/arch.py
+++ b/test/arch/x86/arch.py
@@ -3069,6 +3069,11 @@ reg_tests = [
      "0fe3d9"),
     (m32, "00000000    PAVGW      XMM0, XMM6",
      "660fe3c6"),
+
+    (m32, "00000000    MASKMOVQ   MM2, MM3",
+     "0ff7d3"),
+    (m32, "00000000    MASKMOVDQU XMM4, XMM5",
+     "660ff7e5"),
 ]