libc: minimal: add size optimized string functions

The current implementations of memcpy and memset are optimized for
performance and use a word based loop before the byte based loop.

Add a config option that skips the word based loop. This saves 120
bytes on the Cortex-M0+ which is worthwhile on small apps like a
bootloader.

Enable by default if SIZE_OPTIMIZATIONS is set.

Signed-off-by: Michael Hope <mlhx@google.com>
This commit is contained in:
Michael Hope 2021-06-25 20:17:36 +02:00 committed by Anas Nashif
commit 5d55730cf6
2 changed files with 12 additions and 0 deletions

View file

@ -138,6 +138,13 @@ config MINIMAL_LIBC_LL_PRINTF
Build with long long printf enabled. This will increase the size of Build with long long printf enabled. This will increase the size of
the image. the image.
config MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE
bool "Use size optimized string functions"
default y if SIZE_OPTIMIZATIONS
help
Enable smaller but potentially slower implementations of memcpy and
memset. On the Cortex-M0+ this reduces the total code size by 120 bytes.
endif # MINIMAL_LIBC endif # MINIMAL_LIBC
config STDOUT_CONSOLE config STDOUT_CONSOLE

View file

@ -301,6 +301,8 @@ void *memcpy(void *_MLIBC_RESTRICT d, const void *_MLIBC_RESTRICT s, size_t n)
unsigned char *d_byte = (unsigned char *)d; unsigned char *d_byte = (unsigned char *)d;
const unsigned char *s_byte = (const unsigned char *)s; const unsigned char *s_byte = (const unsigned char *)s;
#if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
const uintptr_t mask = sizeof(mem_word_t) - 1; const uintptr_t mask = sizeof(mem_word_t) - 1;
if ((((uintptr_t)d ^ (uintptr_t)s_byte) & mask) == 0) { if ((((uintptr_t)d ^ (uintptr_t)s_byte) & mask) == 0) {
@ -328,6 +330,7 @@ void *memcpy(void *_MLIBC_RESTRICT d, const void *_MLIBC_RESTRICT s, size_t n)
d_byte = (unsigned char *)d_word; d_byte = (unsigned char *)d_word;
s_byte = (unsigned char *)s_word; s_byte = (unsigned char *)s_word;
} }
#endif
/* do byte-sized copying until finished */ /* do byte-sized copying until finished */
@ -353,6 +356,7 @@ void *memset(void *buf, int c, size_t n)
unsigned char *d_byte = (unsigned char *)buf; unsigned char *d_byte = (unsigned char *)buf;
unsigned char c_byte = (unsigned char)c; unsigned char c_byte = (unsigned char)c;
#if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) { while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) {
if (n == 0) { if (n == 0) {
return buf; return buf;
@ -380,6 +384,7 @@ void *memset(void *buf, int c, size_t n)
/* do byte-sized initialization until finished */ /* do byte-sized initialization until finished */
d_byte = (unsigned char *)d_word; d_byte = (unsigned char *)d_word;
#endif
while (n > 0) { while (n > 0) {
*(d_byte++) = c_byte; *(d_byte++) = c_byte;