about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--test/arch/x86/arch.py79
-rw-r--r--test/arch/x86/sem.py154
-rw-r--r--test/test_all.py1
3 files changed, 230 insertions, 4 deletions
diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py
index 6479b44a..eba4e1f7 100644
--- a/test/arch/x86/arch.py
+++ b/test/arch/x86/arch.py
@@ -1730,14 +1730,85 @@ reg_tests = [
     (m32, "00000000    MOVDQA     DWORD PTR [ESP], XMM0",
      "660f7f0424"),
 
+    #### MMX/SSE/AVX operations
+    ####
+
+    ### Arithmetic (floating-point)
+    ###
+
+    ## Additions
+    # SSE
+    (m32, "00000000    PADDB      XMM0, XMM1",
+     "660ffcc1"),
+    (m64, "00000000    PADDB      XMM0, XMM1",
+     "660ffcc1"),
+    (m32, "00000000    PADDW      XMM0, XMM1",
+     "660ffdc1"),
+    (m32, "00000000    PADDD      XMM0, XMM1",
+     "660ffec1"),
+    (m32, "00000000    PADDQ      XMM0, XMM1",
+     "660fd4c1"),
+
+    ## Substractions
+    # SSE
+    (m32, "00000000    PSUBB      XMM0, XMM1",
+     "660ff8c1"),
+    (m32, "00000000    PSUBW      XMM0, XMM1",
+     "660ff9c1"),
+    (m32, "00000000    PSUBD      XMM0, XMM1",
+     "660ffac1"),
+    (m32, "00000000    PSUBQ      XMM0, XMM1",
+     "660ffbc1"),
+
+    ### Arithmetic (floating-point)
+    ###
+
+    ## Additions
+    # SSE
+    (m32, "00000000    ADDPS      XMM0, XMM1",
+     "0f58c1"),
+    (m32, "00000000    ADDPD      XMM0, XMM1",
+     "660f58c1"),
+
+    ## Substractions
+    # SSE
+    (m32, "00000000    SUBPS      XMM0, XMM1",
+     "0f5cc1"),
+    (m32, "00000000    SUBPD      XMM0, XMM1",
+     "660f5cc1"),
+
+    ## Multiplications
+    # SSE
+    (m32, "00000000    MULPS      XMM0, XMM1",
+     "0f59c1"),
+    (m32, "00000000    MULPD      XMM0, XMM1",
+     "660f59c1"),
+
+    ## Divisions
+    # SSE
+    (m32, "00000000    DIVPS      XMM0, XMM1",
+     "0f5ec1"),
+    (m32, "00000000    DIVPD      XMM0, XMM1",
+     "660f5ec1"),
+
+    ### Converts
+    ###
+
+    ## SS -> SD
+    ##
+
+    # SSE
+    (m32, "00000000    CVTSD2SS   XMM0, XMM0",
+     "f20f5ac0"),
+
+    ## SD -> SS
+    ##
+
+    # SSE
     (m32, "00000000    CVTSS2SD   XMM0, XMM0",
      "f30f5ac0"),
     (m32, "00000000    CVTSS2SD   XMM0, DWORD PTR [EBP+0xFFFFFFD0]",
      "f30f5a45d0"),
-
-    (m32, "00000000    CVTSD2SS   XMM0, XMM0",
-     "f20f5ac0"),
-
 ]
 
 
