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_nocheck(const char *src, char * dst,
24 ENTRY(csum_partial_copy_nocheck)
27 ZERO .D1 A9 ; csum (a side)
28 || ZERO .D2 B9 ; csum (b side)
29 || SHRU .S2X A6,2,B5 ; len / 4
31 ;; Check alignment and size
34 OR .L2X B0,A1,B0 ; non aligned condition
37 || MV .D1X B5,A1 ; words condition
43 ;; Main loop for aligned words
47 || EXTU .S1 A7,0,16,A16
56 || ADD .L1X A9,B9,A9 ; add csum from a and b sides
61 ;; Main loop for non-aligned words
70 || EXTU .S1 A7,0,16,A16
75 || STNW .D2T2 B7,*B4++
86 #ifdef CONFIG_CPU_BIG_ENDIAN
111 ;; Manage eventually the last byte
112 L82: AND .S2X 1,A6,B0
117 L83: LDBU .D1T1 *A4++,A7
122 #ifdef CONFIG_CPU_BIG_ENDIAN
136 L9: SHRU .S2X A9,16,B0
139 L91: SHRU .S2X A9,16,B4
140 || EXTU .S1 A9,16,16,A3
150 ENDPROC(csum_partial_copy_nocheck)
154 ;ip_fast_csum(unsigned char *iph, unsigned int ihl)
156 ; unsigned int checksum = 0;
157 ; unsigned short *tosum = (unsigned short *) iph;
167 ; checksum += *tosum++;
170 ; checksum += *(unsigned char*) tosum;
172 ; while(checksum >> 16)
173 ; checksum = (checksum & 0xffff) + (checksum >> 16);
180 ; return checksum in A4
204 L12: SHRU .S1 A5,16,A0
207 L13: SHRU .S2X A5,16,B4
219 ENDPROC(ip_fast_csum)
223 ;do_csum(unsigned char *buff, unsigned int len)
226 ; unsigned int result = 0;
230 ; odd = 1 & (unsigned long) buff;
232 ;#ifdef __LITTLE_ENDIAN
233 ; result += (*buff << 8);
240 ; count = len >> 1; /* nr of 16-bit words.. */
242 ; if (2 & (unsigned long) buff) {
243 ; result += *(unsigned short *) buff;
248 ; count >>= 1; /* nr of 32-bit words.. */
250 ; unsigned int carry = 0;
252 ; unsigned int w = *(unsigned int *) buff;
257 ; carry = (w > result);
260 ; result = (result & 0xffff) + (result >> 16);
263 ; result += *(unsigned short *) buff;
268 ;#ifdef __LITTLE_ENDIAN
271 ; result += (*buff << 8);
273 ; result = (result & 0xffff) + (result >> 16);
274 ; /* add up carry.. */
275 ; result = (result & 0xffff) + (result >> 16);
277 ; result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
284 ; return checksum in A4
297 #ifdef CONFIG_CPU_BIG_ENDIAN
299 || [A0] LDBU .D1T1 *A4++,A1
302 || [A0] LDBU .D1T1 *A4++,A0
313 || [A0] LDHU .D1T1 *A4++,A0
322 || [B0] MVC .S2 B0,ILC
327 || LDW .D1T1 *A4++,A1
334 || CMPGTU .L1 A1,A2,A0
344 [B0] LDHU .D1T1 *A4++,A0
346 [B0] ADD .L1 A0,A1,A1
349 #ifdef CONFIG_CPU_BIG_ENDIAN
351 || [B0] LDBU .D1T1 *A4,A0
356 [B0] LDBU .D1T1 *A4,A0
358 [B0] ADD .L1 A0,A1,A1
379 ;__wsum csum_partial(const void *buff, int len, __wsum wsum)
381 ; unsigned int sum = (__force unsigned int)wsum;
382 ; unsigned int result = do_csum(buff, len);
384 ; /* add in old sum, and carry.. */
388 ; return (__force __wsum)result;
393 || CALLP .S2 do_csum,B3
399 ENDPROC(csum_partial)
402 ;ip_compute_csum(unsigned char *buff, unsigned int len)
406 ; return checksum in A4
408 ENTRY(ip_compute_csum)
410 || CALLP .S2 do_csum,B3
414 ENDPROC(ip_compute_csum)