summaryrefslogtreecommitdiff
path: root/Kernel/Library/MiniStdLib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Library/MiniStdLib.cpp')
-rw-r--r--Kernel/Library/MiniStdLib.cpp148
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);
+}
+}