mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-24 23:41:23 +01:00

When compiling with -Os option along with -ffreestanding, both GCC and clang will add implicit calls to memcpy() and memset() for stack variables initialized in declaration. The C standard as per Clause 4, the compiler cannot necessarily assume that anything beyond: * float.h * iso646.h * limits.h * stdalign.h * stdarg.h * stdbool.h * stddef.h * stdint.h * stdnoreturn.h * fenv.h * math.h * and the numeric conversion functions of stdlib.h. This patch maps memcpy() and memset() as weak-alias of sbi_memcpy() and sbi_memset() respectively so that implicit calls to memcpy() and memset() will compile properly. Signed-off-by: Anup Patel <anup.patel@wdc.com> Reviewed-by: Dong Du <Dd_nirvana@sjtu.edu.cn> Reviewed-by: Xiang W <wxjstz@126.com>
199 lines
3.2 KiB
C
199 lines
3.2 KiB
C
/*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
|
*
|
|
* Authors:
|
|
* Atish Patra <atish.patra@wdc.com>
|
|
*/
|
|
|
|
/*
|
|
* Simple libc functions. These are not optimized at all and might have some
|
|
* bugs as well. Use any optimized routines from newlib or glibc if required.
|
|
*/
|
|
|
|
#include <sbi/sbi_string.h>
|
|
|
|
/*
|
|
Provides sbi_strcmp for the completeness of supporting string functions.
|
|
it is not recommended to use sbi_strcmp() but use sbi_strncmp instead.
|
|
*/
|
|
int sbi_strcmp(const char *a, const char *b)
|
|
{
|
|
/* search first diff or end of string */
|
|
for (; *a == *b && *a != '\0'; a++, b++)
|
|
;
|
|
|
|
return *a - *b;
|
|
}
|
|
|
|
int sbi_strncmp(const char *a, const char *b, size_t count)
|
|
{
|
|
/* search first diff or end of string */
|
|
for (; count > 0 && *a == *b && *a != '\0'; a++, b++, count--)
|
|
;
|
|
|
|
/* No difference till the end */
|
|
if (!count)
|
|
return 0;
|
|
|
|
return *a - *b;
|
|
}
|
|
|
|
size_t sbi_strlen(const char *str)
|
|
{
|
|
unsigned long ret = 0;
|
|
|
|
while (*str != '\0') {
|
|
ret++;
|
|
str++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
size_t sbi_strnlen(const char *str, size_t count)
|
|
{
|
|
unsigned long ret = 0;
|
|
|
|
while (*str != '\0' && ret < count) {
|
|
ret++;
|
|
str++;
|
|
count--;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
char *sbi_strcpy(char *dest, const char *src)
|
|
{
|
|
char *ret = dest;
|
|
|
|
while (*src != '\0') {
|
|
*dest++ = *src++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
char *sbi_strncpy(char *dest, const char *src, size_t count)
|
|
{
|
|
char *ret = dest;
|
|
|
|
while (count-- && *src != '\0') {
|
|
*dest++ = *src++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
char *sbi_strchr(const char *s, int c)
|
|
{
|
|
while (*s != '\0' && *s != (char)c)
|
|
s++;
|
|
|
|
if (*s == '\0')
|
|
return NULL;
|
|
else
|
|
return (char *)s;
|
|
}
|
|
|
|
char *sbi_strrchr(const char *s, int c)
|
|
{
|
|
const char *last = s + sbi_strlen(s);
|
|
|
|
while (last > s && *last != (char)c)
|
|
last--;
|
|
|
|
if (*last != (char)c)
|
|
return NULL;
|
|
else
|
|
return (char *)last;
|
|
}
|
|
void *sbi_memset(void *s, int c, size_t count)
|
|
{
|
|
char *temp = s;
|
|
|
|
while (count > 0) {
|
|
count--;
|
|
*temp++ = c;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
void *memset(void *s, int c, size_t count) \
|
|
__attribute__((weak, alias("sbi_memset")));
|
|
|
|
void *sbi_memcpy(void *dest, const void *src, size_t count)
|
|
{
|
|
char *temp1 = dest;
|
|
const char *temp2 = src;
|
|
|
|
while (count > 0) {
|
|
*temp1++ = *temp2++;
|
|
count--;
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
void *memcpy(void *dest, const void *src, size_t count) \
|
|
__attribute__((weak, alias("sbi_memcpy")));
|
|
|
|
void *sbi_memmove(void *dest, const void *src, size_t count)
|
|
{
|
|
char *temp1 = (char *)dest;
|
|
const char *temp2 = (char *)src;
|
|
|
|
if (src == dest)
|
|
return dest;
|
|
|
|
if (dest < src) {
|
|
while (count > 0) {
|
|
*temp1++ = *temp2++;
|
|
count--;
|
|
}
|
|
} else {
|
|
temp1 = dest + count - 1;
|
|
temp2 = src + count - 1;
|
|
|
|
while (count > 0) {
|
|
*temp1-- = *temp2--;
|
|
count--;
|
|
}
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
int sbi_memcmp(const void *s1, const void *s2, size_t count)
|
|
{
|
|
const char *temp1 = s1;
|
|
const char *temp2 = s2;
|
|
|
|
for (; count > 0 && (*temp1 == *temp2); count--) {
|
|
temp1++;
|
|
temp2++;
|
|
}
|
|
|
|
if (count > 0)
|
|
return *(unsigned char *)temp1 - *(unsigned char *)temp2;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void *sbi_memchr(const void *s, int c, size_t count)
|
|
{
|
|
const unsigned char *temp = s;
|
|
|
|
while (count > 0) {
|
|
if ((unsigned char)c == *temp++) {
|
|
return (void *)(temp - 1);
|
|
}
|
|
count--;
|
|
}
|
|
|
|
return NULL;
|
|
}
|