Skip to content

Commit

Permalink
Merge the newlibc string into NuttX.
Browse files Browse the repository at this point in the history
Signed-off-by: yangguangcai <[email protected]>
  • Loading branch information
yangguangcai1 committed Aug 26, 2024
1 parent ab92b7d commit 260d815
Show file tree
Hide file tree
Showing 19 changed files with 902 additions and 106 deletions.
88 changes: 77 additions & 11 deletions libs/libc/string/lib_memccpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,33 @@
#include <sys/types.h>
#include <string.h>

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/* Nonzero if either x or y is not aligned on a "long" boundary. */

#define UNALIGNED(x, y) \
(((long)(x) & (sizeof(long) - 1)) | ((long)(y) & (sizeof(long) - 1)))

/* How many bytes are copied each iteration of the word copy loop. */

#define LITTLEBLOCKSIZE (sizeof(long))

/* Threshhold for punting to the byte copier. */

#define TOO_SMALL(len) ((len) < LITTLEBLOCKSIZE)

/* Macros for detecting endchar */

#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */

# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif

/****************************************************************************
* Public Functions
****************************************************************************/
Expand All @@ -49,28 +76,67 @@
#undef memccpy /* See mm/README.txt */
FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n)
{
FAR void *ptr = NULL;
FAR unsigned char *pout = (FAR unsigned char *)s1;
FAR unsigned char *pin = (FAR unsigned char *)s2;
FAR const unsigned char *pin = (FAR const unsigned char *)s2;
FAR long *paligned_out;
FAR const long *paligned_in;
unsigned char endchar = c & 0xff;

/* Copy at most n bytes */
/* If the size is small, or either pin or pout is unaligned,
* then punt into the byte copy loop. This should be rare.
*/

while (n-- > 0)
if (!TOO_SMALL(n) && !UNALIGNED(pin, pout))
{
/* Copy one byte */
unsigned int i;
unsigned long mask = 0;

paligned_out = (FAR long *)pout;
paligned_in = (FAR long *)pin;

/* The fast code reads the ASCII 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 NULL in the
* result.
*/

*pout = *pin++;
for (i = 0; i < LITTLEBLOCKSIZE; i++)
{
mask = (mask << 8) + endchar;
}

/* Did we just copy the terminating byte c? */
/* Copy one long word at a time if possible. */

if (*pout++ == (unsigned char)c)
while (n >= LITTLEBLOCKSIZE)
{
/* Yes return a pointer to the byte after the copy of c into s1 */
unsigned long buffer = (unsigned long)(*paligned_in);
buffer ^= mask;
if (DETECTNULL(buffer))
{
break; /* endchar is found, go byte by byte from here */
}

return (FAR void *)pout;
*paligned_out++ = *paligned_in++;
n -= LITTLEBLOCKSIZE;
}

/* Pick up any residual with a byte copier. */

pout = (FAR unsigned char *)paligned_out;
pin = (FAR unsigned char *)paligned_in;
}

/* C was not found in the first n bytes of s2 */
while (n--)
{
if ((*pout++ = *pin++) == endchar)
{
ptr = pout;
break;
}
}

return NULL;
return ptr;
}
87 changes: 86 additions & 1 deletion libs/libc/string/lib_memchr.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@

#include "libc.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define UNALIGNED(x) ((long)(x) & (sizeof(long) - 1))

/* How many bytes are loaded each iteration of the word copy loop. */

#define LBLOCKSIZE (sizeof(long))

/* Threshhold for punting to the bytewise iterator. */

#define TOO_SMALL(len) ((len) < LBLOCKSIZE)

#if LONG_MAX == 2147483647
# define DETECTNULL(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
#elif LONG_MAX == 9223372036854775807
/* Nonzero if x (a long int) contains a NULL byte. */

# define DETECTNULL(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
#endif

/* DETECTCHAR returns nonzero if (long)x contains the byte used
* to fill (long)mask.
*/

#define DETECTCHAR(x, mask) (DETECTNULL((x) ^ (mask)))

