Merge tag 'rtc-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
[sfrench/cifs-2.6.git] / arch / cris / include / arch-v32 / arch / uaccess.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Authors:    Hans-Peter Nilsson (hp@axis.com)
4  *
5  */
6 #ifndef _CRIS_ARCH_UACCESS_H
7 #define _CRIS_ARCH_UACCESS_H
8
9 /*
10  * We don't tell gcc that we are accessing memory, but this is OK
11  * because we do not write to any memory gcc knows about, so there
12  * are no aliasing issues.
13  *
14  * Note that PC at a fault is the address *at* the faulting
15  * instruction for CRISv32.
16  */
17 #define __put_user_asm(x, addr, err, op)                        \
18         __asm__ __volatile__(                                   \
19                 "2:     "op" %1,[%2]\n"                         \
20                 "4:\n"                                          \
21                 "       .section .fixup,\"ax\"\n"               \
22                 "3:     move.d %3,%0\n"                         \
23                 "       jump 4b\n"                              \
24                 "       nop\n"                                  \
25                 "       .previous\n"                            \
26                 "       .section __ex_table,\"a\"\n"            \
27                 "       .dword 2b,3b\n"                         \
28                 "       .previous\n"                            \
29                 : "=r" (err)                                    \
30                 : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
31
32 #define __put_user_asm_64(x, addr, err) do {                    \
33         int dummy_for_put_user_asm_64_;                         \
34         __asm__ __volatile__(                                   \
35                 "2:     move.d %M2,[%1+]\n"                     \
36                 "4:     move.d %H2,[%1]\n"                      \
37                 "5:\n"                                          \
38                 "       .section .fixup,\"ax\"\n"               \
39                 "3:     move.d %4,%0\n"                         \
40                 "       jump 5b\n"                              \
41                 "       .previous\n"                            \
42                 "       .section __ex_table,\"a\"\n"            \
43                 "       .dword 2b,3b\n"                         \
44                 "       .dword 4b,3b\n"                         \
45                 "       .previous\n"                            \
46                 : "=r" (err), "=b" (dummy_for_put_user_asm_64_) \
47                 : "r" (x), "1" (addr), "g" (-EFAULT),           \
48                   "0" (err));                                   \
49         } while (0)
50
51 /* See comment before __put_user_asm.  */
52
53 #define __get_user_asm(x, addr, err, op)                \
54         __asm__ __volatile__(                           \
55                 "2:     "op" [%2],%1\n"                 \
56                 "4:\n"                                  \
57                 "       .section .fixup,\"ax\"\n"       \
58                 "3:     move.d %3,%0\n"                 \
59                 "       jump 4b\n"                      \
60                 "       moveq 0,%1\n"                   \
61                 "       .previous\n"                    \
62                 "       .section __ex_table,\"a\"\n"    \
63                 "       .dword 2b,3b\n"                 \
64                 "       .previous\n"                    \
65                 : "=r" (err), "=r" (x)                  \
66                 : "r" (addr), "g" (-EFAULT), "0" (err))
67
68 #define __get_user_asm_64(x, addr, err) do {            \
69         int dummy_for_get_user_asm_64_;                 \
70         __asm__ __volatile__(                           \
71                 "2:     move.d [%2+],%M1\n"             \
72                 "4:     move.d [%2],%H1\n"              \
73                 "5:\n"                                  \
74                 "       .section .fixup,\"ax\"\n"       \
75                 "3:     move.d %4,%0\n"                 \
76                 "       jump 5b\n"                      \
77                 "       moveq 0,%1\n"                   \
78                 "       .previous\n"                    \
79                 "       .section __ex_table,\"a\"\n"    \
80                 "       .dword 2b,3b\n"                 \
81                 "       .dword 4b,3b\n"                 \
82                 "       .previous\n"                    \
83                 : "=r" (err), "=r" (x),                 \
84                   "=b" (dummy_for_get_user_asm_64_)     \
85                 : "2" (addr), "g" (-EFAULT), "0" (err));\
86         } while (0)
87
88 /*
89  * Copy a null terminated string from userspace.
90  *
91  * Must return:
92  * -EFAULT              for an exception
93  * count                if we hit the buffer limit
94  * bytes copied         if we hit a null byte
95  * (without the null byte)
96  */
97 static inline long
98 __do_strncpy_from_user(char *dst, const char *src, long count)
99 {
100         long res;
101
102         if (count == 0)
103                 return 0;
104
105         /*
106          * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
107          *  So do we.
108          *
109          *  This code is deduced from:
110          *
111          *      char tmp2;
112          *      long tmp1, tmp3;
113          *      tmp1 = count;
114          *      while ((*dst++ = (tmp2 = *src++)) != 0
115          *             && --tmp1)
116          *        ;
117          *
118          *      res = count - tmp1;
119          *
120          *  with tweaks.
121          */
122
123         __asm__ __volatile__ (
124                 "       move.d %3,%0\n"
125                 "5:     move.b [%2+],$acr\n"
126                 "1:     beq 6f\n"
127                 "       move.b $acr,[%1+]\n"
128
129                 "       subq 1,%0\n"
130                 "2:     bne 1b\n"
131                 "       move.b [%2+],$acr\n"
132
133                 "6:     sub.d %3,%0\n"
134                 "       neg.d %0,%0\n"
135                 "3:\n"
136                 "       .section .fixup,\"ax\"\n"
137                 "4:     move.d %7,%0\n"
138                 "       jump 3b\n"
139                 "       nop\n"
140
141                 /* The address for a fault at the first move is trivial.
142                    The address for a fault at the second move is that of
143                    the preceding branch insn, since the move insn is in
144                    its delay-slot.  Just so you don't get confused...  */
145                 "       .previous\n"
146                 "       .section __ex_table,\"a\"\n"
147                 "       .dword 5b,4b\n"
148                 "       .dword 2b,4b\n"
149                 "       .previous"
150                 : "=r" (res), "=b" (dst), "=b" (src), "=r" (count)
151                 : "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
152                 : "acr");
153
154         return res;
155 }
156
157 /* A few copy asms to build up the more complex ones from.
158
159    Note again, a post-increment is performed regardless of whether a bus
160    fault occurred in that instruction, and PC for a faulted insn is the
161    address for the insn, or for the preceding branch when in a delay-slot.  */
162
163 #define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
164         __asm__ __volatile__ (                          \
165                         COPY                            \
166                 "1:\n"                                  \
167                 "       .section .fixup,\"ax\"\n"       \
168                         FIXUP                           \
169                 "       .previous\n"                    \
170                 "       .section __ex_table,\"a\"\n"    \
171                         TENTRY                          \
172                 "       .previous\n"                    \
173                 : "=b" (to), "=b" (from), "=r" (ret)    \
174                 : "0" (to), "1" (from), "2" (ret)       \
175                 : "acr", "memory")
176
177 #define __asm_copy_from_user_1(to, from, ret) \
178         __asm_copy_user_cont(to, from, ret,     \
179                 "2:     move.b [%1+],$acr\n"    \
180                 "       move.b $acr,[%0+]\n",   \
181                 "3:     addq 1,%2\n"            \
182                 "       jump 1b\n",             \
183                 "       .dword 2b,3b\n")
184
185 #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
186         __asm_copy_user_cont(to, from, ret,             \
187                         COPY                            \
188                 "2:     move.w [%1+],$acr\n"            \
189                 "       move.w $acr,[%0+]\n",           \
190                         FIXUP                           \
191                 "3:     addq 2,%2\n"                    \
192                 "       jump 1b\n",                     \
193                         TENTRY                          \
194                 "       .dword 2b,3b\n")
195
196 #define __asm_copy_from_user_2(to, from, ret) \
197         __asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
198
199 #define __asm_copy_from_user_3(to, from, ret)           \
200         __asm_copy_from_user_2x_cont(to, from, ret,     \
201                 "4:     move.b [%1+],$acr\n"            \
202                 "       move.b $acr,[%0+]\n",           \
203                 "5:     addq 1,%2\n",                   \
204                 "       .dword 4b,5b\n")
205
206 #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
207         __asm_copy_user_cont(to, from, ret,             \
208                         COPY                            \
209                 "2:     move.d [%1+],$acr\n"            \
210                 "       move.d $acr,[%0+]\n",           \
211                         FIXUP                           \
212                 "3:     addq 4,%2\n"                    \
213                 "       jump 1b\n",                     \
214                         TENTRY                          \
215                 "       .dword 2b,3b\n")
216
217 #define __asm_copy_from_user_4(to, from, ret) \
218         __asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
219
220 #define __asm_copy_from_user_5(to, from, ret) \
221         __asm_copy_from_user_4x_cont(to, from, ret,     \
222                 "4:     move.b [%1+],$acr\n"            \
223                 "       move.b $acr,[%0+]\n",           \
224                 "5:     addq 1,%2\n",                   \
225                 "       .dword 4b,5b\n")
226
227 #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
228         __asm_copy_from_user_4x_cont(to, from, ret,     \
229                         COPY                            \
230                 "4:     move.w [%1+],$acr\n"            \
231                 "       move.w $acr,[%0+]\n",           \
232                         FIXUP                           \
233                 "5:     addq 2,%2\n",                   \
234                         TENTRY                          \
235                 "       .dword 4b,5b\n")
236
237 #define __asm_copy_from_user_6(to, from, ret) \
238         __asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
239
240 #define __asm_copy_from_user_7(to, from, ret) \
241         __asm_copy_from_user_6x_cont(to, from, ret,     \
242                 "6:     move.b [%1+],$acr\n"            \
243                 "       move.b $acr,[%0+]\n",           \
244                 "7:     addq 1,%2\n",                   \
245                 "       .dword 6b,7b\n")
246
247 #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
248         __asm_copy_from_user_4x_cont(to, from, ret,     \
249                         COPY                            \
250                 "4:     move.d [%1+],$acr\n"            \
251                 "       move.d $acr,[%0+]\n",           \
252                         FIXUP                           \
253                 "5:     addq 4,%2\n",                   \
254                         TENTRY                          \
255                 "       .dword 4b,5b\n")
256
257 #define __asm_copy_from_user_8(to, from, ret) \
258         __asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
259
260 #define __asm_copy_from_user_9(to, from, ret) \
261         __asm_copy_from_user_8x_cont(to, from, ret,     \
262                 "6:     move.b [%1+],$acr\n"            \
263                 "       move.b $acr,[%0+]\n",           \
264                 "7:     addq 1,%2\n",                   \
265                 "       .dword 6b,7b\n")
266
267 #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
268         __asm_copy_from_user_8x_cont(to, from, ret,     \
269                         COPY                            \
270                 "6:     move.w [%1+],$acr\n"            \
271                 "       move.w $acr,[%0+]\n",           \
272                         FIXUP                           \
273                 "7:     addq 2,%2\n",                   \
274                         TENTRY                          \
275                 "       .dword 6b,7b\n")
276
277 #define __asm_copy_from_user_10(to, from, ret) \
278         __asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
279
280 #define __asm_copy_from_user_11(to, from, ret)          \
281         __asm_copy_from_user_10x_cont(to, from, ret,    \
282                 "8:     move.b [%1+],$acr\n"            \
283                 "       move.b $acr,[%0+]\n",           \
284                 "9:     addq 1,%2\n",                   \
285                 "       .dword 8b,9b\n")
286
287 #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
288         __asm_copy_from_user_8x_cont(to, from, ret,     \
289                         COPY                            \
290                 "6:     move.d [%1+],$acr\n"            \
291                 "       move.d $acr,[%0+]\n",           \
292                         FIXUP                           \
293                 "7:     addq 4,%2\n",                   \
294                         TENTRY                          \
295                 "       .dword 6b,7b\n")
296
297 #define __asm_copy_from_user_12(to, from, ret) \
298         __asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
299
300 #define __asm_copy_from_user_13(to, from, ret) \
301         __asm_copy_from_user_12x_cont(to, from, ret,    \
302                 "8:     move.b [%1+],$acr\n"            \
303                 "       move.b $acr,[%0+]\n",           \
304                 "9:     addq 1,%2\n",                   \
305                 "       .dword 8b,9b\n")
306
307 #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
308         __asm_copy_from_user_12x_cont(to, from, ret,    \
309                         COPY                            \
310                 "8:     move.w [%1+],$acr\n"            \
311                 "       move.w $acr,[%0+]\n",           \
312                         FIXUP                           \
313                 "9:     addq 2,%2\n",                   \
314                         TENTRY                          \
315                 "       .dword 8b,9b\n")
316
317 #define __asm_copy_from_user_14(to, from, ret) \
318         __asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
319
320 #define __asm_copy_from_user_15(to, from, ret) \
321         __asm_copy_from_user_14x_cont(to, from, ret,    \
322                 "10:    move.b [%1+],$acr\n"            \
323                 "       move.b $acr,[%0+]\n",           \
324                 "11:    addq 1,%2\n",                   \
325                 "       .dword 10b,11b\n")
326
327 #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
328         __asm_copy_from_user_12x_cont(to, from, ret,    \
329                         COPY                            \
330                 "8:     move.d [%1+],$acr\n"            \
331                 "       move.d $acr,[%0+]\n",           \
332                         FIXUP                           \
333                 "9:     addq 4,%2\n",                   \
334                         TENTRY                          \
335                 "       .dword 8b,9b\n")
336
337 #define __asm_copy_from_user_16(to, from, ret) \
338         __asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
339
340 #define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
341         __asm_copy_from_user_16x_cont(to, from, ret,    \
342                         COPY                            \
343                 "10:    move.d [%1+],$acr\n"            \
344                 "       move.d $acr,[%0+]\n",           \
345                         FIXUP                           \
346                 "11:    addq 4,%2\n",                   \
347                         TENTRY                          \
348                 "       .dword 10b,11b\n")
349
350 #define __asm_copy_from_user_20(to, from, ret) \
351         __asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
352
353 #define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
354         __asm_copy_from_user_20x_cont(to, from, ret,    \
355                         COPY                            \
356                 "12:    move.d [%1+],$acr\n"            \
357                 "       move.d $acr,[%0+]\n",           \
358                         FIXUP                           \
359                 "13:    addq 4,%2\n",                   \
360                         TENTRY                          \
361                 "       .dword 12b,13b\n")
362
363 #define __asm_copy_from_user_24(to, from, ret) \
364         __asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
365
366 /* And now, the to-user ones.  */
367
368 #define __asm_copy_to_user_1(to, from, ret)     \
369         __asm_copy_user_cont(to, from, ret,     \
370                 "       move.b [%1+],$acr\n"    \
371                 "2:     move.b $acr,[%0+]\n",   \
372                 "3:     jump 1b\n"              \
373                 "       addq 1,%2\n",           \
374                 "       .dword 2b,3b\n")
375
376 #define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
377         __asm_copy_user_cont(to, from, ret,             \
378                         COPY                            \
379                 "       move.w [%1+],$acr\n"            \
380                 "2:     move.w $acr,[%0+]\n",           \
381                         FIXUP                           \
382                 "3:     jump 1b\n"                      \
383                 "       addq 2,%2\n",                   \
384                         TENTRY                          \
385                 "       .dword 2b,3b\n")
386
387 #define __asm_copy_to_user_2(to, from, ret) \
388         __asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
389
390 #define __asm_copy_to_user_3(to, from, ret) \
391         __asm_copy_to_user_2x_cont(to, from, ret,       \
392                 "       move.b [%1+],$acr\n"            \
393                 "4:     move.b $acr,[%0+]\n",           \
394                 "5:     addq 1,%2\n",                   \
395                 "       .dword 4b,5b\n")
396
397 #define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
398         __asm_copy_user_cont(to, from, ret,             \
399                         COPY                            \
400                 "       move.d [%1+],$acr\n"            \
401                 "2:     move.d $acr,[%0+]\n",           \
402                         FIXUP                           \
403                 "3:     jump 1b\n"                      \
404                 "       addq 4,%2\n",                   \
405                         TENTRY                          \
406                 "       .dword 2b,3b\n")
407
408 #define __asm_copy_to_user_4(to, from, ret) \
409         __asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
410
411 #define __asm_copy_to_user_5(to, from, ret) \
412         __asm_copy_to_user_4x_cont(to, from, ret,       \
413                 "       move.b [%1+],$acr\n"            \
414                 "4:     move.b $acr,[%0+]\n",           \
415                 "5:     addq 1,%2\n",                   \
416                 "       .dword 4b,5b\n")
417
418 #define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
419         __asm_copy_to_user_4x_cont(to, from, ret,       \
420                         COPY                            \
421                 "       move.w [%1+],$acr\n"            \
422                 "4:     move.w $acr,[%0+]\n",           \
423                         FIXUP                           \
424                 "5:     addq 2,%2\n",                   \
425                         TENTRY                          \
426                 "       .dword 4b,5b\n")
427
428 #define __asm_copy_to_user_6(to, from, ret) \
429         __asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
430
431 #define __asm_copy_to_user_7(to, from, ret) \
432         __asm_copy_to_user_6x_cont(to, from, ret,       \
433                 "       move.b [%1+],$acr\n"            \
434                 "6:     move.b $acr,[%0+]\n",           \
435                 "7:     addq 1,%2\n",                   \
436                 "       .dword 6b,7b\n")
437
438 #define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
439         __asm_copy_to_user_4x_cont(to, from, ret,       \
440                         COPY                            \
441                 "       move.d [%1+],$acr\n"            \
442                 "4:     move.d $acr,[%0+]\n",           \
443                         FIXUP                           \
444                 "5:     addq 4,%2\n",                   \
445                         TENTRY                          \
446                 "       .dword 4b,5b\n")
447
448 #define __asm_copy_to_user_8(to, from, ret) \
449         __asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
450
451 #define __asm_copy_to_user_9(to, from, ret) \
452         __asm_copy_to_user_8x_cont(to, from, ret,       \
453                 "       move.b [%1+],$acr\n"            \
454                 "6:     move.b $acr,[%0+]\n",           \
455                 "7:     addq 1,%2\n",                   \
456                 "       .dword 6b,7b\n")
457
458 #define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
459         __asm_copy_to_user_8x_cont(to, from, ret,       \
460                         COPY                            \
461                 "       move.w [%1+],$acr\n"            \
462                 "6:     move.w $acr,[%0+]\n",           \
463                         FIXUP                           \
464                 "7:     addq 2,%2\n",                   \
465                         TENTRY                          \
466                 "       .dword 6b,7b\n")
467
468 #define __asm_copy_to_user_10(to, from, ret) \
469         __asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
470
471 #define __asm_copy_to_user_11(to, from, ret) \
472         __asm_copy_to_user_10x_cont(to, from, ret,      \
473                 "       move.b [%1+],$acr\n"            \
474                 "8:     move.b $acr,[%0+]\n",           \
475                 "9:     addq 1,%2\n",                   \
476                 "       .dword 8b,9b\n")
477
478 #define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
479         __asm_copy_to_user_8x_cont(to, from, ret,       \
480                         COPY                            \
481                 "       move.d [%1+],$acr\n"            \
482                 "6:     move.d $acr,[%0+]\n",           \
483                         FIXUP                           \
484                 "7:     addq 4,%2\n",                   \
485                         TENTRY                          \
486                 "       .dword 6b,7b\n")
487
488 #define __asm_copy_to_user_12(to, from, ret) \
489         __asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
490
491 #define __asm_copy_to_user_13(to, from, ret) \
492         __asm_copy_to_user_12x_cont(to, from, ret,      \
493                 "       move.b [%1+],$acr\n"            \
494                 "8:     move.b $acr,[%0+]\n",           \
495                 "9:     addq 1,%2\n",                   \
496                 "       .dword 8b,9b\n")
497
498 #define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
499         __asm_copy_to_user_12x_cont(to, from, ret,      \
500                         COPY                            \
501                 "       move.w [%1+],$acr\n"            \
502                 "8:     move.w $acr,[%0+]\n",           \
503                         FIXUP                           \
504                 "9:     addq 2,%2\n",                   \
505                         TENTRY                          \
506                 "       .dword 8b,9b\n")
507
508 #define __asm_copy_to_user_14(to, from, ret)    \
509         __asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
510
511 #define __asm_copy_to_user_15(to, from, ret) \
512         __asm_copy_to_user_14x_cont(to, from, ret,      \
513                 "       move.b [%1+],$acr\n"            \
514                 "10:    move.b $acr,[%0+]\n",           \
515                 "11:    addq 1,%2\n",                   \
516                 "       .dword 10b,11b\n")
517
518 #define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
519         __asm_copy_to_user_12x_cont(to, from, ret,      \
520                         COPY                            \
521                 "       move.d [%1+],$acr\n"            \
522                 "8:     move.d $acr,[%0+]\n",           \
523                         FIXUP                           \
524                 "9:     addq 4,%2\n",                   \
525                         TENTRY                          \
526                 "       .dword 8b,9b\n")
527
528 #define __asm_copy_to_user_16(to, from, ret) \
529         __asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
530
531 #define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
532         __asm_copy_to_user_16x_cont(to, from, ret,      \
533                         COPY                            \
534                 "       move.d [%1+],$acr\n"            \
535                 "10:    move.d $acr,[%0+]\n",           \
536                         FIXUP                           \
537                 "11:    addq 4,%2\n",                   \
538                         TENTRY                          \
539                 "       .dword 10b,11b\n")
540
541 #define __asm_copy_to_user_20(to, from, ret) \
542         __asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
543
544 #define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
545         __asm_copy_to_user_20x_cont(to, from, ret,      \
546                         COPY                            \
547                 "       move.d [%1+],$acr\n"            \
548                 "12:    move.d $acr,[%0+]\n",           \
549                         FIXUP                           \
550                 "13:    addq 4,%2\n",                   \
551                         TENTRY                          \
552                 "       .dword 12b,13b\n")
553
554 #define __asm_copy_to_user_24(to, from, ret)    \
555         __asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
556
557 /* Define a few clearing asms with exception handlers.  */
558
559 /* This frame-asm is like the __asm_copy_user_cont one, but has one less
560    input.  */
561
562 #define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
563         __asm__ __volatile__ (                          \
564                         CLEAR                           \
565                 "1:\n"                                  \
566                 "       .section .fixup,\"ax\"\n"       \
567                         FIXUP                           \
568                 "       .previous\n"                    \
569                 "       .section __ex_table,\"a\"\n"    \
570                         TENTRY                          \
571                 "       .previous"                      \
572                 : "=b" (to), "=r" (ret)                 \
573                 : "0" (to), "1" (ret)                   \
574                 : "memory")
575
576 #define __asm_clear_1(to, ret) \
577         __asm_clear(to, ret,                    \
578                 "2:     clear.b [%0+]\n",       \
579                 "3:     jump 1b\n"              \
580                 "       addq 1,%1\n",           \
581                 "       .dword 2b,3b\n")
582
583 #define __asm_clear_2(to, ret) \
584         __asm_clear(to, ret,                    \
585                 "2:     clear.w [%0+]\n",       \
586                 "3:     jump 1b\n"              \
587                 "       addq 2,%1\n",           \
588                 "       .dword 2b,3b\n")
589
590 #define __asm_clear_3(to, ret) \
591      __asm_clear(to, ret,                       \
592                  "2:    clear.w [%0+]\n"        \
593                  "3:    clear.b [%0+]\n",       \
594                  "4:    addq 2,%1\n"            \
595                  "5:    jump 1b\n"              \
596                  "      addq 1,%1\n",           \
597                  "      .dword 2b,4b\n"         \
598                  "      .dword 3b,5b\n")
599
600 #define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
601         __asm_clear(to, ret,                            \
602                         CLEAR                           \
603                 "2:     clear.d [%0+]\n",               \
604                         FIXUP                           \
605                 "3:     jump 1b\n"                      \
606                 "       addq 4,%1\n",                   \
607                         TENTRY                          \
608                 "       .dword 2b,3b\n")
609
610 #define __asm_clear_4(to, ret) \
611         __asm_clear_4x_cont(to, ret, "", "", "")
612
613 #define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
614         __asm_clear_4x_cont(to, ret,                    \
615                         CLEAR                           \
616                 "4:     clear.d [%0+]\n",               \
617                         FIXUP                           \
618                 "5:     addq 4,%1\n",                   \
619                         TENTRY                          \
620                 "       .dword 4b,5b\n")
621
622 #define __asm_clear_8(to, ret) \
623         __asm_clear_8x_cont(to, ret, "", "", "")
624
625 #define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
626         __asm_clear_8x_cont(to, ret,                    \
627                         CLEAR                           \
628                 "6:     clear.d [%0+]\n",               \
629                         FIXUP                           \
630                 "7:     addq 4,%1\n",                   \
631                         TENTRY                          \
632                 "       .dword 6b,7b\n")
633
634 #define __asm_clear_12(to, ret) \
635         __asm_clear_12x_cont(to, ret, "", "", "")
636
637 #define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
638         __asm_clear_12x_cont(to, ret,                   \
639                         CLEAR                           \
640                 "8:     clear.d [%0+]\n",               \
641                         FIXUP                           \
642                 "9:     addq 4,%1\n",                   \
643                         TENTRY                          \
644                 "       .dword 8b,9b\n")
645
646 #define __asm_clear_16(to, ret) \
647         __asm_clear_16x_cont(to, ret, "", "", "")
648
649 #define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
650         __asm_clear_16x_cont(to, ret,                   \
651                         CLEAR                           \
652                 "10:    clear.d [%0+]\n",               \
653                         FIXUP                           \
654                 "11:    addq 4,%1\n",                   \
655                         TENTRY                          \
656                 "       .dword 10b,11b\n")
657
658 #define __asm_clear_20(to, ret) \
659         __asm_clear_20x_cont(to, ret, "", "", "")
660
661 #define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
662         __asm_clear_20x_cont(to, ret,                   \
663                         CLEAR                           \
664                 "12:    clear.d [%0+]\n",               \
665                         FIXUP                           \
666                 "13:    addq 4,%1\n",                   \
667                         TENTRY                          \
668                 "       .dword 12b,13b\n")
669
670 #define __asm_clear_24(to, ret) \
671         __asm_clear_24x_cont(to, ret, "", "", "")
672
673 /*
674  * Return the size of a string (including the ending 0)
675  *
676  * Return length of string in userspace including terminating 0
677  * or 0 for error.  Return a value greater than N if too long.
678  */
679
680 static inline long
681 strnlen_user(const char *s, long n)
682 {
683         long res, tmp1;
684
685         if (!access_ok(VERIFY_READ, s, 0))
686                 return 0;
687
688         /*
689          * This code is deduced from:
690          *
691          *      tmp1 = n;
692          *      while (tmp1-- > 0 && *s++)
693          *        ;
694          *
695          *      res = n - tmp1;
696          *
697          *  (with tweaks).
698          */
699
700         __asm__ __volatile__ (
701                 "       move.d %1,$acr\n"
702                 "       cmpq 0,$acr\n"
703                 "0:\n"
704                 "       ble 1f\n"
705                 "       subq 1,$acr\n"
706
707                 "4:     test.b [%0+]\n"
708                 "       bne 0b\n"
709                 "       cmpq 0,$acr\n"
710                 "1:\n"
711                 "       move.d %1,%0\n"
712                 "       sub.d $acr,%0\n"
713                 "2:\n"
714                 "       .section .fixup,\"ax\"\n"
715
716                 "3:     jump 2b\n"
717                 "       clear.d %0\n"
718
719                 "       .previous\n"
720                 "       .section __ex_table,\"a\"\n"
721                 "       .dword 4b,3b\n"
722                 "       .previous\n"
723                 : "=r" (res), "=r" (tmp1)
724                 : "0" (s), "1" (n)
725                 : "acr");
726
727         return res;
728 }
729
730 #endif