diff --git a/test/arch/x86/sem.py b/test/arch/x86/sem.py
new file mode 100644
index 00000000..64447e13
--- /dev/null
+++ b/test/arch/x86/sem.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+# Loosely based on ARM's sem.py
+
+import unittest
+import logging
+import copy
+
+from miasm2.ir.symbexec import symbexec
+from miasm2.arch.x86.arch import mn_x86 as mn
+from miasm2.arch.x86.sem import ir_x86_32 as ir_32, ir_x86_64 as ir_64
+from miasm2.arch.x86.regs import *
+from miasm2.expression.expression import *
+from miasm2.expression.simplifications      import expr_simp
+from miasm2.core import parse_asm, asmbloc
+
+
+logging.getLogger('cpuhelper').setLevel(logging.ERROR)
+EXCLUDE_REGS = set()
+
+m32 = 32
+m64 = 64
+
+def symb_exec(interm, inputstate, debug):
+    sympool = dict(regs_init)
+    sympool.update(inputstate)
+    symexec = symbexec(mn, sympool)
+    symexec.emul_ir_blocs(interm, 0)
+    if debug:
+        for k, v in symexec.symbols.items():
+            if regs_init.get(k, None) != v:
+                print k, v
+    return {k: v for k, v in symexec.symbols.items()
+            if k not in EXCLUDE_REGS and regs_init.get(k, None) != v}
+
+def compute(ir, mode, asm, inputstate={}, debug=False):
+    instr = mn.fromstring(asm, mode)
+    code = mn.asm(instr)[0]
+    instr = mn.dis(code, mode)
+    instr.offset = inputstate.get(EIP, 0)
+    interm = ir()
+    interm.add_instr(instr)
+    return symb_exec(interm, inputstate, debug)
+
+
+def compute_txt(ir, mode, txt, inputstate={}, debug=False):
+    blocs, symbol_pool = parse_asm.parse_txt(mn, mode, txt)
+    symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0)
+    resolved_b, patches = asmbloc.asm_resolve_final(
+        mn, str(mode), blocs[0], symbol_pool)
+    interm = ir(symbol_pool)
+    for bbl in resolved_b:
+        interm.add_bloc(bbl[0])
+    return symb_exec(interm, inputstate, debug)
+
+op_add = lambda a, b: a+b
+op_sub = lambda a, b: a-b
+op_mul = lambda a, b: a*b
+op_div = lambda a, b: a/b
+
+op_and = lambda a, b: a&b
+op_or  = lambda a, b: a|b
+op_xor = lambda a, b: a^b
+
+def int_vec_op(op, elt_size, reg_size, arg1, arg2):
+    arg1 = copy.deepcopy(arg1)
+    arg2 = copy.deepcopy(arg2)
+    assert(reg_size % elt_size == 0)
+    ret = 0
+    mask = (1<<elt_size)-1
+    nelts = reg_size/elt_size
+    for i in xrange(0, nelts):
+        ret |= (op(arg1 & mask, arg2 & mask) & mask) << (i*elt_size)
+        arg1 >>= elt_size
+        arg2 >>= elt_size
+    return ret
+
+MMX_V0 = 0x0001020304050607
+MMX_V1 = 0x0101010101010101
+MMX_A = ExprId('A', 64)
+MMX_B = ExprId('B', 64)
+
+SSE_V0 = 0x00010203040506070001020304050607
+SSE_V1 = 0x01010101010101010101010101010101
+SSE_A = ExprId('A', 128)
+SSE_B = ExprId('B', 128)
+
+class TestX86Semantic(unittest.TestCase):
+
+    def int_sse_op(self, name, op, elt_size, reg_size, arg1, arg2):
+        arg1 = ExprInt_from(XMM0, arg1)
+        arg2 = ExprInt_from(XMM0, arg2)
+        sem = compute(ir_32, m32, '%s XMM0, XMM1' % name,
+                                  {XMM0: arg1, XMM1: arg2},
+                                  False)
+        ref = ExprInt_from(XMM0, int_vec_op(op, elt_size, reg_size, arg1.arg, arg2.arg))
+        self.assertEqual(sem, {XMM0: ref, XMM1: arg2})
+
+    def symb_sse_ops(self, names, a, b, ref):
+        asm = "\n\t".join(["%s XMM0, XMM1" % name for name in names])
+        asm = "main:\n\t" + asm
+        sem = compute_txt(ir_32, m32, asm,
+                                  {XMM0: a, XMM1: b},
+                                  False)
+        self.assertEqual(sem, {XMM0: ref, XMM1: b})
+
+    def mmx_logical_op(self, name, op, arg1, arg2):
+        arg1 = ExprInt_from(mm0, arg1)
+        arg2 = ExprInt_from(mm0, arg2)
+        sem = compute(ir_32, m32, '%s MM0, MM1' % name,
+                                  {mm0: arg1, mm1: arg2},
+                                  False)
+        ref = ExprInt_from(mm0, op(arg1.arg, arg2.arg))
+        self.assertEqual(sem, {mm0: ref, mm1: arg2})
+
+    def sse_logical_op(self, name, op, arg1, arg2):
+        arg1 = ExprInt_from(XMM0, arg1)
+        arg2 = ExprInt_from(XMM1, arg2)
+        sem = compute(ir_32, m32, '%s XMM0, XMM1' % name,
+                                  {XMM0: arg1, XMM1: arg2},
+                                  False)
+        ref = ExprInt_from(XMM0, op(arg1.arg, arg2.arg))
+        self.assertEqual(sem, {XMM0: ref, XMM1: arg2})
+
+    def test_SSE_ADD(self):
+        for op in (("PADDB", 8), ("PADDW", 16), ("PADDD", 32), ("PADDQ", 64)):
+            self.int_sse_op(op[0], op_add, op[1], 128, SSE_V0, SSE_V0)
+            self.int_sse_op(op[0], op_add, op[1], 128, SSE_V0, SSE_V1)
+            self.int_sse_op(op[0], op_add, op[1], 128, SSE_V1, SSE_V0)
+            self.int_sse_op(op[0], op_add, op[1], 128, SSE_V1, SSE_V1)
+
+    def test_SSE_SUB(self):
+        for op in (("PSUBB", 8), ("PSUBW", 16), ("PSUBD", 32), ("PSUBQ", 64)):
+            self.int_sse_op(op[0], op_sub, op[1], 128, SSE_V0, SSE_V0)
+            self.int_sse_op(op[0], op_sub, op[1], 128, SSE_V0, SSE_V1)
+            self.int_sse_op(op[0], op_sub, op[1], 128, SSE_V1, SSE_V0)
+            self.int_sse_op(op[0], op_sub, op[1], 128, SSE_V1, SSE_V1)
+
+    def test_SSE_simp(self):
+        self.symb_sse_ops(["PADDB", "PADDB", "PSUBB"], ExprInt_from(XMM0, 0), SSE_A, SSE_A)
+        self.symb_sse_ops(["PADDB", "PADDQ", "PSUBQ"], ExprInt_from(XMM0, 0), SSE_A, SSE_A)
+        self.symb_sse_ops(["PADDB", "PSUBQ", "PADDQ"], ExprInt_from(XMM0, 0), SSE_A, SSE_A)
+
+    def test_AND(self):
+        self.mmx_logical_op("PAND", op_and, MMX_V0, MMX_V1)
+        self.sse_logical_op("PAND", op_and, SSE_V0, SSE_V1)
+
+
+
+if __name__ == '__main__':
+    testsuite = unittest.TestLoader().loadTestsFromTestCase(TestX86Semantic)
+    report = unittest.TextTestRunner(verbosity=2).run(testsuite)
+    exit(len(report.errors + report.failures))
diff --git a/test/test_all.py b/test/test_all.py
index ae1ca741..eb1e7fcd 100644
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -23,6 +23,7 @@ all_tests = {
     "test": {
         "architecture": [
             ["arch/x86/arch.py"],
+            ["arch/x86/sem.py"],
             ["arch/arm/arch.py"],
             ["arch/arm/sem.py"],
             ["arch/msp430/arch.py"],