[PATCH v3 11/15] riscv: add vectorized strncat
Pincheng Wang
pincheng.plct@isrc.iscas.ac.cn
Fri Aug 14 02:26:52 GMT 2026
The vector implementation locates the end of the destination and appends
at most n bytes of the source in vector-length chunks using
fault-only-first loads (vle8ff.v); vl is capped by the remaining count so
the source is never read across an unmapped page, and the result is always
NUL-terminated. This provides significant performance improvements on
RVV-capable hardware. Use conditional compilation to fall back to the
generic implementation when __riscv_vector is not available, maintaining
compatibility with non-vector RISC-V systems.
Signed-off-by: Pincheng Wang <pincheng.plct@isrc.iscas.ac.cn>
---
newlib/libc/machine/riscv/Makefile.inc | 2 ++
newlib/libc/machine/riscv/strncat-asm.S | 43 +++++++++++++++++++++++++
newlib/libc/machine/riscv/strncat.c | 5 +++
3 files changed, 50 insertions(+)
create mode 100644 newlib/libc/machine/riscv/strncat-asm.S
create mode 100644 newlib/libc/machine/riscv/strncat.c
diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index b8f4d2f9c..fae228e43 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -32,6 +32,8 @@ libc_a_SOURCES += \
%D%/strcpy.c \
%D%/strlen-asm.S \
%D%/strlen.c \
+ %D%/strncat-asm.S \
+ %D%/strncat.c \
%D%/strncmp-asm.S \
%D%/strncmp.c \
%D%/strncpy-asm.S \
diff --git a/newlib/libc/machine/riscv/strncat-asm.S b/newlib/libc/machine/riscv/strncat-asm.S
new file mode 100644
index 000000000..426a0674d
--- /dev/null
+++ b/newlib/libc/machine/riscv/strncat-asm.S
@@ -0,0 +1,43 @@
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+ENTRY(strncat)
+ mv a3, a0
+ /* the strlen of a0. */
+.Lstrlen_loop:
+ vsetvli a4, zero, e8, m1, ta, ma
+
+ vle8ff.v v8, (a3)
+ /* find the '\0'. */
+ vmseq.vx v0, v8, zero
+ csrr a4, vl
+ vfirst.m a5, v0
+ add a3, a3, a4
+ bltz a5, .Lstrlen_loop
+
+ sub a3, a3, a4
+ add a3, a3, a5
+
+ /* copy at most a2 bytes of a1 to a3. */
+.Lstrcpy_loop:
+ vsetvli zero, a2, e8, m1, ta, ma
+
+ vle8ff.v v8, (a1)
+ vmseq.vx v1, v8, zero
+ csrr a4, vl
+ vfirst.m a5, v1
+ vmsif.m v0, v1
+ add a1, a1, a4
+ sub a2, a2, a4
+ vse8.v v8, (a3), v0.t
+ add a3, a3, a4
+ beqz a2, .Lfill_zero
+ bltz a5, .Lstrcpy_loop
+ ret
+.Lfill_zero:
+ bgez a5, .Lfill_zero_end
+ sb zero, (a3)
+.Lfill_zero_end:
+ ret
+END(strncat)
+#endif
diff --git a/newlib/libc/machine/riscv/strncat.c b/newlib/libc/machine/riscv/strncat.c
new file mode 100644
index 000000000..097d9157d
--- /dev/null
+++ b/newlib/libc/machine/riscv/strncat.c
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector)
+# include "../../string/strncat.c"
+#else
+/* strncat defined in strncat-asm.S */
+#endif
--
2.39.5
More information about the Newlib
mailing list