aboutsummaryrefslogtreecommitdiff
path: root/string/aarch64/strrchr-sve.S
blob: d36d69af37fd71a23f656ae0c5bc87f719bd3073 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/*
 * strrchr - find the last of a character in a string
 *
 * Copyright (c) 2019-2021, Arm Limited.
 * SPDX-License-Identifier: MIT
 */

#include "../asmdefs.h"

#if __ARM_FEATURE_SVE
/* Assumptions:
 *
 * ARMv8-a, AArch64
 * SVE Available.
 */

ENTRY (__strrchr_aarch64_sve)
	PTR_ARG (0)
	dup	z1.b, w1		/* replicate byte across vector */
	setffr				/* initialize FFR */
	ptrue	p1.b			/* all ones; loop invariant */
	mov	x2, 0			/* no match found so far */
	pfalse	p2.b

	.p2align 4
	/* Read a vector's worth of bytes, stopping on first fault.  */
0:	ldff1b	z0.b, p1/z, [x0, xzr]
	rdffrs	p0.b, p1/z
	b.nlast	1f

	/* First fault did not fail: the whole vector is valid.
	   Avoid depending on the contents of FFR beyond the branch.  */
	incb	x0, all			/* skip bytes this round */
	cmpeq	p3.b, p1/z, z0.b, 0	/* search for 0 */
	b.any	3f

	cmpeq	p3.b, p1/z, z0.b, z1.b	/* search for c; no eos */
	b.none	0b

	mov	x2, x0			/* save advanced base */
	mov	p2.b, p3.b		/* save current search */
	b	0b

	/* First fault failed: only some of the vector is valid.
	   Perform the comparisions only on the valid bytes.  */
1:	cmpeq	p3.b, p0/z, z0.b, 0	/* search for 0 */
	b.any	2f

	cmpeq	p3.b, p0/z, z0.b, z1.b	/* search for c; no eos */
	mov	x3, x0
	incp	x0, p0.b		/* skip bytes this round */
	setffr				/* re-init FFR */
	b.none	0b

	addvl	x2, x3, 1		/* save advanced base */
	mov	p2.b, p3.b		/* save current search */
	b	0b

	/* Found end-of-string.  */
2:	incb	x0, all			/* advance base */
3:	brka	p3.b, p1/z, p3.b	/* mask after first 0 */
	cmpeq	p3.b, p3/z, z0.b, z1.b	/* search for c not after eos */
	b.any	4f

	/* No C within last vector.  Did we have one before?  */
	cbz	x2, 5f
	mov	x0, x2			/* restore advanced base */
	mov	p3.b, p2.b		/* restore saved search */

	/* Find the *last* match in the predicate.  This is slightly
	   more complicated than finding the first match.  */
4:	rev	p3.b, p3.b		/* reverse the bits */
	brka	p3.b, p1/z, p3.b	/* find position of last match */
	decp	x0, p3.b		/* retard pointer to last match */
	ret

	/* No C whatsoever.  Return NULL.  */
5:	mov	x0, 0
	ret

END (__strrchr_aarch64_sve)

#endif