checksum.s
来自「linux-2.4.29操作系统的源码」· S 代码 · 共 657 行 · 第 1/2 页
S
657 行
/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * arch/sh5/lib/checksum.S * * Copyright (C) 2000, 2001 Paolo Alberelli, Stefano D'Andrea * *//* * * 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 * * SH-5 version: Copyright (C) 2000 Paolo Alberelli, Stefano D'Andrea * * 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 <asm/registers.h> .section .text64, "ax"/* * unsigned int csum_partial(const unsigned char *buf, * int len, * unsigned int sum); * * * computes a partial checksum, e.g. for TCP/UDP fragments *//* * SH-5 ABI convention: * Input parameters: * r2 = *buf * r3 = len * r4 = sum so far computed checksum (may be zero) * return value must be in: * r2 returned checksum */ /* * 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. */#ifndef NOTDEF /* This version of _csum_partial is an easy but unefficient * implementation. * It's mainteined only for historical reasons. */ .global csum_partialcsum_partial: _ptar .byte_footer, t1 /* t1 = .byte_footer */ _ptar .add_short_loop, t2 /* t2 = checksum eval loop */ _ptar .exiting, t3 /* t3 = add carry... */ movi 2, r1 /* we assume buf short aligned */ /* Short must be checksummed */.add_short_loop: bgt r1, r3, t1 /* Size = 1 or 0 (remind) */ ld.uw r2, 0, r7 /* r7 = word to be checksumed*/ add r4, r7, r4 addi r2, 2, r2 /* move buf forward... */ addi r3, -2, r3 /* decrement len */ blink t2, ZERO /* goto .add_short_loop */ .byte_footer: /* still one byte to be checksummed ? */ xor r7, r7, r7 beqi r3, 0, t3 ld.ub r2, 0, r7 /* r7 = last byte... */#ifndef __LITTLE_ENDIAN__ shlli r7, 8, r7#endif.exiting: add r4, r7, r2 ptabs r18, t0 blink t0, ZERO#else /* NOTDEF ---------------------------------------------------- */ .global csum_partialcsum_partial: movi 32, r8 /* r8 = sizeof(8 * int) */ _ptar .byte_footer, t1 /* t1 = .byte_footer */ _ptar .word_footer, t2 /* t2 = .word_footer */ _ptar .long_footer, t3 /* t3 = .long_footer */ _ptar .exit, t4 /* t4 = exit point */ _ptar .long_aligned, t0 /* t0 = .long_aligned */ or r2, ZERO, r5 /* r5 = buffer pointer */ or r3, ZERO, r6 /* r6 = original length */ andi r2, 2, r7 beq r7, ZERO, t0 /* It's buf long aligned */ /* we assume buf short aligned */ beqi r3, 1, t1 /* Size = 1 */ /* Short must be checksummed */ ld.uw r2, 0, r7 /* r7 = word to be checksumed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ addi r6, -2, r6 addi r5, 2, r5 /* r5 is now long aligned */ beq r6, ZERO, t4 /* Exit if done */ or ZERO, ZERO, r7 /* Clean up r7 */ .long_aligned: bgt r8, r6, t3 /* 8 Longs to be checksummed */ ld.l r5, 0, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ ld.l r5, 4, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ ld.l r5, 8, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ ld.l r5, 12, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ ld.l r5, 16, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ ld.l r5, 20, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ ld.l r5, 24, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ ld.l r5, 28, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ sub r6, r8, r6 add r5, r8, r5 blink t0, ZERO .long_footer: movi 4, r8 bgt r8, r6, t2 /* Long to be checksummed */ ld.l r5, 0, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ sub r6, r8, r6 add r5, r8, r5 blink t3, ZERO .word_footer: movi 2, r8 bgt r8, r6, t1 /* Short to be checksummed */ ld.uw r5, 0, r7 /* r7 = data to be checksummed*/ add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */ sub r6, r8, r6 add r5, r8, r5 .byte_footer: beqi r6, 0, t4 /* Short to be checksummed */ ld.ub r5, 0, r7 /* r7 = data to be checksummed*/#ifndef __LITTLE_ENDIAN__ shlli r7, 8, r7#endif add r4, r7, r4 or ZERO, ZERO, r7 mshflo.l r4, r7, r7 shlri r4, 32, r4 add r4, r7, r4 /* Add eventual "carry" */.exit: or r4, ZERO, r2 ptabs r18, t0 blink t0, ZERO#endif /*NOTDEF*//* * 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. *//* * SH-5 ABI convention: * Input parameters: * r2 = const char *src * r3 = char *dst * r4 = int len * r5 = int sum so far computed checksum (may be zero) * r6 = int *src_err_ptr * r7 = int *dst_err_ptr * return value must be in: * r2 returned checksum */#ifndef NOTDEF /* ** This version of _csum_partial_copy_generic is an easy but ** unefficient implementation. ** It's mainteined only for historical reasons. */ .global csum_partial_copy_genericcsum_partial_copy_generic: _ptar .gc_byte_footer, t1 /* t1 = .byte_footer */ _ptar .gc_add_short_loop, t2 /* t2 = checksum eval loop */ _ptar .gc_exiting, t3 /* t3 = add carry... */ or r2, ZERO, r20 /* r20 = source pointer */ or r3, ZERO, r21 /* r21 = destination pointer */ movi 2, r1 /* we assume buf short aligned */ /* Short must be checksummed */.gc_add_short_loop: bgt r1, r4, t1 /* Size = 1 or 0 (remind) */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?