Bug 497723 - forgot to restore callgrind output cleanup
[valgrind.git] / none / tests / s390x / cksm.c
blobaa83ca46d82339e82692a40c75248b020ff05612
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <inttypes.h>
4 #include "test.h"
6 uint32_t data[64];
8 /* The result of a checksum operation */
9 typedef struct {
10 uint64_t addr;
11 uint64_t len;
12 uint32_t sum;
13 char cc;
14 } cksm_t;
17 /* Compute the checksum via the cksm insn */
18 static __attribute__((noinline)) cksm_t
19 cksm_by_insn(const uint32_t *buff, uint64_t len, uint32_t sum)
21 const uint32_t *init_addr = buff;
22 uint64_t init_length = len;
23 uint64_t addr;
24 char cc;
25 cksm_t result;
26 register uint64_t reg2 asm("2") = (uint64_t) buff;
27 register uint64_t reg3 asm("3") = len;
29 asm volatile( " cr 0,0\n\t" /* set cc to 0 */
30 "0: cksm %0,%1\n\t" /* do checksum on longs */
31 " jo 0b\n\t"
32 : "+d" (sum), "+a" (reg2), "+a" (reg3) : : "cc");
34 cc = get_cc();
35 len = reg3;
36 addr = reg2;
38 /* Check the results */
39 if(addr != (uint64_t)init_addr + init_length)
40 printf("FAIL: address not updated properly\n");
42 if(len != 0)
43 printf("FAIL: length not zero\n");
45 if (cc != 0)
46 printf("FAIL: condition code not zero\n");
48 result.addr = addr;
49 result.len = len;
50 result.cc = cc;
51 result.sum = sum;
53 return result;
57 /* Compute the checksum via hand-crafted algorithm */
58 static __attribute__((noinline)) cksm_t
59 cksm_by_hand(const uint32_t *buff, uint64_t len, uint32_t sum)
61 cksm_t result;
62 unsigned int n;
63 uint64_t v64;
64 uint32_t final;
66 for (n=0; n < len/4; n++) {
67 /* Add 4 bytes to the sum. Do this in 64-bit arithmetic so it's
68 easy to see whether there was a carry-out. */
69 v64 = sum;
70 v64 += buff[n];
71 /* If there was a carry-out, add 1 to the sum. */
72 if (v64 >> 32)
73 sum = sum + buff[n] + 1;
74 else
75 sum = sum + buff[n];
78 if (len != 0) {
79 switch (len % 4) {
80 case 0:
81 final = 0; // suppress gcc warning
82 /* done */
83 break;
85 case 1:
86 final = buff[n] & 0xFF000000;
87 break;
89 case 2:
90 final = buff[n] & 0xFFFF0000;
91 break;
93 case 3:
94 final = buff[n] & 0xFFFFFF00;
95 break;
98 if (len % 4) {
99 v64 = sum;
100 v64 += final;
101 /* If there was a carry-out, add 1 to the sum. */
102 if (v64 >> 32)
103 sum = sum + final + 1;
104 else
105 sum = sum + final;
109 result.addr = (uint64_t)buff + len;
110 result.len = 0;
111 result.cc = 0;
112 result.sum = sum;
114 return result;
117 /* The results computed by-insn and by-hand must compare equal and
118 the sum must be identical to EXPECTED_SUM. */
120 compare_results(cksm_t by_hand, cksm_t by_insn, uint32_t expected_sum)
122 int rc = 0;
124 if (by_hand.sum != by_insn.sum) {
125 ++rc;
126 printf("FAIL: sum: by-hand %"PRIx32" by-insn %"PRIx32"\n",
127 by_hand.sum, by_insn.sum);
130 if (by_hand.addr != by_insn.addr) {
131 ++rc;
132 printf("FAIL: addr: by-hand %"PRIx64" by-insn %"PRIx64"\n",
133 by_hand.addr, by_insn.addr);
136 if (by_hand.len != by_insn.len) {
137 ++rc;
138 printf("FAIL: len: by-hand %"PRIx64" by-insn %"PRIx64"\n",
139 by_hand.len, by_insn.len);
142 if (by_hand.cc != by_insn.cc) {
143 ++rc;
144 printf("FAIL: cc: by-hand %d by-insn %d\n",
145 by_hand.cc, by_insn.cc);
148 if (by_insn.sum != expected_sum) {
149 ++rc;
150 printf("FAIL: sum: by-insn %"PRIx32" expected %"PRIx32"\n",
151 by_insn.sum, expected_sum);
154 if (by_hand.sum != expected_sum) {
155 ++rc;
156 printf("FAIL: sum: by-hand %"PRIx32" expected %"PRIx32"\n",
157 by_hand.sum, expected_sum);
160 return rc;
163 /* Run a testcase. Compute the checksum by-hand and by-insn and compare
164 the results */
165 void
166 run_test(const char *name, const uint32_t *buff, uint64_t len, uint32_t sum,
167 uint32_t expected_sum)
169 cksm_t by_hand, by_insn;
171 by_hand = cksm_by_hand(buff, len, sum);
172 by_insn = cksm_by_insn(buff, len, sum);
173 if (compare_results(by_hand, by_insn, expected_sum) != 0) {
174 printf("%s failed\n", name);
178 int main ()
180 uint32_t sum, expected_sum;
181 uint64_t len;
183 /* ---------------- test 1 ------------------------------ */
184 /* Add one word to an initial sum; no carry */
185 sum = 2;
186 data[0] = 1;
187 len = 4;
188 expected_sum = 3;
189 run_test("test1", data, len, sum, expected_sum);
191 /* ---------------- test 2 ------------------------------ */
192 /* Add one word to an initial sum; with carry */
193 sum = 1;
194 data[0] = 0xffffffff;
195 len = 4;
196 expected_sum = 1;
197 run_test("test2", data, len, sum, expected_sum);
199 /* ---------------- test 3 ------------------------------ */
200 /* Add 15 words to an initial sum; no carry */
201 sum = 0x1;
202 data[0] = 0x4;
203 data[1] = 0x10;
204 data[2] = 0x40;
205 data[3] = 0x100;
206 data[4] = 0x400;
207 data[5] = 0x1000;
208 data[6] = 0x4000;
209 data[7] = 0x10000;
210 data[8] = 0x40000;
211 data[9] = 0x100000;
212 data[10] = 0x400000;
213 data[11] = 0x1000000;
214 data[12] = 0x4000000;
215 data[13] = 0x10000000;
216 data[14] = 0x40000000;
217 len = 60;
218 expected_sum = 0x55555555;
219 run_test("test3", data, len, sum, expected_sum);
221 /* ---------------- test 4 ------------------------------ */
222 /* Add some words such that every addition generates a carry.
223 The data is such that the least significant byte is zero,
224 and the carrys from intermediate additions will accumulate
225 in the least significant byte. */
226 sum = 0xff000000;
227 data[0] = 0x80000000; /* 7f0000001 */
228 data[1] = 0x85000000; /* 040000002 */
229 data[2] = 0xff000000; /* 030000003 */
230 data[3] = 0xff000000; /* 020000004 */
231 data[4] = 0xff000000; /* 010000005 */
232 data[5] = 0xff000000; /* 000000006 */
233 len = 24;
234 expected_sum = 0x00000006;
235 run_test("test4", data, len, sum, expected_sum);
237 /* ---------------- test 5 ------------------------------ */
238 /* No words are added. Pass a NULL pointer so an attempt to
239 load would raise a SIGSEGV. */
240 len = 0;
241 sum = 42;
242 expected_sum = sum;
243 run_test("test5", NULL, len, sum, expected_sum);
245 /* ---------------- test 6 ------------------------------ */
246 /* Add 1 byte; no carry */
247 sum = 0x02000000;
248 len = 1;
249 data[0] = 0x7fffffff;
250 expected_sum = 0x81000000;
251 run_test("test6", data, len, sum, expected_sum);
253 /* ---------------- test 7 ------------------------------ */
254 /* Add 1 byte; carry */
255 sum = 0x02000000;
256 len = 1;
257 data[0] = 0xffffffff;
258 expected_sum = 0x01000001;
259 run_test("test7", data, len, sum, expected_sum);
261 /* ---------------- test 8 ------------------------------ */
262 /* Add 2 bytes; no carry */
263 sum = 0x00020000;
264 len = 2;
265 data[0] = 0x7fffffff;
266 expected_sum = 0x80010000;
267 run_test("test8", data, len, sum, expected_sum);
269 /* ---------------- test 9 ------------------------------ */
270 /* Add 2 bytes; carry */
271 sum = 0x00020000;
272 len = 2;
273 data[0] = 0xffffffff;
274 expected_sum = 0x00010001;
275 run_test("test9", data, len, sum, expected_sum);
277 /* ---------------- test 10 ------------------------------ */
278 /* Add 3 bytes; no carry */
279 sum = 0x00000200;
280 len = 3;
281 data[0] = 0x7fffffff;
282 expected_sum = 0x80000100;
283 run_test("test10", data, len, sum, expected_sum);
285 /* ---------------- test 11 ------------------------------ */
286 /* Add 3 bytes; carry */
287 sum = 0x00000200;
288 len = 3;
289 data[0] = 0xffffffff;
290 expected_sum = 0x00000101;
291 run_test("test11", data, len, sum, expected_sum);
293 return 0;