1 /* strcspn (str, ss) -- Return the length of the initial segement of STR
2 which contains no characters from SS.
4 Copyright (C) 1994-1997, 2000, 2003, 2005 Free Software Foundation, Inc.
5 Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>
6 Bug fixes by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
7 This file is part of the GNU C Library.
9 The GNU C Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
14 The GNU C Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with the GNU C Library; if not, write to the Free
21 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 #include "asm-syntax.h"
29 #define PARMS LINKAGE /* no space for saved regs */
31 #define STR RTN+RTN_SIZE
32 #define STOP STR+PTR_SIZE
35 ENTRY (BP_SYM (strpbrk))
40 CHECK_BOUNDS_LOW (%edx, STR(%esp))
42 /* First we create a table with flags for all possible characters.
43 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
44 supported by the C string functions we have 256 characters.
45 Before inserting marks for the stop characters we clear the whole
46 table. The unrolled form is much faster than a loop. */
47 xorl %ecx, %ecx /* %ecx = 0 !!! */
49 pushl %ecx /* make a 256 bytes long block filled with 0 */
50 cfi_adjust_cfa_offset (4)
52 cfi_adjust_cfa_offset (4)
54 cfi_adjust_cfa_offset (4)
56 cfi_adjust_cfa_offset (4)
58 cfi_adjust_cfa_offset (4)
60 cfi_adjust_cfa_offset (4)
62 cfi_adjust_cfa_offset (4)
64 cfi_adjust_cfa_offset (4)
66 cfi_adjust_cfa_offset (4)
68 cfi_adjust_cfa_offset (4)
70 cfi_adjust_cfa_offset (4)
72 cfi_adjust_cfa_offset (4)
74 cfi_adjust_cfa_offset (4)
76 cfi_adjust_cfa_offset (4)
78 cfi_adjust_cfa_offset (4)
80 cfi_adjust_cfa_offset (4)
82 cfi_adjust_cfa_offset (4)
84 cfi_adjust_cfa_offset (4)
86 cfi_adjust_cfa_offset (4)
88 cfi_adjust_cfa_offset (4)
90 cfi_adjust_cfa_offset (4)
92 cfi_adjust_cfa_offset (4)
94 cfi_adjust_cfa_offset (4)
96 cfi_adjust_cfa_offset (4)
98 cfi_adjust_cfa_offset (4)
100 cfi_adjust_cfa_offset (4)
102 cfi_adjust_cfa_offset (4)
104 cfi_adjust_cfa_offset (4)
106 cfi_adjust_cfa_offset (4)
108 cfi_adjust_cfa_offset (4)
110 cfi_adjust_cfa_offset (4)
112 cfi_adjust_cfa_offset (4)
114 cfi_adjust_cfa_offset (4)
116 cfi_adjust_cfa_offset (4)
118 cfi_adjust_cfa_offset (4)
120 cfi_adjust_cfa_offset (4)
122 cfi_adjust_cfa_offset (4)
124 cfi_adjust_cfa_offset (4)
126 cfi_adjust_cfa_offset (4)
128 cfi_adjust_cfa_offset (4)
130 cfi_adjust_cfa_offset (4)
132 cfi_adjust_cfa_offset (4)
134 cfi_adjust_cfa_offset (4)
136 cfi_adjust_cfa_offset (4)
138 cfi_adjust_cfa_offset (4)
140 cfi_adjust_cfa_offset (4)
142 cfi_adjust_cfa_offset (4)
144 cfi_adjust_cfa_offset (4)
146 cfi_adjust_cfa_offset (4)
148 cfi_adjust_cfa_offset (4)
150 cfi_adjust_cfa_offset (4)
152 cfi_adjust_cfa_offset (4)
154 cfi_adjust_cfa_offset (4)
156 cfi_adjust_cfa_offset (4)
158 cfi_adjust_cfa_offset (4)
160 cfi_adjust_cfa_offset (4)
162 cfi_adjust_cfa_offset (4)
164 cfi_adjust_cfa_offset (4)
165 pushl $0 /* These immediate values make the label 2 */
166 cfi_adjust_cfa_offset (4)
167 pushl $0 /* to be aligned on a 16 byte boundary to */
168 cfi_adjust_cfa_offset (4)
169 pushl $0 /* get a better performance of the loop. */
170 cfi_adjust_cfa_offset (4)
172 cfi_adjust_cfa_offset (4)
174 cfi_adjust_cfa_offset (4)
176 cfi_adjust_cfa_offset (4)
178 /* For understanding the following code remember that %ecx == 0 now.
179 Although all the following instruction only modify %cl we always
180 have a correct zero-extended 32-bit value in %ecx. */
182 /* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl". We want
183 longer instructions so that the next loop aligns without adding nops. */
185 L(2): movb (%eax), %cl /* get byte from stopset */
186 testb %cl, %cl /* is NUL char? */
187 jz L(1) /* yes => start compare loop */
188 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
190 movb 1(%eax), %cl /* get byte from stopset */
191 testb $0xff, %cl /* is NUL char? */
192 jz L(1) /* yes => start compare loop */
193 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
195 movb 2(%eax), %cl /* get byte from stopset */
196 testb $0xff, %cl /* is NUL char? */
197 jz L(1) /* yes => start compare loop */
198 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
200 movb 3(%eax), %cl /* get byte from stopset */
201 addl $4, %eax /* increment stopset pointer */
202 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
203 testb $0xff, %cl /* is NUL char? */
204 jnz L(2) /* no => process next dword from stopset */
206 L(1): leal -4(%edx), %eax /* prepare loop */
208 /* We use a neat trick for the following loop. Normally we would
209 have to test for two termination conditions
210 1. a character in the stopset was found
212 2. the end of the string was found
213 But as a sign that the chracter is in the stopset we store its
214 value in the table. But the value of NUL is NUL so the loop
215 terminates for NUL in every case. */
217 L(3): addl $4, %eax /* adjust pointer for full loop round */
219 movb (%eax), %cl /* get byte from string */
220 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
221 je L(4) /* yes => return */
223 movb 1(%eax), %cl /* get byte from string */
224 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
225 je L(5) /* yes => return */
227 movb 2(%eax), %cl /* get byte from string */
228 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
229 je L(6) /* yes => return */
231 movb 3(%eax), %cl /* get byte from string */
232 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
233 jne L(3) /* yes => return */
235 incl %eax /* adjust pointer */
239 L(4): addl $256, %esp /* remove stopset */
240 cfi_adjust_cfa_offset (-256)
242 CHECK_BOUNDS_HIGH (%eax, STR(%esp), jb)
243 orb %cl, %cl /* was last character NUL? */
244 jnz L(7) /* no => return pointer */
246 RETURN_NULL_BOUNDED_POINTER
251 L(7): RETURN_BOUNDED_POINTER (STR(%esp))
255 END (BP_SYM (strpbrk))
256 libc_hidden_builtin_def (strpbrk)