os-k/kaleid/common/memory.c

246 lines
5.7 KiB
C
Raw Normal View History

2018-12-25 19:09:58 +01:00
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: mem*() functions //
//----------------------------------------------------------------------------//
2019-01-01 13:09:57 +01:00
#include <kaleid.h>
2018-12-31 10:49:08 +01:00
2018-12-31 15:08:56 +01:00
//------------------------------------------//
// memset() family //
//------------------------------------------//
2018-12-31 10:49:08 +01:00
2018-12-28 18:52:55 +01:00
//
2019-01-14 14:31:49 +01:00
// Set "bytes"-many bytes starting from ptr to val
2018-12-28 18:52:55 +01:00
//
2019-01-02 17:19:13 +01:00
void *memset(void *ptr, int val, size_t bytes)
2018-12-28 18:52:55 +01:00
{
2018-12-28 20:49:43 +01:00
uchar *uptr = (uchar *)ptr;
2019-01-14 14:31:49 +01:00
//
// Deal with bytes before start of the first aligned qword
//
2018-12-31 15:08:56 +01:00
while (((ulong)uptr % QWORD_ALIGN) > 0 && bytes--) {
2018-12-31 10:49:08 +01:00
*uptr++ = (uchar)val;
}
2019-01-14 14:31:49 +01:00
//
// At this point we're qword-aligned
//
2019-01-02 14:51:40 +01:00
if (bytes > QWORD_SIZE) {
2018-12-31 15:08:56 +01:00
const ulong uval = ((ulong)val << 56) | ((ulong)val << 48)
| ((ulong)val << 40) | ((ulong)val << 32)
| ((ulong)val << 24) | ((ulong)val << 16)
| ((ulong)val << 8) | ((ulong)val);
2018-12-31 10:49:08 +01:00
2019-01-02 14:51:40 +01:00
ulong *uqptr = (ulong *)ptr;
2019-01-14 14:31:49 +01:00
//
// Moving fast, qword by qword
//
2019-01-02 14:51:40 +01:00
while (bytes > QWORD_SIZE) {
*uqptr++ = uval;
bytes -= QWORD_SIZE;
}
2019-01-14 14:31:49 +01:00
2019-01-02 14:51:40 +01:00
uptr = (uchar *)(ulong)uqptr;
2018-12-31 10:49:08 +01:00
}
2019-01-14 14:31:49 +01:00
//
// Deal with the few remaining bytes
//
2019-01-02 17:19:13 +01:00
while (bytes--) *uptr++ = (uchar)val;
2019-01-14 14:31:49 +01:00
2018-12-28 18:52:55 +01:00
return ptr;
}
2018-12-31 15:08:56 +01:00
//
2019-01-19 22:36:38 +01:00
// Set "words"-many words starting from ptr to val
2018-12-31 15:08:56 +01:00
//
void *memsetw(void *ptr, int val, size_t words)
{
ushort *uptr = (ushort *)ptr;
2019-01-14 14:31:49 +01:00
//
// Check whether we can we do this an aligned way
//
2018-12-31 15:08:56 +01:00
if unlikely (((ulong)uptr % WORD_ALIGN) > 0) {
2019-01-14 14:31:49 +01:00
//
// We can't, so we write word by word all the way up
//
2019-01-02 17:19:13 +01:00
while (words--) *uptr++ = (ushort)val;
2018-12-31 15:08:56 +01:00
return uptr;
}
2019-01-14 14:31:49 +01:00
2018-12-31 15:08:56 +01:00
while (((ulong)uptr % QWORD_ALIGN) > 0 && words--) {
*uptr++ = (ushort)val;
}
2019-01-02 14:51:40 +01:00
if (words > QWORDS_TO_WORDS(1)) {
2018-12-31 15:08:56 +01:00
const ulong uval = ((ulong)val << 48) | ((ulong)val << 32)
| ((ulong)val << 16) | ((ulong)val);
2019-01-02 14:51:40 +01:00
ulong *uqptr = (ulong *)uptr;
while (words > QWORDS_TO_WORDS(1)) {
words -= QWORDS_TO_WORDS(1);
*uqptr++ = uval;
}
2019-01-14 14:31:49 +01:00
2019-01-02 14:51:40 +01:00
uptr = (ushort *)(ulong)uqptr;
2018-12-31 15:08:56 +01:00
}
2019-01-14 14:31:49 +01:00
2019-01-02 17:19:13 +01:00
while (words--) *uptr++ = (ushort)val;
2019-01-14 14:31:49 +01:00
2018-12-31 15:08:56 +01:00
return ptr;
}
2019-01-01 17:11:30 +01:00
//
2019-01-19 22:36:38 +01:00
// Set "dwords"-many dwords starting from ptr to val
// XXX unimplemented
2019-01-01 17:11:30 +01:00
//
void *memsetd(void *ptr, int val, size_t dwords)
{
(void)val;
(void)dwords;
return ptr;
}
2018-12-31 15:08:56 +01:00
//
2019-01-19 22:36:38 +01:00
// Set "qwords"-many qwords starting from ptr to val
2018-12-31 15:08:56 +01:00
//
void *memsetq(void *ptr, long val, size_t qwords)
{
2019-01-02 14:51:40 +01:00
ulong *uptr = (ulong *)ptr;
2019-01-14 14:31:49 +01:00
//
// There's no need to check for alignment
//
2019-01-02 14:51:40 +01:00
while (qwords--) *uptr++ = (ulong)val;
2019-01-14 14:31:49 +01:00
2019-01-02 14:51:40 +01:00
return ptr;
2018-12-31 15:08:56 +01:00
}
2019-01-14 14:31:49 +01:00
//------------------------------------------//
// Other mem*() functions //
//------------------------------------------//
2018-12-28 18:52:55 +01:00
//
2019-01-19 22:36:38 +01:00
// Set "bytes"-many bytes starting from ptr to 0
2018-12-28 18:52:55 +01:00
//
void *memzero(void *ptr, size_t bytes)
{
2019-01-02 14:51:40 +01:00
return memsetb(ptr, 0, bytes);
}
//
2019-01-19 22:36:38 +01:00
// Copy "bytes"-many bytes of src to dst
// Does not deal with overlapping blocks (memmove's job)
2019-01-02 14:51:40 +01:00
//
2019-01-14 14:31:49 +01:00
void *memcpy(void *restrict dst, const void *restrict src, size_t bytes)
2019-01-02 14:51:40 +01:00
{
const ulong *usrc = (const ulong *)src;
ulong *udst = (ulong *)dst;
2019-01-14 14:31:49 +01:00
2019-01-02 14:51:40 +01:00
if unlikely (bytes == 0) return dst;
2019-01-14 14:31:49 +01:00
//
// Can align both src and dst at once at once?
//
2019-01-02 14:51:40 +01:00
if unlikely ((ulong)src % WORD_ALIGN == 1
&& (ulong)dst % WORD_ALIGN == 1) {
const uchar *ubsrc = (const uchar *)usrc;
uchar *ubdst = (uchar *)udst;
2019-01-14 14:31:49 +01:00
//
// Yes we can, we're guaranteed to be word-aligned now
//
2019-01-02 14:51:40 +01:00
*ubdst++ = *ubsrc++;
bytes--;
udst = (ulong *)ubdst;
usrc = (ulong *)ubsrc;
2018-12-31 15:08:56 +01:00
}
2019-01-02 14:51:40 +01:00
const ushort *uwsrc = (const ushort *)usrc;
ushort *uwdst = (ushort *)udst;
2019-01-14 14:31:49 +01:00
//
// Align either dst or src for qword access
//
2019-01-02 14:51:40 +01:00
while ((ulong)dst % QWORD_ALIGN > 0
&& (ulong)src % QWORD_ALIGN > 0
&& bytes > WORD_SIZE) {
*uwdst++ = *uwsrc++;
bytes -= WORD_SIZE;
}
udst = (ulong *)uwdst;
usrc = (ulong *)uwsrc;
2019-01-14 14:31:49 +01:00
//
// This should be most of the job
//
2019-01-02 14:51:40 +01:00
while (bytes > QWORD_SIZE) {
*udst++ = *usrc++;
bytes -= QWORD_SIZE;
}
const uchar *ubsrc = (const uchar *)usrc;
ushort *ubdst = (ushort *)udst;
2019-01-14 14:31:49 +01:00
//
// Deal with the few bytes left
//
2019-01-02 17:19:13 +01:00
while (bytes--) *ubdst ++ = *ubsrc++;
return dst;
}
//
2019-01-19 22:36:38 +01:00
// Move memory from src to dest, even if they overlap
2019-01-02 17:19:13 +01:00
//
void *memmove(void *dst, const void *src, size_t bytes)
{
const uchar *usrc = src;
uchar *udst = dst;
2019-01-14 14:31:49 +01:00
//
// Can we use memcpy() safely?
//
2019-01-02 17:19:13 +01:00
if (udst < usrc) {
2019-01-14 14:31:49 +01:00
return memcpy(dst, src, bytes);
2019-01-02 14:51:40 +01:00
}
2019-01-14 14:31:49 +01:00
//
// No, so we go backwards
//
2019-01-02 17:19:13 +01:00
uchar *usrc_end = (uchar *)usrc + bytes - 1;
uchar *udst_end = udst + bytes - 1;
while (bytes--) *udst_end-- = *usrc_end--;
2019-01-02 14:51:40 +01:00
return dst;
2018-12-28 18:52:55 +01:00
}
2019-01-02 17:19:13 +01:00
//
2019-01-19 22:36:38 +01:00
// Compare memory areas
2019-01-02 17:19:13 +01:00
//
int memcmp(const void *ptr1, const void *ptr2, size_t bytes)
{
const uchar *uptr1 = ptr1;
const uchar *uptr2 = ptr2;
while (bytes--) {
if (*uptr1++ != *uptr2++) {
return uptr1[-1] < uptr2[-1] ? -1 : 1;
}
}
return 0;
}