Mark Wielaard 364b6d
diff --git a/none/tests/s390x/vector.h b/none/tests/s390x/vector.h
Mark Wielaard 364b6d
new file mode 100644
Mark Wielaard 364b6d
index 000000000..a6538b43f
Mark Wielaard 364b6d
--- /dev/null
Mark Wielaard 364b6d
+++ b/none/tests/s390x/vector.h
Mark Wielaard 364b6d
@@ -0,0 +1,173 @@
Mark Wielaard 364b6d
+#ifndef S390_TEST_VECTOR_H
Mark Wielaard 364b6d
+#define S390_TEST_VECTOR_H
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+#include "stdbool.h"
Mark Wielaard 364b6d
+#include "stdint.h"
Mark Wielaard 364b6d
+#include "stdio.h"
Mark Wielaard 364b6d
+#include "string.h"
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+/* How many times should every test be executed? */
Mark Wielaard 364b6d
+#define S390_TEST_COUNT 10
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+/* Test the instruction exactly one time. */
Mark Wielaard 364b6d
+#define test_once(insn) test_##insn()
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+/* Test the instruction exactly S390_TEST_COUNT times.
Mark Wielaard 364b6d
+   "..." arguments specifies code which must be executed after each tests
Mark Wielaard 364b6d
+ */
Mark Wielaard 364b6d
+#define test(insn, ...) \
Mark Wielaard 364b6d
+   for(iteration = 0; iteration < S390_TEST_COUNT; iteration++) \
Mark Wielaard 364b6d
+     { test_##insn(); \
Mark Wielaard 364b6d
+        __VA_ARGS__; \
Mark Wielaard 364b6d
+     }
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+#ifdef __GNUC__
Mark Wielaard 364b6d
+/* GCC complains about __int128 with -pedantic */
Mark Wielaard 364b6d
+/* Hope that we will have int128_t in C standard someday. */
Mark Wielaard 364b6d
+#pragma GCC diagnostic ignored "-Wpedantic"
Mark Wielaard 364b6d
+#endif
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+typedef union {
Mark Wielaard 364b6d
+   uint8_t u8[16];
Mark Wielaard 364b6d
+   int8_t s8[16];
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+   uint16_t u16[8];
Mark Wielaard 364b6d
+   int16_t s16[8];
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+   uint32_t u32[4];
Mark Wielaard 364b6d
+   int32_t s32[4];
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+   uint64_t u64[2];
Mark Wielaard 364b6d
+   int64_t s64[2];
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+   unsigned __int128 u128[1];
Mark Wielaard 364b6d
+   __int128 s128[1];
Mark Wielaard 364b6d
+} V128;
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+void print_hex(const V128 value) {
Mark Wielaard 364b6d
+   printf("%016lx | %016lx\n", value.u64[0], value.u64[1]);
Mark Wielaard 364b6d
+}
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+void print_uint64_t(const uint64_t value) {
Mark Wielaard 364b6d
+   printf("%016lx\n", value);
Mark Wielaard 364b6d
+}
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+uint8_t random_element ( void )
Mark Wielaard 364b6d
+{
Mark Wielaard 364b6d
+   static uint32_t seed = 80021;
Mark Wielaard 364b6d
+   seed = 1103515245 * seed + 12345;
Mark Wielaard 364b6d
+   return (seed >> 17) & 0xFF;
Mark Wielaard 364b6d
+}
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+void random_V128 (V128 *block)
Mark Wielaard 364b6d
+{
Mark Wielaard 364b6d
+   size_t i;
Mark Wielaard 364b6d
+   for(i = 0; i < 16; i++)
Mark Wielaard 364b6d
+   {
Mark Wielaard 364b6d
+      block->u8[i] = random_element();
Mark Wielaard 364b6d
+   }
Mark Wielaard 364b6d
+}
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+uint64_t random_uint64_t()
Mark Wielaard 364b6d
+{
Mark Wielaard 364b6d
+   uint64_t result = 0ULL;
Mark Wielaard 364b6d
+   uint8_t  *ptr = (uint8_t *) &result;
Mark Wielaard 364b6d
+   size_t i;
Mark Wielaard 364b6d
+   for(i = 0; i < 8; i++)
Mark Wielaard 364b6d
+   {
Mark Wielaard 364b6d
+      ptr[i] = random_element();
Mark Wielaard 364b6d
+   }
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+   return result;
Mark Wielaard 364b6d
+}
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+/* Memory pool with some random data. Used for some instruction which need
Mark Wielaard 364b6d
+   an address to some memory chunk.
Mark Wielaard 364b6d
+   Pool should be large enough for all insn that use it.
Mark Wielaard 364b6d
+   (64 bytes and aligning are needed by VLBB insn)
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+   Content of this pool must be updated every iteration but not from test to test.
Mark Wielaard 364b6d
+*/
Mark Wielaard 364b6d
+uint8_t random_memory_pool[64] __attribute__ ((aligned (64)));
Mark Wielaard 364b6d
+void randomize_memory_pool()
Mark Wielaard 364b6d
+{
Mark Wielaard 364b6d
+   size_t i;
Mark Wielaard 364b6d
+   for(i = 0; i < sizeof(random_memory_pool) / sizeof(random_memory_pool[0]); i++)
Mark Wielaard 364b6d
+   {
Mark Wielaard 364b6d
+      random_memory_pool[i] = random_element();
Mark Wielaard 364b6d
+   }
Mark Wielaard 364b6d
+}
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+/* Define a test for input. Takes up theese arguments:
Mark Wielaard 364b6d
+      insn        -- instruction name
Mark Wielaard 364b6d
+      asm_string  -- line (or multiple lines) with asm mnemonics for instruction
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+   The folowing registers layout expected:
Mark Wielaard 364b6d
+      ("r" for register form and m for memory form)
Mark Wielaard 364b6d
+      v1         -- vector arg1
Mark Wielaard 364b6d
+      v2         -- vector arg2
Mark Wielaard 364b6d
+      v3         -- vector arg3
Mark Wielaard 364b6d
+      v5         -- vector result
Mark Wielaard 364b6d
+      [{r,m}_arg1]   -- integer arg1
Mark Wielaard 364b6d
+      [{r,m}_arg2]   -- integer arg2
Mark Wielaard 364b6d
+      [{r,m}_arg3]   -- integer arg3
Mark Wielaard 364b6d
+      [{r,m}_result]      -- integer result
Mark Wielaard 364b6d
+      [{r,m}_memory_pool] -- address of random memory pool. Usefull for some instructions
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+*/
Mark Wielaard 364b6d
+#define s390_test_generate(insn, asm_string) \
Mark Wielaard 364b6d
+static void test_##insn() \
Mark Wielaard 364b6d
+{ \
Mark Wielaard 364b6d
+   V128 v_result = { .u64 = {0ULL, 0ULL} }; \
Mark Wielaard 364b6d
+   V128 v_arg1; \
Mark Wielaard 364b6d
+   V128 v_arg2; \
Mark Wielaard 364b6d
+   V128 v_arg3; \
Mark Wielaard 364b6d
+   uint64_t r_arg1 = random_uint64_t(); \
Mark Wielaard 364b6d
+   uint64_t r_arg2 = random_uint64_t(); \
Mark Wielaard 364b6d
+   uint64_t r_arg3 = random_uint64_t(); \
Mark Wielaard 364b6d
+   uint64_t r_result = 0ULL; \
Mark Wielaard 364b6d
+    \
Mark Wielaard 364b6d
+   random_V128(&v_arg1); \
Mark Wielaard 364b6d
+   random_V128(&v_arg2); \
Mark Wielaard 364b6d
+   random_V128(&v_arg3); \
Mark Wielaard 364b6d
+    \
Mark Wielaard 364b6d
+   __asm__ volatile( \
Mark Wielaard 364b6d
+       "vl  %%v1, %[v_arg1]\n" \
Mark Wielaard 364b6d
+       "vl  %%v2, %[v_arg2]\n" \
Mark Wielaard 364b6d
+       "vl  %%v3, %[v_arg3]\n" \
Mark Wielaard 364b6d
+       "vone %%v5\n" \
Mark Wielaard 364b6d
+       asm_string "\n"\
Mark Wielaard 364b6d
+       "vst %%v5, %[v_result]\n" \
Mark Wielaard 364b6d
+       "vst %%v1, %[v_arg1]\n" \
Mark Wielaard 364b6d
+       "vst %%v2, %[v_arg2]\n" \
Mark Wielaard 364b6d
+       "vst %%v3, %[v_arg3]\n" \
Mark Wielaard 364b6d
+       : [v_result]      "=m" (v_result), \
Mark Wielaard 364b6d
+         [m_result]      "=m" (r_result), \
Mark Wielaard 364b6d
+         [r_result]      "+d" (r_result), \
Mark Wielaard 364b6d
+         [r_arg1]        "+d" (r_arg1), \
Mark Wielaard 364b6d
+         [r_arg2]        "+d" (r_arg2), \
Mark Wielaard 364b6d
+         [r_arg3]        "+d" (r_arg3) \
Mark Wielaard 364b6d
+       : [v_arg1]        "m" (v_arg1), \
Mark Wielaard 364b6d
+         [v_arg2]        "m" (v_arg2), \
Mark Wielaard 364b6d
+         [v_arg3]        "m" (v_arg3), \
Mark Wielaard 364b6d
+         [m_arg1]        "m" (r_arg1), \
Mark Wielaard 364b6d
+         [m_arg2]        "m" (r_arg2), \
Mark Wielaard 364b6d
+         [m_arg3]        "m" (r_arg3), \
Mark Wielaard 364b6d
+         [r_memory_pool] "r" (random_memory_pool), \
Mark Wielaard 364b6d
+         [m_memory_pool] "m" (random_memory_pool) \
Mark Wielaard 364b6d
+       : "memory", "cc", \
Mark Wielaard 364b6d
+         "r1", "r2", "r3", "r5", \
Mark Wielaard 364b6d
+         "v1", "v2", "v3", "v5"); \
Mark Wielaard 364b6d
+    \
Mark Wielaard 364b6d
+   printf("insn %s:\n", #insn); \
Mark Wielaard 364b6d
+   printf("  v_arg1   = "); print_hex(v_arg1); \
Mark Wielaard 364b6d
+   printf("  v_arg2   = "); print_hex(v_arg2); \
Mark Wielaard 364b6d
+   printf("  v_arg3   = "); print_hex(v_arg3); \
Mark Wielaard 364b6d
+   printf("  v_result = "); print_hex(v_result); \
Mark Wielaard 364b6d
+   printf("  r_arg1   = "); print_uint64_t(r_arg1); \
Mark Wielaard 364b6d
+   printf("  r_arg2   = "); print_uint64_t(r_arg2); \
Mark Wielaard 364b6d
+   printf("  r_arg3   = "); print_uint64_t(r_arg3); \
Mark Wielaard 364b6d
+   printf("  r_result = "); print_uint64_t(r_result); \
Mark Wielaard 364b6d
+}
Mark Wielaard 364b6d
+
Mark Wielaard 364b6d
+#endif