patch-2.3.23 linux/arch/sh/lib/checksum.S
Next file: linux/arch/sh/lib/checksum.c
Previous file: linux/arch/sh/lib/Makefile
Back to the patch index
Back to the overall index
- Lines: 319
- Date:
Mon Oct 18 11:16:13 1999
- Orig file:
v2.3.22/linux/arch/sh/lib/checksum.S
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.22/linux/arch/sh/lib/checksum.S linux/arch/sh/lib/checksum.S
@@ -0,0 +1,318 @@
+/* $Id: checksum.S,v 1.1 1999/09/18 16:56:53 gniibe Exp $
+ *
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IP/TCP/UDP checksumming routines
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Tom May, <ftom@netcom.com>
+ * Pentium Pro/II routines:
+ * Alexander Kjeldaas <astor@guardian.no>
+ * Finn Arne Gangstad <finnag@guardian.no>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ * handling.
+ * Andi Kleen, add zeroing on error
+ * converted to pure assembler
+ *
+ * SuperH version: Copyright (C) 1999 Niibe Yutaka
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/errno.h>
+#include <linux/linkage.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+ * unsigned int csum_partial(const unsigned char *buf, int len,
+ * unsigned int sum);
+ */
+
+.text
+ENTRY(csum_partial)
+ /*
+ * Experiments with Ethernet and SLIP connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary. We get at
+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+ * alignment for the unrolled loop.
+ */
+ mov r5,r1
+ mov r4,r0
+ tst #2,r0 ! Check alignment.
+ bt 2f ! Jump if alignment is ok.
+ !
+ add #-2,r5 ! Alignment uses up two bytes.
+ cmp/pz r5 !
+ bt/s 1f ! Jump if we had at least two bytes.
+ clrt
+ bra 6f
+ add #2,r5 ! r5 was < 2. Deal with it.
+1:
+ mov.w @r4+,r0
+ extu.w r0,r0
+ addc r0,r6
+ bf 2f
+ add #1,r6
+2:
+ mov #-5,r0
+ shld r0,r5
+ tst r5,r5
+ bt/s 4f ! if it's =0, go to 4f
+ clrt
+3:
+ mov.l @r4+,r0
+ addc r0,r6
+ mov.l @r4+,r0
+ addc r0,r6
+ mov.l @r4+,r0
+ addc r0,r6
+ mov.l @r4+,r0
+ addc r0,r6
+ mov.l @r4+,r0
+ addc r0,r6
+ mov.l @r4+,r0
+ addc r0,r6
+ mov.l @r4+,r0
+ addc r0,r6
+ mov.l @r4+,r0
+ addc r0,r6
+ movt r0
+ dt r5
+ bf/s 3b
+ cmp/eq #1,r0
+ mov #0,r0
+ addc r0,r6
+4:
+ mov r1,r5
+ mov #0x1c,r0
+ and r0,r5
+ tst r5,r5
+ bt/s 6f
+ clrt
+ shlr2 r5
+5:
+ mov.l @r4+,r0
+ addc r0,r6
+ movt r0
+ dt r5
+ bf/s 5b
+ cmp/eq #1,r0
+ mov #0,r0
+ addc r0,r6
+6:
+ mov r1,r5
+ mov #3,r0
+ and r0,r5
+ tst r5,r5
+ bt 9f ! if it's =0 go to 9f
+ mov #2,r1
+ cmp/hs r1,r5
+ bf 7f
+ mov.w @r4+,r0
+ extu.w r0,r0
+ cmp/eq r1,r5
+ bt/s 8f
+ clrt
+ shll16 r0
+ addc r0,r6
+7:
+ mov.b @r4+,r0
+ extu.b r0,r0
+8:
+ addc r0,r6
+ mov #0,r0
+ addc r0,r6
+9:
+ rts
+ mov r6,r0
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
+ int sum, int *src_err_ptr, int *dst_err_ptr)
+ */
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ * DST definitions? It's damn hard to trigger all cases. I hope I got
+ * them all but there's no guarantee.
+ */
+
+#define SRC(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6001f ; \
+ .previous
+
+#define DST(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6002f ; \
+ .previous
+
+ENTRY(csum_partial_copy_generic)
+ mov.l r5,@-r15
+ mov.l r6,@-r15
+
+ mov #2,r0
+ tst r0,r5 ! Check alignment.
+ bt 2f ! Jump if alignment is ok.
+ add #-2,r6 ! Alignment uses up two bytes.
+ cmp/pz r6 ! Jump if we had at least two bytes.
+ bt/s 1f
+ clrt
+ bra 4f
+ add #2,r6 ! ecx was < 2. Deal with it.
+SRC(1: mov.w @r4+,r0 )
+DST( mov.w r0,@r5 )
+ add #2,r5
+ extu.w r0,r0
+ addc r0,r7
+ mov #0,r0
+ addc r0,r7
+2:
+ mov r6,r2
+ mov #-5,r0
+ shld r0,r6
+ tst r6,r6
+ bf/s 2f
+ clrt
+SRC(1: mov.l @r4+,r0 )
+SRC( mov.l @r4+,r1 )
+ addc r0,r7
+DST( mov.l r0,@r5 )
+ add #4,r5
+ addc r1,r7
+DST( mov.l r1,@r5 )
+ add #4,r5
+
+SRC( mov.l @r4+,r0 )
+SRC( mov.l @r4+,r1 )
+ addc r0,r7
+DST( mov.l r0,@r5 )
+ add #4,r5
+ addc r1,r7
+DST( mov.l r1,@r5 )
+ add #4,r5
+
+SRC( mov.l @r4+,r0 )
+SRC( mov.l @r4+,r1 )
+ addc r0,r7
+DST( mov.l r0,@r5 )
+ add #4,r5
+ addc r1,r7
+DST( mov.l r1,@r5 )
+ add #4,r5
+
+SRC( mov.l @r4+,r0 )
+SRC( mov.l @r4+,r1 )
+ addc r0,r7
+DST( mov.l r0,@r5 )
+ add #4,r5
+ addc r1,r7
+DST( mov.l r1,@r5 )
+ add #4,r5
+ movt r0
+ dt r6
+ bf/s 1b
+ cmp/eq #1,r0
+ mov #0,r0
+ addc r0,r7
+
+2: mov r2,r6
+ mov #0x1c,r0
+ and r0,r6
+ cmp/pl r6
+ bf/s 4f
+ clrt
+ shlr2 r6
+SRC(3: mov.l @r4+,r0 )
+ addc r0,r7
+DST( mov.l r0,@r5 )
+ add #4,r5
+ movt r0
+ dt r6
+ bf/s 3b
+ cmp/eq #1,r0
+ mov #0,r0
+ addc r0,r7
+4: mov r2,r6
+ mov #3,r0
+ and r0,r6
+ cmp/pl r6
+ bf 7f
+ mov #2,r1
+ cmp/hs r1,r6
+ bf 5f
+SRC( mov.w @r4+,r0 )
+DST( mov.w r0,@r5 )
+ extu.w r0,r0
+ add #2,r5
+ cmp/eq r1,r6
+ bt/s 6f
+ clrt
+ shll16 r0
+ addc r0,r7
+SRC(5: mov.b @r4+,r0 )
+DST( mov.b r0,@r5 )
+ extu.b r0,r0
+6: addc r0,r7
+ mov #0,r0
+ addc r0,r7
+7:
+5000:
+
+# Exception handler:
+.section .fixup, "ax"
+
+6001:
+ mov.l @(8,r15),r0 ! src_err_ptr
+ mov #-EFAULT,r1
+ mov.l r1,@r0
+
+ ! zero the complete destination - computing the rest
+ ! is too much work
+ mov.l @(4,r15),r5 ! dst
+ mov.l @r15,r6 ! len
+ mov #0,r7
+1: mov.b r7,@r5
+ dt r6
+ bf/s 1b
+ add #1,r5
+ mov.l 8000f,r0
+ jmp @r0
+ nop
+ .balign 4
+8000: .long 5000b
+
+6002:
+ mov.l @(12,r15),r0 ! dst_err_ptr
+ mov #-EFAULT,r1
+ mov.l r1,@r0
+ mov.l 8001f,r0
+ jmp @r0
+ nop
+ .balign 4
+8001: .long 5000b
+
+.previous
+ add #8,r15
+ rts
+ mov r7,r0
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)