Linux 3.16-rc2
[linux/fpc-iii.git] / arch / microblaze / lib / uaccess_old.S
blob0e8cc2710c27fb3503eee296f9041cc38659a99c
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  */
11 #include <linux/errno.h>
12 #include <linux/linkage.h>
13 #include <asm/page.h>
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  */
24         .text
25 .globl __strncpy_user;
26 .type  __strncpy_user, @function
27 .align 4;
28 __strncpy_user:
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 */
40         lbu     r4,r6,r0
41         beqid   r4,2f
42         sb      r4,r5,r0
44         addik   r5,r5,1
45         addik   r6,r6,1         /* delay slot */
47         addik   r3,r3,-1
48         bnei    r3,1b           /* break on len */
50         rsubk   r3,r3,r7        /* temp_count = len - temp_count */
52         rtsd    r15,8
53         nop
54         .size   __strncpy_user, . - __strncpy_user
56         .section        .fixup, "ax"
57         .align  2
59         brid    3b
60         addik   r3,r0, -EFAULT
62         .section        __ex_table, "a"
63         .word   1b,4b
66  * int __strnlen_user(char __user *str, int maxlen);
67  *
68  * Returns:
69  *  0 on error
70  *  maxlen + 1  if no NUL byte found within maxlen bytes
71  *  size of the string (including NUL byte)
72  */
74         .text
75 .globl __strnlen_user;
76 .type  __strnlen_user, @function
77 .align 4;
78 __strnlen_user:
79         beqid   r6,3f
80         addik   r3,r6,0
82         lbu     r4,r5,r0
83         beqid   r4,2f           /* break on NUL */
84         addik   r3,r3,-1        /* delay slot */
86         bneid   r3,1b
87         addik   r5,r5,1         /* delay slot */
89         addik   r3,r3,-1        /* for break on len */
91         rsubk   r3,r3,r6
93         rtsd    r15,8
94         nop
95         .size   __strnlen_user, . - __strnlen_user
97         .section        .fixup,"ax"
99         brid    3b
100         addk    r3,r0,r0
102         .section        __ex_table,"a"
103         .word   1b,4b
105 /* Loop unrolling for __copy_tofrom_user */
106 #define COPY(offset)    \
107 1:      lwi     r4 , r6, 0x0000 + offset;       \
108 2:      lwi     r19, r6, 0x0004 + offset;       \
109 3:      lwi     r20, r6, 0x0008 + offset;       \
110 4:      lwi     r21, r6, 0x000C + offset;       \
111 5:      lwi     r22, r6, 0x0010 + offset;       \
112 6:      lwi     r23, r6, 0x0014 + offset;       \
113 7:      lwi     r24, r6, 0x0018 + offset;       \
114 8:      lwi     r25, r6, 0x001C + offset;       \
115 9:      swi     r4 , r5, 0x0000 + offset;       \
116 10:     swi     r19, r5, 0x0004 + offset;       \
117 11:     swi     r20, r5, 0x0008 + offset;       \
118 12:     swi     r21, r5, 0x000C + offset;       \
119 13:     swi     r22, r5, 0x0010 + offset;       \
120 14:     swi     r23, r5, 0x0014 + offset;       \
121 15:     swi     r24, r5, 0x0018 + offset;       \
122 16:     swi     r25, r5, 0x001C + offset;       \
123         .section __ex_table,"a";                \
124         .word   1b, 33f;                        \
125         .word   2b, 33f;                        \
126         .word   3b, 33f;                        \
127         .word   4b, 33f;                        \
128         .word   5b, 33f;                        \
129         .word   6b, 33f;                        \
130         .word   7b, 33f;                        \
131         .word   8b, 33f;                        \
132         .word   9b, 33f;                        \
133         .word   10b, 33f;                       \
134         .word   11b, 33f;                       \
135         .word   12b, 33f;                       \
136         .word   13b, 33f;                       \
137         .word   14b, 33f;                       \
138         .word   15b, 33f;                       \
139         .word   16b, 33f;                       \
140         .text
142 #define COPY_80(offset) \
143         COPY(0x00 + offset);\
144         COPY(0x20 + offset);\
145         COPY(0x40 + offset);\
146         COPY(0x60 + offset);
149  * int __copy_tofrom_user(char *to, char *from, int len)
150  * Return:
151  *   0 on success
152  *   number of not copied bytes on error
153  */
154         .text
155 .globl __copy_tofrom_user;
156 .type  __copy_tofrom_user, @function
157 .align 4;
158 __copy_tofrom_user:
159         /*
160          * r5 - to
161          * r6 - from
162          * r7, r3 - count
163          * r4 - tempval
164          */
165         beqid   r7, 0f /* zero size is not likely */
166         or      r3, r5, r6 /* find if is any to/from unaligned */
167         or      r3, r3, r7 /* find if count is unaligned */
168         andi    r3, r3, 0x3 /* mask last 3 bits */
169         bneid   r3, bu1 /* if r3 is not zero then byte copying */
170         or      r3, r0, r0
172         rsubi   r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
173         beqid   r3, page;
174         or      r3, r0, r0
176 w1:     lw      r4, r6, r3 /* at least one 4 byte copy */
177 w2:     sw      r4, r5, r3
178         addik   r7, r7, -4
179         bneid   r7, w1
180         addik   r3, r3, 4
181         addik   r3, r7, 0
182         rtsd    r15, 8
183         nop
185         .section        __ex_table,"a"
186         .word   w1, 0f;
187         .word   w2, 0f;
188         .text
190 .align 4 /* Alignment is important to keep icache happy */
191 page:   /* Create room on stack and save registers for storign values */
192         addik   r1, r1, -40
193         swi     r5, r1, 0
194         swi     r6, r1, 4
195         swi     r7, r1, 8
196         swi     r19, r1, 12
197         swi     r20, r1, 16
198         swi     r21, r1, 20
199         swi     r22, r1, 24
200         swi     r23, r1, 28
201         swi     r24, r1, 32
202         swi     r25, r1, 36
203 loop:   /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
204         /* Loop unrolling to get performance boost */
205         COPY_80(0x000);
206         COPY_80(0x080);
207         COPY_80(0x100);
208         COPY_80(0x180);
209         /* copy loop */
210         addik   r6, r6, 0x200
211         addik   r7, r7, -0x200
212         bneid   r7, loop
213         addik   r5, r5, 0x200
215         /* Restore register content */
216         lwi     r5, r1, 0
217         lwi     r6, r1, 4
218         lwi     r7, r1, 8
219         lwi     r19, r1, 12
220         lwi     r20, r1, 16
221         lwi     r21, r1, 20
222         lwi     r22, r1, 24
223         lwi     r23, r1, 28
224         lwi     r24, r1, 32
225         lwi     r25, r1, 36
226         addik   r1, r1, 40
227         /* return back */
228         addik   r3, r0, 0
229         rtsd    r15, 8
230         nop
232 /* Fault case - return temp count */
234         addik   r3, r7, 0
235         /* Restore register content */
236         lwi     r5, r1, 0
237         lwi     r6, r1, 4
238         lwi     r7, r1, 8
239         lwi     r19, r1, 12
240         lwi     r20, r1, 16
241         lwi     r21, r1, 20
242         lwi     r22, r1, 24
243         lwi     r23, r1, 28
244         lwi     r24, r1, 32
245         lwi     r25, r1, 36
246         addik   r1, r1, 40
247         /* return back */
248         rtsd    r15, 8
249         nop
251 .align 4 /* Alignment is important to keep icache happy */
252 bu1:    lbu     r4,r6,r3
253 bu2:    sb      r4,r5,r3
254         addik   r7,r7,-1
255         bneid   r7,bu1
256         addik   r3,r3,1         /* delay slot */
258         addik   r3,r7,0
259         rtsd    r15,8
260         nop
261         .size   __copy_tofrom_user, . - __copy_tofrom_user
263         .section        __ex_table,"a"
264         .word   bu1, 0b;
265         .word   bu2, 0b;
266         .text