]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/strspn.S
Prefer https to http for gnu.org and fsf.org URLs
[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.
04277e02 4 Copyright (C) 1994-2019 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 19 You should have received a copy of the GNU Lesser General Public
59ba27a6 20 License along with the GNU C Library; if not, see
5a82c748 21 <https://www.gnu.org/licenses/>. */
8f5ca04b
RM
22
23#include <sysdep.h>
24#include "asm-syntax.h"
25
2366713d 26#define PARMS 4 /* no space for saved regs */
3f02f778 27#define STR PARMS
2366713d 28#define SKIP STR+4
8f5ca04b
RM
29
30 .text
2366713d 31ENTRY (strspn)
3f02f778
GM
32
33 movl STR(%esp), %edx
34 movl SKIP(%esp), %eax
8f5ca04b
RM
35
36 /* First we create a table with flags for all possible characters.
37 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
38 supported by the C string functions we have 256 characters.
39 Before inserting marks for the stop characters we clear the whole
40 table. The unrolled form is much faster than a loop. */
41 xorl %ecx, %ecx /* %ecx = 0 !!! */
42
43 pushl %ecx /* make a 256 bytes long block filled with 0 */
1ad9da69 44 cfi_adjust_cfa_offset (4)
8f5ca04b 45 pushl %ecx
1ad9da69 46 cfi_adjust_cfa_offset (4)
8f5ca04b 47 pushl %ecx
1ad9da69 48 cfi_adjust_cfa_offset (4)
8f5ca04b 49 pushl %ecx
1ad9da69 50 cfi_adjust_cfa_offset (4)
8f5ca04b 51 pushl %ecx
1ad9da69 52 cfi_adjust_cfa_offset (4)
8f5ca04b 53 pushl %ecx
1ad9da69 54 cfi_adjust_cfa_offset (4)
8f5ca04b 55 pushl %ecx
1ad9da69 56 cfi_adjust_cfa_offset (4)
8f5ca04b 57 pushl %ecx
1ad9da69 58 cfi_adjust_cfa_offset (4)
8f5ca04b 59 pushl %ecx
1ad9da69 60 cfi_adjust_cfa_offset (4)
8f5ca04b 61 pushl %ecx
1ad9da69 62 cfi_adjust_cfa_offset (4)
8f5ca04b 63 pushl %ecx
1ad9da69 64 cfi_adjust_cfa_offset (4)
8f5ca04b 65 pushl %ecx
1ad9da69 66 cfi_adjust_cfa_offset (4)
8f5ca04b 67 pushl %ecx
1ad9da69 68 cfi_adjust_cfa_offset (4)
8f5ca04b 69 pushl %ecx
1ad9da69 70 cfi_adjust_cfa_offset (4)
8f5ca04b 71 pushl %ecx
1ad9da69 72 cfi_adjust_cfa_offset (4)
8f5ca04b 73 pushl %ecx
1ad9da69 74 cfi_adjust_cfa_offset (4)
8f5ca04b 75 pushl %ecx
1ad9da69 76 cfi_adjust_cfa_offset (4)
8f5ca04b 77 pushl %ecx
1ad9da69 78 cfi_adjust_cfa_offset (4)
8f5ca04b 79 pushl %ecx
1ad9da69 80 cfi_adjust_cfa_offset (4)
8f5ca04b 81 pushl %ecx
1ad9da69 82 cfi_adjust_cfa_offset (4)
8f5ca04b 83 pushl %ecx
1ad9da69 84 cfi_adjust_cfa_offset (4)
8f5ca04b 85 pushl %ecx
1ad9da69 86 cfi_adjust_cfa_offset (4)
8f5ca04b 87 pushl %ecx
1ad9da69 88 cfi_adjust_cfa_offset (4)
8f5ca04b 89 pushl %ecx
1ad9da69 90 cfi_adjust_cfa_offset (4)
8f5ca04b 91 pushl %ecx
1ad9da69 92 cfi_adjust_cfa_offset (4)
8f5ca04b 93 pushl %ecx
1ad9da69 94 cfi_adjust_cfa_offset (4)
8f5ca04b 95 pushl %ecx
1ad9da69 96 cfi_adjust_cfa_offset (4)
8f5ca04b 97 pushl %ecx
1ad9da69 98 cfi_adjust_cfa_offset (4)
8f5ca04b 99 pushl %ecx
1ad9da69 100 cfi_adjust_cfa_offset (4)
8f5ca04b 101 pushl %ecx
1ad9da69 102 cfi_adjust_cfa_offset (4)
8f5ca04b 103 pushl %ecx
1ad9da69 104 cfi_adjust_cfa_offset (4)
8f5ca04b 105 pushl %ecx
1ad9da69 106 cfi_adjust_cfa_offset (4)
8f5ca04b 107 pushl %ecx
1ad9da69 108 cfi_adjust_cfa_offset (4)
8f5ca04b 109 pushl %ecx
1ad9da69 110 cfi_adjust_cfa_offset (4)
8f5ca04b 111 pushl %ecx
1ad9da69 112 cfi_adjust_cfa_offset (4)
8f5ca04b 113 pushl %ecx
1ad9da69 114 cfi_adjust_cfa_offset (4)
8f5ca04b 115 pushl %ecx
1ad9da69 116 cfi_adjust_cfa_offset (4)
8f5ca04b 117 pushl %ecx
1ad9da69 118 cfi_adjust_cfa_offset (4)
8f5ca04b 119 pushl %ecx
1ad9da69 120 cfi_adjust_cfa_offset (4)
8f5ca04b 121 pushl %ecx
1ad9da69 122 cfi_adjust_cfa_offset (4)
8f5ca04b 123 pushl %ecx
1ad9da69 124 cfi_adjust_cfa_offset (4)
8f5ca04b 125 pushl %ecx
1ad9da69 126 cfi_adjust_cfa_offset (4)
8f5ca04b 127 pushl %ecx
1ad9da69 128 cfi_adjust_cfa_offset (4)
8f5ca04b 129 pushl %ecx
1ad9da69 130 cfi_adjust_cfa_offset (4)
8f5ca04b 131 pushl %ecx
1ad9da69 132 cfi_adjust_cfa_offset (4)
8f5ca04b 133 pushl %ecx
1ad9da69 134 cfi_adjust_cfa_offset (4)
8f5ca04b 135 pushl %ecx
1ad9da69 136 cfi_adjust_cfa_offset (4)
8f5ca04b 137 pushl %ecx
1ad9da69 138 cfi_adjust_cfa_offset (4)
8f5ca04b 139 pushl %ecx
1ad9da69 140 cfi_adjust_cfa_offset (4)
8f5ca04b 141 pushl %ecx
1ad9da69 142 cfi_adjust_cfa_offset (4)
8f5ca04b 143 pushl %ecx
1ad9da69 144 cfi_adjust_cfa_offset (4)
8f5ca04b 145 pushl %ecx
1ad9da69 146 cfi_adjust_cfa_offset (4)
8f5ca04b 147 pushl %ecx
1ad9da69 148 cfi_adjust_cfa_offset (4)
8f5ca04b 149 pushl %ecx
1ad9da69 150 cfi_adjust_cfa_offset (4)
8f5ca04b 151 pushl %ecx
1ad9da69 152 cfi_adjust_cfa_offset (4)
8f5ca04b 153 pushl %ecx
1ad9da69 154 cfi_adjust_cfa_offset (4)
8f5ca04b 155 pushl %ecx
1ad9da69 156 cfi_adjust_cfa_offset (4)
8f5ca04b 157 pushl %ecx
1ad9da69 158 cfi_adjust_cfa_offset (4)
8f5ca04b 159 pushl $0 /* These immediate values make the label 2 */
1ad9da69 160 cfi_adjust_cfa_offset (4)
8f5ca04b 161 pushl $0 /* to be aligned on a 16 byte boundary to */
1ad9da69 162 cfi_adjust_cfa_offset (4)
8f5ca04b 163 pushl $0 /* get a better performance of the loop. */
1ad9da69 164 cfi_adjust_cfa_offset (4)
8f5ca04b 165 pushl $0
1ad9da69 166 cfi_adjust_cfa_offset (4)
8f5ca04b 167 pushl $0
1ad9da69 168 cfi_adjust_cfa_offset (4)
8f5ca04b 169 pushl $0
1ad9da69 170 cfi_adjust_cfa_offset (4)
8f5ca04b
RM
171
172/* For understanding the following code remember that %ecx == 0 now.
173 Although all the following instruction only modify %cl we always
174 have a correct zero-extended 32-bit value in %ecx. */
175
176/* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl". We want
177 longer instructions so that the next loop aligns without adding nops. */
178
5929563f 179L(2): movb (%eax), %cl /* get byte from stopset */
8f5ca04b 180 testb %cl, %cl /* is NUL char? */
5929563f 181 jz L(1) /* yes => start compare loop */
8f5ca04b
RM
182 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
183
184 movb 1(%eax), %cl /* get byte from stopset */
185 testb $0xff, %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 2(%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 3(%eax), %cl /* get byte from stopset */
195 addl $4, %eax /* increment stopset pointer */
196 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
197 testb $0xff, %cl /* is NUL char? */
5929563f 198 jnz L(2) /* no => process next dword from stopset */
8f5ca04b 199
5929563f 200L(1): leal -4(%edx), %eax /* prepare loop */
8f5ca04b
RM
201
202 /* We use a neat trick for the following loop. Normally we would
203 have to test for two termination conditions
204 1. a character in the stopset was found
205 and
206 2. the end of the string was found
6d52618b 207 But as a sign that the character is in the stopset we store its
8f5ca04b
RM
208 value in the table. But the value of NUL is NUL so the loop
209 terminates for NUL in every case. */
210
5929563f 211L(3): addl $4, %eax /* adjust pointer for full loop round */
8f5ca04b
RM
212
213 movb (%eax), %cl /* get byte from string */
214 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 215 jz L(4) /* no => return */
8f5ca04b
RM
216
217 movb 1(%eax), %cl /* get byte from string */
218 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 219 jz L(5) /* no => return */
8f5ca04b
RM
220
221 movb 2(%eax), %cl /* get byte from string */
222 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 223 jz L(6) /* no => return */
8f5ca04b
RM
224
225 movb 3(%eax), %cl /* get byte from string */
226 testb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 227 jnz L(3) /* yes => start loop again */
8f5ca04b
RM
228
229 incl %eax /* adjust pointer */
5929563f
UD
230L(6): incl %eax
231L(5): incl %eax
8f5ca04b 232
2fc08826 233L(4): addl $256, %esp /* remove stopset */
1ad9da69 234 cfi_adjust_cfa_offset (-256)
2fc08826 235 subl %edx, %eax /* we have to return the number of valid
8f5ca04b
RM
236 characters, so compute distance to first
237 non-valid character */
8f5ca04b 238 ret
2366713d 239END (strspn)
85dd1003 240libc_hidden_builtin_def (strspn)