📄 csum_partial.s
字号:
/* * 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. * * Quick'n'dirty IP checksum ... * * Copyright (C) 1998, 1999 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */#include <linux/errno.h>#include <asm/asm.h>#include <asm/asm-offsets.h>#include <asm/regdef.h>#ifdef CONFIG_64BIT/* * As we are sharing code base with the mips32 tree (which use the o32 ABI * register definitions). We need to redefine the register definitions from * the n64 ABI register naming to the o32 ABI register naming. */#undef t0#undef t1#undef t2#undef t3#define t0 $8#define t1 $9#define t2 $10#define t3 $11#define t4 $12#define t5 $13#define t6 $14#define t7 $15#define USE_DOUBLE#endif#ifdef USE_DOUBLE#define LOAD ld#define ADD daddu#define NBYTES 8#else#define LOAD lw#define ADD addu#define NBYTES 4#endif /* USE_DOUBLE */#define UNIT(unit) ((unit)*NBYTES)#define ADDC(sum,reg) \ ADD sum, reg; \ sltu v1, sum, reg; \ ADD sum, v1#define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \ LOAD _t0, (offset + UNIT(0))(src); \ LOAD _t1, (offset + UNIT(1))(src); \ LOAD _t2, (offset + UNIT(2))(src); \ LOAD _t3, (offset + UNIT(3))(src); \ ADDC(sum, _t0); \ ADDC(sum, _t1); \ ADDC(sum, _t2); \ ADDC(sum, _t3)#ifdef USE_DOUBLE#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \ CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3)#else#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \ CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3); \ CSUM_BIGCHUNK1(src, offset + 0x10, sum, _t0, _t1, _t2, _t3)#endif/* * a0: source address * a1: length of the area to checksum * a2: partial checksum */#define src a0#define sum v0 .text .set noreorder .align 5LEAF(csum_partial) move sum, zero move t7, zero sltiu t8, a1, 0x8 bnez t8, small_csumcpy /* < 8 bytes to copy */ move t2, a1 andi t7, src, 0x1 /* odd buffer? */hword_align: beqz t7, word_align andi t8, src, 0x2 lbu t0, (src) LONG_SUBU a1, a1, 0x1#ifdef __MIPSEL__ sll t0, t0, 8#endif ADDC(sum, t0) PTR_ADDU src, src, 0x1 andi t8, src, 0x2word_align: beqz t8, dword_align sltiu t8, a1, 56 lhu t0, (src) LONG_SUBU a1, a1, 0x2 ADDC(sum, t0) sltiu t8, a1, 56 PTR_ADDU src, src, 0x2dword_align: bnez t8, do_end_words move t8, a1 andi t8, src, 0x4 beqz t8, qword_align andi t8, src, 0x8 lw t0, 0x00(src) LONG_SUBU a1, a1, 0x4 ADDC(sum, t0) PTR_ADDU src, src, 0x4 andi t8, src, 0x8qword_align: beqz t8, oword_align andi t8, src, 0x10#ifdef USE_DOUBLE ld t0, 0x00(src) LONG_SUBU a1, a1, 0x8 ADDC(sum, t0)#else lw t0, 0x00(src) lw t1, 0x04(src) LONG_SUBU a1, a1, 0x8 ADDC(sum, t0) ADDC(sum, t1)#endif PTR_ADDU src, src, 0x8 andi t8, src, 0x10oword_align: beqz t8, begin_movement LONG_SRL t8, a1, 0x7#ifdef USE_DOUBLE ld t0, 0x00(src) ld t1, 0x08(src) ADDC(sum, t0) ADDC(sum, t1)#else CSUM_BIGCHUNK1(src, 0x00, sum, t0, t1, t3, t4)#endif LONG_SUBU a1, a1, 0x10 PTR_ADDU src, src, 0x10 LONG_SRL t8, a1, 0x7begin_movement: beqz t8, 1f andi t2, a1, 0x40move_128bytes: CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4) CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4) CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4) LONG_SUBU t8, t8, 0x01 bnez t8, move_128bytes PTR_ADDU src, src, 0x801: beqz t2, 1f andi t2, a1, 0x20move_64bytes: CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4) PTR_ADDU src, src, 0x401: beqz t2, do_end_words andi t8, a1, 0x1cmove_32bytes: CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) andi t8, a1, 0x1c PTR_ADDU src, src, 0x20do_end_words: beqz t8, small_csumcpy andi t2, a1, 0x3 LONG_SRL t8, t8, 0x2end_words: lw t0, (src) LONG_SUBU t8, t8, 0x1 ADDC(sum, t0) bnez t8, end_words PTR_ADDU src, src, 0x4/* unknown src alignment and < 8 bytes to go */small_csumcpy: move a1, t2 andi t0, a1, 4 beqz t0, 1f andi t0, a1, 2 /* Still a full word to go */ ulw t1, (src) PTR_ADDIU src, 4 ADDC(sum, t1)1: move t1, zero beqz t0, 1f andi t0, a1, 1 /* Still a halfword to go */ ulhu t1, (src) PTR_ADDIU src, 21: beqz t0, 1f sll t1, t1, 16 lbu t2, (src) nop#ifdef __MIPSEB__ sll t2, t2, 8#endif or t1, t21: ADDC(sum, t1) /* fold checksum */#ifdef USE_DOUBLE dsll32 v1, sum, 0 daddu sum, v1 sltu v1, sum, v1 dsra32 sum, sum, 0 addu sum, v1#endif sll v1, sum, 16 addu sum, v1 sltu v1, sum, v1 srl sum, sum, 16 addu sum, v1 /* odd buffer alignment? */ beqz t7, 1f nop sll v1, sum, 8 srl sum, sum, 8 or sum, v1 andi sum, 0xffff1: .set reorder /* Add the passed partial csum. */ ADDC(sum, a2) jr ra .set noreorder END(csum_partial)/* * checksum and copy routines based on memcpy.S * * csum_partial_copy_nocheck(src, dst, len, sum) * __csum_partial_copy_user(src, dst, len, sum, errp) * * See "Spec" in memcpy.S for details. Unlike __copy_user, all * function in this file use the standard calling convention. */#define src a0#define dst a1#define len a2#define psum a3#define sum v0#define odd t8#define errptr t9/* * The exception handler for loads requires that: * 1- AT contain the address of the byte just past the end of the source * of the copy, * 2- src_entry <= src < AT, and * 3- (dst - src) == (dst_entry - src_entry), * The _entry suffix denotes values when __copy_user was called. * * (1) is set up up by __csum_partial_copy_from_user and maintained by * not writing AT in __csum_partial_copy * (2) is met by incrementing src by the number of bytes copied * (3) is met by not doing loads between a pair of increments of dst and src * * The exception handlers for stores stores -EFAULT to errptr and return. * These handlers do not need to overwrite any data. */#define EXC(inst_reg,addr,handler) \9: inst_reg, addr; \ .section __ex_table,"a"; \ PTR 9b, handler; \ .previous#ifdef USE_DOUBLE#define LOAD ld#define LOADL ldl#define LOADR ldr#define STOREL sdl#define STORER sdr#define STORE sd#define ADD daddu#define SUB dsubu#define SRL dsrl#define SLL dsll#define SLLV dsllv#define SRLV dsrlv#define NBYTES 8#define LOG_NBYTES 3#else#define LOAD lw#define LOADL lwl#define LOADR lwr#define STOREL swl#define STORER swr#define STORE sw#define ADD addu#define SUB subu#define SRL srl#define SLL sll#define SLLV sllv#define SRLV srlv#define NBYTES 4#define LOG_NBYTES 2#endif /* USE_DOUBLE */#ifdef CONFIG_CPU_LITTLE_ENDIAN#define LDFIRST LOADR#define LDREST LOADL#define STFIRST STORER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -