blob: 9db357294be1efdbea0021db9fe653e5e872054d [file] [log] [blame]
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +09001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Quick'n'dirty IP checksum ...
7 *
8 * Copyright (C) 1998, 1999 Ralf Baechle
9 * Copyright (C) 1999 Silicon Graphics, Inc.
10 */
11#include <asm/asm.h>
12#include <asm/regdef.h>
13
14#ifdef CONFIG_64BIT
Atsushi Nemoto52ffe762006-12-08 01:04:31 +090015/*
16 * As we are sharing code base with the mips32 tree (which use the o32 ABI
17 * register definitions). We need to redefine the register definitions from
18 * the n64 ABI register naming to the o32 ABI register naming.
19 */
20#undef t0
21#undef t1
22#undef t2
23#undef t3
24#define t0 $8
25#define t1 $9
26#define t2 $10
27#define t3 $11
28#define t4 $12
29#define t5 $13
30#define t6 $14
31#define t7 $15
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +090032
33#define USE_DOUBLE
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +090034#endif
35
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +090036#ifdef USE_DOUBLE
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +090037
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +090038#define LOAD ld
39#define ADD daddu
40#define NBYTES 8
41
42#else
43
44#define LOAD lw
45#define ADD addu
46#define NBYTES 4
47
48#endif /* USE_DOUBLE */
49
50#define UNIT(unit) ((unit)*NBYTES)
51
52#define ADDC(sum,reg) \
53 ADD sum, reg; \
54 sltu v1, sum, reg; \
55 ADD sum, v1
56
57#define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \
58 LOAD _t0, (offset + UNIT(0))(src); \
59 LOAD _t1, (offset + UNIT(1))(src); \
60 LOAD _t2, (offset + UNIT(2))(src); \
61 LOAD _t3, (offset + UNIT(3))(src); \
62 ADDC(sum, _t0); \
63 ADDC(sum, _t1); \
64 ADDC(sum, _t2); \
65 ADDC(sum, _t3)
66
67#ifdef USE_DOUBLE
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +090068#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +090069 CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3)
70#else
71#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \
72 CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3); \
73 CSUM_BIGCHUNK1(src, offset + 0x10, sum, _t0, _t1, _t2, _t3)
74#endif
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +090075
76/*
77 * a0: source address
78 * a1: length of the area to checksum
79 * a2: partial checksum
80 */
81
82#define src a0
83#define sum v0
84
85 .text
86 .set noreorder
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +090087 .align 5
88LEAF(csum_partial)
89 move sum, zero
Atsushi Nemoto52ffe762006-12-08 01:04:31 +090090 move t7, zero
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +090091
92 sltiu t8, a1, 0x8
93 bnez t8, small_csumcpy /* < 8 bytes to copy */
Atsushi Nemoto52ffe762006-12-08 01:04:31 +090094 move t2, a1
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +090095
Atsushi Nemoto773ff782006-12-08 01:04:45 +090096 andi t7, src, 0x1 /* odd buffer? */
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +090097
98hword_align:
Atsushi Nemoto52ffe762006-12-08 01:04:31 +090099 beqz t7, word_align
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900100 andi t8, src, 0x2
101
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900102 lbu t0, (src)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900103 LONG_SUBU a1, a1, 0x1
104#ifdef __MIPSEL__
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900105 sll t0, t0, 8
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900106#endif
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900107 ADDC(sum, t0)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900108 PTR_ADDU src, src, 0x1
109 andi t8, src, 0x2
110
111word_align:
112 beqz t8, dword_align
113 sltiu t8, a1, 56
114
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900115 lhu t0, (src)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900116 LONG_SUBU a1, a1, 0x2
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900117 ADDC(sum, t0)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900118 sltiu t8, a1, 56
119 PTR_ADDU src, src, 0x2
120
121dword_align:
122 bnez t8, do_end_words
123 move t8, a1
124
125 andi t8, src, 0x4
126 beqz t8, qword_align
127 andi t8, src, 0x8
128
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900129 lw t0, 0x00(src)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900130 LONG_SUBU a1, a1, 0x4
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900131 ADDC(sum, t0)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900132 PTR_ADDU src, src, 0x4
133 andi t8, src, 0x8
134
135qword_align:
136 beqz t8, oword_align
137 andi t8, src, 0x10
138
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +0900139#ifdef USE_DOUBLE
140 ld t0, 0x00(src)
141 LONG_SUBU a1, a1, 0x8
142 ADDC(sum, t0)
143#else
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900144 lw t0, 0x00(src)
145 lw t1, 0x04(src)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900146 LONG_SUBU a1, a1, 0x8
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900147 ADDC(sum, t0)
148 ADDC(sum, t1)
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +0900149#endif
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900150 PTR_ADDU src, src, 0x8
151 andi t8, src, 0x10
152
153oword_align:
154 beqz t8, begin_movement
155 LONG_SRL t8, a1, 0x7
156
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +0900157#ifdef USE_DOUBLE
158 ld t0, 0x00(src)
159 ld t1, 0x08(src)
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900160 ADDC(sum, t0)
161 ADDC(sum, t1)
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +0900162#else
163 CSUM_BIGCHUNK1(src, 0x00, sum, t0, t1, t3, t4)
164#endif
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900165 LONG_SUBU a1, a1, 0x10
166 PTR_ADDU src, src, 0x10
167 LONG_SRL t8, a1, 0x7
168
169begin_movement:
170 beqz t8, 1f
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900171 andi t2, a1, 0x40
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900172
173move_128bytes:
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900174 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
175 CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
176 CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
177 CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900178 LONG_SUBU t8, t8, 0x01
179 bnez t8, move_128bytes
180 PTR_ADDU src, src, 0x80
181
1821:
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900183 beqz t2, 1f
184 andi t2, a1, 0x20
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900185
186move_64bytes:
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900187 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
188 CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900189 PTR_ADDU src, src, 0x40
190
1911:
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900192 beqz t2, do_end_words
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900193 andi t8, a1, 0x1c
194
195move_32bytes:
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900196 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900197 andi t8, a1, 0x1c
198 PTR_ADDU src, src, 0x20
199
200do_end_words:
Atsushi Nemoto773ff782006-12-08 01:04:45 +0900201 beqz t8, small_csumcpy
202 andi t2, a1, 0x3
203 LONG_SRL t8, t8, 0x2
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900204
205end_words:
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900206 lw t0, (src)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900207 LONG_SUBU t8, t8, 0x1
Atsushi Nemoto52ffe762006-12-08 01:04:31 +0900208 ADDC(sum, t0)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900209 bnez t8, end_words
210 PTR_ADDU src, src, 0x4
211
Atsushi Nemoto773ff782006-12-08 01:04:45 +0900212/* unknown src alignment and < 8 bytes to go */
213small_csumcpy:
214 move a1, t2
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900215
Atsushi Nemoto773ff782006-12-08 01:04:45 +0900216 andi t0, a1, 4
217 beqz t0, 1f
218 andi t0, a1, 2
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900219
Atsushi Nemoto773ff782006-12-08 01:04:45 +0900220 /* Still a full word to go */
221 ulw t1, (src)
222 PTR_ADDIU src, 4
223 ADDC(sum, t1)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900224
Atsushi Nemoto773ff782006-12-08 01:04:45 +09002251: move t1, zero
226 beqz t0, 1f
227 andi t0, a1, 1
228
229 /* Still a halfword to go */
230 ulhu t1, (src)
231 PTR_ADDIU src, 2
232
2331: beqz t0, 1f
234 sll t1, t1, 16
235
236 lbu t2, (src)
237 nop
238
239#ifdef __MIPSEB__
240 sll t2, t2, 8
241#endif
242 or t1, t2
243
2441: ADDC(sum, t1)
245
246 /* fold checksum */
Atsushi Nemotoed99e2b2006-12-08 01:04:51 +0900247#ifdef USE_DOUBLE
248 dsll32 v1, sum, 0
249 daddu sum, v1
250 sltu v1, sum, v1
251 dsra32 sum, sum, 0
252 addu sum, v1
253#endif
Atsushi Nemoto773ff782006-12-08 01:04:45 +0900254 sll v1, sum, 16
255 addu sum, v1
256 sltu v1, sum, v1
257 srl sum, sum, 16
258 addu sum, v1
259
260 /* odd buffer alignment? */
261 beqz t7, 1f
262 nop
263 sll v1, sum, 8
264 srl sum, sum, 8
265 or sum, v1
266 andi sum, 0xffff
2671:
268 .set reorder
269 /* Add the passed partial csum. */
270 ADDC(sum, a2)
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900271 jr ra
Atsushi Nemoto773ff782006-12-08 01:04:45 +0900272 .set noreorder
Atsushi Nemoto0bcdda02006-12-04 00:42:59 +0900273 END(csum_partial)