[PATCH v3 11/15] riscv: add vectorized strncat

Pincheng Wang <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.