The vector implementation copies the source in vector-length chunks using
fault-only-first loads (vle8ff.v) and masked stores that include the
terminating NUL, so the source is never read across an unmapped page.
This provides significant performance improvements on RVV-capable
hardware. Use conditional compilation to fall back to the scalar
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 | 1 +
newlib/libc/machine/riscv/strcpy-asm.S | 20 ++++++++++++++++++++
newlib/libc/machine/riscv/strcpy.c | 5 +++++
3 files changed, 26 insertions(+)
create mode 100644 newlib/libc/machine/riscv/strcpy-asm.S
@@ -26,6 +26,7 @@ libc_a_SOURCES += \
%D%/strchrnul.c \
%D%/strcmp-asm.S \
%D%/strcmp.S \
+ %D%/strcpy-asm.S \
%D%/strcpy.c \
%D%/strlen-asm.S \
%D%/strlen.c \
new file mode 100644
@@ -0,0 +1,20 @@
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+ENTRY(strcpy)
+ mv a2, a0
+.Lloop:
+ 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, .Lloop
+
+ ret
+END(strcpy)
+#endif
@@ -9,6 +9,10 @@
http://www.opensource.org/licenses.
*/
+#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+/* strcpy defined in strcpy-asm.S */
+#else
+
#include <stdbool.h>
#include "rv_string.h"
@@ -16,3 +20,4 @@ char *strcpy(char *dst, const char *src)
{
return __libc_strcpy(dst, src, true);
}
+#endif