The vector implementation locates the end of the destination and appends
the source in vector-length chunks using fault-only-first loads
(vle8ff.v), so neither string is ever read across an unmapped page. 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/strcat-asm.S | 40 ++++++++++++++++++++++++++
newlib/libc/machine/riscv/strcat.c | 5 ++++
3 files changed, 47 insertions(+)
create mode 100644 newlib/libc/machine/riscv/strcat-asm.S
create mode 100644 newlib/libc/machine/riscv/strcat.c
@@ -20,6 +20,8 @@ libc_a_SOURCES += \
%D%/memset.S \
%D%/setjmp.S \
%D%/stpcpy.c \
+ %D%/strcat-asm.S \
+ %D%/strcat.c \
%D%/strchr-asm.S \
%D%/strchr.c \
%D%/strchrnul-asm.S \
new file mode 100644
@@ -0,0 +1,40 @@
+#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+.text
+.option push
+.option arch, +v
+.global strcat
+.type strcat, @function
+strcat:
+ mv a2, a0
+ /* Perform `strlen(a0)`. */
+.Lstrlen_loop:
+ vsetvli a3, zero, e8, m1, ta, ma
+
+ vle8ff.v v8, (a2)
+ vmseq.vx v0, v8, zero
+ csrr a4, vl
+ vfirst.m a5, v0
+ add a2, a2, a4
+ bltz a5, .Lstrlen_loop
+
+ sub a2, a2, a4
+ add a2, a2, a5
+
+ /* Perform `strcpy(a0 + strlen(a0), a1)`. */
+.Lstrcpy_loop:
+ vsetvli a3, zero, 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
+ vse8.v v8, (a2), v0.t
+ add a2, a2, a4
+ bltz a5, .Lstrcpy_loop
+
+ ret
+.size strcat, .-strcat
+.option pop
+#endif
new file mode 100644
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || __riscv_xlen != 64
+# include "../../string/strcat.c"
+#else
+/* strcat defined in strcat-asm.S */
+#endif