1 /* SPDX-License-Identifier: GPL-2.0+
3 * $Id: checksum.S,v 1.10 2001/07/06 13:11:32 gniibe Exp $
5 * INET An implementation of the TCP/IP protocol suite for the LINUX
6 * operating system. INET is implemented using the BSD Socket
7 * interface as the means of communication with the user level.
9 * IP/TCP/UDP checksumming routines
11 * Authors: Jorge Cwik, <jorge@laser.satlink.net>
12 * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
13 * Tom May, <ftom@netcom.com>
14 * Pentium Pro/II routines:
15 * Alexander Kjeldaas <astor@guardian.no>
16 * Finn Arne Gangstad <finnag@guardian.no>
17 * Lots of code moved from tcp.c and ip.c; see those files
20 * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
22 * Andi Kleen, add zeroing on error
23 * converted to pure assembler
25 * SuperH version: Copyright (C) 1999 Niibe Yutaka
28 #include <asm/errno.h>
29 #include <linux/linkage.h>
32 * computes a partial checksum, e.g. for TCP/UDP fragments
36 * unsigned int csum_partial(const unsigned char *buf, int len,
43 * Experiments with Ethernet and SLIP connections show that buff
44 * is aligned on either a 2-byte or 4-byte boundary. We get at
45 * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
46 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
47 * alignment for the unrolled loop.
51 tst #2, r0 ! Check alignment.
52 bt 2f ! Jump if alignment is ok.
54 add #-2, r5 ! Alignment uses up two bytes.
56 bt/s 1f ! Jump if we had at least two bytes.
59 add #2, r5 ! r5 was < 2. Deal with it.
61 mov r5, r1 ! Save new len for later use.
71 bt/s 4f ! if it's =0, go to 4f
96 addc r5, r6 ! add carry to r6
113 addc r5, r6 ! r5==0 here, so it means add carry-bit
119 bt 9f ! if it's =0 go to 9f
133 #ifndef __LITTLE_ENDIAN__
145 unsigned int csum_partial_copy_generic (const char *src, char *dst, int len)
149 * Copy from ds while checksumming, otherwise like csum_partial with initial
154 9999: __VA_ARGS__ ; \
155 .section __ex_table, "a"; \
156 .long 9999b, 6001f ; \
160 ! r4: const char *SRC
164 ENTRY(csum_partial_copy_generic)
166 mov #3,r0 ! Check src and dest are equally aligned
171 bf 3f ! Different alignments, use slow version
172 tst #1,r0 ! Check dest word aligned
173 bf 3f ! If not, do it the slow way
176 tst r0,r5 ! Check dest alignment.
177 bt 2f ! Jump if alignment is ok.
178 add #-2,r6 ! Alignment uses up two bytes.
179 cmp/pz r6 ! Jump if we had at least two bytes.
182 add #2,r6 ! r6 was < 2. Deal with it.
186 3: ! Handle different src and dest alignments.
187 ! This is not common, so simple byte by byte copy will do.
199 EXC( mov.b r0,@(1,r5) )
203 #ifdef __LITTLE_ENDIAN__
224 ! src and dest equally aligned, but to a two byte boundary.
225 ! Handle first two bytes as a special case
248 EXC( mov.l r1,@(4,r5) )
254 EXC( mov.l r0,@(8,r5) )
255 EXC( mov.l r1,@(12,r5) )
261 EXC( mov.l r0,@(16,r5) )
262 EXC( mov.l r1,@(20,r5) )
268 EXC( mov.l r0,@(24,r5) )
269 EXC( mov.l r1,@(28,r5) )
318 #ifndef __LITTLE_ENDIAN__
327 .section .fixup, "ax"