about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAjax <commial@gmail.com>2018-02-08 12:14:59 +0100
committerAjax <commial@gmail.com>2018-02-09 17:34:35 +0100
commit0c35bb71b6b3f32b2a62618f4b67ef87df81958d (patch)
tree1e1612f116e9f298a396890c302562fa88a29ebd
parentd404b1803c09b61463845fe14feee5324cbdc051 (diff)
downloadmiasm-0c35bb71b6b3f32b2a62618f4b67ef87df81958d.tar.gz
miasm-0c35bb71b6b3f32b2a62618f4b67ef87df81958d.zip
Add PACKSSWB instruction
0F 63 /r PACKSSWB mm1, mm2/m64
66 0F 63 /r PACKSSWB xmm1, xmm2/m128
-rw-r--r--miasm2/arch/x86/arch.py5
-rw-r--r--miasm2/arch/x86/sem.py50
-rw-r--r--test/arch/x86/arch.py4
3 files changed, 59 insertions, 0 deletions
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index 13c06ae6..2196e5ef 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -4453,6 +4453,11 @@ addop("aesdec", [bs8(0x0f), bs8(0x38), bs8(0xde), pref_66] + rmmod(xmm_reg, rm_a
 addop("aesenclast", [bs8(0x0f), bs8(0x38), bs8(0xdd), pref_66] + rmmod(xmm_reg, rm_arg_xmm))
 addop("aesdeclast", [bs8(0x0f), bs8(0x38), bs8(0xdf), pref_66] + rmmod(xmm_reg, rm_arg_xmm))
 
+addop("packsswb", [bs8(0x0f), bs8(0x63), no_xmm_pref] +
+      rmmod(mm_reg, rm_arg_mm_m64))
+addop("packsswb", [bs8(0x0f), bs8(0x63), 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 deebba8c..635206b6 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -4173,6 +4173,54 @@ def palignr(ir, instr, dst, src, imm):
     return [m2_expr.ExprAff(dst, result)], []
 
 
+def _signed_saturation(expr, dst_size):
+    """Saturate the expr @expr for @dst_size bit
+    Signed saturation return MAX_INT / MIN_INT or value depending on the value
+    """
+    assert expr.size > dst_size
+
+    median = 1 << (dst_size - 1)
+    min_int = m2_expr.ExprInt(- median, dst_size)
+    max_int = m2_expr.ExprInt(median - 1, dst_size)
+    signed = expr.msb()
+    value_unsigned = expr ^ expr.mask + m2_expr.ExprInt(1, expr.size)
+    # Re-use the sign bit
+    value = m2_expr.ExprCompose(expr[:dst_size - 1], signed)
+
+    # Bit hack: to avoid a double signed comparison, use mask
+    # ie., in unsigned, 0xXY > 0x0f iff X is not null
+
+    # if expr >s 0
+    #    if expr[dst_size:] > 0: # bigger than max_int
+    #        -> max_int
+    #    else
+    #        -> value
+    # else # negative
+    #    if expr[dst_size:-1] > 0: # smaller than min_int
+    #        -> value
+    #    else
+    #        -> min_int
+
+    return m2_expr.ExprCond(
+        signed,
+        m2_expr.ExprCond(value_unsigned[dst_size:],
+                         min_int,
+                         value),
+        m2_expr.ExprCond(expr[dst_size:],
+                         max_int,
+                         value),
+    )
+
+
+def packsswb(ir, instr, dst, src):
+    out = []
+    for source in [dst, src]:
+        for start in xrange(0, dst.size, 16):
+            out.append(_signed_saturation(source[start:start + 16], 8))
+    return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
+
+
+
 mnemo_func = {'mov': mov,
               'xchg': xchg,
               'movzx': movzx,
@@ -4670,6 +4718,8 @@ mnemo_func = {'mov': mov,
 
               "pmovmskb": pmovmskb,
 
+              "packsswb": packsswb,
+
               "smsw": smsw,
 
               }
diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py
index d3b2964c..b9bfec74 100644
--- a/test/arch/x86/arch.py
+++ b/test/arch/x86/arch.py
@@ -2970,6 +2970,10 @@ reg_tests = [
     (m64, "00000000    BNDMOV     BND3, XMMWORD PTR [RSP + 0xB0]",
      "660f1a9c24b0000000"),
 
+    (m32, "00000000    PACKSSWB   MM7, MM0",
+     "0f63f8"),
+    (m32, "00000000    PACKSSWB   XMM0, XMM5",
+     "660f63c5"),
 ]