|  | /* | 
|  | * Simple sanity test of memcpy, memmove, and memset intrinsics. | 
|  | * (fixed length buffers, variable length buffers, etc.) | 
|  | */ | 
|  |  | 
|  | #include <stdint.h> /* cstdint requires -std=c++0x or higher */ | 
|  | #include <cstdlib> | 
|  | #include <cstring> | 
|  |  | 
|  | #include "mem_intrin.h" | 
|  | #include "xdefs.h" | 
|  |  | 
|  | typedef int elem_t; | 
|  |  | 
|  | /* | 
|  | * Reset buf to the sequence of bytes: n, n+1, n+2 ... length - 1 | 
|  | */ | 
|  | static void __attribute__((noinline)) | 
|  | reset_buf(uint8_t *buf, uint8_t init, SizeT length) { | 
|  | SizeT i; | 
|  | SizeT v = init; | 
|  | for (i = 0; i < length; ++i) | 
|  | buf[i] = v++; | 
|  | } | 
|  |  | 
|  | /* Do a fletcher-16 checksum so that the order of the values matter. | 
|  | * (Not doing a fletcher-32 checksum, since we are working with | 
|  | * smaller buffers, whose total won't approach 2**16). | 
|  | */ | 
|  | static int __attribute__((noinline)) | 
|  | fletcher_checksum(uint8_t *buf, SizeT length) { | 
|  | SizeT i; | 
|  | int sum = 0; | 
|  | int sum_of_sums = 0; | 
|  | const int kModulus = 255; | 
|  | for (i = 0; i < length; ++i) { | 
|  | sum = (sum + buf[i]) % kModulus; | 
|  | sum_of_sums = (sum_of_sums + sum) % kModulus; | 
|  | } | 
|  | return (sum_of_sums << 8) | sum; | 
|  | } | 
|  |  | 
|  | int memcpy_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) { | 
|  | reset_buf(buf, init, length); | 
|  | memcpy((void *)buf2, (void *)buf, length); | 
|  | return fletcher_checksum(buf2, length); | 
|  | } | 
|  |  | 
|  | int memmove_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) { | 
|  | int sum1; | 
|  | int sum2; | 
|  | const int overlap_bytes = 4 * sizeof(elem_t); | 
|  | if (length <= overlap_bytes) | 
|  | return 0; | 
|  | uint8_t *overlap_buf = buf + overlap_bytes; | 
|  | SizeT reduced_length = length - overlap_bytes; | 
|  | reset_buf(buf, init, length); | 
|  |  | 
|  | /* Test w/ overlap. */ | 
|  | memmove((void *)overlap_buf, (void *)buf, reduced_length); | 
|  | sum1 = fletcher_checksum(overlap_buf, reduced_length); | 
|  | /* Test w/out overlap. */ | 
|  | memmove((void *)buf2, (void *)buf, length); | 
|  | sum2 = fletcher_checksum(buf2, length); | 
|  | return sum1 + sum2; | 
|  | } | 
|  |  | 
|  | int memset_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) { | 
|  | memset((void *)buf, init, length); | 
|  | memset((void *)buf2, init + 4, length); | 
|  | return fletcher_checksum(buf, length) + fletcher_checksum(buf2, length); | 
|  | } | 
|  |  | 
|  | #define X(NBYTES)                                                              \ | 
|  | int memcpy_test_fixed_len_##NBYTES(uint8_t init) {                           \ | 
|  | uint8_t buf[NBYTES];                                                       \ | 
|  | uint8_t buf2[NBYTES];                                                      \ | 
|  | reset_buf(buf, init, NBYTES);                                              \ | 
|  | memcpy((void *)buf2, (void *)buf, NBYTES);                                 \ | 
|  | return fletcher_checksum(buf2, NBYTES);                                    \ | 
|  | }                                                                            \ | 
|  | \ | 
|  | int memmove_test_fixed_len_##NBYTES(uint8_t init) {                          \ | 
|  | uint8_t buf[NBYTES + 16];                                                  \ | 
|  | uint8_t buf2[NBYTES + 16];                                                 \ | 
|  | reset_buf(buf, init, NBYTES + 16);                                         \ | 
|  | reset_buf(buf2, init, NBYTES + 16);                                        \ | 
|  | /* Move up */                                                              \ | 
|  | memmove((void *)(buf + 16), (void *)buf, NBYTES);                          \ | 
|  | /* Move down */                                                            \ | 
|  | memmove((void *)buf2, (void *)(buf2 + 16), NBYTES);                        \ | 
|  | return fletcher_checksum(buf, NBYTES + 16) +                               \ | 
|  | fletcher_checksum(buf2, NBYTES + 16);                               \ | 
|  | }                                                                            \ | 
|  | \ | 
|  | int memset_test_fixed_len_##NBYTES(uint8_t init) {                           \ | 
|  | uint8_t buf[NBYTES];                                                       \ | 
|  | memset((void *)buf, init, NBYTES);                                         \ | 
|  | return fletcher_checksum(buf, NBYTES);                                     \ | 
|  | } | 
|  | MEMINTRIN_SIZE_TABLE | 
|  | #undef X |