1/* Copyright (C) 1996-2021 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
4   The GNU C Library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8
9   The GNU C Library is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with the GNU C Library.  If not, see
16   <https://www.gnu.org/licenses/>.  */
17
18/* Return the address of a given character within a null-terminated
19   string, or null if it is not found.
20
21   This is generally scheduled for the EV5 (got to look out for my own
22   interests :-), but with EV4 needs in mind.  There *should* be no more
23   stalls for the EV4 than there are for the EV5.
24*/
25
26#include <sysdep.h>
27
28	.set noreorder
29	.set noat
30
31ENTRY(strchr)
32#ifdef PROF
33	ldgp	gp, 0(pv)
34	lda	AT, _mcount
35	jsr	AT, (AT), _mcount
36	.prologue 1
37#else
38	.prologue 0
39#endif
40
41	zapnot	a1, 1, a1	# e0    : zero extend the search character
42	ldq_u   t0, 0(a0)	# .. e1 : load first quadword
43	sll	a1, 8, t5	# e0    : replicate the search character
44	andnot  a0, 7, v0	# .. e1 : align our loop pointer
45	or	t5, a1, a1	# e0    :
46	lda	t4, -1		# .. e1 : build garbage mask
47	sll	a1, 16, t5	# e0    :
48	cmpbge  zero, t0, t2	# .. e1 : bits set iff byte == zero
49	mskqh	t4, a0, t4	# e0    :
50	or	t5, a1, a1	# .. e1 :
51	sll	a1, 32, t5	# e0    :
52	cmpbge	zero, t4, t4	# .. e1 : bits set iff byte is garbage
53	or	t5, a1, a1	# e0    :
54	xor	t0, a1, t1	# .. e1 : make bytes == c zero
55	cmpbge  zero, t1, t3	# e0    : bits set iff byte == c
56	or	t2, t3, t0	# e1    : bits set iff char match or zero match
57	andnot	t0, t4, t0	# e0    : clear garbage bits
58	bne	t0, $found	# .. e1 (zdb)
59
60$loop:	ldq	t0, 8(v0)	# e0    :
61	addq	v0, 8, v0	# .. e1 :
62	nop			# e0    :
63	xor	t0, a1, t1	# .. e1 (ev5 data stall)
64	cmpbge	zero, t0, t2	# e0    : bits set iff byte == 0
65	cmpbge	zero, t1, t3	# .. e1 : bits set iff byte == c
66	or	t2, t3, t0	# e0    :
67	beq	t0, $loop	# .. e1 (zdb)
68
69$found:	negq    t0, t1		# e0    : clear all but least set bit
70	and     t0, t1, t0	# e1 (stall)
71
72	and	t0, t3, t1	# e0    : bit set iff byte was the char
73	beq	t1, $retnull	# .. e1 (zdb)
74
75	and     t0, 0xf0, t2	# e0    : binary search for that set bit
76	and	t0, 0xcc, t3	# .. e1 :
77	and	t0, 0xaa, t4	# e0    :
78	cmovne	t2, 4, t2	# .. e1 :
79	cmovne	t3, 2, t3	# e0    :
80	cmovne	t4, 1, t4	# .. e1 :
81	addq	t2, t3, t2	# e0    :
82	addq	v0, t4, v0	# .. e1 :
83	addq	v0, t2, v0	# e0    :
84	ret			# .. e1 :
85
86$retnull:
87	mov	zero, v0	# e0    :
88	ret			# .. e1 :
89
90	END(strchr)
91
92weak_alias (strchr, index)
93libc_hidden_builtin_def (strchr)
94