2018-12-25 19:09:58 +01:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
// GNU GPL OS/K //
|
|
|
|
// //
|
|
|
|
// Authors: spectral` //
|
|
|
|
// NeoX //
|
|
|
|
// //
|
|
|
|
// Desc: mem*() functions //
|
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2018-12-31 10:49:08 +01:00
|
|
|
#include <kaleid/common/stdlib.h>
|
|
|
|
|
2018-12-31 15:08:56 +01:00
|
|
|
//------------------------------------------//
|
|
|
|
// memset() family //
|
|
|
|
//------------------------------------------//
|
2018-12-31 10:49:08 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Set "qwords"-many aligned qwords starting from ptr to val
|
|
|
|
//
|
2018-12-31 15:08:56 +01:00
|
|
|
static inline void *_memset_internal(void *ptr, ulong uval, size_t qwords)
|
2018-12-31 10:49:08 +01:00
|
|
|
{
|
|
|
|
size_t n;
|
2018-12-31 15:08:56 +01:00
|
|
|
ulong *uptr = (ulong *)ptr;
|
2018-12-31 10:49:08 +01:00
|
|
|
|
|
|
|
// aligned memory write
|
|
|
|
for (n = 0; n < qwords; n++) {
|
|
|
|
*(uptr + n) = uval;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
2018-12-25 19:09:58 +01:00
|
|
|
|
2018-12-28 18:52:55 +01:00
|
|
|
//
|
|
|
|
// Set "bytes"-many bytes starting from ptr to val
|
|
|
|
//
|
2018-12-28 20:50:28 +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;
|
2018-12-31 10:49:08 +01:00
|
|
|
const size_t qwords = bytes/QWORD_SIZE;
|
2018-12-28 18:52:55 +01:00
|
|
|
|
2018-12-31 10:49:08 +01:00
|
|
|
// get rid of everything after the first byte
|
|
|
|
val = val & 0xFF;
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// move qword by qword
|
|
|
|
if (qwords) {
|
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
|
|
|
|
2018-12-31 15:08:56 +01:00
|
|
|
_memset_internal(uptr, uval, qwords);
|
2018-12-31 10:49:08 +01:00
|
|
|
|
|
|
|
uptr += qwords * QWORD_SIZE;
|
|
|
|
bytes %= QWORD_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// deal with what's left
|
|
|
|
while (bytes--) {
|
|
|
|
*uptr++ = (uchar)val;
|
|
|
|
}
|
2018-12-28 18:52:55 +01:00
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2018-12-31 15:08:56 +01:00
|
|
|
//
|
|
|
|
// Set "words"-many words starting from ptr to val
|
|
|
|
//
|
|
|
|
void *memsetw(void *ptr, int val, size_t words)
|
|
|
|
{
|
|
|
|
ushort *uptr = (ushort *)ptr;
|
|
|
|
|
|
|
|
// get rid of everything after the first word
|
|
|
|
val = val & 0xFFFF;
|
|
|
|
|
|
|
|
// can we do this an aligned way?
|
|
|
|
if unlikely (((ulong)uptr % WORD_ALIGN) > 0) {
|
|
|
|
// no, we can't align ourselves
|
|
|
|
while (words--) {
|
|
|
|
// do it the hard way
|
|
|
|
*uptr++ = (ushort)val;
|
|
|
|
}
|
|
|
|
// too bad '-'
|
|
|
|
return uptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// deal with words before start of the first aligned qword
|
|
|
|
while (((ulong)uptr % QWORD_ALIGN) > 0 && words--) {
|
|
|
|
*uptr++ = (ushort)val;
|
|
|
|
}
|
|
|
|
|
|
|
|
const size_t qwords = (words * WORD_SIZE)/QWORD_SIZE;
|
|
|
|
|
|
|
|
// move qword by qword
|
|
|
|
if (qwords) {
|
|
|
|
const ulong uval = ((ulong)val << 48) | ((ulong)val << 32)
|
|
|
|
| ((ulong)val << 16) | ((ulong)val);
|
|
|
|
|
|
|
|
_memset_internal(uptr, uval, qwords);
|
|
|
|
|
|
|
|
uptr += qwords * QWORD_SIZE / WORD_SIZE;
|
|
|
|
words %= QWORD_SIZE / WORD_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// deal with what's left
|
|
|
|
while (words--) {
|
|
|
|
*uptr++ = (ushort)val;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set "qwords"-many qwords starting from ptr to val
|
|
|
|
//
|
|
|
|
void *memsetq(void *ptr, long val, size_t qwords)
|
|
|
|
{
|
|
|
|
return _memset_internal(ptr, (ulong)val, qwords);
|
|
|
|
}
|
|
|
|
|
2018-12-28 18:52:55 +01:00
|
|
|
//
|
|
|
|
// Set "bytes"-many bytes starting from ptr to 0
|
|
|
|
//
|
|
|
|
void *memzero(void *ptr, size_t bytes)
|
|
|
|
{
|
2018-12-31 15:08:56 +01:00
|
|
|
// is direct aligned access possible? (is "unlikely" good here?)
|
|
|
|
if unlikely (bytes % QWORD_SIZE && (ulong)ptr % QWORD_ALIGN) {
|
|
|
|
return _memset_internal(ptr, (ulong)0, bytes/QWORD_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if unlikely (bytes % WORD_SIZE && (ulong)ptr % WORD_ALIGN) {
|
|
|
|
return memsetw(ptr, (int)0, bytes/WORD_SIZE);
|
|
|
|
}
|
|
|
|
|
2018-12-31 10:49:08 +01:00
|
|
|
return memset(ptr, 0, bytes);
|
2018-12-28 18:52:55 +01:00
|
|
|
}
|
|
|
|
|