about summary refs log tree commit diff stats
path: root/src/miasm/arch/x86/sem.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/miasm/arch/x86/sem.py')
-rw-r--r--src/miasm/arch/x86/sem.py44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/miasm/arch/x86/sem.py b/src/miasm/arch/x86/sem.py
index 26b87110..895be1fa 100644
--- a/src/miasm/arch/x86/sem.py
+++ b/src/miasm/arch/x86/sem.py
@@ -3803,6 +3803,46 @@ def vec_vertical_instr(op, elt_size, apply_on_output=lambda x: x):
     return __vec_vertical_instr_gen(op, elt_size, vec_vertical_sem,
                                     apply_on_output)
 
+# Alternating vertical operation
+
+def vec_alternating_vertical_sem(op1, op2, elt_size, reg_size, dst, src, apply_on_output):
+    assert reg_size % elt_size == 0
+    n = reg_size // elt_size
+    assert n % 2 == 0
+    if op1 == '-' or op2 == '-':
+        ops = [
+            apply_on_output((dst[i * elt_size:(i + 1) * elt_size]
+                             - src[i * elt_size:(i + 1) * elt_size]))
+            for i in range(0, n)
+        ]
+    else:
+        ops = []
+        for i in range(0, n//2):
+            ops.append(apply_on_output(m2_expr.ExprOp(op1, dst[(i*2) * elt_size:((i*2) + 1) * elt_size],
+                                           src[(i*2) * elt_size:((i*2) + 1) * elt_size])))
+            ops.append(apply_on_output(m2_expr.ExprOp(op2, dst[(i*2 + 1) * elt_size:(i*2 + 2) * elt_size],
+                                           src[(i*2 + 1) * elt_size:(i*2 + 2) * elt_size])))
+
+    return m2_expr.ExprCompose(*ops)
+
+
+def __vec_alternating_vertical_instr_gen(op1, op2, elt_size, sem, apply_on_output):
+    def vec_instr(ir, instr, dst, src):
+        e = []
+        if isinstance(src, m2_expr.ExprMem):
+            src = ir.ExprMem(src.ptr, dst.size)
+        reg_size = dst.size
+        e.append(m2_expr.ExprAssign(dst, sem(op1, op2, elt_size, reg_size, dst, src,
+                                          apply_on_output)))
+        return e, []
+    return vec_instr
+
+
+def vec_alternating_vertical_instr(op1, op2, elt_size, apply_on_output=lambda x: x):
+    return __vec_alternating_vertical_instr_gen(op1, op2, elt_size, vec_alternating_vertical_sem,
+                                    apply_on_output)
+
+
 
 def _keep_mul_high(expr, signed=False):
     assert expr.is_op("*") and len(expr.args) == 2
@@ -4002,6 +4042,8 @@ divsd = vec_op_clip('fdiv', 64)
 divps = vec_vertical_instr('fdiv', 32)
 divpd = vec_vertical_instr('fdiv', 64)
 
+addsubps = vec_alternating_vertical_instr('fsub', 'fadd', 32)
+
 # Comparisons (floating-point)
 
 minps = vec_vertical_instr('fmin', 32, _float_min_max)
@@ -5700,6 +5742,8 @@ mnemo_func = {'mov': mov,
               "subps": subps,
               "subpd": subpd,
 
+              "addsubps": addsubps,
+
               # Multiplications
               # SSE
               "mulss": mulss,