mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
s390/string: Convert memset() to C
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>
This commit is contained in:
parent
c3e4b7eb1b
commit
0a8be1f9c7
|
|
@ -11,69 +11,6 @@
|
|||
|
||||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user