[PATCH 1/3] newlib: riscv: Add memchr() and memrchr() implementations

Eric Salem <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <4d1db27470f8833edb05693f286c63cfd001c01f.1746623015.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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.