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