blob: 65b02d9b605af168fa619463e43b9ab0636aee76 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Authors: Bjorn Wesen (bjornw@axis.com)
3 * 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 *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 */
Adrian Bunkd9b54442005-11-07 00:58:44 -080090static inline long
Linus Torvalds1da177e2005-04-16 15:20:36 -070091__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
Adrian Bunkd9b54442005-11-07 00:58:44 -0800605static inline long
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606strnlen_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