⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 checksum.s

📁 linux-2.6.15.6
💻 S
字号:
/* * 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 *		Hirokazu Takata,Hiroyuki Kondo rewrite for the m32r architecture. * *		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. *//* $Id$ */#include <linux/config.h>#include <linux/linkage.h>#include <asm/assembler.h>#include <asm/errno.h>/* * computes a partial checksum, e.g. for TCP/UDP fragments *//*unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) */#ifdef CONFIG_ISA_DUAL_ISSUE	/*	 * 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.	 */	.textENTRY(csum_partial)	; Function args	;  r0: unsigned char *buff	;  r1: int len	;  r2: unsigned int sum	push	r2		    ||	ldi	r2, #0	and3	r7, r0, #1		; Check alignment.	beqz	r7, 1f	 		; Jump if alignment is ok.	; 1-byte mis aligned	ldub	r4, @r0		    ||	addi	r0, #1	; clear c-bit || Alignment uses up bytes.	cmp	r0, r0		    ||	addi	r1, #-1	ldi	r3, #0		    ||	addx	r2, r4	addx	r2, r3	.fillinsn1:	and3	r4, r0, #2		; Check alignment.	beqz	r4, 2f	 		; Jump if alignment is ok.	; clear c-bit || Alignment uses up two bytes.	cmp	r0, r0		    ||	addi	r1, #-2	bgtz	r1, 1f			; Jump if we had at least two bytes.	bra	4f		    ||	addi	r1, #2	.fillinsn			; len(r1) was < 2.  Deal with it.1:	; 2-byte aligned	lduh	r4, @r0		    ||	ldi	r3, #0	addx	r2, r4		    ||	addi	r0, #2	addx	r2, r3	.fillinsn2:	; 4-byte aligned	cmp	r0, r0			; clear c-bit	srl3	r6, r1, #5	beqz	r6, 2f	.fillinsn1:	ld	r3, @r0+	ld	r4, @r0+					; +4	ld	r5, @r0+					; +8	ld	r3, @r0+	    ||	addx    r2, r3		; +12	ld	r4, @r0+	    ||	addx    r2, r4		; +16	ld	r5, @r0+	    ||	addx    r2, r5		; +20	ld	r3, @r0+	    ||	addx    r2, r3		; +24	ld	r4, @r0+	    ||	addx    r2, r4		; +28	addx	r2, r5		    ||	addi	r6, #-1	addx	r2, r3	addx	r2, r4	bnez	r6, 1b	addx	r2, r6			; r6=0	cmp	r0, r0			; This clears c-bit	.fillinsn2:	and3	r6, r1, #0x1c		; withdraw len	beqz	r6, 4f	srli	r6, #2	.fillinsn3:	ld	r4, @r0+	    ||	addi	r6, #-1	addx	r2, r4	bnez	r6, 3b	addx	r2, r6			; r6=0	cmp	r0, r0			; This clears c-bit	.fillinsn4:	and3	r1, r1, #3	beqz	r1, 7f			; if len == 0 goto end	and3	r6, r1, #2	beqz	r6, 5f			; if len < 2  goto 5f(1byte)	lduh	r4, @r0		    ||	addi	r0, #2	addi	r1, #-2		    ||	slli    r4, #16	addx	r2, r4	beqz	r1, 6f	.fillinsn5:	ldub	r4, @r0		    ||	ldi	r1, #0#ifndef __LITTLE_ENDIAN__	slli    r4, #8#endif	addx	r2, r4	.fillinsn6:	addx	r2, r1	.fillinsn7:	and3	r0, r2, #0xffff	srli	r2, #16	add	r0, r2	srl3	r2, r0, #16	beqz	r2, 1f	addi	r0, #1	and3	r0, r0, #0xffff	.fillinsn1:	beqz	r7, 1f			; swap the upper byte for the lower	and3	r2, r0, #0xff	srl3	r0, r0, #8	slli	r2, #8	or	r0, r2	.fillinsn1:	pop	r2		    ||	cmp	r0, r0	addx	r0, r2		    ||	ldi	r2, #0	addx	r0, r2	jmp	r14#else /* not CONFIG_ISA_DUAL_ISSUE */	/*	 * 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.	 */	.textENTRY(csum_partial)	; Function args	;  r0: unsigned char *buff	;  r1: int len	;  r2: unsigned int sum	push	r2	ldi	r2, #0	and3	r7, r0, #1		; Check alignment.	beqz	r7, 1f	 		; Jump if alignment is ok.	; 1-byte mis aligned	ldub	r4, @r0	addi	r0, #1	addi	r1, #-1			; Alignment uses up bytes.	cmp	r0, r0			; clear c-bit	ldi	r3, #0	addx	r2, r4	addx	r2, r3	.fillinsn1:	and3	r4, r0, #2		; Check alignment.	beqz	r4, 2f	 		; Jump if alignment is ok.	addi	r1, #-2			; Alignment uses up two bytes.	cmp		r0, r0			; clear c-bit	bgtz	r1, 1f			; Jump if we had at least two bytes.	addi	r1, #2			; len(r1) was < 2.  Deal with it.	bra	4f	.fillinsn1:	; 2-byte aligned	lduh	r4, @r0	addi	r0, #2	ldi		r3, #0	addx	r2, r4	addx	r2, r3	.fillinsn2:	; 4-byte aligned	cmp	r0, r0			; clear c-bit	srl3	r6, r1, #5	beqz	r6, 2f	.fillinsn1:	ld	r3, @r0+	ld	r4, @r0+		; +4	ld	r5, @r0+		; +8	addx	r2, r3	addx	r2, r4	addx	r2, r5	ld	r3, @r0+		; +12	ld	r4, @r0+		; +16	ld	r5, @r0+		; +20	addx	r2, r3	addx	r2, r4	addx	r2, r5	ld	r3, @r0+		; +24	ld	r4, @r0+		; +28	addi	r6, #-1	addx	r2, r3	addx	r2, r4	bnez	r6, 1b	addx	r2, r6			; r6=0	cmp	r0, r0			; This clears c-bit	.fillinsn2:	and3	r6, r1, #0x1c		; withdraw len	beqz	r6, 4f	srli	r6, #2	.fillinsn3:	ld	r4, @r0+	addi	r6, #-1	addx	r2, r4	bnez	r6, 3b	addx	r2, r6			; r6=0	cmp	r0, r0			; This clears c-bit	.fillinsn4:	and3	r1, r1, #3	beqz	r1, 7f			; if len == 0 goto end	and3	r6, r1, #2	beqz	r6, 5f			; if len < 2  goto 5f(1byte)	lduh	r4, @r0	addi	r0, #2	addi	r1, #-2	slli    r4, #16	addx	r2, r4	beqz	r1, 6f	.fillinsn5:	ldub	r4, @r0#ifndef __LITTLE_ENDIAN__	slli    r4, #8#endif	addx	r2, r4	.fillinsn6:	ldi	r5, #0	addx	r2, r5	.fillinsn7:	and3	r0, r2, #0xffff	srli	r2, #16	add	r0, r2	srl3	r2, r0, #16	beqz	r2, 1f	addi	r0, #1	and3	r0, r0, #0xffff	.fillinsn1:	beqz	r7, 1f	mv	r2, r0	srl3	r0, r2, #8	and3	r2, r2, #0xff	slli	r2, #8	or	r0, r2	.fillinsn1:	pop	r2	cmp	r0, r0	addx	r0, r2	ldi	r2, #0	addx	r0, r2	jmp	r14#endif /* not CONFIG_ISA_DUAL_ISSUE *//*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. */ENTRY(csum_partial_copy_generic)	nop	nop	nop	nop	jmp r14	nop	nop	nop

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -