xref: /freebsd/contrib/arm-optimized-routines/string/aarch64/strnlen-sve.S (revision a03411e84728e9b267056fd31c7d1d9d1dc1b01e)
1/*
2 * strnlen - calculate the length of a string with limit.
3 *
4 * Copyright (c) 2019-2022, Arm Limited.
5 * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
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 (__strnlen_aarch64_sve)
18	PTR_ARG (0)
19	SIZE_ARG (1)
20	setffr				/* initialize FFR */
21	mov	x2, 0			/* initialize len */
22	b	1f
23
24	.p2align 4
25	/* We have off + vl <= max, and so may read the whole vector.  */
260:	ldff1b	z0.b, p0/z, [x0, x2]
27	rdffrs	p1.b, p0/z
28	b.nlast	2f
29
30	/* First fault did not fail: the whole vector is valid.
31	   Avoid depending on the contents of FFR beyond the branch.  */
32	cmpeq	p2.b, p0/z, z0.b, 0
33	b.any	8f
34	incb	x2
35
361:	whilelo	p0.b, x2, x1
37	b.last	0b
38
39	/* We have off + vl < max.  Test for off == max before proceeding.  */
40	b.none	9f
41
42	ldff1b	z0.b, p0/z, [x0, x2]
43	rdffrs	p1.b, p0/z
44	b.nlast	2f
45
46	/* First fault did not fail: the vector up to max is valid.
47	   Avoid depending on the contents of FFR beyond the branch.
48	   Compare for end-of-string, but there are no more bytes.  */
49	cmpeq	p2.b, p0/z, z0.b, 0
50
51	/* Found end-of-string or zero.  */
528:	brkb	p2.b, p0/z, p2.b
53	mov	x0, x2
54	incp	x0, p2.b
55	ret
56
57	/* First fault failed: only some of the vector is valid.
58	   Perform the comparison only on the valid bytes.  */
592:	cmpeq	p2.b, p1/z, z0.b, 0
60	b.any	8b
61
62	/* No inequality or zero found.  Re-init FFR, incr and loop.  */
63	setffr
64	incp	x2, p1.b
65	b	1b
66
67	/* End of count.  Return max.  */
689:	mov	x0, x1
69	ret
70
71END (__strnlen_aarch64_sve)
72
73#endif
74
75