8 /* The result of a checksum operation */
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
;
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 */
32 : "+d" (sum
), "+a" (reg2
), "+a" (reg3
) : : "cc");
38 /* Check the results */
39 if(addr
!= (uint64_t)init_addr
+ init_length
)
40 printf("FAIL: address not updated properly\n");
43 printf("FAIL: length not zero\n");
46 printf("FAIL: condition code not zero\n");
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
)
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. */
71 /* If there was a carry-out, add 1 to the sum. */
73 sum
= sum
+ buff
[n
] + 1;
81 final
= 0; // suppress gcc warning
86 final
= buff
[n
] & 0xFF000000;
90 final
= buff
[n
] & 0xFFFF0000;
94 final
= buff
[n
] & 0xFFFFFF00;
101 /* If there was a carry-out, add 1 to the sum. */
103 sum
= sum
+ final
+ 1;
109 result
.addr
= (uint64_t)buff
+ len
;
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
)
124 if (by_hand
.sum
!= by_insn
.sum
) {
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
) {
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
) {
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
) {
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
) {
150 printf("FAIL: sum: by-insn %"PRIx32
" expected %"PRIx32
"\n",
151 by_insn
.sum
, expected_sum
);
154 if (by_hand
.sum
!= expected_sum
) {
156 printf("FAIL: sum: by-hand %"PRIx32
" expected %"PRIx32
"\n",
157 by_hand
.sum
, expected_sum
);
163 /* Run a testcase. Compute the checksum by-hand and by-insn and compare
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
);
180 uint32_t sum
, expected_sum
;
183 /* ---------------- test 1 ------------------------------ */
184 /* Add one word to an initial sum; no carry */
189 run_test("test1", data
, len
, sum
, expected_sum
);
191 /* ---------------- test 2 ------------------------------ */
192 /* Add one word to an initial sum; with carry */
194 data
[0] = 0xffffffff;
197 run_test("test2", data
, len
, sum
, expected_sum
);
199 /* ---------------- test 3 ------------------------------ */
200 /* Add 15 words to an initial sum; no carry */
213 data
[11] = 0x1000000;
214 data
[12] = 0x4000000;
215 data
[13] = 0x10000000;
216 data
[14] = 0x40000000;
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. */
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 */
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. */
243 run_test("test5", NULL
, len
, sum
, expected_sum
);
245 /* ---------------- test 6 ------------------------------ */
246 /* Add 1 byte; no carry */
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 */
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 */
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 */
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 */
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 */
289 data
[0] = 0xffffffff;
290 expected_sum
= 0x00000101;
291 run_test("test11", data
, len
, sum
, expected_sum
);