PageRenderTime 58ms CodeModel.GetById 10ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/arm26/lib/uaccess-user.S

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