Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <Kernel/StdLib.h>
8
9extern "C" {
10
11void* memcpy(void* dest_ptr, void const* src_ptr, size_t n)
12{
13#if ARCH(X86_64)
14 size_t dest = (size_t)dest_ptr;
15 size_t src = (size_t)src_ptr;
16 // FIXME: Support starting at an unaligned address.
17 if (!(dest & 0x3) && !(src & 0x3) && n >= 12) {
18 size_t size_ts = n / sizeof(size_t);
19 asm volatile(
20 "rep movsq\n"
21 : "=S"(src), "=D"(dest)
22 : "S"(src), "D"(dest), "c"(size_ts)
23 : "memory");
24 n -= size_ts * sizeof(size_t);
25 if (n == 0)
26 return dest_ptr;
27 }
28 asm volatile(
29 "rep movsb\n" ::"S"(src), "D"(dest), "c"(n)
30 : "memory");
31#else
32 u8* pd = (u8*)dest_ptr;
33 u8 const* ps = (u8 const*)src_ptr;
34 for (; n--;)
35 *pd++ = *ps++;
36#endif
37 return dest_ptr;
38}
39
40void* memmove(void* dest, void const* src, size_t n)
41{
42 if (dest < src)
43 return memcpy(dest, src, n);
44
45 u8* pd = (u8*)dest;
46 u8 const* ps = (u8 const*)src;
47 for (pd += n, ps += n; n--;)
48 *--pd = *--ps;
49 return dest;
50}
51
52void* memset(void* dest_ptr, int c, size_t n)
53{
54#if ARCH(X86_64)
55 size_t dest = (size_t)dest_ptr;
56 // FIXME: Support starting at an unaligned address.
57 if (!(dest & 0x3) && n >= 12) {
58 size_t size_ts = n / sizeof(size_t);
59 size_t expanded_c = explode_byte((u8)c);
60 asm volatile(
61 "rep stosq\n"
62 : "=D"(dest)
63 : "D"(dest), "c"(size_ts), "a"(expanded_c)
64 : "memory");
65 n -= size_ts * sizeof(size_t);
66 if (n == 0)
67 return dest_ptr;
68 }
69 asm volatile(
70 "rep stosb\n"
71 : "=D"(dest), "=c"(n)
72 : "0"(dest), "1"(n), "a"(c)
73 : "memory");
74#else
75 u8* pd = (u8*)dest_ptr;
76 for (; n--;)
77 *pd++ = c;
78#endif
79 return dest_ptr;
80}
81
82size_t strlen(char const* str)
83{
84 size_t len = 0;
85 while (*(str++))
86 ++len;
87 return len;
88}
89
90size_t strnlen(char const* str, size_t maxlen)
91{
92 size_t len = 0;
93 for (; len < maxlen && *str; str++)
94 len++;
95 return len;
96}
97
98int strcmp(char const* s1, char const* s2)
99{
100 for (; *s1 == *s2; ++s1, ++s2) {
101 if (*s1 == 0)
102 return 0;
103 }
104 return *(u8 const*)s1 < *(u8 const*)s2 ? -1 : 1;
105}
106
107int memcmp(void const* v1, void const* v2, size_t n)
108{
109 auto const* s1 = (u8 const*)v1;
110 auto const* s2 = (u8 const*)v2;
111 while (n-- > 0) {
112 if (*s1++ != *s2++)
113 return s1[-1] < s2[-1] ? -1 : 1;
114 }
115 return 0;
116}
117
118int strncmp(char const* s1, char const* s2, size_t n)
119{
120 if (!n)
121 return 0;
122 do {
123 if (*s1 != *s2++)
124 return *(unsigned char const*)s1 - *(unsigned char const*)--s2;
125 if (*s1++ == 0)
126 break;
127 } while (--n);
128 return 0;
129}
130
131char* strstr(char const* haystack, char const* needle)
132{
133 char nch;
134 char hch;
135
136 if ((nch = *needle++) != 0) {
137 size_t len = strlen(needle);
138 do {
139 do {
140 if ((hch = *haystack++) == 0)
141 return nullptr;
142 } while (hch != nch);
143 } while (strncmp(haystack, needle, len) != 0);
144 --haystack;
145 }
146 return const_cast<char*>(haystack);
147}
148}