Re: [PATCH 3/3] RISC-V: memcpy() align dest when misaligned access is prohibited
Sebastian Huber <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
Hello Mahmoud Abumandour, I use Newlib on a Microchip PolarFire SoC which doesn't support misaligned access. I get exceptions (mcause is 4 or 6) with the current Newlib. I use the following machine options with GCC 13: -march=rv64imac -mabi=lp64 -mcmodel=medany -mstrict-align It seems that neither __riscv_misaligned_slow nor __riscv_misaligned_avoid is defined by GCC 13, so the workaround is not activated. This define is only available in GCC 14 and later. Would it make sense to change this check to #if !defined(__riscv_misaligned_fast) instead of #if defined(__riscv_misaligned_slow) || defined(__riscv_misaligned_avoid) ? ----- Am 27. Apr 2025 um 13:41 schrieb ma mandourr [email protected]: > From: Mahmoud Abumandour <[email protected]> > > Add a code path for when source and dest are differently aligned. > > If misaligned access is slow or prohibited, and the alignments of the > source and destination are different, we align the destination to do > XLEN stores. This uses only one aligned store for every four (or eight > for XLEN == 64) bytes of data. > > Reviewed-by: Christian Herber <[email protected]> > Signed-off-by: Mahmoud Abumandour <[email protected]> > --- > newlib/libc/machine/riscv/memcpy.c | 72 +++++++++++++++++++++++++----- > 1 file changed, 60 insertions(+), 12 deletions(-) > > diff --git a/newlib/libc/machine/riscv/memcpy.c > b/newlib/libc/machine/riscv/memcpy.c > index 427005efd..5d6b2f301 100644 > --- a/newlib/libc/machine/riscv/memcpy.c > +++ b/newlib/libc/machine/riscv/memcpy.c > @@ -16,7 +16,6 @@ > > #include "../../string/local.h" > #include "xlenint.h" > -#include <stdint.h> > #include <string.h> > #include <sys/asm.h> > > @@ -31,6 +30,30 @@ __libc_memcpy_bytewise (unsigned char *dst, const unsigned > char *src, > *dst++ = *src++; > } > > +#if defined(__riscv_misaligned_slow) || defined(__riscv_misaligned_avoid) > +static uintxlen_t > +__libc_load_xlen (const void *src) > +{ > + const unsigned char *p = (const unsigned char *)src; > + uintxlen_t ret = 0; > + unsigned char b0 = *p++; > + unsigned char b1 = *p++; > + unsigned char b2 = *p++; > + unsigned char b3 = *p++; > + ret = (uintxlen_t)b0 | ((uintxlen_t)b1 << 8) | ((uintxlen_t)b2 << 16) > + | ((uintxlen_t)b3 << 24); > +#if __riscv_xlen == 64 > + unsigned char b4 = *p++; > + unsigned char b5 = *p++; > + unsigned char b6 = *p++; > + unsigned char b7 = *p++; > + ret |= ((uintxlen_t)b4 << 32) | ((uintxlen_t)b5 << 40) > + | ((uintxlen_t)b6 << 48) | ((uintxlen_t)b7 << 56); > +#endif > + return ret; > +} > +#endif > + > void * > __inhibit_loop_to_libcall > memcpy (void *__restrict aa, const void *__restrict bb, size_t n) > @@ -39,23 +62,51 @@ memcpy (void *__restrict aa, const void *__restrict bb, > size_t n) > const unsigned char *b = (const unsigned char *)bb; > unsigned char *end = a + n; > uintptr_t msk = SZREG - 1; > -#if __riscv_misaligned_slow || __riscv_misaligned_fast > if (n < SZREG) > -#else > - if (unlikely ((((uintptr_t)a & msk) != ((uintptr_t)b & msk)) || n < SZREG)) > -#endif > { > if (__builtin_expect (a < end, 1)) > __libc_memcpy_bytewise (a, b, n); > return aa; > } > > +/* > + * If misaligned access is slow or prohibited, and the alignments of the source > + * and destination are different, we align the destination to do XLEN stores. > + * This uses only one aligned store for every four (or eight for XLEN == 64) > + * bytes of data. > + */ > +#if defined(__riscv_misaligned_slow) || defined(__riscv_misaligned_avoid) > + if (unlikely ((((uintptr_t)a & msk) != ((uintptr_t)b & msk)))) > + { > + size_t dst_pad = (uintptr_t)a & msk; > + dst_pad = (SZREG - dst_pad) & msk; > + __libc_memcpy_bytewise (a, b, dst_pad); > + a += dst_pad; > + b += dst_pad; > + > + uintxlen_t *la = (uintxlen_t *)a; > + const unsigned char *cb = (const unsigned char *)b; > + uintxlen_t *lend = (uintxlen_t *)((uintptr_t)end & ~msk); > + > + while (la < lend) > + { > + *la++ = __libc_load_xlen (cb); > + cb += SZREG; > + } > + a = (unsigned char *)la; > + b = (const unsigned char *)cb; > + if (unlikely (a < end)) > + __libc_memcpy_bytewise (a, b, end - a); > + return aa; > + } > +#endif > + > if (unlikely (((uintptr_t)a & msk) != 0)) > { > - size_t rem = SZREG - ((uintptr_t)a & msk); > - __libc_memcpy_bytewise (a, b, rem); > - a += rem; > - b += rem; > + size_t pad = SZREG - ((uintptr_t)a & msk); > + __libc_memcpy_bytewise (a, b, pad); > + a += pad; > + b += pad; > } > > uintxlen_t *la = (uintxlen_t *)a; > @@ -87,9 +138,6 @@ memcpy (void *__restrict aa, const void *__restrict bb, > size_t n) > } > } > > - while (la < lend) > - *la++ = *lb++; > - > a = (unsigned char *)la; > b = (const unsigned char *)lb; > if (unlikely (a < end)) > -- > 2.43.0 -- embedded brains GmbH & Co. KG Herr Sebastian HUBER Dornierstr. 4 82178 Puchheim Germany email: [email protected] phone: +49-89-18 94 741 - 16 fax: +49-89-18 94 741 - 08 Registergericht: Amtsgericht München Registernummer: HRB 157899 Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler Unsere Datenschutzerklärung finden Sie hier: https://embedded-brains.de/datenschutzerklaerung/