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