commit 9c2d4ba4dafa4679127edcb26078a9ddb8695010
parent e00d4a9b82076fde6a6f032753518ee37715bcd4
Author: Autumn! <autumnull@posteo.net>
Date: Thu, 7 Sep 2023 14:47:23 +0000
rt: copy by words in memmove
Signed-off-by: Autumn! <autumnull@posteo.net>
Diffstat:
M | rt/memmove.ha | | | 63 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
1 file changed, 54 insertions(+), 9 deletions(-)
diff --git a/rt/memmove.ha b/rt/memmove.ha
@@ -1,19 +1,64 @@
// License: MPL-2.0
// (c) 2021 Drew DeVault <sir@cmpwn.com>
+def SZSZ = size(size);
+def MODSZ = size(size) - 1;
+
export fn memmove(dest: *opaque, src: *const opaque, n: size) void = {
- let d = dest: *[*]u8, s = src: *const [*]u8;
- if (d: uintptr == s: uintptr) {
- return;
- };
+ // implementation adapted from musl libc
+
+ let d = memfunc_ptr { byte = dest: *[*]u8 };
+ let s = memfunc_ptr { byte = src: *[*]u8 };
- if (d: uintptr < s: uintptr) {
- for (let i = 0z; i < n; i += 1) {
- d[i] = s[i];
+ if (d.uptr == s.uptr) return;
+ // equivalent to n <= abs(src - dest)
+ if (s.uptr - d.uptr - n <= -2*n) return memcpy(dest, src, n);
+
+ if (d.uptr < s.uptr) {
+ // if alignment matches, copy the majority as []size
+ if (s.uptr & MODSZ == d.uptr & MODSZ) {
+ // use u8 until we reach a word boundary
+ for (0 < d.uptr & MODSZ) {
+ if (n == 0) return else n -= 1;
+ d.byte[0] = s.byte[0];
+ d.uptr += 1;
+ s.uptr += 1;
+ };
+ for (SZSZ <= n; n -= SZSZ) {
+ d.sz[0] = s.sz[0];
+ // TODO: should be +=, blocked on compiler bug
+ d.uptr = d.uptr + SZSZ;
+ s.uptr = s.uptr + SZSZ;
+ };
+ };
+ for (0 < n; n -= 1) {
+ d.byte[0] = s.byte[0];
+ d.uptr += 1;
+ s.uptr += 1;
};
} else {
- for (let i = 0z; i < n; i += 1) {
- d[n - i - 1] = s[n - i - 1];
+ d.uptr = d.uptr + n;
+ s.uptr = s.uptr + n;
+ // if alignment matches, copy the majority as []size
+ if (s.uptr & MODSZ == d.uptr & MODSZ) {
+ // use u8 until we reach a word boundary
+ for (0 < d.uptr & MODSZ) {
+ if (n == 0) return else n -= 1;
+ d.uptr -= 1;
+ s.uptr -= 1;
+ d.byte[0] = s.byte[0];
+ };
+ for (SZSZ <= n; n -= SZSZ) {
+ // TODO: should be -=, blocked on compiler bug
+ d.uptr = d.uptr - SZSZ;
+ s.uptr = s.uptr - SZSZ;
+ d.sz[0] = s.sz[0];
+ };
+ };
+ for (0 < n; n -= 1) {
+ d.uptr -= 1;
+ s.uptr -= 1;
+ d.byte[0] = s.byte[0];
};
};
};