1 /*
2 * Simple sanity test of memcpy, memmove, and memset intrinsics.
3 * (fixed length buffers, variable length buffers, etc.)
4 */
5
6 #include <stdint.h> /* cstdint requires -std=c++0x or higher */
7 #include <cstdlib>
8 #include <cstring>
9
10 #include "mem_intrin.h"
11 #include "xdefs.h"
12
13 typedef int elem_t;
14
15 /*
16 * Reset buf to the sequence of bytes: n, n+1, n+2 ... length - 1
17 */
18 static void __attribute__((noinline))
reset_buf(uint8_t * buf,uint8_t init,SizeT length)19 reset_buf(uint8_t *buf, uint8_t init, SizeT length) {
20 SizeT i;
21 SizeT v = init;
22 for (i = 0; i < length; ++i)
23 buf[i] = v++;
24 }
25
26 /* Do a fletcher-16 checksum so that the order of the values matter.
27 * (Not doing a fletcher-32 checksum, since we are working with
28 * smaller buffers, whose total won't approach 2**16).
29 */
30 static int __attribute__((noinline))
fletcher_checksum(uint8_t * buf,SizeT length)31 fletcher_checksum(uint8_t *buf, SizeT length) {
32 SizeT i;
33 int sum = 0;
34 int sum_of_sums = 0;
35 const int kModulus = 255;
36 for (i = 0; i < length; ++i) {
37 sum = (sum + buf[i]) % kModulus;
38 sum_of_sums = (sum_of_sums + sum) % kModulus;
39 }
40 return (sum_of_sums << 8) | sum;
41 }
42
memcpy_test(uint8_t * buf,uint8_t * buf2,uint8_t init,SizeT length)43 int memcpy_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) {
44 reset_buf(buf, init, length);
45 memcpy((void *)buf2, (void *)buf, length);
46 return fletcher_checksum(buf2, length);
47 }
48
memmove_test(uint8_t * buf,uint8_t * buf2,uint8_t init,SizeT length)49 int memmove_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) {
50 int sum1;
51 int sum2;
52 const int overlap_bytes = 4 * sizeof(elem_t);
53 if (length <= overlap_bytes)
54 return 0;
55 uint8_t *overlap_buf = buf + overlap_bytes;
56 SizeT reduced_length = length - overlap_bytes;
57 reset_buf(buf, init, length);
58
59 /* Test w/ overlap. */
60 memmove((void *)overlap_buf, (void *)buf, reduced_length);
61 sum1 = fletcher_checksum(overlap_buf, reduced_length);
62 /* Test w/out overlap. */
63 memmove((void *)buf2, (void *)buf, length);
64 sum2 = fletcher_checksum(buf2, length);
65 return sum1 + sum2;
66 }
67
memset_test(uint8_t * buf,uint8_t * buf2,uint8_t init,SizeT length)68 int memset_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) {
69 memset((void *)buf, init, length);
70 memset((void *)buf2, init + 4, length);
71 return fletcher_checksum(buf, length) + fletcher_checksum(buf2, length);
72 }
73
74 #define X(NBYTES) \
75 int memcpy_test_fixed_len_##NBYTES(uint8_t init) { \
76 uint8_t buf[NBYTES]; \
77 uint8_t buf2[NBYTES]; \
78 reset_buf(buf, init, NBYTES); \
79 memcpy((void *)buf2, (void *)buf, NBYTES); \
80 return fletcher_checksum(buf2, NBYTES); \
81 } \
82 \
83 int memmove_test_fixed_len_##NBYTES(uint8_t init) { \
84 uint8_t buf[NBYTES + 16]; \
85 uint8_t buf2[NBYTES + 16]; \
86 reset_buf(buf, init, NBYTES + 16); \
87 reset_buf(buf2, init, NBYTES + 16); \
88 /* Move up */ \
89 memmove((void *)(buf + 16), (void *)buf, NBYTES); \
90 /* Move down */ \
91 memmove((void *)buf2, (void *)(buf2 + 16), NBYTES); \
92 return fletcher_checksum(buf, NBYTES + 16) + \
93 fletcher_checksum(buf2, NBYTES + 16); \
94 } \
95 \
96 int memset_test_fixed_len_##NBYTES(uint8_t init) { \
97 uint8_t buf[NBYTES]; \
98 memset((void *)buf, init, NBYTES); \
99 return fletcher_checksum(buf, NBYTES); \
100 }
101 MEMINTRIN_SIZE_TABLE
102 #undef X
103