[PATCH v3 1/3] newlib: riscv: Add memchr() and memrchr() implementations
Eric Salem <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <4d1db27470f8833edb05693f286c63cfd001c01f.1747060980.git.ericsalem@gmail.com> |
Copy stock implementations of memchr() and memrchr() to the RISC-V port. Reviewed-by: Christian Herber <[email protected]> Signed-off-by: Eric Salem <[email protected]> --- newlib/libc/machine/riscv/Makefile.inc | 2 +- newlib/libc/machine/riscv/memchr.c | 99 ++++++++++++++++++++++++++ newlib/libc/machine/riscv/memrchr.c | 99 ++++++++++++++++++++++++++ 3 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 newlib/libc/machine/riscv/memchr.c create mode 100644 newlib/libc/machine/riscv/memrchr.c diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc index 4d6c0469abb3..85bed91772cf 100644 --- a/newlib/libc/machine/riscv/Makefile.inc +++ b/newlib/libc/machine/riscv/Makefile.inc @@ -1,3 +1,3 @@ libc_a_SOURCES += \ %D%/memmove.S %D%/memmove-stub.c %D%/memset.S %D%/memcpy-asm.S %D%/memcpy.c %D%/strlen.c \ - %D%/strcpy.c %D%/stpcpy.c %D%/strcmp.S %D%/setjmp.S %D%/ieeefp.c %D%/ffs.c + %D%/strcpy.c %D%/stpcpy.c %D%/strcmp.S %D%/memchr.c %D%/memrchr.c %D%/setjmp.S %D%/ieeefp.c %D%/ffs.c diff --git a/newlib/libc/machine/riscv/memchr.c b/newlib/libc/machine/riscv/memchr.c new file mode 100644 index 000000000000..5c08c12813fe --- /dev/null +++ b/newlib/libc/machine/riscv/memchr.c @@ -0,0 +1,99 @@ +/* +FUNCTION + <<memchr>>---find character in memory + +INDEX + memchr + +SYNOPSIS + #include <string.h> + void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); + +DESCRIPTION + This function searches memory starting at <<*<[src]>>> for the + character <[c]>. The search only ends with the first + occurrence of <[c]>, or after <[length]> characters; in + particular, <<NUL>> does not terminate the search. + +RETURNS + If the character <[c]> is found within <[length]> characters + of <<*<[src]>>>, a pointer to the character is returned. If + <[c]> is not found, then <<NULL>> is returned. + +PORTABILITY +<<memchr>> is ANSI C. + +<<memchr>> requires no supporting OS subroutines. + +QUICKREF + memchr ansi pure +*/ + +#include <_ansi.h> +#include <string.h> +#include <limits.h> +#include "../../string/local.h" + +void * +memchr (const void *src_void, + int c, + size_t length) +{ + const unsigned char *src = (const unsigned char *) src_void; + unsigned char d = c; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned long *asrc; + unsigned long mask; + unsigned int i; + + while (UNALIGNED_X(src)) + { + if (!length--) + return NULL; + if (*src == d) + return (void *) src; + src++; + } + + if (!TOO_SMALL_LITTLE_BLOCK(length)) + { + /* If we get this far, we know that length is large and src is + word-aligned. */ + /* The fast code reads the source one word at a time and only + performs the bytewise search on word-sized segments if they + contain the search character, which is detected by XORing + the word-sized segment with a word-sized block of the search + character and then detecting for the presence of NUL in the + result. */ + asrc = (unsigned long *) src; + mask = d << 8 | d; + mask = mask << 16 | mask; + for (i = 32; i < sizeof(mask) * 8; i <<= 1) + mask = (mask << i) | mask; + + while (!TOO_SMALL_LITTLE_BLOCK(length)) + { + if (DETECT_CHAR(*asrc, mask)) + break; + length -= LITTLE_BLOCK_SIZE; + asrc++; + } + + /* If there are fewer than LITTLE_BLOCK_SIZE characters left, + then we resort to the bytewise loop. */ + + src = (unsigned char *) asrc; + } + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (length--) + { + if (*src == d) + return (void *) src; + src++; + } + + return NULL; +} diff --git a/newlib/libc/machine/riscv/memrchr.c b/newlib/libc/machine/riscv/memrchr.c new file mode 100644 index 000000000000..8d15ccb780ec --- /dev/null +++ b/newlib/libc/machine/riscv/memrchr.c @@ -0,0 +1,99 @@ +/* +FUNCTION + <<memrchr>>---reverse search for character in memory + +INDEX + memrchr + +SYNOPSIS + #include <string.h> + void *memrchr(const void *<[src]>, int <[c]>, size_t <[length]>); + +DESCRIPTION + This function searches memory starting at <[length]> bytes + beyond <<*<[src]>>> backwards for the character <[c]>. + The search only ends with the first occurrence of <[c]>; in + particular, <<NUL>> does not terminate the search. + +RETURNS + If the character <[c]> is found within <[length]> characters + of <<*<[src]>>>, a pointer to the character is returned. If + <[c]> is not found, then <<NULL>> is returned. + +PORTABILITY +<<memrchr>> is a GNU extension. + +<<memrchr>> requires no supporting OS subroutines. + +QUICKREF + memrchr +*/ + +#include <_ansi.h> +#include <string.h> +#include <limits.h> +#include "../../string/local.h" + +void * +memrchr (const void *src_void, + int c, + size_t length) +{ + const unsigned char *src = (const unsigned char *) src_void + length - 1; + unsigned char d = c; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned long *asrc; + unsigned long mask; + unsigned int i; + + while (UNALIGNED_X(src)) + { + if (!length--) + return NULL; + if (*src == d) + return (void *) src; + src--; + } + + if (!TOO_SMALL_LITTLE_BLOCK(length)) + { + /* If we get this far, we know that length is large and src is + word-aligned. */ + /* The fast code reads the source one word at a time and only + performs the bytewise search on word-sized segments if they + contain the search character, which is detected by XORing + the word-sized segment with a word-sized block of the search + character and then detecting for the presence of NUL in the + result. */ + asrc = (unsigned long *) (src - LITTLE_BLOCK_SIZE + 1); + mask = d << 8 | d; + mask = mask << 16 | mask; + for (i = 32; i < sizeof(mask) * 8; i <<= 1) + mask = (mask << i) | mask; + + while (!TOO_SMALL_LITTLE_BLOCK(length)) + { + if (DETECT_CHAR(*asrc, mask)) + break; + length -= LITTLE_BLOCK_SIZE; + asrc--; + } + + /* If there are fewer than LITTLE_BLOCK_SIZE characters left, + then we resort to the bytewise loop. */ + + src = (unsigned char *) asrc + LITTLE_BLOCK_SIZE - 1; + } + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (length--) + { + if (*src == d) + return (void *) src; + src--; + } + + return NULL; +} -- 2.49.0