1/* Generic optimized strlen using SIMD.
2 Copyright (C) 2012-2024 Free Software Foundation, Inc.
3
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library. If not, see
18 <https://www.gnu.org/licenses/>. */
19
20#include <sysdep.h>
21
22/* Assumptions:
23 *
24 * ARMv8-a, AArch64, Advanced SIMD.
25 * MTE compatible.
26 */
27
28#ifndef STRLEN
29# define STRLEN __strlen
30#endif
31
32#define srcin x0
33#define result x0
34
35#define src x1
36#define synd x2
37#define tmp x3
38#define shift x4
39
40#define data q0
41#define vdata v0
42#define vhas_nul v1
43#define vend v2
44#define dend d2
45
46/* Core algorithm:
47 Process the string in 16-byte aligned chunks. Compute a 64-bit mask with
48 four bits per byte using the shrn instruction. A count trailing zeros then
49 identifies the first zero byte. */
50
51ENTRY (STRLEN)
52 PTR_ARG (0)
53 bic src, srcin, 15
54 ld1 {vdata.16b}, [src]
55 cmeq vhas_nul.16b, vdata.16b, 0
56 lsl shift, srcin, 2
57 shrn vend.8b, vhas_nul.8h, 4 /* 128->64 */
58 fmov synd, dend
59 lsr synd, synd, shift
60 cbz synd, L(next16)
61
62 rbit synd, synd
63 clz result, synd
64 lsr result, result, 2
65 ret
66
67L(next16):
68 ldr data, [src, 16]
69 cmeq vhas_nul.16b, vdata.16b, 0
70 shrn vend.8b, vhas_nul.8h, 4 /* 128->64 */
71 fmov synd, dend
72 cbz synd, L(loop)
73 add src, src, 16
74#ifndef __AARCH64EB__
75 rbit synd, synd
76#endif
77 sub result, src, srcin
78 clz tmp, synd
79 add result, result, tmp, lsr 2
80 ret
81
82 .p2align 5
83L(loop):
84 ldr data, [src, 32]!
85 cmeq vhas_nul.16b, vdata.16b, 0
86 addhn vend.8b, vhas_nul.8h, vhas_nul.8h
87 fmov synd, dend
88 cbnz synd, L(loop_end)
89 ldr data, [src, 16]
90 cmeq vhas_nul.16b, vdata.16b, 0
91 addhn vend.8b, vhas_nul.8h, vhas_nul.8h
92 fmov synd, dend
93 cbz synd, L(loop)
94 add src, src, 16
95L(loop_end):
96 sub result, shift, src, lsl 2 /* (srcin - src) << 2. */
97#ifndef __AARCH64EB__
98 rbit synd, synd
99 sub result, result, 3
100#endif
101 clz tmp, synd
102 sub result, tmp, result
103 lsr result, result, 2
104 ret
105
106END (STRLEN)
107weak_alias (STRLEN, strlen)
108libc_hidden_builtin_def (strlen)
109

source code of glibc/sysdeps/aarch64/strlen.S