1/*
2 * memchr - find a character in a memory zone
3 *
4 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 * See https://llvm.org/LICENSE.txt for license information.
6 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 */
8
9#if __ARM_FEATURE_SVE
10/* Assumptions:
11 *
12 * ARMv8-a, AArch64
13 * SVE Available.
14 */
15
16	.arch	armv8-a+sve
17	.text
18
19	.globl	__memchr_aarch64_sve
20	.type	__memchr_aarch64_sve, %function
21	.p2align 4
22__memchr_aarch64_sve:
23	dup	z1.b, w1			/* duplicate c to a vector */
24	setffr					/* initialize FFR */
25	mov	x3, 0				/* initialize off */
26	nop
27
280:	whilelo	p1.b, x3, x2			/* make sure off < max */
29	b.none	9f
30
31	/* Read a vector's worth of bytes, bounded by max,
32	   stopping on first fault.  */
33	ldff1b	z0.b, p1/z, [x0, x3]
34	rdffrs	p0.b, p1/z
35	b.nlast	2f
36
37	/* First fault did not fail: the vector bounded by max is valid.
38	   Avoid depending on the contents of FFR beyond the branch.  */
39	incb	x3				/* speculate increment */
40	cmpeq	p2.b, p1/z, z0.b, z1.b		/* search for c */
41	b.none	0b
42	decb	x3				/* undo speculate */
43
44	/* Found C.  */
451:	brkb	p2.b, p1/z, p2.b	/* find the first c */
46	add	x0, x0, x3		/* form partial pointer */
47	incp	x0, p2.b		/* form final pointer to c */
48	ret
49
50	/* First fault failed: only some of the vector is valid.
51	   Perform the comparison only on the valid bytes.  */
522:	cmpeq	p2.b, p0/z, z0.b, z1.b
53	b.any	1b
54
55	/* No C found.  Re-init FFR, increment, and loop.  */
56	setffr
57	incp	x3, p0.b
58	b	0b
59
60	/* Found end of count.  */
619:	mov	x0, 0			/* return null */
62	ret
63
64	.size	__memchr_aarch64_sve, . - __memchr_aarch64_sve
65#endif
66