Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6.git] / arch / cris / arch-v32 / lib / checksumcopy.S
1 /*
2  * A fast checksum+copy routine using movem
3  * Copyright (c) 1998-2007 Axis Communications AB
4  *
5  * Authors:     Bjorn Wesen
6  *
7  * csum_partial_copy_nocheck(const char *src, char *dst,
8  *                           int len, unsigned int sum)
9  */
10
11         .globl  csum_partial_copy_nocheck
12 csum_partial_copy_nocheck:
13
14         ;; r10 - src
15         ;; r11 - dst
16         ;; r12 - length
17         ;; r13 - checksum
18
19         ;; Optimized for large packets
20         subq    10*4, $r12
21         blt     _word_loop
22         move.d  $r12, $acr
23
24         subq    9*4,$sp
25         clearf  c
26         movem   $r8,[$sp]
27
28         ;; do a movem copy and checksum
29 1:      ;; A failing userspace access (the read) will have this as PC.
30 _mloop: movem   [$r10+],$r9     ; read 10 longwords
31         addoq   -10*4, $acr, $acr ; loop counter in latency cycle
32         movem   $r9,[$r11+]     ; write 10 longwords
33
34         ;; perform dword checksumming on the 10 longwords
35         addc    $r0,$r13
36         addc    $r1,$r13
37         addc    $r2,$r13
38         addc    $r3,$r13
39         addc    $r4,$r13
40         addc    $r5,$r13
41         addc    $r6,$r13
42         addc    $r7,$r13
43         addc    $r8,$r13
44         addc    $r9,$r13
45
46         ;; test $acr, without trashing carry.
47         move.d  $acr, $acr
48         bpl     _mloop
49         ;; r12 <= acr  is needed after mloop and in the exception handlers.
50         move.d  $acr, $r12
51
52         ;; fold the last carry into r13
53         addc    0, $r13
54         movem   [$sp+],$r8      ; restore regs
55
56 _word_loop:
57         addq    10*4,$r12       ; compensate for last loop underflowing length
58
59         ;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below
60         ;; r9 can be used as temporary.
61         move.d  $r13,$r9
62         lsrq    16,$r9          ; r0 = checksum >> 16
63         and.d   0xffff,$r13     ; checksum = checksum & 0xffff
64
65         subq    2, $r12
66         blt     _no_words
67         add.d   $r9,$r13        ; checksum += r0
68
69         ;; copy and checksum the rest of the words
70 2:      ;; A failing userspace access for the read below will have this as PC.
71 _wloop: move.w  [$r10+],$r9
72         addu.w  $r9,$r13
73         subq    2,$r12
74         bge     _wloop
75         move.w  $r9,[$r11+]
76
77 _no_words:
78         addq    2,$r12
79         bne     _do_byte
80         nop
81         ret
82         move.d  $r13,$r10
83
84 _do_byte:
85         ;; copy and checksum the last byte
86 3:      ;; A failing userspace access for the read below will have this as PC.
87         move.b  [$r10],$r9
88         addu.b  $r9,$r13
89         move.b  $r9,[$r11]
90         ret
91         move.d  $r13,$r10