/****************************************************************************
* Public Functions
****************************************************************************/
Expand All @@ -51,10 +79,67 @@
FAR void *memchr(FAR const void *s, int c, size_t n)
{
FAR const unsigned char *p = (FAR const unsigned char *)s;
FAR unsigned long *asrc;
unsigned char d = c;
unsigned long mask;
unsigned int i;

while (UNALIGNED(p))
{
if (!n--)
{
return NULL;
}

if (*p == d)
{
return (FAR void *)p;
}

p++;
}

if (!TOO_SMALL(n))
{
/* If we get this far, we know that n is large and p 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 = (FAR unsigned long *)p;
mask = d << 8 | d;
mask = mask << 16 | mask;
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
{
mask = (mask << i) | mask;
}

while (n >= LBLOCKSIZE)
{
if (DETECTCHAR(*asrc, mask))
{
break;
}

n -= LBLOCKSIZE;
asrc++;
}

/* If there are fewer than LBLOCKSIZE characters left,
* then we resort to the bytewise loop.
*/

p = (FAR unsigned char *)asrc;
}

while (n--)
{
if (*p == (unsigned char)c)
if (*p == d)
{
return (FAR void *)p;
}
Expand Down
56 changes: 51 additions & 5 deletions libs/libc/string/lib_memcmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@

#include "libc.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/* Nonzero if either x or y is not aligned on a "long" boundary. */

#define UNALIGNED(x, y) \
(((long)(x) & (sizeof(long) - 1)) | ((long)(y) & (sizeof(long) - 1)))

/* How many bytes are copied each iteration of the word copy loop. */

#define LBLOCKSIZE (sizeof(long))

/* Threshhold for punting to the byte copier. */

#define TOO_SMALL(len) ((len) < LBLOCKSIZE)

/****************************************************************************
* Public Functions
****************************************************************************/
Expand All @@ -39,16 +56,45 @@ int memcmp(FAR const void *s1, FAR const void *s2, size_t n)
{
FAR unsigned char *p1 = (FAR unsigned char *)s1;
FAR unsigned char *p2 = (FAR unsigned char *)s2;
FAR unsigned long *a1;
FAR unsigned long *a2;

while (n-- > 0)
/* If the size is too small, or either pointer is unaligned,
* then we punt to the byte compare loop. Hopefully this will
* not turn up in inner loops.
*/

if (!TOO_SMALL(n) && !UNALIGNED(p1, p2))
{
if (*p1 < *p2)
/* Otherwise, load and compare the blocks of memory one
* word at a time.
*/

a1 = (FAR unsigned long *)p1;
a2 = (FAR unsigned long *)p2;
while (n >= LBLOCKSIZE)
{
return -1;
if (*a1 != *a2)
{
break;
}

a1++;
a2++;
n -= LBLOCKSIZE;
}
else if (*p1 > *p2)

/* check s mod LBLOCKSIZE remaining characters */

p1 = (FAR unsigned char *)a1;
p2 = (FAR unsigned char *)a2;
}

while (n--)
{
if (*p1 != *p2)
{
return 1;
return *p1 - *p2;
}

p1++;
Expand Down
64 changes: 61 additions & 3 deletions libs/libc/string/lib_memcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,27 @@

#include "libc.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/* Nonzero if either x or y is not aligned on a "long" boundary. */

#define UNALIGNED(x, y) \
(((long)(x) & (sizeof(long) - 1)) | ((long)(y) & (sizeof(long) - 1)))

/* How many bytes are copied each iteration of the 4X unrolled loop. */

#define BIGBLOCKSIZE (sizeof(long) << 2)

/* How many bytes are copied each iteration of the word copy loop. */

#define LITTLEBLOCKSIZE (sizeof(long))

/* Threshhold for punting to the byte copier. */

#define TOO_SMALL(len) ((len) < BIGBLOCKSIZE)

/****************************************************************************
* Public Functions
****************************************************************************/
Expand All @@ -41,9 +62,46 @@
no_builtin("memcpy")
FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n)
{
FAR unsigned char *pout = (FAR unsigned char *)dest;
FAR unsigned char *pin = (FAR unsigned char *)src;
while (n-- > 0)
FAR char *pout = dest;
FAR const char *pin = src;
FAR long *paligned_out;
FAR const long *paligned_in;

/* If the size is small, or either pin or pout is unaligned,
* then punt into the byte copy loop. This should be rare.
*/

if (!TOO_SMALL(n) && !UNALIGNED(pin, pout))
{
paligned_out = (FAR long *)pout;
paligned_in = (FAR long *)pin;

/* Copy 4X long words at a time if possible. */

while (n >= BIGBLOCKSIZE)
{
*paligned_out++ = *paligned_in++;
*paligned_out++ = *paligned_in++;
*paligned_out++ = *paligned_in++;
*paligned_out++ = *paligned_in++;
n -= BIGBLOCKSIZE;
}

/* Copy one long word at a time if possible. */

while (n >= LITTLEBLOCKSIZE)
{
*paligned_out++ = *paligned_in++;
n -= LITTLEBLOCKSIZE;
}

/* Pick up any residual with a byte copier. */

pout = (FAR char *)paligned_out;
pin = (FAR char *)paligned_in;
}

while (n--)
{
*pout++ = *pin++;
}
Expand Down
8 changes: 1 addition & 7 deletions libs/libc/string/lib_memmove.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,7 @@ FAR void *memmove(FAR void *dest, FAR const void *src, size_t count)

if (dest <= src)
{
tmp = (FAR char *) dest;
s = (FAR char *) src;

while (count--)
{
*tmp++ = *s++;
}
memcpy(dest, src, count);
}
else
{
Expand Down
Loading

0 comments on commit 260d815

Please sign in to comment.