]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/x86_64/strtok.S
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / sysdeps / x86_64 / strtok.S
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2 For AMD x86-64.
3 Copyright (C) 1998,2000,2001,2002,2003 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.
7
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.
12
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.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with the GNU C Library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 02111-1307 USA. */
22
23 #include <sysdep.h>
24 #include "asm-syntax.h"
25 #include "bp-sym.h"
26 #include "bp-asm.h"
27
28 /* This file can be used for the strtok and strtok_r functions:
29
30 strtok:
31 INPUT PARAMETER:
32 str %rdi
33 delim %rsi
34
35 strtok_r:
36 INPUT PARAMETER:
37 str %rdi
38 delim %rsi
39 save_ptr %rdx
40
41 We do a common implementation here. */
42
43 #ifdef USE_AS_STRTOK_R
44 # define SAVE_PTR (%r9)
45 #else
46 .bss
47 .local save_ptr
48 ASM_TYPE_DIRECTIVE (save_ptr, @object)
49 .size save_ptr, 8
50 save_ptr:
51 .space 8
52
53 # ifdef PIC
54 # define SAVE_PTR save_ptr(%rip)
55 # else
56 # define SAVE_PTR save_ptr
57 # endif
58
59 # define FUNCTION strtok
60 #endif
61
62 .text
63 ENTRY (BP_SYM (FUNCTION))
64 /* First we create a table with flags for all possible characters.
65 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
66 supported by the C string functions we have 256 characters.
67 Before inserting marks for the stop characters we clear the whole
68 table. */
69 movq %rdi, %r8 /* Save value. */
70 subq $256, %rsp /* Make space for 256 bytes. */
71 cfi_adjust_cfa_offset(256)
72 movq $32, %rcx /* 32*8 bytes = 256 bytes. */
73 movq %rsp, %rdi
74 xorq %rax, %rax /* We store 0s. */
75 cld
76 rep
77 stosq
78
79 /* Note: %rcx = 0 !!! */
80
81 #ifdef USE_AS_STRTOK_R
82 /* The value is stored in the third argument. */
83 movq %rdx, %rax
84 movq %rdx, %r9 /* Save value - see def. of SAVE_PTR. */
85 movq (%rax), %rax
86 #else
87 /* The value is in the local variable defined above. But
88 we have to take care for PIC code. */
89 movq SAVE_PTR, %rax
90 #endif
91 movq %r8, %rdx /* Get start of string. */
92
93 /* If the pointer is NULL we have to use the stored value of
94 the last run. */
95 cmpq $0, %rdx
96 cmove %rax, %rdx
97 testq %rdx, %rdx
98 jz L(returnNULL)
99 movq %rsi, %rax /* Get start of delimiter set. */
100
101 /* For understanding the following code remember that %rcx == 0 now.
102 Although all the following instruction only modify %cl we always
103 have a correct zero-extended 64-bit value in %rcx. */
104
105 L(2): movb (%rax), %cl /* get byte from stopset */
106 testb %cl, %cl /* is NUL char? */
107 jz L(1) /* yes => start compare loop */
108 movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */
109
110 movb 1(%rax), %cl /* get byte from stopset */
111 testb $0xff, %cl /* is NUL char? */
112 jz L(1) /* yes => start compare loop */
113 movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */
114
115 movb 2(%rax), %cl /* get byte from stopset */
116 testb $0xff, %cl /* is NUL char? */
117 jz L(1) /* yes => start compare loop */
118 movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */
119
120 movb 3(%rax), %cl /* get byte from stopset */
121 addq $4, %rax /* increment stopset pointer */
122 movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */
123 testb $0xff, %cl /* is NUL char? */
124 jnz L(2) /* no => process next dword from stopset */
125
126 L(1):
127
128 leaq -4(%rdx), %rax /* prepare loop */
129
130 /* We use a neat trick for the following loop. Normally we would
131 have to test for two termination conditions
132 1. a character in the stopset was found
133 and
134 2. the end of the string was found
135 As a sign that the character is in the stopset we store its
136 value in the table. The value of NUL is NUL so the loop
137 terminates for NUL in every case. */
138
139 L(3): addq $4, %rax /* adjust pointer for full loop round */
140
141 movb (%rax), %cl /* get byte from string */
142 testb %cl, (%rsp,%rcx) /* is it contained in stopset? */
143 jz L(4) /* no => start of token */
144
145 movb 1(%rax), %cl /* get byte from string */
146 testb %cl, (%rsp,%rcx) /* is it contained in stopset? */
147 jz L(5) /* no => start of token */
148
149 movb 2(%rax), %cl /* get byte from string */
150 testb %cl, (%rsp,%rcx) /* is it contained in stopset? */
151 jz L(6) /* no => start of token */
152
153 movb 3(%rax), %cl /* get byte from string */
154 testb %cl, (%rsp,%rcx) /* is it contained in stopset? */
155 jnz L(3) /* yes => start of loop */
156
157 incq %rax /* adjust pointer */
158 L(6): incq %rax
159 L(5): incq %rax
160
161 /* Now we have to terminate the string. */
162
163 L(4): leaq -4(%rax), %rdx /* We use %rDX for the next run. */
164
165 L(7): addq $4, %rdx /* adjust pointer for full loop round */
166
167 movb (%rdx), %cl /* get byte from string */
168 cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */
169 je L(8) /* yes => return */
170
171 movb 1(%rdx), %cl /* get byte from string */
172 cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */
173 je L(9) /* yes => return */
174
175 movb 2(%rdx), %cl /* get byte from string */
176 cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */
177 je L(10) /* yes => return */
178
179 movb 3(%rdx), %cl /* get byte from string */
180 cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */
181 jne L(7) /* no => start loop again */
182
183 incq %rdx /* adjust pointer */
184 L(10): incq %rdx
185 L(9): incq %rdx
186
187 L(8): cmpq %rax, %rdx
188 je L(returnNULL) /* There was no token anymore. */
189
190 movb $0, (%rdx) /* Terminate string. */
191
192 /* Are we at end of string? */
193 cmpb $0, %cl
194 leaq 1(%rdx), %rcx
195 cmovne %rcx, %rdx
196
197 /* Store the pointer to the next character. */
198 movq %rdx, SAVE_PTR
199
200 L(epilogue):
201 /* Remove the stopset table. */
202 addq $256, %rsp
203 cfi_adjust_cfa_offset(-256)
204 retq
205
206 L(returnNULL):
207 xorq %rax, %rax
208 jmp L(epilogue)
209
210 END (BP_SYM (FUNCTION))