[PATCH 11/17] riscv: add vectorized strncat
Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:42 +0800
| 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 | 47 +++++++++++++++++++++++++ newlib/libc/machine/riscv/strncat.c | 5 +++ 3 files changed, 54 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..b5ae54328 --- /dev/null +++ b/newlib/libc/machine/riscv/strncat-asm.S @@ -0,0 +1,47 @@ +#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED) +.text +.option push +.option arch, +v +.global strncat +.type strncat, @function +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 +.size strncat, .-strncat +.option pop +#endif diff --git a/newlib/libc/machine/riscv/strncat.c b/newlib/libc/machine/riscv/strncat.c new file mode 100644 index 000000000..186f2158e --- /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) || __riscv_xlen != 64 +# include "../../string/strncat.c" +#else +/* strncat defined in strncat-asm.S */ +#endif -- 2.39.5