Bug 497723 - forgot to restore callgrind output cleanup
[valgrind.git] / none / tests / s390x / vector.h
blob23ae1e93844981ac484384d2bc76fb4a75e10778
1 #ifndef S390_TEST_VECTOR_H
2 #define S390_TEST_VECTOR_H
4 #include "stdbool.h"
5 #include "stdint.h"
6 #include "stdio.h"
7 #include "string.h"
9 /* How many times should every test be executed? */
10 #ifndef S390_TEST_COUNT
11 #define S390_TEST_COUNT 10
12 #endif
14 /* Test the instruction exactly one time. */
15 #define test_once(insn) test_##insn ()
17 /* Test the instruction exactly S390_TEST_COUNT times.
18 "..." arguments specifies code which must be executed after each tests
20 #define test(insn, ...) \
21 for(iteration = 0; iteration < S390_TEST_COUNT; iteration++) \
22 { test_once(insn); \
23 __VA_ARGS__; \
26 #define test_with_selective_printing(insn, info) \
27 for(iteration = 0; iteration < S390_TEST_COUNT; iteration++) \
28 { test_ ## insn ## _selective(info); }
30 #ifdef __GNUC__
31 /* GCC complains about __int128 with -pedantic */
32 /* Hope that we will have int128_t in C standard someday. */
33 #pragma GCC diagnostic ignored "-Wpedantic"
34 #endif
36 typedef union {
37 uint8_t u8[16];
38 int8_t s8[16];
40 uint16_t u16[8];
41 int16_t s16[8];
43 uint32_t u32[4];
44 int32_t s32[4];
45 float f32[4];
47 uint64_t u64[2];
48 int64_t s64[2];
49 double f64[2];
51 unsigned __int128 u128[1];
52 __int128 s128[1];
53 } V128;
55 typedef enum {
56 V128_NO_PRINTING = 0,
57 V128_V_RES_AS_INT = 1 << 0,
58 V128_V_ARG1_AS_INT = 1 << 1,
59 V128_V_ARG2_AS_INT = 1 << 2,
60 V128_V_ARG3_AS_INT = 1 << 3,
61 V128_V_RES_AS_FLOAT64 = 1 << 4,
62 V128_V_ARG1_AS_FLOAT64 = 1 << 5,
63 V128_V_ARG2_AS_FLOAT64 = 1 << 6,
64 V128_V_ARG3_AS_FLOAT64 = 1 << 7,
65 V128_V_RES_AS_FLOAT32 = 1 << 8,
66 V128_V_ARG1_AS_FLOAT32 = 1 << 9,
67 V128_V_ARG2_AS_FLOAT32 = 1 << 10,
68 V128_V_ARG3_AS_FLOAT32 = 1 << 11,
69 V128_R_RES = 1 << 12,
70 V128_R_ARG1 = 1 << 13,
71 V128_R_ARG2 = 1 << 14,
72 V128_R_ARG3 = 1 << 15,
73 V128_V_RES_EVEN_ONLY = 1 << 16,
74 V128_V_RES_ZERO_ONLY = 1 << 17,
75 V128_PRINT_ALL = (V128_V_RES_AS_INT |
76 V128_V_ARG1_AS_INT |
77 V128_V_ARG2_AS_INT |
78 V128_V_ARG3_AS_INT |
79 V128_R_RES |
80 V128_R_ARG1 |
81 V128_R_ARG2 |
82 V128_R_ARG3),
83 } s390x_test_usageInfo;
85 void print_hex(const V128 value) {
86 printf("%016lx | %016lx\n", value.u64[0], value.u64[1]);
89 void print_hex64(const V128 value, int zero_only) {
90 if (zero_only)
91 printf("%016lx | --\n", value.u64[0]);
92 else
93 printf("%016lx | %016lx\n", value.u64[0], value.u64[1]);
96 void print_f32(const V128 value, int even_only, int zero_only) {
97 if (zero_only)
98 printf("%a | -- | -- | --\n", value.f32[0]);
99 else if (even_only)
100 printf("%a | -- | %a | --\n", value.f32[0], value.f32[2]);
101 else
102 printf("%a | %a | %a | %a\n",
103 value.f32[0], value.f32[1], value.f32[2], value.f32[3]);
106 void print_f64(const V128 value, int zero_only) {
107 if (zero_only)
108 printf("%a | --\n", value.f64[0]);
109 else
110 printf("%a | %a\n", value.f64[0], value.f64[1]);
113 void print_uint64_t(const uint64_t value) {
114 printf("%016lx\n", value);
117 uint8_t random_element ( void )
119 static uint32_t seed = 80021;
120 seed = 1103515245 * seed + 12345;
121 return (seed >> 17) & 0xFF;
124 void random_V128 (V128 *block)
126 size_t i;
127 for(i = 0; i < 16; i++)
129 block->u8[i] = random_element();
133 uint64_t random_uint64_t()
135 uint64_t result = 0ULL;
136 uint8_t *ptr = (uint8_t *) &result;
137 size_t i;
138 for(i = 0; i < 8; i++)
140 ptr[i] = random_element();
143 return result;
146 /* Memory pool with some random data. Used for some instruction which need
147 an address to some memory chunk.
148 Pool should be large enough for all insn that use it.
149 (64 bytes and aligning are needed by VLBB insn)
151 Content of this pool must be updated every iteration but not from test to test.
153 uint8_t random_memory_pool[64] __attribute__ ((aligned (64)));
154 void randomize_memory_pool()
156 size_t i;
157 for(i = 0; i < sizeof(random_memory_pool) / sizeof(random_memory_pool[0]); i++)
159 random_memory_pool[i] = random_element();
163 /* Define a test for input. Takes up theese arguments:
164 insn -- instruction name
165 asm_string -- line (or multiple lines) with asm mnemonics for instruction
167 The folowing registers layout expected:
168 ("r" for register form and m for memory form)
169 v1 -- vector arg1
170 v2 -- vector arg2
171 v3 -- vector arg3
172 v5 -- vector result
173 [{r,m}_arg1] -- integer arg1
174 [{r,m}_arg2] -- integer arg2
175 [{r,m}_arg3] -- integer arg3
176 [{r,m}_result] -- integer result
177 [{r,m}_memory_pool] -- address of random memory pool. Useful for some instructions
181 struct insn_operands {
182 V128 v_arg[3];
183 V128 v_result;
184 uint64_t r_arg[3];
185 uint64_t r_result;
188 void print_results(s390x_test_usageInfo info,
189 const struct insn_operands *orig,
190 const struct insn_operands *current)
192 unsigned int v_equal = 0;
193 unsigned int r_equal = 0;
194 int i;
195 for (i = 0; i < 3; i++) {
196 if (memcmp(&orig->v_arg[i], &current->v_arg[i],
197 sizeof(orig->v_arg[i])) == 0)
198 v_equal |= 1 << i;
199 if (orig->r_arg[i] == current->r_arg[i])
200 r_equal |= 1 << i;
202 for (i = 0; i < 3; i++) {
203 if (!(v_equal & (1 << i)) && (info & (V128_V_ARG1_AS_INT << i))) {
204 printf(" v_arg%d = ", i + 1);
205 print_hex(current->v_arg[i]);
208 if (info & V128_V_RES_AS_INT) {
209 printf(" v_result = ");
210 print_hex64(current->v_result, info & V128_V_RES_ZERO_ONLY);
212 for (i = 0; i < 3; i++) {
213 if (!(v_equal & (1 << i)) && (info & (V128_V_ARG1_AS_FLOAT64 << i))) {
214 printf(" v_arg%d = ", i + 1);
215 print_f64(current->v_arg[i], 0);
218 if (info & V128_V_RES_AS_FLOAT64) {
219 printf(" v_result = ");
220 print_f64(current->v_result, info & V128_V_RES_ZERO_ONLY);
222 for (i = 0; i < 3; i++) {
223 if (!(v_equal & (1 << i)) && (info & (V128_V_ARG1_AS_FLOAT32 << i))) {
224 printf(" v_arg%d = ", i + 1);
225 print_f32(current->v_arg[i], 0, 0);
228 if (info & V128_V_RES_AS_FLOAT32) {
229 printf(" v_result = ");
230 print_f32(current->v_result, info & V128_V_RES_EVEN_ONLY,
231 info & V128_V_RES_ZERO_ONLY);
233 for (i = 0; i < 3; i++) {
234 if (!(r_equal & (1 << i)) && (info & (V128_R_ARG1 << i))) {
235 printf(" r_arg%d = ", i + 1);
236 print_uint64_t(current->r_arg[i]);
239 if (info & V128_R_RES) {
240 printf(" r_result = ");
241 print_uint64_t(current->r_result);
245 #define s390_test_generate(insn, asm_string) \
246 static void test_##insn##_selective(const s390x_test_usageInfo info) \
248 struct insn_operands orig = { .v_result.u64 = {0ULL, 0ULL} }; \
249 struct insn_operands current; \
250 orig.r_arg[0] = random_uint64_t(); \
251 orig.r_arg[1] = random_uint64_t(); \
252 orig.r_arg[2] = random_uint64_t(); \
253 orig.r_result = 0ULL; \
254 random_V128(&orig.v_arg[0]); \
255 random_V128(&orig.v_arg[1]); \
256 random_V128(&orig.v_arg[2]); \
257 current = orig; \
259 __asm__ volatile( \
260 "vl %%v1, %[v_arg1]\n" \
261 "vl %%v2, %[v_arg2]\n" \
262 "vl %%v3, %[v_arg3]\n" \
263 "vone %%v5\n" \
264 "srnmb 1(0)\n " \
265 asm_string "\n"\
266 "vst %%v5, %[v_result]\n" \
267 "vst %%v1, %[v_arg1]\n" \
268 "vst %%v2, %[v_arg2]\n" \
269 "vst %%v3, %[v_arg3]\n" \
270 : [v_result] "+R" (current.v_result), \
271 [r_result] "+d" (current.r_result), \
272 [r_arg1] "+a" (current.r_arg[0]), \
273 [r_arg2] "+a" (current.r_arg[1]), \
274 [r_arg3] "+a" (current.r_arg[2]), \
275 [v_arg1] "+R" (current.v_arg[0]), \
276 [v_arg2] "+R" (current.v_arg[1]), \
277 [v_arg3] "+R" (current.v_arg[2]) \
278 : [m_arg1] "R" (current.r_arg[0]), \
279 [m_arg2] "R" (current.r_arg[1]), \
280 [m_arg3] "R" (current.r_arg[2]), \
281 [r_memory_pool] "d" (random_memory_pool), \
282 [m_memory_pool] "R" (random_memory_pool) \
283 : "cc", "v1", "v2", "v3", "v5"); \
285 printf("insn %s:\n", #insn); \
286 print_results(info, &orig, &current); \
288 __attribute__((unused)) static void test_##insn() \
290 test_##insn##_selective (V128_PRINT_ALL); \
293 /* Stores CC to %[r_result].
294 Useful when testing instructions which modify condition code.
296 #define S390_TEST_PUT_CC_TO_RESULT "ipm %[r_result] \n srl %[r_result], 28 \n"
298 #endif