1
2
3
4
5
6
7
8
9
10
11
12#include <linux/errno.h>
13#include <asm/asm.h>
14#include <asm/asm-offsets.h>
15#include <asm/regdef.h>
16
17#ifdef CONFIG_64BIT
18
19
20
21
22
23#undef t0
24#undef t1
25#undef t2
26#undef t3
27#define t0 $8
28#define t1 $9
29#define t2 $10
30#define t3 $11
31#define t4 $12
32#define t5 $13
33#define t6 $14
34#define t7 $15
35
36#define USE_DOUBLE
37#endif
38
39#ifdef USE_DOUBLE
40
41#define LOAD ld
42#define LOAD32 lwu
43#define ADD daddu
44#define NBYTES 8
45
46#else
47
48#define LOAD lw
49#define LOAD32 lw
50#define ADD addu
51#define NBYTES 4
52
53#endif
54
55#define UNIT(unit) ((unit)*NBYTES)
56
57#define ADDC(sum,reg) \
58 ADD sum, reg; \
59 sltu v1, sum, reg; \
60 ADD sum, v1; \
61
62#define ADDC32(sum,reg) \
63 addu sum, reg; \
64 sltu v1, sum, reg; \
65 addu sum, v1; \
66
67#define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \
68 LOAD _t0, (offset + UNIT(0))(src); \
69 LOAD _t1, (offset + UNIT(1))(src); \
70 LOAD _t2, (offset + UNIT(2))(src); \
71 LOAD _t3, (offset + UNIT(3))(src); \
72 ADDC(sum, _t0); \
73 ADDC(sum, _t1); \
74 ADDC(sum, _t2); \
75 ADDC(sum, _t3)
76
77#ifdef USE_DOUBLE
78#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \
79 CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3)
80#else
81#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \
82 CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3); \
83 CSUM_BIGCHUNK1(src, offset + 0x10, sum, _t0, _t1, _t2, _t3)
84#endif
85
86
87
88
89
90
91
92#define src a0
93#define sum v0
94
95 .text
96 .set noreorder
97 .align 5
98LEAF(csum_partial)
99 move sum, zero
100 move t7, zero
101
102 sltiu t8, a1, 0x8
103 bnez t8, .Lsmall_csumcpy
104 move t2, a1
105
106 andi t7, src, 0x1
107
108.Lhword_align:
109 beqz t7, .Lword_align
110 andi t8, src, 0x2
111
112 lbu t0, (src)
113 LONG_SUBU a1, a1, 0x1
114#ifdef __MIPSEL__
115 sll t0, t0, 8
116#endif
117 ADDC(sum, t0)
118 PTR_ADDU src, src, 0x1
119 andi t8, src, 0x2
120
121.Lword_align:
122 beqz t8, .Ldword_align
123 sltiu t8, a1, 56
124
125 lhu t0, (src)
126 LONG_SUBU a1, a1, 0x2
127 ADDC(sum, t0)
128 sltiu t8, a1, 56
129 PTR_ADDU src, src, 0x2
130
131.Ldword_align:
132 bnez t8, .Ldo_end_words
133 move t8, a1
134
135 andi t8, src, 0x4
136 beqz t8, .Lqword_align
137 andi t8, src, 0x8
138
139 LOAD32 t0, 0x00(src)
140 LONG_SUBU a1, a1, 0x4
141 ADDC(sum, t0)
142 PTR_ADDU src, src, 0x4
143 andi t8, src, 0x8
144
145.Lqword_align:
146 beqz t8, .Loword_align
147 andi t8, src, 0x10
148
149#ifdef USE_DOUBLE
150 ld t0, 0x00(src)
151 LONG_SUBU a1, a1, 0x8
152 ADDC(sum, t0)
153#else
154 lw t0, 0x00(src)
155 lw t1, 0x04(src)
156 LONG_SUBU a1, a1, 0x8
157 ADDC(sum, t0)
158 ADDC(sum, t1)
159#endif
160 PTR_ADDU src, src, 0x8
161 andi t8, src, 0x10
162
163.Loword_align:
164 beqz t8, .Lbegin_movement
165 LONG_SRL t8, a1, 0x7
166
167#ifdef USE_DOUBLE
168 ld t0, 0x00(src)
169 ld t1, 0x08(src)
170 ADDC(sum, t0)
171 ADDC(sum, t1)
172#else
173 CSUM_BIGCHUNK1(src, 0x00, sum, t0, t1, t3, t4)
174#endif
175 LONG_SUBU a1, a1, 0x10
176 PTR_ADDU src, src, 0x10
177 LONG_SRL t8, a1, 0x7
178
179.Lbegin_movement:
180 beqz t8, 1f
181 andi t2, a1, 0x40
182
183.Lmove_128bytes:
184 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
185 CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
186 CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
187 CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
188 LONG_SUBU t8, t8, 0x01
189 .set reorder
190 PTR_ADDU src, src, 0x80
191 bnez t8, .Lmove_128bytes
192 .set noreorder
193
1941:
195 beqz t2, 1f
196 andi t2, a1, 0x20
197
198.Lmove_64bytes:
199 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
200 CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
201 PTR_ADDU src, src, 0x40
202
2031:
204 beqz t2, .Ldo_end_words
205 andi t8, a1, 0x1c
206
207.Lmove_32bytes:
208 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
209 andi t8, a1, 0x1c
210 PTR_ADDU src, src, 0x20
211
212.Ldo_end_words:
213 beqz t8, .Lsmall_csumcpy
214 andi t2, a1, 0x3
215 LONG_SRL t8, t8, 0x2
216
217.Lend_words:
218 LOAD32 t0, (src)
219 LONG_SUBU t8, t8, 0x1
220 ADDC(sum, t0)
221 .set reorder
222 PTR_ADDU src, src, 0x4
223 bnez t8, .Lend_words
224 .set noreorder
225
226
227.Lsmall_csumcpy:
228 move a1, t2
229
230 andi t0, a1, 4
231 beqz t0, 1f
232 andi t0, a1, 2
233
234
235 ulw t1, (src)
236 PTR_ADDIU src, 4
237#ifdef USE_DOUBLE
238 dsll t1, t1, 32
239#endif
240 ADDC(sum, t1)
241
2421: move t1, zero
243 beqz t0, 1f
244 andi t0, a1, 1
245
246
247 ulhu t1, (src)
248 PTR_ADDIU src, 2
249
2501: beqz t0, 1f
251 sll t1, t1, 16
252
253 lbu t2, (src)
254 nop
255
256#ifdef __MIPSEB__
257 sll t2, t2, 8
258#endif
259 or t1, t2
260
2611: ADDC(sum, t1)
262
263
264#ifdef USE_DOUBLE
265 dsll32 v1, sum, 0
266 daddu sum, v1
267 sltu v1, sum, v1
268 dsra32 sum, sum, 0
269 addu sum, v1
270#endif
271
272
273#ifdef CPU_MIPSR2
274 wsbh v1, sum
275 movn sum, v1, t7
276#else
277 beqz t7, 1f
278 lui v1, 0x00ff
279 addu v1, 0x00ff
280 and t0, sum, v1
281 sll t0, t0, 8
282 srl sum, sum, 8
283 and sum, sum, v1
284 or sum, sum, t0
2851:
286#endif
287 .set reorder
288
289 ADDC32(sum, a2)
290 jr ra
291 .set noreorder
292 END(csum_partial)
293
294
295
296
297
298
299
300
301
302
303
304
305#define src a0
306#define dst a1
307#define len a2
308#define psum a3
309#define sum v0
310#define odd t8
311#define errptr t9
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330#define EXC(inst_reg,addr,handler) \
3319: inst_reg, addr; \
332 .section __ex_table,"a"; \
333 PTR 9b, handler; \
334 .previous
335
336#ifdef USE_DOUBLE
337
338#define LOAD ld
339#define LOADL ldl
340#define LOADR ldr
341#define STOREL sdl
342#define STORER sdr
343#define STORE sd
344#define ADD daddu
345#define SUB dsubu
346#define SRL dsrl
347#define SLL dsll
348#define SLLV dsllv
349#define SRLV dsrlv
350#define NBYTES 8
351#define LOG_NBYTES 3
352
353#else
354
355#define LOAD lw
356#define LOADL lwl
357#define LOADR lwr
358#define STOREL swl
359#define STORER swr
360#define STORE sw
361#define ADD addu
362#define SUB subu
363#define SRL srl
364#define SLL sll
365#define SLLV sllv
366#define SRLV srlv
367#define NBYTES 4
368#define LOG_NBYTES 2
369
370#endif
371
372#ifdef CONFIG_CPU_LITTLE_ENDIAN
373#define LDFIRST LOADR
374#define LDREST LOADL
375#define STFIRST STORER
376#define STREST STOREL
377#define SHIFT_DISCARD SLLV
378#define SHIFT_DISCARD_REVERT SRLV
379#else
380#define LDFIRST LOADL
381#define LDREST LOADR
382#define STFIRST STOREL
383#define STREST STORER
384#define SHIFT_DISCARD SRLV
385#define SHIFT_DISCARD_REVERT SLLV
386#endif
387
388#define FIRST(unit) ((unit)*NBYTES)
389#define REST(unit) (FIRST(unit)+NBYTES-1)
390
391#define ADDRMASK (NBYTES-1)
392
393#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
394 .set noat
395#else
396 .set at=v1
397#endif
398
399LEAF(__csum_partial_copy_user)
400 PTR_ADDU AT, src, len
401#ifdef CONFIG_64BIT
402 move errptr, a4
403#else
404 lw errptr, 16(sp)
405#endif
406FEXPORT(csum_partial_copy_nocheck)
407 move sum, zero
408 move odd, zero
409
410
411
412
413
414
415
416
417
418
419
420 sltu t2, len, NBYTES
421 and t1, dst, ADDRMASK
422 bnez t2, .Lcopy_bytes_checklen
423 and t0, src, ADDRMASK
424 andi odd, dst, 0x1
425 bnez t1, .Ldst_unaligned
426 nop
427 bnez t0, .Lsrc_unaligned_dst_aligned
428
429
430
431
432.Lboth_aligned:
433 SRL t0, len, LOG_NBYTES+3
434 beqz t0, .Lcleanup_both_aligned
435 nop
436 SUB len, 8*NBYTES
437 .align 4
4381:
439EXC( LOAD t0, UNIT(0)(src), .Ll_exc)
440EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy)
441EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy)
442EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy)
443EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy)
444EXC( LOAD t5, UNIT(5)(src), .Ll_exc_copy)
445EXC( LOAD t6, UNIT(6)(src), .Ll_exc_copy)
446EXC( LOAD t7, UNIT(7)(src), .Ll_exc_copy)
447 SUB len, len, 8*NBYTES
448 ADD src, src, 8*NBYTES
449EXC( STORE t0, UNIT(0)(dst), .Ls_exc)
450 ADDC(sum, t0)
451EXC( STORE t1, UNIT(1)(dst), .Ls_exc)
452 ADDC(sum, t1)
453EXC( STORE t2, UNIT(2)(dst), .Ls_exc)
454 ADDC(sum, t2)
455EXC( STORE t3, UNIT(3)(dst), .Ls_exc)
456 ADDC(sum, t3)
457EXC( STORE t4, UNIT(4)(dst), .Ls_exc)
458 ADDC(sum, t4)
459EXC( STORE t5, UNIT(5)(dst), .Ls_exc)
460 ADDC(sum, t5)
461EXC( STORE t6, UNIT(6)(dst), .Ls_exc)
462 ADDC(sum, t6)
463EXC( STORE t7, UNIT(7)(dst), .Ls_exc)
464 ADDC(sum, t7)
465 .set reorder
466 ADD dst, dst, 8*NBYTES
467 bgez len, 1b
468 .set noreorder
469 ADD len, 8*NBYTES
470
471
472
473
474.Lcleanup_both_aligned:
475#define rem t7
476 beqz len, .Ldone
477 sltu t0, len, 4*NBYTES
478 bnez t0, .Lless_than_4units
479 and rem, len, (NBYTES-1)
480
481
482
483EXC( LOAD t0, UNIT(0)(src), .Ll_exc)
484EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy)
485EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy)
486EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy)
487 SUB len, len, 4*NBYTES
488 ADD src, src, 4*NBYTES
489EXC( STORE t0, UNIT(0)(dst), .Ls_exc)
490 ADDC(sum, t0)
491EXC( STORE t1, UNIT(1)(dst), .Ls_exc)
492 ADDC(sum, t1)
493EXC( STORE t2, UNIT(2)(dst), .Ls_exc)
494 ADDC(sum, t2)
495EXC( STORE t3, UNIT(3)(dst), .Ls_exc)
496 ADDC(sum, t3)
497 .set reorder
498 ADD dst, dst, 4*NBYTES
499 beqz len, .Ldone
500 .set noreorder
501.Lless_than_4units:
502
503
504
505 beq rem, len, .Lcopy_bytes
506 nop
5071:
508EXC( LOAD t0, 0(src), .Ll_exc)
509 ADD src, src, NBYTES
510 SUB len, len, NBYTES
511EXC( STORE t0, 0(dst), .Ls_exc)
512 ADDC(sum, t0)
513 .set reorder
514 ADD dst, dst, NBYTES
515 bne rem, len, 1b
516 .set noreorder
517
518
519
520
521
522
523
524
525
526
527
528
529#define bits t2
530 beqz len, .Ldone
531 ADD t1, dst, len
532 li bits, 8*NBYTES
533 SLL rem, len, 3
534EXC( LOAD t0, 0(src), .Ll_exc)
535 SUB bits, bits, rem
536 SHIFT_DISCARD t0, t0, bits
537EXC( STREST t0, -1(t1), .Ls_exc)
538 SHIFT_DISCARD_REVERT t0, t0, bits
539 .set reorder
540 ADDC(sum, t0)
541 b .Ldone
542 .set noreorder
543.Ldst_unaligned:
544
545
546
547
548
549
550
551
552
553#define match rem
554EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc)
555 ADD t2, zero, NBYTES
556EXC( LDREST t3, REST(0)(src), .Ll_exc_copy)
557 SUB t2, t2, t1
558 xor match, t0, t1
559EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc)
560 SLL t4, t1, 3
561 SHIFT_DISCARD t3, t3, t4
562
563 ADDC(sum, t3)
564 beq len, t2, .Ldone
565 SUB len, len, t2
566 ADD dst, dst, t2
567 beqz match, .Lboth_aligned
568 ADD src, src, t2
569
570.Lsrc_unaligned_dst_aligned:
571 SRL t0, len, LOG_NBYTES+2
572 beqz t0, .Lcleanup_src_unaligned
573 and rem, len, (4*NBYTES-1)
5741:
575
576
577
578
579
580
581EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc)
582EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy)
583 SUB len, len, 4*NBYTES
584EXC( LDREST t0, REST(0)(src), .Ll_exc_copy)
585EXC( LDREST t1, REST(1)(src), .Ll_exc_copy)
586EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy)
587EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy)
588EXC( LDREST t2, REST(2)(src), .Ll_exc_copy)
589EXC( LDREST t3, REST(3)(src), .Ll_exc_copy)
590 ADD src, src, 4*NBYTES
591#ifdef CONFIG_CPU_SB1
592 nop
593#endif
594EXC( STORE t0, UNIT(0)(dst), .Ls_exc)
595 ADDC(sum, t0)
596EXC( STORE t1, UNIT(1)(dst), .Ls_exc)
597 ADDC(sum, t1)
598EXC( STORE t2, UNIT(2)(dst), .Ls_exc)
599 ADDC(sum, t2)
600EXC( STORE t3, UNIT(3)(dst), .Ls_exc)
601 ADDC(sum, t3)
602 .set reorder
603 ADD dst, dst, 4*NBYTES
604 bne len, rem, 1b
605 .set noreorder
606
607.Lcleanup_src_unaligned:
608 beqz len, .Ldone
609 and rem, len, NBYTES-1
610 beq rem, len, .Lcopy_bytes
611 nop
6121:
613EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc)
614EXC( LDREST t0, REST(0)(src), .Ll_exc_copy)
615 ADD src, src, NBYTES
616 SUB len, len, NBYTES
617EXC( STORE t0, 0(dst), .Ls_exc)
618 ADDC(sum, t0)
619 .set reorder
620 ADD dst, dst, NBYTES
621 bne len, rem, 1b
622 .set noreorder
623
624.Lcopy_bytes_checklen:
625 beqz len, .Ldone
626 nop
627.Lcopy_bytes:
628
629#ifdef CONFIG_CPU_LITTLE_ENDIAN
630#define SHIFT_START 0
631#define SHIFT_INC 8
632#else
633#define SHIFT_START 8*(NBYTES-1)
634#define SHIFT_INC -8
635#endif
636 move t2, zero
637 li t3, SHIFT_START
638
639#define COPY_BYTE(N) \
640EXC( lbu t0, N(src), .Ll_exc_copy); \
641 SUB len, len, 1; \
642EXC( sb t0, N(dst), .Ls_exc); \
643 SLLV t0, t0, t3; \
644 addu t3, SHIFT_INC; \
645 beqz len, .Lcopy_bytes_done; \
646 or t2, t0
647
648 COPY_BYTE(0)
649 COPY_BYTE(1)
650#ifdef USE_DOUBLE
651 COPY_BYTE(2)
652 COPY_BYTE(3)
653 COPY_BYTE(4)
654 COPY_BYTE(5)
655#endif
656EXC( lbu t0, NBYTES-2(src), .Ll_exc_copy)
657 SUB len, len, 1
658EXC( sb t0, NBYTES-2(dst), .Ls_exc)
659 SLLV t0, t0, t3
660 or t2, t0
661.Lcopy_bytes_done:
662 ADDC(sum, t2)
663.Ldone:
664
665#ifdef USE_DOUBLE
666 dsll32 v1, sum, 0
667 daddu sum, v1
668 sltu v1, sum, v1
669 dsra32 sum, sum, 0
670 addu sum, v1
671#endif
672
673#ifdef CPU_MIPSR2
674 wsbh v1, sum
675 movn sum, v1, odd
676#else
677 beqz odd, 1f
678 lui v1, 0x00ff
679 addu v1, 0x00ff
680 and t0, sum, v1
681 sll t0, t0, 8
682 srl sum, sum, 8
683 and sum, sum, v1
684 or sum, sum, t0
6851:
686#endif
687 .set reorder
688 ADDC32(sum, psum)
689 jr ra
690 .set noreorder
691
692.Ll_exc_copy:
693
694
695
696
697
698
699
700
701
702
703 LOAD t0, TI_TASK($28)
704 li t2, SHIFT_START
705 LOAD t0, THREAD_BUADDR(t0)
7061:
707EXC( lbu t1, 0(src), .Ll_exc)
708 ADD src, src, 1
709 sb t1, 0(dst)
710 SLLV t1, t1, t2
711 addu t2, SHIFT_INC
712 ADDC(sum, t1)
713 .set reorder
714 ADD dst, dst, 1
715 bne src, t0, 1b
716 .set noreorder
717.Ll_exc:
718 LOAD t0, TI_TASK($28)
719 nop
720 LOAD t0, THREAD_BUADDR(t0)
721 nop
722 SUB len, AT, t0
723
724
725
726
727
728 ADD dst, t0
729 SUB dst, src
730
731
732
733
734 .set reorder
735 SUB src, len, 1
736 beqz len, .Ldone
737 .set noreorder
7381: sb zero, 0(dst)
739 ADD dst, dst, 1
740 .set push
741 .set noat
742#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
743 bnez src, 1b
744 SUB src, src, 1
745#else
746 li v1, 1
747 bnez src, 1b
748 SUB src, src, v1
749#endif
750 li v1, -EFAULT
751 b .Ldone
752 sw v1, (errptr)
753
754.Ls_exc:
755 li v0, -1
756 li v1, -EFAULT
757 jr ra
758 sw v1, (errptr)
759 .set pop
760 END(__csum_partial_copy_user)
761