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