.
[glibc/pb-stable.git] / sysdeps / i386 / strpbrk.S
blob1f78e206465720a3a3a87c252b7807f4c3aa7b9a
1 /* strcspn (str, ss) -- Return the length of the initial segement of STR
2                         which contains no characters from SS.
3    For Intel 80x86, x>=3.
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
22    02111-1307 USA.  */
24 #include <sysdep.h>
25 #include "asm-syntax.h"
26 #include "bp-sym.h"
27 #include "bp-asm.h"
29 #define PARMS   LINKAGE         /* no space for saved regs */
30 #define RTN     PARMS
31 #define STR     RTN+RTN_SIZE
32 #define STOP    STR+PTR_SIZE
34         .text
35 ENTRY (BP_SYM (strpbrk))
36         ENTER
38         movl STR(%esp), %edx
39         movl STOP(%esp), %eax
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)
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 %ecx
160         cfi_adjust_cfa_offset (4)
161         pushl %ecx
162         cfi_adjust_cfa_offset (4)
163         pushl %ecx
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)
171         pushl $0
172         cfi_adjust_cfa_offset (4)
173         pushl $0
174         cfi_adjust_cfa_offset (4)
175         pushl $0
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
211            and
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 */
236 L(6):   incl %eax
237 L(5):   incl %eax
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 */
245         xorl %eax, %eax
246         RETURN_NULL_BOUNDED_POINTER
248         LEAVE
249         RET_PTR
251 L(7):   RETURN_BOUNDED_POINTER (STR(%esp))
253         LEAVE
254         RET_PTR
255 END (BP_SYM (strpbrk))
256 libc_hidden_builtin_def (strpbrk)