Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / x86_64 / strtok.S
blobbb5ba2e28f683359112a7e25cb8b9029c1e03b5b
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2    For AMD x86-64.
3    Copyright (C) 1998-2014 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Based on i686 version contributed by Ulrich Drepper
6    <drepper@cygnus.com>, 1998.
8    The GNU C Library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public
10    License as published by the Free Software Foundation; either
11    version 2.1 of the License, or (at your option) any later version.
13    The GNU C Library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
18    You should have received a copy of the GNU Lesser General Public
19    License along with the GNU C Library; if not, see
20    <http://www.gnu.org/licenses/>.  */
22 #include <sysdep.h>
23 #include "asm-syntax.h"
25 /* This file can be used for the strtok and strtok_r functions:
27    strtok:
28         INPUT PARAMETER:
29         str             %rdi
30         delim           %rsi
32    strtok_r:
33         INPUT PARAMETER:
34         str             %rdi
35         delim           %rsi
36         save_ptr        %rdx
38    We do a common implementation here.  */
40 #ifdef USE_AS_STRTOK_R
41 # define SAVE_PTR (%r9)
42 #else
43         .bss
44         .local save_ptr
45         .type save_ptr, @object
46         .size save_ptr, LP_SIZE
47 save_ptr:
48         .space LP_SIZE
50 # ifdef PIC
51 #  define SAVE_PTR save_ptr(%rip)
52 # else
53 #  define SAVE_PTR save_ptr
54 # endif
56 # define FUNCTION strtok
57 #endif
59         .text
60 ENTRY (FUNCTION)
61         /* First we create a table with flags for all possible characters.
62            For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
63            supported by the C string functions we have 256 characters.
64            Before inserting marks for the stop characters we clear the whole
65            table.  */
66         movq %rdi, %r8                  /* Save value.  */
67         subq $256, %rsp                 /* Make space for 256 bytes.  */
68         cfi_adjust_cfa_offset(256)
69         movl $32,  %ecx                 /* 32*8 bytes = 256 bytes.  */
70         movq %rsp, %rdi
71         xorl %eax, %eax                 /* We store 0s.  */
72         cld
73         rep
74         stosq
76         /* Note: %rcx = 0 !!! */
78 #ifdef USE_AS_STRTOK_R
79         /* The value is stored in the third argument.  */
80         mov %RDX_LP, %R9_LP     /* Save value - see def. of SAVE_PTR.  */
81         mov (%rdx), %RAX_LP
82 #else
83         /* The value is in the local variable defined above.  But
84            we have to take care for PIC code.  */
85         mov SAVE_PTR, %RAX_LP
86 #endif
87         movq %r8, %rdx          /* Get start of string.  */
89         /* If the pointer is NULL we have to use the stored value of
90            the last run.  */
91         cmpq $0, %rdx
92         cmove %rax, %rdx
93         testq %rdx, %rdx
94         jz L(returnNULL)
95         movq %rsi, %rax         /* Get start of delimiter set.  */
97 /* For understanding the following code remember that %rcx == 0 now.
98    Although all the following instruction only modify %cl we always
99    have a correct zero-extended 64-bit value in %rcx.  */
101 L(2):   movb (%rax), %cl        /* get byte from stopset */
102         testb %cl, %cl          /* is NUL char? */
103         jz L(1)                 /* yes => start compare loop */
104         movb %cl, (%rsp,%rcx)   /* set corresponding byte in stopset table */
106         movb 1(%rax), %cl       /* get byte from stopset */
107         testb $0xff, %cl        /* is NUL char? */
108         jz L(1)                 /* yes => start compare loop */
109         movb %cl, (%rsp,%rcx)   /* set corresponding byte in stopset table */
111         movb 2(%rax), %cl       /* get byte from stopset */
112         testb $0xff, %cl        /* is NUL char? */
113         jz L(1)                 /* yes => start compare loop */
114         movb %cl, (%rsp,%rcx)   /* set corresponding byte in stopset table */
116         movb 3(%rax), %cl       /* get byte from stopset */
117         addq $4, %rax           /* increment stopset pointer */
118         movb %cl, (%rsp,%rcx)   /* set corresponding byte in stopset table */
119         testb $0xff, %cl        /* is NUL char? */
120         jnz L(2)                /* no => process next dword from stopset */
122 L(1):
124         leaq -4(%rdx), %rax     /* prepare loop */
126         /* We use a neat trick for the following loop.  Normally we would
127            have to test for two termination conditions
128            1. a character in the stopset was found
129            and
130            2. the end of the string was found
131            As a sign that the character is in the stopset we store its
132            value in the table.  The value of NUL is NUL so the loop
133            terminates for NUL in every case.  */
135 L(3):   addq $4, %rax           /* adjust pointer for full loop round */
137         movb (%rax), %cl        /* get byte from string */
138         testb %cl, (%rsp,%rcx)  /* is it contained in stopset? */
139         jz L(4)                 /* no => start of token */
141         movb 1(%rax), %cl       /* get byte from string */
142         testb %cl, (%rsp,%rcx)  /* is it contained in stopset? */
143         jz L(5)                 /* no => start of token */
145         movb 2(%rax), %cl       /* get byte from string */
146         testb %cl, (%rsp,%rcx)  /* is it contained in stopset? */
147         jz L(6)                 /* no => start of token */
149         movb 3(%rax), %cl       /* get byte from string */
150         testb %cl, (%rsp,%rcx)  /* is it contained in stopset? */
151         jnz L(3)                /* yes => start of loop */
153         incq %rax               /* adjust pointer */
154 L(6):   incq %rax
155 L(5):   incq %rax
157         /* Now we have to terminate the string.  */
159 L(4):   leaq -4(%rax), %rdx     /* We use %rDX for the next run.  */
161 L(7):   addq $4, %rdx           /* adjust pointer for full loop round */
163         movb (%rdx), %cl        /* get byte from string */
164         cmpb %cl, (%rsp,%rcx)   /* is it contained in skipset? */
165         je L(8)                 /* yes => return */
167         movb 1(%rdx), %cl       /* get byte from string */
168         cmpb %cl, (%rsp,%rcx)   /* is it contained in skipset? */
169         je L(9)                 /* yes => return */
171         movb 2(%rdx), %cl       /* get byte from string */
172         cmpb %cl, (%rsp,%rcx)   /* is it contained in skipset? */
173         je L(10)                /* yes => return */
175         movb 3(%rdx), %cl       /* get byte from string */
176         cmpb %cl, (%rsp,%rcx)   /* is it contained in skipset? */
177         jne L(7)                /* no => start loop again */
179         incq %rdx               /* adjust pointer */
180 L(10):  incq %rdx
181 L(9):   incq %rdx
183 L(8):   cmpq %rax, %rdx
184         je L(returnNULL)        /* There was no token anymore.  */
186         movb $0, (%rdx)         /* Terminate string.  */
188         /* Are we at end of string?  */
189         cmpb $0, %cl
190         leaq 1(%rdx), %rcx
191         cmovne %rcx, %rdx
193         /* Store the pointer to the next character.  */
194         mov %RDX_LP, SAVE_PTR
196 L(epilogue):
197         /* Remove the stopset table.  */
198         addq $256, %rsp
199         cfi_adjust_cfa_offset(-256)
200         retq
202 L(returnNULL):
203         xorl %eax, %eax
204         /* Store the pointer to the next character.  */
205         mov %RDX_LP, SAVE_PTR
206         jmp L(epilogue)
208 END (FUNCTION)