1 /* $Id: checksum.S,v 1.10 2001/07/06 13:11:32 gniibe Exp $
3 * INET An implementation of the TCP/IP protocol suite for the LINUX
4 * operating system. INET is implemented using the BSD Socket
5 * interface as the means of communication with the user level.
7 * IP/TCP/UDP checksumming routines
9 * Authors: Jorge Cwik, <jorge@laser.satlink.net>
10 * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
11 * Tom May, <ftom@netcom.com>
12 * Pentium Pro/II routines:
13 * Alexander Kjeldaas <astor@guardian.no>
14 * Finn Arne Gangstad <finnag@guardian.no>
15 * Lots of code moved from tcp.c and ip.c; see those files
18 * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
20 * Andi Kleen, add zeroing on error
21 * converted to pure assembler
23 * SuperH version: Copyright (C) 1999 Niibe Yutaka
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version
28 * 2 of the License, or (at your option) any later version.
31 #include <asm/errno.h>
32 #include <linux/linkage.h>
35 * computes a partial checksum, e.g. for TCP/UDP fragments
39 * asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum);
45 * Experiments with Ethernet and SLIP connections show that buff
46 * is aligned on either a 2-byte or 4-byte boundary. We get at
47 * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
48 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
49 * alignment for the unrolled loop.
52 tst #3, r0 ! Check alignment.
53 bt/s 2f ! Jump if alignment is ok.
54 mov r4, r7 ! Keep a copy to check for alignment
56 tst #1, r0 ! Check alignment.
57 bt 21f ! Jump if alignment is boundary of 2bytes.
65 addc r0, r6 ! t=0 from previous tst
75 ! buf is 2 byte aligned (len could be 0)
76 add #-2, r5 ! Alignment uses up two bytes.
78 bt/s 1f ! Jump if we had at least two bytes.
81 add #2, r5 ! r5 was < 2. Deal with it.
89 ! buf is 4 byte aligned (len could be 0)
94 bt/s 4f ! if it's =0, go to 4f
118 ! here, we know r1==0
119 addc r1, r6 ! add carry to r6
125 ! 4 bytes or more remaining
137 addc r1, r6 ! r1==0 here, so it means add carry-bit
139 ! 3 bytes or less remaining
143 bt 9f ! if it's =0 go to 9f
157 #ifndef __LITTLE_ENDIAN__
165 ! Check if the buffer was misaligned, if so realign sum
179 unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
180 int sum, int *src_err_ptr, int *dst_err_ptr)
184 * Copy from ds while checksumming, otherwise like csum_partial
186 * The macros SRC and DST specify the type of access for the instruction.
187 * thus we can call a custom exception handler for all access types.
189 * FIXME: could someone double-check whether I haven't mixed up some SRC and
190 * DST definitions? It's damn hard to trigger all cases. I hope I got
191 * them all but there's no guarantee.
195 9999: __VA_ARGS__ ; \
196 .section __ex_table, "a"; \
197 .long 9999b, 6001f ; \
201 9999: __VA_ARGS__ ; \
202 .section __ex_table, "a"; \
203 .long 9999b, 6002f ; \
207 ! r4: const char *SRC
216 ENTRY(csum_partial_copy_generic)
220 mov #3,r0 ! Check src and dest are equally aligned
225 bf 3f ! Different alignments, use slow version
226 tst #1,r0 ! Check dest word aligned
227 bf 3f ! If not, do it the slow way
230 tst r0,r5 ! Check dest alignment.
231 bt 2f ! Jump if alignment is ok.
232 add #-2,r6 ! Alignment uses up two bytes.
233 cmp/pz r6 ! Jump if we had at least two bytes.
236 add #2,r6 ! r6 was < 2. Deal with it.
240 3: ! Handle different src and dest alignments.
241 ! This is not common, so simple byte by byte copy will do.
253 DST( mov.b r0,@(1,r5) )
257 #ifdef __LITTLE_ENDIAN__
278 ! src and dest equally aligned, but to a two byte boundary.
279 ! Handle first two bytes as a special case
302 DST( mov.l r1,@(4,r5) )
308 DST( mov.l r0,@(8,r5) )
309 DST( mov.l r1,@(12,r5) )
315 DST( mov.l r0,@(16,r5) )
316 DST( mov.l r1,@(20,r5) )
322 DST( mov.l r0,@(24,r5) )
323 DST( mov.l r1,@(28,r5) )
372 #ifndef __LITTLE_ENDIAN__
382 .section .fixup, "ax"
385 mov.l @(8,r15),r0 ! src_err_ptr
389 ! zero the complete destination - computing the rest
391 mov.l @(4,r15),r5 ! dst
405 mov.l @(12,r15),r0 ! dst_err_ptr