GNU Linux-libre 4.19.245-gnu1
[releases.git] / arch / s390 / lib / mem.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * String handling functions.
4  *
5  * Copyright IBM Corp. 2012
6  */
7
8 #include <linux/linkage.h>
9 #include <asm/export.h>
10 #include <asm/nospec-insn.h>
11
12         GEN_BR_THUNK %r14
13
14 /*
15  * void *memmove(void *dest, const void *src, size_t n)
16  */
17 ENTRY(memmove)
18         ltgr    %r4,%r4
19         lgr     %r1,%r2
20         jz      .Lmemmove_exit
21         aghi    %r4,-1
22         clgr    %r2,%r3
23         jnh     .Lmemmove_forward
24         la      %r5,1(%r4,%r3)
25         clgr    %r2,%r5
26         jl      .Lmemmove_reverse
27 .Lmemmove_forward:
28         srlg    %r0,%r4,8
29         ltgr    %r0,%r0
30         jz      .Lmemmove_forward_remainder
31 .Lmemmove_forward_loop:
32         mvc     0(256,%r1),0(%r3)
33         la      %r1,256(%r1)
34         la      %r3,256(%r3)
35         brctg   %r0,.Lmemmove_forward_loop
36 .Lmemmove_forward_remainder:
37         larl    %r5,.Lmemmove_mvc
38         ex      %r4,0(%r5)
39 .Lmemmove_exit:
40         BR_EX   %r14
41 .Lmemmove_reverse:
42         ic      %r0,0(%r4,%r3)
43         stc     %r0,0(%r4,%r1)
44         brctg   %r4,.Lmemmove_reverse
45         ic      %r0,0(%r4,%r3)
46         stc     %r0,0(%r4,%r1)
47         BR_EX   %r14
48 .Lmemmove_mvc:
49         mvc     0(1,%r1),0(%r3)
50 EXPORT_SYMBOL(memmove)
51
52 /*
53  * memset implementation
54  *
55  * This code corresponds to the C construct below. We do distinguish
56  * between clearing (c == 0) and setting a memory array (c != 0) simply
57  * because nearly all memset invocations in the kernel clear memory and
58  * the xc instruction is preferred in such cases.
59  *
60  * void *memset(void *s, int c, size_t n)
61  * {
62  *      if (likely(c == 0))
63  *              return __builtin_memset(s, 0, n);
64  *      return __builtin_memset(s, c, n);
65  * }
66  */
67 ENTRY(memset)
68         ltgr    %r4,%r4
69         jz      .Lmemset_exit
70         ltgr    %r3,%r3
71         jnz     .Lmemset_fill
72         aghi    %r4,-1
73         srlg    %r3,%r4,8
74         ltgr    %r3,%r3
75         lgr     %r1,%r2
76         jz      .Lmemset_clear_remainder
77 .Lmemset_clear_loop:
78         xc      0(256,%r1),0(%r1)
79         la      %r1,256(%r1)
80         brctg   %r3,.Lmemset_clear_loop
81 .Lmemset_clear_remainder:
82         larl    %r3,.Lmemset_xc
83         ex      %r4,0(%r3)
84 .Lmemset_exit:
85         BR_EX   %r14
86 .Lmemset_fill:
87         cghi    %r4,1
88         lgr     %r1,%r2
89         je      .Lmemset_fill_exit
90         aghi    %r4,-2
91         srlg    %r5,%r4,8
92         ltgr    %r5,%r5
93         jz      .Lmemset_fill_remainder
94 .Lmemset_fill_loop:
95         stc     %r3,0(%r1)
96         mvc     1(255,%r1),0(%r1)
97         la      %r1,256(%r1)
98         brctg   %r5,.Lmemset_fill_loop
99 .Lmemset_fill_remainder:
100         stc     %r3,0(%r1)
101         larl    %r5,.Lmemset_mvc
102         ex      %r4,0(%r5)
103         BR_EX   %r14
104 .Lmemset_fill_exit:
105         stc     %r3,0(%r1)
106         BR_EX   %r14
107 .Lmemset_xc:
108         xc      0(1,%r1),0(%r1)
109 .Lmemset_mvc:
110         mvc     1(1,%r1),0(%r1)
111 EXPORT_SYMBOL(memset)
112
113 /*
114  * memcpy implementation
115  *
116  * void *memcpy(void *dest, const void *src, size_t n)
117  */
118 ENTRY(memcpy)
119         ltgr    %r4,%r4
120         jz      .Lmemcpy_exit
121         aghi    %r4,-1
122         srlg    %r5,%r4,8
123         ltgr    %r5,%r5
124         lgr     %r1,%r2
125         jnz     .Lmemcpy_loop
126 .Lmemcpy_remainder:
127         larl    %r5,.Lmemcpy_mvc
128         ex      %r4,0(%r5)
129 .Lmemcpy_exit:
130         BR_EX   %r14
131 .Lmemcpy_loop:
132         mvc     0(256,%r1),0(%r3)
133         la      %r1,256(%r1)
134         la      %r3,256(%r3)
135         brctg   %r5,.Lmemcpy_loop
136         j       .Lmemcpy_remainder
137 .Lmemcpy_mvc:
138         mvc     0(1,%r1),0(%r3)
139 EXPORT_SYMBOL(memcpy)
140
141 /*
142  * __memset16/32/64
143  *
144  * void *__memset16(uint16_t *s, uint16_t v, size_t count)
145  * void *__memset32(uint32_t *s, uint32_t v, size_t count)
146  * void *__memset64(uint64_t *s, uint64_t v, size_t count)
147  */
148 .macro __MEMSET bits,bytes,insn
149 ENTRY(__memset\bits)
150         ltgr    %r4,%r4
151         jz      .L__memset_exit\bits
152         cghi    %r4,\bytes
153         je      .L__memset_store\bits
154         aghi    %r4,-(\bytes+1)
155         srlg    %r5,%r4,8
156         ltgr    %r5,%r5
157         lgr     %r1,%r2
158         jz      .L__memset_remainder\bits
159 .L__memset_loop\bits:
160         \insn   %r3,0(%r1)
161         mvc     \bytes(256-\bytes,%r1),0(%r1)
162         la      %r1,256(%r1)
163         brctg   %r5,.L__memset_loop\bits
164 .L__memset_remainder\bits:
165         \insn   %r3,0(%r1)
166         larl    %r5,.L__memset_mvc\bits
167         ex      %r4,0(%r5)
168         BR_EX   %r14
169 .L__memset_store\bits:
170         \insn   %r3,0(%r2)
171 .L__memset_exit\bits:
172         BR_EX   %r14
173 .L__memset_mvc\bits:
174         mvc     \bytes(1,%r1),0(%r1)
175 .endm
176
177 __MEMSET 16,2,sth
178 EXPORT_SYMBOL(__memset16)
179
180 __MEMSET 32,4,st
181 EXPORT_SYMBOL(__memset32)
182
183 __MEMSET 64,8,stg
184 EXPORT_SYMBOL(__memset64)