]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/string: Convert memmove() to C
authorHeiko Carstens <hca@linux.ibm.com>
Tue, 9 Jun 2026 10:33:38 +0000 (12:33 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Wed, 10 Jun 2026 14:55:20 +0000 (16:55 +0200)
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 <jchrist@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/lib/mem.S
arch/s390/lib/string.c

index d026debf250c73cba9349b8584b2afd202fe1a3d..712b955ea9b4ab4337b2ae3c2a2304cc7fdc95a7 100644 (file)
 
        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
  *
index a48e5bb3c15f9908b6071535ae273e1ffe3b5c1d..648d5a66484d8aab020703742e54b0c00908dfb3 100644 (file)
 #include <linux/export.h>
 #include <asm/asm.h>
 
+#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
  */