1/*
2 * arch/alpha/lib/strlen_user.S
3 *
4 * Return the length of the string including the NUL terminator
5 * (strlen+1) or zero if an error occurred.
6 *
7 * In places where it is critical to limit the processing time,
8 * and the data is not trusted, strnlen_user() should be used.
9 * It will return a value greater than its second argument if
10 * that limit would be exceeded. This implementation is allowed
11 * to access memory beyond the limit, but will not cross a page
12 * boundary when doing so.
13 */
14
15#include <asm/regdef.h>
16
17
18/* Allow an exception for an insn; exit if we get one.  */
19#define EX(x,y...)			\
20	99: x,##y;			\
21	.section __ex_table,"a";	\
22	.gprel32 99b;			\
23	lda v0, $exception-99b(zero);	\
24	.previous
25
26
27	.set noreorder
28	.set noat
29	.text
30
31	.globl __strlen_user
32	.ent __strlen_user
33	.frame sp, 0, ra
34
35	.align 3
36__strlen_user:
37	ldah	a1, 32767(zero)	# do not use plain strlen_user() for strings
38				# that might be almost 2 GB long; you should
39				# be using strnlen_user() instead
40
41	.globl __strnlen_user
42
43	.align 3
44__strnlen_user:
45	ldgp	$29,0($27)	# we do exceptions -- we need the gp.
46	.prologue 1
47
48	EX( ldq_u t0, 0(a0) )	# load first quadword (a0 may be misaligned)
49	lda     t1, -1(zero)
50	insqh   t1, a0, t1
51	andnot  a0, 7, v0
52	or      t1, t0, t0
53	subq	a0, 1, a0	# get our +1 for the return
54	cmpbge  zero, t0, t1	# t1 <- bitmask: bit i == 1 <==> i-th byte == 0
55	subq	a1, 7, t2
56	subq	a0, v0, t0
57	bne     t1, $found
58
59	addq	t2, t0, t2
60	addq	a1, 1, a1
61
62	.align 3
63$loop:	ble	t2, $limit
64	EX( ldq t0, 8(v0) )
65	subq	t2, 8, t2
66	addq    v0, 8, v0	# addr += 8
67	cmpbge  zero, t0, t1
68	beq     t1, $loop
69
70$found:	negq    t1, t2		# clear all but least set bit
71	and     t1, t2, t1
72
73	and     t1, 0xf0, t2	# binary search for that set bit
74	and	t1, 0xcc, t3
75	and	t1, 0xaa, t4
76	cmovne	t2, 4, t2
77	cmovne	t3, 2, t3
78	cmovne	t4, 1, t4
79	addq	t2, t3, t2
80	addq	v0, t4, v0
81	addq	v0, t2, v0
82	nop			# dual issue next two on ev4 and ev5
83	subq    v0, a0, v0
84$exception:
85	ret
86
87	.align 3		# currently redundant
88$limit:
89	subq	a1, t2, v0
90	ret
91
92	.end __strlen_user
93