]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/i386/strspn.S
1a02026285adcd05f9d2c92e76caf24a775f76e6
[thirdparty/glibc.git] / sysdeps / i386 / strspn.S
1 /* strcspn (str, ss) -- Return the length of the initial segement of STR
2 which contains only characters from SS.
3 For Intel 80x86, x>=3.
4 Copyright (C) 1994, 1995 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.
8
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.
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 Library General Public License for more details.
18
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
21 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 #include <sysdep.h>
25 #include "asm-syntax.h"
26
27 /*
28 INPUT PARAMETERS:
29 str (sp + 4)
30 skipset (sp + 8)
31 */
32
33 .text
34 ENTRY (strspn)
35 movl 4(%esp), %edx /* get string pointer */
36 movl 8(%esp), %eax /* get skipset pointer */
37
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 !!! */
44
45 pushl %ecx /* make a 256 bytes long block filled with 0 */
46 pushl %ecx
47 pushl %ecx
48 pushl %ecx
49 pushl %ecx
50 pushl %ecx
51 pushl %ecx
52 pushl %ecx
53 pushl %ecx
54 pushl %ecx
55 pushl %ecx
56 pushl %ecx
57 pushl %ecx
58 pushl %ecx
59 pushl %ecx
60 pushl %ecx
61 pushl %ecx
62 pushl %ecx
63 pushl %ecx
64 pushl %ecx
65 pushl %ecx
66 pushl %ecx
67 pushl %ecx
68 pushl %ecx
69 pushl %ecx
70 pushl %ecx
71 pushl %ecx
72 pushl %ecx
73 pushl %ecx
74 pushl %ecx
75 pushl %ecx
76 pushl %ecx
77 pushl %ecx
78 pushl %ecx
79 pushl %ecx
80 pushl %ecx
81 pushl %ecx
82 pushl %ecx
83 pushl %ecx
84 pushl %ecx
85 pushl %ecx
86 pushl %ecx
87 pushl %ecx
88 pushl %ecx
89 pushl %ecx
90 pushl %ecx
91 pushl %ecx
92 pushl %ecx
93 pushl %ecx
94 pushl %ecx
95 pushl %ecx
96 pushl %ecx
97 pushl %ecx
98 pushl %ecx
99 pushl %ecx
100 pushl %ecx
101 pushl %ecx
102 pushl %ecx
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. */
106 pushl $0
107 pushl $0
108 pushl $0
109
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. */
113
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. */
116
117 L2: movb (%eax), %cl /* get byte from stopset */
118 testb %cl, %cl /* is NUL char? */
119 jz L1 /* yes => start compare loop */
120 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
121
122 movb 1(%eax), %cl /* get byte from stopset */
123 testb $0xff, %cl /* is NUL char? */
124 jz L1 /* yes => start compare loop */
125 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
126
127 movb 2(%eax), %cl /* get byte from stopset */
128 testb $0xff, %cl /* is NUL char? */
129 jz L1 /* yes => start compare loop */
130 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
131
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 L2 /* no => process next dword from stopset */
137
138 L1: leal -4(%edx), %eax /* prepare loop */
139
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
143 and
144 2. the end of the string was found
145 But as a sign that the chracter 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. */
148
149 L3: addl $4, %eax /* adjust pointer for full loop round */
150
151 movb (%eax), %cl /* get byte from string */
152 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
153 jz L4 /* no => return */
154
155 movb 1(%eax), %cl /* get byte from string */
156 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
157 jz L5 /* no => return */
158
159 movb 2(%eax), %cl /* get byte from string */
160 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
161 jz L6 /* no => return */
162
163 movb 3(%eax), %cl /* get byte from string */
164 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
165 jnz L3 /* yes => start loop again */
166
167 incl %eax /* adjust pointer */
168 L6: incl %eax
169 L5: incl %eax
170
171 L4: 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 */
175
176 ret