Bug 497723 - forgot to restore callgrind output cleanup
[valgrind.git] / none / tests / s390x / lsc2.c
blobd8f59f72c9be9477170a3339b26698ce0952de9f
1 /*
2 * s390x z13 instructions test
4 * Copyright (c) 2017 Vadim Barkov
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #define _GNU_SOURCE
20 #include "assert.h"
21 #include "math.h"
22 #include "stdbool.h"
23 #include "stdint.h"
24 #include "stdio.h"
25 #include "string.h"
27 /* Colors for output */
28 #ifndef S390_TESTS_NOCOLOR
29 # define RED "\033[31m"
30 # define GREEN "\033[32m"
31 # define RESET "\033[0m"
32 #else
33 # define RED
34 # define GREEN
35 # define RESET
36 #endif
38 #define printPassed(insn) \
39 printf(RESET "%15s :\t " GREEN "PASSED" RESET "\n", #insn)
40 #define printFailed(insn) \
41 printf(RESET "%15s :\t " RED "FAILED" RESET "\n", #insn)
43 #define test(insn) \
44 { \
45 if (test_##insn()) \
46 printPassed(insn); \
47 else \
48 printFailed(insn); \
51 #define SMART_RETURN_R64(insn) \
52 bool result = after == expected; \
53 if (!result) { \
54 printf("[ERROR] %s:\n", #insn); \
55 printf("after: %lx\n", (uint64_t) after); \
56 printf("expected: %lx\n", (uint64_t) expected); \
57 } \
58 return result
60 /* Constant value for immediate instructions' tests */
61 #define IMMEDIATE_VALUE 0x0abc
62 #define IMMEDIATE_VALUE_STR "0x0abc"
64 /* Useful macros for testing many input values
65 and printing message after test execution
67 #define test_each(type, var, instruction) \
68 { \
69 type##_foreach((var), test_##instruction((var))); \
72 #define test_range(var, from, to, instruction) \
73 { \
74 bool result = true; \
75 __int_foreach(var, from, to, result &= (test_##instruction((var)))); \
76 if (result) \
77 printPassed(instruction); \
78 else \
79 printFailed(instruction); \
82 #define __int_foreach(var, minValue, maxValue, statement) \
83 { \
84 for (var = minValue; var < maxValue; var++) { \
85 statement; \
86 } \
88 { statement; } \
91 #define uint32_foreach(var, statement) \
92 __int_foreach(var, 0, UINT32_MAX, statement)
93 #define int32_foreach(var, statement) \
94 __int_foreach(var, INT32_MIN, INT32_MAX, statement)
95 #define uint64_foreach(var, statement) \
96 __int_foreach(var, 0, UINT64_MAX, statement)
98 /* load and zero rightmost byte */
99 static bool test_lzrf(const uint32_t testedValue)
101 uint32_t after;
102 uint32_t expected = testedValue & 0xffffff00;
104 __asm__ volatile("lzrf %0, %1" : "=d"(after) : "T"(testedValue) : );
105 SMART_RETURN_R64(lzrf);
108 /* load and zero rightmost byte 64bit*/
109 static bool test_lzrg(const uint64_t testedValue)
111 uint64_t after = testedValue;
112 uint64_t expected = testedValue & 0xffffffffffffff00UL;
114 __asm__ volatile("lzrg %0, %1" : "=d"(after) : "T"(testedValue) : );
115 SMART_RETURN_R64(lzrg);
118 /* load logical and zero rightmost byte */
119 static bool test_llzrgf(const uint32_t testedValue)
121 uint64_t after = 0;
122 uint32_t expected = testedValue & 0xffffff00;
124 __asm__ volatile("llzrgf %0, %1" : "=d"(after) : "T"(testedValue) : );
125 SMART_RETURN_R64(llzrgf);
128 /* compare instructions */
129 #define __compare_r "cr"
130 #define __compare_m "c"
132 /* load high on condition */
133 #define declare_load_high_on_condition(TESTED_INSTRUCTION, CONDITION_SYMBOL, \
134 ARGUMENT_ASM_TYPE) \
135 bool test_##TESTED_INSTRUCTION(const int32_t testedValue) \
137 uint64_t expected; \
138 const uint64_t valueBeforeTest = 0x6666666699999999UL; \
139 const uint64_t overrideValue = 0xeeeeeeeeeeeeeeeeUL; \
140 const int32_t invertedValue = testedValue ^ 0xffffffff; \
141 uint64_t after = valueBeforeTest; \
142 if (testedValue CONDITION_SYMBOL invertedValue) { \
143 expected = 0xeeeeeeee99999999UL; \
144 } else { \
145 expected = valueBeforeTest; \
148 __asm__ volatile( \
149 "cr %[testedValue], %[invertedValue]\n" #TESTED_INSTRUCTION \
150 " %[after], %[overrideValue]\n" \
151 : [after] "+d"(after) \
152 : [testedValue] "d"(testedValue), \
153 [invertedValue] "d"(invertedValue), \
154 [overrideValue] #ARGUMENT_ASM_TYPE(overrideValue) \
155 : "cc"); \
157 SMART_RETURN_R64(TESTED_INSTRUCTION); \
160 declare_load_high_on_condition(locfhre, ==, d)
161 declare_load_high_on_condition(locfhrne, !=, d)
162 declare_load_high_on_condition(locfhrh, >, d)
163 declare_load_high_on_condition(locfhrl, <, d)
164 declare_load_high_on_condition(locfhe, ==, Q)
165 declare_load_high_on_condition(locfhne, !=, Q)
166 declare_load_high_on_condition(locfhh, >, Q)
167 declare_load_high_on_condition(locfhl, <, Q)
169 /* store high on condition */
170 #define declare_store_high_on_condition(TESTED_INSTRUCTION, CONDITION_SYMBOL, \
171 ARGUMENT_ASM_TYPE) \
172 bool test_##TESTED_INSTRUCTION(const int32_t testedValue) \
174 uint64_t expected; \
175 const uint64_t valueBeforeTest = 0x6666666699999999UL; \
176 const uint64_t overrideValue = 0xeeeeeeeeeeeeeeeeUL; \
177 const int32_t invertedValue = testedValue ^ 0xffffffff; \
178 uint64_t after = valueBeforeTest; \
179 if (testedValue CONDITION_SYMBOL invertedValue) { \
180 expected = 0xeeeeeeee99999999UL; \
181 } else { \
182 expected = valueBeforeTest; \
185 __asm__ volatile( \
186 "cr %[testedValue], %[invertedValue]\n" #TESTED_INSTRUCTION \
187 " %[overrideValue], %[after]\n" \
188 : [after] "+" #ARGUMENT_ASM_TYPE(after) \
189 : [testedValue] "d"(testedValue), \
190 [invertedValue] "d"(invertedValue), \
191 [overrideValue] "d"(overrideValue) \
192 : "cc"); \
194 SMART_RETURN_R64(TESTED_INSTRUCTION); \
197 declare_store_high_on_condition(stocfhe, ==, Q)
198 declare_store_high_on_condition(stocfhne, !=, Q)
199 declare_store_high_on_condition(stocfhh, >, Q)
200 declare_store_high_on_condition(stocfhl, <, Q)
202 #define __format_uint32_t "%x"
203 #define __format_uint64_t "%lx"
204 #define __halfword_valueBefore_uint32_t 0x66669999
205 #define __halfword_valueBefore_uint64_t 0x6666666699999999UL
206 /* load halfword immediate on condition */
207 #define declare_load_halfword_immediate_on_condition( \
208 TESTED_INSTRUCTION, ARGUMENT_TYPE, CONDITION_SYMBOL, ARGUMENT_ASM_TYPE) \
209 bool test_##TESTED_INSTRUCTION(const int32_t testedValue) \
211 ARGUMENT_TYPE expected; \
212 const ARGUMENT_TYPE valueBeforeTest = \
213 __halfword_valueBefore_##ARGUMENT_TYPE; \
214 const int32_t invertedValue = testedValue ^ 0xffffffff; \
215 ARGUMENT_TYPE after = valueBeforeTest; \
216 if (testedValue CONDITION_SYMBOL invertedValue) { \
217 expected = IMMEDIATE_VALUE; \
218 } else { \
219 expected = valueBeforeTest; \
222 __asm__ volatile( \
223 "cr %[testedValue], %[invertedValue]\n" #TESTED_INSTRUCTION \
224 " %[after], " IMMEDIATE_VALUE_STR "\n" \
225 : [after] "+d"(after) \
226 : [testedValue] "d"(testedValue), \
227 [invertedValue] "d"(invertedValue) \
228 : "cc"); \
230 SMART_RETURN_R64(TESTED_INSTRUCTION); \
233 declare_load_halfword_immediate_on_condition(lochie, uint32_t, ==, r)
234 declare_load_halfword_immediate_on_condition(lochine, uint32_t, !=, r)
235 declare_load_halfword_immediate_on_condition(lochih, uint32_t, >, r)
236 declare_load_halfword_immediate_on_condition(lochil, uint32_t, <, r)
237 declare_load_halfword_immediate_on_condition(locghie, uint64_t, ==, r)
238 declare_load_halfword_immediate_on_condition(locghine, uint64_t, !=, r)
239 declare_load_halfword_immediate_on_condition(locghih, uint64_t, >, r)
240 declare_load_halfword_immediate_on_condition(locghil, uint64_t, <, r)
242 /* load halfword high immediate on condition */
243 #define declare_load_halfword_high_immediate_on_condition( \
244 TESTED_INSTRUCTION, CONDITION_SYMBOL, ARGUMENT_ASM_TYPE) \
245 bool test_##TESTED_INSTRUCTION(const int32_t testedValue) \
247 uint64_t expected; \
248 const uint64_t valueBeforeTest = __halfword_valueBefore_uint64_t; \
249 const int32_t invertedValue = testedValue ^ 0xffffffff; \
250 uint64_t after = valueBeforeTest; \
251 if (testedValue CONDITION_SYMBOL invertedValue) { \
252 expected = IMMEDIATE_VALUE; \
253 expected <<= 32; \
254 expected += \
255 __halfword_valueBefore_uint64_t & 0x00000000ffffffffUL; \
256 } else { \
257 expected = valueBeforeTest; \
260 __asm__ volatile( \
261 "cr %[testedValue], %[invertedValue]\n" #TESTED_INSTRUCTION \
262 " %[after], " IMMEDIATE_VALUE_STR "\n" \
263 : [after] "+d"(after) \
264 : [testedValue] "d"(testedValue), \
265 [invertedValue] "d"(invertedValue) \
266 : "cc"); \
268 SMART_RETURN_R64(TESTED_INSTRUCTION); \
271 declare_load_halfword_high_immediate_on_condition(lochhie, ==, r)
272 declare_load_halfword_high_immediate_on_condition(lochhine, !=, r)
273 declare_load_halfword_high_immediate_on_condition(lochhih, >, r)
274 declare_load_halfword_high_immediate_on_condition(lochhil, <, r)
276 static void test_all_locfh()
278 int32_t signed32bit = 0;
280 test_each(int32, signed32bit, locfhe);
281 test_each(int32, signed32bit, locfhne);
282 test_each(int32, signed32bit, locfhh);
283 test_each(int32, signed32bit, locfhl);
285 test_each(int32, signed32bit, locfhre);
286 test_each(int32, signed32bit, locfhrne);
287 test_each(int32, signed32bit, locfhrh);
288 test_each(int32, signed32bit, locfhrl);
291 /* load count to block boundary */
292 #define declare_load_count_to_block_boundary(M_FIELD) \
293 bool test_lcbb##M_FIELD(const uint32_t testedValue) \
295 const size_t boundary = 64 * (1UL << (M_FIELD)); \
296 const uint32_t *testedPointer = \
297 (uint32_t *)(boundary - \
298 ((testedValue < boundary) ? testedValue : 0)); \
299 uint32_t after = 0; \
300 uint32_t expected = boundary - ((size_t)testedPointer % boundary); \
301 if (expected > 16) \
302 expected = 16; \
304 __asm__ volatile("lcbb %[after], %[testedPointer], " #M_FIELD \
305 "\n" \
306 : [after] "=d"(after) \
307 : [testedPointer] "R"(*testedPointer) \
308 : "cc"); \
310 SMART_RETURN_R64(lcbb##M_FIELD); \
313 declare_load_count_to_block_boundary(0)
314 declare_load_count_to_block_boundary(1)
315 declare_load_count_to_block_boundary(2)
316 declare_load_count_to_block_boundary(3)
317 declare_load_count_to_block_boundary(4)
318 declare_load_count_to_block_boundary(5)
319 declare_load_count_to_block_boundary(6)
321 static bool test_lcbb0_cc(const uint32_t testedValue)
323 const size_t boundary = 64;
324 const uint32_t *testedPointer =
325 (uint32_t *)(boundary -
326 ((testedValue < boundary) ? testedValue : 0));
327 uint32_t expectedForLCBB = boundary - ((size_t)testedPointer % boundary);
329 uint32_t after = 0;
330 uint32_t expected = (expectedForLCBB >= 16) ? 0 : 3;
331 __asm__ volatile("lcbb %[cc], %[testedPointer], 0 \n"
332 "ipm %[cc] \n"
333 "srl %[cc], 28 \n"
334 : [cc] "=d"(after)
335 : [testedPointer] "R"(*testedPointer)
336 : "cc");
337 SMART_RETURN_R64(lcbb0_cc);
341 static void test_all_lzr()
343 uint32_t unsigned32bit = 0;
345 test_each(uint32, unsigned32bit, lzrf);
346 test_each(uint32, unsigned32bit, lzrg);
349 static void test_all_stocfh()
351 int32_t signed32bit = 0;
353 test_each(int32, signed32bit, stocfhne);
354 test_each(int32, signed32bit, stocfhe);
355 test_each(int32, signed32bit, stocfhh);
356 test_each(int32, signed32bit, stocfhl);
359 static void test_all_lochi()
361 int32_t signed32bit = 0;
363 test_each(int32, signed32bit, locghine);
364 test_each(int32, signed32bit, locghine);
365 test_each(int32, signed32bit, locghih);
366 test_each(int32, signed32bit, locghil);
368 test_each(int32, signed32bit, lochine);
369 test_each(int32, signed32bit, lochie);
370 test_each(int32, signed32bit, lochil);
371 test_each(int32, signed32bit, lochih);
374 static void test_all_lochhi()
376 int32_t signed32bit = 0;
378 test_each(int32, signed32bit, lochhine);
379 test_each(int32, signed32bit, lochhie);
380 test_each(int32, signed32bit, lochhih);
381 test_each(int32, signed32bit, lochhil);
384 static void test_all_lcbb()
386 size_t tested = 0;
388 test_range(tested, 0, 64, lcbb0);
389 test_range(tested, 0, 128, lcbb1);
390 test_range(tested, 0, 256, lcbb2);
391 test_range(tested, 0, 512, lcbb3);
392 test_range(tested, 0, 1024, lcbb4);
393 test_range(tested, 0, 2048, lcbb5);
394 test_range(tested, 0, 4096, lcbb6);
395 test_range(tested, 0, 64, lcbb0_cc);
398 void test_long_all() {
399 uint64_t unsigned64bit = 0;
401 test_all_lcbb();
402 test_all_lochhi();
403 test_all_lochi();
404 test_all_stocfh();
405 test_all_locfh();
406 test_all_lzr();
407 test_each(uint64, unsigned64bit, llzrgf);
410 #define SHORT_TESTS_UNSIGNED_FROM 0
411 #define SHORT_TESTS_SIGNED_FROM -0xffff
412 #define SHORT_TESTS_TO 0xffff
414 void test_short_all()
416 uint32_t unsigned32bit = 0;
417 int32_t signed32bit = 0;
418 uint64_t unsigned64bit = 0;
420 test_range(unsigned32bit, SHORT_TESTS_UNSIGNED_FROM, SHORT_TESTS_TO, lzrf);
421 test_range(unsigned64bit, SHORT_TESTS_UNSIGNED_FROM, SHORT_TESTS_TO, lzrg);
422 test_range(unsigned64bit, SHORT_TESTS_UNSIGNED_FROM, SHORT_TESTS_TO, llzrgf);
424 /* stocfh */
425 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, stocfhne);
426 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, stocfhe);
427 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, stocfhh);
428 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, stocfhl);
430 /* locfh */
431 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locfhe);
432 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locfhne);
433 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locfhh);
434 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locfhl);
436 /* locfhr */
437 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locfhre);
438 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locfhrne);
439 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locfhrh);
440 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locfhrl);
442 /* lochhi */
443 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, lochhine);
444 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, lochhie);
445 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, lochhih);
446 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, lochhil);
448 /* lochi */
449 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, lochine);
450 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, lochie);
451 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, lochih);
452 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, lochil);
454 /* locghi */
455 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locghine);
456 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locghie);
457 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locghih);
458 test_range(signed32bit, SHORT_TESTS_SIGNED_FROM, SHORT_TESTS_TO, locghil);
460 test_all_lcbb(); /* These test is not long, so we can run it on all range */
463 int main(int argc, char *argv[])
465 bool shouldRunLongTests = false;
467 /* --long option forces to test all possible values (it is very long)*/
468 if (argc > 1)
469 if (strcmp(argv[1], "--long") == 0)
470 shouldRunLongTests = true;
472 printf("Tests started:\n");
473 if (shouldRunLongTests)
474 test_long_all();
475 else
476 test_short_all();
478 printf("Tests ended.\n");
479 return 0;