xref: /freebsd/contrib/arm-optimized-routines/string/aarch64/memchr-sve.S (revision 29fc4075e69fd27de0cded313ac6000165d99f8b)
1/*
2 * memchr - find a character in a memory zone
3 *
4 * Copyright (c) 2018-2021, Arm Limited.
5 * SPDX-License-Identifier: MIT
6 */
7
8#include "../asmdefs.h"
9
10#if __ARM_FEATURE_SVE
11/* Assumptions:
12 *
13 * ARMv8-a, AArch64
14 * SVE Available.
15 */
16
17ENTRY (__memchr_aarch64_sve)
18	PTR_ARG (0)
19	SIZE_ARG (2)
20	dup	z1.b, w1			/* duplicate c to a vector */
21	setffr					/* initialize FFR */
22	mov	x3, 0				/* initialize off */
23
24	.p2align 4
250:	whilelo	p1.b, x3, x2			/* make sure off < max */
26	b.none	9f
27
28	/* Read a vector's worth of bytes, bounded by max,
29	   stopping on first fault.  */
30	ldff1b	z0.b, p1/z, [x0, x3]
31	rdffrs	p0.b, p1/z
32	b.nlast	2f
33
34	/* First fault did not fail: the vector bounded by max is valid.
35	   Avoid depending on the contents of FFR beyond the branch.  */
36	incb	x3				/* speculate increment */
37	cmpeq	p2.b, p1/z, z0.b, z1.b		/* search for c */
38	b.none	0b
39	decb	x3				/* undo speculate */
40
41	/* Found C.  */
421:	brkb	p2.b, p1/z, p2.b	/* find the first c */
43	add	x0, x0, x3		/* form partial pointer */
44	incp	x0, p2.b		/* form final pointer to c */
45	ret
46
47	/* First fault failed: only some of the vector is valid.
48	   Perform the comparision only on the valid bytes.  */
492:	cmpeq	p2.b, p0/z, z0.b, z1.b
50	b.any	1b
51
52	/* No C found.  Re-init FFR, increment, and loop.  */
53	setffr
54	incp	x3, p0.b
55	b	0b
56
57	/* Found end of count.  */
589:	mov	x0, 0			/* return null */
59	ret
60
61END (__memchr_aarch64_sve)
62
63#endif
64
65