Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sh/lib/checksum.S
10817 views
1
/* $Id: checksum.S,v 1.10 2001/07/06 13:11:32 gniibe Exp $
2
*
3
* INET An implementation of the TCP/IP protocol suite for the LINUX
4
* operating system. INET is implemented using the BSD Socket
5
* interface as the means of communication with the user level.
6
*
7
* IP/TCP/UDP checksumming routines
8
*
9
* Authors: Jorge Cwik, <[email protected]>
10
* Arnt Gulbrandsen, <[email protected]>
11
* Tom May, <[email protected]>
12
* Pentium Pro/II routines:
13
* Alexander Kjeldaas <[email protected]>
14
* Finn Arne Gangstad <[email protected]>
15
* Lots of code moved from tcp.c and ip.c; see those files
16
* for more names.
17
*
18
* Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
19
* handling.
20
* Andi Kleen, add zeroing on error
21
* converted to pure assembler
22
*
23
* SuperH version: Copyright (C) 1999 Niibe Yutaka
24
*
25
* This program is free software; you can redistribute it and/or
26
* modify it under the terms of the GNU General Public License
27
* as published by the Free Software Foundation; either version
28
* 2 of the License, or (at your option) any later version.
29
*/
30
31
#include <asm/errno.h>
32
#include <linux/linkage.h>
33
34
/*
35
* computes a partial checksum, e.g. for TCP/UDP fragments
36
*/
37
38
/*
39
* asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum);
40
*/
41
42
.text
43
ENTRY(csum_partial)
44
/*
45
* Experiments with Ethernet and SLIP connections show that buff
46
* is aligned on either a 2-byte or 4-byte boundary. We get at
47
* least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
48
* Fortunately, it is easy to convert 2-byte alignment to 4-byte
49
* alignment for the unrolled loop.
50
*/
51
mov r4, r0
52
tst #3, r0 ! Check alignment.
53
bt/s 2f ! Jump if alignment is ok.
54
mov r4, r7 ! Keep a copy to check for alignment
55
!
56
tst #1, r0 ! Check alignment.
57
bt 21f ! Jump if alignment is boundary of 2bytes.
58
59
! buf is odd
60
tst r5, r5
61
add #-1, r5
62
bt 9f
63
mov.b @r4+, r0
64
extu.b r0, r0
65
addc r0, r6 ! t=0 from previous tst
66
mov r6, r0
67
shll8 r6
68
shlr16 r0
69
shlr8 r0
70
or r0, r6
71
mov r4, r0
72
tst #2, r0
73
bt 2f
74
21:
75
! buf is 2 byte aligned (len could be 0)
76
add #-2, r5 ! Alignment uses up two bytes.
77
cmp/pz r5 !
78
bt/s 1f ! Jump if we had at least two bytes.
79
clrt
80
bra 6f
81
add #2, r5 ! r5 was < 2. Deal with it.
82
1:
83
mov.w @r4+, r0
84
extu.w r0, r0
85
addc r0, r6
86
bf 2f
87
add #1, r6
88
2:
89
! buf is 4 byte aligned (len could be 0)
90
mov r5, r1
91
mov #-5, r0
92
shld r0, r1
93
tst r1, r1
94
bt/s 4f ! if it's =0, go to 4f
95
clrt
96
.align 2
97
3:
98
mov.l @r4+, r0
99
mov.l @r4+, r2
100
mov.l @r4+, r3
101
addc r0, r6
102
mov.l @r4+, r0
103
addc r2, r6
104
mov.l @r4+, r2
105
addc r3, r6
106
mov.l @r4+, r3
107
addc r0, r6
108
mov.l @r4+, r0
109
addc r2, r6
110
mov.l @r4+, r2
111
addc r3, r6
112
addc r0, r6
113
addc r2, r6
114
movt r0
115
dt r1
116
bf/s 3b
117
cmp/eq #1, r0
118
! here, we know r1==0
119
addc r1, r6 ! add carry to r6
120
4:
121
mov r5, r0
122
and #0x1c, r0
123
tst r0, r0
124
bt 6f
125
! 4 bytes or more remaining
126
mov r0, r1
127
shlr2 r1
128
mov #0, r2
129
5:
130
addc r2, r6
131
mov.l @r4+, r2
132
movt r0
133
dt r1
134
bf/s 5b
135
cmp/eq #1, r0
136
addc r2, r6
137
addc r1, r6 ! r1==0 here, so it means add carry-bit
138
6:
139
! 3 bytes or less remaining
140
mov #3, r0
141
and r0, r5
142
tst r5, r5
143
bt 9f ! if it's =0 go to 9f
144
mov #2, r1
145
cmp/hs r1, r5
146
bf 7f
147
mov.w @r4+, r0
148
extu.w r0, r0
149
cmp/eq r1, r5
150
bt/s 8f
151
clrt
152
shll16 r0
153
addc r0, r6
154
7:
155
mov.b @r4+, r0
156
extu.b r0, r0
157
#ifndef __LITTLE_ENDIAN__
158
shll8 r0
159
#endif
160
8:
161
addc r0, r6
162
mov #0, r0
163
addc r0, r6
164
9:
165
! Check if the buffer was misaligned, if so realign sum
166
mov r7, r0
167
tst #1, r0
168
bt 10f
169
mov r6, r0
170
shll8 r6
171
shlr16 r0
172
shlr8 r0
173
or r0, r6
174
10:
175
rts
176
mov r6, r0
177
178
/*
179
unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
180
int sum, int *src_err_ptr, int *dst_err_ptr)
181
*/
182
183
/*
184
* Copy from ds while checksumming, otherwise like csum_partial
185
*
186
* The macros SRC and DST specify the type of access for the instruction.
187
* thus we can call a custom exception handler for all access types.
188
*
189
* FIXME: could someone double-check whether I haven't mixed up some SRC and
190
* DST definitions? It's damn hard to trigger all cases. I hope I got
191
* them all but there's no guarantee.
192
*/
193
194
#define SRC(...) \
195
9999: __VA_ARGS__ ; \
196
.section __ex_table, "a"; \
197
.long 9999b, 6001f ; \
198
.previous
199
200
#define DST(...) \
201
9999: __VA_ARGS__ ; \
202
.section __ex_table, "a"; \
203
.long 9999b, 6002f ; \
204
.previous
205
206
!
207
! r4: const char *SRC
208
! r5: char *DST
209
! r6: int LEN
210
! r7: int SUM
211
!
212
! on stack:
213
! int *SRC_ERR_PTR
214
! int *DST_ERR_PTR
215
!
216
ENTRY(csum_partial_copy_generic)
217
mov.l r5,@-r15
218
mov.l r6,@-r15
219
220
mov #3,r0 ! Check src and dest are equally aligned
221
mov r4,r1
222
and r0,r1
223
and r5,r0
224
cmp/eq r1,r0
225
bf 3f ! Different alignments, use slow version
226
tst #1,r0 ! Check dest word aligned
227
bf 3f ! If not, do it the slow way
228
229
mov #2,r0
230
tst r0,r5 ! Check dest alignment.
231
bt 2f ! Jump if alignment is ok.
232
add #-2,r6 ! Alignment uses up two bytes.
233
cmp/pz r6 ! Jump if we had at least two bytes.
234
bt/s 1f
235
clrt
236
add #2,r6 ! r6 was < 2. Deal with it.
237
bra 4f
238
mov r6,r2
239
240
3: ! Handle different src and dest alignments.
241
! This is not common, so simple byte by byte copy will do.
242
mov r6,r2
243
shlr r6
244
tst r6,r6
245
bt 4f
246
clrt
247
.align 2
248
5:
249
SRC( mov.b @r4+,r1 )
250
SRC( mov.b @r4+,r0 )
251
extu.b r1,r1
252
DST( mov.b r1,@r5 )
253
DST( mov.b r0,@(1,r5) )
254
extu.b r0,r0
255
add #2,r5
256
257
#ifdef __LITTLE_ENDIAN__
258
shll8 r0
259
#else
260
shll8 r1
261
#endif
262
or r1,r0
263
264
addc r0,r7
265
movt r0
266
dt r6
267
bf/s 5b
268
cmp/eq #1,r0
269
mov #0,r0
270
addc r0, r7
271
272
mov r2, r0
273
tst #1, r0
274
bt 7f
275
bra 5f
276
clrt
277
278
! src and dest equally aligned, but to a two byte boundary.
279
! Handle first two bytes as a special case
280
.align 2
281
1:
282
SRC( mov.w @r4+,r0 )
283
DST( mov.w r0,@r5 )
284
add #2,r5
285
extu.w r0,r0
286
addc r0,r7
287
mov #0,r0
288
addc r0,r7
289
2:
290
mov r6,r2
291
mov #-5,r0
292
shld r0,r6
293
tst r6,r6
294
bt/s 2f
295
clrt
296
.align 2
297
1:
298
SRC( mov.l @r4+,r0 )
299
SRC( mov.l @r4+,r1 )
300
addc r0,r7
301
DST( mov.l r0,@r5 )
302
DST( mov.l r1,@(4,r5) )
303
addc r1,r7
304
305
SRC( mov.l @r4+,r0 )
306
SRC( mov.l @r4+,r1 )
307
addc r0,r7
308
DST( mov.l r0,@(8,r5) )
309
DST( mov.l r1,@(12,r5) )
310
addc r1,r7
311
312
SRC( mov.l @r4+,r0 )
313
SRC( mov.l @r4+,r1 )
314
addc r0,r7
315
DST( mov.l r0,@(16,r5) )
316
DST( mov.l r1,@(20,r5) )
317
addc r1,r7
318
319
SRC( mov.l @r4+,r0 )
320
SRC( mov.l @r4+,r1 )
321
addc r0,r7
322
DST( mov.l r0,@(24,r5) )
323
DST( mov.l r1,@(28,r5) )
324
addc r1,r7
325
add #32,r5
326
movt r0
327
dt r6
328
bf/s 1b
329
cmp/eq #1,r0
330
mov #0,r0
331
addc r0,r7
332
333
2: mov r2,r6
334
mov #0x1c,r0
335
and r0,r6
336
cmp/pl r6
337
bf/s 4f
338
clrt
339
shlr2 r6
340
3:
341
SRC( mov.l @r4+,r0 )
342
addc r0,r7
343
DST( mov.l r0,@r5 )
344
add #4,r5
345
movt r0
346
dt r6
347
bf/s 3b
348
cmp/eq #1,r0
349
mov #0,r0
350
addc r0,r7
351
4: mov r2,r6
352
mov #3,r0
353
and r0,r6
354
cmp/pl r6
355
bf 7f
356
mov #2,r1
357
cmp/hs r1,r6
358
bf 5f
359
SRC( mov.w @r4+,r0 )
360
DST( mov.w r0,@r5 )
361
extu.w r0,r0
362
add #2,r5
363
cmp/eq r1,r6
364
bt/s 6f
365
clrt
366
shll16 r0
367
addc r0,r7
368
5:
369
SRC( mov.b @r4+,r0 )
370
DST( mov.b r0,@r5 )
371
extu.b r0,r0
372
#ifndef __LITTLE_ENDIAN__
373
shll8 r0
374
#endif
375
6: addc r0,r7
376
mov #0,r0
377
addc r0,r7
378
7:
379
5000:
380
381
# Exception handler:
382
.section .fixup, "ax"
383
384
6001:
385
mov.l @(8,r15),r0 ! src_err_ptr
386
mov #-EFAULT,r1
387
mov.l r1,@r0
388
389
! zero the complete destination - computing the rest
390
! is too much work
391
mov.l @(4,r15),r5 ! dst
392
mov.l @r15,r6 ! len
393
mov #0,r7
394
1: mov.b r7,@r5
395
dt r6
396
bf/s 1b
397
add #1,r5
398
mov.l 8000f,r0
399
jmp @r0
400
nop
401
.align 2
402
8000: .long 5000b
403
404
6002:
405
mov.l @(12,r15),r0 ! dst_err_ptr
406
mov #-EFAULT,r1
407
mov.l r1,@r0
408
mov.l 8001f,r0
409
jmp @r0
410
nop
411
.align 2
412
8001: .long 5000b
413
414
.previous
415
add #8,r15
416
rts
417
mov r7,r0
418
419