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