GNU Linux-libre 4.14.290-gnu1
[releases.git] / arch / cris / arch-v32 / lib / checksum.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * A fast checksum routine using movem
4  * Copyright (c) 1998-2007 Axis Communications AB
5  *
6  * csum_partial(const unsigned char * buff, int len, unsigned int sum)
7  */
8
9         .globl  csum_partial
10         .type   csum_partial,@function
11 csum_partial:
12
13         ;; r10 - src
14         ;; r11 - length
15         ;; r12 - checksum
16
17         ;; Optimized for large packets
18         subq    10*4, $r11
19         blt     _word_loop
20         move.d  $r11, $acr
21
22         subq    9*4,$sp
23         clearf  c
24         movem   $r8,[$sp]
25
26         ;; do a movem checksum
27
28 _mloop: movem   [$r10+],$r9     ; read 10 longwords
29         ;; Loop count without touching the c flag.
30         addoq   -10*4, $acr, $acr
31         ;; perform dword checksumming on the 10 longwords
32
33         addc    $r0,$r12
34         addc    $r1,$r12
35         addc    $r2,$r12
36         addc    $r3,$r12
37         addc    $r4,$r12
38         addc    $r5,$r12
39         addc    $r6,$r12
40         addc    $r7,$r12
41         addc    $r8,$r12
42         addc    $r9,$r12
43
44         ;; test $acr without trashing carry.
45         move.d  $acr, $acr
46         bpl     _mloop
47         ;; r11 <= acr  is not really needed in the mloop, just using the dslot
48         ;; to prepare for what is needed after mloop.
49         move.d  $acr, $r11
50
51         ;; fold the last carry into r13
52         addc    0, $r12
53         movem   [$sp+],$r8      ; restore regs
54
55 _word_loop:
56         addq    10*4,$r11       ; compensate for last loop underflowing length
57
58         moveq   -1,$r9          ; put 0xffff in r9, faster than move.d 0xffff,r9
59         lsrq    16,$r9
60
61         move.d  $r12,$r13
62         lsrq    16,$r13         ; r13 = checksum >> 16
63         and.d   $r9,$r12        ; checksum = checksum & 0xffff
64
65 _no_fold:
66         subq    2,$r11
67         blt     _no_words
68         add.d   $r13,$r12       ; checksum += r13
69
70         ;; checksum the rest of the words
71 _wloop: subq    2,$r11
72         bge     _wloop
73         addu.w  [$r10+],$r12
74
75 _no_words:
76         addq    2,$r11
77         ;; see if we have one odd byte more
78         bne     _do_byte
79         nop
80         ret
81         move.d  $r12,$r10
82
83 _do_byte:
84         ;; copy and checksum the last byte
85         addu.b  [$r10],$r12
86         ret
87         move.d  $r12,$r10
88
89         .size   csum_partial, .-csum_partial