Linux-2.6.12-rc2
[pandora-kernel.git] / arch / arm / lib / uaccess.S
1 /*
2  *  linux/arch/arm/lib/uaccess.S
3  *
4  *  Copyright (C) 1995, 1996,1997,1998 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  *  Routines to block copy data to/from user memory
11  *   These are highly optimised both for the 4k page size
12  *   and for various alignments.
13  */
14 #include <linux/linkage.h>
15 #include <asm/assembler.h>
16 #include <asm/errno.h>
17
18                 .text
19
20 #define PAGE_SHIFT 12
21
22 /* Prototype: int __arch_copy_to_user(void *to, const char *from, size_t n)
23  * Purpose  : copy a block to user memory from kernel memory
24  * Params   : to   - user memory
25  *          : from - kernel memory
26  *          : n    - number of bytes to copy
27  * Returns  : Number of bytes NOT copied.
28  */
29
30 .c2u_dest_not_aligned:
31                 rsb     ip, ip, #4
32                 cmp     ip, #2
33                 ldrb    r3, [r1], #1
34 USER(           strbt   r3, [r0], #1)                   @ May fault
35                 ldrgeb  r3, [r1], #1
36 USER(           strgebt r3, [r0], #1)                   @ May fault
37                 ldrgtb  r3, [r1], #1
38 USER(           strgtbt r3, [r0], #1)                   @ May fault
39                 sub     r2, r2, ip
40                 b       .c2u_dest_aligned
41
42 ENTRY(__arch_copy_to_user)
43                 stmfd   sp!, {r2, r4 - r7, lr}
44                 cmp     r2, #4
45                 blt     .c2u_not_enough
46         PLD(    pld     [r1, #0]                )
47         PLD(    pld     [r0, #0]                )
48                 ands    ip, r0, #3
49                 bne     .c2u_dest_not_aligned
50 .c2u_dest_aligned:
51
52                 ands    ip, r1, #3
53                 bne     .c2u_src_not_aligned
54 /*
55  * Seeing as there has to be at least 8 bytes to copy, we can
56  * copy one word, and force a user-mode page fault...
57  */
58
59 .c2u_0fupi:     subs    r2, r2, #4
60                 addmi   ip, r2, #4
61                 bmi     .c2u_0nowords
62                 ldr     r3, [r1], #4
63 USER(           strt    r3, [r0], #4)                   @ May fault
64                 mov     ip, r0, lsl #32 - PAGE_SHIFT    @ On each page, use a ld/st??t instruction
65                 rsb     ip, ip, #0
66                 movs    ip, ip, lsr #32 - PAGE_SHIFT
67                 beq     .c2u_0fupi
68 /*
69  * ip = max no. of bytes to copy before needing another "strt" insn
70  */
71                 cmp     r2, ip
72                 movlt   ip, r2
73                 sub     r2, r2, ip
74                 subs    ip, ip, #32
75                 blt     .c2u_0rem8lp
76         PLD(    pld     [r1, #28]               )
77         PLD(    pld     [r0, #28]               )
78         PLD(    subs    ip, ip, #64                     )
79         PLD(    blt     .c2u_0cpynopld          )
80         PLD(    pld     [r1, #60]               )
81         PLD(    pld     [r0, #60]               )
82
83 .c2u_0cpy8lp:
84         PLD(    pld     [r1, #92]               )
85         PLD(    pld     [r0, #92]               )
86 .c2u_0cpynopld: ldmia   r1!, {r3 - r6}
87                 stmia   r0!, {r3 - r6}                  @ Shouldnt fault
88                 ldmia   r1!, {r3 - r6}
89                 subs    ip, ip, #32
90                 stmia   r0!, {r3 - r6}                  @ Shouldnt fault
91                 bpl     .c2u_0cpy8lp
92         PLD(    cmn     ip, #64                 )
93         PLD(    bge     .c2u_0cpynopld          )
94         PLD(    add     ip, ip, #64             )
95
96 .c2u_0rem8lp:   cmn     ip, #16
97                 ldmgeia r1!, {r3 - r6}
98                 stmgeia r0!, {r3 - r6}                  @ Shouldnt fault
99                 tst     ip, #8
100                 ldmneia r1!, {r3 - r4}
101                 stmneia r0!, {r3 - r4}                  @ Shouldnt fault
102                 tst     ip, #4
103                 ldrne   r3, [r1], #4
104                 strnet  r3, [r0], #4                    @ Shouldnt fault
105                 ands    ip, ip, #3
106                 beq     .c2u_0fupi
107 .c2u_0nowords:  teq     ip, #0
108                 beq     .c2u_finished
109 .c2u_nowords:   cmp     ip, #2
110                 ldrb    r3, [r1], #1
111 USER(           strbt   r3, [r0], #1)                   @ May fault
112                 ldrgeb  r3, [r1], #1
113 USER(           strgebt r3, [r0], #1)                   @ May fault
114                 ldrgtb  r3, [r1], #1
115 USER(           strgtbt r3, [r0], #1)                   @ May fault
116                 b       .c2u_finished
117
118 .c2u_not_enough:
119                 movs    ip, r2
120                 bne     .c2u_nowords
121 .c2u_finished:  mov     r0, #0
122                 LOADREGS(fd,sp!,{r2, r4 - r7, pc})
123
124 .c2u_src_not_aligned:
125                 bic     r1, r1, #3
126                 ldr     r7, [r1], #4
127                 cmp     ip, #2
128                 bgt     .c2u_3fupi
129                 beq     .c2u_2fupi
130 .c2u_1fupi:     subs    r2, r2, #4
131                 addmi   ip, r2, #4
132                 bmi     .c2u_1nowords
133                 mov     r3, r7, pull #8
134                 ldr     r7, [r1], #4
135                 orr     r3, r3, r7, push #24
136 USER(           strt    r3, [r0], #4)                   @ May fault
137                 mov     ip, r0, lsl #32 - PAGE_SHIFT
138                 rsb     ip, ip, #0
139                 movs    ip, ip, lsr #32 - PAGE_SHIFT
140                 beq     .c2u_1fupi
141                 cmp     r2, ip
142                 movlt   ip, r2
143                 sub     r2, r2, ip
144                 subs    ip, ip, #16
145                 blt     .c2u_1rem8lp
146         PLD(    pld     [r1, #12]               )
147         PLD(    pld     [r0, #12]               )
148         PLD(    subs    ip, ip, #32             )
149         PLD(    blt     .c2u_1cpynopld          )
150         PLD(    pld     [r1, #28]               )
151         PLD(    pld     [r0, #28]               )
152
153 .c2u_1cpy8lp:
154         PLD(    pld     [r1, #44]               )
155         PLD(    pld     [r0, #44]               )
156 .c2u_1cpynopld: mov     r3, r7, pull #8
157                 ldmia   r1!, {r4 - r7}
158                 subs    ip, ip, #16
159                 orr     r3, r3, r4, push #24
160                 mov     r4, r4, pull #8
161                 orr     r4, r4, r5, push #24
162                 mov     r5, r5, pull #8
163                 orr     r5, r5, r6, push #24
164                 mov     r6, r6, pull #8
165                 orr     r6, r6, r7, push #24
166                 stmia   r0!, {r3 - r6}                  @ Shouldnt fault
167                 bpl     .c2u_1cpy8lp
168         PLD(    cmn     ip, #32                 )
169         PLD(    bge     .c2u_1cpynopld          )
170         PLD(    add     ip, ip, #32             )
171
172 .c2u_1rem8lp:   tst     ip, #8
173                 movne   r3, r7, pull #8
174                 ldmneia r1!, {r4, r7}
175                 orrne   r3, r3, r4, push #24
176                 movne   r4, r4, pull #8
177                 orrne   r4, r4, r7, push #24
178                 stmneia r0!, {r3 - r4}                  @ Shouldnt fault
179                 tst     ip, #4
180                 movne   r3, r7, pull #8
181                 ldrne   r7, [r1], #4
182                 orrne   r3, r3, r7, push #24
183                 strnet  r3, [r0], #4                    @ Shouldnt fault
184                 ands    ip, ip, #3
185                 beq     .c2u_1fupi
186 .c2u_1nowords:  mov     r3, r7, get_byte_1
187                 teq     ip, #0
188                 beq     .c2u_finished
189                 cmp     ip, #2
190 USER(           strbt   r3, [r0], #1)                   @ May fault
191                 movge   r3, r7, get_byte_2
192 USER(           strgebt r3, [r0], #1)                   @ May fault
193                 movgt   r3, r7, get_byte_3
194 USER(           strgtbt r3, [r0], #1)                   @ May fault
195                 b       .c2u_finished
196
197 .c2u_2fupi:     subs    r2, r2, #4
198                 addmi   ip, r2, #4
199                 bmi     .c2u_2nowords
200                 mov     r3, r7, pull #16
201                 ldr     r7, [r1], #4
202                 orr     r3, r3, r7, push #16
203 USER(           strt    r3, [r0], #4)                   @ May fault
204                 mov     ip, r0, lsl #32 - PAGE_SHIFT
205                 rsb     ip, ip, #0
206                 movs    ip, ip, lsr #32 - PAGE_SHIFT
207                 beq     .c2u_2fupi
208                 cmp     r2, ip
209                 movlt   ip, r2
210                 sub     r2, r2, ip
211                 subs    ip, ip, #16
212                 blt     .c2u_2rem8lp
213         PLD(    pld     [r1, #12]               )
214         PLD(    pld     [r0, #12]               )
215         PLD(    subs    ip, ip, #32             )
216         PLD(    blt     .c2u_2cpynopld          )
217         PLD(    pld     [r1, #28]               )
218         PLD(    pld     [r0, #28]               )
219
220 .c2u_2cpy8lp:
221         PLD(    pld     [r1, #44]               )
222         PLD(    pld     [r0, #44]               )
223 .c2u_2cpynopld: mov     r3, r7, pull #16
224                 ldmia   r1!, {r4 - r7}
225                 subs    ip, ip, #16
226                 orr     r3, r3, r4, push #16
227                 mov     r4, r4, pull #16
228                 orr     r4, r4, r5, push #16
229                 mov     r5, r5, pull #16
230                 orr     r5, r5, r6, push #16
231                 mov     r6, r6, pull #16
232                 orr     r6, r6, r7, push #16
233                 stmia   r0!, {r3 - r6}                  @ Shouldnt fault
234                 bpl     .c2u_2cpy8lp
235         PLD(    cmn     ip, #32                 )
236         PLD(    bge     .c2u_2cpynopld          )
237         PLD(    add     ip, ip, #32             )
238
239 .c2u_2rem8lp:   tst     ip, #8
240                 movne   r3, r7, pull #16
241                 ldmneia r1!, {r4, r7}
242                 orrne   r3, r3, r4, push #16
243                 movne   r4, r4, pull #16
244                 orrne   r4, r4, r7, push #16
245                 stmneia r0!, {r3 - r4}                  @ Shouldnt fault
246                 tst     ip, #4
247                 movne   r3, r7, pull #16
248                 ldrne   r7, [r1], #4
249                 orrne   r3, r3, r7, push #16
250                 strnet  r3, [r0], #4                    @ Shouldnt fault
251                 ands    ip, ip, #3
252                 beq     .c2u_2fupi
253 .c2u_2nowords:  mov     r3, r7, get_byte_2
254                 teq     ip, #0
255                 beq     .c2u_finished
256                 cmp     ip, #2
257 USER(           strbt   r3, [r0], #1)                   @ May fault
258                 movge   r3, r7, get_byte_3
259 USER(           strgebt r3, [r0], #1)                   @ May fault
260                 ldrgtb  r3, [r1], #0
261 USER(           strgtbt r3, [r0], #1)                   @ May fault
262                 b       .c2u_finished
263
264 .c2u_3fupi:     subs    r2, r2, #4
265                 addmi   ip, r2, #4
266                 bmi     .c2u_3nowords
267                 mov     r3, r7, pull #24
268                 ldr     r7, [r1], #4
269                 orr     r3, r3, r7, push #8
270 USER(           strt    r3, [r0], #4)                   @ May fault
271                 mov     ip, r0, lsl #32 - PAGE_SHIFT
272                 rsb     ip, ip, #0
273                 movs    ip, ip, lsr #32 - PAGE_SHIFT
274                 beq     .c2u_3fupi
275                 cmp     r2, ip
276                 movlt   ip, r2
277                 sub     r2, r2, ip
278                 subs    ip, ip, #16
279                 blt     .c2u_3rem8lp
280         PLD(    pld     [r1, #12]               )
281         PLD(    pld     [r0, #12]               )
282         PLD(    subs    ip, ip, #32             )
283         PLD(    blt     .c2u_3cpynopld          )
284         PLD(    pld     [r1, #28]               )
285         PLD(    pld     [r0, #28]               )
286
287 .c2u_3cpy8lp:
288         PLD(    pld     [r1, #44]               )
289         PLD(    pld     [r0, #44]               )
290 .c2u_3cpynopld: mov     r3, r7, pull #24
291                 ldmia   r1!, {r4 - r7}
292                 subs    ip, ip, #16
293                 orr     r3, r3, r4, push #8
294                 mov     r4, r4, pull #24
295                 orr     r4, r4, r5, push #8
296                 mov     r5, r5, pull #24
297                 orr     r5, r5, r6, push #8
298                 mov     r6, r6, pull #24
299                 orr     r6, r6, r7, push #8
300                 stmia   r0!, {r3 - r6}                  @ Shouldnt fault
301                 bpl     .c2u_3cpy8lp
302         PLD(    cmn     ip, #32                 )
303         PLD(    bge     .c2u_3cpynopld          )
304         PLD(    add     ip, ip, #32             )
305
306 .c2u_3rem8lp:   tst     ip, #8
307                 movne   r3, r7, pull #24
308                 ldmneia r1!, {r4, r7}
309                 orrne   r3, r3, r4, push #8
310                 movne   r4, r4, pull #24
311                 orrne   r4, r4, r7, push #8
312                 stmneia r0!, {r3 - r4}                  @ Shouldnt fault
313                 tst     ip, #4
314                 movne   r3, r7, pull #24
315                 ldrne   r7, [r1], #4
316                 orrne   r3, r3, r7, push #8
317                 strnet  r3, [r0], #4                    @ Shouldnt fault
318                 ands    ip, ip, #3
319                 beq     .c2u_3fupi
320 .c2u_3nowords:  mov     r3, r7, get_byte_3
321                 teq     ip, #0
322                 beq     .c2u_finished
323                 cmp     ip, #2
324 USER(           strbt   r3, [r0], #1)                   @ May fault
325                 ldrgeb  r3, [r1], #1
326 USER(           strgebt r3, [r0], #1)                   @ May fault
327                 ldrgtb  r3, [r1], #0
328 USER(           strgtbt r3, [r0], #1)                   @ May fault
329                 b       .c2u_finished
330
331                 .section .fixup,"ax"
332                 .align  0
333 9001:           LOADREGS(fd,sp!, {r0, r4 - r7, pc})
334                 .previous
335
336 /* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
337  * Purpose  : copy a block from user memory to kernel memory
338  * Params   : to   - kernel memory
339  *          : from - user memory
340  *          : n    - number of bytes to copy
341  * Returns  : Number of bytes NOT copied.
342  */
343 .cfu_dest_not_aligned:
344                 rsb     ip, ip, #4
345                 cmp     ip, #2
346 USER(           ldrbt   r3, [r1], #1)                   @ May fault
347                 strb    r3, [r0], #1
348 USER(           ldrgebt r3, [r1], #1)                   @ May fault
349                 strgeb  r3, [r0], #1
350 USER(           ldrgtbt r3, [r1], #1)                   @ May fault
351                 strgtb  r3, [r0], #1
352                 sub     r2, r2, ip
353                 b       .cfu_dest_aligned
354
355 ENTRY(__arch_copy_from_user)
356                 stmfd   sp!, {r0, r2, r4 - r7, lr}
357                 cmp     r2, #4
358                 blt     .cfu_not_enough
359         PLD(    pld     [r1, #0]                )
360         PLD(    pld     [r0, #0]                )
361                 ands    ip, r0, #3
362                 bne     .cfu_dest_not_aligned
363 .cfu_dest_aligned:
364                 ands    ip, r1, #3
365                 bne     .cfu_src_not_aligned
366 /*
367  * Seeing as there has to be at least 8 bytes to copy, we can
368  * copy one word, and force a user-mode page fault...
369  */
370
371 .cfu_0fupi:     subs    r2, r2, #4
372                 addmi   ip, r2, #4
373                 bmi     .cfu_0nowords
374 USER(           ldrt    r3, [r1], #4)
375                 str     r3, [r0], #4
376                 mov     ip, r1, lsl #32 - PAGE_SHIFT    @ On each page, use a ld/st??t instruction
377                 rsb     ip, ip, #0
378                 movs    ip, ip, lsr #32 - PAGE_SHIFT
379                 beq     .cfu_0fupi
380 /*
381  * ip = max no. of bytes to copy before needing another "strt" insn
382  */
383                 cmp     r2, ip
384                 movlt   ip, r2
385                 sub     r2, r2, ip
386                 subs    ip, ip, #32
387                 blt     .cfu_0rem8lp
388         PLD(    pld     [r1, #28]               )
389         PLD(    pld     [r0, #28]               )
390         PLD(    subs    ip, ip, #64                     )
391         PLD(    blt     .cfu_0cpynopld          )
392         PLD(    pld     [r1, #60]               )
393         PLD(    pld     [r0, #60]               )
394
395 .cfu_0cpy8lp:
396         PLD(    pld     [r1, #92]               )
397         PLD(    pld     [r0, #92]               )
398 .cfu_0cpynopld: ldmia   r1!, {r3 - r6}                  @ Shouldnt fault
399                 stmia   r0!, {r3 - r6}
400                 ldmia   r1!, {r3 - r6}                  @ Shouldnt fault
401                 subs    ip, ip, #32
402                 stmia   r0!, {r3 - r6}
403                 bpl     .cfu_0cpy8lp
404         PLD(    cmn     ip, #64                 )
405         PLD(    bge     .cfu_0cpynopld          )
406         PLD(    add     ip, ip, #64             )
407
408 .cfu_0rem8lp:   cmn     ip, #16
409                 ldmgeia r1!, {r3 - r6}                  @ Shouldnt fault
410                 stmgeia r0!, {r3 - r6}
411                 tst     ip, #8
412                 ldmneia r1!, {r3 - r4}                  @ Shouldnt fault
413                 stmneia r0!, {r3 - r4}
414                 tst     ip, #4
415                 ldrnet  r3, [r1], #4                    @ Shouldnt fault
416                 strne   r3, [r0], #4
417                 ands    ip, ip, #3
418                 beq     .cfu_0fupi
419 .cfu_0nowords:  teq     ip, #0
420                 beq     .cfu_finished
421 .cfu_nowords:   cmp     ip, #2
422 USER(           ldrbt   r3, [r1], #1)                   @ May fault
423                 strb    r3, [r0], #1
424 USER(           ldrgebt r3, [r1], #1)                   @ May fault
425                 strgeb  r3, [r0], #1
426 USER(           ldrgtbt r3, [r1], #1)                   @ May fault
427                 strgtb  r3, [r0], #1
428                 b       .cfu_finished
429
430 .cfu_not_enough:
431                 movs    ip, r2
432                 bne     .cfu_nowords
433 .cfu_finished:  mov     r0, #0
434                 add     sp, sp, #8
435                 LOADREGS(fd,sp!,{r4 - r7, pc})
436
437 .cfu_src_not_aligned:
438                 bic     r1, r1, #3
439 USER(           ldrt    r7, [r1], #4)                   @ May fault
440                 cmp     ip, #2
441                 bgt     .cfu_3fupi
442                 beq     .cfu_2fupi
443 .cfu_1fupi:     subs    r2, r2, #4
444                 addmi   ip, r2, #4
445                 bmi     .cfu_1nowords
446                 mov     r3, r7, pull #8
447 USER(           ldrt    r7, [r1], #4)                   @ May fault
448                 orr     r3, r3, r7, push #24
449                 str     r3, [r0], #4
450                 mov     ip, r1, lsl #32 - PAGE_SHIFT
451                 rsb     ip, ip, #0
452                 movs    ip, ip, lsr #32 - PAGE_SHIFT
453                 beq     .cfu_1fupi
454                 cmp     r2, ip
455                 movlt   ip, r2
456                 sub     r2, r2, ip
457                 subs    ip, ip, #16
458                 blt     .cfu_1rem8lp
459         PLD(    pld     [r1, #12]               )
460         PLD(    pld     [r0, #12]               )
461         PLD(    subs    ip, ip, #32             )
462         PLD(    blt     .cfu_1cpynopld          )
463         PLD(    pld     [r1, #28]               )
464         PLD(    pld     [r0, #28]               )
465
466 .cfu_1cpy8lp:
467         PLD(    pld     [r1, #44]               )
468         PLD(    pld     [r0, #44]               )
469 .cfu_1cpynopld: mov     r3, r7, pull #8
470                 ldmia   r1!, {r4 - r7}                  @ Shouldnt fault
471                 subs    ip, ip, #16
472                 orr     r3, r3, r4, push #24
473                 mov     r4, r4, pull #8
474                 orr     r4, r4, r5, push #24
475                 mov     r5, r5, pull #8
476                 orr     r5, r5, r6, push #24
477                 mov     r6, r6, pull #8
478                 orr     r6, r6, r7, push #24
479                 stmia   r0!, {r3 - r6}
480                 bpl     .cfu_1cpy8lp
481         PLD(    cmn     ip, #32                 )
482         PLD(    bge     .cfu_1cpynopld          )
483         PLD(    add     ip, ip, #32             )
484
485 .cfu_1rem8lp:   tst     ip, #8
486                 movne   r3, r7, pull #8
487                 ldmneia r1!, {r4, r7}                   @ Shouldnt fault
488                 orrne   r3, r3, r4, push #24
489                 movne   r4, r4, pull #8
490                 orrne   r4, r4, r7, push #24
491                 stmneia r0!, {r3 - r4}
492                 tst     ip, #4
493                 movne   r3, r7, pull #8
494 USER(           ldrnet  r7, [r1], #4)                   @ May fault
495                 orrne   r3, r3, r7, push #24
496                 strne   r3, [r0], #4
497                 ands    ip, ip, #3
498                 beq     .cfu_1fupi
499 .cfu_1nowords:  mov     r3, r7, get_byte_1
500                 teq     ip, #0
501                 beq     .cfu_finished
502                 cmp     ip, #2
503                 strb    r3, [r0], #1
504                 movge   r3, r7, get_byte_2
505                 strgeb  r3, [r0], #1
506                 movgt   r3, r7, get_byte_3
507                 strgtb  r3, [r0], #1
508                 b       .cfu_finished
509
510 .cfu_2fupi:     subs    r2, r2, #4
511                 addmi   ip, r2, #4
512                 bmi     .cfu_2nowords
513                 mov     r3, r7, pull #16
514 USER(           ldrt    r7, [r1], #4)                   @ May fault
515                 orr     r3, r3, r7, push #16
516                 str     r3, [r0], #4
517                 mov     ip, r1, lsl #32 - PAGE_SHIFT
518                 rsb     ip, ip, #0
519                 movs    ip, ip, lsr #32 - PAGE_SHIFT
520                 beq     .cfu_2fupi
521                 cmp     r2, ip
522                 movlt   ip, r2
523                 sub     r2, r2, ip
524                 subs    ip, ip, #16
525                 blt     .cfu_2rem8lp
526         PLD(    pld     [r1, #12]               )
527         PLD(    pld     [r0, #12]               )
528         PLD(    subs    ip, ip, #32             )
529         PLD(    blt     .cfu_2cpynopld          )
530         PLD(    pld     [r1, #28]               )
531         PLD(    pld     [r0, #28]               )
532
533 .cfu_2cpy8lp:
534         PLD(    pld     [r1, #44]               )
535         PLD(    pld     [r0, #44]               )
536 .cfu_2cpynopld: mov     r3, r7, pull #16
537                 ldmia   r1!, {r4 - r7}                  @ Shouldnt fault
538                 subs    ip, ip, #16
539                 orr     r3, r3, r4, push #16
540                 mov     r4, r4, pull #16
541                 orr     r4, r4, r5, push #16
542                 mov     r5, r5, pull #16
543                 orr     r5, r5, r6, push #16
544                 mov     r6, r6, pull #16
545                 orr     r6, r6, r7, push #16
546                 stmia   r0!, {r3 - r6}
547                 bpl     .cfu_2cpy8lp
548         PLD(    cmn     ip, #32                 )
549         PLD(    bge     .cfu_2cpynopld          )
550         PLD(    add     ip, ip, #32             )
551
552 .cfu_2rem8lp:   tst     ip, #8
553                 movne   r3, r7, pull #16
554                 ldmneia r1!, {r4, r7}                   @ Shouldnt fault
555                 orrne   r3, r3, r4, push #16
556                 movne   r4, r4, pull #16
557                 orrne   r4, r4, r7, push #16
558                 stmneia r0!, {r3 - r4}
559                 tst     ip, #4
560                 movne   r3, r7, pull #16
561 USER(           ldrnet  r7, [r1], #4)                   @ May fault
562                 orrne   r3, r3, r7, push #16
563                 strne   r3, [r0], #4
564                 ands    ip, ip, #3
565                 beq     .cfu_2fupi
566 .cfu_2nowords:  mov     r3, r7, get_byte_2
567                 teq     ip, #0
568                 beq     .cfu_finished
569                 cmp     ip, #2
570                 strb    r3, [r0], #1
571                 movge   r3, r7, get_byte_3
572                 strgeb  r3, [r0], #1
573 USER(           ldrgtbt r3, [r1], #0)                   @ May fault
574                 strgtb  r3, [r0], #1
575                 b       .cfu_finished
576
577 .cfu_3fupi:     subs    r2, r2, #4
578                 addmi   ip, r2, #4
579                 bmi     .cfu_3nowords
580                 mov     r3, r7, pull #24
581 USER(           ldrt    r7, [r1], #4)                   @ May fault
582                 orr     r3, r3, r7, push #8
583                 str     r3, [r0], #4
584                 mov     ip, r1, lsl #32 - PAGE_SHIFT
585                 rsb     ip, ip, #0
586                 movs    ip, ip, lsr #32 - PAGE_SHIFT
587                 beq     .cfu_3fupi
588                 cmp     r2, ip
589                 movlt   ip, r2
590                 sub     r2, r2, ip
591                 subs    ip, ip, #16
592                 blt     .cfu_3rem8lp
593         PLD(    pld     [r1, #12]               )
594         PLD(    pld     [r0, #12]               )
595         PLD(    subs    ip, ip, #32             )
596         PLD(    blt     .cfu_3cpynopld          )
597         PLD(    pld     [r1, #28]               )
598         PLD(    pld     [r0, #28]               )
599
600 .cfu_3cpy8lp:
601         PLD(    pld     [r1, #44]               )
602         PLD(    pld     [r0, #44]               )
603 .cfu_3cpynopld: mov     r3, r7, pull #24
604                 ldmia   r1!, {r4 - r7}                  @ Shouldnt fault
605                 orr     r3, r3, r4, push #8
606                 mov     r4, r4, pull #24
607                 orr     r4, r4, r5, push #8
608                 mov     r5, r5, pull #24
609                 orr     r5, r5, r6, push #8
610                 mov     r6, r6, pull #24
611                 orr     r6, r6, r7, push #8
612                 stmia   r0!, {r3 - r6}
613                 subs    ip, ip, #16
614                 bpl     .cfu_3cpy8lp
615         PLD(    cmn     ip, #32                 )
616         PLD(    bge     .cfu_3cpynopld          )
617         PLD(    add     ip, ip, #32             )
618
619 .cfu_3rem8lp:   tst     ip, #8
620                 movne   r3, r7, pull #24
621                 ldmneia r1!, {r4, r7}                   @ Shouldnt fault
622                 orrne   r3, r3, r4, push #8
623                 movne   r4, r4, pull #24
624                 orrne   r4, r4, r7, push #8
625                 stmneia r0!, {r3 - r4}
626                 tst     ip, #4
627                 movne   r3, r7, pull #24
628 USER(           ldrnet  r7, [r1], #4)                   @ May fault
629                 orrne   r3, r3, r7, push #8
630                 strne   r3, [r0], #4
631                 ands    ip, ip, #3
632                 beq     .cfu_3fupi
633 .cfu_3nowords:  mov     r3, r7, get_byte_3
634                 teq     ip, #0
635                 beq     .cfu_finished
636                 cmp     ip, #2
637                 strb    r3, [r0], #1
638 USER(           ldrgebt r3, [r1], #1)                   @ May fault
639                 strgeb  r3, [r0], #1
640 USER(           ldrgtbt r3, [r1], #1)                   @ May fault
641                 strgtb  r3, [r0], #1
642                 b       .cfu_finished
643
644                 .section .fixup,"ax"
645                 .align  0
646                 /*
647                  * We took an exception.  r0 contains a pointer to
648                  * the byte not copied.
649                  */
650 9001:           ldr     r2, [sp], #4                    @ void *to
651                 sub     r2, r0, r2                      @ bytes copied
652                 ldr     r1, [sp], #4                    @ unsigned long count
653                 subs    r4, r1, r2                      @ bytes left to copy
654                 movne   r1, r4
655                 blne    __memzero
656                 mov     r0, r4
657                 LOADREGS(fd,sp!, {r4 - r7, pc})
658                 .previous
659
660 /* Prototype: int __arch_clear_user(void *addr, size_t sz)
661  * Purpose  : clear some user memory
662  * Params   : addr - user memory address to clear
663  *          : sz   - number of bytes to clear
664  * Returns  : number of bytes NOT cleared
665  */
666 ENTRY(__arch_clear_user)
667                 stmfd   sp!, {r1, lr}
668                 mov     r2, #0
669                 cmp     r1, #4
670                 blt     2f
671                 ands    ip, r0, #3
672                 beq     1f
673                 cmp     ip, #2
674 USER(           strbt   r2, [r0], #1)
675 USER(           strlebt r2, [r0], #1)
676 USER(           strltbt r2, [r0], #1)
677                 rsb     ip, ip, #4
678                 sub     r1, r1, ip              @  7  6  5  4  3  2  1
679 1:              subs    r1, r1, #8              @ -1 -2 -3 -4 -5 -6 -7
680 USER(           strplt  r2, [r0], #4)
681 USER(           strplt  r2, [r0], #4)
682                 bpl     1b
683                 adds    r1, r1, #4              @  3  2  1  0 -1 -2 -3
684 USER(           strplt  r2, [r0], #4)
685 2:              tst     r1, #2                  @ 1x 1x 0x 0x 1x 1x 0x
686 USER(           strnebt r2, [r0], #1)
687 USER(           strnebt r2, [r0], #1)
688                 tst     r1, #1                  @ x1 x0 x1 x0 x1 x0 x1
689 USER(           strnebt r2, [r0], #1)
690                 mov     r0, #0
691                 LOADREGS(fd,sp!, {r1, pc})
692
693                 .section .fixup,"ax"
694                 .align  0
695 9001:           LOADREGS(fd,sp!, {r0, pc})
696                 .previous
697