about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/x86/arch.py9
-rw-r--r--miasm2/arch/x86/sem.py21
-rw-r--r--test/arch/x86/arch.py9
3 files changed, 39 insertions, 0 deletions
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index f4ef7349..303cad6e 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -4486,6 +4486,15 @@ addop("psubusw", [bs8(0x0f), bs8(0xd9), no_xmm_pref] +
 addop("psubusw", [bs8(0x0f), bs8(0xd9), pref_66] +
       rmmod(xmm_reg, rm_arg_xmm_m128))
 
+addop("paddusb", [bs8(0x0f), bs8(0xdc), no_xmm_pref] +
+      rmmod(mm_reg, rm_arg_mm_m64))
+addop("paddusb", [bs8(0x0f), bs8(0xdc), pref_66] +
+      rmmod(xmm_reg, rm_arg_xmm_m128))
+addop("paddusw", [bs8(0x0f), bs8(0xdd), no_xmm_pref] +
+      rmmod(mm_reg, rm_arg_mm_m64))
+addop("paddusw", [bs8(0x0f), bs8(0xdd), 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 4b4f40a1..adf5820d 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -4294,11 +4294,30 @@ def _saturation_sub(expr):
     arg2 = expr.args[1].args[0].zeroExtend(expr.size + 1)
     return _unsigned_saturation(arg1 - arg2, expr.size)
 
+def _saturation_add(expr):
+    assert expr.is_op("+") and len(expr.args) == 2
+
+    # Compute the addition on one more bit to be able to distinguish cases:
+    # 0x48 + 0xd7 in 8 bit, should saturate
+
+    arg1 = expr.args[0].zeroExtend(expr.size + 1)
+    arg2 = expr.args[1].zeroExtend(expr.size + 1)
+
+    # We can also use _unsigned_saturation with two additionnal bits (to
+    # distinguish minus and overflow case)
+    # The resulting expression being more complicated with an impossible case
+    # (signed=True), we rewrite the rule here
+
+    return m2_expr.ExprCond((arg1 + arg2).msb(), m2_expr.ExprInt(-1, expr.size),
+                            expr)
+
 
 # Saturate SSE operations
 
 psubusb = vec_vertical_instr('-', 8, _saturation_sub)
 psubusw = vec_vertical_instr('-', 16, _saturation_sub)
+paddusb = vec_vertical_instr('+', 8, _saturation_add)
+paddusw = vec_vertical_instr('+', 16, _saturation_add)
 
 
 mnemo_func = {'mov': mov,
@@ -4810,6 +4829,8 @@ mnemo_func = {'mov': mov,
 
               "psubusb": psubusb,
               "psubusw": psubusw,
+              "paddusb": paddusb,
+              "paddusw": paddusw,
 
               "smsw": smsw,
 
diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py
index 3e0b9333..9b1a4d25 100644
--- a/test/arch/x86/arch.py
+++ b/test/arch/x86/arch.py
@@ -3000,6 +3000,15 @@ reg_tests = [
     (m32, "00000000    PSUBUSW    XMM0, XMM5",
      "660fd9c5"),
 
+    (m32, "00000000    PADDUSB    MM5, MM3",
+     "0fdceb"),
+    (m32, "00000000    PADDUSB    XMM0, XMM6",
+     "660fdcc6"),
+
+    (m32, "00000000    PADDUSW    MM7, MM5",
+     "0fddfd"),
+    (m32, "00000000    PADDUSW    XMM0, XMM1",
+     "660fddc1"),
 ]