1/* SPDX-License-Identifier: GPL-2.0 */
2/* copy_in_user.S: Copy from userspace to userspace.
3 *
4 * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
5 */
6
7#include <linux/export.h>
8#include <linux/linkage.h>
9#include <asm/asi.h>
10
11#define XCC xcc
12
13#define EX(x,y,z)		\
1498:	x,y;			\
15	.section __ex_table,"a";\
16	.align 4;		\
17	.word 98b, z;		\
18	.text;			\
19	.align 4;
20
21#define EX_O4(x,y) EX(x,y,__retl_o4_plus_8)
22#define EX_O2_4(x,y) EX(x,y,__retl_o2_plus_4)
23#define EX_O2_1(x,y) EX(x,y,__retl_o2_plus_1)
24
25	.register	%g2,#scratch
26	.register	%g3,#scratch
27
28	.text
29__retl_o4_plus_8:
30	add	%o4, %o2, %o4
31	retl
32	 add	%o4, 8, %o0
33__retl_o2_plus_4:
34	retl
35	 add	%o2, 4, %o0
36__retl_o2_plus_1:
37	retl
38	 add	%o2, 1, %o0
39
40	.align	32
41
42	/* Don't try to get too fancy here, just nice and
43	 * simple.  This is predominantly used for well aligned
44	 * small copies in the compat layer.  It is also used
45	 * to copy register windows around during thread cloning.
46	 */
47
48ENTRY(raw_copy_in_user)	/* %o0=dst, %o1=src, %o2=len */
49	cmp		%o2, 0
50	be,pn		%XCC, 85f
51	 or		%o0, %o1, %o3
52	cmp		%o2, 16
53	bleu,a,pn	%XCC, 80f
54	 or		%o3, %o2, %o3
55
56	/* 16 < len <= 64 */
57	andcc		%o3, 0x7, %g0
58	bne,pn		%XCC, 90f
59	 nop
60
61	andn		%o2, 0x7, %o4
62	and		%o2, 0x7, %o2
631:	subcc		%o4, 0x8, %o4
64	EX_O4(ldxa [%o1] %asi, %o5)
65	EX_O4(stxa %o5, [%o0] %asi)
66	add		%o1, 0x8, %o1
67	bgu,pt		%XCC, 1b
68	 add		%o0, 0x8, %o0
69	andcc		%o2, 0x4, %g0
70	be,pt		%XCC, 1f
71	 nop
72	sub		%o2, 0x4, %o2
73	EX_O2_4(lduwa [%o1] %asi, %o5)
74	EX_O2_4(stwa %o5, [%o0] %asi)
75	add		%o1, 0x4, %o1
76	add		%o0, 0x4, %o0
771:	cmp		%o2, 0
78	be,pt		%XCC, 85f
79	 nop
80	ba,pt		%xcc, 90f
81	 nop
82
8380:	/* 0 < len <= 16 */
84	andcc		%o3, 0x3, %g0
85	bne,pn		%XCC, 90f
86	 nop
87
8882:
89	subcc		%o2, 4, %o2
90	EX_O2_4(lduwa [%o1] %asi, %g1)
91	EX_O2_4(stwa %g1, [%o0] %asi)
92	add		%o1, 4, %o1
93	bgu,pt		%XCC, 82b
94	 add		%o0, 4, %o0
95
9685:	retl
97	 clr		%o0
98
99	.align	32
10090:
101	subcc		%o2, 1, %o2
102	EX_O2_1(lduba [%o1] %asi, %g1)
103	EX_O2_1(stba %g1, [%o0] %asi)
104	add		%o1, 1, %o1
105	bgu,pt		%XCC, 90b
106	 add		%o0, 1, %o0
107	retl
108	 clr		%o0
109ENDPROC(raw_copy_in_user)
110EXPORT_SYMBOL(raw_copy_in_user)
111