Kyle Swenson | 8d8f654 | 2021-03-15 11:02:55 -0600 | [diff] [blame^] | 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), "=&d" (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 8b\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), "=&d" (tmp) |
| 100 | : "0" (n / 4), "d" (n & 3)); |
| 101 | |
| 102 | return res; |
| 103 | } |
| 104 | EXPORT_SYMBOL(__generic_copy_to_user); |
| 105 | |
| 106 | /* |
| 107 | * Zero Userspace |
| 108 | */ |
| 109 | |
| 110 | unsigned long __clear_user(void __user *to, unsigned long n) |
| 111 | { |
| 112 | unsigned long res; |
| 113 | |
| 114 | asm volatile ("\n" |
| 115 | " tst.l %0\n" |
| 116 | " jeq 3f\n" |
| 117 | "1: "MOVES".l %2,(%1)+\n" |
| 118 | "2: subq.l #1,%0\n" |
| 119 | " jne 1b\n" |
| 120 | "3: btst #1,%4\n" |
| 121 | " jeq 5f\n" |
| 122 | "4: "MOVES".w %2,(%1)+\n" |
| 123 | "5: btst #0,%4\n" |
| 124 | " jeq 7f\n" |
| 125 | "6: "MOVES".b %2,(%1)\n" |
| 126 | "7:\n" |
| 127 | " .section .fixup,\"ax\"\n" |
| 128 | " .even\n" |
| 129 | "10: lsl.l #2,%0\n" |
| 130 | "40: add.l %4,%0\n" |
| 131 | " jra 7b\n" |
| 132 | " .previous\n" |
| 133 | "\n" |
| 134 | " .section __ex_table,\"a\"\n" |
| 135 | " .align 4\n" |
| 136 | " .long 1b,10b\n" |
| 137 | " .long 2b,10b\n" |
| 138 | " .long 4b,40b\n" |
| 139 | " .long 5b,40b\n" |
| 140 | " .long 6b,40b\n" |
| 141 | " .long 7b,40b\n" |
| 142 | " .previous" |
| 143 | : "=d" (res), "+a" (to) |
| 144 | : "d" (0), "0" (n / 4), "d" (n & 3)); |
| 145 | |
| 146 | return res; |
| 147 | } |
| 148 | EXPORT_SYMBOL(__clear_user); |