1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
3 Copyright (C) 1998-2016 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/>. */
23 #include "asm-syntax.h"
25 /* This file can be used for the strtok and strtok_r functions:
38 We do a common implementation here. */
40 #ifdef USE_AS_STRTOK_R
41 # define SAVE_PTR (%r9)
45 .type save_ptr, @object
46 .size save_ptr, LP_SIZE
51 # define SAVE_PTR save_ptr(%rip)
53 # define SAVE_PTR save_ptr
56 # define FUNCTION strtok
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
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. */
71 xorl %eax, %eax /* We store 0s. */
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. */
83 /* The value is in the local variable defined above. But
84 we have to take care for PIC code. */
87 movq %r8, %rdx /* Get start of string. */
89 /* If the pointer is NULL we have to use the stored value of
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 */
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
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 */
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 */
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? */
193 /* Store the pointer to the next character. */
194 mov %RDX_LP, SAVE_PTR
197 /* Remove the stopset table. */
199 cfi_adjust_cfa_offset(-256)
204 /* Store the pointer to the next character. */
205 mov %RDX_LP, SAVE_PTR