1bbbf1280Sopenharmony_ci/*
2bbbf1280Sopenharmony_ci * __strlen_aarch64_sve - compute the length of a string
3bbbf1280Sopenharmony_ci *
4bbbf1280Sopenharmony_ci * Copyright (c) 2018-2021, Arm Limited.
5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT
6bbbf1280Sopenharmony_ci */
7bbbf1280Sopenharmony_ci
8bbbf1280Sopenharmony_ci#include "../asmdefs.h"
9bbbf1280Sopenharmony_ci
10bbbf1280Sopenharmony_ci#if __ARM_FEATURE_SVE
11bbbf1280Sopenharmony_ci/* Assumptions:
12bbbf1280Sopenharmony_ci *
13bbbf1280Sopenharmony_ci * ARMv8-a, AArch64
14bbbf1280Sopenharmony_ci * SVE Available.
15bbbf1280Sopenharmony_ci */
16bbbf1280Sopenharmony_ci
17bbbf1280Sopenharmony_ciENTRY (__strlen_aarch64_sve)
18bbbf1280Sopenharmony_ci	PTR_ARG (0)
19bbbf1280Sopenharmony_ci	setffr			/* initialize FFR */
20bbbf1280Sopenharmony_ci	ptrue	p2.b		/* all ones; loop invariant */
21bbbf1280Sopenharmony_ci	mov	x1, 0		/* initialize length */
22bbbf1280Sopenharmony_ci
23bbbf1280Sopenharmony_ci	/* Read a vector's worth of bytes, stopping on first fault.  */
24bbbf1280Sopenharmony_ci	.p2align 4
25bbbf1280Sopenharmony_ci0:	ldff1b	z0.b, p2/z, [x0, x1]
26bbbf1280Sopenharmony_ci	rdffrs	p0.b, p2/z
27bbbf1280Sopenharmony_ci	b.nlast	2f
28bbbf1280Sopenharmony_ci
29bbbf1280Sopenharmony_ci	/* First fault did not fail: the whole vector is valid.
30bbbf1280Sopenharmony_ci	   Avoid depending on the contents of FFR beyond the branch.  */
31bbbf1280Sopenharmony_ci	incb	x1, all			/* speculate increment */
32bbbf1280Sopenharmony_ci	cmpeq	p1.b, p2/z, z0.b, 0	/* loop if no zeros */
33bbbf1280Sopenharmony_ci	b.none	0b
34bbbf1280Sopenharmony_ci	decb	x1, all			/* undo speculate */
35bbbf1280Sopenharmony_ci
36bbbf1280Sopenharmony_ci	/* Zero found.  Select the bytes before the first and count them.  */
37bbbf1280Sopenharmony_ci1:	brkb	p0.b, p2/z, p1.b
38bbbf1280Sopenharmony_ci	incp	x1, p0.b
39bbbf1280Sopenharmony_ci	mov	x0, x1
40bbbf1280Sopenharmony_ci	ret
41bbbf1280Sopenharmony_ci
42bbbf1280Sopenharmony_ci	/* First fault failed: only some of the vector is valid.
43bbbf1280Sopenharmony_ci	   Perform the comparison only on the valid bytes.  */
44bbbf1280Sopenharmony_ci2:	cmpeq	p1.b, p0/z, z0.b, 0
45bbbf1280Sopenharmony_ci	b.any	1b
46bbbf1280Sopenharmony_ci
47bbbf1280Sopenharmony_ci	/* No zero found.  Re-init FFR, increment, and loop.  */
48bbbf1280Sopenharmony_ci	setffr
49bbbf1280Sopenharmony_ci	incp	x1, p0.b
50bbbf1280Sopenharmony_ci	b	0b
51bbbf1280Sopenharmony_ci
52bbbf1280Sopenharmony_ciEND (__strlen_aarch64_sve)
53bbbf1280Sopenharmony_ci
54bbbf1280Sopenharmony_ci#endif
55bbbf1280Sopenharmony_ci
56