/*
* 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