1 | /* strcspn (str, ss) -- Return the length of the initial segment of STR |
2 | which contains only characters from SS. |
3 | For Intel 80x86, x>=3. |
4 | Copyright (C) 1994-2024 Free Software Foundation, Inc. |
5 | This file is part of the GNU C Library. |
6 | |
7 | The GNU C Library is free software; you can redistribute it and/or |
8 | modify it under the terms of the GNU Lesser General Public |
9 | License as published by the Free Software Foundation; either |
10 | version 2.1 of the License, or (at your option) any later version. |
11 | |
12 | The GNU C Library is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | Lesser General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU Lesser General Public |
18 | License along with the GNU C Library; if not, see |
19 | <https://www.gnu.org/licenses/>. */ |
20 | |
21 | #include <sysdep.h> |
22 | #include "asm-syntax.h" |
23 | |
24 | #define PARMS 4 /* no space for saved regs */ |
25 | #define STR PARMS |
26 | #define SKIP STR+4 |
27 | |
28 | .text |
29 | ENTRY (strspn) |
30 | |
31 | movl STR(%esp), %edx |
32 | movl SKIP(%esp), %eax |
33 | |
34 | /* First we create a table with flags for all possible characters. |
35 | For the ASCII (7bit/8bit) or ISO-8859-X character sets which are |
36 | supported by the C string functions we have 256 characters. |
37 | Before inserting marks for the stop characters we clear the whole |
38 | table. The unrolled form is much faster than a loop. */ |
39 | xorl %ecx, %ecx /* %ecx = 0 !!! */ |
40 | |
41 | pushl %ecx /* make a 256 bytes long block filled with 0 */ |
42 | cfi_adjust_cfa_offset (4) |
43 | pushl %ecx |
44 | cfi_adjust_cfa_offset (4) |
45 | pushl %ecx |
46 | cfi_adjust_cfa_offset (4) |
47 | pushl %ecx |
48 | cfi_adjust_cfa_offset (4) |
49 | pushl %ecx |
50 | cfi_adjust_cfa_offset (4) |
51 | pushl %ecx |
52 | cfi_adjust_cfa_offset (4) |
53 | pushl %ecx |
54 | cfi_adjust_cfa_offset (4) |
55 | pushl %ecx |
56 | cfi_adjust_cfa_offset (4) |
57 | pushl %ecx |
58 | cfi_adjust_cfa_offset (4) |
59 | pushl %ecx |
60 | cfi_adjust_cfa_offset (4) |
61 | pushl %ecx |
62 | cfi_adjust_cfa_offset (4) |
63 | pushl %ecx |
64 | cfi_adjust_cfa_offset (4) |
65 | pushl %ecx |
66 | cfi_adjust_cfa_offset (4) |
67 | pushl %ecx |
68 | cfi_adjust_cfa_offset (4) |
69 | pushl %ecx |
70 | cfi_adjust_cfa_offset (4) |
71 | pushl %ecx |
72 | cfi_adjust_cfa_offset (4) |
73 | pushl %ecx |
74 | cfi_adjust_cfa_offset (4) |
75 | pushl %ecx |
76 | cfi_adjust_cfa_offset (4) |
77 | pushl %ecx |
78 | cfi_adjust_cfa_offset (4) |
79 | pushl %ecx |
80 | cfi_adjust_cfa_offset (4) |
81 | pushl %ecx |
82 | cfi_adjust_cfa_offset (4) |
83 | pushl %ecx |
84 | cfi_adjust_cfa_offset (4) |
85 | pushl %ecx |
86 | cfi_adjust_cfa_offset (4) |
87 | pushl %ecx |
88 | cfi_adjust_cfa_offset (4) |
89 | pushl %ecx |
90 | cfi_adjust_cfa_offset (4) |
91 | pushl %ecx |
92 | cfi_adjust_cfa_offset (4) |
93 | pushl %ecx |
94 | cfi_adjust_cfa_offset (4) |
95 | pushl %ecx |
96 | cfi_adjust_cfa_offset (4) |
97 | pushl %ecx |
98 | cfi_adjust_cfa_offset (4) |
99 | pushl %ecx |
100 | cfi_adjust_cfa_offset (4) |
101 | pushl %ecx |
102 | cfi_adjust_cfa_offset (4) |
103 | pushl %ecx |
104 | cfi_adjust_cfa_offset (4) |
105 | pushl %ecx |
106 | cfi_adjust_cfa_offset (4) |
107 | pushl %ecx |
108 | cfi_adjust_cfa_offset (4) |
109 | pushl %ecx |
110 | cfi_adjust_cfa_offset (4) |
111 | pushl %ecx |
112 | cfi_adjust_cfa_offset (4) |
113 | pushl %ecx |
114 | cfi_adjust_cfa_offset (4) |
115 | pushl %ecx |
116 | cfi_adjust_cfa_offset (4) |
117 | pushl %ecx |
118 | cfi_adjust_cfa_offset (4) |
119 | pushl %ecx |
120 | cfi_adjust_cfa_offset (4) |
121 | pushl %ecx |
122 | cfi_adjust_cfa_offset (4) |
123 | pushl %ecx |
124 | cfi_adjust_cfa_offset (4) |
125 | pushl %ecx |
126 | cfi_adjust_cfa_offset (4) |
127 | pushl %ecx |
128 | cfi_adjust_cfa_offset (4) |
129 | pushl %ecx |
130 | cfi_adjust_cfa_offset (4) |
131 | pushl %ecx |
132 | cfi_adjust_cfa_offset (4) |
133 | pushl %ecx |
134 | cfi_adjust_cfa_offset (4) |
135 | pushl %ecx |
136 | cfi_adjust_cfa_offset (4) |
137 | pushl %ecx |
138 | cfi_adjust_cfa_offset (4) |
139 | pushl %ecx |
140 | cfi_adjust_cfa_offset (4) |
141 | pushl %ecx |
142 | cfi_adjust_cfa_offset (4) |
143 | pushl %ecx |
144 | cfi_adjust_cfa_offset (4) |
145 | pushl %ecx |
146 | cfi_adjust_cfa_offset (4) |
147 | pushl %ecx |
148 | cfi_adjust_cfa_offset (4) |
149 | pushl %ecx |
150 | cfi_adjust_cfa_offset (4) |
151 | pushl %ecx |
152 | cfi_adjust_cfa_offset (4) |
153 | pushl %ecx |
154 | cfi_adjust_cfa_offset (4) |
155 | pushl %ecx |
156 | cfi_adjust_cfa_offset (4) |
157 | pushl $0 /* These immediate values make the label 2 */ |
158 | cfi_adjust_cfa_offset (4) |
159 | pushl $0 /* to be aligned on a 16 byte boundary to */ |
160 | cfi_adjust_cfa_offset (4) |
161 | pushl $0 /* get a better performance of the loop. */ |
162 | cfi_adjust_cfa_offset (4) |
163 | pushl $0 |
164 | cfi_adjust_cfa_offset (4) |
165 | pushl $0 |
166 | cfi_adjust_cfa_offset (4) |
167 | pushl $0 |
168 | cfi_adjust_cfa_offset (4) |
169 | |
170 | /* For understanding the following code remember that %ecx == 0 now. |
171 | Although all the following instruction only modify %cl we always |
172 | have a correct zero-extended 32-bit value in %ecx. */ |
173 | |
174 | /* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl". We want |
175 | longer instructions so that the next loop aligns without adding nops. */ |
176 | |
177 | L(2): movb (%eax), %cl /* get byte from stopset */ |
178 | testb %cl, %cl /* is NUL char? */ |
179 | jz L(1) /* yes => start compare loop */ |
180 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
181 | |
182 | movb 1(%eax), %cl /* get byte from stopset */ |
183 | testb $0xff, %cl /* is NUL char? */ |
184 | jz L(1) /* yes => start compare loop */ |
185 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
186 | |
187 | movb 2(%eax), %cl /* get byte from stopset */ |
188 | testb $0xff, %cl /* is NUL char? */ |
189 | jz L(1) /* yes => start compare loop */ |
190 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
191 | |
192 | movb 3(%eax), %cl /* get byte from stopset */ |
193 | addl $4, %eax /* increment stopset pointer */ |
194 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
195 | testb $0xff, %cl /* is NUL char? */ |
196 | jnz L(2) /* no => process next dword from stopset */ |
197 | |
198 | L(1): leal -4(%edx), %eax /* prepare loop */ |
199 | |
200 | /* We use a neat trick for the following loop. Normally we would |
201 | have to test for two termination conditions |
202 | 1. a character in the stopset was found |
203 | and |
204 | 2. the end of the string was found |
205 | But as a sign that the character is in the stopset we store its |
206 | value in the table. But the value of NUL is NUL so the loop |
207 | terminates for NUL in every case. */ |
208 | |
209 | L(3): addl $4, %eax /* adjust pointer for full loop round */ |
210 | |
211 | movb (%eax), %cl /* get byte from string */ |
212 | testb %cl, (%esp,%ecx) /* is it contained in skipset? */ |
213 | jz L(4) /* no => return */ |
214 | |
215 | movb 1(%eax), %cl /* get byte from string */ |
216 | testb %cl, (%esp,%ecx) /* is it contained in skipset? */ |
217 | jz L(5) /* no => return */ |
218 | |
219 | movb 2(%eax), %cl /* get byte from string */ |
220 | testb %cl, (%esp,%ecx) /* is it contained in skipset? */ |
221 | jz L(6) /* no => return */ |
222 | |
223 | movb 3(%eax), %cl /* get byte from string */ |
224 | testb %cl, (%esp,%ecx) /* is it contained in skipset? */ |
225 | jnz L(3) /* yes => start loop again */ |
226 | |
227 | incl %eax /* adjust pointer */ |
228 | L(6): incl %eax |
229 | L(5): incl %eax |
230 | |
231 | L(4): addl $256, %esp /* remove stopset */ |
232 | cfi_adjust_cfa_offset (-256) |
233 | subl %edx, %eax /* we have to return the number of valid |
234 | characters, so compute distance to first |
235 | non-valid character */ |
236 | ret |
237 | END (strspn) |
238 | libc_hidden_builtin_def (strspn) |
239 | |