xref: /linux/arch/sparc/lib/copy_in_user.S (revision 98838d95075a5295f3478ceba18bcccf472e30f4)
1/* copy_in_user.S: Copy from userspace to userspace.
2 *
3 * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
4 */
5
6#include <linux/linkage.h>
7#include <asm/asi.h>
8#include <asm/export.h>
9
10#define XCC xcc
11
12#define EX(x,y)			\
1398:	x,y;			\
14	.section __ex_table,"a";\
15	.align 4;		\
16	.word 98b, __retl_one;	\
17	.text;			\
18	.align 4;
19
20	.register	%g2,#scratch
21	.register	%g3,#scratch
22
23	.text
24	.align	32
25
26	/* Don't try to get too fancy here, just nice and
27	 * simple.  This is predominantly used for well aligned
28	 * small copies in the compat layer.  It is also used
29	 * to copy register windows around during thread cloning.
30	 */
31
32ENTRY(___copy_in_user)	/* %o0=dst, %o1=src, %o2=len */
33	cmp		%o2, 0
34	be,pn		%XCC, 85f
35	 or		%o0, %o1, %o3
36	cmp		%o2, 16
37	bleu,a,pn	%XCC, 80f
38	 or		%o3, %o2, %o3
39
40	/* 16 < len <= 64 */
41	andcc		%o3, 0x7, %g0
42	bne,pn		%XCC, 90f
43	 nop
44
45	andn		%o2, 0x7, %o4
46	and		%o2, 0x7, %o2
471:	subcc		%o4, 0x8, %o4
48	EX(ldxa [%o1] %asi, %o5)
49	EX(stxa %o5, [%o0] %asi)
50	add		%o1, 0x8, %o1
51	bgu,pt		%XCC, 1b
52	 add		%o0, 0x8, %o0
53	andcc		%o2, 0x4, %g0
54	be,pt		%XCC, 1f
55	 nop
56	sub		%o2, 0x4, %o2
57	EX(lduwa [%o1] %asi, %o5)
58	EX(stwa %o5, [%o0] %asi)
59	add		%o1, 0x4, %o1
60	add		%o0, 0x4, %o0
611:	cmp		%o2, 0
62	be,pt		%XCC, 85f
63	 nop
64	ba,pt		%xcc, 90f
65	 nop
66
6780:	/* 0 < len <= 16 */
68	andcc		%o3, 0x3, %g0
69	bne,pn		%XCC, 90f
70	 nop
71
7282:
73	subcc		%o2, 4, %o2
74	EX(lduwa [%o1] %asi, %g1)
75	EX(stwa %g1, [%o0] %asi)
76	add		%o1, 4, %o1
77	bgu,pt		%XCC, 82b
78	 add		%o0, 4, %o0
79
8085:	retl
81	 clr		%o0
82
83	.align	32
8490:
85	subcc		%o2, 1, %o2
86	EX(lduba [%o1] %asi, %g1)
87	EX(stba %g1, [%o0] %asi)
88	add		%o1, 1, %o1
89	bgu,pt		%XCC, 90b
90	 add		%o0, 1, %o0
91	retl
92	 clr		%o0
93ENDPROC(___copy_in_user)
94EXPORT_SYMBOL(___copy_in_user)
95