1 /*
2  * strchr/strchrnul - find a character in a string
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 
17 /* To build as strchrnul, define BUILD_STRCHRNUL before compiling this file.  */
18 #ifdef BUILD_STRCHRNUL
19 #define FUNC  __strchrnul_aarch64_sve
20 #else
21 #define FUNC  __strchr_aarch64_sve
22 #endif
23 
24 ENTRY (FUNC)
25 	PTR_ARG (0)
26 	dup	z1.b, w1		/* replicate byte across vector */
27 	setffr				/* initialize FFR */
28 	ptrue	p1.b			/* all ones; loop invariant */
29 
30 	.p2align 4
31 	/* Read a vector's worth of bytes, stopping on first fault.  */
32 0:	ldff1b	z0.b, p1/z, [x0, xzr]
33 	rdffrs	p0.b, p1/z
34 	b.nlast	2f
35 
36 	/* First fault did not fail: the whole vector is valid.
37 	   Avoid depending on the contents of FFR beyond the branch.  */
38 	incb	x0				/* speculate increment */
39 	cmpeq	p2.b, p1/z, z0.b, z1.b		/* search for c */
40 	cmpeq	p3.b, p1/z, z0.b, 0		/* search for 0 */
41 	orrs	p4.b, p1/z, p2.b, p3.b		/* c | 0 */
42 	b.none	0b
43 	decb	x0				/* undo speculate */
44 
45 	/* Found C or 0.  */
46 1:	brka	p4.b, p1/z, p4.b	/* find first such */
47 	sub	x0, x0, 1		/* adjust pointer for that byte */
48 	incp	x0, p4.b
49 #ifndef BUILD_STRCHRNUL
50 	ptest	p4, p2.b		/* was first in c? */
51 	csel	x0, xzr, x0, none	/* if there was no c, return null */
52 #endif
53 	ret
54 
55 	/* First fault failed: only some of the vector is valid.
56 	   Perform the comparision only on the valid bytes.  */
57 2:	cmpeq	p2.b, p0/z, z0.b, z1.b		/* search for c */
58 	cmpeq	p3.b, p0/z, z0.b, 0		/* search for 0 */
59 	orrs	p4.b, p0/z, p2.b, p3.b		/* c | 0 */
60 	b.any	1b
61 
62 	/* No C or 0 found.  Re-init FFR, increment, and loop.  */
63 	setffr
64 	incp	x0, p0.b
65 	b	0b
66 
67 END (FUNC)
68 
69 #endif
70 
71