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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
/* Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#ifdef USE_AS_STRCSPN
# define STRSPN strcspn
# define SBT orr /* SBT -- `set bit' */
#else
# define STRSPN strspn
# define SBT bic
#endif
#ifdef __AARCH64EB__
# define LS_FW lsl
# define LS_BK lsr
#else
# define LS_FW lsr
# define LS_BK lsl
#endif
#define og_s x0
#define set x1 /* ACCEPT for strspn, REJECT for strcspn */
#define byte_i x3
#define bits_i x4
#define one x6
#define syndrome x5
#define s x6
#define vbyte_i v1.16b
#define vbits_i v2.16b
#define table v4.16b-v5.16b
#define table_a v4
#define table_b v5
#define sevens v7.16b
ENTRY(STRSPN)
ldrb w2, [set]
cbz w2, L(early)
#ifdef USE_AS_STRCSPN
ldrb w3, [set, 1]
cbz w3, L(early)
#endif
/* Table has ones for bytes to reject and zeros for bytes to accept */
mov one, 1
#ifdef USE_AS_STRCSPN
stp one, xzr, [sp, -32]!
.cfi_def_cfa_offset 32
stp xzr, xzr, [sp, 16]
#else
mvni v0.4s, 0
stp q0, q0, [sp, -32]!
.cfi_def_cfa_offset 32
#endif
.p2align 4
L(fill_table):
lsr byte_i, x2, 6 /* x2 / 64 */
lsl bits_i, one, x2 /* x2 % 64 implicitly */
ldrb w2, [set, 1]!
ldr x5, [sp, byte_i, lsl 3]
SBT x5, x5, bits_i
str x5, [sp, byte_i, lsl 3]
cbnz w2, L(fill_table)
ld1 {table_a.2d-table_b.2d}, [sp], 32
.cfi_def_cfa_offset 0
ubfiz syndrome, og_s, 2, 4 /* Bottom 4 bits, times 4 to count nibbles */
and s, og_s, -16 /* Round S down to 16-byte boundary */
movi sevens, 7
/* Bias the syndrome to mask off these nibbles */
mov x8, -1
LS_BK syndrome, x8, syndrome
mvn syndrome, syndrome
L(loop):
ldr q0, [s], 16
ushr vbyte_i, v0.16b, 3
bic vbits_i, sevens, v0.16b
tbl v0.16b, {table}, vbyte_i
/* Bring the relevant bit to the MSB of each byte */
sshl v0.16b, v0.16b, vbits_i
/* Set every bit of each byte to its MSB */
cmlt v0.16b, v0.16b, 0
/* Bytes->nibbles */
shrn v0.8b, v0.8h, 4
fmov x2, d0
bic syndrome, x2, syndrome
cbz syndrome, L(loop)
#ifndef __AARCH64EB__
rbit syndrome, syndrome
#endif
sub s, s, 16
clz syndrome, syndrome
sub x0, s, og_s
add x0, x0, syndrome, lsr 2
ret
.balign 8 /* For strspn, which has only 2 instructions here */
L(early):
#ifdef USE_AS_STRCSPN
/* strlen(set) < 2: call strchrnul(s, *set) and get its offset from S */
stp fp, lr, [sp, -32]!
.cfi_def_cfa_offset 32
.cfi_offset fp, -32
.cfi_offset lr, -24
str x19, [sp, 16]
.cfi_offset 19, -16
mov w1, w2
mov fp, sp
mov x19, x0
bl __strchrnul
sub x0, x0, x19
ldr x19, [sp, 16]
ldp fp, lr, [sp], 32
.cfi_restore lr
.cfi_restore fp
.cfi_restore 19
.cfi_def_cfa_offset 0
#else
mov w0, 0
#endif
ret
END(STRSPN)
#undef set
libc_hidden_def(STRSPN)
|