2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
6 * IP/TCP/UDP checksumming routines
8 * Authors: Jorge Cwik, <jorge@laser.satlink.net>
9 * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
10 * Tom May, <ftom@netcom.com>
11 * Pentium Pro/II routines:
12 * Alexander Kjeldaas <astor@guardian.no>
13 * Finn Arne Gangstad <finnag@guardian.no>
14 * Lots of code moved from tcp.c and ip.c; see those files
17 * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
19 * Andi Kleen, add zeroing on error
20 * converted to pure assembler
21 * Hirokazu Takata,Hiroyuki Kondo rewrite for the m32r architecture.
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version
26 * 2 of the License, or (at your option) any later version.
31 #include <linux/config.h>
32 #include <linux/linkage.h>
33 #include <asm/assembler.h>
34 #include <asm/errno.h>
37 * computes a partial checksum, e.g. for TCP/UDP fragments
41 unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
45 #ifdef CONFIG_ISA_DUAL_ISSUE
48 * Experiments with Ethernet and SLIP connections show that buff
49 * is aligned on either a 2-byte or 4-byte boundary. We get at
50 * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
51 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
52 * alignment for the unrolled loop.
58 ; r0: unsigned char *buff
60 ; r2: unsigned int sum
63 and3 r7, r0, #1 ; Check alignment.
64 beqz r7, 1f ; Jump if alignment is ok.
66 ldub r4, @r0 || addi r0, #1
67 ; clear c-bit || Alignment uses up bytes.
68 cmp r0, r0 || addi r1, #-1
69 ldi r3, #0 || addx r2, r4
73 and3 r4, r0, #2 ; Check alignment.
74 beqz r4, 2f ; Jump if alignment is ok.
75 ; clear c-bit || Alignment uses up two bytes.
76 cmp r0, r0 || addi r1, #-2
77 bgtz r1, 1f ; Jump if we had at least two bytes.
79 .fillinsn ; len(r1) was < 2. Deal with it.
82 lduh r4, @r0 || ldi r3, #0
83 addx r2, r4 || addi r0, #2
88 cmp r0, r0 ; clear c-bit
96 ld r3, @r0+ || addx r2, r3 ; +12
97 ld r4, @r0+ || addx r2, r4 ; +16
98 ld r5, @r0+ || addx r2, r5 ; +20
99 ld r3, @r0+ || addx r2, r3 ; +24
100 ld r4, @r0+ || addx r2, r4 ; +28
101 addx r2, r5 || addi r6, #-1
107 cmp r0, r0 ; This clears c-bit
109 2: and3 r6, r1, #0x1c ; withdraw len
114 3: ld r4, @r0+ || addi r6, #-1
119 cmp r0, r0 ; This clears c-bit
122 beqz r1, 7f ; if len == 0 goto end
124 beqz r6, 5f ; if len < 2 goto 5f(1byte)
125 lduh r4, @r0 || addi r0, #2
126 addi r1, #-2 || slli r4, #16
130 5: ldub r4, @r0 || ldi r1, #0
131 #ifndef __LITTLE_ENDIAN__
148 beqz r7, 1f ; swap the upper byte for the lower
156 addx r0, r2 || ldi r2, #0
160 #else /* not CONFIG_ISA_DUAL_ISSUE */
163 * Experiments with Ethernet and SLIP connections show that buff
164 * is aligned on either a 2-byte or 4-byte boundary. We get at
165 * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
166 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
167 * alignment for the unrolled loop.
173 ; r0: unsigned char *buff
175 ; r2: unsigned int sum
179 and3 r7, r0, #1 ; Check alignment.
180 beqz r7, 1f ; Jump if alignment is ok.
184 addi r1, #-1 ; Alignment uses up bytes.
185 cmp r0, r0 ; clear c-bit
191 and3 r4, r0, #2 ; Check alignment.
192 beqz r4, 2f ; Jump if alignment is ok.
193 addi r1, #-2 ; Alignment uses up two bytes.
194 cmp r0, r0 ; clear c-bit
195 bgtz r1, 1f ; Jump if we had at least two bytes.
196 addi r1, #2 ; len(r1) was < 2. Deal with it.
209 cmp r0, r0 ; clear c-bit
233 cmp r0, r0 ; This clears c-bit
236 2: and3 r6, r1, #0x1c ; withdraw len
246 cmp r0, r0 ; This clears c-bit
250 beqz r1, 7f ; if len == 0 goto end
252 beqz r6, 5f ; if len < 2 goto 5f(1byte)
262 #ifndef __LITTLE_ENDIAN__
295 #endif /* not CONFIG_ISA_DUAL_ISSUE */
298 unsigned int csum_partial_copy_generic (const char *src, char *dst,
299 int len, int sum, int *src_err_ptr, int *dst_err_ptr)
303 * Copy from ds while checksumming, otherwise like csum_partial
305 * The macros SRC and DST specify the type of access for the instruction.
306 * thus we can call a custom exception handler for all access types.
308 * FIXME: could someone double-check whether I haven't mixed up some SRC and
309 * DST definitions? It's damn hard to trigger all cases. I hope I got
310 * them all but there's no guarantee.
313 ENTRY(csum_partial_copy_generic)