summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2022-02-07 19:23:40 +0300
committerPaul E. McKenney <paulmck@kernel.org>2022-04-21 03:05:44 +0300
commitd8dcc2d8d93e5d4263ca9f8c5bdfb713f82fe923 (patch)
tree6c1aefa5cf149f006e4f2f07dd904222915750e2
parent830acd088edc1604ee46916188491ef634441fc6 (diff)
downloadlinux-d8dcc2d8d93e5d4263ca9f8c5bdfb713f82fe923.tar.xz
tools/nolibc/string: use unidirectional variants for memcpy()
Till now memcpy() relies on memmove(), but it's always included for libgcc, so we have a larger than needed function. Let's implement two unidirectional variants to copy from bottom to top and from top to bottom, and use the former for memcpy(). The variants are optimized to be compact, and at the same time the compiler is sometimes able to detect the loop and to replace it with a "rep movsb". The new function is 24 bytes instead of 52 on x86_64. Signed-off-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
-rw-r--r--tools/include/nolibc/string.h24
1 files changed, 23 insertions, 1 deletions
diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h
index 8a23cda2d450..6d8fad7a92e6 100644
--- a/tools/include/nolibc/string.h
+++ b/tools/include/nolibc/string.h
@@ -26,6 +26,28 @@ int memcmp(const void *s1, const void *s2, size_t n)
}
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)
{
ssize_t pos = (dst <= src) ? -1 : (long)len;
@@ -42,7 +64,7 @@ void *memmove(void *dst, const void *src, size_t len)
__attribute__((weak,unused))
void *memcpy(void *dst, const void *src, size_t len)
{
- return memmove(dst, src, len);
+ return _nolibc_memcpy_up(dst, src, len);
}
static __attribute__((unused))