1 | /* strcspn (str, ss) -- Return the length of the initial segment of STR |
2 | which contains no 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 RTN PARMS |
26 | #define STR RTN |
27 | #define STOP STR+4 |
28 | |
29 | .text |
30 | ENTRY (strpbrk) |
31 | |
32 | movl STR(%esp), %edx |
33 | movl STOP(%esp), %eax |
34 | |
35 | /* First we create a table with flags for all possible characters. |
36 | For the ASCII (7bit/8bit) or ISO-8859-X character sets which are |
37 | supported by the C string functions we have 256 characters. |
38 | Before inserting marks for the stop characters we clear the whole |
39 | table. The unrolled form is much faster than a loop. */ |
40 | xorl %ecx, %ecx /* %ecx = 0 !!! */ |
41 | |
42 | pushl %ecx /* make a 256 bytes long block filled with 0 */ |
43 | cfi_adjust_cfa_offset (4) |
44 | pushl %ecx |
45 | cfi_adjust_cfa_offset (4) |
46 | pushl %ecx |
47 | cfi_adjust_cfa_offset (4) |
48 | pushl %ecx |
49 | cfi_adjust_cfa_offset (4) |
50 | pushl %ecx |
51 | cfi_adjust_cfa_offset (4) |
52 | pushl %ecx |
53 | cfi_adjust_cfa_offset (4) |
54 | pushl %ecx |
55 | cfi_adjust_cfa_offset (4) |
56 | pushl %ecx |
57 | cfi_adjust_cfa_offset (4) |
58 | pushl %ecx |
59 | cfi_adjust_cfa_offset (4) |
60 | pushl %ecx |
61 | cfi_adjust_cfa_offset (4) |
62 | pushl %ecx |
63 | cfi_adjust_cfa_offset (4) |
64 | pushl %ecx |
65 | cfi_adjust_cfa_offset (4) |
66 | pushl %ecx |
67 | cfi_adjust_cfa_offset (4) |
68 | pushl %ecx |
69 | cfi_adjust_cfa_offset (4) |
70 | pushl %ecx |
71 | cfi_adjust_cfa_offset (4) |
72 | pushl %ecx |
73 | cfi_adjust_cfa_offset (4) |
74 | pushl %ecx |
75 | cfi_adjust_cfa_offset (4) |
76 | pushl %ecx |
77 | cfi_adjust_cfa_offset (4) |
78 | pushl %ecx |
79 | cfi_adjust_cfa_offset (4) |
80 | pushl %ecx |
81 | cfi_adjust_cfa_offset (4) |
82 | pushl %ecx |
83 | cfi_adjust_cfa_offset (4) |
84 | pushl %ecx |
85 | cfi_adjust_cfa_offset (4) |
86 | pushl %ecx |
87 | cfi_adjust_cfa_offset (4) |
88 | pushl %ecx |
89 | cfi_adjust_cfa_offset (4) |
90 | pushl %ecx |
91 | cfi_adjust_cfa_offset (4) |
92 | pushl %ecx |
93 | cfi_adjust_cfa_offset (4) |
94 | pushl %ecx |
95 | cfi_adjust_cfa_offset (4) |
96 | pushl %ecx |
97 | cfi_adjust_cfa_offset (4) |
98 | pushl %ecx |
99 | cfi_adjust_cfa_offset (4) |
100 | pushl %ecx |
101 | cfi_adjust_cfa_offset (4) |
102 | pushl %ecx |
103 | cfi_adjust_cfa_offset (4) |
104 | pushl %ecx |
105 | cfi_adjust_cfa_offset (4) |
106 | pushl %ecx |
107 | cfi_adjust_cfa_offset (4) |
108 | pushl %ecx |
109 | cfi_adjust_cfa_offset (4) |
110 | pushl %ecx |
111 | cfi_adjust_cfa_offset (4) |
112 | pushl %ecx |
113 | cfi_adjust_cfa_offset (4) |
114 | pushl %ecx |
115 | cfi_adjust_cfa_offset (4) |
116 | pushl %ecx |
117 | cfi_adjust_cfa_offset (4) |
118 | pushl %ecx |
119 | cfi_adjust_cfa_offset (4) |
120 | pushl %ecx |
121 | cfi_adjust_cfa_offset (4) |
122 | pushl %ecx |
123 | cfi_adjust_cfa_offset (4) |
124 | pushl %ecx |
125 | cfi_adjust_cfa_offset (4) |
126 | pushl %ecx |
127 | cfi_adjust_cfa_offset (4) |
128 | pushl %ecx |
129 | cfi_adjust_cfa_offset (4) |
130 | pushl %ecx |
131 | cfi_adjust_cfa_offset (4) |
132 | pushl %ecx |
133 | cfi_adjust_cfa_offset (4) |
134 | pushl %ecx |
135 | cfi_adjust_cfa_offset (4) |
136 | pushl %ecx |
137 | cfi_adjust_cfa_offset (4) |
138 | pushl %ecx |
139 | cfi_adjust_cfa_offset (4) |
140 | pushl %ecx |
141 | cfi_adjust_cfa_offset (4) |
142 | pushl %ecx |
143 | cfi_adjust_cfa_offset (4) |
144 | pushl %ecx |
145 | cfi_adjust_cfa_offset (4) |
146 | pushl %ecx |
147 | cfi_adjust_cfa_offset (4) |
148 | pushl %ecx |
149 | cfi_adjust_cfa_offset (4) |
150 | pushl %ecx |
151 | cfi_adjust_cfa_offset (4) |
152 | pushl %ecx |
153 | cfi_adjust_cfa_offset (4) |
154 | pushl %ecx |
155 | cfi_adjust_cfa_offset (4) |
156 | pushl %ecx |
157 | cfi_adjust_cfa_offset (4) |
158 | pushl $0 /* These immediate values make the label 2 */ |
159 | cfi_adjust_cfa_offset (4) |
160 | pushl $0 /* to be aligned on a 16 byte boundary to */ |
161 | cfi_adjust_cfa_offset (4) |
162 | pushl $0 /* get a better performance of the loop. */ |
163 | cfi_adjust_cfa_offset (4) |
164 | pushl $0 |
165 | cfi_adjust_cfa_offset (4) |
166 | pushl $0 |
167 | cfi_adjust_cfa_offset (4) |
168 | pushl $0 |
169 | cfi_adjust_cfa_offset (4) |
170 | |
171 | /* For understanding the following code remember that %ecx == 0 now. |
172 | Although all the following instruction only modify %cl we always |
173 | have a correct zero-extended 32-bit value in %ecx. */ |
174 | |
175 | /* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl". We want |
176 | longer instructions so that the next loop aligns without adding nops. */ |
177 | |
178 | L(2): movb (%eax), %cl /* get byte from stopset */ |
179 | testb %cl, %cl /* is NUL char? */ |
180 | jz L(1) /* yes => start compare loop */ |
181 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
182 | |
183 | movb 1(%eax), %cl /* get byte from stopset */ |
184 | testb $0xff, %cl /* is NUL char? */ |
185 | jz L(1) /* yes => start compare loop */ |
186 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
187 | |
188 | movb 2(%eax), %cl /* get byte from stopset */ |
189 | testb $0xff, %cl /* is NUL char? */ |
190 | jz L(1) /* yes => start compare loop */ |
191 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
192 | |
193 | movb 3(%eax), %cl /* get byte from stopset */ |
194 | addl $4, %eax /* increment stopset pointer */ |
195 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
196 | testb $0xff, %cl /* is NUL char? */ |
197 | jnz L(2) /* no => process next dword from stopset */ |
198 | |
199 | L(1): leal -4(%edx), %eax /* prepare loop */ |
200 | |
201 | /* We use a neat trick for the following loop. Normally we would |
202 | have to test for two termination conditions |
203 | 1. a character in the stopset was found |
204 | and |
205 | 2. the end of the string was found |
206 | But as a sign that the character is in the stopset we store its |
207 | value in the table. But the value of NUL is NUL so the loop |
208 | terminates for NUL in every case. */ |
209 | |
210 | L(3): addl $4, %eax /* adjust pointer for full loop round */ |
211 | |
212 | movb (%eax), %cl /* get byte from string */ |
213 | cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */ |
214 | je L(4) /* yes => return */ |
215 | |
216 | movb 1(%eax), %cl /* get byte from string */ |
217 | cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */ |
218 | je L(5) /* yes => return */ |
219 | |
220 | movb 2(%eax), %cl /* get byte from string */ |
221 | cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */ |
222 | je L(6) /* yes => return */ |
223 | |
224 | movb 3(%eax), %cl /* get byte from string */ |
225 | cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */ |
226 | jne L(3) /* yes => return */ |
227 | |
228 | incl %eax /* adjust pointer */ |
229 | L(6): incl %eax |
230 | L(5): incl %eax |
231 | |
232 | L(4): addl $256, %esp /* remove stopset */ |
233 | cfi_adjust_cfa_offset (-256) |
234 | |
235 | orb %cl, %cl /* was last character NUL? */ |
236 | jnz L(7) /* no => return pointer */ |
237 | xorl %eax, %eax |
238 | |
239 | L(7): ret |
240 | END (strpbrk) |
241 | libc_hidden_builtin_def (strpbrk) |
242 | |