From c3e4b7eb1b981712ebd128825d4ef3b4e9e0ee8b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 9 Jun 2026 12:33:38 +0200 Subject: [PATCH] s390/string: Convert memmove() to C Convert memmove() from assembler to C, which should make it easier to read and change, if required. And it allows the compiler to optimize the code, and use different instructions, except for the used inline assemblies. Reviewed-by: Juergen Christ Signed-off-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/lib/mem.S | 41 ------------------------------------- arch/s390/lib/string.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/arch/s390/lib/mem.S b/arch/s390/lib/mem.S index d026debf250c..712b955ea9b4 100644 --- a/arch/s390/lib/mem.S +++ b/arch/s390/lib/mem.S @@ -11,47 +11,6 @@ GEN_BR_THUNK %r14 -/* - * void *memmove(void *dest, const void *src, size_t n) - */ -SYM_FUNC_START(__memmove) - ltgr %r4,%r4 - lgr %r1,%r2 - jz .Lmemmove_exit - aghi %r4,-1 - clgr %r2,%r3 - jnh .Lmemmove_forward - la %r5,1(%r4,%r3) - clgr %r2,%r5 - jl .Lmemmove_reverse -.Lmemmove_forward: - srlg %r0,%r4,8 - ltgr %r0,%r0 - jz .Lmemmove_forward_remainder -.Lmemmove_forward_loop: - mvc 0(256,%r1),0(%r3) - la %r1,256(%r1) - la %r3,256(%r3) - brctg %r0,.Lmemmove_forward_loop -.Lmemmove_forward_remainder: - exrl %r4,.Lmemmove_mvc -.Lmemmove_exit: - BR_EX %r14 -.Lmemmove_reverse: - ic %r0,0(%r4,%r3) - stc %r0,0(%r4,%r1) - brctg %r4,.Lmemmove_reverse - ic %r0,0(%r4,%r3) - stc %r0,0(%r4,%r1) - BR_EX %r14 -.Lmemmove_mvc: - mvc 0(1,%r1),0(%r3) -SYM_FUNC_END(__memmove) -EXPORT_SYMBOL(__memmove) - -SYM_FUNC_ALIAS(memmove, __memmove) -EXPORT_SYMBOL(memmove) - /* * memset implementation * diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index a48e5bb3c15f..648d5a66484d 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c @@ -17,6 +17,52 @@ #include #include +#define SYMBOL_FUNCTION_ALIAS(alias, name) \ +asm(".globl " __stringify(alias) "\n\t" \ + ".set " __stringify(alias) "," __stringify(name)) + +#ifdef __HAVE_ARCH_MEMMOVE +noinstr void *__memmove(void *dest, const void *src, size_t n) +{ + const char *s = src; + char *d = dest; + + if (!n) + return dest; + if ((d <= s || d >= s + n)) { + /* Forward copy */ + while (n >= 256) { + asm volatile( + " mvc 0(256,%[d]),0(%[s])\n" + : + : [d] "a" (d), [s] "a" (s) + : "memory"); + d += 256; + s += 256; + n -= 256; + } + if (n) { + asm volatile( + " exrl %[n],0f\n" + " j 1f\n" + "0: mvc 0(1,%[d]),0(%[s])\n" + "1:" + : + : [d] "a" (d), [s] "a" (s), [n] "a" (n - 1) + : "memory"); + } + } else { + /* Backward copy */ + while (n--) + d[n] = s[n]; + } + return dest; +} +SYMBOL_FUNCTION_ALIAS(memmove, __memmove); +EXPORT_SYMBOL(__memmove); +EXPORT_SYMBOL(memmove); +#endif + /* * Helper functions to find the end of a string */