b1faa46c1d70271d7156d03bad7221f8852f801c
[linux-flexiantxendom0-3.2.10.git] / arch / mips / lib / strnlen_user.S
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (c) 1996, 1998, 1999 by Ralf Baechle
7  * Copyright (c) 1999 Silicon Graphics, Inc.
8  */
9 #include <asm/asm.h>
10 #include <asm/offset.h>
11 #include <asm/regdef.h>
12 #include <asm/sgidefs.h>
13
14 #define EX(insn,reg,addr,handler)                       \
15 9:      insn    reg, addr;                              \
16         .section __ex_table,"a";                        \
17         PTR     9b, handler;                            \
18         .previous
19
20 /*
21  * Return the size of a string (including the ending 0)
22  *
23  * Return 0 for error, len of string but at max a1 otherwise
24  *
25  * Note: for performance reasons we deliberately accept that a user may
26  *       make strlen_user and strnlen_user access the first few KSEG0
27  *       bytes.  There's nothing secret there ...
28  */
29 LEAF(__strnlen_user_asm)
30         lw      v0, TI_ADDR_LIMIT($28)  # pointer ok?
31         and     v0, a0
32         bltz    v0, fault
33
34 FEXPORT(__strnlen_user_nocheck_asm)
35         .type   __strnlen_user_nocheck_asm,@function
36         move    v0, a0
37         addu    a1, a0                  # stop pointer
38         .set    noreorder
39 1:      beq     v0, a1, 1f              # limit reached?
40          addiu  v0, 1
41         .set    reorder
42         EX(lb, t0, -1(v0), fault)
43         bnez    t0, 1b
44 1:      subu    v0, a0
45         jr      ra
46         END(__strnlen_user_asm)
47
48 fault:  move    v0, zero
49         jr      ra