commit e00d4a9b82076fde6a6f032753518ee37715bcd4
parent e227605a8680844a3465328fe9335adbe58decdd
Author: Autumn! <autumnull@posteo.net>
Date: Thu, 7 Sep 2023 14:47:22 +0000
rt: copy by words in memcpy
Signed-off-by: Autumn! <autumnull@posteo.net>
Diffstat:
4 files changed, 95 insertions(+), 4 deletions(-)
diff --git a/rt/memcpy.ha b/rt/memcpy.ha
@@ -1,9 +1,85 @@
// License: MPL-2.0
// (c) 2021 Drew DeVault <sir@cmpwn.com>
-export fn memcpy(dest: *opaque, src: *const opaque, amt: size) void = {
- let a = dest: *[*]u8, b = src: *const [*]u8;
- for (let i = 0z; i < amt; i += 1) {
- a[i] = b[i];
+def MOD32 = size(u32) - 1;
+
+export fn memcpy(dest: *opaque, src: *const opaque, n: size) void = {
+ // implementation adapted from musl libc
+
+ let d = memfunc_ptr { byte = dest: *[*]u8 };
+ let s = memfunc_ptr { byte = src: *[*]u8 };
+
+ // copy bytes until src pointer is u32-aligned
+ for (s.uptr & MOD32 != 0 && 0 < n; n -= 1) {
+ d.byte[0] = s.byte[0];
+ d.uptr += 1;
+ s.uptr += 1;
+ };
+
+ // if dest is u32-aligned with src, copy as batches of u32s
+ if (d.uptr & MOD32 == 0) {
+ for (16 <= n; n -= 16) {
+ d.quad[0] = s.quad[0];
+ d.quad[1] = s.quad[1];
+ d.quad[2] = s.quad[2];
+ d.quad[3] = s.quad[3];
+ d.uptr += 16;
+ s.uptr += 16;
+ };
+ if (n & 8 != 0) {
+ d.quad[0] = s.quad[0];
+ d.quad[1] = s.quad[1];
+ d.uptr += 8;
+ s.uptr += 8;
+ };
+ if (n & 4 != 0) {
+ d.quad[0] = s.quad[0];
+ d.uptr += 4;
+ s.uptr += 4;
+ };
+ } else {
+ // TODO: musl uses some byte-order-dependent code here
+ // which could be incorporated at some point.
+ for (16 <= n; n -= 16) {
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ };
+ if (n & 8 != 0) {
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ };
+ if (n & 4 != 0) {
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ };
+ };
+ if (n & 2 != 0) {
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ d.byte[0] = s.byte[0]; d.uptr += 1; s.uptr += 1;
+ };
+ if (n & 1 != 0) {
+ d.byte[0] = s.byte[0];
};
};
diff --git a/rt/memfunc_ptr.ha b/rt/memfunc_ptr.ha
@@ -0,0 +1,9 @@
+// License: MPL-2.0
+
+type memfunc_ptr = union {
+ byte: *[*]u8,
+ quad: *[*]u32,
+ octs: *[*]u64,
+ sz: *[*]size,
+ uptr: uintptr,
+};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -40,6 +40,7 @@ gensrcs_rt() {
jmp.ha \
malloc.ha \
memcpy.ha \
+ memfunc_ptr.ha \
memmove.ha \
memset.ha \
strcmp.ha \
@@ -66,6 +67,7 @@ gensrcs_rt() {
jmp.ha \
malloc.ha \
memcpy.ha \
+ memfunc_ptr.ha \
memmove.ha \
memset.ha \
strcmp.ha \
diff --git a/stdlib.mk b/stdlib.mk
@@ -24,6 +24,7 @@ stdlib_rt_linux_srcs = \
$(STDLIB)/rt/jmp.ha \
$(STDLIB)/rt/malloc.ha \
$(STDLIB)/rt/memcpy.ha \
+ $(STDLIB)/rt/memfunc_ptr.ha \
$(STDLIB)/rt/memmove.ha \
$(STDLIB)/rt/memset.ha \
$(STDLIB)/rt/strcmp.ha \
@@ -53,6 +54,7 @@ stdlib_rt_freebsd_srcs = \
$(STDLIB)/rt/jmp.ha \
$(STDLIB)/rt/malloc.ha \
$(STDLIB)/rt/memcpy.ha \
+ $(STDLIB)/rt/memfunc_ptr.ha \
$(STDLIB)/rt/memmove.ha \
$(STDLIB)/rt/memset.ha \
$(STDLIB)/rt/strcmp.ha \
@@ -2466,6 +2468,7 @@ testlib_rt_linux_srcs = \
$(STDLIB)/rt/jmp.ha \
$(STDLIB)/rt/malloc.ha \
$(STDLIB)/rt/memcpy.ha \
+ $(STDLIB)/rt/memfunc_ptr.ha \
$(STDLIB)/rt/memmove.ha \
$(STDLIB)/rt/memset.ha \
$(STDLIB)/rt/strcmp.ha \
@@ -2496,6 +2499,7 @@ testlib_rt_freebsd_srcs = \
$(STDLIB)/rt/jmp.ha \
$(STDLIB)/rt/malloc.ha \
$(STDLIB)/rt/memcpy.ha \
+ $(STDLIB)/rt/memfunc_ptr.ha \
$(STDLIB)/rt/memmove.ha \
$(STDLIB)/rt/memset.ha \
$(STDLIB)/rt/strcmp.ha \