string.c: make it 64-bit compatible

Casting a pointer to an int produces warnings with 64-bit targets.
Furthermore, an int is not always the optimal memory element that
can be copied in that case.

Let's use uintptr_t to cast pointers to integers for alignment
determination purposes, and mem_word_t to denote the optimal memory
"word" that can be copied on the platform.

The mem_word_t definition is equivalent to uintptr_t by default.
However, some 32-bit targets such as ARM platforms with the LDRD/STRD
instructions could benefit from word_t being an uint64_t.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2019-05-27 19:26:46 -04:00 committed by Andrew Boie
commit 03170c040c
2 changed files with 31 additions and 11 deletions

View file

@ -45,4 +45,18 @@ typedef int off_t;
typedef int64_t time_t; typedef int64_t time_t;
typedef int32_t suseconds_t; typedef int32_t suseconds_t;
#if !defined(__mem_word_t_defined)
#define __mem_word_t_defined
/*
* The mem_word_t should match the optimal memory access word width
* on the target platform. Here we defaults it to uintptr_t.
*/
typedef uintptr_t mem_word_t;
#define Z_MEM_WORD_T_WIDTH __INTPTR_WIDTH__
#endif
#endif /* ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_SYS_TYPES_H_ */ #endif /* ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_SYS_TYPES_H_ */

View file

@ -7,6 +7,8 @@
*/ */
#include <string.h> #include <string.h>
#include <stdint.h>
#include <sys/types.h>
/** /**
* *
@ -241,12 +243,13 @@ 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;
const uintptr_t mask = sizeof(mem_word_t) - 1;
if ((((unsigned int)d ^ (unsigned int)s_byte) & 0x3) == 0U) { if ((((uintptr_t)d ^ (uintptr_t)s_byte) & mask) == 0) {
/* do byte-sized copying until word-aligned or finished */ /* do byte-sized copying until word-aligned or finished */
while (((unsigned int)d_byte) & 0x3) { while (((uintptr_t)d_byte) & mask) {
if (n == 0) { if (n == 0) {
return d; return d;
} }
@ -256,12 +259,12 @@ void *memcpy(void *_MLIBC_RESTRICT d, const void *_MLIBC_RESTRICT s, size_t n)
/* do word-sized copying as long as possible */ /* do word-sized copying as long as possible */
unsigned int *d_word = (unsigned int *)d_byte; mem_word_t *d_word = (mem_word_t *)d_byte;
const unsigned int *s_word = (const unsigned int *)s_byte; const mem_word_t *s_word = (const mem_word_t *)s_byte;
while (n >= sizeof(unsigned int)) { while (n >= sizeof(mem_word_t)) {
*(d_word++) = *(s_word++); *(d_word++) = *(s_word++);
n -= sizeof(unsigned int); n -= sizeof(mem_word_t);
} }
d_byte = (unsigned char *)d_word; d_byte = (unsigned char *)d_word;
@ -292,7 +295,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;
while (((unsigned int)d_byte) & 0x3) { while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) {
if (n == 0) { if (n == 0) {
return buf; return buf;
} }
@ -302,15 +305,18 @@ void *memset(void *buf, int c, size_t n)
/* do word-sized initialization as long as possible */ /* do word-sized initialization as long as possible */
unsigned int *d_word = (unsigned int *)d_byte; mem_word_t *d_word = (mem_word_t *)d_byte;
unsigned int c_word = (unsigned int)(unsigned char)c; mem_word_t c_word = (mem_word_t)c_byte;
c_word |= c_word << 8; c_word |= c_word << 8;
c_word |= c_word << 16; c_word |= c_word << 16;
#if Z_MEM_WORD_T_WIDTH > 32
c_word |= c_word << 32;
#endif
while (n >= sizeof(unsigned int)) { while (n >= sizeof(mem_word_t)) {
*(d_word++) = c_word; *(d_word++) = c_word;
n -= sizeof(unsigned int); n -= sizeof(mem_word_t);
} }
/* do byte-sized initialization until finished */ /* do byte-sized initialization until finished */