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, 2004 by Ralf Baechle
7  * Copyright (c) 1999 Silicon Graphics, Inc.
8  */
9 #include <linux/export.h>
10 #include <asm/asm.h>
11 #include <asm/asm-offsets.h>
12 #include <asm/regdef.h>
13 
14 #define EX(insn,reg,addr,handler)			\
15 9:	insn	reg, addr;				\
16 	.section __ex_table,"a";			\
17 	PTR_WD	9b, handler;				\
18 	.previous
19 
20 /*
21  * Return the size of a string including the ending NUL character up to a
22  * maximum of a1 or 0 in case of error.
23  *
24  * Note: for performance reasons we deliberately accept that a user may
25  *	 make strlen_user and strnlen_user access the first few KSEG0
26  *	 bytes.	 There's nothing secret there.	On 64-bit accessing beyond
27  *	 the maximum is a tad hairier ...
28  */
29 LEAF(__strnlen_user_asm)
30 	move		v0, a0
31 	PTR_ADDU	a1, a0			# stop pointer
32 1:
33 #ifdef CONFIG_CPU_DADDI_WORKAROUNDS
34 	.set		noat
35 	li		AT, 1
36 #endif
37 	beq		v0, a1, 1f		# limit reached?
38 #ifdef CONFIG_EVA
39 	.set push
40 	.set eva
41 	EX(lbe, t0, (v0), .Lfault)
42 	.set pop
43 #else
44 	EX(lb, t0, (v0), .Lfault)
45 #endif
46 	.set		noreorder
47 	bnez		t0, 1b
48 1:
49 #ifndef CONFIG_CPU_DADDI_WORKAROUNDS
50 	 PTR_ADDIU	v0, 1
51 #else
52 	 PTR_ADDU	v0, AT
53 	.set		at
54 #endif
55 	.set		reorder
56 	PTR_SUBU	v0, a0
57 	jr		ra
58 	END(__strnlen_user_asm)
59 
60 .Lfault:
61 	move		v0, zero
62 	jr		ra
63 
64 	EXPORT_SYMBOL(__strnlen_user_asm)
65