Skip to content
Permalink
Browse files

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>
  • Loading branch information...
Nicolas Pitre authored and andrewboie committed May 27, 2019
1 parent 98627cc commit 03170c040ca6f593ab6b4d49c1f5f9e4e32abb21
Showing with 31 additions and 11 deletions.
  1. +14 −0 lib/libc/minimal/include/sys/types.h
  2. +17 −11 lib/libc/minimal/source/string/string.c
@@ -45,4 +45,18 @@ typedef int off_t;
typedef int64_t time_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_ */
@@ -7,6 +7,8 @@
*/

#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;
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 */

while (((unsigned int)d_byte) & 0x3) {
while (((uintptr_t)d_byte) & mask) {
if (n == 0) {
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 */

unsigned int *d_word = (unsigned int *)d_byte;
const unsigned int *s_word = (const unsigned int *)s_byte;
mem_word_t *d_word = (mem_word_t *)d_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++);
n -= sizeof(unsigned int);
n -= sizeof(mem_word_t);
}

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 c_byte = (unsigned char)c;

while (((unsigned int)d_byte) & 0x3) {
while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) {
if (n == 0) {
return buf;
}
@@ -302,15 +305,18 @@ void *memset(void *buf, int c, size_t n)

/* do word-sized initialization as long as possible */

unsigned int *d_word = (unsigned int *)d_byte;
unsigned int c_word = (unsigned int)(unsigned char)c;
mem_word_t *d_word = (mem_word_t *)d_byte;
mem_word_t c_word = (mem_word_t)c_byte;

c_word |= c_word << 8;
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;
n -= sizeof(unsigned int);
n -= sizeof(mem_word_t);
}

/* do byte-sized initialization until finished */

0 comments on commit 03170c0

Please sign in to comment.
You can’t perform that action at this time.