Merge with Linux 2.5.59.
[linux-2.6/linux-mips.git] / include / asm-m68k / uaccess.h
blobdfbb1e9e9abb7cc59a009c26c5fd401fba85b0eb
1 #ifndef __M68K_UACCESS_H
2 #define __M68K_UACCESS_H
4 /*
5 * User space memory access functions
6 */
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <asm/segment.h>
11 #define VERIFY_READ 0
12 #define VERIFY_WRITE 1
14 /* We let the MMU do all checking */
15 #define access_ok(type,addr,size) 1
17 extern inline int verify_area(int type, const void * addr, unsigned long size)
19 return access_ok(type,addr,size)?0:-EFAULT;
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.
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.
35 struct exception_table_entry
37 unsigned long insn, fixup;
42 * These are the main single-value transfer routines. They automatically
43 * use the right size if we just have the right pointer type.
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; \
69 #define __put_user(x, ptr) put_user(x, ptr)
71 extern int __put_user_bad(void);
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.
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))
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; \
117 (x) = __gu_val; \
118 __gu_err; \
120 #define __get_user(x, ptr) get_user(x, ptr)
122 extern int __get_user_bad(void);
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))
141 static inline unsigned long
142 __generic_copy_from_user(void *to, const void *from, unsigned long n)
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;
196 static inline unsigned long
197 __generic_copy_to_user(void *to, const void *from, unsigned long n)
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;
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")
271 static inline unsigned long
272 __constant_copy_from_user(void *to, const void *from, unsigned long n)
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;
492 break;
494 return n;
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")
524 static inline unsigned long
525 __constant_copy_to_user(void *to, const void *from, unsigned long n)
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;
748 break;
750 return n;
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))
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))
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)
767 * Copy a null terminated string from userspace.
770 static inline long
771 strncpy_from_user(char *dst, const char *src, long count)
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;
800 * Return the size of a string (including the ending 0)
802 * Return 0 on exception, a value greater than N if too long
804 static inline long strnlen_user(const char *src, long n)
806 long res;
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;
840 #define strlen_user(str) strnlen_user(str, 32767)
843 * Zero Userspace
846 static inline unsigned long
847 clear_user(void *to, unsigned long n)
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;
889 #endif /* _M68K_UACCESS_H */