about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAjax <commial@gmail.com>2018-02-08 13:24:29 +0100
committerAjax <commial@gmail.com>2018-02-09 17:34:35 +0100
commit615ee255906c0fe036e9dc87ee65ed27e0b6f88d (patch)
treea5ef99e08b4b8b9eb0e81d644834794efe7dd52d
parent0264e8ae0338b7ecd5bbe5af8783193a3e7a1e7e (diff)
downloadmiasm-615ee255906c0fe036e9dc87ee65ed27e0b6f88d.tar.gz
miasm-615ee255906c0fe036e9dc87ee65ed27e0b6f88d.zip
Add PACKUSWB instruction
-rw-r--r--miasm2/arch/x86/arch.py5
-rw-r--r--miasm2/arch/x86/sem.py33
-rw-r--r--test/arch/x86/arch.py5
3 files changed, 43 insertions, 0 deletions
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index 793d5a47..572c2378 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -4463,6 +4463,11 @@ addop("packsswb", [bs8(0x0f), bs8(0x63), no_xmm_pref] +
 addop("packsswb", [bs8(0x0f), bs8(0x63), pref_66] +
       rmmod(xmm_reg, rm_arg_xmm_m128))
 
+addop("packuswb", [bs8(0x0f), bs8(0x67), no_xmm_pref] +
+      rmmod(mm_reg, rm_arg_mm_m64))
+addop("packuswb", [bs8(0x0f), bs8(0x67), pref_66] +
+      rmmod(xmm_reg, rm_arg_xmm_m128))
+
 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 635206b6..6dcc76af 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -4212,6 +4212,31 @@ def _signed_saturation(expr, dst_size):
     )
 
 
+def _unsigned_saturation(expr, dst_size):
+    """Saturate the expr @expr for @dst_size bit
+    Unsigned saturation return MAX_INT or value depending on the value
+    """
+    assert expr.size > dst_size
+
+    zero = m2_expr.ExprInt(0, dst_size)
+    max_int = m2_expr.ExprInt(-1, dst_size)
+    value = expr[:dst_size]
+    signed = expr.msb()
+
+
+    # Bit hack: to avoid a double signed comparison, use mask
+    # ie., in unsigned, 0xXY > 0x0f iff X is not null
+
+    return m2_expr.ExprCond(
+        signed,
+        zero,
+        m2_expr.ExprCond(expr[dst_size:],
+                         max_int,
+                         value),
+    )
+
+
+
 def packsswb(ir, instr, dst, src):
     out = []
     for source in [dst, src]:
@@ -4220,6 +4245,13 @@ def packsswb(ir, instr, dst, src):
     return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
 
 
+def packuswb(ir, instr, dst, src):
+    out = []
+    for source in [dst, src]:
+        for start in xrange(0, dst.size, 16):
+            out.append(_unsigned_saturation(source[start:start + 16], 8))
+    return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
+
 
 mnemo_func = {'mov': mov,
               'xchg': xchg,
@@ -4719,6 +4751,7 @@ mnemo_func = {'mov': mov,
               "pmovmskb": pmovmskb,
 
               "packsswb": packsswb,
+              "packuswb": packuswb,
 
               "smsw": smsw,
 
diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py
index b9bfec74..fbcb88f8 100644
--- a/test/arch/x86/arch.py
+++ b/test/arch/x86/arch.py
@@ -2974,6 +2974,11 @@ reg_tests = [
      "0f63f8"),
     (m32, "00000000    PACKSSWB   XMM0, XMM5",
      "660f63c5"),
+
+    (m32, "00000000    PACKUSWB   MM1, MM7",
+     "0f67cf"),
+    (m32, "00000000    PACKUSWB   XMM0, XMM6",
+     "660f67c6"),
 ]