20#include "pedigree/kernel/compiler.h"
21#include "pedigree/kernel/processor/types.h"
22#include "pedigree/kernel/utilities/assert.h"
23#include "pedigree/kernel/utilities/utility.h"
27#if HAS_ADDRESS_SANITIZER
32#define SSE_THRESHOLD 1024
33#define STOSB_THRESHOLD 64
40#if UTILITY_LINUX_COVERAGE
48#define EXPORT EXPORTED_PUBLIC
51extern void memzero_xmm_aligned(
void*,
size_t);
52extern void memzero_xmm(
void*,
size_t);
54void* WordSet(
void* buf,
int c,
size_t n);
55void* DoubleWordSet(
void* buf,
unsigned int c,
size_t n);
56void* QuadWordSet(
void* buf,
unsigned long long c,
size_t n);
60#if !HAS_ADDRESS_SANITIZER
61EXPORT
int memcmp(
const void* p1,
const void* p2,
size_t len)
PURE;
62EXPORT
void* memset(
void* buf,
int c,
size_t n);
63EXPORT
void* memcpy(
void* restrict s1,
const void* restrict s2,
size_t n);
64EXPORT
void* memmove(
void* s1,
const void* s2,
size_t n);
66EXPORT
int memcmp(
const void* p1,
const void* p2,
size_t len) {
67 const char* a = (
const char*)p1;
68 const char* b = (
const char*)p2;
71 for (; i < len; i++) {
72 if ((r = a[i] - b[i]) != 0)
78EXPORT
void* memset(
void* buf,
int c,
size_t n) {
80 if (n >= STOSB_THRESHOLD) {
81#if defined(__x86_64__)
83 void* destination = buf;
84 size_t head = (-(uintptr_t)buf) & 7;
85 const size_t words = (n - head) / 8;
86 const size_t tail = (n - head) & 7;
87 const uint64_t value = (
unsigned char)c * 0x0101010101010101ULL;
90 "mov %[words], %%rcx\n\t"
92 "mov %[tail], %%rcx\n\t"
94 :
"+&D"(destination),
"+&c"(head)
95 :
"a"(value), [words]
"r"(words), [tail]
"r"(tail)
99 __asm__ __volatile__(
"rep stosb" :
"=&D"(a),
"=&c"(b) :
"0"(buf),
"a"(c),
"1"(n) :
"memory");
104 unsigned char* tmp = (
unsigned char*)buf;
111EXPORT
void* memcpy(
void* restrict s1,
const void* restrict s2,
size_t n) {
113 if (n >= STOSB_THRESHOLD) {
114#if defined(__x86_64__)
115 void* destination = s1;
116 const void* source = s2;
117 size_t head = (-(uintptr_t)s1) & 7;
118 const size_t words = (n - head) / 8;
119 const size_t tail = (n - head) & 7;
120 __asm__ __volatile__(
122 "mov %[words], %%rcx\n\t"
124 "mov %[tail], %%rcx\n\t"
126 :
"+&D"(destination),
"+&S"(source),
"+&c"(head)
127 : [words]
"r"(words), [tail]
"r"(tail)
131 __asm__ __volatile__(
"rep movsb"
132 :
"=&c"(a),
"=&D"(b),
"=&S"(c)
133 :
"1"(s1),
"2"(s2),
"0"(n)
139 const unsigned char* restrict sp = (
const unsigned char* restrict)s2;
140 unsigned char* restrict dp = (
unsigned char* restrict)s1;
147static inline void* memmove_x86(
void* s1,
const void* s2,
size_t n) {
148 const unsigned char* sp = (
const unsigned char*)s2 + (n - 1);
149 unsigned char* dp = (
unsigned char*)s1 + (n - 1);
151#if defined(__x86_64__)
152 size_t head = ((uintptr_t)s1 + n) & 7;
153 const size_t words = (n - head) / 8;
154 const size_t tail = (n - head) & 7;
157 __asm__ __volatile__(
162 "mov %[words], %%rcx\n\t"
166 "mov %[tail], %%rcx\n\t"
169 :
"+&D"(dp),
"+&S"(sp),
"+&c"(head)
170 : [words]
"r"(words), [tail]
"r"(tail)
174 __asm__ __volatile__(
"std; rep movsb; cld"
175 :
"=&c"(a),
"=&D"(b),
"=&S"(c)
176 :
"1"(dp),
"2"(sp),
"0"(n)
183EXPORT
void* memmove(
void* s1,
const void* s2,
size_t n) {
187 const size_t orig_n = n;
188 if (
LIKELY((s1 < s2) || !overlaps(s1, s2, n))) {
193 if (n >= STOSB_THRESHOLD) {
194 memmove_x86(s1, s2, n);
198 const unsigned char* sp = (
const unsigned char*)s2 + (n - 1);
199 unsigned char* dp = (
unsigned char*)s1 + (n - 1);
207#if EXCESSIVE_ADDITIONAL_CHECKS
209 if (
LIKELY(!overlaps(s1, s2, orig_n))) {
210 assert(!memcmp(s1, s2, orig_n));
221int overlaps(
const void* s1,
const void* s2,
size_t n) {
222 uintptr_t a = (uintptr_t)s1;
223 uintptr_t a_end = (uintptr_t)s1 + n;
224 uintptr_t b = (uintptr_t)s2;
225 uintptr_t b_end = (uintptr_t)s2 + n;
227 return (a <= b_end) && (b <= a_end) ? 1 : 0;
230void* WordSet(
void* buf,
int c,
size_t n) {
232 if (n >= STOSB_THRESHOLD) {
234 __asm__ __volatile__(
"rep stosw" :
"=&D"(a),
"=&c"(b) :
"0"(buf),
"a"(c),
"1"(n) :
"memory");
238 unsigned short* tmp = (
unsigned short*)buf;
245void* DoubleWordSet(
void* buf,
unsigned int c,
size_t n) {
247 if (n >= STOSB_THRESHOLD) {
249 __asm__ __volatile__(
"rep stosl" :
"=&D"(a),
"=&c"(b) :
"0"(buf),
"a"(c),
"1"(n) :
"memory");
253 unsigned int* tmp = (
unsigned int*)buf;
260void* QuadWordSet(
void* buf,
unsigned long long c,
size_t n) {
262 if (n >= STOSB_THRESHOLD) {
264 __asm__ __volatile__(
"rep stosq" :
"=&D"(a),
"=&c"(b) :
"0"(buf),
"a"(c),
"1"(n) :
"memory");
268 unsigned long long* p = (
unsigned long long*)buf;
277void* ForwardMemoryCopy(
void* a,
const void* b,
size_t c) {
278 return memcpy(a, b, c);
281void* MemoryCopy(
void* a,
const void* b,
size_t c) {
282 return memmove(a, b, c);
285void* ByteSet(
void* a,
int b,
size_t c) {
286 return memset(a, b, c);
289int MemoryCompare(
const void* a,
const void* b,
size_t c) {
290 return memcmp(a, b, c);