Not needed anymore.
[kopensolaris-gnu/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-1997, 2000, 2003, 2005 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, write to the Free
21    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22    02111-1307 USA.  */
23
24 #include <sysdep.h>
25 #include "asm-syntax.h"
26 #include "bp-sym.h"
27 #include "bp-asm.h"
28
29 #define PARMS   LINKAGE         /* no space for saved regs */
30 #define STR     PARMS
31 #define SKIP    STR+PTR_SIZE
32
33         .text
34 ENTRY (BP_SYM (strspn))
35         ENTER
36
37         movl STR(%esp), %edx
38         movl SKIP(%esp), %eax
39         CHECK_BOUNDS_LOW (%edx, STR(%esp))
40
41         /* First we create a table with flags for all possible characters.
42            For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
43            supported by the C string functions we have 256 characters.
44            Before inserting marks for the stop characters we clear the whole
45            table.  The unrolled form is much faster than a loop.  */
46         xorl %ecx, %ecx         /* %ecx = 0 !!! */
47
48         pushl %ecx              /* make a 256 bytes long block filled with 0 */
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 %ecx
159         cfi_adjust_cfa_offset (4)
160         pushl %ecx
161         cfi_adjust_cfa_offset (4)
162         pushl %ecx
163         cfi_adjust_cfa_offset (4)
164         pushl $0                /* These immediate values make the label 2 */
165         cfi_adjust_cfa_offset (4)
166         pushl $0                /* to be aligned on a 16 byte boundary to */
167         cfi_adjust_cfa_offset (4)
168         pushl $0                /* get a better performance of the loop.  */
169         cfi_adjust_cfa_offset (4)
170         pushl $0
171         cfi_adjust_cfa_offset (4)
172         pushl $0
173         cfi_adjust_cfa_offset (4)
174         pushl $0
175         cfi_adjust_cfa_offset (4)
176
177 /* For understanding the following code remember that %ecx == 0 now.
178    Although all the following instruction only modify %cl we always
179    have a correct zero-extended 32-bit value in %ecx.  */
180
181 /* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl".  We want
182    longer instructions so that the next loop aligns without adding nops.  */
183
184 L(2):   movb (%eax), %cl        /* get byte from stopset */
185         testb %cl, %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 1(%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 2(%eax), %cl       /* get byte from stopset */
195         testb $0xff, %cl        /* is NUL char? */
196         jz L(1)                 /* yes => start compare loop */
197         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
198
199         movb 3(%eax), %cl       /* get byte from stopset */
200         addl $4, %eax           /* increment stopset pointer */
201         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
202         testb $0xff, %cl        /* is NUL char? */
203         jnz L(2)                /* no => process next dword from stopset */
204
205 L(1):   leal -4(%edx), %eax     /* prepare loop */
206
207         /* We use a neat trick for the following loop.  Normally we would
208            have to test for two termination conditions
209            1. a character in the stopset was found
210            and
211            2. the end of the string was found
212            But as a sign that the character is in the stopset we store its
213            value in the table.  But the value of NUL is NUL so the loop
214            terminates for NUL in every case.  */
215
216 L(3):   addl $4, %eax           /* adjust pointer for full loop round */
217
218         movb (%eax), %cl        /* get byte from string */
219         testb %cl, (%esp,%ecx)  /* is it contained in skipset? */
220         jz L(4)                 /* no => return */
221
222         movb 1(%eax), %cl       /* get byte from string */
223         testb %cl, (%esp,%ecx)  /* is it contained in skipset? */
224         jz L(5)                 /* no => return */
225
226         movb 2(%eax), %cl       /* get byte from string */
227         testb %cl, (%esp,%ecx)  /* is it contained in skipset? */
228         jz L(6)                 /* no => return */
229
230         movb 3(%eax), %cl       /* get byte from string */
231         testb %cl, (%esp,%ecx)  /* is it contained in skipset? */
232         jnz L(3)                /* yes => start loop again */
233
234         incl %eax               /* adjust pointer */
235 L(6):   incl %eax
236 L(5):   incl %eax
237
238 L(4):   addl $256, %esp         /* remove stopset */
239         cfi_adjust_cfa_offset (-256)
240         CHECK_BOUNDS_HIGH (%eax, STR(%esp), jb)
241         subl %edx, %eax         /* we have to return the number of valid
242                                    characters, so compute distance to first
243                                    non-valid character */
244         LEAVE
245         ret
246 END (BP_SYM (strspn))
247 libc_hidden_builtin_def (strspn)