]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/i386/strspn.S
0182f7040377cbb7cc4715e3d4d9a153aee1d9cd
[thirdparty/glibc.git] / sysdeps / i386 / strspn.S
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-2019 Free Software Foundation, Inc.
5 This file is part of the GNU C Library.
6 Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>
7 Bug fixes by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
8
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.
13
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.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with the GNU C Library; if not, see
21 <http://www.gnu.org/licenses/>. */
22
23 #include <sysdep.h>
24 #include "asm-syntax.h"
25
26 #define PARMS 4 /* no space for saved regs */
27 #define STR PARMS
28 #define SKIP STR+4
29
30 .text
31 ENTRY (strspn)
32
33 movl STR(%esp), %edx
34 movl SKIP(%esp), %eax
35
36 /* First we create a table with flags for all possible characters.
37 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
38 supported by the C string functions we have 256 characters.
39 Before inserting marks for the stop characters we clear the whole
40 table. The unrolled form is much faster than a loop. */
41 xorl %ecx, %ecx /* %ecx = 0 !!! */
42
43 pushl %ecx /* make a 256 bytes long block filled with 0 */
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 %ecx
158 cfi_adjust_cfa_offset (4)
159 pushl $0 /* These immediate values make the label 2 */
160 cfi_adjust_cfa_offset (4)
161 pushl $0 /* to be aligned on a 16 byte boundary to */
162 cfi_adjust_cfa_offset (4)
163 pushl $0 /* get a better performance of the loop. */
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 pushl $0
170 cfi_adjust_cfa_offset (4)
171
172 /* For understanding the following code remember that %ecx == 0 now.
173 Although all the following instruction only modify %cl we always
174 have a correct zero-extended 32-bit value in %ecx. */
175
176 /* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl". We want
177 longer instructions so that the next loop aligns without adding nops. */
178
179 L(2): movb (%eax), %cl /* get byte from stopset */
180 testb %cl, %cl /* is NUL char? */
181 jz L(1) /* yes => start compare loop */
182 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
183
184 movb 1(%eax), %cl /* get byte from stopset */
185 testb $0xff, %cl /* is NUL char? */
186 jz L(1) /* yes => start compare loop */
187 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
188
189 movb 2(%eax), %cl /* get byte from stopset */
190 testb $0xff, %cl /* is NUL char? */
191 jz L(1) /* yes => start compare loop */
192 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
193
194 movb 3(%eax), %cl /* get byte from stopset */
195 addl $4, %eax /* increment stopset pointer */
196 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
197 testb $0xff, %cl /* is NUL char? */
198 jnz L(2) /* no => process next dword from stopset */
199
200 L(1): leal -4(%edx), %eax /* prepare loop */
201
202 /* We use a neat trick for the following loop. Normally we would
203 have to test for two termination conditions
204 1. a character in the stopset was found
205 and
206 2. the end of the string was found
207 But as a sign that the character is in the stopset we store its
208 value in the table. But the value of NUL is NUL so the loop
209 terminates for NUL in every case. */
210
211 L(3): addl $4, %eax /* adjust pointer for full loop round */
212
213 movb (%eax), %cl /* get byte from string */
214 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
215 jz L(4) /* no => return */
216
217 movb 1(%eax), %cl /* get byte from string */
218 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
219 jz L(5) /* no => return */
220
221 movb 2(%eax), %cl /* get byte from string */
222 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
223 jz L(6) /* no => return */
224
225 movb 3(%eax), %cl /* get byte from string */
226 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
227 jnz L(3) /* yes => start loop again */
228
229 incl %eax /* adjust pointer */
230 L(6): incl %eax
231 L(5): incl %eax
232
233 L(4): addl $256, %esp /* remove stopset */
234 cfi_adjust_cfa_offset (-256)
235 subl %edx, %eax /* we have to return the number of valid
236 characters, so compute distance to first
237 non-valid character */
238 ret
239 END (strspn)
240 libc_hidden_builtin_def (strspn)