GNU Linux-libre 4.19.264-gnu1
[releases.git] / arch / sparc / lib / csum_copy.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* csum_copy.S: Checksum+copy code for sparc64
3  *
4  * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
5  */
6
7 #include <asm/export.h>
8
9 #ifdef __KERNEL__
10 #define GLOBAL_SPARE    %g7
11 #else
12 #define GLOBAL_SPARE    %g5
13 #endif
14
15 #ifndef EX_LD
16 #define EX_LD(x)        x
17 #endif
18
19 #ifndef EX_ST
20 #define EX_ST(x)        x
21 #endif
22
23 #ifndef EX_RETVAL
24 #define EX_RETVAL(x)    x
25 #endif
26
27 #ifndef LOAD
28 #define LOAD(type,addr,dest)    type [addr], dest
29 #endif
30
31 #ifndef STORE
32 #define STORE(type,src,addr)    type src, [addr]
33 #endif
34
35 #ifndef FUNC_NAME
36 #define FUNC_NAME       csum_partial_copy_nocheck
37 #endif
38
39         .register       %g2, #scratch
40         .register       %g3, #scratch
41
42         .text
43
44 90:
45         /* We checked for zero length already, so there must be
46          * at least one byte.
47          */
48         be,pt           %icc, 1f
49          nop
50         EX_LD(LOAD(ldub, %o0 + 0x00, %o4))
51         add             %o0, 1, %o0
52         sub             %o2, 1, %o2
53         EX_ST(STORE(stb, %o4, %o1 + 0x00))
54         add             %o1, 1, %o1
55 1:      andcc           %o0, 0x2, %g0
56         be,pn           %icc, 80f
57          cmp            %o2, 2
58         blu,pn          %icc, 60f
59          nop
60         EX_LD(LOAD(lduh, %o0 + 0x00, %o5))
61         add             %o0, 2, %o0
62         sub             %o2, 2, %o2
63         EX_ST(STORE(sth, %o5, %o1 + 0x00))
64         add             %o1, 2, %o1
65         ba,pt           %xcc, 80f
66          add            %o5, %o4, %o4
67
68         .globl          FUNC_NAME
69         .type           FUNC_NAME,#function
70         EXPORT_SYMBOL(FUNC_NAME)
71 FUNC_NAME:              /* %o0=src, %o1=dst, %o2=len, %o3=sum */
72         LOAD(prefetch, %o0 + 0x000, #n_reads)
73         xor             %o0, %o1, %g1
74         clr             %o4
75         andcc           %g1, 0x3, %g0
76         bne,pn          %icc, 95f
77          LOAD(prefetch, %o0 + 0x040, #n_reads)
78         
79         brz,pn          %o2, 70f
80          andcc          %o0, 0x3, %g0
81
82         /* We "remember" whether the lowest bit in the address
83          * was set in GLOBAL_SPARE.  Because if it is, we have to swap
84          * upper and lower 8 bit fields of the sum we calculate.
85         */
86         bne,pn          %icc, 90b
87          andcc          %o0, 0x1, GLOBAL_SPARE
88
89 80:
90         LOAD(prefetch, %o0 + 0x080, #n_reads)
91         andncc          %o2, 0x3f, %g3
92
93         LOAD(prefetch, %o0 + 0x0c0, #n_reads)
94         sub             %o2, %g3, %o2
95         brz,pn          %g3, 2f
96          LOAD(prefetch, %o0 + 0x100, #n_reads)
97
98         /* So that we don't need to use the non-pairing
99          * add-with-carry instructions we accumulate 32-bit
100          * values into a 64-bit register.  At the end of the
101          * loop we fold it down to 32-bits and so on.
102          */
103         ba,pt           %xcc, 1f
104         LOAD(prefetch, %o0 + 0x140, #n_reads)
105
106         .align          32
107 1:      EX_LD(LOAD(lduw, %o0 + 0x00, %o5))
108         EX_LD(LOAD(lduw, %o0 + 0x04, %g1))
109         EX_LD(LOAD(lduw, %o0 + 0x08, %g2))
110         add             %o4, %o5, %o4
111         EX_ST(STORE(stw, %o5, %o1 + 0x00))
112         EX_LD(LOAD(lduw, %o0 + 0x0c, %o5))
113         add             %o4, %g1, %o4
114         EX_ST(STORE(stw, %g1, %o1 + 0x04))
115         EX_LD(LOAD(lduw, %o0 + 0x10, %g1))
116         add             %o4, %g2, %o4
117         EX_ST(STORE(stw, %g2, %o1 + 0x08))
118         EX_LD(LOAD(lduw, %o0 + 0x14, %g2))
119         add             %o4, %o5, %o4
120         EX_ST(STORE(stw, %o5, %o1 + 0x0c))
121         EX_LD(LOAD(lduw, %o0 + 0x18, %o5))
122         add             %o4, %g1, %o4
123         EX_ST(STORE(stw, %g1, %o1 + 0x10))
124         EX_LD(LOAD(lduw, %o0 + 0x1c, %g1))
125         add             %o4, %g2, %o4
126         EX_ST(STORE(stw, %g2, %o1 + 0x14))
127         EX_LD(LOAD(lduw, %o0 + 0x20, %g2))
128         add             %o4, %o5, %o4
129         EX_ST(STORE(stw, %o5, %o1 + 0x18))
130         EX_LD(LOAD(lduw, %o0 + 0x24, %o5))
131         add             %o4, %g1, %o4
132         EX_ST(STORE(stw, %g1, %o1 + 0x1c))
133         EX_LD(LOAD(lduw, %o0 + 0x28, %g1))
134         add             %o4, %g2, %o4
135         EX_ST(STORE(stw, %g2, %o1 + 0x20))
136         EX_LD(LOAD(lduw, %o0 + 0x2c, %g2))
137         add             %o4, %o5, %o4
138         EX_ST(STORE(stw, %o5, %o1 + 0x24))
139         EX_LD(LOAD(lduw, %o0 + 0x30, %o5))
140         add             %o4, %g1, %o4
141         EX_ST(STORE(stw, %g1, %o1 + 0x28))
142         EX_LD(LOAD(lduw, %o0 + 0x34, %g1))
143         add             %o4, %g2, %o4
144         EX_ST(STORE(stw, %g2, %o1 + 0x2c))
145         EX_LD(LOAD(lduw, %o0 + 0x38, %g2))
146         add             %o4, %o5, %o4
147         EX_ST(STORE(stw, %o5, %o1 + 0x30))
148         EX_LD(LOAD(lduw, %o0 + 0x3c, %o5))
149         add             %o4, %g1, %o4
150         EX_ST(STORE(stw, %g1, %o1 + 0x34))
151         LOAD(prefetch, %o0 + 0x180, #n_reads)
152         add             %o4, %g2, %o4
153         EX_ST(STORE(stw, %g2, %o1 + 0x38))
154         subcc           %g3, 0x40, %g3
155         add             %o0, 0x40, %o0
156         add             %o4, %o5, %o4
157         EX_ST(STORE(stw, %o5, %o1 + 0x3c))
158         bne,pt          %icc, 1b
159          add            %o1, 0x40, %o1
160
161 2:      and             %o2, 0x3c, %g3
162         brz,pn          %g3, 2f
163          sub            %o2, %g3, %o2
164 1:      EX_LD(LOAD(lduw, %o0 + 0x00, %o5))
165         subcc           %g3, 0x4, %g3
166         add             %o0, 0x4, %o0
167         add             %o4, %o5, %o4
168         EX_ST(STORE(stw, %o5, %o1 + 0x00))
169         bne,pt          %icc, 1b
170          add            %o1, 0x4, %o1
171
172 2:
173         /* fold 64-->32 */
174         srlx            %o4, 32, %o5
175         srl             %o4, 0, %o4
176         add             %o4, %o5, %o4
177         srlx            %o4, 32, %o5
178         srl             %o4, 0, %o4
179         add             %o4, %o5, %o4
180
181         /* fold 32-->16 */
182         sethi           %hi(0xffff0000), %g1
183         srl             %o4, 16, %o5
184         andn            %o4, %g1, %g2
185         add             %o5, %g2, %o4
186         srl             %o4, 16, %o5
187         andn            %o4, %g1, %g2
188         add             %o5, %g2, %o4
189
190 60:
191         /* %o4 has the 16-bit sum we have calculated so-far.  */
192         cmp             %o2, 2
193         blu,pt          %icc, 1f
194          nop
195         EX_LD(LOAD(lduh, %o0 + 0x00, %o5))
196         sub             %o2, 2, %o2
197         add             %o0, 2, %o0
198         add             %o4, %o5, %o4
199         EX_ST(STORE(sth, %o5, %o1 + 0x00))
200         add             %o1, 0x2, %o1
201 1:      brz,pt          %o2, 1f
202          nop
203         EX_LD(LOAD(ldub, %o0 + 0x00, %o5))
204         sub             %o2, 1, %o2
205         add             %o0, 1, %o0
206         EX_ST(STORE(stb, %o5, %o1 + 0x00))
207         sllx            %o5, 8, %o5
208         add             %o1, 1, %o1
209         add             %o4, %o5, %o4
210 1:
211         /* fold 32-->16 */
212         sethi           %hi(0xffff0000), %g1
213         srl             %o4, 16, %o5
214         andn            %o4, %g1, %g2
215         add             %o5, %g2, %o4
216         srl             %o4, 16, %o5
217         andn            %o4, %g1, %g2
218         add             %o5, %g2, %o4
219
220 1:      brz,pt          GLOBAL_SPARE, 1f
221          nop
222
223         /* We started with an odd byte, byte-swap the result.  */
224         srl             %o4, 8, %o5
225         and             %o4, 0xff, %g1
226         sll             %g1, 8, %g1
227         or              %o5, %g1, %o4
228
229 1:      addcc           %o3, %o4, %o3
230         addc            %g0, %o3, %o3
231
232 70:
233         retl
234          srl            %o3, 0, %o0
235
236 95:     mov             0, GLOBAL_SPARE
237         brlez,pn        %o2, 4f
238          andcc          %o0, 1, %o5             
239         be,a,pt         %icc, 1f
240          srl            %o2, 1, %g1             
241         sub             %o2, 1, %o2     
242         EX_LD(LOAD(ldub, %o0, GLOBAL_SPARE))
243         add             %o0, 1, %o0     
244         EX_ST(STORE(stb, GLOBAL_SPARE, %o1))
245         srl             %o2, 1, %g1
246         add             %o1, 1, %o1
247 1:      brz,a,pn        %g1, 3f
248          andcc          %o2, 1, %g0
249         andcc           %o0, 2, %g0     
250         be,a,pt         %icc, 1f
251          srl            %g1, 1, %g1
252         EX_LD(LOAD(lduh, %o0, %o4))
253         sub             %o2, 2, %o2     
254         srl             %o4, 8, %g2
255         sub             %g1, 1, %g1     
256         EX_ST(STORE(stb, %g2, %o1))
257         add             %o4, GLOBAL_SPARE, GLOBAL_SPARE
258         EX_ST(STORE(stb, %o4, %o1 + 1))
259         add             %o0, 2, %o0     
260         srl             %g1, 1, %g1
261         add             %o1, 2, %o1
262 1:      brz,a,pn        %g1, 2f         
263          andcc          %o2, 2, %g0
264         EX_LD(LOAD(lduw, %o0, %o4))
265 5:      srl             %o4, 24, %g2
266         srl             %o4, 16, %g3
267         EX_ST(STORE(stb, %g2, %o1))
268         srl             %o4, 8, %g2
269         EX_ST(STORE(stb, %g3, %o1 + 1))
270         add             %o0, 4, %o0
271         EX_ST(STORE(stb, %g2, %o1 + 2))
272         addcc           %o4, GLOBAL_SPARE, GLOBAL_SPARE
273         EX_ST(STORE(stb, %o4, %o1 + 3))
274         addc            GLOBAL_SPARE, %g0, GLOBAL_SPARE
275         add             %o1, 4, %o1
276         subcc           %g1, 1, %g1
277         bne,a,pt        %icc, 5b
278          EX_LD(LOAD(lduw, %o0, %o4))
279         sll             GLOBAL_SPARE, 16, %g2
280         srl             GLOBAL_SPARE, 16, GLOBAL_SPARE
281         srl             %g2, 16, %g2
282         andcc           %o2, 2, %g0
283         add             %g2, GLOBAL_SPARE, GLOBAL_SPARE 
284 2:      be,a,pt         %icc, 3f                
285          andcc          %o2, 1, %g0
286         EX_LD(LOAD(lduh, %o0, %o4))
287         andcc           %o2, 1, %g0
288         srl             %o4, 8, %g2
289         add             %o0, 2, %o0     
290         EX_ST(STORE(stb, %g2, %o1))
291         add             GLOBAL_SPARE, %o4, GLOBAL_SPARE
292         EX_ST(STORE(stb, %o4, %o1 + 1))
293         add             %o1, 2, %o1
294 3:      be,a,pt         %icc, 1f                
295          sll            GLOBAL_SPARE, 16, %o4
296         EX_LD(LOAD(ldub, %o0, %g2))
297         sll             %g2, 8, %o4     
298         EX_ST(STORE(stb, %g2, %o1))
299         add             GLOBAL_SPARE, %o4, GLOBAL_SPARE
300         sll             GLOBAL_SPARE, 16, %o4
301 1:      addcc           %o4, GLOBAL_SPARE, GLOBAL_SPARE
302         srl             GLOBAL_SPARE, 16, %o4
303         addc            %g0, %o4, GLOBAL_SPARE
304         brz,pt          %o5, 4f
305          srl            GLOBAL_SPARE, 8, %o4
306         and             GLOBAL_SPARE, 0xff, %g2
307         and             %o4, 0xff, %o4
308         sll             %g2, 8, %g2
309         or              %g2, %o4, GLOBAL_SPARE
310 4:      addcc           %o3, GLOBAL_SPARE, %o3
311         addc            %g0, %o3, %o0
312         retl
313          srl            %o0, 0, %o0
314         .size           FUNC_NAME, .-FUNC_NAME