summaryrefslogtreecommitdiffstats
path: root/libc-top-half/musl/src/string
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 13:54:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 13:54:38 +0000
commit8c1ab65c0f548d20b7f177bdb736daaf603340e1 (patch)
treedf55b7e75bf43f2bf500845b105afe3ac3a5157e /libc-top-half/musl/src/string
parentInitial commit. (diff)
downloadwasi-libc-8c1ab65c0f548d20b7f177bdb736daaf603340e1.tar.xz
wasi-libc-8c1ab65c0f548d20b7f177bdb736daaf603340e1.zip
Adding upstream version 0.0~git20221206.8b7148f.upstream/0.0_git20221206.8b7148f
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libc-top-half/musl/src/string')
-rw-r--r--libc-top-half/musl/src/string/aarch64/memcpy.S186
-rw-r--r--libc-top-half/musl/src/string/aarch64/memset.S115
-rw-r--r--libc-top-half/musl/src/string/arm/__aeabi_memcpy.s45
-rw-r--r--libc-top-half/musl/src/string/arm/__aeabi_memset.s31
-rw-r--r--libc-top-half/musl/src/string/arm/memcpy.S479
-rw-r--r--libc-top-half/musl/src/string/bcmp.c8
-rw-r--r--libc-top-half/musl/src/string/bcopy.c8
-rw-r--r--libc-top-half/musl/src/string/bzero.c8
-rw-r--r--libc-top-half/musl/src/string/explicit_bzero.c8
-rw-r--r--libc-top-half/musl/src/string/i386/memcpy.s32
-rw-r--r--libc-top-half/musl/src/string/i386/memmove.s22
-rw-r--r--libc-top-half/musl/src/string/i386/memset.s76
-rw-r--r--libc-top-half/musl/src/string/index.c8
-rw-r--r--libc-top-half/musl/src/string/memccpy.c34
-rw-r--r--libc-top-half/musl/src/string/memchr.c27
-rw-r--r--libc-top-half/musl/src/string/memcmp.c8
-rw-r--r--libc-top-half/musl/src/string/memcpy.c128
-rw-r--r--libc-top-half/musl/src/string/memmem.c149
-rw-r--r--libc-top-half/musl/src/string/memmove.c46
-rw-r--r--libc-top-half/musl/src/string/mempcpy.c7
-rw-r--r--libc-top-half/musl/src/string/memrchr.c11
-rw-r--r--libc-top-half/musl/src/string/memset.c94
-rw-r--r--libc-top-half/musl/src/string/rindex.c8
-rw-r--r--libc-top-half/musl/src/string/stpcpy.c29
-rw-r--r--libc-top-half/musl/src/string/stpncpy.c32
-rw-r--r--libc-top-half/musl/src/string/strcasecmp.c16
-rw-r--r--libc-top-half/musl/src/string/strcasestr.c9
-rw-r--r--libc-top-half/musl/src/string/strcat.c7
-rw-r--r--libc-top-half/musl/src/string/strchr.c7
-rw-r--r--libc-top-half/musl/src/string/strchrnul.c28
-rw-r--r--libc-top-half/musl/src/string/strcmp.c7
-rw-r--r--libc-top-half/musl/src/string/strcpy.c7
-rw-r--r--libc-top-half/musl/src/string/strcspn.c17
-rw-r--r--libc-top-half/musl/src/string/strdup.c10
-rw-r--r--libc-top-half/musl/src/string/strerror_r.c19
-rw-r--r--libc-top-half/musl/src/string/strlcat.c9
-rw-r--r--libc-top-half/musl/src/string/strlcpy.c34
-rw-r--r--libc-top-half/musl/src/string/strlen.c22
-rw-r--r--libc-top-half/musl/src/string/strncasecmp.c17
-rw-r--r--libc-top-half/musl/src/string/strncat.c10
-rw-r--r--libc-top-half/musl/src/string/strncmp.c9
-rw-r--r--libc-top-half/musl/src/string/strncpy.c7
-rw-r--r--libc-top-half/musl/src/string/strndup.c12
-rw-r--r--libc-top-half/musl/src/string/strnlen.c7
-rw-r--r--libc-top-half/musl/src/string/strpbrk.c7
-rw-r--r--libc-top-half/musl/src/string/strrchr.c6
-rw-r--r--libc-top-half/musl/src/string/strsep.c13
-rw-r--r--libc-top-half/musl/src/string/strsignal.c126
-rw-r--r--libc-top-half/musl/src/string/strspn.c20
-rw-r--r--libc-top-half/musl/src/string/strstr.c154
-rw-r--r--libc-top-half/musl/src/string/strtok.c13
-rw-r--r--libc-top-half/musl/src/string/strtok_r.c12
-rw-r--r--libc-top-half/musl/src/string/strverscmp.c34
-rw-r--r--libc-top-half/musl/src/string/swab.c13
-rw-r--r--libc-top-half/musl/src/string/wcpcpy.c6
-rw-r--r--libc-top-half/musl/src/string/wcpncpy.c6
-rw-r--r--libc-top-half/musl/src/string/wcscasecmp.c7
-rw-r--r--libc-top-half/musl/src/string/wcscasecmp_l.c6
-rw-r--r--libc-top-half/musl/src/string/wcscat.c7
-rw-r--r--libc-top-half/musl/src/string/wcschr.c8
-rw-r--r--libc-top-half/musl/src/string/wcscmp.c7
-rw-r--r--libc-top-half/musl/src/string/wcscpy.c8
-rw-r--r--libc-top-half/musl/src/string/wcscspn.c10
-rw-r--r--libc-top-half/musl/src/string/wcsdup.c10
-rw-r--r--libc-top-half/musl/src/string/wcslen.c8
-rw-r--r--libc-top-half/musl/src/string/wcsncasecmp.c9
-rw-r--r--libc-top-half/musl/src/string/wcsncasecmp_l.c6
-rw-r--r--libc-top-half/musl/src/string/wcsncat.c10
-rw-r--r--libc-top-half/musl/src/string/wcsncmp.c7
-rw-r--r--libc-top-half/musl/src/string/wcsncpy.c9
-rw-r--r--libc-top-half/musl/src/string/wcsnlen.c8
-rw-r--r--libc-top-half/musl/src/string/wcspbrk.c7
-rw-r--r--libc-top-half/musl/src/string/wcsrchr.c8
-rw-r--r--libc-top-half/musl/src/string/wcsspn.c8
-rw-r--r--libc-top-half/musl/src/string/wcsstr.c105
-rw-r--r--libc-top-half/musl/src/string/wcstok.c12
-rw-r--r--libc-top-half/musl/src/string/wcswcs.c6
-rw-r--r--libc-top-half/musl/src/string/wmemchr.c7
-rw-r--r--libc-top-half/musl/src/string/wmemcmp.c7
-rw-r--r--libc-top-half/musl/src/string/wmemcpy.c8
-rw-r--r--libc-top-half/musl/src/string/wmemmove.c13
-rw-r--r--libc-top-half/musl/src/string/wmemset.c8
-rw-r--r--libc-top-half/musl/src/string/x86_64/memcpy.s25
-rw-r--r--libc-top-half/musl/src/string/x86_64/memmove.s16
-rw-r--r--libc-top-half/musl/src/string/x86_64/memset.s72
85 files changed, 2685 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/string/aarch64/memcpy.S b/libc-top-half/musl/src/string/aarch64/memcpy.S
new file mode 100644
index 0000000..48bb8a8
--- /dev/null
+++ b/libc-top-half/musl/src/string/aarch64/memcpy.S
@@ -0,0 +1,186 @@
+/*
+ * memcpy - copy memory area
+ *
+ * Copyright (c) 2012-2020, Arm Limited.
+ * SPDX-License-Identifier: MIT
+ */
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64, unaligned accesses.
+ *
+ */
+
+#define dstin x0
+#define src x1
+#define count x2
+#define dst x3
+#define srcend x4
+#define dstend x5
+#define A_l x6
+#define A_lw w6
+#define A_h x7
+#define B_l x8
+#define B_lw w8
+#define B_h x9
+#define C_l x10
+#define C_lw w10
+#define C_h x11
+#define D_l x12
+#define D_h x13
+#define E_l x14
+#define E_h x15
+#define F_l x16
+#define F_h x17
+#define G_l count
+#define G_h dst
+#define H_l src
+#define H_h srcend
+#define tmp1 x14
+
+/* This implementation of memcpy uses unaligned accesses and branchless
+ sequences to keep the code small, simple and improve performance.
+
+ Copies are split into 3 main cases: small copies of up to 32 bytes, medium
+ copies of up to 128 bytes, and large copies. The overhead of the overlap
+ check is negligible since it is only required for large copies.
+
+ Large copies use a software pipelined loop processing 64 bytes per iteration.
+ The destination pointer is 16-byte aligned to minimize unaligned accesses.
+ The loop tail is handled by always copying 64 bytes from the end.
+*/
+
+.global memcpy
+.type memcpy,%function
+memcpy:
+ add srcend, src, count
+ add dstend, dstin, count
+ cmp count, 128
+ b.hi .Lcopy_long
+ cmp count, 32
+ b.hi .Lcopy32_128
+
+ /* Small copies: 0..32 bytes. */
+ cmp count, 16
+ b.lo .Lcopy16
+ ldp A_l, A_h, [src]
+ ldp D_l, D_h, [srcend, -16]
+ stp A_l, A_h, [dstin]
+ stp D_l, D_h, [dstend, -16]
+ ret
+
+ /* Copy 8-15 bytes. */
+.Lcopy16:
+ tbz count, 3, .Lcopy8
+ ldr A_l, [src]
+ ldr A_h, [srcend, -8]
+ str A_l, [dstin]
+ str A_h, [dstend, -8]
+ ret
+
+ .p2align 3
+ /* Copy 4-7 bytes. */
+.Lcopy8:
+ tbz count, 2, .Lcopy4
+ ldr A_lw, [src]
+ ldr B_lw, [srcend, -4]
+ str A_lw, [dstin]
+ str B_lw, [dstend, -4]
+ ret
+
+ /* Copy 0..3 bytes using a branchless sequence. */
+.Lcopy4:
+ cbz count, .Lcopy0
+ lsr tmp1, count, 1
+ ldrb A_lw, [src]
+ ldrb C_lw, [srcend, -1]
+ ldrb B_lw, [src, tmp1]
+ strb A_lw, [dstin]
+ strb B_lw, [dstin, tmp1]
+ strb C_lw, [dstend, -1]
+.Lcopy0:
+ ret
+
+ .p2align 4
+ /* Medium copies: 33..128 bytes. */
+.Lcopy32_128:
+ ldp A_l, A_h, [src]
+ ldp B_l, B_h, [src, 16]
+ ldp C_l, C_h, [srcend, -32]
+ ldp D_l, D_h, [srcend, -16]
+ cmp count, 64
+ b.hi .Lcopy128
+ stp A_l, A_h, [dstin]
+ stp B_l, B_h, [dstin, 16]
+ stp C_l, C_h, [dstend, -32]
+ stp D_l, D_h, [dstend, -16]
+ ret
+
+ .p2align 4
+ /* Copy 65..128 bytes. */
+.Lcopy128:
+ ldp E_l, E_h, [src, 32]
+ ldp F_l, F_h, [src, 48]
+ cmp count, 96
+ b.ls .Lcopy96
+ ldp G_l, G_h, [srcend, -64]
+ ldp H_l, H_h, [srcend, -48]
+ stp G_l, G_h, [dstend, -64]
+ stp H_l, H_h, [dstend, -48]
+.Lcopy96:
+ stp A_l, A_h, [dstin]
+ stp B_l, B_h, [dstin, 16]
+ stp E_l, E_h, [dstin, 32]
+ stp F_l, F_h, [dstin, 48]
+ stp C_l, C_h, [dstend, -32]
+ stp D_l, D_h, [dstend, -16]
+ ret
+
+ .p2align 4
+ /* Copy more than 128 bytes. */
+.Lcopy_long:
+
+ /* Copy 16 bytes and then align dst to 16-byte alignment. */
+
+ ldp D_l, D_h, [src]
+ and tmp1, dstin, 15
+ bic dst, dstin, 15
+ sub src, src, tmp1
+ add count, count, tmp1 /* Count is now 16 too large. */
+ ldp A_l, A_h, [src, 16]
+ stp D_l, D_h, [dstin]
+ ldp B_l, B_h, [src, 32]
+ ldp C_l, C_h, [src, 48]
+ ldp D_l, D_h, [src, 64]!
+ subs count, count, 128 + 16 /* Test and readjust count. */
+ b.ls .Lcopy64_from_end
+
+.Lloop64:
+ stp A_l, A_h, [dst, 16]
+ ldp A_l, A_h, [src, 16]
+ stp B_l, B_h, [dst, 32]
+ ldp B_l, B_h, [src, 32]
+ stp C_l, C_h, [dst, 48]
+ ldp C_l, C_h, [src, 48]
+ stp D_l, D_h, [dst, 64]!
+ ldp D_l, D_h, [src, 64]!
+ subs count, count, 64
+ b.hi .Lloop64
+
+ /* Write the last iteration and copy 64 bytes from the end. */
+.Lcopy64_from_end:
+ ldp E_l, E_h, [srcend, -64]
+ stp A_l, A_h, [dst, 16]
+ ldp A_l, A_h, [srcend, -48]
+ stp B_l, B_h, [dst, 32]
+ ldp B_l, B_h, [srcend, -32]
+ stp C_l, C_h, [dst, 48]
+ ldp C_l, C_h, [srcend, -16]
+ stp D_l, D_h, [dst, 64]
+ stp E_l, E_h, [dstend, -64]
+ stp A_l, A_h, [dstend, -48]
+ stp B_l, B_h, [dstend, -32]
+ stp C_l, C_h, [dstend, -16]
+ ret
+
+.size memcpy,.-memcpy
diff --git a/libc-top-half/musl/src/string/aarch64/memset.S b/libc-top-half/musl/src/string/aarch64/memset.S
new file mode 100644
index 0000000..f0d29b7
--- /dev/null
+++ b/libc-top-half/musl/src/string/aarch64/memset.S
@@ -0,0 +1,115 @@
+/*
+ * memset - fill memory with a constant byte
+ *
+ * Copyright (c) 2012-2020, Arm Limited.
+ * SPDX-License-Identifier: MIT
+ */
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64, Advanced SIMD, unaligned accesses.
+ *
+ */
+
+#define dstin x0
+#define val x1
+#define valw w1
+#define count x2
+#define dst x3
+#define dstend x4
+#define zva_val x5
+
+.global memset
+.type memset,%function
+memset:
+
+ dup v0.16B, valw
+ add dstend, dstin, count
+
+ cmp count, 96
+ b.hi .Lset_long
+ cmp count, 16
+ b.hs .Lset_medium
+ mov val, v0.D[0]
+
+ /* Set 0..15 bytes. */
+ tbz count, 3, 1f
+ str val, [dstin]
+ str val, [dstend, -8]
+ ret
+ nop
+1: tbz count, 2, 2f
+ str valw, [dstin]
+ str valw, [dstend, -4]
+ ret
+2: cbz count, 3f
+ strb valw, [dstin]
+ tbz count, 1, 3f
+ strh valw, [dstend, -2]
+3: ret
+
+ /* Set 17..96 bytes. */
+.Lset_medium:
+ str q0, [dstin]
+ tbnz count, 6, .Lset96
+ str q0, [dstend, -16]
+ tbz count, 5, 1f
+ str q0, [dstin, 16]
+ str q0, [dstend, -32]
+1: ret
+
+ .p2align 4
+ /* Set 64..96 bytes. Write 64 bytes from the start and
+ 32 bytes from the end. */
+.Lset96:
+ str q0, [dstin, 16]
+ stp q0, q0, [dstin, 32]
+ stp q0, q0, [dstend, -32]
+ ret
+
+ .p2align 4
+.Lset_long:
+ and valw, valw, 255
+ bic dst, dstin, 15
+ str q0, [dstin]
+ cmp count, 160
+ ccmp valw, 0, 0, hs
+ b.ne .Lno_zva
+
+#ifndef SKIP_ZVA_CHECK
+ mrs zva_val, dczid_el0
+ and zva_val, zva_val, 31
+ cmp zva_val, 4 /* ZVA size is 64 bytes. */
+ b.ne .Lno_zva
+#endif
+ str q0, [dst, 16]
+ stp q0, q0, [dst, 32]
+ bic dst, dst, 63
+ sub count, dstend, dst /* Count is now 64 too large. */
+ sub count, count, 128 /* Adjust count and bias for loop. */
+
+ .p2align 4
+.Lzva_loop:
+ add dst, dst, 64
+ dc zva, dst
+ subs count, count, 64
+ b.hi .Lzva_loop
+ stp q0, q0, [dstend, -64]
+ stp q0, q0, [dstend, -32]
+ ret
+
+.Lno_zva:
+ sub count, dstend, dst /* Count is 16 too large. */
+ sub dst, dst, 16 /* Dst is biased by -32. */
+ sub count, count, 64 + 16 /* Adjust count and bias for loop. */
+.Lno_zva_loop:
+ stp q0, q0, [dst, 32]
+ stp q0, q0, [dst, 64]!
+ subs count, count, 64
+ b.hi .Lno_zva_loop
+ stp q0, q0, [dstend, -64]
+ stp q0, q0, [dstend, -32]
+ ret
+
+.size memset,.-memset
+
diff --git a/libc-top-half/musl/src/string/arm/__aeabi_memcpy.s b/libc-top-half/musl/src/string/arm/__aeabi_memcpy.s
new file mode 100644
index 0000000..3a527e4
--- /dev/null
+++ b/libc-top-half/musl/src/string/arm/__aeabi_memcpy.s
@@ -0,0 +1,45 @@
+.syntax unified
+
+.global __aeabi_memcpy8
+.global __aeabi_memcpy4
+.global __aeabi_memcpy
+.global __aeabi_memmove8
+.global __aeabi_memmove4
+.global __aeabi_memmove
+
+.type __aeabi_memcpy8,%function
+.type __aeabi_memcpy4,%function
+.type __aeabi_memcpy,%function
+.type __aeabi_memmove8,%function
+.type __aeabi_memmove4,%function
+.type __aeabi_memmove,%function
+
+__aeabi_memmove8:
+__aeabi_memmove4:
+__aeabi_memmove:
+ cmp r0, r1
+ bls 3f
+ cmp r2, #0
+ beq 2f
+ adds r0, r0, r2
+ adds r2, r1, r2
+1: subs r2, r2, #1
+ ldrb r3, [r2]
+ subs r0, r0, #1
+ strb r3, [r0]
+ cmp r1, r2
+ bne 1b
+2: bx lr
+__aeabi_memcpy8:
+__aeabi_memcpy4:
+__aeabi_memcpy:
+3: cmp r2, #0
+ beq 2f
+ adds r2, r1, r2
+1: ldrb r3, [r1]
+ adds r1, r1, #1
+ strb r3, [r0]
+ adds r0, r0, #1
+ cmp r1, r2
+ bne 1b
+2: bx lr
diff --git a/libc-top-half/musl/src/string/arm/__aeabi_memset.s b/libc-top-half/musl/src/string/arm/__aeabi_memset.s
new file mode 100644
index 0000000..f9f6058
--- /dev/null
+++ b/libc-top-half/musl/src/string/arm/__aeabi_memset.s
@@ -0,0 +1,31 @@
+.syntax unified
+
+.global __aeabi_memclr8
+.global __aeabi_memclr4
+.global __aeabi_memclr
+.global __aeabi_memset8
+.global __aeabi_memset4
+.global __aeabi_memset
+
+.type __aeabi_memclr8,%function
+.type __aeabi_memclr4,%function
+.type __aeabi_memclr,%function
+.type __aeabi_memset8,%function
+.type __aeabi_memset4,%function
+.type __aeabi_memset,%function
+
+__aeabi_memclr8:
+__aeabi_memclr4:
+__aeabi_memclr:
+ movs r2, #0
+__aeabi_memset8:
+__aeabi_memset4:
+__aeabi_memset:
+ cmp r1, #0
+ beq 2f
+ adds r1, r0, r1
+1: strb r2, [r0]
+ adds r0, r0, #1
+ cmp r1, r0
+ bne 1b
+2: bx lr
diff --git a/libc-top-half/musl/src/string/arm/memcpy.S b/libc-top-half/musl/src/string/arm/memcpy.S
new file mode 100644
index 0000000..869e344
--- /dev/null
+++ b/libc-top-half/musl/src/string/arm/memcpy.S
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * Optimized memcpy() for ARM.
+ *
+ * note that memcpy() always returns the destination pointer,
+ * so we have to preserve R0.
+ */
+
+/*
+ * This file has been modified from the original for use in musl libc.
+ * The main changes are: addition of .type memcpy,%function to make the
+ * code safely callable from thumb mode, adjusting the return
+ * instructions to be compatible with pre-thumb ARM cpus, removal of
+ * prefetch code that is not compatible with older cpus and support for
+ * building as thumb 2 and big-endian.
+ */
+
+.syntax unified
+
+.global memcpy
+.type memcpy,%function
+memcpy:
+ /* The stack must always be 64-bits aligned to be compliant with the
+ * ARM ABI. Since we have to save R0, we might as well save R4
+ * which we can use for better pipelining of the reads below
+ */
+ .fnstart
+ .save {r0, r4, lr}
+ stmfd sp!, {r0, r4, lr}
+ /* Making room for r5-r11 which will be spilled later */
+ .pad #28
+ sub sp, sp, #28
+
+ /* it simplifies things to take care of len<4 early */
+ cmp r2, #4
+ blo copy_last_3_and_return
+
+ /* compute the offset to align the source
+ * offset = (4-(src&3))&3 = -src & 3
+ */
+ rsb r3, r1, #0
+ ands r3, r3, #3
+ beq src_aligned
+
+ /* align source to 32 bits. We need to insert 2 instructions between
+ * a ldr[b|h] and str[b|h] because byte and half-word instructions
+ * stall 2 cycles.
+ */
+ movs r12, r3, lsl #31
+ sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
+ ldrbmi r3, [r1], #1
+ ldrbcs r4, [r1], #1
+ ldrbcs r12,[r1], #1
+ strbmi r3, [r0], #1
+ strbcs r4, [r0], #1
+ strbcs r12,[r0], #1
+
+src_aligned:
+
+ /* see if src and dst are aligned together (congruent) */
+ eor r12, r0, r1
+ tst r12, #3
+ bne non_congruent
+
+ /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
+ * frame. Don't update sp.
+ */
+ stmea sp, {r5-r11}
+
+ /* align the destination to a cache-line */
+ rsb r3, r0, #0
+ ands r3, r3, #0x1C
+ beq congruent_aligned32
+ cmp r3, r2
+ andhi r3, r2, #0x1C
+
+ /* conditionnaly copies 0 to 7 words (length in r3) */
+ movs r12, r3, lsl #28
+ ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
+ ldmmi r1!, {r8, r9} /* 8 bytes */
+ stmcs r0!, {r4, r5, r6, r7}
+ stmmi r0!, {r8, r9}
+ tst r3, #0x4
+ ldrne r10,[r1], #4 /* 4 bytes */
+ strne r10,[r0], #4
+ sub r2, r2, r3
+
+congruent_aligned32:
+ /*
+ * here source is aligned to 32 bytes.
+ */
+
+cached_aligned32:
+ subs r2, r2, #32
+ blo less_than_32_left
+
+ /*
+ * We preload a cache-line up to 64 bytes ahead. On the 926, this will
+ * stall only until the requested world is fetched, but the linefill
+ * continues in the the background.
+ * While the linefill is going, we write our previous cache-line
+ * into the write-buffer (which should have some free space).
+ * When the linefill is done, the writebuffer will
+ * start dumping its content into memory
+ *
+ * While all this is going, we then load a full cache line into
+ * 8 registers, this cache line should be in the cache by now
+ * (or partly in the cache).
+ *
+ * This code should work well regardless of the source/dest alignment.
+ *
+ */
+
+ /* Align the preload register to a cache-line because the cpu does
+ * "critical word first" (the first word requested is loaded first).
+ */
+ @ bic r12, r1, #0x1F
+ @ add r12, r12, #64
+
+1: ldmia r1!, { r4-r11 }
+ subs r2, r2, #32
+
+ /*
+ * NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
+ * for ARM9 preload will not be safely guarded by the preceding subs.
+ * When it is safely guarded the only possibility to have SIGSEGV here
+ * is because the caller overstates the length.
+ */
+ @ ldrhi r3, [r12], #32 /* cheap ARM9 preload */
+ stmia r0!, { r4-r11 }
+ bhs 1b
+
+ add r2, r2, #32
+
+less_than_32_left:
+ /*
+ * less than 32 bytes left at this point (length in r2)
+ */
+
+ /* skip all this if there is nothing to do, which should
+ * be a common case (if not executed the code below takes
+ * about 16 cycles)
+ */
+ tst r2, #0x1F
+ beq 1f
+
+ /* conditionnaly copies 0 to 31 bytes */
+ movs r12, r2, lsl #28
+ ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
+ ldmmi r1!, {r8, r9} /* 8 bytes */
+ stmcs r0!, {r4, r5, r6, r7}
+ stmmi r0!, {r8, r9}
+ movs r12, r2, lsl #30
+ ldrcs r3, [r1], #4 /* 4 bytes */
+ ldrhmi r4, [r1], #2 /* 2 bytes */
+ strcs r3, [r0], #4
+ strhmi r4, [r0], #2
+ tst r2, #0x1
+ ldrbne r3, [r1] /* last byte */
+ strbne r3, [r0]
+
+ /* we're done! restore everything and return */
+1: ldmfd sp!, {r5-r11}
+ ldmfd sp!, {r0, r4, lr}
+ bx lr
+
+ /********************************************************************/
+
+non_congruent:
+ /*
+ * here source is aligned to 4 bytes
+ * but destination is not.
+ *
+ * in the code below r2 is the number of bytes read
+ * (the number of bytes written is always smaller, because we have
+ * partial words in the shift queue)
+ */
+ cmp r2, #4
+ blo copy_last_3_and_return
+
+ /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
+ * frame. Don't update sp.
+ */
+ stmea sp, {r5-r11}
+
+ /* compute shifts needed to align src to dest */
+ rsb r5, r0, #0
+ and r5, r5, #3 /* r5 = # bytes in partial words */
+ mov r12, r5, lsl #3 /* r12 = right */
+ rsb lr, r12, #32 /* lr = left */
+
+ /* read the first word */
+ ldr r3, [r1], #4
+ sub r2, r2, #4
+
+ /* write a partial word (0 to 3 bytes), such that destination
+ * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
+ */
+ movs r5, r5, lsl #31
+
+#if __ARMEB__
+ movmi r3, r3, ror #24
+ strbmi r3, [r0], #1
+ movcs r3, r3, ror #24
+ strbcs r3, [r0], #1
+ movcs r3, r3, ror #24
+ strbcs r3, [r0], #1
+#else
+ strbmi r3, [r0], #1
+ movmi r3, r3, lsr #8
+ strbcs r3, [r0], #1
+ movcs r3, r3, lsr #8
+ strbcs r3, [r0], #1
+ movcs r3, r3, lsr #8
+#endif
+
+ cmp r2, #4
+ blo partial_word_tail
+
+#if __ARMEB__
+ mov r3, r3, lsr r12
+ mov r3, r3, lsl r12
+#endif
+
+ /* Align destination to 32 bytes (cache line boundary) */
+1: tst r0, #0x1c
+ beq 2f
+ ldr r5, [r1], #4
+ sub r2, r2, #4
+#if __ARMEB__
+ mov r4, r5, lsr lr
+ orr r4, r4, r3
+ mov r3, r5, lsl r12
+#else
+ mov r4, r5, lsl lr
+ orr r4, r4, r3
+ mov r3, r5, lsr r12
+#endif
+ str r4, [r0], #4
+ cmp r2, #4
+ bhs 1b
+ blo partial_word_tail
+
+ /* copy 32 bytes at a time */
+2: subs r2, r2, #32
+ blo less_than_thirtytwo
+
+ /* Use immediate mode for the shifts, because there is an extra cycle
+ * for register shifts, which could account for up to 50% of
+ * performance hit.
+ */
+
+ cmp r12, #24
+ beq loop24
+ cmp r12, #8
+ beq loop8
+
+loop16:
+ ldr r12, [r1], #4
+1: mov r4, r12
+ ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
+ subs r2, r2, #32
+ ldrhs r12, [r1], #4
+#if __ARMEB__
+ orr r3, r3, r4, lsr #16
+ mov r4, r4, lsl #16
+ orr r4, r4, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r6, lsr #16
+ mov r6, r6, lsl #16
+ orr r6, r6, r7, lsr #16
+ mov r7, r7, lsl #16
+ orr r7, r7, r8, lsr #16
+ mov r8, r8, lsl #16
+ orr r8, r8, r9, lsr #16
+ mov r9, r9, lsl #16
+ orr r9, r9, r10, lsr #16
+ mov r10, r10, lsl #16
+ orr r10, r10, r11, lsr #16
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsl #16
+#else
+ orr r3, r3, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ mov r6, r6, lsr #16
+ orr r6, r6, r7, lsl #16
+ mov r7, r7, lsr #16
+ orr r7, r7, r8, lsl #16
+ mov r8, r8, lsr #16
+ orr r8, r8, r9, lsl #16
+ mov r9, r9, lsr #16
+ orr r9, r9, r10, lsl #16
+ mov r10, r10, lsr #16
+ orr r10, r10, r11, lsl #16
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsr #16
+#endif
+ bhs 1b
+ b less_than_thirtytwo
+
+loop8:
+ ldr r12, [r1], #4
+1: mov r4, r12
+ ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
+ subs r2, r2, #32
+ ldrhs r12, [r1], #4
+#if __ARMEB__
+ orr r3, r3, r4, lsr #24
+ mov r4, r4, lsl #8
+ orr r4, r4, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r6, lsr #24
+ mov r6, r6, lsl #8
+ orr r6, r6, r7, lsr #24
+ mov r7, r7, lsl #8
+ orr r7, r7, r8, lsr #24
+ mov r8, r8, lsl #8
+ orr r8, r8, r9, lsr #24
+ mov r9, r9, lsl #8
+ orr r9, r9, r10, lsr #24
+ mov r10, r10, lsl #8
+ orr r10, r10, r11, lsr #24
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsl #8
+#else
+ orr r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ mov r6, r6, lsr #8
+ orr r6, r6, r7, lsl #24
+ mov r7, r7, lsr #8
+ orr r7, r7, r8, lsl #24
+ mov r8, r8, lsr #8
+ orr r8, r8, r9, lsl #24
+ mov r9, r9, lsr #8
+ orr r9, r9, r10, lsl #24
+ mov r10, r10, lsr #8
+ orr r10, r10, r11, lsl #24
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsr #8
+#endif
+ bhs 1b
+ b less_than_thirtytwo
+
+loop24:
+ ldr r12, [r1], #4
+1: mov r4, r12
+ ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
+ subs r2, r2, #32
+ ldrhs r12, [r1], #4
+#if __ARMEB__
+ orr r3, r3, r4, lsr #8
+ mov r4, r4, lsl #24
+ orr r4, r4, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r6, lsr #8
+ mov r6, r6, lsl #24
+ orr r6, r6, r7, lsr #8
+ mov r7, r7, lsl #24
+ orr r7, r7, r8, lsr #8
+ mov r8, r8, lsl #24
+ orr r8, r8, r9, lsr #8
+ mov r9, r9, lsl #24
+ orr r9, r9, r10, lsr #8
+ mov r10, r10, lsl #24
+ orr r10, r10, r11, lsr #8
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsl #24
+#else
+ orr r3, r3, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ mov r6, r6, lsr #24
+ orr r6, r6, r7, lsl #8
+ mov r7, r7, lsr #24
+ orr r7, r7, r8, lsl #8
+ mov r8, r8, lsr #24
+ orr r8, r8, r9, lsl #8
+ mov r9, r9, lsr #24
+ orr r9, r9, r10, lsl #8
+ mov r10, r10, lsr #24
+ orr r10, r10, r11, lsl #8
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsr #24
+#endif
+ bhs 1b
+
+less_than_thirtytwo:
+ /* copy the last 0 to 31 bytes of the source */
+ rsb r12, lr, #32 /* we corrupted r12, recompute it */
+ add r2, r2, #32
+ cmp r2, #4
+ blo partial_word_tail
+
+1: ldr r5, [r1], #4
+ sub r2, r2, #4
+#if __ARMEB__
+ mov r4, r5, lsr lr
+ orr r4, r4, r3
+ mov r3, r5, lsl r12
+#else
+ mov r4, r5, lsl lr
+ orr r4, r4, r3
+ mov r3, r5, lsr r12
+#endif
+ str r4, [r0], #4
+ cmp r2, #4
+ bhs 1b
+
+partial_word_tail:
+ /* we have a partial word in the input buffer */
+ movs r5, lr, lsl #(31-3)
+#if __ARMEB__
+ movmi r3, r3, ror #24
+ strbmi r3, [r0], #1
+ movcs r3, r3, ror #24
+ strbcs r3, [r0], #1
+ movcs r3, r3, ror #24
+ strbcs r3, [r0], #1
+#else
+ strbmi r3, [r0], #1
+ movmi r3, r3, lsr #8
+ strbcs r3, [r0], #1
+ movcs r3, r3, lsr #8
+ strbcs r3, [r0], #1
+#endif
+
+ /* Refill spilled registers from the stack. Don't update sp. */
+ ldmfd sp, {r5-r11}
+
+copy_last_3_and_return:
+ movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
+ ldrbmi r2, [r1], #1
+ ldrbcs r3, [r1], #1
+ ldrbcs r12,[r1]
+ strbmi r2, [r0], #1
+ strbcs r3, [r0], #1
+ strbcs r12,[r0]
+
+ /* we're done! restore sp and spilled registers and return */
+ add sp, sp, #28
+ ldmfd sp!, {r0, r4, lr}
+ bx lr
+
diff --git a/libc-top-half/musl/src/string/bcmp.c b/libc-top-half/musl/src/string/bcmp.c
new file mode 100644
index 0000000..87c6007
--- /dev/null
+++ b/libc-top-half/musl/src/string/bcmp.c
@@ -0,0 +1,8 @@
+#define _BSD_SOURCE
+#include <string.h>
+#include <strings.h>
+
+int bcmp(const void *s1, const void *s2, size_t n)
+{
+ return memcmp(s1, s2, n);
+}
diff --git a/libc-top-half/musl/src/string/bcopy.c b/libc-top-half/musl/src/string/bcopy.c
new file mode 100644
index 0000000..a07129f
--- /dev/null
+++ b/libc-top-half/musl/src/string/bcopy.c
@@ -0,0 +1,8 @@
+#define _BSD_SOURCE
+#include <string.h>
+#include <strings.h>
+
+void bcopy(const void *s1, void *s2, size_t n)
+{
+ memmove(s2, s1, n);
+}
diff --git a/libc-top-half/musl/src/string/bzero.c b/libc-top-half/musl/src/string/bzero.c
new file mode 100644
index 0000000..ba536b0
--- /dev/null
+++ b/libc-top-half/musl/src/string/bzero.c
@@ -0,0 +1,8 @@
+#define _BSD_SOURCE
+#include <string.h>
+#include <strings.h>
+
+void bzero(void *s, size_t n)
+{
+ memset(s, 0, n);
+}
diff --git a/libc-top-half/musl/src/string/explicit_bzero.c b/libc-top-half/musl/src/string/explicit_bzero.c
new file mode 100644
index 0000000..f2e12f2
--- /dev/null
+++ b/libc-top-half/musl/src/string/explicit_bzero.c
@@ -0,0 +1,8 @@
+#define _BSD_SOURCE
+#include <string.h>
+
+void explicit_bzero(void *d, size_t n)
+{
+ d = memset(d, 0, n);
+ __asm__ __volatile__ ("" : : "r"(d) : "memory");
+}
diff --git a/libc-top-half/musl/src/string/i386/memcpy.s b/libc-top-half/musl/src/string/i386/memcpy.s
new file mode 100644
index 0000000..0608dd8
--- /dev/null
+++ b/libc-top-half/musl/src/string/i386/memcpy.s
@@ -0,0 +1,32 @@
+.global memcpy
+.global __memcpy_fwd
+.hidden __memcpy_fwd
+.type memcpy,@function
+memcpy:
+__memcpy_fwd:
+ push %esi
+ push %edi
+ mov 12(%esp),%edi
+ mov 16(%esp),%esi
+ mov 20(%esp),%ecx
+ mov %edi,%eax
+ cmp $4,%ecx
+ jc 1f
+ test $3,%edi
+ jz 1f
+2: movsb
+ dec %ecx
+ test $3,%edi
+ jnz 2b
+1: mov %ecx,%edx
+ shr $2,%ecx
+ rep
+ movsl
+ and $3,%edx
+ jz 1f
+2: movsb
+ dec %edx
+ jnz 2b
+1: pop %edi
+ pop %esi
+ ret
diff --git a/libc-top-half/musl/src/string/i386/memmove.s b/libc-top-half/musl/src/string/i386/memmove.s
new file mode 100644
index 0000000..2a6a504
--- /dev/null
+++ b/libc-top-half/musl/src/string/i386/memmove.s
@@ -0,0 +1,22 @@
+.global memmove
+.type memmove,@function
+memmove:
+ mov 4(%esp),%eax
+ sub 8(%esp),%eax
+ cmp 12(%esp),%eax
+.hidden __memcpy_fwd
+ jae __memcpy_fwd
+ push %esi
+ push %edi
+ mov 12(%esp),%edi
+ mov 16(%esp),%esi
+ mov 20(%esp),%ecx
+ lea -1(%edi,%ecx),%edi
+ lea -1(%esi,%ecx),%esi
+ std
+ rep movsb
+ cld
+ lea 1(%edi),%eax
+ pop %edi
+ pop %esi
+ ret
diff --git a/libc-top-half/musl/src/string/i386/memset.s b/libc-top-half/musl/src/string/i386/memset.s
new file mode 100644
index 0000000..d00422c
--- /dev/null
+++ b/libc-top-half/musl/src/string/i386/memset.s
@@ -0,0 +1,76 @@
+.global memset
+.type memset,@function
+memset:
+ mov 12(%esp),%ecx
+ cmp $62,%ecx
+ ja 2f
+
+ mov 8(%esp),%dl
+ mov 4(%esp),%eax
+ test %ecx,%ecx
+ jz 1f
+
+ mov %dl,%dh
+
+ mov %dl,(%eax)
+ mov %dl,-1(%eax,%ecx)
+ cmp $2,%ecx
+ jbe 1f
+
+ mov %dx,1(%eax)
+ mov %dx,(-1-2)(%eax,%ecx)
+ cmp $6,%ecx
+ jbe 1f
+
+ shl $16,%edx
+ mov 8(%esp),%dl
+ mov 8(%esp),%dh
+
+ mov %edx,(1+2)(%eax)
+ mov %edx,(-1-2-4)(%eax,%ecx)
+ cmp $14,%ecx
+ jbe 1f
+
+ mov %edx,(1+2+4)(%eax)
+ mov %edx,(1+2+4+4)(%eax)
+ mov %edx,(-1-2-4-8)(%eax,%ecx)
+ mov %edx,(-1-2-4-4)(%eax,%ecx)
+ cmp $30,%ecx
+ jbe 1f
+
+ mov %edx,(1+2+4+8)(%eax)
+ mov %edx,(1+2+4+8+4)(%eax)
+ mov %edx,(1+2+4+8+8)(%eax)
+ mov %edx,(1+2+4+8+12)(%eax)
+ mov %edx,(-1-2-4-8-16)(%eax,%ecx)
+ mov %edx,(-1-2-4-8-12)(%eax,%ecx)
+ mov %edx,(-1-2-4-8-8)(%eax,%ecx)
+ mov %edx,(-1-2-4-8-4)(%eax,%ecx)
+
+1: ret
+
+2: movzbl 8(%esp),%eax
+ mov %edi,12(%esp)
+ imul $0x1010101,%eax
+ mov 4(%esp),%edi
+ test $15,%edi
+ mov %eax,-4(%edi,%ecx)
+ jnz 2f
+
+1: shr $2, %ecx
+ rep
+ stosl
+ mov 4(%esp),%eax
+ mov 12(%esp),%edi
+ ret
+
+2: xor %edx,%edx
+ sub %edi,%edx
+ and $15,%edx
+ mov %eax,(%edi)
+ mov %eax,4(%edi)
+ mov %eax,8(%edi)
+ mov %eax,12(%edi)
+ sub %edx,%ecx
+ add %edx,%edi
+ jmp 1b
diff --git a/libc-top-half/musl/src/string/index.c b/libc-top-half/musl/src/string/index.c
new file mode 100644
index 0000000..252948f
--- /dev/null
+++ b/libc-top-half/musl/src/string/index.c
@@ -0,0 +1,8 @@
+#define _BSD_SOURCE
+#include <string.h>
+#include <strings.h>
+
+char *index(const char *s, int c)
+{
+ return strchr(s, c);
+}
diff --git a/libc-top-half/musl/src/string/memccpy.c b/libc-top-half/musl/src/string/memccpy.c
new file mode 100644
index 0000000..3b0a370
--- /dev/null
+++ b/libc-top-half/musl/src/string/memccpy.c
@@ -0,0 +1,34 @@
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
+{
+ unsigned char *d = dest;
+ const unsigned char *s = src;
+
+ c = (unsigned char)c;
+#ifdef __GNUC__
+ typedef size_t __attribute__((__may_alias__)) word;
+ word *wd;
+ const word *ws;
+ if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
+ for (; ((uintptr_t)s & ALIGN) && n && (*d=*s)!=c; n--, s++, d++);
+ if ((uintptr_t)s & ALIGN) goto tail;
+ size_t k = ONES * c;
+ wd=(void *)d; ws=(const void *)s;
+ for (; n>=sizeof(size_t) && !HASZERO(*ws^k);
+ n-=sizeof(size_t), ws++, wd++) *wd = *ws;
+ d=(void *)wd; s=(const void *)ws;
+ }
+#endif
+ for (; n && (*d=*s)!=c; n--, s++, d++);
+tail:
+ if (n) return d+1;
+ return 0;
+}
diff --git a/libc-top-half/musl/src/string/memchr.c b/libc-top-half/musl/src/string/memchr.c
new file mode 100644
index 0000000..65f0d78
--- /dev/null
+++ b/libc-top-half/musl/src/string/memchr.c
@@ -0,0 +1,27 @@
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define SS (sizeof(size_t))
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+void *memchr(const void *src, int c, size_t n)
+{
+ const unsigned char *s = src;
+ c = (unsigned char)c;
+#ifdef __GNUC__
+ for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
+ if (n && *s != c) {
+ typedef size_t __attribute__((__may_alias__)) word;
+ const word *w;
+ size_t k = ONES * c;
+ for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
+ s = (const void *)w;
+ }
+#endif
+ for (; n && *s != c; s++, n--);
+ return n ? (void *)s : 0;
+}
diff --git a/libc-top-half/musl/src/string/memcmp.c b/libc-top-half/musl/src/string/memcmp.c
new file mode 100644
index 0000000..bdbce9f
--- /dev/null
+++ b/libc-top-half/musl/src/string/memcmp.c
@@ -0,0 +1,8 @@
+#include <string.h>
+
+int memcmp(const void *vl, const void *vr, size_t n)
+{
+ const unsigned char *l=vl, *r=vr;
+ for (; n && *l == *r; n--, l++, r++);
+ return n ? *l-*r : 0;
+}
diff --git a/libc-top-half/musl/src/string/memcpy.c b/libc-top-half/musl/src/string/memcpy.c
new file mode 100644
index 0000000..3cc7e28
--- /dev/null
+++ b/libc-top-half/musl/src/string/memcpy.c
@@ -0,0 +1,128 @@
+#include <string.h>
+#include <stdint.h>
+#include <endian.h>
+
+void *memcpy(void *restrict dest, const void *restrict src, size_t n)
+{
+#if defined(__wasm_bulk_memory__)
+ if (n > BULK_MEMORY_THRESHOLD)
+ return __builtin_memcpy(dest, src, n);
+#endif
+ unsigned char *d = dest;
+ const unsigned char *s = src;
+
+#ifdef __GNUC__
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define LS >>
+#define RS <<
+#else
+#define LS <<
+#define RS >>
+#endif
+
+ typedef uint32_t __attribute__((__may_alias__)) u32;
+ uint32_t w, x;
+
+ for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++;
+
+ if ((uintptr_t)d % 4 == 0) {
+ for (; n>=16; s+=16, d+=16, n-=16) {
+ *(u32 *)(d+0) = *(u32 *)(s+0);
+ *(u32 *)(d+4) = *(u32 *)(s+4);
+ *(u32 *)(d+8) = *(u32 *)(s+8);
+ *(u32 *)(d+12) = *(u32 *)(s+12);
+ }
+ if (n&8) {
+ *(u32 *)(d+0) = *(u32 *)(s+0);
+ *(u32 *)(d+4) = *(u32 *)(s+4);
+ d += 8; s += 8;
+ }
+ if (n&4) {
+ *(u32 *)(d+0) = *(u32 *)(s+0);
+ d += 4; s += 4;
+ }
+ if (n&2) {
+ *d++ = *s++; *d++ = *s++;
+ }
+ if (n&1) {
+ *d = *s;
+ }
+ return dest;
+ }
+
+ if (n >= 32) switch ((uintptr_t)d % 4) {
+ case 1:
+ w = *(u32 *)s;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ n -= 3;
+ for (; n>=17; s+=16, d+=16, n-=16) {
+ x = *(u32 *)(s+1);
+ *(u32 *)(d+0) = (w LS 24) | (x RS 8);
+ w = *(u32 *)(s+5);
+ *(u32 *)(d+4) = (x LS 24) | (w RS 8);
+ x = *(u32 *)(s+9);
+ *(u32 *)(d+8) = (w LS 24) | (x RS 8);
+ w = *(u32 *)(s+13);
+ *(u32 *)(d+12) = (x LS 24) | (w RS 8);
+ }
+ break;
+ case 2:
+ w = *(u32 *)s;
+ *d++ = *s++;
+ *d++ = *s++;
+ n -= 2;
+ for (; n>=18; s+=16, d+=16, n-=16) {
+ x = *(u32 *)(s+2);
+ *(u32 *)(d+0) = (w LS 16) | (x RS 16);
+ w = *(u32 *)(s+6);
+ *(u32 *)(d+4) = (x LS 16) | (w RS 16);
+ x = *(u32 *)(s+10);
+ *(u32 *)(d+8) = (w LS 16) | (x RS 16);
+ w = *(u32 *)(s+14);
+ *(u32 *)(d+12) = (x LS 16) | (w RS 16);
+ }
+ break;
+ case 3:
+ w = *(u32 *)s;
+ *d++ = *s++;
+ n -= 1;
+ for (; n>=19; s+=16, d+=16, n-=16) {
+ x = *(u32 *)(s+3);
+ *(u32 *)(d+0) = (w LS 8) | (x RS 24);
+ w = *(u32 *)(s+7);
+ *(u32 *)(d+4) = (x LS 8) | (w RS 24);
+ x = *(u32 *)(s+11);
+ *(u32 *)(d+8) = (w LS 8) | (x RS 24);
+ w = *(u32 *)(s+15);
+ *(u32 *)(d+12) = (x LS 8) | (w RS 24);
+ }
+ break;
+ }
+ if (n&16) {
+ *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+ *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+ *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+ *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+ }
+ if (n&8) {
+ *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+ *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+ }
+ if (n&4) {
+ *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+ }
+ if (n&2) {
+ *d++ = *s++; *d++ = *s++;
+ }
+ if (n&1) {
+ *d = *s;
+ }
+ return dest;
+#endif
+
+ for (; n; n--) *d++ = *s++;
+ return dest;
+}
diff --git a/libc-top-half/musl/src/string/memmem.c b/libc-top-half/musl/src/string/memmem.c
new file mode 100644
index 0000000..11eff86
--- /dev/null
+++ b/libc-top-half/musl/src/string/memmem.c
@@ -0,0 +1,149 @@
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdint.h>
+
+static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+ uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
+ for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++)
+ if (hw == nw) return (char *)h-2;
+ return hw == nw ? (char *)h-2 : 0;
+}
+
+static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
+ for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8)
+ if (hw == nw) return (char *)h-3;
+ return hw == nw ? (char *)h-3 : 0;
+}
+
+static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+ for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++)
+ if (hw == nw) return (char *)h-4;
+ return hw == nw ? (char *)h-4 : 0;
+}
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l)
+{
+ size_t i, ip, jp, k, p, ms, p0, mem, mem0;
+ size_t byteset[32 / sizeof(size_t)] = { 0 };
+ size_t shift[256];
+
+ /* Computing length of needle and fill shift table */
+ for (i=0; i<l; i++)
+ BITOP(byteset, n[i], |=), shift[n[i]] = i+1;
+
+ /* Compute maximal suffix */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] > n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ ms = ip;
+ p0 = p;
+
+ /* And with the opposite comparison */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] < n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ if (ip+1 > ms+1) ms = ip;
+ else p = p0;
+
+ /* Periodic needle? */
+ if (memcmp(n, n+p, ms+1)) {
+ mem0 = 0;
+ p = MAX(ms, l-ms-1) + 1;
+ } else mem0 = l-p;
+ mem = 0;
+
+ /* Search loop */
+ for (;;) {
+ /* If remainder of haystack is shorter than needle, done */
+ if (z-h < l) return 0;
+
+ /* Check last byte first; advance by shift on mismatch */
+ if (BITOP(byteset, h[l-1], &)) {
+ k = l-shift[h[l-1]];
+ if (k) {
+ if (k < mem) k = mem;
+ h += k;
+ mem = 0;
+ continue;
+ }
+ } else {
+ h += l;
+ mem = 0;
+ continue;
+ }
+
+ /* Compare right half */
+ for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++);
+ if (k < l) {
+ h += k-ms;
+ mem = 0;
+ continue;
+ }
+ /* Compare left half */
+ for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+ if (k <= mem) return (char *)h;
+ h += p;
+ mem = mem0;
+ }
+}
+
+void *memmem(const void *h0, size_t k, const void *n0, size_t l)
+{
+ const unsigned char *h = h0, *n = n0;
+
+ /* Return immediately on empty needle */
+ if (!l) return (void *)h;
+
+ /* Return immediately when needle is longer than haystack */
+ if (k<l) return 0;
+
+ /* Use faster algorithms for short needles */
+ h = memchr(h0, *n, k);
+ if (!h || l==1) return (void *)h;
+ k -= h - (const unsigned char *)h0;
+ if (k<l) return 0;
+ if (l==2) return twobyte_memmem(h, k, n);
+ if (l==3) return threebyte_memmem(h, k, n);
+ if (l==4) return fourbyte_memmem(h, k, n);
+
+ return twoway_memmem(h, h+k, n, l);
+}
diff --git a/libc-top-half/musl/src/string/memmove.c b/libc-top-half/musl/src/string/memmove.c
new file mode 100644
index 0000000..7376a52
--- /dev/null
+++ b/libc-top-half/musl/src/string/memmove.c
@@ -0,0 +1,46 @@
+#include <string.h>
+#include <stdint.h>
+
+#ifdef __GNUC__
+typedef __attribute__((__may_alias__)) size_t WT;
+#define WS (sizeof(WT))
+#endif
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+#if defined(__wasm_bulk_memory__)
+ if (n > BULK_MEMORY_THRESHOLD)
+ return __builtin_memmove(dest, src, n);
+#endif
+ char *d = dest;
+ const char *s = src;
+
+ if (d==s) return d;
+ if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n);
+
+ if (d<s) {
+#ifdef __GNUC__
+ if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
+ while ((uintptr_t)d % WS) {
+ if (!n--) return dest;
+ *d++ = *s++;
+ }
+ for (; n>=WS; n-=WS, d+=WS, s+=WS) *(WT *)d = *(WT *)s;
+ }
+#endif
+ for (; n; n--) *d++ = *s++;
+ } else {
+#ifdef __GNUC__
+ if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
+ while ((uintptr_t)(d+n) % WS) {
+ if (!n--) return dest;
+ d[n] = s[n];
+ }
+ while (n>=WS) n-=WS, *(WT *)(d+n) = *(WT *)(s+n);
+ }
+#endif
+ while (n) n--, d[n] = s[n];
+ }
+
+ return dest;
+}
diff --git a/libc-top-half/musl/src/string/mempcpy.c b/libc-top-half/musl/src/string/mempcpy.c
new file mode 100644
index 0000000..a297985
--- /dev/null
+++ b/libc-top-half/musl/src/string/mempcpy.c
@@ -0,0 +1,7 @@
+#define _GNU_SOURCE
+#include <string.h>
+
+void *mempcpy(void *dest, const void *src, size_t n)
+{
+ return (char *)memcpy(dest, src, n) + n;
+}
diff --git a/libc-top-half/musl/src/string/memrchr.c b/libc-top-half/musl/src/string/memrchr.c
new file mode 100644
index 0000000..e51748b
--- /dev/null
+++ b/libc-top-half/musl/src/string/memrchr.c
@@ -0,0 +1,11 @@
+#include <string.h>
+
+void *__memrchr(const void *m, int c, size_t n)
+{
+ const unsigned char *s = m;
+ c = (unsigned char)c;
+ while (n--) if (s[n]==c) return (void *)(s+n);
+ return 0;
+}
+
+weak_alias(__memrchr, memrchr);
diff --git a/libc-top-half/musl/src/string/memset.c b/libc-top-half/musl/src/string/memset.c
new file mode 100644
index 0000000..f64c9cf
--- /dev/null
+++ b/libc-top-half/musl/src/string/memset.c
@@ -0,0 +1,94 @@
+#include <string.h>
+#include <stdint.h>
+
+void *memset(void *dest, int c, size_t n)
+{
+#if defined(__wasm_bulk_memory__)
+ if (n > BULK_MEMORY_THRESHOLD)
+ return __builtin_memset(dest, c, n);
+#endif
+ unsigned char *s = dest;
+ size_t k;
+
+ /* Fill head and tail with minimal branching. Each
+ * conditional ensures that all the subsequently used
+ * offsets are well-defined and in the dest region. */
+
+ if (!n) return dest;
+ s[0] = c;
+ s[n-1] = c;
+ if (n <= 2) return dest;
+ s[1] = c;
+ s[2] = c;
+ s[n-2] = c;
+ s[n-3] = c;
+ if (n <= 6) return dest;
+ s[3] = c;
+ s[n-4] = c;
+ if (n <= 8) return dest;
+
+ /* Advance pointer to align it at a 4-byte boundary,
+ * and truncate n to a multiple of 4. The previous code
+ * already took care of any head/tail that get cut off
+ * by the alignment. */
+
+ k = -(uintptr_t)s & 3;
+ s += k;
+ n -= k;
+ n &= -4;
+
+#ifdef __GNUC__
+ typedef uint32_t __attribute__((__may_alias__)) u32;
+ typedef uint64_t __attribute__((__may_alias__)) u64;
+
+ u32 c32 = ((u32)-1)/255 * (unsigned char)c;
+
+ /* In preparation to copy 32 bytes at a time, aligned on
+ * an 8-byte bounary, fill head/tail up to 28 bytes each.
+ * As in the initial byte-based head/tail fill, each
+ * conditional below ensures that the subsequent offsets
+ * are valid (e.g. !(n<=24) implies n>=28). */
+
+ *(u32 *)(s+0) = c32;
+ *(u32 *)(s+n-4) = c32;
+ if (n <= 8) return dest;
+ *(u32 *)(s+4) = c32;
+ *(u32 *)(s+8) = c32;
+ *(u32 *)(s+n-12) = c32;
+ *(u32 *)(s+n-8) = c32;
+ if (n <= 24) return dest;
+ *(u32 *)(s+12) = c32;
+ *(u32 *)(s+16) = c32;
+ *(u32 *)(s+20) = c32;
+ *(u32 *)(s+24) = c32;
+ *(u32 *)(s+n-28) = c32;
+ *(u32 *)(s+n-24) = c32;
+ *(u32 *)(s+n-20) = c32;
+ *(u32 *)(s+n-16) = c32;
+
+ /* Align to a multiple of 8 so we can fill 64 bits at a time,
+ * and avoid writing the same bytes twice as much as is
+ * practical without introducing additional branching. */
+
+ k = 24 + ((uintptr_t)s & 4);
+ s += k;
+ n -= k;
+
+ /* If this loop is reached, 28 tail bytes have already been
+ * filled, so any remainder when n drops below 32 can be
+ * safely ignored. */
+
+ u64 c64 = c32 | ((u64)c32 << 32);
+ for (; n >= 32; n-=32, s+=32) {
+ *(u64 *)(s+0) = c64;
+ *(u64 *)(s+8) = c64;
+ *(u64 *)(s+16) = c64;
+ *(u64 *)(s+24) = c64;
+ }
+#else
+ /* Pure C fallback with no aliasing violations. */
+ for (; n; n--, s++) *s = c;
+#endif
+
+ return dest;
+}
diff --git a/libc-top-half/musl/src/string/rindex.c b/libc-top-half/musl/src/string/rindex.c
new file mode 100644
index 0000000..693c750
--- /dev/null
+++ b/libc-top-half/musl/src/string/rindex.c
@@ -0,0 +1,8 @@
+#define _BSD_SOURCE
+#include <string.h>
+#include <strings.h>
+
+char *rindex(const char *s, int c)
+{
+ return strrchr(s, c);
+}
diff --git a/libc-top-half/musl/src/string/stpcpy.c b/libc-top-half/musl/src/string/stpcpy.c
new file mode 100644
index 0000000..4db46a9
--- /dev/null
+++ b/libc-top-half/musl/src/string/stpcpy.c
@@ -0,0 +1,29 @@
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t))
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *__stpcpy(char *restrict d, const char *restrict s)
+{
+#ifdef __GNUC__
+ typedef size_t __attribute__((__may_alias__)) word;
+ word *wd;
+ const word *ws;
+ if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) {
+ for (; (uintptr_t)s % ALIGN; s++, d++)
+ if (!(*d=*s)) return d;
+ wd=(void *)d; ws=(const void *)s;
+ for (; !HASZERO(*ws); *wd++ = *ws++);
+ d=(void *)wd; s=(const void *)ws;
+ }
+#endif
+ for (; (*d=*s); s++, d++);
+
+ return d;
+}
+
+weak_alias(__stpcpy, stpcpy);
diff --git a/libc-top-half/musl/src/string/stpncpy.c b/libc-top-half/musl/src/string/stpncpy.c
new file mode 100644
index 0000000..f57fa6b
--- /dev/null
+++ b/libc-top-half/musl/src/string/stpncpy.c
@@ -0,0 +1,32 @@
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *__stpncpy(char *restrict d, const char *restrict s, size_t n)
+{
+#ifdef __GNUC__
+ typedef size_t __attribute__((__may_alias__)) word;
+ word *wd;
+ const word *ws;
+ if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
+ for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
+ if (!n || !*s) goto tail;
+ wd=(void *)d; ws=(const void *)s;
+ for (; n>=sizeof(size_t) && !HASZERO(*ws);
+ n-=sizeof(size_t), ws++, wd++) *wd = *ws;
+ d=(void *)wd; s=(const void *)ws;
+ }
+#endif
+ for (; n && (*d=*s); n--, s++, d++);
+tail:
+ memset(d, 0, n);
+ return d;
+}
+
+weak_alias(__stpncpy, stpncpy);
+
diff --git a/libc-top-half/musl/src/string/strcasecmp.c b/libc-top-half/musl/src/string/strcasecmp.c
new file mode 100644
index 0000000..002c6aa
--- /dev/null
+++ b/libc-top-half/musl/src/string/strcasecmp.c
@@ -0,0 +1,16 @@
+#include <strings.h>
+#include <ctype.h>
+
+int strcasecmp(const char *_l, const char *_r)
+{
+ const unsigned char *l=(void *)_l, *r=(void *)_r;
+ for (; *l && *r && (*l == *r || tolower(*l) == tolower(*r)); l++, r++);
+ return tolower(*l) - tolower(*r);
+}
+
+int __strcasecmp_l(const char *l, const char *r, locale_t loc)
+{
+ return strcasecmp(l, r);
+}
+
+weak_alias(__strcasecmp_l, strcasecmp_l);
diff --git a/libc-top-half/musl/src/string/strcasestr.c b/libc-top-half/musl/src/string/strcasestr.c
new file mode 100644
index 0000000..af109f3
--- /dev/null
+++ b/libc-top-half/musl/src/string/strcasestr.c
@@ -0,0 +1,9 @@
+#define _GNU_SOURCE
+#include <string.h>
+
+char *strcasestr(const char *h, const char *n)
+{
+ size_t l = strlen(n);
+ for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h;
+ return 0;
+}
diff --git a/libc-top-half/musl/src/string/strcat.c b/libc-top-half/musl/src/string/strcat.c
new file mode 100644
index 0000000..33f749b
--- /dev/null
+++ b/libc-top-half/musl/src/string/strcat.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strcat(char *restrict dest, const char *restrict src)
+{
+ strcpy(dest + strlen(dest), src);
+ return dest;
+}
diff --git a/libc-top-half/musl/src/string/strchr.c b/libc-top-half/musl/src/string/strchr.c
new file mode 100644
index 0000000..3cbc828
--- /dev/null
+++ b/libc-top-half/musl/src/string/strchr.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strchr(const char *s, int c)
+{
+ char *r = __strchrnul(s, c);
+ return *(unsigned char *)r == (unsigned char)c ? r : 0;
+}
diff --git a/libc-top-half/musl/src/string/strchrnul.c b/libc-top-half/musl/src/string/strchrnul.c
new file mode 100644
index 0000000..39e2635
--- /dev/null
+++ b/libc-top-half/musl/src/string/strchrnul.c
@@ -0,0 +1,28 @@
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t))
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *__strchrnul(const char *s, int c)
+{
+ c = (unsigned char)c;
+ if (!c) return (char *)s + strlen(s);
+
+#ifdef __GNUC__
+ typedef size_t __attribute__((__may_alias__)) word;
+ const word *w;
+ for (; (uintptr_t)s % ALIGN; s++)
+ if (!*s || *(unsigned char *)s == c) return (char *)s;
+ size_t k = ONES * c;
+ for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
+ s = (void *)w;
+#endif
+ for (; *s && *(unsigned char *)s != c; s++);
+ return (char *)s;
+}
+
+weak_alias(__strchrnul, strchrnul);
diff --git a/libc-top-half/musl/src/string/strcmp.c b/libc-top-half/musl/src/string/strcmp.c
new file mode 100644
index 0000000..808bd83
--- /dev/null
+++ b/libc-top-half/musl/src/string/strcmp.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+int strcmp(const char *l, const char *r)
+{
+ for (; *l==*r && *l; l++, r++);
+ return *(unsigned char *)l - *(unsigned char *)r;
+}
diff --git a/libc-top-half/musl/src/string/strcpy.c b/libc-top-half/musl/src/string/strcpy.c
new file mode 100644
index 0000000..6668a12
--- /dev/null
+++ b/libc-top-half/musl/src/string/strcpy.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strcpy(char *restrict dest, const char *restrict src)
+{
+ __stpcpy(dest, src);
+ return dest;
+}
diff --git a/libc-top-half/musl/src/string/strcspn.c b/libc-top-half/musl/src/string/strcspn.c
new file mode 100644
index 0000000..a0c617b
--- /dev/null
+++ b/libc-top-half/musl/src/string/strcspn.c
@@ -0,0 +1,17 @@
+#include <string.h>
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+size_t strcspn(const char *s, const char *c)
+{
+ const char *a = s;
+ size_t byteset[32/sizeof(size_t)];
+
+ if (!c[0] || !c[1]) return __strchrnul(s, *c)-a;
+
+ memset(byteset, 0, sizeof byteset);
+ for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
+ for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++);
+ return s-a;
+}
diff --git a/libc-top-half/musl/src/string/strdup.c b/libc-top-half/musl/src/string/strdup.c
new file mode 100644
index 0000000..d4c2744
--- /dev/null
+++ b/libc-top-half/musl/src/string/strdup.c
@@ -0,0 +1,10 @@
+#include <stdlib.h>
+#include <string.h>
+
+char *strdup(const char *s)
+{
+ size_t l = strlen(s);
+ char *d = malloc(l+1);
+ if (!d) return NULL;
+ return memcpy(d, s, l+1);
+}
diff --git a/libc-top-half/musl/src/string/strerror_r.c b/libc-top-half/musl/src/string/strerror_r.c
new file mode 100644
index 0000000..1dc88bb
--- /dev/null
+++ b/libc-top-half/musl/src/string/strerror_r.c
@@ -0,0 +1,19 @@
+#include <string.h>
+#include <errno.h>
+
+int strerror_r(int err, char *buf, size_t buflen)
+{
+ char *msg = strerror(err);
+ size_t l = strlen(msg);
+ if (l >= buflen) {
+ if (buflen) {
+ memcpy(buf, msg, buflen-1);
+ buf[buflen-1] = 0;
+ }
+ return ERANGE;
+ }
+ memcpy(buf, msg, l+1);
+ return 0;
+}
+
+weak_alias(strerror_r, __xpg_strerror_r);
diff --git a/libc-top-half/musl/src/string/strlcat.c b/libc-top-half/musl/src/string/strlcat.c
new file mode 100644
index 0000000..ef81209
--- /dev/null
+++ b/libc-top-half/musl/src/string/strlcat.c
@@ -0,0 +1,9 @@
+#define _BSD_SOURCE
+#include <string.h>
+
+size_t strlcat(char *d, const char *s, size_t n)
+{
+ size_t l = strnlen(d, n);
+ if (l == n) return l + strlen(s);
+ return l + strlcpy(d+l, s, n-l);
+}
diff --git a/libc-top-half/musl/src/string/strlcpy.c b/libc-top-half/musl/src/string/strlcpy.c
new file mode 100644
index 0000000..ffa0b0b
--- /dev/null
+++ b/libc-top-half/musl/src/string/strlcpy.c
@@ -0,0 +1,34 @@
+#define _BSD_SOURCE
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+size_t strlcpy(char *d, const char *s, size_t n)
+{
+ char *d0 = d;
+ size_t *wd;
+
+ if (!n--) goto finish;
+#ifdef __GNUC__
+ typedef size_t __attribute__((__may_alias__)) word;
+ const word *ws;
+ if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
+ for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
+ if (n && *s) {
+ wd=(void *)d; ws=(const void *)s;
+ for (; n>=sizeof(size_t) && !HASZERO(*ws);
+ n-=sizeof(size_t), ws++, wd++) *wd = *ws;
+ d=(void *)wd; s=(const void *)ws;
+ }
+ }
+#endif
+ for (; n && (*d=*s); n--, s++, d++);
+ *d = 0;
+finish:
+ return d-d0 + strlen(s);
+}
diff --git a/libc-top-half/musl/src/string/strlen.c b/libc-top-half/musl/src/string/strlen.c
new file mode 100644
index 0000000..309990f
--- /dev/null
+++ b/libc-top-half/musl/src/string/strlen.c
@@ -0,0 +1,22 @@
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t))
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+size_t strlen(const char *s)
+{
+ const char *a = s;
+#ifdef __GNUC__
+ typedef size_t __attribute__((__may_alias__)) word;
+ const word *w;
+ for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a;
+ for (w = (const void *)s; !HASZERO(*w); w++);
+ s = (const void *)w;
+#endif
+ for (; *s; s++);
+ return s-a;
+}
diff --git a/libc-top-half/musl/src/string/strncasecmp.c b/libc-top-half/musl/src/string/strncasecmp.c
new file mode 100644
index 0000000..e0ef93c
--- /dev/null
+++ b/libc-top-half/musl/src/string/strncasecmp.c
@@ -0,0 +1,17 @@
+#include <strings.h>
+#include <ctype.h>
+
+int strncasecmp(const char *_l, const char *_r, size_t n)
+{
+ const unsigned char *l=(void *)_l, *r=(void *)_r;
+ if (!n--) return 0;
+ for (; *l && *r && n && (*l == *r || tolower(*l) == tolower(*r)); l++, r++, n--);
+ return tolower(*l) - tolower(*r);
+}
+
+int __strncasecmp_l(const char *l, const char *r, size_t n, locale_t loc)
+{
+ return strncasecmp(l, r, n);
+}
+
+weak_alias(__strncasecmp_l, strncasecmp_l);
diff --git a/libc-top-half/musl/src/string/strncat.c b/libc-top-half/musl/src/string/strncat.c
new file mode 100644
index 0000000..01ca2a2
--- /dev/null
+++ b/libc-top-half/musl/src/string/strncat.c
@@ -0,0 +1,10 @@
+#include <string.h>
+
+char *strncat(char *restrict d, const char *restrict s, size_t n)
+{
+ char *a = d;
+ d += strlen(d);
+ while (n && *s) n--, *d++ = *s++;
+ *d++ = 0;
+ return a;
+}
diff --git a/libc-top-half/musl/src/string/strncmp.c b/libc-top-half/musl/src/string/strncmp.c
new file mode 100644
index 0000000..e228843
--- /dev/null
+++ b/libc-top-half/musl/src/string/strncmp.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+int strncmp(const char *_l, const char *_r, size_t n)
+{
+ const unsigned char *l=(void *)_l, *r=(void *)_r;
+ if (!n--) return 0;
+ for (; *l && *r && n && *l == *r ; l++, r++, n--);
+ return *l - *r;
+}
diff --git a/libc-top-half/musl/src/string/strncpy.c b/libc-top-half/musl/src/string/strncpy.c
new file mode 100644
index 0000000..545892e
--- /dev/null
+++ b/libc-top-half/musl/src/string/strncpy.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strncpy(char *restrict d, const char *restrict s, size_t n)
+{
+ __stpncpy(d, s, n);
+ return d;
+}
diff --git a/libc-top-half/musl/src/string/strndup.c b/libc-top-half/musl/src/string/strndup.c
new file mode 100644
index 0000000..617d27b
--- /dev/null
+++ b/libc-top-half/musl/src/string/strndup.c
@@ -0,0 +1,12 @@
+#include <stdlib.h>
+#include <string.h>
+
+char *strndup(const char *s, size_t n)
+{
+ size_t l = strnlen(s, n);
+ char *d = malloc(l+1);
+ if (!d) return NULL;
+ memcpy(d, s, l);
+ d[l] = 0;
+ return d;
+}
diff --git a/libc-top-half/musl/src/string/strnlen.c b/libc-top-half/musl/src/string/strnlen.c
new file mode 100644
index 0000000..6442eb7
--- /dev/null
+++ b/libc-top-half/musl/src/string/strnlen.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+size_t strnlen(const char *s, size_t n)
+{
+ const char *p = memchr(s, 0, n);
+ return p ? p-s : n;
+}
diff --git a/libc-top-half/musl/src/string/strpbrk.c b/libc-top-half/musl/src/string/strpbrk.c
new file mode 100644
index 0000000..55947c6
--- /dev/null
+++ b/libc-top-half/musl/src/string/strpbrk.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strpbrk(const char *s, const char *b)
+{
+ s += strcspn(s, b);
+ return *s ? (char *)s : 0;
+}
diff --git a/libc-top-half/musl/src/string/strrchr.c b/libc-top-half/musl/src/string/strrchr.c
new file mode 100644
index 0000000..98ad1b0
--- /dev/null
+++ b/libc-top-half/musl/src/string/strrchr.c
@@ -0,0 +1,6 @@
+#include <string.h>
+
+char *strrchr(const char *s, int c)
+{
+ return __memrchr(s, c, strlen(s) + 1);
+}
diff --git a/libc-top-half/musl/src/string/strsep.c b/libc-top-half/musl/src/string/strsep.c
new file mode 100644
index 0000000..cb37c32
--- /dev/null
+++ b/libc-top-half/musl/src/string/strsep.c
@@ -0,0 +1,13 @@
+#define _GNU_SOURCE
+#include <string.h>
+
+char *strsep(char **str, const char *sep)
+{
+ char *s = *str, *end;
+ if (!s) return NULL;
+ end = s + strcspn(s, sep);
+ if (*end) *end++ = 0;
+ else end = 0;
+ *str = end;
+ return s;
+}
diff --git a/libc-top-half/musl/src/string/strsignal.c b/libc-top-half/musl/src/string/strsignal.c
new file mode 100644
index 0000000..5156366
--- /dev/null
+++ b/libc-top-half/musl/src/string/strsignal.c
@@ -0,0 +1,126 @@
+#include <signal.h>
+#include <string.h>
+#include "locale_impl.h"
+
+#if (SIGHUP == 1) && (SIGINT == 2) && (SIGQUIT == 3) && (SIGILL == 4) \
+ && (SIGTRAP == 5) && (SIGABRT == 6) && (SIGBUS == 7) && (SIGFPE == 8) \
+ && (SIGKILL == 9) && (SIGUSR1 == 10) && (SIGSEGV == 11) && (SIGUSR2 == 12) \
+ && (SIGPIPE == 13) && (SIGALRM == 14) && (SIGTERM == 15) && (SIGSTKFLT == 16) \
+ && (SIGCHLD == 17) && (SIGCONT == 18) && (SIGSTOP == 19) && (SIGTSTP == 20) \
+ && (SIGTTIN == 21) && (SIGTTOU == 22) && (SIGURG == 23) && (SIGXCPU == 24) \
+ && (SIGXFSZ == 25) && (SIGVTALRM == 26) && (SIGPROF == 27) && (SIGWINCH == 28) \
+ && (SIGPOLL == 29) && (SIGPWR == 30) && (SIGSYS == 31)
+
+#define sigmap(x) x
+
+#else
+
+static const char map[] = {
+ [SIGHUP] = 1,
+ [SIGINT] = 2,
+ [SIGQUIT] = 3,
+ [SIGILL] = 4,
+ [SIGTRAP] = 5,
+ [SIGABRT] = 6,
+ [SIGBUS] = 7,
+ [SIGFPE] = 8,
+ [SIGKILL] = 9,
+ [SIGUSR1] = 10,
+ [SIGSEGV] = 11,
+ [SIGUSR2] = 12,
+ [SIGPIPE] = 13,
+ [SIGALRM] = 14,
+ [SIGTERM] = 15,
+#if defined(SIGSTKFLT)
+ [SIGSTKFLT] = 16,
+#elif defined(SIGEMT)
+ [SIGEMT] = 16,
+#endif
+ [SIGCHLD] = 17,
+ [SIGCONT] = 18,
+ [SIGSTOP] = 19,
+ [SIGTSTP] = 20,
+ [SIGTTIN] = 21,
+ [SIGTTOU] = 22,
+ [SIGURG] = 23,
+ [SIGXCPU] = 24,
+ [SIGXFSZ] = 25,
+ [SIGVTALRM] = 26,
+ [SIGPROF] = 27,
+ [SIGWINCH] = 28,
+ [SIGPOLL] = 29,
+ [SIGPWR] = 30,
+ [SIGSYS] = 31
+};
+
+#define sigmap(x) ((x) >= sizeof map ? (x) : map[(x)])
+
+#endif
+
+static const char strings[] =
+ "Unknown signal\0"
+ "Hangup\0"
+ "Interrupt\0"
+ "Quit\0"
+ "Illegal instruction\0"
+ "Trace/breakpoint trap\0"
+ "Aborted\0"
+ "Bus error\0"
+ "Arithmetic exception\0"
+ "Killed\0"
+ "User defined signal 1\0"
+ "Segmentation fault\0"
+ "User defined signal 2\0"
+ "Broken pipe\0"
+ "Alarm clock\0"
+ "Terminated\0"
+#if defined(SIGSTKFLT)
+ "Stack fault\0"
+#elif defined(SIGEMT)
+ "Emulator trap\0"
+#else
+ "Unknown signal\0"
+#endif
+ "Child process status\0"
+ "Continued\0"
+ "Stopped (signal)\0"
+ "Stopped\0"
+ "Stopped (tty input)\0"
+ "Stopped (tty output)\0"
+ "Urgent I/O condition\0"
+ "CPU time limit exceeded\0"
+ "File size limit exceeded\0"
+ "Virtual timer expired\0"
+ "Profiling timer expired\0"
+ "Window changed\0"
+ "I/O possible\0"
+ "Power failure\0"
+ "Bad system call\0"
+ "RT32"
+ "\0RT33\0RT34\0RT35\0RT36\0RT37\0RT38\0RT39\0RT40"
+ "\0RT41\0RT42\0RT43\0RT44\0RT45\0RT46\0RT47\0RT48"
+ "\0RT49\0RT50\0RT51\0RT52\0RT53\0RT54\0RT55\0RT56"
+ "\0RT57\0RT58\0RT59\0RT60\0RT61\0RT62\0RT63\0RT64"
+#if _NSIG > 65
+ "\0RT65\0RT66\0RT67\0RT68\0RT69\0RT70\0RT71\0RT72"
+ "\0RT73\0RT74\0RT75\0RT76\0RT77\0RT78\0RT79\0RT80"
+ "\0RT81\0RT82\0RT83\0RT84\0RT85\0RT86\0RT87\0RT88"
+ "\0RT89\0RT90\0RT91\0RT92\0RT93\0RT94\0RT95\0RT96"
+ "\0RT97\0RT98\0RT99\0RT100\0RT101\0RT102\0RT103\0RT104"
+ "\0RT105\0RT106\0RT107\0RT108\0RT109\0RT110\0RT111\0RT112"
+ "\0RT113\0RT114\0RT115\0RT116\0RT117\0RT118\0RT119\0RT120"
+ "\0RT121\0RT122\0RT123\0RT124\0RT125\0RT126\0RT127\0RT128"
+#endif
+ "";
+
+char *strsignal(int signum)
+{
+ const char *s = strings;
+
+ signum = sigmap(signum);
+ if (signum - 1U >= _NSIG-1) signum = 0;
+
+ for (; signum--; s++) for (; *s; s++);
+
+ return (char *)LCTRANS_CUR(s);
+}
diff --git a/libc-top-half/musl/src/string/strspn.c b/libc-top-half/musl/src/string/strspn.c
new file mode 100644
index 0000000..9543dad
--- /dev/null
+++ b/libc-top-half/musl/src/string/strspn.c
@@ -0,0 +1,20 @@
+#include <string.h>
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+size_t strspn(const char *s, const char *c)
+{
+ const char *a = s;
+ size_t byteset[32/sizeof(size_t)] = { 0 };
+
+ if (!c[0]) return 0;
+ if (!c[1]) {
+ for (; *s == *c; s++);
+ return s-a;
+ }
+
+ for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
+ for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++);
+ return s-a;
+}
diff --git a/libc-top-half/musl/src/string/strstr.c b/libc-top-half/musl/src/string/strstr.c
new file mode 100644
index 0000000..96657bc
--- /dev/null
+++ b/libc-top-half/musl/src/string/strstr.c
@@ -0,0 +1,154 @@
+#include <string.h>
+#include <stdint.h>
+
+static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+ uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
+ for (h++; *h && hw != nw; hw = hw<<8 | *++h);
+ return *h ? (char *)h-1 : 0;
+}
+
+static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
+ for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
+ return *h ? (char *)h-2 : 0;
+}
+
+static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+ for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
+ return *h ? (char *)h-3 : 0;
+}
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
+{
+ const unsigned char *z;
+ size_t l, ip, jp, k, p, ms, p0, mem, mem0;
+ size_t byteset[32 / sizeof(size_t)] = { 0 };
+ size_t shift[256];
+
+ /* Computing length of needle and fill shift table */
+ for (l=0; n[l] && h[l]; l++)
+ BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
+ if (n[l]) return 0; /* hit the end of h */
+
+ /* Compute maximal suffix */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] > n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ ms = ip;
+ p0 = p;
+
+ /* And with the opposite comparison */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] < n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ if (ip+1 > ms+1) ms = ip;
+ else p = p0;
+
+ /* Periodic needle? */
+ if (memcmp(n, n+p, ms+1)) {
+ mem0 = 0;
+ p = MAX(ms, l-ms-1) + 1;
+ } else mem0 = l-p;
+ mem = 0;
+
+ /* Initialize incremental end-of-haystack pointer */
+ z = h;
+
+ /* Search loop */
+ for (;;) {
+ /* Update incremental end-of-haystack pointer */
+ if (z-h < l) {
+ /* Fast estimate for MAX(l,63) */
+ size_t grow = l | 63;
+ const unsigned char *z2 = memchr(z, 0, grow);
+ if (z2) {
+ z = z2;
+ if (z-h < l) return 0;
+ } else z += grow;
+ }
+
+ /* Check last byte first; advance by shift on mismatch */
+ if (BITOP(byteset, h[l-1], &)) {
+ k = l-shift[h[l-1]];
+ if (k) {
+ if (k < mem) k = mem;
+ h += k;
+ mem = 0;
+ continue;
+ }
+ } else {
+ h += l;
+ mem = 0;
+ continue;
+ }
+
+ /* Compare right half */
+ for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
+ if (n[k]) {
+ h += k-ms;
+ mem = 0;
+ continue;
+ }
+ /* Compare left half */
+ for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+ if (k <= mem) return (char *)h;
+ h += p;
+ mem = mem0;
+ }
+}
+
+char *strstr(const char *h, const char *n)
+{
+ /* Return immediately on empty needle */
+ if (!n[0]) return (char *)h;
+
+ /* Use faster algorithms for short needles */
+ h = strchr(h, *n);
+ if (!h || !n[1]) return (char *)h;
+ if (!h[1]) return 0;
+ if (!n[2]) return twobyte_strstr((void *)h, (void *)n);
+ if (!h[2]) return 0;
+ if (!n[3]) return threebyte_strstr((void *)h, (void *)n);
+ if (!h[3]) return 0;
+ if (!n[4]) return fourbyte_strstr((void *)h, (void *)n);
+
+ return twoway_strstr((void *)h, (void *)n);
+}
diff --git a/libc-top-half/musl/src/string/strtok.c b/libc-top-half/musl/src/string/strtok.c
new file mode 100644
index 0000000..3508790
--- /dev/null
+++ b/libc-top-half/musl/src/string/strtok.c
@@ -0,0 +1,13 @@
+#include <string.h>
+
+char *strtok(char *restrict s, const char *restrict sep)
+{
+ static char *p;
+ if (!s && !(s = p)) return NULL;
+ s += strspn(s, sep);
+ if (!*s) return p = 0;
+ p = s + strcspn(s, sep);
+ if (*p) *p++ = 0;
+ else p = 0;
+ return s;
+}
diff --git a/libc-top-half/musl/src/string/strtok_r.c b/libc-top-half/musl/src/string/strtok_r.c
new file mode 100644
index 0000000..862d4fe
--- /dev/null
+++ b/libc-top-half/musl/src/string/strtok_r.c
@@ -0,0 +1,12 @@
+#include <string.h>
+
+char *strtok_r(char *restrict s, const char *restrict sep, char **restrict p)
+{
+ if (!s && !(s = *p)) return NULL;
+ s += strspn(s, sep);
+ if (!*s) return *p = 0;
+ *p = s + strcspn(s, sep);
+ if (**p) *(*p)++ = 0;
+ else *p = 0;
+ return s;
+}
diff --git a/libc-top-half/musl/src/string/strverscmp.c b/libc-top-half/musl/src/string/strverscmp.c
new file mode 100644
index 0000000..4daf276
--- /dev/null
+++ b/libc-top-half/musl/src/string/strverscmp.c
@@ -0,0 +1,34 @@
+#define _GNU_SOURCE
+#include <ctype.h>
+#include <string.h>
+
+int strverscmp(const char *l0, const char *r0)
+{
+ const unsigned char *l = (const void *)l0;
+ const unsigned char *r = (const void *)r0;
+ size_t i, dp, j;
+ int z = 1;
+
+ /* Find maximal matching prefix and track its maximal digit
+ * suffix and whether those digits are all zeros. */
+ for (dp=i=0; l[i]==r[i]; i++) {
+ int c = l[i];
+ if (!c) return 0;
+ if (!isdigit(c)) dp=i+1, z=1;
+ else if (c!='0') z=0;
+ }
+
+ if (l[dp]!='0' && r[dp]!='0') {
+ /* If we're not looking at a digit sequence that began
+ * with a zero, longest digit string is greater. */
+ for (j=i; isdigit(l[j]); j++)
+ if (!isdigit(r[j])) return 1;
+ if (isdigit(r[j])) return -1;
+ } else if (z && dp<i && (isdigit(l[i]) || isdigit(r[i]))) {
+ /* Otherwise, if common prefix of digit sequence is
+ * all zeros, digits order less than non-digits. */
+ return (unsigned char)(l[i]-'0') - (unsigned char)(r[i]-'0');
+ }
+
+ return l[i] - r[i];
+}
diff --git a/libc-top-half/musl/src/string/swab.c b/libc-top-half/musl/src/string/swab.c
new file mode 100644
index 0000000..ace0f46
--- /dev/null
+++ b/libc-top-half/musl/src/string/swab.c
@@ -0,0 +1,13 @@
+#include <unistd.h>
+
+void swab(const void *restrict _src, void *restrict _dest, ssize_t n)
+{
+ const char *src = _src;
+ char *dest = _dest;
+ for (; n>1; n-=2) {
+ dest[0] = src[1];
+ dest[1] = src[0];
+ dest += 2;
+ src += 2;
+ }
+}
diff --git a/libc-top-half/musl/src/string/wcpcpy.c b/libc-top-half/musl/src/string/wcpcpy.c
new file mode 100644
index 0000000..ef40134
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcpcpy.c
@@ -0,0 +1,6 @@
+#include <wchar.h>
+
+wchar_t *wcpcpy(wchar_t *restrict d, const wchar_t *restrict s)
+{
+ return wcscpy(d, s) + wcslen(s);
+}
diff --git a/libc-top-half/musl/src/string/wcpncpy.c b/libc-top-half/musl/src/string/wcpncpy.c
new file mode 100644
index 0000000..b667f6d
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcpncpy.c
@@ -0,0 +1,6 @@
+#include <wchar.h>
+
+wchar_t *wcpncpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
+{
+ return wcsncpy(d, s, n) + wcsnlen(s, n);
+}
diff --git a/libc-top-half/musl/src/string/wcscasecmp.c b/libc-top-half/musl/src/string/wcscasecmp.c
new file mode 100644
index 0000000..3edeec7
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcscasecmp.c
@@ -0,0 +1,7 @@
+#include <wchar.h>
+#include <wctype.h>
+
+int wcscasecmp(const wchar_t *l, const wchar_t *r)
+{
+ return wcsncasecmp(l, r, -1);
+}
diff --git a/libc-top-half/musl/src/string/wcscasecmp_l.c b/libc-top-half/musl/src/string/wcscasecmp_l.c
new file mode 100644
index 0000000..065dd0a
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcscasecmp_l.c
@@ -0,0 +1,6 @@
+#include <wchar.h>
+
+int wcscasecmp_l(const wchar_t *l, const wchar_t *r, locale_t locale)
+{
+ return wcscasecmp(l, r);
+}
diff --git a/libc-top-half/musl/src/string/wcscat.c b/libc-top-half/musl/src/string/wcscat.c
new file mode 100644
index 0000000..d4f00eb
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcscat.c
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+wchar_t *wcscat(wchar_t *restrict dest, const wchar_t *restrict src)
+{
+ wcscpy(dest + wcslen(dest), src);
+ return dest;
+}
diff --git a/libc-top-half/musl/src/string/wcschr.c b/libc-top-half/musl/src/string/wcschr.c
new file mode 100644
index 0000000..8dfc2f3
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcschr.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+wchar_t *wcschr(const wchar_t *s, wchar_t c)
+{
+ if (!c) return (wchar_t *)s + wcslen(s);
+ for (; *s && *s != c; s++);
+ return *s ? (wchar_t *)s : 0;
+}
diff --git a/libc-top-half/musl/src/string/wcscmp.c b/libc-top-half/musl/src/string/wcscmp.c
new file mode 100644
index 0000000..26eeee7
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcscmp.c
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+int wcscmp(const wchar_t *l, const wchar_t *r)
+{
+ for (; *l==*r && *l && *r; l++, r++);
+ return *l - *r;
+}
diff --git a/libc-top-half/musl/src/string/wcscpy.c b/libc-top-half/musl/src/string/wcscpy.c
new file mode 100644
index 0000000..625bf53
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcscpy.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+wchar_t *wcscpy(wchar_t *restrict d, const wchar_t *restrict s)
+{
+ wchar_t *a = d;
+ while ((*d++ = *s++));
+ return a;
+}
diff --git a/libc-top-half/musl/src/string/wcscspn.c b/libc-top-half/musl/src/string/wcscspn.c
new file mode 100644
index 0000000..c4e5272
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcscspn.c
@@ -0,0 +1,10 @@
+#include <wchar.h>
+
+size_t wcscspn(const wchar_t *s, const wchar_t *c)
+{
+ const wchar_t *a;
+ if (!c[0]) return wcslen(s);
+ if (!c[1]) return (s=wcschr(a=s, *c)) ? s-a : wcslen(a);
+ for (a=s; *s && !wcschr(c, *s); s++);
+ return s-a;
+}
diff --git a/libc-top-half/musl/src/string/wcsdup.c b/libc-top-half/musl/src/string/wcsdup.c
new file mode 100644
index 0000000..f398e80
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsdup.c
@@ -0,0 +1,10 @@
+#include <stdlib.h>
+#include <wchar.h>
+
+wchar_t *wcsdup(const wchar_t *s)
+{
+ size_t l = wcslen(s);
+ wchar_t *d = malloc((l+1)*sizeof(wchar_t));
+ if (!d) return NULL;
+ return wmemcpy(d, s, l+1);
+}
diff --git a/libc-top-half/musl/src/string/wcslen.c b/libc-top-half/musl/src/string/wcslen.c
new file mode 100644
index 0000000..1b7b665
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcslen.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+size_t wcslen(const wchar_t *s)
+{
+ const wchar_t *a;
+ for (a=s; *s; s++);
+ return s-a;
+}
diff --git a/libc-top-half/musl/src/string/wcsncasecmp.c b/libc-top-half/musl/src/string/wcsncasecmp.c
new file mode 100644
index 0000000..8fefe79
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsncasecmp.c
@@ -0,0 +1,9 @@
+#include <wchar.h>
+#include <wctype.h>
+
+int wcsncasecmp(const wchar_t *l, const wchar_t *r, size_t n)
+{
+ if (!n--) return 0;
+ for (; *l && *r && n && (*l == *r || towlower(*l) == towlower(*r)); l++, r++, n--);
+ return towlower(*l) - towlower(*r);
+}
diff --git a/libc-top-half/musl/src/string/wcsncasecmp_l.c b/libc-top-half/musl/src/string/wcsncasecmp_l.c
new file mode 100644
index 0000000..6387248
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsncasecmp_l.c
@@ -0,0 +1,6 @@
+#include <wchar.h>
+
+int wcsncasecmp_l(const wchar_t *l, const wchar_t *r, size_t n, locale_t locale)
+{
+ return wcsncasecmp(l, r, n);
+}
diff --git a/libc-top-half/musl/src/string/wcsncat.c b/libc-top-half/musl/src/string/wcsncat.c
new file mode 100644
index 0000000..8563f1a
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsncat.c
@@ -0,0 +1,10 @@
+#include <wchar.h>
+
+wchar_t *wcsncat(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
+{
+ wchar_t *a = d;
+ d += wcslen(d);
+ while (n && *s) n--, *d++ = *s++;
+ *d++ = 0;
+ return a;
+}
diff --git a/libc-top-half/musl/src/string/wcsncmp.c b/libc-top-half/musl/src/string/wcsncmp.c
new file mode 100644
index 0000000..4ab32a9
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsncmp.c
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+int wcsncmp(const wchar_t *l, const wchar_t *r, size_t n)
+{
+ for (; n && *l==*r && *l && *r; n--, l++, r++);
+ return n ? *l - *r : 0;
+}
diff --git a/libc-top-half/musl/src/string/wcsncpy.c b/libc-top-half/musl/src/string/wcsncpy.c
new file mode 100644
index 0000000..4bede04
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsncpy.c
@@ -0,0 +1,9 @@
+#include <wchar.h>
+
+wchar_t *wcsncpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
+{
+ wchar_t *a = d;
+ while (n && *s) n--, *d++ = *s++;
+ wmemset(d, 0, n);
+ return a;
+}
diff --git a/libc-top-half/musl/src/string/wcsnlen.c b/libc-top-half/musl/src/string/wcsnlen.c
new file mode 100644
index 0000000..a776337
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsnlen.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+size_t wcsnlen(const wchar_t *s, size_t n)
+{
+ const wchar_t *z = wmemchr(s, 0, n);
+ if (z) n = z-s;
+ return n;
+}
diff --git a/libc-top-half/musl/src/string/wcspbrk.c b/libc-top-half/musl/src/string/wcspbrk.c
new file mode 100644
index 0000000..0c72c19
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcspbrk.c
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+wchar_t *wcspbrk(const wchar_t *s, const wchar_t *b)
+{
+ s += wcscspn(s, b);
+ return *s ? (wchar_t *)s : NULL;
+}
diff --git a/libc-top-half/musl/src/string/wcsrchr.c b/libc-top-half/musl/src/string/wcsrchr.c
new file mode 100644
index 0000000..8961b9e
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsrchr.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+wchar_t *wcsrchr(const wchar_t *s, wchar_t c)
+{
+ const wchar_t *p;
+ for (p=s+wcslen(s); p>=s && *p!=c; p--);
+ return p>=s ? (wchar_t *)p : 0;
+}
diff --git a/libc-top-half/musl/src/string/wcsspn.c b/libc-top-half/musl/src/string/wcsspn.c
new file mode 100644
index 0000000..4320d8f
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsspn.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+size_t wcsspn(const wchar_t *s, const wchar_t *c)
+{
+ const wchar_t *a;
+ for (a=s; *s && wcschr(c, *s); s++);
+ return s-a;
+}
diff --git a/libc-top-half/musl/src/string/wcsstr.c b/libc-top-half/musl/src/string/wcsstr.c
new file mode 100644
index 0000000..4caaef3
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcsstr.c
@@ -0,0 +1,105 @@
+#include <wchar.h>
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n)
+{
+ const wchar_t *z;
+ size_t l, ip, jp, k, p, ms, p0, mem, mem0;
+
+ /* Computing length of needle */
+ for (l=0; n[l] && h[l]; l++);
+ if (n[l]) return 0; /* hit the end of h */
+
+ /* Compute maximal suffix */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] > n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ ms = ip;
+ p0 = p;
+
+ /* And with the opposite comparison */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] < n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ if (ip+1 > ms+1) ms = ip;
+ else p = p0;
+
+ /* Periodic needle? */
+ if (wmemcmp(n, n+p, ms+1)) {
+ mem0 = 0;
+ p = MAX(ms, l-ms-1) + 1;
+ } else mem0 = l-p;
+ mem = 0;
+
+ /* Initialize incremental end-of-haystack pointer */
+ z = h;
+
+ /* Search loop */
+ for (;;) {
+ /* Update incremental end-of-haystack pointer */
+ if (z-h < l) {
+ /* Fast estimate for MIN(l,63) */
+ size_t grow = l | 63;
+ const wchar_t *z2 = wmemchr(z, 0, grow);
+ if (z2) {
+ z = z2;
+ if (z-h < l) return 0;
+ } else z += grow;
+ }
+
+ /* Compare right half */
+ for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
+ if (n[k]) {
+ h += k-ms;
+ mem = 0;
+ continue;
+ }
+ /* Compare left half */
+ for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+ if (k <= mem) return (wchar_t *)h;
+ h += p;
+ mem = mem0;
+ }
+}
+
+wchar_t *wcsstr(const wchar_t *restrict h, const wchar_t *restrict n)
+{
+ /* Return immediately on empty needle or haystack */
+ if (!n[0]) return (wchar_t *)h;
+ if (!h[0]) return 0;
+
+ /* Use faster algorithms for short needles */
+ h = wcschr(h, *n);
+ if (!h || !n[1]) return (wchar_t *)h;
+ if (!h[1]) return 0;
+
+ return twoway_wcsstr(h, n);
+}
diff --git a/libc-top-half/musl/src/string/wcstok.c b/libc-top-half/musl/src/string/wcstok.c
new file mode 100644
index 0000000..ecc8033
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcstok.c
@@ -0,0 +1,12 @@
+#include <wchar.h>
+
+wchar_t *wcstok(wchar_t *restrict s, const wchar_t *restrict sep, wchar_t **restrict p)
+{
+ if (!s && !(s = *p)) return NULL;
+ s += wcsspn(s, sep);
+ if (!*s) return *p = 0;
+ *p = s + wcscspn(s, sep);
+ if (**p) *(*p)++ = 0;
+ else *p = 0;
+ return s;
+}
diff --git a/libc-top-half/musl/src/string/wcswcs.c b/libc-top-half/musl/src/string/wcswcs.c
new file mode 100644
index 0000000..9cfe4ac
--- /dev/null
+++ b/libc-top-half/musl/src/string/wcswcs.c
@@ -0,0 +1,6 @@
+#include <wchar.h>
+
+wchar_t *wcswcs(const wchar_t *haystack, const wchar_t *needle)
+{
+ return wcsstr(haystack, needle);
+}
diff --git a/libc-top-half/musl/src/string/wmemchr.c b/libc-top-half/musl/src/string/wmemchr.c
new file mode 100644
index 0000000..2bc2c27
--- /dev/null
+++ b/libc-top-half/musl/src/string/wmemchr.c
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n)
+{
+ for (; n && *s != c; n--, s++);
+ return n ? (wchar_t *)s : 0;
+}
diff --git a/libc-top-half/musl/src/string/wmemcmp.c b/libc-top-half/musl/src/string/wmemcmp.c
new file mode 100644
index 0000000..2a19326
--- /dev/null
+++ b/libc-top-half/musl/src/string/wmemcmp.c
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+int wmemcmp(const wchar_t *l, const wchar_t *r, size_t n)
+{
+ for (; n && *l==*r; n--, l++, r++);
+ return n ? *l-*r : 0;
+}
diff --git a/libc-top-half/musl/src/string/wmemcpy.c b/libc-top-half/musl/src/string/wmemcpy.c
new file mode 100644
index 0000000..52e6e6e
--- /dev/null
+++ b/libc-top-half/musl/src/string/wmemcpy.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+wchar_t *wmemcpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
+{
+ wchar_t *a = d;
+ while (n--) *d++ = *s++;
+ return a;
+}
diff --git a/libc-top-half/musl/src/string/wmemmove.c b/libc-top-half/musl/src/string/wmemmove.c
new file mode 100644
index 0000000..964c903
--- /dev/null
+++ b/libc-top-half/musl/src/string/wmemmove.c
@@ -0,0 +1,13 @@
+#include <wchar.h>
+#include <stdint.h>
+
+wchar_t *wmemmove(wchar_t *d, const wchar_t *s, size_t n)
+{
+ wchar_t *d0 = d;
+ if (d == s) return d;
+ if ((uintptr_t)d-(uintptr_t)s < n * sizeof *d)
+ while (n--) d[n] = s[n];
+ else
+ while (n--) *d++ = *s++;
+ return d0;
+}
diff --git a/libc-top-half/musl/src/string/wmemset.c b/libc-top-half/musl/src/string/wmemset.c
new file mode 100644
index 0000000..07a037a
--- /dev/null
+++ b/libc-top-half/musl/src/string/wmemset.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+wchar_t *wmemset(wchar_t *d, wchar_t c, size_t n)
+{
+ wchar_t *ret = d;
+ while (n--) *d++ = c;
+ return ret;
+}
diff --git a/libc-top-half/musl/src/string/x86_64/memcpy.s b/libc-top-half/musl/src/string/x86_64/memcpy.s
new file mode 100644
index 0000000..3d960ef
--- /dev/null
+++ b/libc-top-half/musl/src/string/x86_64/memcpy.s
@@ -0,0 +1,25 @@
+.global memcpy
+.global __memcpy_fwd
+.hidden __memcpy_fwd
+.type memcpy,@function
+memcpy:
+__memcpy_fwd:
+ mov %rdi,%rax
+ cmp $8,%rdx
+ jc 1f
+ test $7,%edi
+ jz 1f
+2: movsb
+ dec %rdx
+ test $7,%edi
+ jnz 2b
+1: mov %rdx,%rcx
+ shr $3,%rcx
+ rep
+ movsq
+ and $7,%edx
+ jz 1f
+2: movsb
+ dec %edx
+ jnz 2b
+1: ret
diff --git a/libc-top-half/musl/src/string/x86_64/memmove.s b/libc-top-half/musl/src/string/x86_64/memmove.s
new file mode 100644
index 0000000..172c025
--- /dev/null
+++ b/libc-top-half/musl/src/string/x86_64/memmove.s
@@ -0,0 +1,16 @@
+.global memmove
+.type memmove,@function
+memmove:
+ mov %rdi,%rax
+ sub %rsi,%rax
+ cmp %rdx,%rax
+.hidden __memcpy_fwd
+ jae __memcpy_fwd
+ mov %rdx,%rcx
+ lea -1(%rdi,%rdx),%rdi
+ lea -1(%rsi,%rdx),%rsi
+ std
+ rep movsb
+ cld
+ lea 1(%rdi),%rax
+ ret
diff --git a/libc-top-half/musl/src/string/x86_64/memset.s b/libc-top-half/musl/src/string/x86_64/memset.s
new file mode 100644
index 0000000..2d3f5e5
--- /dev/null
+++ b/libc-top-half/musl/src/string/x86_64/memset.s
@@ -0,0 +1,72 @@
+.global memset
+.type memset,@function
+memset:
+ movzbq %sil,%rax
+ mov $0x101010101010101,%r8
+ imul %r8,%rax
+
+ cmp $126,%rdx
+ ja 2f
+
+ test %edx,%edx
+ jz 1f
+
+ mov %sil,(%rdi)
+ mov %sil,-1(%rdi,%rdx)
+ cmp $2,%edx
+ jbe 1f
+
+ mov %ax,1(%rdi)
+ mov %ax,(-1-2)(%rdi,%rdx)
+ cmp $6,%edx
+ jbe 1f
+
+ mov %eax,(1+2)(%rdi)
+ mov %eax,(-1-2-4)(%rdi,%rdx)
+ cmp $14,%edx
+ jbe 1f
+
+ mov %rax,(1+2+4)(%rdi)
+ mov %rax,(-1-2-4-8)(%rdi,%rdx)
+ cmp $30,%edx
+ jbe 1f
+
+ mov %rax,(1+2+4+8)(%rdi)
+ mov %rax,(1+2+4+8+8)(%rdi)
+ mov %rax,(-1-2-4-8-16)(%rdi,%rdx)
+ mov %rax,(-1-2-4-8-8)(%rdi,%rdx)
+ cmp $62,%edx
+ jbe 1f
+
+ mov %rax,(1+2+4+8+16)(%rdi)
+ mov %rax,(1+2+4+8+16+8)(%rdi)
+ mov %rax,(1+2+4+8+16+16)(%rdi)
+ mov %rax,(1+2+4+8+16+24)(%rdi)
+ mov %rax,(-1-2-4-8-16-32)(%rdi,%rdx)
+ mov %rax,(-1-2-4-8-16-24)(%rdi,%rdx)
+ mov %rax,(-1-2-4-8-16-16)(%rdi,%rdx)
+ mov %rax,(-1-2-4-8-16-8)(%rdi,%rdx)
+
+1: mov %rdi,%rax
+ ret
+
+2: test $15,%edi
+ mov %rdi,%r8
+ mov %rax,-8(%rdi,%rdx)
+ mov %rdx,%rcx
+ jnz 2f
+
+1: shr $3,%rcx
+ rep
+ stosq
+ mov %r8,%rax
+ ret
+
+2: xor %edx,%edx
+ sub %edi,%edx
+ and $15,%edx
+ mov %rax,(%rdi)
+ mov %rax,8(%rdi)
+ sub %rdx,%rcx
+ add %rdx,%rdi
+ jmp 1b