]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/string: Convert memset() to C
authorHeiko Carstens <hca@linux.ibm.com>
Tue, 9 Jun 2026 10:33:39 +0000 (12:33 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Wed, 10 Jun 2026 14:55:21 +0000 (16:55 +0200)
Convert memset() 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 712b955ea9b4ab4337b2ae3c2a2304cc7fdc95a7..a27b103d7450cfd128e3ce41f4a2da09e0d2baa3 100644 (file)
 
        GEN_BR_THUNK %r14
 
-/*
- * memset implementation
- *
- * This code corresponds to the C construct below. We do distinguish
- * between clearing (c == 0) and setting a memory array (c != 0) simply
- * because nearly all memset invocations in the kernel clear memory and
- * the xc instruction is preferred in such cases.
- *
- * void *memset(void *s, int c, size_t n)
- * {
- *     if (likely(c == 0))
- *             return __builtin_memset(s, 0, n);
- *     return __builtin_memset(s, c, n);
- * }
- */
-SYM_FUNC_START(__memset)
-       ltgr    %r4,%r4
-       jz      .Lmemset_exit
-       ltgr    %r3,%r3
-       jnz     .Lmemset_fill
-       aghi    %r4,-1
-       srlg    %r3,%r4,8
-       ltgr    %r3,%r3
-       lgr     %r1,%r2
-       jz      .Lmemset_clear_remainder
-.Lmemset_clear_loop:
-       xc      0(256,%r1),0(%r1)
-       la      %r1,256(%r1)
-       brctg   %r3,.Lmemset_clear_loop
-.Lmemset_clear_remainder:
-       exrl    %r4,.Lmemset_xc
-.Lmemset_exit:
-       BR_EX   %r14
-.Lmemset_fill:
-       cghi    %r4,1
-       lgr     %r1,%r2
-       je      .Lmemset_fill_exit
-       aghi    %r4,-2
-       srlg    %r5,%r4,8
-       ltgr    %r5,%r5
-       jz      .Lmemset_fill_remainder
-.Lmemset_fill_loop:
-       stc     %r3,0(%r1)
-       mvc     1(255,%r1),0(%r1)
-       la      %r1,256(%r1)
-       brctg   %r5,.Lmemset_fill_loop
-.Lmemset_fill_remainder:
-       stc     %r3,0(%r1)
-       exrl    %r4,.Lmemset_mvc
-       BR_EX   %r14
-.Lmemset_fill_exit:
-       stc     %r3,0(%r1)
-       BR_EX   %r14
-.Lmemset_xc:
-       xc      0(1,%r1),0(%r1)
-.Lmemset_mvc:
-       mvc     1(1,%r1),0(%r1)
-SYM_FUNC_END(__memset)
-EXPORT_SYMBOL(__memset)
-
-SYM_FUNC_ALIAS(memset, __memset)
-EXPORT_SYMBOL(memset)
-
 /*
  * memcpy implementation
  *
index 648d5a66484d8aab020703742e54b0c00908dfb3..f59d67925e772b725b871cd404c74fe1cc25ef0e 100644 (file)
@@ -63,6 +63,67 @@ EXPORT_SYMBOL(__memmove);
 EXPORT_SYMBOL(memmove);
 #endif
 
+#ifdef __HAVE_ARCH_MEMSET
+noinstr void *__memset(void *s, int c, size_t n)
+{
+       char *xs = s;
+
+       if (!n)
+               return s;
+       if (!c) {
+               /* Clear memory */
+               while (n >= 256) {
+                       asm volatile(
+                               "       xc       0(256,%[xs]),0(%[xs])"
+                               :
+                               : [xs] "a" (xs)
+                               : "cc", "memory");
+                       xs += 256;
+                       n -= 256;
+               }
+               if (!n)
+                       return s;
+               asm volatile(
+                       "       exrl    %[n],0f\n"
+                       "       j       1f\n"
+                       "0:     xc      0(1,%[xs]),0(%[xs])\n"
+                       "1:"
+                       :
+                       : [xs] "a" (xs), [n] "a" (n - 1)
+                       : "cc", "memory");
+       } else {
+               /* Fill memory */
+               while (n >= 256) {
+                       *xs = c;
+                       asm volatile(
+                               "       mvc     1(255,%[xs]),0(%[xs])"
+                               :
+                               : [xs] "a" (xs)
+                               : "memory");
+                       xs += 256;
+                       n -= 256;
+               }
+               if (!n)
+                       return s;
+               *xs = c;
+               if (n == 1)
+                       return s;
+               asm volatile(
+                       "       exrl    %[n],0f\n"
+                       "       j       1f\n"
+                       "0:     mvc     1(1,%[xs]),0(%[xs])\n"
+                       "1:"
+                       :
+                       : [xs] "a" (xs), [n] "a" (n - 2)
+                       : "memory");
+       }
+       return s;
+}
+SYMBOL_FUNCTION_ALIAS(memset, __memset);
+EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(memset);
+#endif
+
 /*
  * Helper functions to find the end of a string
  */