aboutsummaryrefslogtreecommitdiff
path: root/libs/libc/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libc/mem.c')
-rw-r--r--libs/libc/mem.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/libs/libc/mem.c b/libs/libc/mem.c
new file mode 100644
index 0000000..95242e4
--- /dev/null
+++ b/libs/libc/mem.c
@@ -0,0 +1,121 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#include <assert.h>
+#include <def.h>
+#include <mem.h>
+#include <sys.h>
+
+void *memcpy(void *dest, const void *src, u32 n)
+{
+#ifdef userspace
+ // Inspired by Jeko at osdev
+ u8 *dest_byte = dest;
+ const u8 *src_byte = src;
+ for (u32 i = 0; i < n / 16; i++) {
+ __asm__ volatile("movups (%0), %%xmm0\n"
+ "movntdq %%xmm0, (%1)\n" ::"r"(src_byte),
+ "r"(dest_byte)
+ : "memory");
+
+ src_byte += 16;
+ dest_byte += 16;
+ }
+
+ if (n & 7) {
+ n = n & 7;
+
+ int d0, d1, d2;
+ __asm__ volatile("rep ; movsl\n\t"
+ "testb $2,%b4\n\t"
+ "je 1f\n\t"
+ "movsw\n"
+ "1:\ttestb $1,%b4\n\t"
+ "je 2f\n\t"
+ "movsb\n"
+ "2:"
+ : "=&c"(d0), "=&D"(d1), "=&S"(d2)
+ : "0"(n / 4), "q"(n), "1"((long)dest_byte), "2"((long)src_byte)
+ : "memory");
+ }
+ return dest_byte;
+#else
+ // Inspired by jgraef at osdev
+ u32 num_dwords = n / 4;
+ u32 num_bytes = n % 4;
+ u32 *dest32 = (u32 *)dest;
+ const u32 *src32 = (const u32 *)src;
+ u8 *dest8 = ((u8 *)dest) + num_dwords * 4;
+ const u8 *src8 = ((const u8 *)src) + num_dwords * 4;
+
+ // TODO: What's faster?
+ __asm__ volatile("rep movsl\n"
+ : "=S"(src32), "=D"(dest32), "=c"(num_dwords)
+ : "S"(src32), "D"(dest32), "c"(num_dwords)
+ : "memory");
+
+ /* for (u32 i = 0; i < num_dwords; i++) { */
+ /* dest32[i] = src32[i]; */
+ /* } */
+
+ for (u32 i = 0; i < num_bytes; i++) {
+ dest8[i] = src8[i];
+ }
+ return dest;
+#endif
+}
+
+void *memset(void *dest, int val, u32 n)
+{
+ u32 uval = val;
+ u32 num_dwords = n / 4;
+ u32 num_bytes = n % 4;
+ u32 *dest32 = (u32 *)dest;
+ u8 *dest8 = ((u8 *)dest) + num_dwords * 4;
+ u8 val8 = (u8)val;
+ u32 val32 = uval | (uval << 8) | (uval << 16) | (uval << 24);
+
+ // TODO: What's faster?
+ __asm__ volatile("rep stosl\n"
+ : "=D"(dest32), "=c"(num_dwords)
+ : "D"(dest32), "c"(num_dwords), "a"(val32)
+ : "memory");
+
+ /* for (u32 i = 0; i < num_dwords; i++) { */
+ /* dest32[i] = val32; */
+ /* } */
+
+ for (u32 i = 0; i < num_bytes; i++) {
+ dest8[i] = val8;
+ }
+ return dest;
+}
+
+void *memchr(void *src, int c, u32 n)
+{
+ u8 *s = (u8 *)src;
+
+ while (n-- > 0) {
+ if (*s == c)
+ return s;
+ s++;
+ }
+ return NULL;
+}
+
+int memcmp(const void *s1, const void *s2, u32 n)
+{
+ const u8 *a = (const u8 *)s1;
+ const u8 *b = (const u8 *)s2;
+ for (u32 i = 0; i < n; i++) {
+ if (a[i] < b[i])
+ return -1;
+ else if (b[i] < a[i])
+ return 1;
+ }
+ return 0;
+}
+
+int mememp(const u8 *buf, u32 n)
+{
+ return buf[0] == 0 && !memcmp(buf, buf + 1, n - 1);
+}