• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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