[1/4] newlib: riscv: Add XLEN typedef and clean up types

Message ID ace3e6acdf3e9178c5da4ba44ad5e117c64b06c5.1742483743.git.ericsalem@gmail.com
State New
Headers
Series newlib: riscv: Optimize string functions |

Commit Message

Eric Salem March 20, 2025, 3:28 p.m. UTC
  The size of the long data type isn't precisely defined in the C
standard, so create a new typedef that uses either uint32_t or uint64_t
based on XLEN. The fixed width types are more robust against any ABI
changes and fit the data types of the intrinsic functions. Use the new
uintxlen_t type instead of long and uintptr_t.

Reviewed-by: Christian Herber <christian.herber@oss.nxp.com>
Signed-off-by: Eric Salem <ericsalem@gmail.com>
---
 newlib/libc/machine/riscv/strcpy.c     | 40 +++++++++++---------------
 newlib/libc/machine/riscv/strlen.c     | 37 ++++++++++++------------
 newlib/libc/machine/riscv/sys/asm.h    |  4 +++
 newlib/libc/machine/riscv/sys/string.h |  8 ++++--
 4 files changed, 45 insertions(+), 44 deletions(-)
  

Patch

diff --git a/newlib/libc/machine/riscv/strcpy.c b/newlib/libc/machine/riscv/strcpy.c
index 08aef64ba6c9..7b1780025ab9 100644
--- a/newlib/libc/machine/riscv/strcpy.c
+++ b/newlib/libc/machine/riscv/strcpy.c
@@ -11,6 +11,7 @@ 
 
 #include <string.h>
 #include <stdint.h>
+#include "sys/asm.h"
 
 char *strcpy(char *dst, const char *src)
 {
@@ -18,37 +19,30 @@  char *strcpy(char *dst, const char *src)
 
 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
 #if !(__riscv_misaligned_slow || __riscv_misaligned_fast)
-  int misaligned = ((uintptr_t)dst | (uintptr_t)src) & (sizeof (long) - 1);
+  int misaligned = ((uintxlen_t)dst | (uintxlen_t)src) & (sizeof (uintxlen_t) - 1);
   if (__builtin_expect(!misaligned, 1))
 #endif
     {
-      long *ldst = (long *)dst;
-      const long *lsrc = (const long *)src;
+      uintxlen_t *pdst = (uintxlen_t *)dst;
+      const uintxlen_t *psrc = (const uintxlen_t *)src;
 
-      while (!__libc_detect_null(*lsrc))
-	*ldst++ = *lsrc++;
+      while (!__libc_detect_null(*psrc))
+        *pdst++ = *psrc++;
 
-      dst = (char *)ldst;
-      src = (const char *)lsrc;
+      dst = (char *)pdst;
+      src = (const char *)psrc;
 
-      char c0 = src[0];
-      char c1 = src[1];
-      char c2 = src[2];
-      if (!(*dst++ = c0)) return dst0;
-      if (!(*dst++ = c1)) return dst0;
-      char c3 = src[3];
-      if (!(*dst++ = c2)) return dst0;
-      if (sizeof (long) == 4) goto out;
-      char c4 = src[4];
-      if (!(*dst++ = c3)) return dst0;
-      char c5 = src[5];
-      if (!(*dst++ = c4)) return dst0;
-      char c6 = src[6];
-      if (!(*dst++ = c5)) return dst0;
-      if (!(*dst++ = c6)) return dst0;
+      if (!(*dst++ = src[0])) return dst0;
+      if (!(*dst++ = src[1])) return dst0;
+      if (!(*dst++ = src[2])) return dst0;
+      if (sizeof (*pdst ) == 4) goto out;
+      if (!(*dst++ = src[3])) return dst0;
+      if (!(*dst++ = src[4])) return dst0;
+      if (!(*dst++ = src[5])) return dst0;
+      if (!(*dst++ = src[6])) return dst0;
 
 out:
-      *dst++ = 0;
+      *dst = 0;
       return dst0;
     }
 #endif /* not PREFER_SIZE_OVER_SPEED */
diff --git a/newlib/libc/machine/riscv/strlen.c b/newlib/libc/machine/riscv/strlen.c
index 3b0406699272..5d314ec51a72 100644
--- a/newlib/libc/machine/riscv/strlen.c
+++ b/newlib/libc/machine/riscv/strlen.c
@@ -11,6 +11,7 @@ 
 
 #include <string.h>
 #include <stdint.h>
+#include "sys/asm.h"
 
 size_t strlen(const char *str)
 {
@@ -21,33 +22,33 @@  size_t strlen(const char *str)
     ;
   return str - start - 1;
 #else
-  if (__builtin_expect ((uintptr_t)str & (sizeof (long) - 1), 0)) do
+  if (__builtin_expect ((uintxlen_t)str & (sizeof (uintxlen_t) - 1), 0)) do
     {
       char ch = *str;
       str++;
       if (!ch)
-	return str - start - 1;
-    } while ((uintptr_t)str & (sizeof (long) - 1));
+      return str - start - 1;
+    } while ((uintxlen_t)str & (sizeof (uintxlen_t) - 1));
 
-  unsigned long *ls = (unsigned long *)str;
-  while (!__libc_detect_null (*ls++))
+  uintxlen_t *ps = (uintxlen_t *)str;
+  while (!__libc_detect_null (*ps++))
     ;
-  asm volatile ("" : "+r"(ls)); /* prevent "optimization" */
+  asm volatile ("" : "+r"(ps)); /* prevent "optimization" */
 
-  str = (const char *)ls;
-  size_t ret = str - start, sl = sizeof (long);
+  str = (const char *)ps;
+  size_t ret = str - start, sp = sizeof (*ps);
 
-  char c0 = str[0 - sl], c1 = str[1 - sl], c2 = str[2 - sl], c3 = str[3 - sl];
-  if (c0 == 0)            return ret + 0 - sl;
-  if (c1 == 0)            return ret + 1 - sl;
-  if (c2 == 0)            return ret + 2 - sl;
-  if (sl == 4 || c3 == 0) return ret + 3 - sl;
+  char c0 = str[0 - sp], c1 = str[1 - sp], c2 = str[2 - sp], c3 = str[3 - sp];
+  if (c0 == 0)             return ret + 0 - sp;
+  if (c1 == 0)             return ret + 1 - sp;
+  if (c2 == 0)             return ret + 2 - sp;
+  if (sp == 4 || c3 == 0)  return ret + 3 - sp;
 
-  c0 = str[4 - sl], c1 = str[5 - sl], c2 = str[6 - sl], c3 = str[7 - sl];
-  if (c0 == 0)            return ret + 4 - sl;
-  if (c1 == 0)            return ret + 5 - sl;
-  if (c2 == 0)            return ret + 6 - sl;
+  c0 = str[4 - sp], c1 = str[5 - sp], c2 = str[6 - sp];
+  if (c0 == 0)             return ret + 4 - sp;
+  if (c1 == 0)             return ret + 5 - sp;
+  if (c2 == 0)             return ret + 6 - sp;
 
-  return ret + 7 - sl;
+  return ret + 7 - sp;
 #endif /* not PREFER_SIZE_OVER_SPEED */
 }
