• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * strrchr - find the last of a character in a string
3 *
4 * Copyright (c) 2019, Arm Limited.
5 * SPDX-License-Identifier: MIT
6 */
7
8/* Assumptions:
9 *
10 * ARMv8-a, AArch64
11 * SVE Available.
12 */
13
14	.arch	armv8-a+sve
15	.text
16
17	.globl	__strrchr_aarch64_sve
18	.type	__strrchr_aarch64_sve, %function
19	.p2align 4
20__strrchr_aarch64_sve:
21	dup	z1.b, w1		/* replicate byte across vector */
22	setffr				/* initialize FFR */
23	ptrue	p1.b			/* all ones; loop invariant */
24	mov	x2, 0			/* no match found so far */
25	pfalse	p2.b
26
27	.p2align 4
28	/* Read a vector's worth of bytes, stopping on first fault.  */
290:	ldff1b	z0.b, p1/z, [x0, xzr]
30	rdffrs	p0.b, p1/z
31	b.nlast	1f
32
33	/* First fault did not fail: the whole vector is valid.
34	   Avoid depending on the contents of FFR beyond the branch.  */
35	incb	x0, all			/* skip bytes this round */
36	cmpeq	p3.b, p1/z, z0.b, 0	/* search for 0 */
37	b.any	3f
38
39	cmpeq	p3.b, p1/z, z0.b, z1.b	/* search for c; no eos */
40	b.none	0b
41
42	mov	x2, x0			/* save advanced base */
43	mov	p2.b, p3.b		/* save current search */
44	b	0b
45
46	/* First fault failed: only some of the vector is valid.
47	   Perform the comparisions only on the valid bytes.  */
481:	cmpeq	p3.b, p0/z, z0.b, 0	/* search for 0 */
49	b.any	2f
50
51	cmpeq	p3.b, p0/z, z0.b, z1.b	/* search for c; no eos */
52	mov	x3, x0
53	incp	x0, p0.b		/* skip bytes this round */
54	setffr				/* re-init FFR */
55	b.none	0b
56
57	addvl	x2, x3, 1		/* save advanced base */
58	mov	p2.b, p3.b		/* save current search */
59	b	0b
60
61	/* Found end-of-string.  */
622:	incb	x0, all			/* advance base */
633:	brka	p3.b, p1/z, p3.b	/* mask after first 0 */
64	cmpeq	p3.b, p3/z, z0.b, z1.b	/* search for c not after eos */
65	b.any	4f
66
67	/* No C within last vector.  Did we have one before?  */
68	cbz	x2, 5f
69	mov	x0, x2			/* restore advanced base */
70	mov	p3.b, p2.b		/* restore saved search */
71
72	/* Find the *last* match in the predicate.  This is slightly
73	   more complicated than finding the first match.  */
744:	rev	p3.b, p3.b		/* reverse the bits */
75	brka	p3.b, p1/z, p3.b	/* find position of last match */
76	decp	x0, p3.b		/* retard pointer to last match */
77	ret
78
79	/* No C whatsoever.  Return NULL.  */
805:	mov	x0, 0
81	ret
82
83	.size	__strrchr_aarch64_sve, . - __strrchr_aarch64_sve
84