]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/strpbrk.S
2.5-18.1
[thirdparty/glibc.git] / sysdeps / i386 / strpbrk.S
CommitLineData
8f5ca04b
RM
1/* strcspn (str, ss) -- Return the length of the initial segement of STR
2 which contains no characters from SS.
5929563f 3 For Intel 80x86, x>=3.
0ecb606c 4 Copyright (C) 1994-1997, 2000, 2003, 2005 Free Software Foundation, Inc.
5929563f
UD
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.
8
9 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
5929563f
UD
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
41bdb6e2 17 Lesser General Public License for more details.
5929563f 18
41bdb6e2
AJ
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. */
8f5ca04b
RM
23
24#include <sysdep.h>
25#include "asm-syntax.h"
2fc08826 26#include "bp-sym.h"
3f02f778 27#include "bp-asm.h"
8f5ca04b 28
3f02f778
GM
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
8f5ca04b
RM
33
34 .text
2fc08826 35ENTRY (BP_SYM (strpbrk))
3f02f778
GM
36 ENTER
37
38 movl STR(%esp), %edx
39 movl STOP(%esp), %eax
2fc08826 40 CHECK_BOUNDS_LOW (%edx, STR(%esp))
8f5ca04b
RM
41
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 !!! */
48
49 pushl %ecx /* make a 256 bytes long block filled with 0 */
0ecb606c 50 cfi_adjust_cfa_offset (4)
8f5ca04b 51 pushl %ecx
0ecb606c 52 cfi_adjust_cfa_offset (4)
8f5ca04b 53 pushl %ecx
0ecb606c 54 cfi_adjust_cfa_offset (4)
8f5ca04b 55 pushl %ecx
0ecb606c 56 cfi_adjust_cfa_offset (4)
8f5ca04b 57 pushl %ecx
0ecb606c 58 cfi_adjust_cfa_offset (4)
8f5ca04b 59 pushl %ecx
0ecb606c 60 cfi_adjust_cfa_offset (4)
8f5ca04b 61 pushl %ecx
0ecb606c 62 cfi_adjust_cfa_offset (4)
8f5ca04b 63 pushl %ecx
0ecb606c 64 cfi_adjust_cfa_offset (4)
8f5ca04b 65 pushl %ecx
0ecb606c 66 cfi_adjust_cfa_offset (4)
8f5ca04b 67 pushl %ecx
0ecb606c 68 cfi_adjust_cfa_offset (4)
8f5ca04b 69 pushl %ecx
0ecb606c 70 cfi_adjust_cfa_offset (4)
8f5ca04b 71 pushl %ecx
0ecb606c 72 cfi_adjust_cfa_offset (4)
8f5ca04b 73 pushl %ecx
0ecb606c 74 cfi_adjust_cfa_offset (4)
8f5ca04b 75 pushl %ecx
0ecb606c 76 cfi_adjust_cfa_offset (4)
8f5ca04b 77 pushl %ecx
0ecb606c 78 cfi_adjust_cfa_offset (4)
8f5ca04b 79 pushl %ecx
0ecb606c 80 cfi_adjust_cfa_offset (4)
8f5ca04b 81 pushl %ecx
0ecb606c 82 cfi_adjust_cfa_offset (4)
8f5ca04b 83 pushl %ecx
0ecb606c 84 cfi_adjust_cfa_offset (4)
8f5ca04b 85 pushl %ecx
0ecb606c 86 cfi_adjust_cfa_offset (4)
8f5ca04b 87 pushl %ecx
0ecb606c 88 cfi_adjust_cfa_offset (4)
8f5ca04b 89 pushl %ecx
0ecb606c 90 cfi_adjust_cfa_offset (4)
8f5ca04b 91 pushl %ecx
0ecb606c 92 cfi_adjust_cfa_offset (4)
8f5ca04b 93 pushl %ecx
0ecb606c 94 cfi_adjust_cfa_offset (4)
8f5ca04b 95 pushl %ecx
0ecb606c 96 cfi_adjust_cfa_offset (4)
8f5ca04b 97 pushl %ecx
0ecb606c 98 cfi_adjust_cfa_offset (4)
8f5ca04b 99 pushl %ecx
0ecb606c 100 cfi_adjust_cfa_offset (4)
8f5ca04b 101 pushl %ecx
0ecb606c 102 cfi_adjust_cfa_offset (4)
8f5ca04b 103 pushl %ecx
0ecb606c 104 cfi_adjust_cfa_offset (4)
8f5ca04b 105 pushl %ecx
0ecb606c 106 cfi_adjust_cfa_offset (4)
8f5ca04b 107 pushl %ecx
0ecb606c 108 cfi_adjust_cfa_offset (4)
8f5ca04b 109 pushl %ecx
0ecb606c 110 cfi_adjust_cfa_offset (4)
8f5ca04b 111 pushl %ecx
0ecb606c 112 cfi_adjust_cfa_offset (4)
8f5ca04b 113 pushl %ecx
0ecb606c 114 cfi_adjust_cfa_offset (4)
8f5ca04b 115 pushl %ecx
0ecb606c 116 cfi_adjust_cfa_offset (4)
8f5ca04b 117 pushl %ecx
0ecb606c 118 cfi_adjust_cfa_offset (4)
8f5ca04b 119 pushl %ecx
0ecb606c 120 cfi_adjust_cfa_offset (4)
8f5ca04b 121 pushl %ecx
0ecb606c 122 cfi_adjust_cfa_offset (4)
8f5ca04b 123 pushl %ecx
0ecb606c 124 cfi_adjust_cfa_offset (4)
8f5ca04b 125 pushl %ecx
0ecb606c 126 cfi_adjust_cfa_offset (4)
8f5ca04b 127 pushl %ecx
0ecb606c 128 cfi_adjust_cfa_offset (4)
8f5ca04b 129 pushl %ecx
0ecb606c 130 cfi_adjust_cfa_offset (4)
8f5ca04b 131 pushl %ecx
0ecb606c 132 cfi_adjust_cfa_offset (4)
8f5ca04b 133 pushl %ecx
0ecb606c 134 cfi_adjust_cfa_offset (4)
8f5ca04b 135 pushl %ecx
0ecb606c 136 cfi_adjust_cfa_offset (4)
8f5ca04b 137 pushl %ecx
0ecb606c 138 cfi_adjust_cfa_offset (4)
8f5ca04b 139 pushl %ecx
0ecb606c 140 cfi_adjust_cfa_offset (4)
8f5ca04b 141 pushl %ecx
0ecb606c 142 cfi_adjust_cfa_offset (4)
8f5ca04b 143 pushl %ecx
0ecb606c 144 cfi_adjust_cfa_offset (4)
8f5ca04b 145 pushl %ecx
0ecb606c 146 cfi_adjust_cfa_offset (4)
8f5ca04b 147 pushl %ecx
0ecb606c 148 cfi_adjust_cfa_offset (4)
8f5ca04b 149 pushl %ecx
0ecb606c 150 cfi_adjust_cfa_offset (4)
8f5ca04b 151 pushl %ecx
0ecb606c 152 cfi_adjust_cfa_offset (4)
8f5ca04b 153 pushl %ecx
0ecb606c 154 cfi_adjust_cfa_offset (4)
8f5ca04b 155 pushl %ecx
0ecb606c 156 cfi_adjust_cfa_offset (4)
8f5ca04b 157 pushl %ecx
0ecb606c 158 cfi_adjust_cfa_offset (4)
8f5ca04b 159 pushl %ecx
0ecb606c 160 cfi_adjust_cfa_offset (4)
8f5ca04b 161 pushl %ecx
0ecb606c 162 cfi_adjust_cfa_offset (4)
8f5ca04b 163 pushl %ecx
0ecb606c 164 cfi_adjust_cfa_offset (4)
8f5ca04b 165 pushl $0 /* These immediate values make the label 2 */
0ecb606c 166 cfi_adjust_cfa_offset (4)
8f5ca04b 167 pushl $0 /* to be aligned on a 16 byte boundary to */
0ecb606c 168 cfi_adjust_cfa_offset (4)
8f5ca04b 169 pushl $0 /* get a better performance of the loop. */
0ecb606c 170 cfi_adjust_cfa_offset (4)
8f5ca04b 171 pushl $0
0ecb606c 172 cfi_adjust_cfa_offset (4)
8f5ca04b 173 pushl $0
0ecb606c 174 cfi_adjust_cfa_offset (4)
8f5ca04b 175 pushl $0
0ecb606c 176 cfi_adjust_cfa_offset (4)
8f5ca04b
RM
177
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. */
181
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. */
184
5929563f 185L(2): movb (%eax), %cl /* get byte from stopset */
8f5ca04b 186 testb %cl, %cl /* is NUL char? */
5929563f 187 jz L(1) /* yes => start compare loop */
8f5ca04b
RM
188 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
189
190 movb 1(%eax), %cl /* get byte from stopset */
191 testb $0xff, %cl /* is NUL char? */
5929563f 192 jz L(1) /* yes => start compare loop */
8f5ca04b
RM
193 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
194
195 movb 2(%eax), %cl /* get byte from stopset */
196 testb $0xff, %cl /* is NUL char? */
5929563f 197 jz L(1) /* yes => start compare loop */
8f5ca04b
RM
198 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
199
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? */
5929563f 204 jnz L(2) /* no => process next dword from stopset */
8f5ca04b 205
5929563f 206L(1): leal -4(%edx), %eax /* prepare loop */
8f5ca04b
RM
207
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. */
216
5929563f 217L(3): addl $4, %eax /* adjust pointer for full loop round */
8f5ca04b
RM
218
219 movb (%eax), %cl /* get byte from string */
220 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 221 je L(4) /* yes => return */
8f5ca04b
RM
222
223 movb 1(%eax), %cl /* get byte from string */
224 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 225 je L(5) /* yes => return */
8f5ca04b
RM
226
227 movb 2(%eax), %cl /* get byte from string */
228 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 229 je L(6) /* yes => return */
8f5ca04b
RM
230
231 movb 3(%eax), %cl /* get byte from string */
232 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 233 jne L(3) /* yes => return */
8f5ca04b
RM
234
235 incl %eax /* adjust pointer */
5929563f
UD
236L(6): incl %eax
237L(5): incl %eax
8f5ca04b 238
5929563f 239L(4): addl $256, %esp /* remove stopset */
0ecb606c 240 cfi_adjust_cfa_offset (-256)
8f5ca04b 241
2fc08826 242 CHECK_BOUNDS_HIGH (%eax, STR(%esp), jb)
8f5ca04b 243 orb %cl, %cl /* was last character NUL? */
2fc08826
GM
244 jnz L(7) /* no => return pointer */
245 xorl %eax, %eax
246 RETURN_NULL_BOUNDED_POINTER
8f5ca04b 247
2fc08826 248 LEAVE
3f02f778 249 RET_PTR
2fc08826
GM
250
251L(7): RETURN_BOUNDED_POINTER (STR(%esp))
252
253 LEAVE
254 RET_PTR
255END (BP_SYM (strpbrk))
85dd1003 256libc_hidden_builtin_def (strpbrk)