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