162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
362306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
462306a36Sopenharmony_ci * for more details.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (c) 1996, 1998, 1999, 2004 by Ralf Baechle
762306a36Sopenharmony_ci * Copyright (c) 1999 Silicon Graphics, Inc.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#include <linux/export.h>
1062306a36Sopenharmony_ci#include <asm/asm.h>
1162306a36Sopenharmony_ci#include <asm/asm-offsets.h>
1262306a36Sopenharmony_ci#include <asm/regdef.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define EX(insn,reg,addr,handler)			\
1562306a36Sopenharmony_ci9:	insn	reg, addr;				\
1662306a36Sopenharmony_ci	.section __ex_table,"a";			\
1762306a36Sopenharmony_ci	PTR_WD	9b, handler;				\
1862306a36Sopenharmony_ci	.previous
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * Return the size of a string including the ending NUL character up to a
2262306a36Sopenharmony_ci * maximum of a1 or 0 in case of error.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Note: for performance reasons we deliberately accept that a user may
2562306a36Sopenharmony_ci *	 make strlen_user and strnlen_user access the first few KSEG0
2662306a36Sopenharmony_ci *	 bytes.	 There's nothing secret there.	On 64-bit accessing beyond
2762306a36Sopenharmony_ci *	 the maximum is a tad hairier ...
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_ciLEAF(__strnlen_user_asm)
3062306a36Sopenharmony_ci	move		v0, a0
3162306a36Sopenharmony_ci	PTR_ADDU	a1, a0			# stop pointer
3262306a36Sopenharmony_ci1:
3362306a36Sopenharmony_ci#ifdef CONFIG_CPU_DADDI_WORKAROUNDS
3462306a36Sopenharmony_ci	.set		noat
3562306a36Sopenharmony_ci	li		AT, 1
3662306a36Sopenharmony_ci#endif
3762306a36Sopenharmony_ci	beq		v0, a1, 1f		# limit reached?
3862306a36Sopenharmony_ci#ifdef CONFIG_EVA
3962306a36Sopenharmony_ci	.set push
4062306a36Sopenharmony_ci	.set eva
4162306a36Sopenharmony_ci	EX(lbe, t0, (v0), .Lfault)
4262306a36Sopenharmony_ci	.set pop
4362306a36Sopenharmony_ci#else
4462306a36Sopenharmony_ci	EX(lb, t0, (v0), .Lfault)
4562306a36Sopenharmony_ci#endif
4662306a36Sopenharmony_ci	.set		noreorder
4762306a36Sopenharmony_ci	bnez		t0, 1b
4862306a36Sopenharmony_ci1:
4962306a36Sopenharmony_ci#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
5062306a36Sopenharmony_ci	 PTR_ADDIU	v0, 1
5162306a36Sopenharmony_ci#else
5262306a36Sopenharmony_ci	 PTR_ADDU	v0, AT
5362306a36Sopenharmony_ci	.set		at
5462306a36Sopenharmony_ci#endif
5562306a36Sopenharmony_ci	.set		reorder
5662306a36Sopenharmony_ci	PTR_SUBU	v0, a0
5762306a36Sopenharmony_ci	jr		ra
5862306a36Sopenharmony_ci	END(__strnlen_user_asm)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci.Lfault:
6162306a36Sopenharmony_ci	move		v0, zero
6262306a36Sopenharmony_ci	jr		ra
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	EXPORT_SYMBOL(__strnlen_user_asm)
65