[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