ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / include / asm-m68k / uaccess.h
1 #ifndef __M68K_UACCESS_H
2 #define __M68K_UACCESS_H
3
4 /*
5  * User space memory access functions
6  */
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <asm/segment.h>
10
11 #define VERIFY_READ     0
12 #define VERIFY_WRITE    1
13
14 /* We let the MMU do all checking */
15 #define access_ok(type,addr,size) 1
16
17 static inline int verify_area(int type, const void *addr, unsigned long size)
18 {
19         return access_ok(type,addr,size)?0:-EFAULT;
20 }
21
22 /*
23  * The exception table consists of pairs of addresses: the first is the
24  * address of an instruction that is allowed to fault, and the second is
25  * the address at which the program should continue.  No registers are
26  * modified, so it is entirely up to the continuation code to figure out
27  * what to do.
28  *
29  * All the routines below use bits of fixup code that are out of line
30  * with the main instruction path.  This means when everything is well,
31  * we don't even have to jump over them.  Further, they do not intrude
32  * on our cache or tlb entries.
33  */
34
35 struct exception_table_entry
36 {
37         unsigned long insn, fixup;
38 };
39
40
41 /*
42  * These are the main single-value transfer routines.  They automatically
43  * use the right size if we just have the right pointer type.
44  */
45
46 #define put_user(x, ptr)                                \
47 ({                                                      \
48     int __pu_err;                                       \
49     typeof(*(ptr)) __pu_val = (x);                      \
50     switch (sizeof (*(ptr))) {                          \
51     case 1:                                             \
52         __put_user_asm(__pu_err, __pu_val, ptr, b);     \
53         break;                                          \
54     case 2:                                             \
55         __put_user_asm(__pu_err, __pu_val, ptr, w);     \
56         break;                                          \
57     case 4:                                             \
58         __put_user_asm(__pu_err, __pu_val, ptr, l);     \
59         break;                                          \
60     case 8:                                             \
61        __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8);        \
62        break;                                           \
63     default:                                            \
64         __pu_err = __put_user_bad();                    \
65         break;                                          \
66     }                                                   \
67     __pu_err;                                           \
68 })
69 #define __put_user(x, ptr) put_user(x, ptr)
70
71 extern int __put_user_bad(void);
72
73 /*
74  * Tell gcc we read from memory instead of writing: this is because
75  * we do not write to any memory gcc knows about, so there are no
76  * aliasing issues.
77  */
78 #define __put_user_asm(err,x,ptr,bwl)                   \
79 __asm__ __volatile__                                    \
80     ("21:moves" #bwl " %2,%1\n"                         \
81      "1:\n"                                             \
82      ".section .fixup,\"ax\"\n"                         \
83      "   .even\n"                                       \
84      "2: movel %3,%0\n"                                 \
85      "   jra 1b\n"                                      \
86      ".previous\n"                                      \
87      ".section __ex_table,\"a\"\n"                      \
88      "   .align 4\n"                                    \
89      "   .long 21b,2b\n"                                \
90      "   .long 1b,2b\n"                                 \
91      ".previous"                                        \
92      : "=d"(err)                                        \
93      : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
94
95 #define get_user(x, ptr)                                        \
96 ({                                                              \
97     int __gu_err;                                               \
98     typeof(*(ptr)) __gu_val;                                    \
99     switch (sizeof(*(ptr))) {                                   \
100     case 1:                                                     \
101         __get_user_asm(__gu_err, __gu_val, ptr, b, "=d");       \
102         break;                                                  \
103     case 2:                                                     \
104         __get_user_asm(__gu_err, __gu_val, ptr, w, "=r");       \
105         break;                                                  \
106     case 4:                                                     \
107         __get_user_asm(__gu_err, __gu_val, ptr, l, "=r");       \
108         break;                                                  \
109     case 8:                                                     \
110         __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8);  \
111         break;                                                  \
112     default:                                                    \
113         __gu_val = 0;                                           \
114         __gu_err = __get_user_bad();                            \
115         break;                                                  \
116     }                                                           \
117     (x) = __gu_val;                                             \
118     __gu_err;                                                   \
119 })
120 #define __get_user(x, ptr) get_user(x, ptr)
121
122 extern int __get_user_bad(void);
123
124 #define __get_user_asm(err,x,ptr,bwl,reg)       \
125 __asm__ __volatile__                            \
126     ("1: moves" #bwl " %2,%1\n"                 \
127      "2:\n"                                     \
128      ".section .fixup,\"ax\"\n"                 \
129      "   .even\n"                               \
130      "3: movel %3,%0\n"                         \
131      "   sub" #bwl " %1,%1\n"                   \
132      "   jra 2b\n"                              \
133      ".previous\n"                              \
134      ".section __ex_table,\"a\"\n"              \
135      "   .align 4\n"                            \
136      "   .long 1b,3b\n"                         \
137      ".previous"                                \
138      : "=d"(err), reg(x)                        \
139      : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
140
141 static inline unsigned long
142 __generic_copy_from_user(void *to, const void *from, unsigned long n)
143 {
144     unsigned long tmp;
145     __asm__ __volatile__
146         ("   tstl %2\n"
147          "   jeq 2f\n"
148          "1: movesl (%1)+,%3\n"
149          "   movel %3,(%0)+\n"
150          "   subql #1,%2\n"
151          "   jne 1b\n"
152          "2: movel %4,%2\n"
153          "   bclr #1,%2\n"
154          "   jeq 4f\n"
155          "3: movesw (%1)+,%3\n"
156          "   movew %3,(%0)+\n"
157          "4: bclr #0,%2\n"
158          "   jeq 6f\n"
159          "5: movesb (%1)+,%3\n"
160          "   moveb %3,(%0)+\n"
161          "6:\n"
162          ".section .fixup,\"ax\"\n"
163          "   .even\n"
164          "7: movel %2,%%d0\n"
165          "71:clrl (%0)+\n"
166          "   subql #1,%%d0\n"
167          "   jne 71b\n"
168          "   lsll #2,%2\n"
169          "   addl %4,%2\n"
170          "   btst #1,%4\n"
171          "   jne 81f\n"
172          "   btst #0,%4\n"
173          "   jne 91f\n"
174          "   jra 6b\n"
175          "8: addql #2,%2\n"
176          "81:clrw (%0)+\n"
177          "   btst #0,%4\n"
178          "   jne 91f\n"
179          "   jra 6b\n"
180          "9: addql #1,%2\n"
181          "91:clrb (%0)+\n"
182          "   jra 6b\n"
183          ".previous\n"
184          ".section __ex_table,\"a\"\n"
185          "   .align 4\n"
186          "   .long 1b,7b\n"
187          "   .long 3b,8b\n"
188          "   .long 5b,9b\n"
189          ".previous"
190          : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
191          : "d"(n & 3), "0"(to), "1"(from), "2"(n/4)
192          : "d0", "memory");
193     return n;
194 }
195
196 static inline unsigned long
197 __generic_copy_to_user(void *to, const void *from, unsigned long n)
198 {
199     unsigned long tmp;
200     __asm__ __volatile__
201         ("   tstl %2\n"
202          "   jeq 3f\n"
203          "1: movel (%1)+,%3\n"
204          "22:movesl %3,(%0)+\n"
205          "2: subql #1,%2\n"
206          "   jne 1b\n"
207          "3: movel %4,%2\n"
208          "   bclr #1,%2\n"
209          "   jeq 4f\n"
210          "   movew (%1)+,%3\n"
211          "24:movesw %3,(%0)+\n"
212          "4: bclr #0,%2\n"
213          "   jeq 5f\n"
214          "   moveb (%1)+,%3\n"
215          "25:movesb %3,(%0)+\n"
216          "5:\n"
217          ".section .fixup,\"ax\"\n"
218          "   .even\n"
219          "60:addql #1,%2\n"
220          "6: lsll #2,%2\n"
221          "   addl %4,%2\n"
222          "   jra 5b\n"
223          "7: addql #2,%2\n"
224          "   jra 5b\n"
225          "8: addql #1,%2\n"
226          "   jra 5b\n"
227          ".previous\n"
228          ".section __ex_table,\"a\"\n"
229          "   .align 4\n"
230          "   .long 1b,60b\n"
231          "   .long 22b,6b\n"
232          "   .long 2b,6b\n"
233          "   .long 24b,7b\n"
234          "   .long 3b,60b\n"
235          "   .long 4b,7b\n"
236          "   .long 25b,8b\n"
237          "   .long 5b,8b\n"
238          ".previous"
239          : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
240          : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)
241          : "memory");
242     return n;
243 }
244
245 #define __copy_from_user_big(to, from, n, fixup, copy)  \
246     __asm__ __volatile__                                \
247         ("10: movesl (%1)+,%%d0\n"                      \
248          "    movel %%d0,(%0)+\n"                       \
249          "    subql #1,%2\n"                            \
250          "    jne 10b\n"                                \
251          ".section .fixup,\"ax\"\n"                     \
252          "    .even\n"                                  \
253          "11: movel %2,%%d0\n"                          \
254          "13: clrl (%0)+\n"                             \
255          "    subql #1,%%d0\n"                          \
256          "    jne 13b\n"                                \
257          "    lsll #2,%2\n"                             \
258          fixup "\n"                                     \
259          "    jra 12f\n"                                \
260          ".previous\n"                                  \
261          ".section __ex_table,\"a\"\n"                  \
262          "    .align 4\n"                               \
263          "    .long 10b,11b\n"                          \
264          ".previous\n"                                  \
265          copy "\n"                                      \
266          "12:"                                          \
267          : "=a"(to), "=a"(from), "=d"(n)                \
268          : "0"(to), "1"(from), "2"(n/4)                 \
269          : "d0", "memory")
270
271 static inline unsigned long
272 __constant_copy_from_user(void *to, const void *from, unsigned long n)
273 {
274     switch (n) {
275     case 0:
276         break;
277     case 1:
278         __asm__ __volatile__
279             ("1: movesb (%1)+,%%d0\n"
280              "   moveb %%d0,(%0)+\n"
281              "2:\n"
282              ".section .fixup,\"ax\"\n"
283              "   .even\n"
284              "3: addql #1,%2\n"
285              "   clrb (%0)+\n"
286              "   jra 2b\n"
287              ".previous\n"
288              ".section __ex_table,\"a\"\n"
289              "   .align 4\n"
290              "   .long 1b,3b\n"
291              ".previous"
292              : "=a"(to), "=a"(from), "=d"(n)
293              : "0"(to), "1"(from), "2"(0)
294              : "d0", "memory");
295         break;
296     case 2:
297         __asm__ __volatile__
298             ("1: movesw (%1)+,%%d0\n"
299              "   movew %%d0,(%0)+\n"
300              "2:\n"
301              ".section .fixup,\"ax\"\n"
302              "   .even\n"
303              "3: addql #2,%2\n"
304              "   clrw (%0)+\n"
305              "   jra 2b\n"
306              ".previous\n"
307              ".section __ex_table,\"a\"\n"
308              "   .align 4\n"
309              "   .long 1b,3b\n"
310              ".previous"
311              : "=a"(to), "=a"(from), "=d"(n)
312              : "0"(to), "1"(from), "2"(0)
313              : "d0", "memory");
314         break;
315     case 3:
316         __asm__ __volatile__
317             ("1: movesw (%1)+,%%d0\n"
318              "   movew %%d0,(%0)+\n"
319              "2: movesb (%1)+,%%d0\n"
320              "   moveb %%d0,(%0)+\n"
321              "3:"
322              ".section .fixup,\"ax\"\n"
323              "   .even\n"
324              "4: addql #2,%2\n"
325              "   clrw (%0)+\n"
326              "5: addql #1,%2\n"
327              "   clrb (%0)+\n"
328              "   jra 3b\n"
329              ".previous\n"
330              ".section __ex_table,\"a\"\n"
331              "   .align 4\n"
332              "   .long 1b,4b\n"
333              "   .long 2b,5b\n"
334              ".previous"
335              : "=a"(to), "=a"(from), "=d"(n)
336              : "0"(to), "1"(from), "2"(0)
337              : "d0", "memory");
338         break;
339     case 4:
340         __asm__ __volatile__
341             ("1: movesl (%1)+,%%d0\n"
342              "   movel %%d0,(%0)+\n"
343              "2:"
344              ".section .fixup,\"ax\"\n"
345              "   .even\n"
346              "3: addql #4,%2\n"
347              "   clrl (%0)+\n"
348              "   jra 2b\n"
349              ".previous\n"
350              ".section __ex_table,\"a\"\n"
351              "   .align 4\n"
352              "   .long 1b,3b\n"
353              ".previous"
354              : "=a"(to), "=a"(from), "=d"(n)
355              : "0"(to), "1"(from), "2"(0)
356              : "d0", "memory");
357         break;
358     case 8:
359         __asm__ __volatile__
360             ("1: movesl (%1)+,%%d0\n"
361              "   movel %%d0,(%0)+\n"
362              "2: movesl (%1)+,%%d0\n"
363              "   movel %%d0,(%0)+\n"
364              "3:"
365              ".section .fixup,\"ax\"\n"
366              "   .even\n"
367              "4: addql #4,%2\n"
368              "   clrl (%0)+\n"
369              "5: addql #4,%2\n"
370              "   clrl (%0)+\n"
371              "   jra 3b\n"
372              ".previous\n"
373              ".section __ex_table,\"a\"\n"
374              "   .align 4\n"
375              "   .long 1b,4b\n"
376              "   .long 2b,5b\n"
377              ".previous"
378              : "=a"(to), "=a"(from), "=d"(n)
379              : "0"(to), "1"(from), "2"(0)
380              : "d0", "memory");
381         break;
382     case 12:
383         __asm__ __volatile__
384             ("1: movesl (%1)+,%%d0\n"
385              "   movel %%d0,(%0)+\n"
386              "2: movesl (%1)+,%%d0\n"
387              "   movel %%d0,(%0)+\n"
388              "3: movesl (%1)+,%%d0\n"
389              "   movel %%d0,(%0)+\n"
390              "4:"
391              ".section .fixup,\"ax\"\n"
392              "   .even\n"
393              "5: addql #4,%2\n"
394              "   clrl (%0)+\n"
395              "6: addql #4,%2\n"
396              "   clrl (%0)+\n"
397              "7: addql #4,%2\n"
398              "   clrl (%0)+\n"
399              "   jra 4b\n"
400              ".previous\n"
401              ".section __ex_table,\"a\"\n"
402              "   .align 4\n"
403              "   .long 1b,5b\n"
404              "   .long 2b,6b\n"
405              "   .long 3b,7b\n"
406              ".previous"
407              : "=a"(to), "=a"(from), "=d"(n)
408              : "0"(to), "1"(from), "2"(0)
409              : "d0", "memory");
410         break;
411     case 16:
412         __asm__ __volatile__
413             ("1: movesl (%1)+,%%d0\n"
414              "   movel %%d0,(%0)+\n"
415              "2: movesl (%1)+,%%d0\n"
416              "   movel %%d0,(%0)+\n"
417              "3: movesl (%1)+,%%d0\n"
418              "   movel %%d0,(%0)+\n"
419              "4: movesl (%1)+,%%d0\n"
420              "   movel %%d0,(%0)+\n"
421              "5:"
422              ".section .fixup,\"ax\"\n"
423              "   .even\n"
424              "6: addql #4,%2\n"
425              "   clrl (%0)+\n"
426              "7: addql #4,%2\n"
427              "   clrl (%0)+\n"
428              "8: addql #4,%2\n"
429              "   clrl (%0)+\n"
430              "9: addql #4,%2\n"
431              "   clrl (%0)+\n"
432              "   jra 5b\n"
433              ".previous\n"
434              ".section __ex_table,\"a\"\n"
435              "   .align 4\n"
436              "   .long 1b,6b\n"
437              "   .long 2b,7b\n"
438              "   .long 3b,8b\n"
439              "   .long 4b,9b\n"
440              ".previous"
441              : "=a"(to), "=a"(from), "=d"(n)
442              : "0"(to), "1"(from), "2"(0)
443              : "d0", "memory");
444         break;
445     default:
446         switch (n & 3) {
447         case 0:
448             __copy_from_user_big(to, from, n, "", "");
449             break;
450         case 1:
451             __copy_from_user_big(to, from, n,
452                                  /* fixup */
453                                  "1: addql #1,%2\n"
454                                  "   clrb (%0)+",
455                                  /* copy */
456                                  "2: movesb (%1)+,%%d0\n"
457                                  "   moveb %%d0,(%0)+\n"
458                                  ".section __ex_table,\"a\"\n"
459                                  "   .long 2b,1b\n"
460                                  ".previous");
461             break;
462         case 2:
463             __copy_from_user_big(to, from, n,
464                                  /* fixup */
465                                  "1: addql #2,%2\n"
466                                  "   clrw (%0)+",
467                                  /* copy */
468                                  "2: movesw (%1)+,%%d0\n"
469                                  "   movew %%d0,(%0)+\n"
470                                  ".section __ex_table,\"a\"\n"
471                                  "   .long 2b,1b\n"
472                                  ".previous");
473             break;
474         case 3:
475             __copy_from_user_big(to, from, n,
476                                  /* fixup */
477                                  "1: addql #2,%2\n"
478                                  "   clrw (%0)+\n"
479                                  "2: addql #1,%2\n"
480                                  "   clrb (%0)+",
481                                  /* copy */
482                                  "3: movesw (%1)+,%%d0\n"
483                                  "   movew %%d0,(%0)+\n"
484                                  "4: movesb (%1)+,%%d0\n"
485                                  "   moveb %%d0,(%0)+\n"
486                                  ".section __ex_table,\"a\"\n"
487                                  "   .long 3b,1b\n"
488                                  "   .long 4b,2b\n"
489                                  ".previous");
490             break;
491         }
492         break;
493     }
494     return n;
495 }
496
497 #define __copy_to_user_big(to, from, n, fixup, copy)    \
498     __asm__ __volatile__                                \
499         ("10: movel (%1)+,%%d0\n"                       \
500          "31: movesl %%d0,(%0)+\n"                      \
501          "11: subql #1,%2\n"                            \
502          "    jne 10b\n"                                \
503          "41:\n"                                        \
504          ".section .fixup,\"ax\"\n"                     \
505          "   .even\n"                                   \
506          "22: addql #1,%2\n"                            \
507          "12: lsll #2,%2\n"                             \
508          fixup "\n"                                     \
509          "    jra 13f\n"                                \
510          ".previous\n"                                  \
511          ".section __ex_table,\"a\"\n"                  \
512          "    .align 4\n"                               \
513          "    .long 10b,22b\n"                          \
514          "    .long 31b,12b\n"                          \
515          "    .long 11b,12b\n"                          \
516          "    .long 41b,22b\n"                          \
517          ".previous\n"                                  \
518          copy "\n"                                      \
519          "13:"                                          \
520          : "=a"(to), "=a"(from), "=d"(n)                \
521          : "0"(to), "1"(from), "2"(n/4)                 \
522          : "d0", "memory")
523
524 static inline unsigned long
525 __constant_copy_to_user(void *to, const void *from, unsigned long n)
526 {
527     switch (n) {
528     case 0:
529         break;
530     case 1:
531         __asm__ __volatile__
532             ("   moveb (%1)+,%%d0\n"
533              "21:movesb %%d0,(%0)+\n"
534              "1:\n"
535              ".section .fixup,\"ax\"\n"
536              "   .even\n"
537              "2: addql #1,%2\n"
538              "   jra 1b\n"
539              ".previous\n"
540              ".section __ex_table,\"a\"\n"
541              "   .align 4\n  "
542              "   .long 21b,2b\n"
543              "   .long 1b,2b\n"
544              ".previous"
545              : "=a"(to), "=a"(from), "=d"(n)
546              : "0"(to), "1"(from), "2"(0)
547              : "d0", "memory");
548         break;
549     case 2:
550         __asm__ __volatile__
551             ("   movew (%1)+,%%d0\n"
552              "21:movesw %%d0,(%0)+\n"
553              "1:\n"
554              ".section .fixup,\"ax\"\n"
555              "   .even\n"
556              "2: addql #2,%2\n"
557              "   jra 1b\n"
558              ".previous\n"
559              ".section __ex_table,\"a\"\n"
560              "   .align 4\n"
561              "   .long 21b,2b\n"
562              "   .long 1b,2b\n"
563              ".previous"
564              : "=a"(to), "=a"(from), "=d"(n)
565              : "0"(to), "1"(from), "2"(0)
566              : "d0", "memory");
567         break;
568     case 3:
569         __asm__ __volatile__
570             ("   movew (%1)+,%%d0\n"
571              "21:movesw %%d0,(%0)+\n"
572              "1: moveb (%1)+,%%d0\n"
573              "22:movesb %%d0,(%0)+\n"
574              "2:\n"
575              ".section .fixup,\"ax\"\n"
576              "   .even\n"
577              "3: addql #2,%2\n"
578              "4: addql #1,%2\n"
579              "   jra 2b\n"
580              ".previous\n"
581              ".section __ex_table,\"a\"\n"
582              "   .align 4\n"
583              "   .long 21b,3b\n"
584              "   .long 1b,3b\n"
585              "   .long 22b,4b\n"
586              "   .long 2b,4b\n"
587              ".previous"
588              : "=a"(to), "=a"(from), "=d"(n)
589              : "0"(to), "1"(from), "2"(0)
590              : "d0", "memory");
591         break;
592     case 4:
593         __asm__ __volatile__
594             ("   movel (%1)+,%%d0\n"
595              "21:movesl %%d0,(%0)+\n"
596              "1:\n"
597              ".section .fixup,\"ax\"\n"
598              "   .even\n"
599              "2: addql #4,%2\n"
600              "   jra 1b\n"
601              ".previous\n"
602              ".section __ex_table,\"a\"\n"
603              "   .align 4\n"
604              "   .long 21b,2b\n"
605              "   .long 1b,2b\n"
606              ".previous"
607              : "=a"(to), "=a"(from), "=d"(n)
608              : "0"(to), "1"(from), "2"(0)
609              : "d0", "memory");
610         break;
611     case 8:
612         __asm__ __volatile__
613             ("   movel (%1)+,%%d0\n"
614              "21:movesl %%d0,(%0)+\n"
615              "1: movel (%1)+,%%d0\n"
616              "22:movesl %%d0,(%0)+\n"
617              "2:\n"
618              ".section .fixup,\"ax\"\n"
619              "   .even\n"
620              "3: addql #4,%2\n"
621              "4: addql #4,%2\n"
622              "   jra 2b\n"
623              ".previous\n"
624              ".section __ex_table,\"a\"\n"
625              "   .align 4\n"
626              "   .long 21b,3b\n"
627              "   .long 1b,3b\n"
628              "   .long 22b,4b\n"
629              "   .long 2b,4b\n"
630              ".previous"
631              : "=a"(to), "=a"(from), "=d"(n)
632              : "0"(to), "1"(from), "2"(0)
633              : "d0", "memory");
634         break;
635     case 12:
636         __asm__ __volatile__
637             ("   movel (%1)+,%%d0\n"
638              "21:movesl %%d0,(%0)+\n"
639              "1: movel (%1)+,%%d0\n"
640              "22:movesl %%d0,(%0)+\n"
641              "2: movel (%1)+,%%d0\n"
642              "23:movesl %%d0,(%0)+\n"
643              "3:\n"
644              ".section .fixup,\"ax\"\n"
645              "   .even\n"
646              "4: addql #4,%2\n"
647              "5: addql #4,%2\n"
648              "6: addql #4,%2\n"
649              "   jra 3b\n"
650              ".previous\n"
651              ".section __ex_table,\"a\"\n"
652              "   .align 4\n"
653              "   .long 21b,4b\n"
654              "   .long 1b,4b\n"
655              "   .long 22b,5b\n"
656              "   .long 2b,5b\n"
657              "   .long 23b,6b\n"
658              "   .long 3b,6b\n"
659              ".previous"
660              : "=a"(to), "=a"(from), "=d"(n)
661              : "0"(to), "1"(from), "2"(0)
662              : "d0", "memory");
663         break;
664     case 16:
665         __asm__ __volatile__
666             ("   movel (%1)+,%%d0\n"
667              "21:movesl %%d0,(%0)+\n"
668              "1: movel (%1)+,%%d0\n"
669              "22:movesl %%d0,(%0)+\n"
670              "2: movel (%1)+,%%d0\n"
671              "23:movesl %%d0,(%0)+\n"
672              "3: movel (%1)+,%%d0\n"
673              "24:movesl %%d0,(%0)+\n"
674              "4:"
675              ".section .fixup,\"ax\"\n"
676              "   .even\n"
677              "5: addql #4,%2\n"
678              "6: addql #4,%2\n"
679              "7: addql #4,%2\n"
680              "8: addql #4,%2\n"
681              "   jra 4b\n"
682              ".previous\n"
683              ".section __ex_table,\"a\"\n"
684              "   .align 4\n"
685              "   .long 21b,5b\n"
686              "   .long 1b,5b\n"
687              "   .long 22b,6b\n"
688              "   .long 2b,6b\n"
689              "   .long 23b,7b\n"
690              "   .long 3b,7b\n"
691              "   .long 24b,8b\n"
692              "   .long 4b,8b\n"
693              ".previous"
694              : "=a"(to), "=a"(from), "=d"(n)
695              : "0"(to), "1"(from), "2"(0)
696              : "d0", "memory");
697         break;
698     default:
699         switch (n & 3) {
700         case 0:
701             __copy_to_user_big(to, from, n, "", "");
702             break;
703         case 1:
704             __copy_to_user_big(to, from, n,
705                                /* fixup */
706                                "1: addql #1,%2",
707                                /* copy */
708                                "   moveb (%1)+,%%d0\n"
709                                "22:movesb %%d0,(%0)+\n"
710                                "2:"
711                                ".section __ex_table,\"a\"\n"
712                                "   .long 22b,1b\n"
713                                "   .long 2b,1b\n"
714                                ".previous");
715             break;
716         case 2:
717             __copy_to_user_big(to, from, n,
718                                /* fixup */
719                                "1: addql #2,%2",
720                                /* copy */
721                                "   movew (%1)+,%%d0\n"
722                                "22:movesw %%d0,(%0)+\n"
723                                "2:"
724                                ".section __ex_table,\"a\"\n"
725                                "   .long 22b,1b\n"
726                                "   .long 2b,1b\n"
727                                ".previous");
728             break;
729         case 3:
730             __copy_to_user_big(to, from, n,
731                                /* fixup */
732                                "1: addql #2,%2\n"
733                                "2: addql #1,%2",
734                                /* copy */
735                                "   movew (%1)+,%%d0\n"
736                                "23:movesw %%d0,(%0)+\n"
737                                "3: moveb (%1)+,%%d0\n"
738                                "24:movesb %%d0,(%0)+\n"
739                                "4:"
740                                ".section __ex_table,\"a\"\n"
741                                "   .long 23b,1b\n"
742                                "   .long 3b,1b\n"
743                                "   .long 24b,2b\n"
744                                "   .long 4b,2b\n"
745                                ".previous");
746             break;
747         }
748         break;
749     }
750     return n;
751 }
752
753 #define copy_from_user(to, from, n)             \
754 (__builtin_constant_p(n) ?                      \
755  __constant_copy_from_user(to, from, n) :       \
756  __generic_copy_from_user(to, from, n))
757
758 #define copy_to_user(to, from, n)               \
759 (__builtin_constant_p(n) ?                      \
760  __constant_copy_to_user(to, from, n) :         \
761  __generic_copy_to_user(to, from, n))
762
763 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
764 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
765
766 /*
767  * Copy a null terminated string from userspace.
768  */
769
770 static inline long
771 strncpy_from_user(char *dst, const char *src, long count)
772 {
773     long res;
774     if (count == 0) return count;
775     __asm__ __volatile__
776         ("1: movesb (%2)+,%%d0\n"
777          "12:moveb %%d0,(%1)+\n"
778          "   jeq 2f\n"
779          "   subql #1,%3\n"
780          "   jne 1b\n"
781          "2: subl %3,%0\n"
782          "3:\n"
783          ".section .fixup,\"ax\"\n"
784          "   .even\n"
785          "4: movel %4,%0\n"
786          "   jra 3b\n"
787          ".previous\n"
788          ".section __ex_table,\"a\"\n"
789          "   .align 4\n"
790          "   .long 1b,4b\n"
791          "   .long 12b,4b\n"
792          ".previous"
793          : "=d"(res), "=a"(dst), "=a"(src), "=d"(count)
794          : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count)
795          : "d0", "memory");
796     return res;
797 }
798
799 /*
800  * Return the size of a string (including the ending 0)
801  *
802  * Return 0 on exception, a value greater than N if too long
803  */
804 static inline long strnlen_user(const char *src, long n)
805 {
806         long res;
807
808         res = -(long)src;
809         __asm__ __volatile__
810                 ("1:\n"
811                  "   tstl %2\n"
812                  "   jeq 3f\n"
813                  "2: movesb (%1)+,%%d0\n"
814                  "22:\n"
815                  "   subql #1,%2\n"
816                  "   tstb %%d0\n"
817                  "   jne 1b\n"
818                  "   jra 4f\n"
819                  "3:\n"
820                  "   addql #1,%0\n"
821                  "4:\n"
822                  "   addl %1,%0\n"
823                  "5:\n"
824                  ".section .fixup,\"ax\"\n"
825                  "   .even\n"
826                  "6: moveq %3,%0\n"
827                  "   jra 5b\n"
828                  ".previous\n"
829                  ".section __ex_table,\"a\"\n"
830                  "   .align 4\n"
831                  "   .long 2b,6b\n"
832                  "   .long 22b,6b\n"
833                  ".previous"
834                  : "=d"(res), "=a"(src), "=d"(n)
835                  : "i"(0), "0"(res), "1"(src), "2"(n)
836                  : "d0");
837         return res;
838 }
839
840 #define strlen_user(str) strnlen_user(str, 32767)
841
842 /*
843  * Zero Userspace
844  */
845
846 static inline unsigned long
847 clear_user(void *to, unsigned long n)
848 {
849     __asm__ __volatile__
850         ("   tstl %1\n"
851          "   jeq 3f\n"
852          "1: movesl %3,(%0)+\n"
853          "2: subql #1,%1\n"
854          "   jne 1b\n"
855          "3: movel %2,%1\n"
856          "   bclr #1,%1\n"
857          "   jeq 4f\n"
858          "24:movesw %3,(%0)+\n"
859          "4: bclr #0,%1\n"
860          "   jeq 5f\n"
861          "25:movesb %3,(%0)+\n"
862          "5:\n"
863          ".section .fixup,\"ax\"\n"
864          "   .even\n"
865          "61:addql #1,%1\n"
866          "6: lsll #2,%1\n"
867          "   addl %2,%1\n"
868          "   jra 5b\n"
869          "7: addql #2,%1\n"
870          "   jra 5b\n"
871          "8: addql #1,%1\n"
872          "   jra 5b\n"
873          ".previous\n"
874          ".section __ex_table,\"a\"\n"
875          "   .align 4\n"
876          "   .long 1b,61b\n"
877          "   .long 2b,6b\n"
878          "   .long 3b,61b\n"
879          "   .long 24b,7b\n"
880          "   .long 4b,7b\n"
881          "   .long 25b,8b\n"
882          "   .long 5b,8b\n"
883          ".previous"
884          : "=a"(to), "=d"(n)
885          : "r"(n & 3), "r"(0), "0"(to), "1"(n/4));
886     return n;
887 }
888
889 #endif /* _M68K_UACCESS_H */