xref: /openbmc/linux/arch/microblaze/lib/uaccess_old.S (revision 762f99f4f3cb41a775b5157dd761217beba65873)
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 /* Loop unrolling for __copy_tofrom_user */
16 #define COPY(offset)	\
17 1:	lwi	r4 , r6, 0x0000 + offset;	\
18 2:	lwi	r19, r6, 0x0004 + offset;	\
19 3:	lwi	r20, r6, 0x0008 + offset;	\
20 4:	lwi	r21, r6, 0x000C + offset;	\
21 5:	lwi	r22, r6, 0x0010 + offset;	\
22 6:	lwi	r23, r6, 0x0014 + offset;	\
23 7:	lwi	r24, r6, 0x0018 + offset;	\
24 8:	lwi	r25, r6, 0x001C + offset;	\
25 9:	swi	r4 , r5, 0x0000 + offset;	\
26 10:	swi	r19, r5, 0x0004 + offset;	\
27 11:	swi	r20, r5, 0x0008 + offset;	\
28 12:	swi	r21, r5, 0x000C + offset;	\
29 13:	swi	r22, r5, 0x0010 + offset;	\
30 14:	swi	r23, r5, 0x0014 + offset;	\
31 15:	swi	r24, r5, 0x0018 + offset;	\
32 16:	swi	r25, r5, 0x001C + offset;	\
33 	.section __ex_table,"a";		\
34 	.word	1b, 33f;			\
35 	.word	2b, 33f;			\
36 	.word	3b, 33f;			\
37 	.word	4b, 33f;			\
38 	.word	5b, 33f;			\
39 	.word	6b, 33f;			\
40 	.word	7b, 33f;			\
41 	.word	8b, 33f;			\
42 	.word	9b, 33f;			\
43 	.word	10b, 33f;			\
44 	.word	11b, 33f;			\
45 	.word	12b, 33f;			\
46 	.word	13b, 33f;			\
47 	.word	14b, 33f;			\
48 	.word	15b, 33f;			\
49 	.word	16b, 33f;			\
50 	.text
51 
52 #define COPY_80(offset)	\
53 	COPY(0x00 + offset);\
54 	COPY(0x20 + offset);\
55 	COPY(0x40 + offset);\
56 	COPY(0x60 + offset);
57 
58 /*
59  * int __copy_tofrom_user(char *to, char *from, int len)
60  * Return:
61  *   0 on success
62  *   number of not copied bytes on error
63  */
64 	.text
65 .globl __copy_tofrom_user;
66 .type  __copy_tofrom_user, @function
67 .align 4;
68 __copy_tofrom_user:
69 	/*
70 	 * r5 - to
71 	 * r6 - from
72 	 * r7, r3 - count
73 	 * r4 - tempval
74 	 */
75 	beqid	r7, 0f /* zero size is not likely */
76 	or	r3, r5, r6 /* find if is any to/from unaligned */
77 	or	r3, r3, r7 /* find if count is unaligned */
78 	andi	r3, r3, 0x3 /* mask last 3 bits */
79 	bneid	r3, bu1 /* if r3 is not zero then byte copying */
80 	or	r3, r0, r0
81 
82 	rsubi	r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
83 	beqid	r3, page;
84 	or	r3, r0, r0
85 
86 w1:	lw	r4, r6, r3 /* at least one 4 byte copy */
87 w2:	sw	r4, r5, r3
88 	addik	r7, r7, -4
89 	bneid	r7, w1
90 	addik	r3, r3, 4
91 	addik	r3, r7, 0
92 	rtsd	r15, 8
93 	nop
94 
95 	.section	__ex_table,"a"
96 	.word	w1, 0f;
97 	.word	w2, 0f;
98 	.text
99 
100 .align 4 /* Alignment is important to keep icache happy */
101 page:	/* Create room on stack and save registers for storing values */
102 	addik   r1, r1, -40
103 	swi	r5, r1, 0
104 	swi	r6, r1, 4
105 	swi	r7, r1, 8
106 	swi	r19, r1, 12
107 	swi	r20, r1, 16
108 	swi	r21, r1, 20
109 	swi	r22, r1, 24
110 	swi	r23, r1, 28
111 	swi	r24, r1, 32
112 	swi	r25, r1, 36
113 loop:	/* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
114 	/* Loop unrolling to get performance boost */
115 	COPY_80(0x000);
116 	COPY_80(0x080);
117 	COPY_80(0x100);
118 	COPY_80(0x180);
119 	/* copy loop */
120 	addik   r6, r6, 0x200
121 	addik   r7, r7, -0x200
122 	bneid   r7, loop
123 	addik   r5, r5, 0x200
124 
125 	/* Restore register content */
126 	lwi	r5, r1, 0
127 	lwi	r6, r1, 4
128 	lwi	r7, r1, 8
129 	lwi	r19, r1, 12
130 	lwi	r20, r1, 16
131 	lwi	r21, r1, 20
132 	lwi	r22, r1, 24
133 	lwi	r23, r1, 28
134 	lwi	r24, r1, 32
135 	lwi	r25, r1, 36
136 	addik   r1, r1, 40
137 	/* return back */
138 	addik	r3, r0, 0
139 	rtsd	r15, 8
140 	nop
141 
142 /* Fault case - return temp count */
143 33:
144 	addik	r3, r7, 0
145 	/* Restore register content */
146 	lwi	r5, r1, 0
147 	lwi	r6, r1, 4
148 	lwi	r7, r1, 8
149 	lwi	r19, r1, 12
150 	lwi	r20, r1, 16
151 	lwi	r21, r1, 20
152 	lwi	r22, r1, 24
153 	lwi	r23, r1, 28
154 	lwi	r24, r1, 32
155 	lwi	r25, r1, 36
156 	addik   r1, r1, 40
157 	/* return back */
158 	rtsd	r15, 8
159 	nop
160 
161 .align 4 /* Alignment is important to keep icache happy */
162 bu1:	lbu	r4,r6,r3
163 bu2:	sb	r4,r5,r3
164 	addik	r7,r7,-1
165 	bneid	r7,bu1
166 	addik	r3,r3,1		/* delay slot */
167 0:
168 	addik	r3,r7,0
169 	rtsd	r15,8
170 	nop
171 	.size   __copy_tofrom_user, . - __copy_tofrom_user
172 
173 	.section	__ex_table,"a"
174 	.word	bu1, 0b;
175 	.word	bu2, 0b;
176 	.text
177