| git.druid.rocks | index | druid520 | kaboom | src/ | user/ | mem.nsc |
src/user/mem.nsc
/*
* memcpy/memset/memmove/memcmp -- the byte-level primitives every
* other new libc module here (string.nsc, malloc's callers, whatever
* comes next) builds on. reads go through lib.nsc's own ptr_byte_at
* (already global, already linked into every program -- no reason to
* duplicate it a second time the way the kernel side's several
* separate ptr_byte_at copies do, now that a real shared libc exists
* to put it in). writes need a byte-set counterpart lib.nsc never
* needed (nothing there ever wrote through a raw ptr), so that's
* this file's own addition: the same read-modify-write-the-containing-
* word technique used everywhere else a raw ptr needs single-byte
* granularity (nsc's `*p` is always a full 8-byte load/store, never
* byte-granular).
*/
include "lib.nsh";
global void
mem_byte_set(ptr base, u64 index, u8 val)
{
u64 wordoff;
u64 byteoff;
u64 word;
wordoff = index & ~(u64)7;
byteoff = index & (u64)7;
word = (u64)*(base + wordoff);
word = word & ~((u64)0xff << (byteoff * (u64)8));
word = word | ((u64)val << (byteoff * (u64)8));
*(base + wordoff) = (i64)word;
}
global ptr
memset(ptr dst, u8 val, u64 n)
{
u64 i;
i = 0;
while(i < n)
{
mem_byte_set(dst, i, val);
i = i + (u64)1;
}
return dst;
}
global ptr
memcpy(ptr dst, ptr src, u64 n)
{
u64 i;
i = 0;
while(i < n)
{
mem_byte_set(dst, i, ptr_byte_at(src, i));
i = i + (u64)1;
}
return dst;
}
/* handles overlap correctly by choosing a copy direction based on
* which end overlaps -- the one thing plain memcpy is allowed to get
* wrong. */
global ptr
memmove(ptr dst, ptr src, u64 n)
{
u64 i;
if((u64)dst <= (u64)src)
{
i = 0;
while(i < n)
{
mem_byte_set(dst, i, ptr_byte_at(src, i));
i = i + (u64)1;
}
}
else
{
i = n;
while(i > (u64)0)
{
i = i - (u64)1;
mem_byte_set(dst, i, ptr_byte_at(src, i));
}
}
return dst;
}
global i32
memcmp(ptr a, ptr b, u64 n)
{
u64 i;
u8 ca;
u8 cb;
i = 0;
while(i < n)
{
ca = ptr_byte_at(a, i);
cb = ptr_byte_at(b, i);
if(ca != cb)
{
if(ca < cb)
{
return -1;
}
return 1;
}
i = i + (u64)1;
}
return 0;
}