new file mode 100644
@@ -0,0 +1,35 @@
+#include <stdint.h>
+
+static const unsigned long int ones = (~0UL / 255); /* 0x0101...*/
+static const unsigned long int add = 127 * (~0UL / 255);
+static const unsigned long int high_bits = 128 * (~0UL / 255);
+
+/* Use vector arithmetic tricks. Idea is to take expression works on
+ unsigned byte and evaluates 0 for nozero byte and nonzero on zero byte.
+ Our expression is ((s + 127) ^ (~s)) & 128
+ Now we evaluate this expression on each byte in parallel and on first
+ nonzero byte our expression will have nonzero value. */
+
+static __always_inline
+unsigned long int
+contains_zero (unsigned long int s)
+{
+ return ((s + add) ^ ~s) & high_bits;
+}
+
+#define LSIZE sizeof (unsigned long int)
+#define CROSS_PAGE(x, n) (((uintptr_t)x) % 4096 >= 4096 - n)
+
+static __always_inline
+size_t
+first_nonzero_byte (unsigned long int u)
+{
+#ifdef FAST_FFS
+ return ffsl (u) / 8 - 1;
+#else
+ u = u = u ^ (u - 1);
+ u = u & ones;
+ u = u * ones;
+ return (u >> (8 * LSIZE - 8)) - 1;
+#endif
+}
@@ -25,9 +25,8 @@
#undef strchr
-
/* Include strchrnul and let gcc inline it. */
-#define AS_STRCHRNUL
+#define AS_STRCHR
#define STRCHRNUL strchrnul_i
#include "string/strchrnul.c"
@@ -23,6 +23,7 @@
#include <string.h>
#include <libc-internal.h>
#include <stdint.h>
+#include "string/common.h"
#undef __strchrnul
#undef strchrnul
@@ -30,24 +31,8 @@
# define STRCHRNUL __strchrnul
#endif
-static const unsigned long int ones = (~0UL / 255); /* 0x0101...*/
-static const unsigned long int add = 127 * (~0UL / 255);
-static const unsigned long int high_bits = 128 * (~0UL / 255);
-/* Use vector arithmetic tricks. Idea is to take expression works on
- unsigned byte and evaluates 0 for nozero byte and nonzero on zero byte.
- Our expression is ((s + 127) ^ (~s)) & 128
- Now we evaluate this expression on each byte in parallel and on first
- nonzero byte our expression will have nonzero value. */
-
-static always_inline
-unsigned long int
-contains_zero (unsigned long int s)
-{
- return ((s + add) ^ ~s) & high_bits;
-}
-
-static always_inline
+static __always_inline
int
found_in_long_bytes(char *s, unsigned long int cmask, char **result)
{
@@ -55,19 +40,16 @@ found_in_long_bytes(char *s, unsigned long int cmask, char **result)
unsigned long int mask = contains_zero (*lptr) | contains_zero (*lptr ^ cmask);
if (mask)
{
- *result = s + ffsl (mask) / 8 - 1;
+ *result = s + first_nonzero_byte (mask);
return 1;
}
else
return 0;
}
-#define LSIZE sizeof (unsigned long int)
-#define CROSS_PAGE(x, n) (((uintptr_t)x)%4096 >= 4096 - n)
-
/* Find the first occurrence of C in S or the final NUL byte. */
#ifdef AS_STRCHR
-static always_inline
+static __always_inline
#endif
char *
STRCHRNUL (const char *s_in, int c_in)
@@ -122,7 +104,7 @@ STRCHRNUL (const char *s_in, int c_in)
>> (8 * (s_aligned - s));
if (mask)
- return s + ffsl (mask) / 8 - 1;
+ return s + first_nonzero_byte (mask);
if (found_in_long_bytes (s + 1 * LSIZE, cmask, &r))
return r;
@@ -160,14 +142,6 @@ STRCHRNUL (const char *s_in, int c_in)
return r;
}
-
-char *strchr(char *s, int c)
-{
- char *r = __strchrnule(s,c);
- return *r ? r : 0;
-
-}
-
-#ifndef AS_STRCHR
+#ifdef AS_STRCHR
weak_alias (__strchrnul, strchrnul)
#endif