Home | History | Annotate | Download | only in crosstest
      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))
     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))
     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 
     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 
     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 
     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