1 ; SPDX-License-Identifier: GPL-2.0-only
3 ; linux/arch/c6x/lib/csum_64plus.s
5 ; Port on Texas Instruments TMS320C6x architecture
7 ; Copyright (C) 2006, 2009, 2010, 2011 Texas Instruments Incorporated
8 ; Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
10 #include <linux/linkage.h>
13 ;unsigned int csum_partial_copy(const char *src, char * dst,
24 ENTRY(csum_partial_copy)
27 MV .D1X B6,A31 ; given csum
28 ZERO .D1 A9 ; csum (a side)
29 || ZERO .D2 B9 ; csum (b side)
30 || SHRU .S2X A6,2,B5 ; len / 4
32 ;; Check alignment and size
35 OR .L2X B0,A1,B0 ; non aligned condition
38 || MV .D1X B5,A1 ; words condition
44 ;; Main loop for aligned words
48 || EXTU .S1 A7,0,16,A16
57 || ADD .L1X A9,B9,A9 ; add csum from a and b sides
62 ;; Main loop for non-aligned words
71 || EXTU .S1 A7,0,16,A16
76 || STNW .D2T2 B7,*B4++
87 #ifdef CONFIG_CPU_BIG_ENDIAN
112 ;; Manage eventually the last byte
113 L82: AND .S2X 1,A6,B0
118 L83: LDBU .D1T1 *A4++,A7
123 #ifdef CONFIG_CPU_BIG_ENDIAN
137 L9: SHRU .S2X A9,16,B0
140 L91: SHRU .S2X A9,16,B4
141 || EXTU .S1 A9,16,16,A3
147 L10: ADD .D1 A31,A9,A9
152 ENDPROC(csum_partial_copy)
156 ;ip_fast_csum(unsigned char *iph, unsigned int ihl)
158 ; unsigned int checksum = 0;
159 ; unsigned short *tosum = (unsigned short *) iph;
169 ; checksum += *tosum++;
172 ; checksum += *(unsigned char*) tosum;
174 ; while(checksum >> 16)
175 ; checksum = (checksum & 0xffff) + (checksum >> 16);
182 ; return checksum in A4
206 L12: SHRU .S1 A5,16,A0
209 L13: SHRU .S2X A5,16,B4
221 ENDPROC(ip_fast_csum)
225 ;do_csum(unsigned char *buff, unsigned int len)
228 ; unsigned int result = 0;
232 ; odd = 1 & (unsigned long) buff;
234 ;#ifdef __LITTLE_ENDIAN
235 ; result += (*buff << 8);
242 ; count = len >> 1; /* nr of 16-bit words.. */
244 ; if (2 & (unsigned long) buff) {
245 ; result += *(unsigned short *) buff;
250 ; count >>= 1; /* nr of 32-bit words.. */
252 ; unsigned int carry = 0;
254 ; unsigned int w = *(unsigned int *) buff;
259 ; carry = (w > result);
262 ; result = (result & 0xffff) + (result >> 16);
265 ; result += *(unsigned short *) buff;
270 ;#ifdef __LITTLE_ENDIAN
273 ; result += (*buff << 8);
275 ; result = (result & 0xffff) + (result >> 16);
276 ; /* add up carry.. */
277 ; result = (result & 0xffff) + (result >> 16);
279 ; result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
286 ; return checksum in A4
299 #ifdef CONFIG_CPU_BIG_ENDIAN
301 || [A0] LDBU .D1T1 *A4++,A1
304 || [A0] LDBU .D1T1 *A4++,A0
315 || [A0] LDHU .D1T1 *A4++,A0
324 || [B0] MVC .S2 B0,ILC
329 || LDW .D1T1 *A4++,A1
336 || CMPGTU .L1 A1,A2,A0
346 [B0] LDHU .D1T1 *A4++,A0
348 [B0] ADD .L1 A0,A1,A1
351 #ifdef CONFIG_CPU_BIG_ENDIAN
353 || [B0] LDBU .D1T1 *A4,A0
358 [B0] LDBU .D1T1 *A4,A0
360 [B0] ADD .L1 A0,A1,A1
381 ;__wsum csum_partial(const void *buff, int len, __wsum wsum)
383 ; unsigned int sum = (__force unsigned int)wsum;
384 ; unsigned int result = do_csum(buff, len);
386 ; /* add in old sum, and carry.. */
390 ; return (__force __wsum)result;
395 || CALLP .S2 do_csum,B3
401 ENDPROC(csum_partial)
404 ;ip_compute_csum(unsigned char *buff, unsigned int len)
408 ; return checksum in A4
410 ENTRY(ip_compute_csum)
412 || CALLP .S2 do_csum,B3
416 ENDPROC(ip_compute_csum)