]>
Commit | Line | Data |
---|---|---|
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. |
a334319f | 4 | Copyright (C) 1994-1997, 2000, 2003 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 | 35 | ENTRY (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 */ | |
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 %ecx | |
104 | pushl %ecx | |
105 | pushl %ecx | |
106 | pushl %ecx | |
107 | pushl $0 /* These immediate values make the label 2 */ | |
108 | pushl $0 /* to be aligned on a 16 byte boundary to */ | |
109 | pushl $0 /* get a better performance of the loop. */ | |
110 | pushl $0 | |
111 | pushl $0 | |
112 | pushl $0 | |
113 | ||
114 | /* For understanding the following code remember that %ecx == 0 now. | |
115 | Although all the following instruction only modify %cl we always | |
116 | have a correct zero-extended 32-bit value in %ecx. */ | |
117 | ||
118 | /* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl". We want | |
119 | longer instructions so that the next loop aligns without adding nops. */ | |
120 | ||
5929563f | 121 | L(2): movb (%eax), %cl /* get byte from stopset */ |
8f5ca04b | 122 | testb %cl, %cl /* is NUL char? */ |
5929563f | 123 | jz L(1) /* yes => start compare loop */ |
8f5ca04b RM |
124 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
125 | ||
126 | movb 1(%eax), %cl /* get byte from stopset */ | |
127 | testb $0xff, %cl /* is NUL char? */ | |
5929563f | 128 | jz L(1) /* yes => start compare loop */ |
8f5ca04b RM |
129 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
130 | ||
131 | movb 2(%eax), %cl /* get byte from stopset */ | |
132 | testb $0xff, %cl /* is NUL char? */ | |
5929563f | 133 | jz L(1) /* yes => start compare loop */ |
8f5ca04b RM |
134 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
135 | ||
136 | movb 3(%eax), %cl /* get byte from stopset */ | |
137 | addl $4, %eax /* increment stopset pointer */ | |
138 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
139 | testb $0xff, %cl /* is NUL char? */ | |
5929563f | 140 | jnz L(2) /* no => process next dword from stopset */ |
8f5ca04b | 141 | |
5929563f | 142 | L(1): leal -4(%edx), %eax /* prepare loop */ |
8f5ca04b RM |
143 | |
144 | /* We use a neat trick for the following loop. Normally we would | |
145 | have to test for two termination conditions | |
146 | 1. a character in the stopset was found | |
147 | and | |
148 | 2. the end of the string was found | |
149 | But as a sign that the chracter is in the stopset we store its | |
150 | value in the table. But the value of NUL is NUL so the loop | |
151 | terminates for NUL in every case. */ | |
152 | ||
5929563f | 153 | L(3): addl $4, %eax /* adjust pointer for full loop round */ |
8f5ca04b RM |
154 | |
155 | movb (%eax), %cl /* get byte from string */ | |
156 | cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
5929563f | 157 | je L(4) /* yes => return */ |
8f5ca04b RM |
158 | |
159 | movb 1(%eax), %cl /* get byte from string */ | |
160 | cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
5929563f | 161 | je L(5) /* yes => return */ |
8f5ca04b RM |
162 | |
163 | movb 2(%eax), %cl /* get byte from string */ | |
164 | cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
5929563f | 165 | je L(6) /* yes => return */ |
8f5ca04b RM |
166 | |
167 | movb 3(%eax), %cl /* get byte from string */ | |
168 | cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
5929563f | 169 | jne L(3) /* yes => return */ |
8f5ca04b RM |
170 | |
171 | incl %eax /* adjust pointer */ | |
5929563f UD |
172 | L(6): incl %eax |
173 | L(5): incl %eax | |
8f5ca04b | 174 | |
5929563f | 175 | L(4): addl $256, %esp /* remove stopset */ |
8f5ca04b | 176 | |
2fc08826 | 177 | CHECK_BOUNDS_HIGH (%eax, STR(%esp), jb) |
8f5ca04b | 178 | orb %cl, %cl /* was last character NUL? */ |
2fc08826 GM |
179 | jnz L(7) /* no => return pointer */ |
180 | xorl %eax, %eax | |
181 | RETURN_NULL_BOUNDED_POINTER | |
8f5ca04b | 182 | |
2fc08826 | 183 | LEAVE |
3f02f778 | 184 | RET_PTR |
2fc08826 GM |
185 | |
186 | L(7): RETURN_BOUNDED_POINTER (STR(%esp)) | |
187 | ||
188 | LEAVE | |
189 | RET_PTR | |
190 | END (BP_SYM (strpbrk)) | |
85dd1003 | 191 | libc_hidden_builtin_def (strpbrk) |