[PATCH] m68k: clean up uaccess.h
[linux-3.10.git] / arch / m68k / lib / uaccess.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file COPYING in the main directory of this archive
4  * for more details.
5  */
6
7 #include <linux/module.h>
8 #include <asm/uaccess.h>
9
10 unsigned long __generic_copy_from_user(void *to, const void __user *from,
11                                        unsigned long n)
12 {
13         unsigned long tmp, res;
14
15         asm volatile ("\n"
16                 "       tst.l   %0\n"
17                 "       jeq     2f\n"
18                 "1:     moves.l (%1)+,%3\n"
19                 "       move.l  %3,(%2)+\n"
20                 "       subq.l  #1,%0\n"
21                 "       jne     1b\n"
22                 "2:     btst    #1,%5\n"
23                 "       jeq     4f\n"
24                 "3:     moves.w (%1)+,%3\n"
25                 "       move.w  %3,(%2)+\n"
26                 "4:     btst    #0,%5\n"
27                 "       jeq     6f\n"
28                 "5:     moves.b (%1)+,%3\n"
29                 "       move.b  %3,(%2)+\n"
30                 "6:\n"
31                 "       .section .fixup,\"ax\"\n"
32                 "       .even\n"
33                 "10:    move.l  %0,%3\n"
34                 "7:     clr.l   (%2)+\n"
35                 "       subq.l  #1,%3\n"
36                 "       jne     7b\n"
37                 "       lsl.l   #2,%0\n"
38                 "       btst    #1,%5\n"
39                 "       jeq     8f\n"
40                 "30:    clr.w   (%2)+\n"
41                 "       addq.l  #2,%0\n"
42                 "8:     btst    #0,%5\n"
43                 "       jeq     6b\n"
44                 "50:    clr.b   (%2)+\n"
45                 "       addq.l  #1,%0\n"
46                 "       jra     6b\n"
47                 "       .previous\n"
48                 "\n"
49                 "       .section __ex_table,\"a\"\n"
50                 "       .align  4\n"
51                 "       .long   1b,10b\n"
52                 "       .long   3b,30b\n"
53                 "       .long   5b,50b\n"
54                 "       .previous"
55                 : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
56                 : "0" (n / 4), "d" (n & 3));
57
58         return res;
59 }
60 EXPORT_SYMBOL(__generic_copy_from_user);
61
62 unsigned long __generic_copy_to_user(void __user *to, const void *from,
63                                      unsigned long n)
64 {
65         unsigned long tmp, res;
66
67         asm volatile ("\n"
68                 "       tst.l   %0\n"
69                 "       jeq     4f\n"
70                 "1:     move.l  (%1)+,%3\n"
71                 "2:     moves.l %3,(%2)+\n"
72                 "3:     subq.l  #1,%0\n"
73                 "       jne     1b\n"
74                 "4:     btst    #1,%5\n"
75                 "       jeq     6f\n"
76                 "       move.w  (%1)+,%3\n"
77                 "5:     moves.w %3,(%2)+\n"
78                 "6:     btst    #0,%5\n"
79                 "       jeq     8f\n"
80                 "       move.b  (%1)+,%3\n"
81                 "7:     moves.b  %3,(%2)+\n"
82                 "8:\n"
83                 "       .section .fixup,\"ax\"\n"
84                 "       .even\n"
85                 "20:    lsl.l   #2,%0\n"
86                 "50:    add.l   %5,%0\n"
87                 "       jra     7b\n"
88                 "       .previous\n"
89                 "\n"
90                 "       .section __ex_table,\"a\"\n"
91                 "       .align  4\n"
92                 "       .long   2b,20b\n"
93                 "       .long   3b,20b\n"
94                 "       .long   5b,50b\n"
95                 "       .long   6b,50b\n"
96                 "       .long   7b,50b\n"
97                 "       .long   8b,50b\n"
98                 "       .previous"
99                 : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
100                 : "0" (n / 4), "d" (n & 3));
101
102         return res;
103 }
104 EXPORT_SYMBOL(__generic_copy_to_user);
105
106 /*
107  * Copy a null terminated string from userspace.
108  */
109 long strncpy_from_user(char *dst, const char __user *src, long count)
110 {
111         long res;
112         char c;
113
114         if (count <= 0)
115                 return count;
116
117         asm volatile ("\n"
118                 "1:     moves.b (%2)+,%4\n"
119                 "       move.b  %4,(%1)+\n"
120                 "       jeq     2f\n"
121                 "       subq.l  #1,%3\n"
122                 "       jne     1b\n"
123                 "2:     sub.l   %3,%0\n"
124                 "3:\n"
125                 "       .section .fixup,\"ax\"\n"
126                 "       .even\n"
127                 "10:    move.l  %5,%0\n"
128                 "       jra     3b\n"
129                 "       .previous\n"
130                 "\n"
131                 "       .section __ex_table,\"a\"\n"
132                 "       .align  4\n"
133                 "       .long   1b,10b\n"
134                 "       .previous"
135                 : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c)
136                 : "i" (-EFAULT), "0" (count));
137
138         return res;
139 }
140 EXPORT_SYMBOL(strncpy_from_user);
141
142 /*
143  * Return the size of a string (including the ending 0)
144  *
145  * Return 0 on exception, a value greater than N if too long
146  */
147 long strnlen_user(const char __user *src, long n)
148 {
149         char c;
150         long res;
151
152         asm volatile ("\n"
153                 "1:     subq.l  #1,%1\n"
154                 "       jmi     3f\n"
155                 "2:     moves.b (%0)+,%2\n"
156                 "       tst.b   %2\n"
157                 "       jne     1b\n"
158                 "       jra     4f\n"
159                 "\n"
160                 "3:     addq.l  #1,%0\n"
161                 "4:     sub.l   %4,%0\n"
162                 "5:\n"
163                 "       .section .fixup,\"ax\"\n"
164                 "       .even\n"
165                 "20:    sub.l   %0,%0\n"
166                 "       jra     5b\n"
167                 "       .previous\n"
168                 "\n"
169                 "       .section __ex_table,\"a\"\n"
170                 "       .align  4\n"
171                 "       .long   2b,20b\n"
172                 "       .previous\n"
173                 : "=&a" (res), "+d" (n), "=&d" (c)
174                 : "0" (src), "r" (src));
175
176         return res;
177 }
178 EXPORT_SYMBOL(strnlen_user);
179
180 /*
181  * Zero Userspace
182  */
183
184 unsigned long clear_user(void __user *to, unsigned long n)
185 {
186         unsigned long res;
187
188         asm volatile ("\n"
189                 "       tst.l   %0\n"
190                 "       jeq     3f\n"
191                 "1:     moves.l %2,(%1)+\n"
192                 "2:     subq.l  #1,%0\n"
193                 "       jne     1b\n"
194                 "3:     btst    #1,%4\n"
195                 "       jeq     5f\n"
196                 "4:     moves.w %2,(%1)+\n"
197                 "5:     btst    #0,%4\n"
198                 "       jeq     7f\n"
199                 "6:     moves.b %2,(%1)\n"
200                 "7:\n"
201                 "       .section .fixup,\"ax\"\n"
202                 "       .even\n"
203                 "10:    lsl.l   #2,%0\n"
204                 "40:    add.l   %4,%0\n"
205                 "       jra     7b\n"
206                 "       .previous\n"
207                 "\n"
208                 "       .section __ex_table,\"a\"\n"
209                 "       .align  4\n"
210                 "       .long   1b,10b\n"
211                 "       .long   2b,10b\n"
212                 "       .long   4b,40b\n"
213                 "       .long   5b,40b\n"
214                 "       .long   6b,40b\n"
215                 "       .long   7b,40b\n"
216                 "       .previous"
217                 : "=d" (res), "+a" (to)
218                 : "r" (0), "0" (n / 4), "d" (n & 3));
219
220     return res;
221 }
222 EXPORT_SYMBOL(clear_user);