diff options
Diffstat (limited to 'Kernel/Library/MiniStdLib.cpp')
-rw-r--r-- | Kernel/Library/MiniStdLib.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/Kernel/Library/MiniStdLib.cpp b/Kernel/Library/MiniStdLib.cpp new file mode 100644 index 0000000000..023f9f1155 --- /dev/null +++ b/Kernel/Library/MiniStdLib.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/Library/StdLib.h> + +extern "C" { + +void* memcpy(void* dest_ptr, void const* src_ptr, size_t n) +{ +#if ARCH(X86_64) + 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 movsq\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"); +#else + u8* pd = (u8*)dest_ptr; + u8 const* ps = (u8 const*)src_ptr; + for (; n--;) + *pd++ = *ps++; +#endif + return dest_ptr; +} + +void* memmove(void* dest, void const* src, size_t n) +{ + if (dest < src) + return memcpy(dest, src, n); + + u8* pd = (u8*)dest; + u8 const* ps = (u8 const*)src; + for (pd += n, ps += n; n--;) + *--pd = *--ps; + return dest; +} + +void* memset(void* dest_ptr, int c, size_t n) +{ +#if ARCH(X86_64) + 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 = explode_byte((u8)c); + asm volatile( + "rep stosq\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"); +#else + u8* pd = (u8*)dest_ptr; + for (; n--;) + *pd++ = c; +#endif + return dest_ptr; +} + +size_t strlen(char const* str) +{ + size_t len = 0; + while (*(str++)) + ++len; + return len; +} + +size_t strnlen(char const* str, size_t maxlen) +{ + size_t len = 0; + for (; len < maxlen && *str; str++) + len++; + return len; +} + +int strcmp(char const* s1, char const* s2) +{ + for (; *s1 == *s2; ++s1, ++s2) { + if (*s1 == 0) + return 0; + } + return *(u8 const*)s1 < *(u8 const*)s2 ? -1 : 1; +} + +int memcmp(void const* v1, void const* v2, size_t n) +{ + auto const* s1 = (u8 const*)v1; + auto const* s2 = (u8 const*)v2; + while (n-- > 0) { + if (*s1++ != *s2++) + return s1[-1] < s2[-1] ? -1 : 1; + } + return 0; +} + +int strncmp(char const* s1, char const* s2, size_t n) +{ + if (!n) + return 0; + do { + if (*s1 != *s2++) + return *(unsigned char const*)s1 - *(unsigned char const*)--s2; + if (*s1++ == 0) + break; + } while (--n); + return 0; +} + +char* strstr(char const* haystack, char const* needle) +{ + char nch; + char hch; + + if ((nch = *needle++) != 0) { + size_t len = strlen(needle); + do { + do { + if ((hch = *haystack++) == 0) + return nullptr; + } while (hch != nch); + } while (strncmp(haystack, needle, len) != 0); + --haystack; + } + return const_cast<char*>(haystack); +} +} |