1 /* strcspn (str, ss) -- Return the length of the initial segment of STR
2 which contains no characters from SS.
4 Copyright (C) 1994, 1995, 1996, 1997 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>
9 The GNU C Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 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 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with the GNU C Library; see the file COPYING.LIB. If not,
21 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
25 #include "asm-syntax.h"
35 movl 4(%esp), %edx /* get string pointer */
36 movl 8(%esp), %eax /* get stopset pointer */
38 /* First we create a table with flags for all possible characters.
39 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
40 supported by the C string functions we have 256 characters.
41 Before inserting marks for the stop characters we clear the whole
42 table. The unrolled form is much faster than a loop. */
43 xorl %ecx, %ecx /* %ecx = 0 !!! */
45 pushl %ecx /* make a 256 bytes long block filled with 0 */
103 pushl $0 /* These immediate values make the label 2 */
104 pushl $0 /* to be aligned on a 16 byte boundary to */
105 pushl $0 /* get a better performance of the loop. */
110 /* For understanding the following code remember that %ecx == 0 now.
111 Although all the following instruction only modify %cl we always
112 have a correct zero-extended 32-bit value in %ecx. */
114 /* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl". We want
115 longer instructions so that the next loop aligns without adding nops. */
117 L(2): movb (%eax), %cl /* get byte from stopset */
118 testb %cl, %cl /* is NUL char? */
119 jz L(1) /* yes => start compare loop */
120 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
122 movb 1(%eax), %cl /* get byte from stopset */
123 testb $0xff, %cl /* is NUL char? */
124 jz L(1) /* yes => start compare loop */
125 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
127 movb 2(%eax), %cl /* get byte from stopset */
128 testb $0xff, %cl /* is NUL char? */
129 jz L(1) /* yes => start compare loop */
130 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
132 movb 3(%eax), %cl /* get byte from stopset */
133 addl $4, %eax /* increment stopset pointer */
134 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
135 testb $0xff, %cl /* is NUL char? */
136 jnz L(2) /* no => process next dword from stopset */
138 L(1): leal -4(%edx), %eax /* prepare loop */
140 /* We use a neat trick for the following loop. Normally we would
141 have to test for two termination conditions
142 1. a character in the stopset was found
144 2. the end of the string was found
145 But as a sign that the character is in the stopset we store its
146 value in the table. But the value of NUL is NUL so the loop
147 terminates for NUL in every case. */
149 L(3): addl $4, %eax /* adjust pointer for full loop round */
151 movb (%eax), %cl /* get byte from string */
152 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
153 je L(4) /* yes => return */
155 movb 1(%eax), %cl /* get byte from string */
156 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
157 je L(5) /* yes => return */
159 movb 2(%eax), %cl /* get byte from string */
160 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
161 je L(6) /* yes => return */
163 movb 3(%eax), %cl /* get byte from string */
164 cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
165 jne L(3) /* yes => return */
167 incl %eax /* adjust pointer */
171 L(4): subl %edx, %eax /* we have to return the number of valid
172 characters, so compute distance to first
173 non-valid character */
174 addl $256, %esp /* remove stopset */