Merge tag 'drivers-5.10-2020-10-12' of git://git.kernel.dk/linux-block
[linux-2.6-block.git] / arch / c6x / lib / csum_64plus.S
1 ; SPDX-License-Identifier: GPL-2.0-only
2 ;
3 ;  linux/arch/c6x/lib/csum_64plus.s
4 ;
5 ;  Port on Texas Instruments TMS320C6x architecture
6 ;
7 ;  Copyright (C) 2006, 2009, 2010, 2011 Texas Instruments Incorporated
8 ;  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
9 ;
10 #include <linux/linkage.h>
11
12 ;
13 ;unsigned int csum_partial_copy_nocheck(const char *src, char * dst,
14 ;                                       int len, int sum)
15 ;
16 ; A4:   src
17 ; B4:   dst
18 ; A6:   len
19 ; B6:   sum
20 ; return csum in A4
21 ;
22
23         .text
24 ENTRY(csum_partial_copy_nocheck)
25         MVC     .S2     ILC,B30
26
27         ZERO    .D1     A9              ; csum (a side)
28 ||      ZERO    .D2     B9              ; csum (b side)
29 ||      SHRU    .S2X    A6,2,B5         ; len / 4
30
31         ;; Check alignment and size
32         AND     .S1     3,A4,A1
33 ||      AND     .S2     3,B4,B0
34         OR      .L2X    B0,A1,B0        ; non aligned condition
35 ||      MVC     .S2     B5,ILC
36 ||      MVK     .D2     1,B2
37 ||      MV      .D1X    B5,A1           ; words condition
38   [!A1] B       .S1     L8
39    [B0] BNOP    .S1     L6,5
40
41         SPLOOP          1
42
43         ;; Main loop for aligned words
44         LDW     .D1T1   *A4++,A7
45         NOP     4
46         MV      .S2X    A7,B7
47 ||      EXTU    .S1     A7,0,16,A16
48         STW     .D2T2   B7,*B4++
49 ||      MPYU    .M2     B7,B2,B8
50 ||      ADD     .L1     A16,A9,A9
51         NOP
52         SPKERNEL        8,0
53 ||      ADD     .L2     B8,B9,B9
54
55         ZERO    .D1     A1
56 ||      ADD     .L1X    A9,B9,A9        ;  add csum from a and b sides
57
58 L6:
59   [!A1] BNOP    .S1     L8,5
60
61         ;; Main loop for non-aligned words
62         SPLOOP          2
63  ||     MVK     .L1     1,A2
64
65         LDNW    .D1T1   *A4++,A7
66         NOP             3
67
68         NOP
69         MV      .S2X    A7,B7
70  ||     EXTU    .S1     A7,0,16,A16
71  ||     MPYU    .M1     A7,A2,A8
72
73         ADD     .L1     A16,A9,A9
74         SPKERNEL        6,0
75  ||     STNW    .D2T2   B7,*B4++
76  ||     ADD     .L1     A8,A9,A9
77
78 L8:     AND     .S2X    2,A6,B5
79         CMPGT   .L2     B5,0,B0
80   [!B0] BNOP    .S1     L82,4
81
82         ;; Manage half-word
83         ZERO    .L1     A7
84 ||      ZERO    .D1     A8
85
86 #ifdef CONFIG_CPU_BIG_ENDIAN
87
88         LDBU    .D1T1   *A4++,A7
89         LDBU    .D1T1   *A4++,A8
90         NOP             3
91         SHL     .S1     A7,8,A0
92         ADD     .S1     A8,A9,A9
93         STB     .D2T1   A7,*B4++
94 ||      ADD     .S1     A0,A9,A9
95         STB     .D2T1   A8,*B4++
96
97 #else
98
99         LDBU    .D1T1   *A4++,A7
100         LDBU    .D1T1   *A4++,A8
101         NOP             3
102         ADD     .S1     A7,A9,A9
103         SHL     .S1     A8,8,A0
104
105         STB     .D2T1   A7,*B4++
106 ||      ADD     .S1     A0,A9,A9
107         STB     .D2T1   A8,*B4++
108
109 #endif
110
111         ;; Manage eventually the last byte
112 L82:    AND     .S2X    1,A6,B0
113   [!B0] BNOP    .S1     L9,5
114
115 ||      ZERO    .L1     A7
116
117 L83:    LDBU    .D1T1   *A4++,A7
118         NOP             4
119
120         MV      .L2X    A7,B7
121
122 #ifdef CONFIG_CPU_BIG_ENDIAN
123
124         STB     .D2T2   B7,*B4++
125 ||      SHL     .S1     A7,8,A7
126         ADD     .S1     A7,A9,A9
127
128 #else
129
130         STB     .D2T2   B7,*B4++
131 ||      ADD     .S1     A7,A9,A9
132
133 #endif
134
135         ;; Fold the csum
136 L9:     SHRU    .S2X    A9,16,B0
137   [!B0] BNOP    .S1     L10,5
138
139 L91:    SHRU    .S2X    A9,16,B4
140 ||      EXTU    .S1     A9,16,16,A3
141         ADD     .D1X    A3,B4,A9
142
143         SHRU    .S1     A9,16,A0
144    [A0] BNOP    .S1     L91,5
145
146 L10:    MV      .D1     A9,A4
147
148         BNOP    .S2     B3,4
149         MVC     .S2     B30,ILC
150 ENDPROC(csum_partial_copy_nocheck)
151
152 ;
153 ;unsigned short
154 ;ip_fast_csum(unsigned char *iph, unsigned int ihl)
155 ;{
156 ;       unsigned int checksum = 0;
157 ;       unsigned short *tosum = (unsigned short *) iph;
158 ;       int len;
159 ;
160 ;       len = ihl*4;
161 ;
162 ;       if (len <= 0)
163 ;               return 0;
164 ;
165 ;       while(len) {
166 ;               len -= 2;
167 ;               checksum += *tosum++;
168 ;       }
169 ;       if (len & 1)
170 ;               checksum += *(unsigned char*) tosum;
171 ;
172 ;       while(checksum >> 16)
173 ;               checksum = (checksum & 0xffff) + (checksum >> 16);
174 ;
175 ;       return ~checksum;
176 ;}
177 ;
178 ; A4:   iph
179 ; B4:   ihl
180 ; return checksum in A4
181 ;
182         .text
183
184 ENTRY(ip_fast_csum)
185         ZERO    .D1     A5
186  ||     MVC     .S2     ILC,B30
187         SHL     .S2     B4,2,B0
188         CMPGT   .L2     B0,0,B1
189   [!B1] BNOP    .S1     L15,4
190   [!B1] ZERO    .D1     A3
191
192   [!B0] B       .S1     L12
193         SHRU    .S2     B0,1,B0
194         MVC     .S2     B0,ILC
195         NOP     3
196
197         SPLOOP  1
198         LDHU    .D1T1   *A4++,A3
199         NOP     3
200         NOP
201         SPKERNEL        5,0
202  ||     ADD     .L1     A3,A5,A5
203
204 L12:    SHRU    .S1     A5,16,A0
205   [!A0] BNOP    .S1     L14,5
206
207 L13:    SHRU    .S2X    A5,16,B4
208         EXTU    .S1     A5,16,16,A3
209         ADD     .D1X    A3,B4,A5
210         SHRU    .S1     A5,16,A0
211   [A0]  BNOP    .S1     L13,5
212
213 L14:    NOT     .D1     A5,A3
214         EXTU    .S1     A3,16,16,A3
215
216 L15:    BNOP    .S2     B3,3
217         MVC     .S2     B30,ILC
218         MV      .D1     A3,A4
219 ENDPROC(ip_fast_csum)
220
221 ;
222 ;unsigned short
223 ;do_csum(unsigned char *buff, unsigned int len)
224 ;{
225 ;       int odd, count;
226 ;       unsigned int result = 0;
227 ;
228 ;       if (len <= 0)
229 ;               goto out;
230 ;       odd = 1 & (unsigned long) buff;
231 ;       if (odd) {
232 ;#ifdef __LITTLE_ENDIAN
233 ;               result += (*buff << 8);
234 ;#else
235 ;               result = *buff;
236 ;#endif
237 ;               len--;
238 ;               buff++;
239 ;       }
240 ;       count = len >> 1;               /* nr of 16-bit words.. */
241 ;       if (count) {
242 ;               if (2 & (unsigned long) buff) {
243 ;                       result += *(unsigned short *) buff;
244 ;                       count--;
245 ;                       len -= 2;
246 ;                       buff += 2;
247 ;               }
248 ;               count >>= 1;            /* nr of 32-bit words.. */
249 ;               if (count) {
250 ;                       unsigned int carry = 0;
251 ;                       do {
252 ;                               unsigned int w = *(unsigned int *) buff;
253 ;                               count--;
254 ;                               buff += 4;
255 ;                               result += carry;
256 ;                               result += w;
257 ;                               carry = (w > result);
258 ;                       } while (count);
259 ;                       result += carry;
260 ;                       result = (result & 0xffff) + (result >> 16);
261 ;               }
262 ;               if (len & 2) {
263 ;                       result += *(unsigned short *) buff;
264 ;                       buff += 2;
265 ;               }
266 ;       }
267 ;       if (len & 1)
268 ;#ifdef __LITTLE_ENDIAN
269 ;               result += *buff;
270 ;#else
271 ;               result += (*buff << 8);
272 ;#endif
273 ;       result = (result & 0xffff) + (result >> 16);
274 ;       /* add up carry.. */
275 ;       result = (result & 0xffff) + (result >> 16);
276 ;       if (odd)
277 ;               result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
278 ;out:
279 ;       return result;
280 ;}
281 ;
282 ; A4:   buff
283 ; B4:   len
284 ; return checksum in A4
285 ;
286
287 ENTRY(do_csum)
288            CMPGT   .L2     B4,0,B0
289    [!B0]   BNOP    .S1     L26,3
290            EXTU    .S1     A4,31,31,A0
291
292            MV      .L1     A0,A3
293 ||         MV      .S1X    B3,A5
294 ||         MV      .L2     B4,B3
295 ||         ZERO    .D1     A1
296
297 #ifdef CONFIG_CPU_BIG_ENDIAN
298    [A0]    SUB     .L2     B3,1,B3
299 || [A0]    LDBU    .D1T1   *A4++,A1
300 #else
301    [!A0]   BNOP    .S1     L21,5
302 || [A0]    LDBU    .D1T1   *A4++,A0
303            SUB     .L2     B3,1,B3
304 ||         SHL     .S1     A0,8,A1
305 L21:
306 #endif
307            SHR     .S2     B3,1,B0
308    [!B0]   BNOP    .S1     L24,3
309            MVK     .L1     2,A0
310            AND     .L1     A4,A0,A0
311
312    [!A0]   BNOP    .S1     L22,5
313 || [A0]    LDHU    .D1T1   *A4++,A0
314            SUB     .L2     B0,1,B0
315 ||         SUB     .S2     B3,2,B3
316 ||         ADD     .L1     A0,A1,A1
317 L22:
318            SHR     .S2     B0,1,B0
319 ||         ZERO    .L1     A0
320
321    [!B0]   BNOP    .S1     L23,5
322 || [B0]    MVC     .S2     B0,ILC
323
324            SPLOOP  3
325            SPMASK  L1
326 ||         MV      .L1     A1,A2
327 ||         LDW     .D1T1   *A4++,A1
328
329            NOP     4
330            ADD     .L1     A0,A1,A0
331            ADD     .L1     A2,A0,A2
332
333            SPKERNEL 1,2
334 ||         CMPGTU  .L1     A1,A2,A0
335
336            ADD     .L1     A0,A2,A6
337            EXTU    .S1     A6,16,16,A7
338            SHRU    .S2X    A6,16,B0
339            NOP             1
340            ADD     .L1X    A7,B0,A1
341 L23:
342            MVK     .L2     2,B0
343            AND     .L2     B3,B0,B0
344    [B0]    LDHU    .D1T1   *A4++,A0
345            NOP     4
346    [B0]    ADD     .L1     A0,A1,A1
347 L24:
348            EXTU    .S2     B3,31,31,B0
349 #ifdef CONFIG_CPU_BIG_ENDIAN
350    [!B0]   BNOP    .S1     L25,4
351 || [B0]    LDBU    .D1T1   *A4,A0
352            SHL     .S1     A0,8,A0
353            ADD     .L1     A0,A1,A1
354 L25:
355 #else
356    [B0]    LDBU    .D1T1   *A4,A0
357            NOP     4
358    [B0]    ADD     .L1     A0,A1,A1
359 #endif
360            EXTU    .S1     A1,16,16,A0
361            SHRU    .S2X    A1,16,B0
362            NOP     1
363            ADD     .L1X    A0,B0,A0
364            SHRU    .S1     A0,16,A1
365            ADD     .L1     A0,A1,A0
366            EXTU    .S1     A0,16,16,A1
367            EXTU    .S1     A1,16,24,A2
368
369            EXTU    .S1     A1,24,16,A0
370 ||         MV      .L2X    A3,B0
371
372    [B0]    OR      .L1     A0,A2,A1
373 L26:
374            NOP     1
375            BNOP    .S2X    A5,4
376            MV      .L1     A1,A4
377 ENDPROC(do_csum)
378
379 ;__wsum csum_partial(const void *buff, int len, __wsum wsum)
380 ;{
381 ;       unsigned int sum = (__force unsigned int)wsum;
382 ;       unsigned int result = do_csum(buff, len);
383 ;
384 ;       /* add in old sum, and carry.. */
385 ;       result += sum;
386 ;       if (sum > result)
387 ;               result += 1;
388 ;       return (__force __wsum)result;
389 ;}
390 ;
391 ENTRY(csum_partial)
392            MV      .L1X    B3,A9
393 ||         CALLP   .S2     do_csum,B3
394 ||         MV      .S1     A6,A8
395            BNOP    .S2X    A9,2
396            ADD     .L1     A8,A4,A1
397            CMPGTU  .L1     A8,A1,A0
398            ADD     .L1     A1,A0,A4
399 ENDPROC(csum_partial)
400
401 ;unsigned short
402 ;ip_compute_csum(unsigned char *buff, unsigned int len)
403 ;
404 ; A4:   buff
405 ; B4:   len
406 ; return checksum in A4
407
408 ENTRY(ip_compute_csum)
409            MV      .L1X    B3,A9
410 ||         CALLP   .S2     do_csum,B3
411            BNOP    .S2X    A9,3
412            NOT     .S1     A4,A4
413            CLR     .S1     A4,16,31,A4
414 ENDPROC(ip_compute_csum)