mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-07 19:57:45 +03:00
6693cfb26a
I just discovered the hard way that clobbering FPU/MMX/SSE registers in the kernel makes things very confusing for userspace (and other kernel threads.) Let's banish all of those things from the kernel to keep things simple.
150 lines
3.2 KiB
C++
150 lines
3.2 KiB
C++
#include <AK/Types.h>
|
|
#include "Assertions.h"
|
|
#include "kmalloc.h"
|
|
#include <AK/StdLibExtras.h>
|
|
#include <AK/Types.h>
|
|
|
|
extern "C" {
|
|
|
|
void* memcpy(void* dest_ptr, const void* src_ptr, size_t n)
|
|
{
|
|
#ifndef KERNEL
|
|
if (n >= 1024)
|
|
return mmx_memcpy(dest_ptr, src_ptr, n);
|
|
#endif
|
|
|
|
size_t dest = (size_t)dest_ptr;
|
|
size_t src = (size_t)src_ptr;
|
|
// FIXME: Support starting at an unaligned address.
|
|
if (!(dest & 0x3) && !(src & 0x3) && n >= 12) {
|
|
size_t size_ts = n / sizeof(size_t);
|
|
asm volatile(
|
|
"rep movsl\n"
|
|
: "=S"(src), "=D"(dest)
|
|
: "S"(src), "D"(dest), "c"(size_ts)
|
|
: "memory"
|
|
);
|
|
n -= size_ts * sizeof(size_t);
|
|
if (n == 0)
|
|
return dest_ptr;
|
|
}
|
|
asm volatile(
|
|
"rep movsb\n"
|
|
:: "S"(src), "D"(dest), "c"(n)
|
|
: "memory"
|
|
);
|
|
return dest_ptr;
|
|
}
|
|
|
|
void* memmove(void* dest, const void* src, size_t n)
|
|
{
|
|
if (dest < src)
|
|
return memcpy(dest, src, n);
|
|
|
|
byte *pd = (byte*)dest;
|
|
const byte *ps = (const byte*)src;
|
|
for (pd += n, ps += n; n--;)
|
|
*--pd = *--ps;
|
|
return dest;
|
|
}
|
|
|
|
char* strcpy(char* dest, const char *src)
|
|
{
|
|
auto* dest_ptr = dest;
|
|
auto* src_ptr = src;
|
|
while ((*dest_ptr++ = *src_ptr++) != '\0');
|
|
return dest;
|
|
}
|
|
|
|
char* strncpy(char* dest, const char* src, size_t n)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < n && src[i] != '\0'; ++i)
|
|
dest[i] = src[i];
|
|
for ( ; i < n; ++i)
|
|
dest[i] = '\0';
|
|
return dest;
|
|
}
|
|
|
|
void* memset(void* dest_ptr, int c, size_t n)
|
|
{
|
|
size_t dest = (size_t)dest_ptr;
|
|
// FIXME: Support starting at an unaligned address.
|
|
if (!(dest & 0x3) && n >= 12) {
|
|
size_t size_ts = n / sizeof(size_t);
|
|
size_t expanded_c = (byte)c;
|
|
expanded_c |= expanded_c << 8;
|
|
expanded_c |= expanded_c << 16;
|
|
asm volatile(
|
|
"rep stosl\n"
|
|
: "=D"(dest)
|
|
: "D"(dest), "c"(size_ts), "a"(expanded_c)
|
|
: "memory"
|
|
);
|
|
n -= size_ts * sizeof(size_t);
|
|
if (n == 0)
|
|
return dest_ptr;
|
|
}
|
|
asm volatile(
|
|
"rep stosb\n"
|
|
: "=D" (dest), "=c" (n)
|
|
: "0" (dest), "1" (n), "a" (c)
|
|
: "memory"
|
|
);
|
|
return dest_ptr;
|
|
}
|
|
|
|
char* strrchr(const char* str, int ch)
|
|
{
|
|
char *last = nullptr;
|
|
char c;
|
|
for (; (c = *str); ++str) {
|
|
if (c == ch)
|
|
last = const_cast<char*>(str);
|
|
}
|
|
return last;
|
|
}
|
|
|
|
size_t strlen(const char* str)
|
|
{
|
|
size_t len = 0;
|
|
while (*(str++))
|
|
++len;
|
|
return len;
|
|
}
|
|
|
|
int strcmp(const char *s1, const char *s2)
|
|
{
|
|
for (; *s1 == *s2; ++s1, ++s2) {
|
|
if (*s1 == 0)
|
|
return 0;
|
|
}
|
|
return *(const byte*)s1 < *(const byte*)s2 ? -1 : 1;
|
|
}
|
|
|
|
char* strdup(const char *str)
|
|
{
|
|
size_t len = strlen(str);
|
|
char* new_str = (char*)kmalloc(len + 1);
|
|
strcpy(new_str, str);
|
|
return new_str;
|
|
}
|
|
|
|
int memcmp(const void* v1, const void* v2, size_t n)
|
|
{
|
|
auto* s1 = (const byte*)v1;
|
|
auto* s2 = (const byte*)v2;
|
|
while (n-- > 0) {
|
|
if (*s1++ != *s2++)
|
|
return s1[-1] < s2[-1] ? -1 : 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
[[noreturn]] void __cxa_pure_virtual()
|
|
{
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
|
|
}
|