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