summaryrefslogtreecommitdiff
path: root/lib/libc/string/memcpy.c
diff options
context:
space:
mode:
authorKacper <kacper@mail.openlinux.dev>2025-12-25 19:24:38 +0100
committerKacper <kacper@mail.openlinux.dev>2025-12-25 20:35:03 +0100
commita984eb367c032dbe2577f01238c3d1268526be70 (patch)
tree437fef40379b2758b129ccea39df3570fa2d145e /lib/libc/string/memcpy.c
parent8834571b202cf4dc9c649cfb096c213b6ecf1566 (diff)
Clang-tidy fixes
Diffstat (limited to 'lib/libc/string/memcpy.c')
-rw-r--r--lib/libc/string/memcpy.c98
1 files changed, 94 insertions, 4 deletions
diff --git a/lib/libc/string/memcpy.c b/lib/libc/string/memcpy.c
index f87d95cd..83a29170 100644
--- a/lib/libc/string/memcpy.c
+++ b/lib/libc/string/memcpy.c
@@ -1,5 +1,6 @@
#include <errno.h> // for EINVAL, ERANGE
#include <stddef.h> // for NULL, errno_t
+#include <stdint.h>
#include <string.h> // for rsize_t, memcpy, size_t, memcpy_s
#include <sys/cdefs.h>
@@ -7,12 +8,101 @@ __weak void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void *memcpy(void *restrict s1, const void *restrict s2, size_t n)
{
- unsigned char *dest = (unsigned char *)s1;
- const unsigned char *src = (const unsigned char *)s2;
+ unsigned char *d = (unsigned char *)s1;
+ const unsigned char *s = (const unsigned char *)s2;
- while (n--) {
- *dest++ = *src++;
+ if (n == 0)
+ return s1;
+
+ if (n < 16) {
+ if (n >= 8) {
+ *(uint64_t *)d = *(const uint64_t *)s;
+ d += 8;
+ s += 8;
+ n -= 8;
+ }
+ if (n >= 4) {
+ *(uint32_t *)d = *(const uint32_t *)s;
+ d += 4;
+ s += 4;
+ n -= 4;
+ }
+ if (n >= 2) {
+ *(uint16_t *)d = *(const uint16_t *)s;
+ d += 2;
+ s += 2;
+ n -= 2;
+ }
+ if (n)
+ *d = *s;
+ return s1;
+ }
+
+ uintptr_t align_mask = 15;
+ size_t misalign = (uintptr_t)d & align_mask;
+ if (misalign) {
+ size_t to_align = 16 - misalign;
+ if (to_align > n)
+ to_align = n;
+ for (size_t i = 0; i < to_align; ++i)
+ *d++ = *s++;
+ n -= to_align;
+ }
+
+ while (n >= 128) {
+#pragma unroll
+ for (int i = 0; i < 8; ++i) {
+ ((i128 *)d)[i] = ((const i128 *)s)[i];
+ }
+ d += 128;
+ s += 128;
+ n -= 128;
+ }
+ while (n >= 64) {
+#pragma unroll
+ for (int i = 0; i < 4; ++i) {
+ ((i128 *)d)[i] = ((const i128 *)s)[i];
+ }
+ d += 64;
+ s += 64;
+ n -= 64;
+ }
+ while (n >= 32) {
+#pragma unroll
+ for (int i = 0; i < 2; ++i) {
+ ((i128 *)d)[i] = ((const i128 *)s)[i];
+ }
+ d += 32;
+ s += 32;
+ n -= 32;
+ }
+ while (n >= 16) {
+ *(i128 *)d = *(const i128 *)s;
+ d += 16;
+ s += 16;
+ n -= 16;
+ }
+
+ if (n >= 8) {
+ *(uint64_t *)d = *(const uint64_t *)s;
+ d += 8;
+ s += 8;
+ n -= 8;
+ }
+ if (n >= 4) {
+ *(uint32_t *)d = *(const uint32_t *)s;
+ d += 4;
+ s += 4;
+ n -= 4;
+ }
+ if (n >= 2) {
+ *(uint16_t *)d = *(const uint16_t *)s;
+ d += 2;
+ s += 2;
+ n -= 2;
}
+ if (n)
+ *d = *s;
return s1;
}