aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v32/lib/checksum.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/cris/arch-v32/lib/checksum.S')
-rw-r--r--arch/cris/arch-v32/lib/checksum.S111
1 files changed, 111 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/lib/checksum.S b/arch/cris/arch-v32/lib/checksum.S
new file mode 100644
index 000000000000..32e66181b826
--- /dev/null
+++ b/arch/cris/arch-v32/lib/checksum.S
@@ -0,0 +1,111 @@
1/*
2 * A fast checksum routine using movem
3 * Copyright (c) 1998-2001, 2003 Axis Communications AB
4 *
5 * csum_partial(const unsigned char * buff, int len, unsigned int sum)
6 */
7
8 .globl csum_partial
9csum_partial:
10
11 ;; r10 - src
12 ;; r11 - length
13 ;; r12 - checksum
14
15 ;; check for breakeven length between movem and normal word looping versions
16 ;; we also do _NOT_ want to compute a checksum over more than the
17 ;; actual length when length < 40
18
19 cmpu.w 80,$r11
20 blo _word_loop
21 nop
22
23 ;; need to save the registers we use below in the movem loop
24 ;; this overhead is why we have a check above for breakeven length
25 ;; only r0 - r8 have to be saved, the other ones are clobber-able
26 ;; according to the ABI
27
28 subq 9*4,$sp
29 subq 10*4,$r11 ; update length for the first loop
30 movem $r8,[$sp]
31
32 ;; do a movem checksum
33
34_mloop: movem [$r10+],$r9 ; read 10 longwords
35
36 ;; perform dword checksumming on the 10 longwords
37
38 add.d $r0,$r12
39 addc $r1,$r12
40 addc $r2,$r12
41 addc $r3,$r12
42 addc $r4,$r12
43 addc $r5,$r12
44 addc $r6,$r12
45 addc $r7,$r12
46 addc $r8,$r12
47 addc $r9,$r12
48
49 ;; fold the carry into the checksum, to avoid having to loop the carry
50 ;; back into the top
51
52 addc 0,$r12
53 addc 0,$r12 ; do it again, since we might have generated a carry
54
55 subq 10*4,$r11
56 bge _mloop
57 nop
58
59 addq 10*4,$r11 ; compensate for last loop underflowing length
60
61 movem [$sp+],$r8 ; restore regs
62
63_word_loop:
64 ;; only fold if there is anything to fold.
65
66 cmpq 0,$r12
67 beq _no_fold
68
69 ;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below.
70 ;; r9 and r13 can be used as temporaries.
71
72 moveq -1,$r9 ; put 0xffff in r9, faster than move.d 0xffff,r9
73 lsrq 16,$r9
74
75 move.d $r12,$r13
76 lsrq 16,$r13 ; r13 = checksum >> 16
77 and.d $r9,$r12 ; checksum = checksum & 0xffff
78 add.d $r13,$r12 ; checksum += r13
79 move.d $r12,$r13 ; do the same again, maybe we got a carry last add
80 lsrq 16,$r13
81 and.d $r9,$r12
82 add.d $r13,$r12
83
84_no_fold:
85 cmpq 2,$r11
86 blt _no_words
87 nop
88
89 ;; checksum the rest of the words
90
91 subq 2,$r11
92
93_wloop: subq 2,$r11
94 bge _wloop
95 addu.w [$r10+],$r12
96
97 addq 2,$r11
98
99_no_words:
100 ;; see if we have one odd byte more
101 cmpq 1,$r11
102 beq _do_byte
103 nop
104 ret
105 move.d $r12,$r10
106
107_do_byte:
108 ;; copy and checksum the last byte
109 addu.b [$r10],$r12
110 ret
111 move.d $r12,$r10