]> git.ipfire.org Git - thirdparty/kernel/linux.git/blob
5714886
[thirdparty/kernel/linux.git] /
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)