1 #ifndef S390_TEST_VECTOR_H
2 #define S390_TEST_VECTOR_H
9 /* How many times should every test be executed? */
10 #ifndef S390_TEST_COUNT
11 #define S390_TEST_COUNT 10
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++) \
26 #define test_with_selective_printing(insn, info) \
27 for(iteration = 0; iteration < S390_TEST_COUNT; iteration++) \
28 { test_ ## insn ## _selective(info); }
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"
51 unsigned __int128 u128
[1];
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,
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
|
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
) {
91 printf("%016lx | --\n", value
.u64
[0]);
93 printf("%016lx | %016lx\n", value
.u64
[0], value
.u64
[1]);
96 void print_f32(const V128 value
, int even_only
, int zero_only
) {
98 printf("%a | -- | -- | --\n", value
.f32
[0]);
100 printf("%a | -- | %a | --\n", value
.f32
[0], value
.f32
[2]);
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
) {
108 printf("%a | --\n", value
.f64
[0]);
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
)
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
;
138 for(i
= 0; i
< 8; i
++)
140 ptr
[i
] = random_element();
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()
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)
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
{
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;
195 for (i
= 0; i
< 3; i
++) {
196 if (memcmp(&orig
->v_arg
[i
], ¤t
->v_arg
[i
],
197 sizeof(orig
->v_arg
[i
])) == 0)
199 if (orig
->r_arg
[i
] == current
->r_arg
[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]); \
260 "vl %%v1, %[v_arg1]\n" \
261 "vl %%v2, %[v_arg2]\n" \
262 "vl %%v3, %[v_arg3]\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, ¤t); \
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"