This is an automated email from the ASF dual-hosted git repository. jerpelea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit d1dc791d11363c1366289112d7d3c5b92674d708 Author: Xiang Xiao <[email protected]> AuthorDate: Sun Aug 16 22:54:21 2026 +0800 libs/libc/string: Add 4-byte alignment middle path for BSD functions. libc_data_t is 8 bytes wide, so a buffer which is 4-byte but not 8-byte aligned falls back to the byte at a time loop. Add a 32-bit middle path so such buffers still handle four bytes per iteration. * Add DETECTNULL32/DETECTCHAR32, UNALIGNED4/UNALIGNED4_X, LITTLEBLOCKSIZE4/BIGBLOCKSIZE4 and TOO_SMALL4 to libs/libc/libc.h. * Take the new path in memccpy, memcmp, memcpy, memset, stpcpy, stpncpy, strcmp, strcpy, strncmp and strncpy when both pointers are 4-byte aligned but the 8-byte path can't be used. Assisted-by: Claude:claude-opus-5 Signed-off-by: Xiang Xiao <[email protected]> --- libs/libc/libc.h | 26 +++++++++++++++++- libs/libc/string/lib_bsdmemccpy.c | 55 +++++++++++++++++++++++---------------- libs/libc/string/lib_bsdmemchr.c | 2 -- libs/libc/string/lib_bsdmemcmp.c | 29 +++++++++++++++------ libs/libc/string/lib_bsdmemcpy.c | 35 ++++++++++++++++++++----- libs/libc/string/lib_bsdmemrchr.c | 2 -- libs/libc/string/lib_bsdmemset.c | 45 +++++++++++++++++++++++++------- libs/libc/string/lib_bsdstpcpy.c | 24 ++++++++++------- libs/libc/string/lib_bsdstpncpy.c | 24 +++++++++++------ libs/libc/string/lib_bsdstrcmp.c | 33 ++++++++++++++--------- libs/libc/string/lib_bsdstrcpy.c | 23 ++++++++++------ libs/libc/string/lib_bsdstrncmp.c | 39 +++++++++++++++------------ libs/libc/string/lib_bsdstrncpy.c | 24 +++++++++++------ 13 files changed, 247 insertions(+), 114 deletions(-) diff --git a/libs/libc/libc.h b/libs/libc/libc.h index 3e010bdb9e6..2cc91f5069d 100644 --- a/libs/libc/libc.h +++ b/libs/libc/libc.h @@ -184,6 +184,7 @@ /* How many bytes are copied each iteration of the word copy loop. */ #define LITTLEBLOCKSIZE (sizeof(libc_data_t)) +#define BIGBLOCKSIZE (sizeof(libc_data_t) << 2) /* Threshold for punting to the byte copier. */ @@ -191,7 +192,30 @@ /* Macros for detecting endchar */ -#define DETECTNULL(x) (((x) - 0x0101010101010101LL) & ~(x) & 0x8080808080808080LL) +#define DETECTNULL(x) \ + (((x) - 0x0101010101010101LL) & ~(x) & 0x8080808080808080LL) + +#define DETECTCHAR(x, mask) (DETECTNULL((x) ^ (mask))) + +/* 32-bit helpers for the 4-byte middle path on 64-bit platforms. + * When libc_data_t is 8 bytes, pointers that are 4-byte aligned + * but not 8-byte aligned would otherwise fall back to byte-at-a-time. + */ + +#define DETECTNULL32(x) \ + (((x) - (uint32_t)0x01010101) & ~(x) & (uint32_t)0x80808080) + +#define DETECTCHAR32(x, mask) (DETECTNULL32((x) ^ (mask))) + +#define UNALIGNED4(x, y) \ + ((((uintptr_t)(x)) | ((uintptr_t)(y))) & 3) + +#define UNALIGNED4_X(x) (((uintptr_t)(x)) & 3) + +#define LITTLEBLOCKSIZE4 (sizeof(uint32_t)) +#define BIGBLOCKSIZE4 (sizeof(uint32_t) << 2) + +#define TOO_SMALL4(len) ((len) < LITTLEBLOCKSIZE4) #ifndef __ASSEMBLY__ diff --git a/libs/libc/string/lib_bsdmemccpy.c b/libs/libc/string/lib_bsdmemccpy.c index 406f1ddc408..610c482c400 100644 --- a/libs/libc/string/lib_bsdmemccpy.c +++ b/libs/libc/string/lib_bsdmemccpy.c @@ -56,11 +56,8 @@ #undef memccpy 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 const unsigned char *pin = (FAR const unsigned char *)s2; - FAR libc_data_t *paligned_out; - FAR const libc_data_t *paligned_in; unsigned char endchar = c & 0xff; /* If the size is small, or either pin or pout is unaligned, @@ -69,41 +66,56 @@ FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n) if (!TOO_SMALL(n) && !UNALIGNED(pin, pout)) { - unsigned int i; + FAR libc_data_t *paligned_out = (FAR libc_data_t *)pout; + FAR const libc_data_t *paligned_in = (FAR libc_data_t *)pin; libc_data_t mask = 0; - - paligned_out = (FAR libc_data_t *)pout; - paligned_in = (FAR libc_data_t *)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. - */ + unsigned int i; for (i = 0; i < LITTLEBLOCKSIZE; i++) { mask = (mask << 8) + endchar; } - /* Copy one libc_data_t word at a time if possible. */ - while (n >= LITTLEBLOCKSIZE) { libc_data_t buffer = (libc_data_t)(*paligned_in); buffer ^= mask; if (DETECTNULL(buffer)) { - break; /* endchar is found, go byte by byte from here */ + break; } *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; + } + else if (!TOO_SMALL4(n) && !UNALIGNED4(pin, pout)) + { + FAR uint32_t *paligned_out = (FAR uint32_t *)pout; + FAR const uint32_t *paligned_in = (FAR uint32_t *)pin; + uint32_t mask = 0; + unsigned int i; + + for (i = 0; i < LITTLEBLOCKSIZE4; i++) + { + mask = (mask << 8) + endchar; + } + + while (n >= LITTLEBLOCKSIZE4) + { + uint32_t buffer = *paligned_in; + buffer ^= mask; + if (DETECTNULL32(buffer)) + { + break; + } + + *paligned_out++ = *paligned_in++; + n -= LITTLEBLOCKSIZE4; + } pout = (FAR unsigned char *)paligned_out; pin = (FAR unsigned char *)paligned_in; @@ -113,10 +125,9 @@ FAR void *memccpy(FAR void *s1, FAR const void *s2, int c, size_t n) { if ((*pout++ = *pin++) == endchar) { - ptr = pout; - break; + return pout; } } - return ptr; + return NULL; } diff --git a/libs/libc/string/lib_bsdmemchr.c b/libs/libc/string/lib_bsdmemchr.c index 88ed624fc7b..30db3b0a7c7 100644 --- a/libs/libc/string/lib_bsdmemchr.c +++ b/libs/libc/string/lib_bsdmemchr.c @@ -33,8 +33,6 @@ * Pre-processor Definitions ****************************************************************************/ -#define DETECTCHAR(x, mask) (DETECTNULL((x) ^ (mask))) - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/libs/libc/string/lib_bsdmemcmp.c b/libs/libc/string/lib_bsdmemcmp.c index 5a7a532c936..871b2275aa7 100644 --- a/libs/libc/string/lib_bsdmemcmp.c +++ b/libs/libc/string/lib_bsdmemcmp.c @@ -44,8 +44,6 @@ 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 libc_data_t *a1; - FAR libc_data_t *a2; /* If the size is too small, or either pointer is unaligned, * then we punt to the byte compare loop. Hopefully this will @@ -54,12 +52,9 @@ int memcmp(FAR const void *s1, FAR const void *s2, size_t n) if (!TOO_SMALL(n) && !UNALIGNED(p1, p2)) { - /* Otherwise, load and compare the blocks of memory one - * word at a time. - */ + FAR libc_data_t *a1 = (FAR libc_data_t *)p1; + FAR libc_data_t *a2 = (FAR libc_data_t *)p2; - a1 = (FAR libc_data_t *)p1; - a2 = (FAR libc_data_t *)p2; while (n >= LITTLEBLOCKSIZE) { if (*a1 != *a2) @@ -72,7 +67,25 @@ int memcmp(FAR const void *s1, FAR const void *s2, size_t n) n -= LITTLEBLOCKSIZE; } - /* check s mod LBLOCKSIZE remaining characters */ + p1 = (FAR unsigned char *)a1; + p2 = (FAR unsigned char *)a2; + } + else if (!TOO_SMALL4(n) && !UNALIGNED4(p1, p2)) + { + FAR uint32_t *a1 = (FAR uint32_t *)p1; + FAR uint32_t *a2 = (FAR uint32_t *)p2; + + while (n >= LITTLEBLOCKSIZE4) + { + if (*a1 != *a2) + { + break; + } + + a1++; + a2++; + n -= LITTLEBLOCKSIZE4; + } p1 = (FAR unsigned char *)a1; p2 = (FAR unsigned char *)a2; diff --git a/libs/libc/string/lib_bsdmemcpy.c b/libs/libc/string/lib_bsdmemcpy.c index 6686088f6eb..3950a85f9c0 100644 --- a/libs/libc/string/lib_bsdmemcpy.c +++ b/libs/libc/string/lib_bsdmemcpy.c @@ -33,8 +33,6 @@ * Pre-processor Definitions ****************************************************************************/ -#define BIGBLOCKSIZE (sizeof(libc_data_t) << 2) - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -50,8 +48,6 @@ FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n) { FAR char *pout = dest; FAR const char *pin = src; - FAR libc_data_t *paligned_out; - FAR const libc_data_t *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. @@ -59,8 +55,8 @@ FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n) if (!TOO_SMALL(n) && !UNALIGNED(pin, pout)) { - paligned_out = (FAR libc_data_t *)pout; - paligned_in = (FAR libc_data_t *)pin; + FAR libc_data_t *paligned_out = (FAR libc_data_t *)pout; + FAR const libc_data_t *paligned_in = (FAR libc_data_t *)pin; /* Copy 4X libc_data_t words at a time if possible. */ @@ -81,7 +77,32 @@ FAR void *memcpy(FAR void *dest, FAR const void *src, size_t n) n -= LITTLEBLOCKSIZE; } - /* Pick up any residual with a byte copier. */ + pout = (FAR char *)paligned_out; + pin = (FAR char *)paligned_in; + } + else if (!TOO_SMALL4(n) && !UNALIGNED4(pin, pout)) + { + FAR uint32_t *paligned_out = (FAR uint32_t *)pout; + FAR const uint32_t *paligned_in = (FAR uint32_t *)pin; + + /* Copy 4X uint32_t words at a time if possible. */ + + while (n >= BIGBLOCKSIZE4) + { + *paligned_out++ = *paligned_in++; + *paligned_out++ = *paligned_in++; + *paligned_out++ = *paligned_in++; + *paligned_out++ = *paligned_in++; + n -= BIGBLOCKSIZE4; + } + + /* Copy one uint32_t word at a time if possible. */ + + while (n >= LITTLEBLOCKSIZE4) + { + *paligned_out++ = *paligned_in++; + n -= LITTLEBLOCKSIZE4; + } pout = (FAR char *)paligned_out; pin = (FAR char *)paligned_in; diff --git a/libs/libc/string/lib_bsdmemrchr.c b/libs/libc/string/lib_bsdmemrchr.c index b16651dfcf0..22d8875de97 100644 --- a/libs/libc/string/lib_bsdmemrchr.c +++ b/libs/libc/string/lib_bsdmemrchr.c @@ -33,8 +33,6 @@ * Pre-processor Definitions ****************************************************************************/ -#define DETECTCHAR(x, mask) (DETECTNULL((x) ^ (mask))) - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/libs/libc/string/lib_bsdmemset.c b/libs/libc/string/lib_bsdmemset.c index 1a0b0ecabd2..efdafdea9dd 100644 --- a/libs/libc/string/lib_bsdmemset.c +++ b/libs/libc/string/lib_bsdmemset.c @@ -48,7 +48,6 @@ FAR void *memset(FAR void *m, int c, size_t n) { FAR libc_data_t *aligned_addr; FAR char *s = (FAR char *)m; - unsigned int d = (unsigned char)c; libc_data_t buffer; int i; @@ -66,17 +65,19 @@ FAR void *memset(FAR void *m, int c, size_t n) } } + buffer = (uint8_t)c; + buffer |= (buffer << 8); + buffer |= (buffer << 16); + for (i = 32; i < LITTLEBLOCKSIZE * 8; i <<= 1) + { + buffer = (buffer << i) | buffer; + } + if (!TOO_SMALL(n)) { /* If we get this far, we know that n is large and s is word-aligned. */ aligned_addr = (FAR libc_data_t *)s; - buffer = (d << 8) | d; - buffer |= (buffer << 16); - for (i = 32; i < LITTLEBLOCKSIZE * 8; i <<= 1) - { - buffer = (buffer << i) | buffer; - } /* Unroll the loop. */ @@ -100,9 +101,35 @@ FAR void *memset(FAR void *m, int c, size_t n) s = (FAR char *)aligned_addr; } - while (n--) + /* Tail: here s is libc_data_t-aligned and n < LITTLEBLOCKSIZE. + * Fill with aligned stores of decreasing width - no unaligned access, + * no overlap, no over-write. + */ + + if (LITTLEBLOCKSIZE > 8 && n >= 8) + { + *(FAR uint64_t *)s = (uint64_t)buffer; + s += 8; + n -= 8; + } + + if (n >= 4) + { + *(FAR uint32_t *)s = (uint32_t)buffer; + s += 4; + n -= 4; + } + + if (n >= 2) + { + *(FAR uint16_t *)s = (uint16_t)buffer; + s += 2; + n -= 2; + } + + if (n) { - *s++ = c; + *s = (uint8_t)buffer; } return m; diff --git a/libs/libc/string/lib_bsdstpcpy.c b/libs/libc/string/lib_bsdstpcpy.c index db6a5090841..fbd9687adef 100644 --- a/libs/libc/string/lib_bsdstpcpy.c +++ b/libs/libc/string/lib_bsdstpcpy.c @@ -56,19 +56,12 @@ no_builtin("stpcpy") nosanitize_address FAR char *stpcpy(FAR char *dest, FAR const char *src) { - FAR libc_data_t *aligned_dst; - FAR const libc_data_t *aligned_src; - /* If src or dest is unaligned, then copy bytes. */ if (!UNALIGNED(src, dest)) { - aligned_dst = (FAR libc_data_t *)dest; - aligned_src = (FAR libc_data_t *)src; - - /* src and dest are both "libc_data_t" aligned, try to do "libc_data_t" - * sized copies. - */ + FAR libc_data_t *aligned_dst = (FAR libc_data_t *)dest; + FAR const libc_data_t *aligned_src = (FAR libc_data_t *)src; while (!DETECTNULL(*aligned_src)) { @@ -78,6 +71,19 @@ FAR char *stpcpy(FAR char *dest, FAR const char *src) dest = (FAR char *)aligned_dst; src = (FAR char *)aligned_src; } + else if (!UNALIGNED4(src, dest)) + { + FAR uint32_t *aligned_dst = (FAR uint32_t *)dest; + FAR const uint32_t *aligned_src = (FAR uint32_t *)src; + + while (!DETECTNULL32(*aligned_src)) + { + *aligned_dst++ = *aligned_src++; + } + + dest = (FAR char *)aligned_dst; + src = (FAR char *)aligned_src; + } while ((*dest++ = *src++) != '\0'); diff --git a/libs/libc/string/lib_bsdstpncpy.c b/libs/libc/string/lib_bsdstpncpy.c index c06533a8835..1f8914551d4 100644 --- a/libs/libc/string/lib_bsdstpncpy.c +++ b/libs/libc/string/lib_bsdstpncpy.c @@ -66,19 +66,13 @@ no_builtin("stpncpy") FAR char *stpncpy(FAR char *dest, FAR const char *src, size_t n) { FAR char *ret = NULL; - FAR libc_data_t *aligned_dst; - FAR const libc_data_t *aligned_src; /* If src and dest is aligned and n large enough, then copy words. */ if (!UNALIGNED(src, dest) && !TOO_SMALL(n)) { - aligned_dst = (FAR libc_data_t *)dest; - aligned_src = (FAR libc_data_t *)src; - - /* src and dest are both "libc_data_t" aligned, try to do "libc_data_t" - * sized copies. - */ + FAR libc_data_t *aligned_dst = (FAR libc_data_t *)dest; + FAR const libc_data_t *aligned_src = (FAR libc_data_t *)src; while (n >= LITTLEBLOCKSIZE && !DETECTNULL(*aligned_src)) { @@ -89,6 +83,20 @@ FAR char *stpncpy(FAR char *dest, FAR const char *src, size_t n) dest = (FAR char *)aligned_dst; src = (FAR char *)aligned_src; } + else if (!UNALIGNED4(src, dest) && !TOO_SMALL4(n)) + { + FAR uint32_t *aligned_dst = (FAR uint32_t *)dest; + FAR const uint32_t *aligned_src = (FAR uint32_t *)src; + + while (n >= LITTLEBLOCKSIZE4 && !DETECTNULL32(*aligned_src)) + { + n -= LITTLEBLOCKSIZE4; + *aligned_dst++ = *aligned_src++; + } + + dest = (FAR char *)aligned_dst; + src = (FAR char *)aligned_src; + } while (n > 0) { diff --git a/libs/libc/string/lib_bsdstrcmp.c b/libs/libc/string/lib_bsdstrcmp.c index fb2224e4f41..2ec0fed57cb 100644 --- a/libs/libc/string/lib_bsdstrcmp.c +++ b/libs/libc/string/lib_bsdstrcmp.c @@ -43,23 +43,15 @@ no_builtin("strcmp") nosanitize_address int strcmp(FAR const char *cs, FAR const char *ct) { - FAR libc_data_t *a1; - FAR libc_data_t *a2; - /* If cs or ct are unaligned, then compare bytes. */ if (!UNALIGNED(cs, ct)) { - /* If cs and ct are word-aligned, compare them a word at a time. */ + FAR libc_data_t *a1 = (FAR libc_data_t *)cs; + FAR libc_data_t *a2 = (FAR libc_data_t *)ct; - a1 = (FAR libc_data_t *)cs; - a2 = (FAR libc_data_t *)ct; while (*a1 == *a2) { - /* To get here, *a1 == *a2, thus if we find a null in *a1, - * then the strings must be equal, so return zero. - */ - if (DETECTNULL(*a1)) { return 0; @@ -69,9 +61,24 @@ int strcmp(FAR const char *cs, FAR const char *ct) a2++; } - /* A difference was detected in last few bytes of cs, - * so search bytewise. - */ + cs = (FAR char *)a1; + ct = (FAR char *)a2; + } + else if (!UNALIGNED4(cs, ct)) + { + FAR uint32_t *a1 = (FAR uint32_t *)cs; + FAR uint32_t *a2 = (FAR uint32_t *)ct; + + while (*a1 == *a2) + { + if (DETECTNULL32(*a1)) + { + return 0; + } + + a1++; + a2++; + } cs = (FAR char *)a1; ct = (FAR char *)a2; diff --git a/libs/libc/string/lib_bsdstrcpy.c b/libs/libc/string/lib_bsdstrcpy.c index 439489c1a64..a19e44d4c94 100644 --- a/libs/libc/string/lib_bsdstrcpy.c +++ b/libs/libc/string/lib_bsdstrcpy.c @@ -57,19 +57,13 @@ FAR char *strcpy(FAR char *dest, FAR const char *src) { FAR char *dst0 = dest; FAR const char *src0 = src; - FAR libc_data_t *aligned_dst; - FAR const libc_data_t *aligned_src; /* If SRC or DEST is unaligned, then copy bytes. */ if (!UNALIGNED(src0, dst0)) { - aligned_dst = (FAR libc_data_t *)dst0; - aligned_src = (FAR libc_data_t *)src0; - - /* SRC and DEST are both "libc_data_t" aligned, try to do "libc_data_t" - * sized copies. - */ + FAR libc_data_t *aligned_dst = (FAR libc_data_t *)dst0; + FAR const libc_data_t *aligned_src = (FAR libc_data_t *)src0; while (!DETECTNULL(*aligned_src)) { @@ -79,6 +73,19 @@ FAR char *strcpy(FAR char *dest, FAR const char *src) dst0 = (FAR char *)aligned_dst; src0 = (FAR char *)aligned_src; } + else if (!UNALIGNED4(src0, dst0)) + { + FAR uint32_t *aligned_dst = (FAR uint32_t *)dst0; + FAR const uint32_t *aligned_src = (FAR uint32_t *)src0; + + while (!DETECTNULL32(*aligned_src)) + { + *aligned_dst++ = *aligned_src++; + } + + dst0 = (FAR char *)aligned_dst; + src0 = (FAR char *)aligned_src; + } while ((*dst0++ = *src0++) != '\0'); diff --git a/libs/libc/string/lib_bsdstrncmp.c b/libs/libc/string/lib_bsdstrncmp.c index 747b3b55a22..20f127e1716 100644 --- a/libs/libc/string/lib_bsdstrncmp.c +++ b/libs/libc/string/lib_bsdstrncmp.c @@ -43,9 +43,6 @@ no_builtin("strncmp") nosanitize_address int strncmp(FAR const char *cs, FAR const char *ct, size_t nb) { - FAR libc_data_t *a1; - FAR libc_data_t *a2; - if (nb == 0) { return 0; @@ -55,18 +52,13 @@ int strncmp(FAR const char *cs, FAR const char *ct, size_t nb) if (!UNALIGNED(cs, ct)) { - /* If cs and ct are word-aligned, compare them a word at a time. */ + FAR libc_data_t *a1 = (FAR libc_data_t *)cs; + FAR libc_data_t *a2 = (FAR libc_data_t *)ct; - a1 = (FAR libc_data_t *)cs; - a2 = (FAR libc_data_t *)ct; while (nb >= LITTLEBLOCKSIZE && *a1 == *a2) { nb -= LITTLEBLOCKSIZE; - /* If we've run out of bytes or hit a null, return zero - * since we already know *a1 == *a2. - */ - if (nb == 0 || DETECTNULL(*a1)) { return 0; @@ -76,9 +68,26 @@ int strncmp(FAR const char *cs, FAR const char *ct, size_t nb) a2++; } - /* A difference was detected in last few bytes of cs, so search - * bytewise. - */ + cs = (FAR char *)a1; + ct = (FAR char *)a2; + } + else if (!UNALIGNED4(cs, ct)) + { + FAR uint32_t *a1 = (FAR uint32_t *)cs; + FAR uint32_t *a2 = (FAR uint32_t *)ct; + + while (nb >= LITTLEBLOCKSIZE4 && *a1 == *a2) + { + nb -= LITTLEBLOCKSIZE4; + + if (nb == 0 || DETECTNULL32(*a1)) + { + return 0; + } + + a1++; + a2++; + } cs = (FAR char *)a1; ct = (FAR char *)a2; @@ -86,10 +95,6 @@ int strncmp(FAR const char *cs, FAR const char *ct, size_t nb) while (nb-- > 0 && *cs == *ct) { - /* If we've run out of bytes or hit a null, return zero - * since we already know *cs == *ct. - */ - if (nb == 0 || *cs == '\0') { return 0; diff --git a/libs/libc/string/lib_bsdstrncpy.c b/libs/libc/string/lib_bsdstrncpy.c index adeed181234..79aeca0aba7 100644 --- a/libs/libc/string/lib_bsdstrncpy.c +++ b/libs/libc/string/lib_bsdstrncpy.c @@ -66,19 +66,13 @@ FAR char *strncpy(FAR char *dest, FAR const char *src, size_t n) { FAR char *dst0 = dest; FAR const char *src0 = src; - FAR libc_data_t *aligned_dst; - FAR const libc_data_t *aligned_src; /* If src and dest is aligned and n large enough, then copy words. */ if (!UNALIGNED(src0, dst0) && !TOO_SMALL(n)) { - aligned_dst = (FAR libc_data_t *)dst0; - aligned_src = (FAR libc_data_t *)src0; - - /* src and dest are both "libc_data_t" aligned, try to do "libc_data_t" - * sized copies. - */ + FAR libc_data_t *aligned_dst = (FAR libc_data_t *)dst0; + FAR const libc_data_t *aligned_src = (FAR libc_data_t *)src0; while (n >= LITTLEBLOCKSIZE && !DETECTNULL(*aligned_src)) { @@ -89,6 +83,20 @@ FAR char *strncpy(FAR char *dest, FAR const char *src, size_t n) dst0 = (FAR char *)aligned_dst; src0 = (FAR char *)aligned_src; } + else if (!UNALIGNED4(src0, dst0) && !TOO_SMALL4(n)) + { + FAR uint32_t *aligned_dst = (FAR uint32_t *)dst0; + FAR const uint32_t *aligned_src = (FAR uint32_t *)src0; + + while (n >= LITTLEBLOCKSIZE4 && !DETECTNULL32(*aligned_src)) + { + n -= LITTLEBLOCKSIZE4; + *aligned_dst++ = *aligned_src++; + } + + dst0 = (FAR char *)aligned_dst; + src0 = (FAR char *)aligned_src; + } while (n > 0) {
