Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / i386 / i686 / strtok.S
blob3cfc008b5938af60ee11e15188d8f9be6b139b78
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2    For Intel 80686.
3    Copyright (C) 1998-2015 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, see
19    <http://www.gnu.org/licenses/>.  */
21 #include <sysdep.h>
22 #include "asm-syntax.h"
24 /* This file can be used for three variants of the strtok function:
26    strtok:
27         INPUT PARAMETER:
28         str             (sp + 4)
29         delim           (sp + 8)
31    strtok_r:
32         INPUT PARAMETER:
33         str             (sp + 4)
34         delim           (sp + 8)
35         save_ptr        (sp + 12)
37    We do a common implementation here.  */
39 #ifdef USE_AS_STRTOK_R
40 # define SAVE_PTR 0(%ecx)
41 #else
42         .bss
43         .local save_ptr
44         .type save_ptr, @object
45         .size save_ptr, 4
46 save_ptr:
47         .space 4
49 # ifdef PIC
50 #  define SAVE_PTR save_ptr@GOTOFF(%ebx)
51 # else
52 #  define SAVE_PTR save_ptr
53 # endif
55 # define FUNCTION strtok
56 #endif
58 #if !defined USE_AS_STRTOK_R && defined PIC
59 # define PARMS  4+256+4 /* space for table and saved PIC register */
60 #else
61 # define PARMS  4+256   /* space for table */
62 #endif
63 #define RTN     PARMS
64 #define STR     RTN
65 #define DELIM   STR+4
66 #ifdef USE_AS_STRTOK_R
67 # define SAVE   DELIM+4
68 #endif
70         .text
72 #if !defined USE_AS_STRTOK_R && defined PIC
73 0:      movl (%esp), %ebx
74         ret
75 #endif
77 ENTRY (FUNCTION)
79 #if !defined USE_AS_STRTOK_R && defined PIC
80         pushl %ebx                      /* Save PIC register.  */
81         cfi_adjust_cfa_offset (4)
82         cfi_rel_offset (ebx, 0)
83         call 0b
84         addl $_GLOBAL_OFFSET_TABLE_, %ebx
85 #endif
87         /* First we create a table with flags for all possible characters.
88            For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
89            supported by the C string functions we have 256 characters.
90            Before inserting marks for the stop characters we clear the whole
91            table.  */
92         movl %edi, %edx
93         subl $256, %esp
94         cfi_adjust_cfa_offset (256)
95         movl $64, %ecx
96         movl %esp, %edi
97         xorl %eax, %eax
98         cld
99         rep
100         stosl
102         /* Note: %ecx = 0 !!! */
103         movl %edx, %edi
105         movl STR(%esp), %edx            /* Get start of string.  */
107 #ifdef USE_AS_STRTOK_R
108         /* The value is stored in the third argument.  */
109         movl SAVE(%esp), %eax
110         movl (%eax), %eax
111 #else
112         /* The value is in the local variable defined above.  But
113            we have to take care for PIC code.  */
114         movl SAVE_PTR, %eax
115 #endif
117         /* If the pointer is NULL we have to use the stored value of
118            the last run.  */
119         cmpl $0, %edx
120         cmove %eax, %edx
121         testl %edx, %edx
122         jz L(returnNULL)
123         movl DELIM(%esp), %eax          /* Get start of delimiter set.  */
125 /* For understanding the following code remember that %ecx == 0 now.
126    Although all the following instruction only modify %cl we always
127    have a correct zero-extended 32-bit value in %ecx.  */
129 L(2):   movb (%eax), %cl        /* get byte from stopset */
130         testb %cl, %cl          /* is NUL char? */
131         jz L(1)                 /* yes => start compare loop */
132         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
134         movb 1(%eax), %cl       /* get byte from stopset */
135         testb $0xff, %cl        /* is NUL char? */
136         jz L(1)                 /* yes => start compare loop */
137         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
139         movb 2(%eax), %cl       /* get byte from stopset */
140         testb $0xff, %cl        /* is NUL char? */
141         jz L(1)                 /* yes => start compare loop */
142         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
144         movb 3(%eax), %cl       /* get byte from stopset */
145         addl $4, %eax           /* increment stopset pointer */
146         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
147         testb $0xff, %cl        /* is NUL char? */
148         jnz L(2)                /* no => process next dword from stopset */
150 L(1):   leal -4(%edx), %eax     /* prepare loop */
152         /* We use a neat trick for the following loop.  Normally we would
153            have to test for two termination conditions
154            1. a character in the stopset was found
155            and
156            2. the end of the string was found
157            As a sign that the character is in the stopset we store its
158            value in the table.  The value of NUL is NUL so the loop
159            terminates for NUL in every case.  */
161 L(3):   addl $4, %eax           /* adjust pointer for full loop round */
163         movb (%eax), %cl        /* get byte from string */
164         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
165         jz L(4)                 /* no => start of token */
167         movb 1(%eax), %cl       /* get byte from string */
168         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
169         jz L(5)                 /* no => start of token */
171         movb 2(%eax), %cl       /* get byte from string */
172         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
173         jz L(6)                 /* no => start of token */
175         movb 3(%eax), %cl       /* get byte from string */
176         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
177         jnz L(3)                /* yes => start of loop */
179         incl %eax               /* adjust pointer */
180 L(6):   incl %eax
181 L(5):   incl %eax
183         /* Now we have to terminate the string.  */
185 L(4):   leal -4(%eax), %edx     /* We use %EDX for the next run.  */
187 L(7):   addl $4, %edx           /* adjust pointer for full loop round */
189         movb (%edx), %cl        /* get byte from string */
190         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
191         je L(8)                 /* yes => return */
193         movb 1(%edx), %cl       /* get byte from string */
194         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
195         je L(9)                 /* yes => return */
197         movb 2(%edx), %cl       /* get byte from string */
198         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
199         je L(10)                /* yes => return */
201         movb 3(%edx), %cl       /* get byte from string */
202         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
203         jne L(7)                /* no => start loop again */
205         incl %edx               /* adjust pointer */
206 L(10):  incl %edx
207 L(9):   incl %edx
209 L(8):   cmpl %eax, %edx
210         je L(returnNULL)        /* There was no token anymore.  */
212         movb $0, (%edx)         /* Terminate string.  */
214         /* Are we at end of string?  */
215         cmpb $0, %cl
216         leal 1(%edx), %ecx
217         cmovne %ecx, %edx
219         /* Store the pointer to the next character.  */
220 #ifdef USE_AS_STRTOK_R
221         movl SAVE(%esp), %ecx
222 #endif
223         movl %edx, SAVE_PTR
225 L(epilogue):
226         /* Remove the stopset table.  */
227         addl $256, %esp
228         cfi_adjust_cfa_offset (-256)
229 #if !defined USE_AS_STRTOK_R && defined PIC
230         popl %ebx
231         cfi_adjust_cfa_offset (-4)
232         cfi_restore (ebx)
233 #endif
234         ret
236 L(returnNULL):
237         xorl %eax, %eax
238 #ifdef USE_AS_STRTOK_R
239         movl SAVE(%esp), %ecx
240 #endif
241         movl %edx, SAVE_PTR
242         jmp L(epilogue)
244 END (FUNCTION)