target: Fix bug in handling of FILEIO + block_device resize ops
[linux-flexiantxendom0-3.2.10.git] / arch / microblaze / lib / uaccess_old.S
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 */
39 1:
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--" */
50 2:
51         rsubk   r3,r3,r7        /* temp_count = len - temp_count */
52 3:
53         rtsd    r15,8
54         nop
55         .size   __strncpy_user, . - __strncpy_user
56
57         .section        .fixup, "ax"
58         .align  2
59 4:
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
82 1:
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 */
91 2:
92         rsubk   r3,r3,r6
93 3:
94         rtsd    r15,8
95         nop
96         .size   __strnlen_user, . - __strnlen_user
97
98         .section        .fixup,"ax"
99 4:
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)    \
108 1:      lwi     r4 , r6, 0x0000 + offset;       \
109 2:      lwi     r19, r6, 0x0004 + offset;       \
110 3:      lwi     r20, r6, 0x0008 + offset;       \
111 4:      lwi     r21, r6, 0x000C + offset;       \
112 5:      lwi     r22, r6, 0x0010 + offset;       \
113 6:      lwi     r23, r6, 0x0014 + offset;       \
114 7:      lwi     r24, r6, 0x0018 + offset;       \
115 8:      lwi     r25, r6, 0x001C + offset;       \
116 9:      swi     r4 , r5, 0x0000 + offset;       \
117 10:     swi     r19, r5, 0x0004 + offset;       \
118 11:     swi     r20, r5, 0x0008 + offset;       \
119 12:     swi     r21, r5, 0x000C + offset;       \
120 13:     swi     r22, r5, 0x0010 + offset;       \
121 14:     swi     r23, r5, 0x0014 + offset;       \
122 15:     swi     r24, r5, 0x0018 + offset;       \
123 16:     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
177 w1:     lw      r4, r6, r3 /* at least one 4 byte copy */
178 w2:     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 */
192 page:   /* 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
201 loop:   /* 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 */
227 bu1:    lbu     r4,r6,r3
228 bu2:    sb      r4,r5,r3
229         addik   r7,r7,-1
230         bneid   r7,bu1
231         addik   r3,r3,1         /* delay slot */
232 0:
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