mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-15 07:27:20 +00:00
The direction test inside the loop was not always completely optimized, resulting in a larger than necessary function. This change adds a direction variable that is set out of the loop. Now the function is down to 48 bytes on x86, 32 on ARM and 68 on mips. It's worth noting that other approaches were attempted (including relying on the up and down functions) but they were only slightly beneficial on x86 and cost more on others. Signed-off-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
138 lines
2.3 KiB
C
138 lines
2.3 KiB
C
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
|
/*
|
|
* string function definitions for NOLIBC
|
|
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
|
*/
|
|
|
|
#ifndef _NOLIBC_STRING_H
|
|
#define _NOLIBC_STRING_H
|
|
|
|
#include "std.h"
|
|
|
|
/*
|
|
* As much as possible, please keep functions alphabetically sorted.
|
|
*/
|
|
|
|
static __attribute__((unused))
|
|
int memcmp(const void *s1, const void *s2, size_t n)
|
|
{
|
|
size_t ofs = 0;
|
|
char c1 = 0;
|
|
|
|
while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) {
|
|
ofs++;
|
|
}
|
|
return c1;
|
|
}
|
|
|
|
static __attribute__((unused))
|
|
void *_nolibc_memcpy_up(void *dst, const void *src, size_t len)
|
|
{
|
|
size_t pos = 0;
|
|
|
|
while (pos < len) {
|
|
((char *)dst)[pos] = ((const char *)src)[pos];
|
|
pos++;
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
static __attribute__((unused))
|
|
void *_nolibc_memcpy_down(void *dst, const void *src, size_t len)
|
|
{
|
|
while (len) {
|
|
len--;
|
|
((char *)dst)[len] = ((const char *)src)[len];
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
static __attribute__((unused))
|
|
void *memmove(void *dst, const void *src, size_t len)
|
|
{
|
|
size_t dir, pos;
|
|
|
|
pos = len;
|
|
dir = -1;
|
|
|
|
if (dst < src) {
|
|
pos = -1;
|
|
dir = 1;
|
|
}
|
|
|
|
while (len) {
|
|
pos += dir;
|
|
((char *)dst)[pos] = ((const char *)src)[pos];
|
|
len--;
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
/* must be exported, as it's used by libgcc on ARM */
|
|
__attribute__((weak,unused))
|
|
void *memcpy(void *dst, const void *src, size_t len)
|
|
{
|
|
return _nolibc_memcpy_up(dst, src, len);
|
|
}
|
|
|
|
static __attribute__((unused))
|
|
void *memset(void *dst, int b, size_t len)
|
|
{
|
|
char *p = dst;
|
|
|
|
while (len--)
|
|
*(p++) = b;
|
|
return dst;
|
|
}
|
|
|
|
static __attribute__((unused))
|
|
char *strchr(const char *s, int c)
|
|
{
|
|
while (*s) {
|
|
if (*s == (char)c)
|
|
return (char *)s;
|
|
s++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static __attribute__((unused))
|
|
char *strcpy(char *dst, const char *src)
|
|
{
|
|
char *ret = dst;
|
|
|
|
while ((*dst++ = *src++));
|
|
return ret;
|
|
}
|
|
|
|
/* this function is only used with arguments that are not constants */
|
|
static __attribute__((unused))
|
|
size_t nolibc_strlen(const char *str)
|
|
{
|
|
size_t len;
|
|
|
|
for (len = 0; str[len]; len++);
|
|
return len;
|
|
}
|
|
|
|
#define strlen(str) ({ \
|
|
__builtin_constant_p((str)) ? \
|
|
__builtin_strlen((str)) : \
|
|
nolibc_strlen((str)); \
|
|
})
|
|
|
|
static __attribute__((unused))
|
|
char *strrchr(const char *s, int c)
|
|
{
|
|
const char *ret = NULL;
|
|
|
|
while (*s) {
|
|
if (*s == (char)c)
|
|
ret = s;
|
|
s++;
|
|
}
|
|
return (char *)ret;
|
|
}
|
|
|
|
#endif /* _NOLIBC_STRING_H */
|