75 lines
1.9 KiB
C
75 lines
1.9 KiB
C
// memPattern.h - the byte pattern the memBlock tests fill and check.
|
|
//
|
|
// The byte at address a is a's low byte xor a mix of its page and bank, so
|
|
// a copy off by one byte, one page or one bank reads wrong. Walked a page
|
|
// at a time so the per-byte work stays 16-bit.
|
|
#ifndef MEM_PATTERN_H
|
|
#define MEM_PATTERN_H
|
|
|
|
typedef unsigned char u8;
|
|
typedef unsigned short u16;
|
|
typedef unsigned long u32;
|
|
typedef unsigned long size_t;
|
|
|
|
#define PAGE_BYTES 256u
|
|
|
|
static void fill(u32 a, u32 n, u8 seed);
|
|
static int holds(u32 a, u32 from, u32 n, u8 seed);
|
|
void *memcpy(void *dst, const void *src, size_t n);
|
|
void *memmove(void *dst, const void *src, size_t n);
|
|
void *memset(void *dst, int c, size_t n);
|
|
static u8 mixOf(u32 a, u8 seed);
|
|
|
|
|
|
// [a, a + n) = the pattern of its own addresses.
|
|
static void fill(u32 a, u32 n, u8 seed) {
|
|
u8 *p = (u8 *)a;
|
|
while (n != 0u) {
|
|
u8 lo = (u8)a;
|
|
u8 m = mixOf(a, seed);
|
|
u16 run = (u16)(PAGE_BYTES - lo);
|
|
u16 i;
|
|
if ((u32)run > n) {
|
|
run = (u16)n;
|
|
}
|
|
for (i = 0; i < run; i++) {
|
|
p[i] = (u8)(lo ^ m);
|
|
lo++;
|
|
}
|
|
p += run;
|
|
a += run;
|
|
n -= run;
|
|
}
|
|
}
|
|
|
|
|
|
// 1 when [a, a + n) holds the pattern of [from, from + n).
|
|
static int holds(u32 a, u32 from, u32 n, u8 seed) {
|
|
const u8 *p = (const u8 *)a;
|
|
while (n != 0u) {
|
|
u8 lo = (u8)from;
|
|
u8 m = mixOf(from, seed);
|
|
u16 run = (u16)(PAGE_BYTES - lo);
|
|
u16 i;
|
|
if ((u32)run > n) {
|
|
run = (u16)n;
|
|
}
|
|
for (i = 0; i < run; i++) {
|
|
if (p[i] != (u8)(lo ^ m)) {
|
|
return 0;
|
|
}
|
|
lo++;
|
|
}
|
|
p += run;
|
|
from += run;
|
|
n -= run;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
static u8 mixOf(u32 a, u8 seed) {
|
|
return (u8)((u8)((u8)(a >> 8) * 7u) ^ (u8)((u8)(a >> 16) * 13u) ^ seed);
|
|
}
|
|
|
|
#endif
|