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