2 ; linux/arch/c6x/lib/csum_64plus.s
4 ; Port on Texas Instruments TMS320C6x architecture
6 ; Copyright (C) 2006, 2009, 2010, 2011 Texas Instruments Incorporated
7 ; Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
9 ; This program is free software; you can redistribute it and/or modify
10 ; it under the terms of the GNU General Public License version 2 as
11 ; published by the Free Software Foundation.
13 #include <linux/linkage.h>
16 ;unsigned int csum_partial_copy(const char *src, char * dst,
27 ENTRY(csum_partial_copy)
30 MV .D1X B6,A31 ; given csum
31 ZERO .D1 A9 ; csum (a side)
32 || ZERO .D2 B9 ; csum (b side)
33 || SHRU .S2X A6,2,B5 ; len / 4
35 ;; Check alignment and size
38 OR .L2X B0,A1,B0 ; non aligned condition
41 || MV .D1X B5,A1 ; words condition
47 ;; Main loop for aligned words
51 || EXTU .S1 A7,0,16,A16
60 || ADD .L1X A9,B9,A9 ; add csum from a and b sides
65 ;; Main loop for non-aligned words
74 || EXTU .S1 A7,0,16,A16
79 || STNW .D2T2 B7,*B4++
90 #ifdef CONFIG_CPU_BIG_ENDIAN
115 ;; Manage eventually the last byte
116 L82: AND .S2X 1,A6,B0
121 L83: LDBU .D1T1 *A4++,A7
126 #ifdef CONFIG_CPU_BIG_ENDIAN
140 L9: SHRU .S2X A9,16,B0
143 L91: SHRU .S2X A9,16,B4
144 || EXTU .S1 A9,16,16,A3
150 L10: ADD .D1 A31,A9,A9
155 ENDPROC(csum_partial_copy)
159 ;ip_fast_csum(unsigned char *iph, unsigned int ihl)
161 ; unsigned int checksum = 0;
162 ; unsigned short *tosum = (unsigned short *) iph;
172 ; checksum += *tosum++;
175 ; checksum += *(unsigned char*) tosum;
177 ; while(checksum >> 16)
178 ; checksum = (checksum & 0xffff) + (checksum >> 16);
185 ; return checksum in A4
209 L12: SHRU .S1 A5,16,A0
212 L13: SHRU .S2X A5,16,B4
224 ENDPROC(ip_fast_csum)
228 ;do_csum(unsigned char *buff, unsigned int len)
231 ; unsigned int result = 0;
235 ; odd = 1 & (unsigned long) buff;
237 ;#ifdef __LITTLE_ENDIAN
238 ; result += (*buff << 8);
245 ; count = len >> 1; /* nr of 16-bit words.. */
247 ; if (2 & (unsigned long) buff) {
248 ; result += *(unsigned short *) buff;
253 ; count >>= 1; /* nr of 32-bit words.. */
255 ; unsigned int carry = 0;
257 ; unsigned int w = *(unsigned int *) buff;
262 ; carry = (w > result);
265 ; result = (result & 0xffff) + (result >> 16);
268 ; result += *(unsigned short *) buff;
273 ;#ifdef __LITTLE_ENDIAN
276 ; result += (*buff << 8);
278 ; result = (result & 0xffff) + (result >> 16);
279 ; /* add up carry.. */
280 ; result = (result & 0xffff) + (result >> 16);
282 ; result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
289 ; return checksum in A4
302 #ifdef CONFIG_CPU_BIG_ENDIAN
304 || [A0] LDBU .D1T1 *A4++,A1
307 || [A0] LDBU .D1T1 *A4++,A0
318 || [A0] LDHU .D1T1 *A4++,A0
327 || [B0] MVC .S2 B0,ILC
332 || LDW .D1T1 *A4++,A1
339 || CMPGTU .L1 A1,A2,A0
349 [B0] LDHU .D1T1 *A4++,A0
351 [B0] ADD .L1 A0,A1,A1
354 #ifdef CONFIG_CPU_BIG_ENDIAN
356 || [B0] LDBU .D1T1 *A4,A0
361 [B0] LDBU .D1T1 *A4,A0
363 [B0] ADD .L1 A0,A1,A1
384 ;__wsum csum_partial(const void *buff, int len, __wsum wsum)
386 ; unsigned int sum = (__force unsigned int)wsum;
387 ; unsigned int result = do_csum(buff, len);
389 ; /* add in old sum, and carry.. */
393 ; return (__force __wsum)result;
398 || CALLP .S2 do_csum,B3
404 ENDPROC(csum_partial)
407 ;ip_compute_csum(unsigned char *buff, unsigned int len)
411 ; return checksum in A4
413 ENTRY(ip_compute_csum)
415 || CALLP .S2 do_csum,B3
419 ENDPROC(ip_compute_csum)