]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/strspn.S
2.5-18.1
[thirdparty/glibc.git] / sysdeps / i386 / strspn.S
CommitLineData
6d52618b 1/* strcspn (str, ss) -- Return the length of the initial segment of STR
8f5ca04b 2 which contains only characters from SS.
6d52618b 3 For Intel 80x86, x>=3.
0ecb606c 4 Copyright (C) 1994-1997, 2000, 2003, 2005 Free Software Foundation, Inc.
6d52618b
UD
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
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.
6d52618b
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.
6d52618b 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 STR PARMS
31#define SKIP STR+PTR_SIZE
8f5ca04b
RM
32
33 .text
2fc08826 34ENTRY (BP_SYM (strspn))
3f02f778
GM
35 ENTER
36
37 movl STR(%esp), %edx
38 movl SKIP(%esp), %eax
2fc08826 39 CHECK_BOUNDS_LOW (%edx, STR(%esp))
8f5ca04b
RM
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 */
0ecb606c 49 cfi_adjust_cfa_offset (4)
8f5ca04b 50 pushl %ecx
0ecb606c 51 cfi_adjust_cfa_offset (4)
8f5ca04b 52 pushl %ecx
0ecb606c 53 cfi_adjust_cfa_offset (4)
8f5ca04b 54 pushl %ecx
0ecb606c 55 cfi_adjust_cfa_offset (4)
8f5ca04b 56 pushl %ecx
0ecb606c 57 cfi_adjust_cfa_offset (4)
8f5ca04b 58 pushl %ecx
0ecb606c 59 cfi_adjust_cfa_offset (4)
8f5ca04b 60 pushl %ecx
0ecb606c 61 cfi_adjust_cfa_offset (4)
8f5ca04b 62 pushl %ecx
0ecb606c 63 cfi_adjust_cfa_offset (4)
8f5ca04b 64 pushl %ecx
0ecb606c 65 cfi_adjust_cfa_offset (4)
8f5ca04b 66 pushl %ecx
0ecb606c 67 cfi_adjust_cfa_offset (4)
8f5ca04b 68 pushl %ecx
0ecb606c 69 cfi_adjust_cfa_offset (4)
8f5ca04b 70 pushl %ecx
0ecb606c 71 cfi_adjust_cfa_offset (4)
8f5ca04b 72 pushl %ecx
0ecb606c 73 cfi_adjust_cfa_offset (4)
8f5ca04b 74 pushl %ecx
0ecb606c 75 cfi_adjust_cfa_offset (4)
8f5ca04b 76 pushl %ecx
0ecb606c 77 cfi_adjust_cfa_offset (4)
8f5ca04b 78 pushl %ecx
0ecb606c 79 cfi_adjust_cfa_offset (4)
8f5ca04b 80 pushl %ecx
0ecb606c 81 cfi_adjust_cfa_offset (4)
8f5ca04b 82 pushl %ecx
0ecb606c 83 cfi_adjust_cfa_offset (4)
8f5ca04b 84 pushl %ecx
0ecb606c 85 cfi_adjust_cfa_offset (4)
8f5ca04b 86 pushl %ecx
0ecb606c 87 cfi_adjust_cfa_offset (4)
8f5ca04b 88 pushl %ecx
0ecb606c 89 cfi_adjust_cfa_offset (4)
8f5ca04b 90 pushl %ecx
0ecb606c 91 cfi_adjust_cfa_offset (4)
8f5ca04b 92 pushl %ecx
0ecb606c 93 cfi_adjust_cfa_offset (4)
8f5ca04b 94 pushl %ecx
0ecb606c 95 cfi_adjust_cfa_offset (4)
8f5ca04b 96 pushl %ecx
0ecb606c 97 cfi_adjust_cfa_offset (4)
8f5ca04b 98 pushl %ecx
0ecb606c 99 cfi_adjust_cfa_offset (4)
8f5ca04b 100 pushl %ecx
0ecb606c 101 cfi_adjust_cfa_offset (4)
8f5ca04b 102 pushl %ecx
0ecb606c 103 cfi_adjust_cfa_offset (4)
8f5ca04b 104 pushl %ecx
0ecb606c 105 cfi_adjust_cfa_offset (4)
8f5ca04b 106 pushl %ecx
0ecb606c 107 cfi_adjust_cfa_offset (4)
8f5ca04b 108 pushl %ecx
0ecb606c 109 cfi_adjust_cfa_offset (4)
8f5ca04b 110 pushl %ecx
0ecb606c 111 cfi_adjust_cfa_offset (4)
8f5ca04b 112 pushl %ecx
0ecb606c 113 cfi_adjust_cfa_offset (4)
8f5ca04b 114 pushl %ecx
0ecb606c 115 cfi_adjust_cfa_offset (4)
8f5ca04b 116 pushl %ecx
0ecb606c 117 cfi_adjust_cfa_offset (4)
8f5ca04b 118 pushl %ecx
0ecb606c 119 cfi_adjust_cfa_offset (4)
8f5ca04b 120 pushl %ecx
0ecb606c 121 cfi_adjust_cfa_offset (4)
8f5ca04b 122 pushl %ecx
0ecb606c 123 cfi_adjust_cfa_offset (4)
8f5ca04b 124 pushl %ecx
0ecb606c 125 cfi_adjust_cfa_offset (4)
8f5ca04b 126 pushl %ecx
0ecb606c 127 cfi_adjust_cfa_offset (4)
8f5ca04b 128 pushl %ecx
0ecb606c 129 cfi_adjust_cfa_offset (4)
8f5ca04b 130 pushl %ecx
0ecb606c 131 cfi_adjust_cfa_offset (4)
8f5ca04b 132 pushl %ecx
0ecb606c 133 cfi_adjust_cfa_offset (4)
8f5ca04b 134 pushl %ecx
0ecb606c 135 cfi_adjust_cfa_offset (4)
8f5ca04b 136 pushl %ecx
0ecb606c 137 cfi_adjust_cfa_offset (4)
8f5ca04b 138 pushl %ecx
0ecb606c 139 cfi_adjust_cfa_offset (4)
8f5ca04b 140 pushl %ecx
0ecb606c 141 cfi_adjust_cfa_offset (4)
8f5ca04b 142 pushl %ecx
0ecb606c 143 cfi_adjust_cfa_offset (4)
8f5ca04b 144 pushl %ecx
0ecb606c 145 cfi_adjust_cfa_offset (4)
8f5ca04b 146 pushl %ecx
0ecb606c 147 cfi_adjust_cfa_offset (4)
8f5ca04b 148 pushl %ecx
0ecb606c 149 cfi_adjust_cfa_offset (4)
8f5ca04b 150 pushl %ecx
0ecb606c 151 cfi_adjust_cfa_offset (4)
8f5ca04b 152 pushl %ecx
0ecb606c 153 cfi_adjust_cfa_offset (4)
8f5ca04b 154 pushl %ecx
0ecb606c 155 cfi_adjust_cfa_offset (4)
8f5ca04b 156 pushl %ecx
0ecb606c 157 cfi_adjust_cfa_offset (4)
8f5ca04b 158 pushl %ecx
0ecb606c 159 cfi_adjust_cfa_offset (4)
8f5ca04b 160 pushl %ecx
0ecb606c 161 cfi_adjust_cfa_offset (4)
8f5ca04b 162 pushl %ecx
0ecb606c 163 cfi_adjust_cfa_offset (4)
8f5ca04b 164 pushl $0 /* These immediate values make the label 2 */
0ecb606c 165 cfi_adjust_cfa_offset (4)
8f5ca04b 166 pushl $0 /* to be aligned on a 16 byte boundary to */
0ecb606c 167 cfi_adjust_cfa_offset (4)
8f5ca04b 168 pushl $0 /* get a better performance of the loop. */
0ecb606c 169 cfi_adjust_cfa_offset (4)
8f5ca04b 170 pushl $0
0ecb606c 171 cfi_adjust_cfa_offset (4)
8f5ca04b 172 pushl $0
0ecb606c 173 cfi_adjust_cfa_offset (4)
8f5ca04b 174 pushl $0
0ecb606c 175 cfi_adjust_cfa_offset (4)
8f5ca04b
RM
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
5929563f 184L(2): movb (%eax), %cl /* get byte from stopset */
8f5ca04b 185 testb %cl, %cl /* is NUL char? */
5929563f 186 jz L(1) /* yes => start compare loop */
8f5ca04b
RM
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? */
5929563f 191 jz L(1) /* yes => start compare loop */
8f5ca04b
RM
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? */
5929563f 196 jz L(1) /* yes => start compare loop */
8f5ca04b
RM
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? */
5929563f 203 jnz L(2) /* no => process next dword from stopset */
8f5ca04b 204
5929563f 205L(1): leal -4(%edx), %eax /* prepare loop */
8f5ca04b
RM
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
6d52618b 212 But as a sign that the character is in the stopset we store its
8f5ca04b
RM
213 value in the table. But the value of NUL is NUL so the loop
214 terminates for NUL in every case. */
215
5929563f 216L(3): addl $4, %eax /* adjust pointer for full loop round */
8f5ca04b
RM
217
218 movb (%eax), %cl /* get byte from string */
219 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 220 jz L(4) /* no => return */
8f5ca04b
RM
221
222 movb 1(%eax), %cl /* get byte from string */
223 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 224 jz L(5) /* no => return */
8f5ca04b
RM
225
226 movb 2(%eax), %cl /* get byte from string */
227 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 228 jz L(6) /* no => return */
8f5ca04b
RM
229
230 movb 3(%eax), %cl /* get byte from string */
231 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 232 jnz L(3) /* yes => start loop again */
8f5ca04b
RM
233
234 incl %eax /* adjust pointer */
5929563f
UD
235L(6): incl %eax
236L(5): incl %eax
8f5ca04b 237
2fc08826 238L(4): addl $256, %esp /* remove stopset */
0ecb606c 239 cfi_adjust_cfa_offset (-256)
2fc08826
GM
240 CHECK_BOUNDS_HIGH (%eax, STR(%esp), jb)
241 subl %edx, %eax /* we have to return the number of valid
8f5ca04b
RM
242 characters, so compute distance to first
243 non-valid character */
3f02f778 244 LEAVE
8f5ca04b 245 ret
2fc08826 246END (BP_SYM (strspn))
85dd1003 247libc_hidden_builtin_def (strspn)