License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-block.git] / arch / cris / include / arch-v32 / arch / uaccess.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
51533b61
MS
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 */
d9b5444e 97static inline long
51533b61
MS
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"
da2af0a7 126 "1: beq 6f\n"
51533b61
MS
127 " move.b $acr,[%1+]\n"
128
129 " subq 1,%0\n"
130 "2: bne 1b\n"
131 " move.b [%2+],$acr\n"
132
da2af0a7 133 "6: sub.d %3,%0\n"
51533b61
MS
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
da2af0a7 144 its delay-slot. Just so you don't get confused... */
51533b61
MS
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" \
de09be34 182 " jump 1b\n", \
51533b61
MS
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" \
de09be34 192 " jump 1b\n", \
51533b61
MS
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", \
de09be34 203 "5: addq 1,%2\n", \
51533b61
MS
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" \
de09be34 213 " jump 1b\n", \
51533b61
MS
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", \
c8313947 224 "5: addq 1,%2\n", \
51533b61
MS
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 \
c8313947 233 "5: addq 2,%2\n", \
51533b61
MS
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", \
c8313947 244 "7: addq 1,%2\n", \
51533b61
MS
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 \
c8313947 253 "5: addq 4,%2\n", \
51533b61
MS
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", \
c8313947 264 "7: addq 1,%2\n", \
51533b61
MS
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 \
c8313947 273 "7: addq 2,%2\n", \
51533b61
MS
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", \
c8313947 284 "9: addq 1,%2\n", \
51533b61
MS
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 \
c8313947 293 "7: addq 4,%2\n", \
51533b61
MS
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", \
c8313947 304 "9: addq 1,%2\n", \
51533b61
MS
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 \
c8313947 313 "9: addq 2,%2\n", \
51533b61
MS
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", \
c8313947 324 "11: addq 1,%2\n", \
51533b61
MS
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 \
c8313947 333 "9: addq 4,%2\n", \
51533b61
MS
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 \
c8313947 346 "11: addq 4,%2\n", \
51533b61
MS
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 \
c8313947 359 "13: addq 4,%2\n", \
51533b61
MS
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
d9b5444e 680static inline long
51533b61
MS
681strnlen_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