ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / arm / lib / csumpartialcopygeneric.S
1 /*
2  *  linux/arch/arm/lib/csumpartialcopygeneric.S
3  *
4  *  Copyright (C) 1995-2001 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 /*
12  * unsigned int
13  * csum_partial_copy_xxx(const char *src, char *dst, int len, int sum, )
14  *  r0 = src, r1 = dst, r2 = len, r3 = sum
15  *  Returns : r0 = checksum
16  *
17  * Note that 'tst' and 'teq' preserve the carry flag.
18  */
19
20 src     .req    r0
21 dst     .req    r1
22 len     .req    r2
23 sum     .req    r3
24
25 .zero:          mov     r0, sum
26                 load_regs       ea
27
28                 /*
29                  * Align an unaligned destination pointer.  We know that
30                  * we have >= 8 bytes here, so we don't need to check
31                  * the length.  Note that the source pointer hasn't been
32                  * aligned yet.
33                  */
34 .dst_unaligned: tst     dst, #1
35                 beq     .dst_16bit
36
37                 load1b  ip
38                 sub     len, len, #1
39                 adcs    sum, sum, ip, put_byte_1        @ update checksum
40                 strb    ip, [dst], #1
41                 tst     dst, #2
42                 moveq   pc, lr                  @ dst is now 32bit aligned
43
44 .dst_16bit:     load2b  r8, ip
45                 sub     len, len, #2
46                 adcs    sum, sum, r8, put_byte_0
47                 strb    r8, [dst], #1
48                 adcs    sum, sum, ip, put_byte_1
49                 strb    ip, [dst], #1
50                 mov     pc, lr                  @ dst is now 32bit aligned
51
52                 /*
53                  * Handle 0 to 7 bytes, with any alignment of source and
54                  * destination pointers.  Note that when we get here, C = 0
55                  */
56 .less8:         teq     len, #0                 @ check for zero count
57                 beq     .zero
58
59                 /* we must have at least one byte. */
60                 tst     dst, #1                 @ dst 16-bit aligned
61                 beq     .less8_aligned
62
63                 /* Align dst */
64                 load1b  ip
65                 sub     len, len, #1
66                 adcs    sum, sum, ip, put_byte_1        @ update checksum
67                 strb    ip, [dst], #1
68                 tst     len, #6
69                 beq     .less8_byteonly
70
71 1:              load2b  r8, ip
72                 sub     len, len, #2
73                 adcs    sum, sum, r8, put_byte_0
74                 strb    r8, [dst], #1
75                 adcs    sum, sum, ip, put_byte_1
76                 strb    ip, [dst], #1
77 .less8_aligned: tst     len, #6
78                 bne     1b
79 .less8_byteonly:
80                 tst     len, #1
81                 beq     .done
82                 load1b  r8
83                 adcs    sum, sum, r8, put_byte_0        @ update checksum
84                 strb    r8, [dst], #1
85                 b       .done
86
87 FN_ENTRY
88                 mov     ip, sp
89                 save_regs
90                 sub     fp, ip, #4
91
92                 cmp     len, #8                 @ Ensure that we have at least
93                 blo     .less8                  @ 8 bytes to copy.
94
95                 adds    sum, sum, #0            @ C = 0
96                 tst     dst, #3                 @ Test destination alignment
97                 blne    .dst_unaligned          @ align destination, return here
98
99                 /*
100                  * Ok, the dst pointer is now 32bit aligned, and we know
101                  * that we must have more than 4 bytes to copy.  Note
102                  * that C contains the carry from the dst alignment above.
103                  */
104
105                 tst     src, #3                 @ Test source alignment
106                 bne     .src_not_aligned
107
108                 /* Routine for src & dst aligned */
109
110                 bics    ip, len, #15
111                 beq     2f
112
113 1:              load4l  r4, r5, r6, r7
114                 stmia   dst!, {r4, r5, r6, r7}
115                 adcs    sum, sum, r4
116                 adcs    sum, sum, r5
117                 adcs    sum, sum, r6
118                 adcs    sum, sum, r7
119                 sub     ip, ip, #16
120                 teq     ip, #0
121                 bne     1b
122
123 2:              ands    ip, len, #12
124                 beq     4f
125                 tst     ip, #8
126                 beq     3f
127                 load2l  r4, r5
128                 stmia   dst!, {r4, r5}
129                 adcs    sum, sum, r4
130                 adcs    sum, sum, r5
131                 tst     ip, #4
132                 beq     4f
133
134 3:              load1l  r4
135                 str     r4, [dst], #4
136                 adcs    sum, sum, r4
137
138 4:              ands    len, len, #3
139                 beq     .done
140                 load1l  r4
141                 tst     len, #2
142                 mov     r5, r4, get_byte_0
143                 beq     .exit
144                 adcs    sum, sum, r4, push #16
145                 strb    r5, [dst], #1
146                 mov     r5, r4, get_byte_1
147                 strb    r5, [dst], #1
148                 mov     r5, r4, get_byte_2
149 .exit:          tst     len, #1
150                 strneb  r5, [dst], #1
151                 andne   r5, r5, #255
152                 adcnes  sum, sum, r5, put_byte_0
153
154                 /*
155                  * If the dst pointer was not 16-bit aligned, we
156                  * need to rotate the checksum here to get around
157                  * the inefficient byte manipulations in the
158                  * architecture independent code.
159                  */
160 .done:          adc     r0, sum, #0
161                 ldr     sum, [sp, #0]           @ dst
162                 tst     sum, #1
163                 movne   sum, r0, lsl #8
164                 orrne   r0, sum, r0, lsr #24
165                 load_regs       ea
166
167 .src_not_aligned:
168                 adc     sum, sum, #0            @ include C from dst alignment
169                 and     ip, src, #3
170                 bic     src, src, #3
171                 load1l  r5
172                 cmp     ip, #2
173                 beq     .src2_aligned
174                 bhi     .src3_aligned
175                 mov     r4, r5, pull #8         @ C = 0
176                 bics    ip, len, #15
177                 beq     2f
178 1:              load4l  r5, r6, r7, r8
179                 orr     r4, r4, r5, push #24
180                 mov     r5, r5, pull #8
181                 orr     r5, r5, r6, push #24
182                 mov     r6, r6, pull #8
183                 orr     r6, r6, r7, push #24
184                 mov     r7, r7, pull #8
185                 orr     r7, r7, r8, push #24
186                 stmia   dst!, {r4, r5, r6, r7}
187                 adcs    sum, sum, r4
188                 adcs    sum, sum, r5
189                 adcs    sum, sum, r6
190                 adcs    sum, sum, r7
191                 mov     r4, r8, pull #8
192                 sub     ip, ip, #16
193                 teq     ip, #0
194                 bne     1b
195 2:              ands    ip, len, #12
196                 beq     4f
197                 tst     ip, #8
198                 beq     3f
199                 load2l  r5, r6
200                 orr     r4, r4, r5, push #24
201                 mov     r5, r5, pull #8
202                 orr     r5, r5, r6, push #24
203                 stmia   dst!, {r4, r5}
204                 adcs    sum, sum, r4
205                 adcs    sum, sum, r5
206                 mov     r4, r6, pull #8
207                 tst     ip, #4
208                 beq     4f
209 3:              load1l  r5
210                 orr     r4, r4, r5, push #24
211                 str     r4, [dst], #4
212                 adcs    sum, sum, r4
213                 mov     r4, r5, pull #8
214 4:              ands    len, len, #3
215                 beq     .done
216                 mov     r5, r4, get_byte_0
217                 tst     len, #2
218                 beq     .exit
219                 adcs    sum, sum, r4, push #16
220                 strb    r5, [dst], #1
221                 mov     r5, r4, get_byte_1
222                 strb    r5, [dst], #1
223                 mov     r5, r4, get_byte_2
224                 b       .exit
225
226 .src2_aligned:  mov     r4, r5, pull #16
227                 adds    sum, sum, #0
228                 bics    ip, len, #15
229                 beq     2f
230 1:              load4l  r5, r6, r7, r8
231                 orr     r4, r4, r5, push #16
232                 mov     r5, r5, pull #16
233                 orr     r5, r5, r6, push #16
234                 mov     r6, r6, pull #16
235                 orr     r6, r6, r7, push #16
236                 mov     r7, r7, pull #16
237                 orr     r7, r7, r8, push #16
238                 stmia   dst!, {r4, r5, r6, r7}
239                 adcs    sum, sum, r4
240                 adcs    sum, sum, r5
241                 adcs    sum, sum, r6
242                 adcs    sum, sum, r7
243                 mov     r4, r8, pull #16
244                 sub     ip, ip, #16
245                 teq     ip, #0
246                 bne     1b
247 2:              ands    ip, len, #12
248                 beq     4f
249                 tst     ip, #8
250                 beq     3f
251                 load2l  r5, r6
252                 orr     r4, r4, r5, push #16
253                 mov     r5, r5, pull #16
254                 orr     r5, r5, r6, push #16
255                 stmia   dst!, {r4, r5}
256                 adcs    sum, sum, r4
257                 adcs    sum, sum, r5
258                 mov     r4, r6, pull #16
259                 tst     ip, #4
260                 beq     4f
261 3:              load1l  r5
262                 orr     r4, r4, r5, push #16
263                 str     r4, [dst], #4
264                 adcs    sum, sum, r4
265                 mov     r4, r5, pull #16
266 4:              ands    len, len, #3
267                 beq     .done
268                 mov     r5, r4, get_byte_0
269                 tst     len, #2
270                 beq     .exit
271                 adcs    sum, sum, r4
272                 strb    r5, [dst], #1
273                 mov     r5, r4, get_byte_1
274                 strb    r5, [dst], #1
275                 tst     len, #1
276                 beq     .done
277                 load1b  r5
278                 b       .exit
279
280 .src3_aligned:  mov     r4, r5, pull #24
281                 adds    sum, sum, #0
282                 bics    ip, len, #15
283                 beq     2f
284 1:              load4l  r5, r6, r7, r8
285                 orr     r4, r4, r5, push #8
286                 mov     r5, r5, pull #24
287                 orr     r5, r5, r6, push #8
288                 mov     r6, r6, pull #24
289                 orr     r6, r6, r7, push #8
290                 mov     r7, r7, pull #24
291                 orr     r7, r7, r8, push #8
292                 stmia   dst!, {r4, r5, r6, r7}
293                 adcs    sum, sum, r4
294                 adcs    sum, sum, r5
295                 adcs    sum, sum, r6
296                 adcs    sum, sum, r7
297                 mov     r4, r8, pull #24
298                 sub     ip, ip, #16
299                 teq     ip, #0
300                 bne     1b
301 2:              ands    ip, len, #12
302                 beq     4f
303                 tst     ip, #8
304                 beq     3f
305                 load2l  r5, r6
306                 orr     r4, r4, r5, push #8
307                 mov     r5, r5, pull #24
308                 orr     r5, r5, r6, push #8
309                 stmia   dst!, {r4, r5}
310                 adcs    sum, sum, r4
311                 adcs    sum, sum, r5
312                 mov     r4, r6, pull #24
313                 tst     ip, #4
314                 beq     4f
315 3:              load1l  r5
316                 orr     r4, r4, r5, push #8
317                 str     r4, [dst], #4
318                 adcs    sum, sum, r4
319                 mov     r4, r5, pull #24
320 4:              ands    len, len, #3
321                 beq     .done
322                 mov     r5, r4, get_byte_0
323                 tst     len, #2
324                 beq     .exit
325                 strb    r5, [dst], #1
326                 adcs    sum, sum, r4
327                 load1l  r4
328                 mov     r5, r4, get_byte_0
329                 strb    r5, [dst], #1
330                 adcs    sum, sum, r4, push #24
331                 mov     r5, r4, get_byte_1
332                 b       .exit