diff options
Diffstat (limited to 'libs/libc/mem.c')
-rw-r--r-- | libs/libc/mem.c | 121 |
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); +} |