diff --git a/newlib/libc/machine/riscv/sys/asm.h b/newlib/libc/machine/riscv/sys/asm.h
index 8c8aeb3ae775..0a354b220517 100644
--- a/newlib/libc/machine/riscv/sys/asm.h
+++ b/newlib/libc/machine/riscv/sys/asm.h
@@ -12,6 +12,8 @@ 
 #ifndef _SYS_ASM_H
 #define _SYS_ASM_H
 
+#include <stdint.h>
+
 /*
  * Macros to handle different pointer/register sizes for 32/64-bit code
  */
@@ -20,11 +22,13 @@ 
 # define SZREG	8
 # define REG_S sd
 # define REG_L ld
+typedef uint64_t uintxlen_t;
 #elif __riscv_xlen == 32
 # define PTRLOG 2
 # define SZREG	4
 # define REG_S sw
 # define REG_L lw
+typedef uint32_t uintxlen_t;
 #else
 # error __riscv_xlen must equal 32 or 64
 #endif
diff --git a/newlib/libc/machine/riscv/sys/string.h b/newlib/libc/machine/riscv/sys/string.h
index beebe31f728f..6a0c42a49c12 100644
--- a/newlib/libc/machine/riscv/sys/string.h
+++ b/newlib/libc/machine/riscv/sys/string.h
@@ -12,10 +12,12 @@ 
 #ifndef _SYS_STRING_H
 #define _SYS_STRING_H
 
-static __inline unsigned long __libc_detect_null(unsigned long w)
+#include "asm.h"
+
+static __inline uintxlen_t __libc_detect_null(uintxlen_t w)
 {
-  unsigned long mask = 0x7f7f7f7f;
-  if (sizeof (long) == 8)
+  uintxlen_t mask = 0x7f7f7f7f;
+  if (sizeof (w) == 8)
     mask = ((mask << 16) << 16) | mask;
   return ~(((w & mask) + mask) | w | mask);
 }