xref: /linux/arch/microblaze/lib/uaccess_old.S (revision f2ee442115c9b6219083c019939a9cc0c9abb2f8)
1/*
2 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
3 * Copyright (C) 2009 PetaLogix
4 * Copyright (C) 2007 LynuxWorks, Inc.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License.  See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/errno.h>
12#include <linux/linkage.h>
13#include <asm/page.h>
14
15/*
16 * int __strncpy_user(char *to, char *from, int len);
17 *
18 * Returns:
19 *  -EFAULT  for an exception
20 *  len      if we hit the buffer limit
21 *  bytes copied
22 */
23
24	.text
25.globl __strncpy_user;
26.type  __strncpy_user, @function
27.align 4;
28__strncpy_user:
29
30	/*
31	 * r5 - to
32	 * r6 - from
33	 * r7 - len
34	 * r3 - temp count
35	 * r4 - temp val
36	 */
37	beqid	r7,3f
38	addik	r3,r7,0		/* temp_count = len */
391:
40	lbu	r4,r6,r0
41	sb	r4,r5,r0
42
43	addik	r3,r3,-1
44	beqi	r3,2f		/* break on len */
45
46	addik	r5,r5,1
47	bneid	r4,1b
48	addik	r6,r6,1		/* delay slot */
49	addik	r3,r3,1		/* undo "temp_count--" */
502:
51	rsubk	r3,r3,r7	/* temp_count = len - temp_count */
523:
53	rtsd	r15,8
54	nop
55	.size   __strncpy_user, . - __strncpy_user
56
57	.section	.fixup, "ax"
58	.align	2
594:
60	brid	3b
61	addik	r3,r0, -EFAULT
62
63	.section	__ex_table, "a"
64	.word	1b,4b
65
66/*
67 * int __strnlen_user(char __user *str, int maxlen);
68 *
69 * Returns:
70 *  0 on error
71 *  maxlen + 1  if no NUL byte found within maxlen bytes
72 *  size of the string (including NUL byte)
73 */
74
75	.text
76.globl __strnlen_user;
77.type  __strnlen_user, @function
78.align 4;
79__strnlen_user:
80	beqid	r6,3f
81	addik	r3,r6,0
821:
83	lbu	r4,r5,r0
84	beqid	r4,2f		/* break on NUL */
85	addik	r3,r3,-1	/* delay slot */
86
87	bneid	r3,1b
88	addik	r5,r5,1		/* delay slot */
89
90	addik	r3,r3,-1	/* for break on len */
912:
92	rsubk	r3,r3,r6
933:
94	rtsd	r15,8
95	nop
96	.size   __strnlen_user, . - __strnlen_user
97
98	.section	.fixup,"ax"
994:
100	brid	3b
101	addk	r3,r0,r0
102
103	.section	__ex_table,"a"
104	.word	1b,4b
105
106/* Loop unrolling for __copy_tofrom_user */
107#define COPY(offset)	\
1081:	lwi	r4 , r6, 0x0000 + offset;	\
1092:	lwi	r19, r6, 0x0004 + offset;	\
1103:	lwi	r20, r6, 0x0008 + offset;	\
1114:	lwi	r21, r6, 0x000C + offset;	\
1125:	lwi	r22, r6, 0x0010 + offset;	\
1136:	lwi	r23, r6, 0x0014 + offset;	\
1147:	lwi	r24, r6, 0x0018 + offset;	\
1158:	lwi	r25, r6, 0x001C + offset;	\
1169:	swi	r4 , r5, 0x0000 + offset;	\
11710:	swi	r19, r5, 0x0004 + offset;	\
11811:	swi	r20, r5, 0x0008 + offset;	\
11912:	swi	r21, r5, 0x000C + offset;	\
12013:	swi	r22, r5, 0x0010 + offset;	\
12114:	swi	r23, r5, 0x0014 + offset;	\
12215:	swi	r24, r5, 0x0018 + offset;	\
12316:	swi	r25, r5, 0x001C + offset;	\
124	.section __ex_table,"a";		\
125	.word	1b, 0f;				\
126	.word	2b, 0f;				\
127	.word	3b, 0f;				\
128	.word	4b, 0f;				\
129	.word	5b, 0f;				\
130	.word	6b, 0f;				\
131	.word	7b, 0f;				\
132	.word	8b, 0f;				\
133	.word	9b, 0f;				\
134	.word	10b, 0f;			\
135	.word	11b, 0f;			\
136	.word	12b, 0f;			\
137	.word	13b, 0f;			\
138	.word	14b, 0f;			\
139	.word	15b, 0f;			\
140	.word	16b, 0f;			\
141	.text
142
143#define COPY_80(offset)	\
144	COPY(0x00 + offset);\
145	COPY(0x20 + offset);\
146	COPY(0x40 + offset);\
147	COPY(0x60 + offset);
148
149/*
150 * int __copy_tofrom_user(char *to, char *from, int len)
151 * Return:
152 *   0 on success
153 *   number of not copied bytes on error
154 */
155	.text
156.globl __copy_tofrom_user;
157.type  __copy_tofrom_user, @function
158.align 4;
159__copy_tofrom_user:
160	/*
161	 * r5 - to
162	 * r6 - from
163	 * r7, r3 - count
164	 * r4 - tempval
165	 */
166	beqid	r7, 0f /* zero size is not likely */
167	or	r3, r5, r6 /* find if is any to/from unaligned */
168	or	r3, r3, r7 /* find if count is unaligned */
169	andi	r3, r3, 0x3 /* mask last 3 bits */
170	bneid	r3, bu1 /* if r3 is not zero then byte copying */
171	or	r3, r0, r0
172
173	rsubi	r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
174	beqid	r3, page;
175	or	r3, r0, r0
176
177w1:	lw	r4, r6, r3 /* at least one 4 byte copy */
178w2:	sw	r4, r5, r3
179	addik	r7, r7, -4
180	bneid	r7, w1
181	addik	r3, r3, 4
182	addik	r3, r7, 0
183	rtsd	r15, 8
184	nop
185
186	.section	__ex_table,"a"
187	.word	w1, 0f;
188	.word	w2, 0f;
189	.text
190
191.align 4 /* Alignment is important to keep icache happy */
192page:	/* Create room on stack and save registers for storign values */
193	addik   r1, r1, -32
194	swi	r19, r1, 4
195	swi	r20, r1, 8
196	swi	r21, r1, 12
197	swi	r22, r1, 16
198	swi	r23, r1, 20
199	swi	r24, r1, 24
200	swi	r25, r1, 28
201loop:	/* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
202	/* Loop unrolling to get performance boost */
203	COPY_80(0x000);
204	COPY_80(0x080);
205	COPY_80(0x100);
206	COPY_80(0x180);
207	/* copy loop */
208	addik	r6, r6, 0x200
209	addik	r7, r7, -0x200
210	bneid	r7, loop
211	addik	r5, r5, 0x200
212	/* Restore register content */
213	lwi	r19, r1, 4
214	lwi	r20, r1, 8
215	lwi	r21, r1, 12
216	lwi	r22, r1, 16
217	lwi	r23, r1, 20
218	lwi	r24, r1, 24
219	lwi	r25, r1, 28
220	addik   r1, r1, 32
221	/* return back */
222	addik	r3, r7, 0
223	rtsd	r15, 8
224	nop
225
226.align 4 /* Alignment is important to keep icache happy */
227bu1:	lbu	r4,r6,r3
228bu2:	sb	r4,r5,r3
229	addik	r7,r7,-1
230	bneid	r7,bu1
231	addik	r3,r3,1		/* delay slot */
2320:
233	addik	r3,r7,0
234	rtsd	r15,8
235	nop
236	.size   __copy_tofrom_user, . - __copy_tofrom_user
237
238	.section	__ex_table,"a"
239	.word	bu1, 0b;
240	.word	bu2, 0b;
241	.text
242