#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdint.h>
#ifdef __arm__
void *__aeabi_memset(void *dest, size_t n, int c);
void *__aeabi_memset4(void *dest, size_t n, int c);
void *__aeabi_memset8(void *dest, size_t n, int c);
void __aeabi_memclr(void *dest, size_t n);
void __aeabi_memclr4(void *dest, size_t n);
void __aeabi_memclr8(void *dest, size_t n);
#endif
static uint8_t crc_table[256];
static uint8_t
crc8(uint8_t c)
{
int i;
for (i = 0; i < 8; i++) {
if (c & 1)
c = 0x31 ^ (c >> 1);
else
c >>= 1;
}
return c;
}
static void
init_crc(void)
{
int i;
for (i = 0; i < 256; i++)
crc_table[i] = crc8((uint8_t)i);
}
static char
expect(size_t _pos)
{
#ifdef __MSP430__
uint32_t pos = (uint32_t)_pos;
#else
size_t pos = _pos;
#endif
unsigned int i;
uint8_t c = 0xff;
for (i = 0; i < sizeof(size_t); i++)
c ^= crc_table[(uint8_t)(pos >> (i * 8))];
return (char)c;
}
static size_t
check(char *label, void *buf, size_t size, size_t start, size_t end, int c)
{
size_t p;
size_t error = 0;
char *b = buf;
for (p = 0; p < size; p++) {
char g = b[p];
char e = c;
if (p < start || end <= p)
e = expect(p);
if (g != e) {
fprintf(stderr, "%s(%zu, %zu):%zu expect 0x%02x got 0x%02x\n", label, start, end, p,
(uint8_t)e, (uint8_t)g);
error++;
}
}
return error;
}
static size_t
randrange(size_t max)
{
size_t pot;
size_t rnd;
for (pot = 1; pot && pot < max; pot <<= 1)
;
for (;;) {
rnd = random() & (pot - 1);
if (rnd < max)
return rnd;
}
}
#define MAX_BUF 1024
#define NEND 64
#define NSTART 64
static char buf[MAX_BUF];
static void
fill(void)
{
size_t p;
for (p = 0; p < MAX_BUF; p++)
buf[p] = expect(p);
}
static size_t
test(size_t start, size_t end, int c)
{
size_t error = 0;
char *b = buf;
fill();
memset(b + start, c, end - start);
error += check("memset", buf, MAX_BUF, start, end, c);
fill();
bzero(b + start, end - start);
error += check("bzero", buf, MAX_BUF, start, end, 0);
#ifdef __arm__
fill();
__aeabi_memset(b + start, end - start, c);
error += check("__aeabi_memset", buf, MAX_BUF, start, end, c);
fill();
__aeabi_memclr(b + start, end - start);
error += check("__aeabi_memclr", buf, MAX_BUF, start, end, 0);
start &= ~3;
end &= ~3;
fill();
__aeabi_memset4(b + start, end - start, c);
error += check("__aeabi_memset4", buf, MAX_BUF, start, end, c);
fill();
__aeabi_memclr4(b + start, end - start);
error += check("__aeabi_memclr4", buf, MAX_BUF, start, end, 0);
start &= ~7;
end &= ~7;
fill();
__aeabi_memset8(b + start, end - start, c);
error += check("__aeabi_memset8", buf, MAX_BUF, start, end, c);
fill();
__aeabi_memclr8(b + start, end - start);
error += check("__aeabi_memclr8", buf, MAX_BUF, start, end, 0);
#endif
return error;
}
int
main(void)
{
size_t error;
size_t end;
size_t start;
int nend;
int nstart;
int ret = 0;
init_crc();
for (nend = 0; nend < NEND; nend++) {
end = randrange(MAX_BUF + 1);
for (nstart = 0; nstart < NSTART; nstart++) {
start = randrange(end + 1);
int c = randrange(INT_MAX);
error = test(start, end, c);
if (error)
ret = 1;
}
}
return ret;
}