1 /* strcat(dest, src) -- Append SRC on the end of DEST.
3 Copyright (C) 1994-2017 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de>.
6 Optimised a little by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
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 #define PARMS 4+4 /* space for 1 saved reg */
33 pushl %edi /* Save callee-safe register. */
34 cfi_adjust_cfa_offset (4)
39 testb $0xff, (%ecx) /* Is source string empty? */
40 jz L(8) /* yes => return */
42 /* Test the first bytes separately until destination is aligned. */
43 testl $3, %edx /* destination pointer aligned? */
44 jz L(1) /* yes => begin scan loop */
45 testb $0xff, (%edx) /* is end of string? */
46 jz L(2) /* yes => start appending */
47 incl %edx /* increment source pointer */
49 testl $3, %edx /* destination pointer aligned? */
50 jz L(1) /* yes => begin scan loop */
51 testb $0xff, (%edx) /* is end of string? */
52 jz L(2) /* yes => start appending */
53 incl %edx /* increment source pointer */
55 testl $3, %edx /* destination pointer aligned? */
56 jz L(1) /* yes => begin scan loop */
57 testb $0xff, (%edx) /* is end of string? */
58 jz L(2) /* yes => start appending */
59 incl %edx /* increment source pointer */
61 /* Now we are aligned. Begin scan loop. */
64 cfi_rel_offset (edi, 0)
67 L(4): addl $16,%edx /* increment destination pointer for round */
69 L(1): movl (%edx), %eax /* get word (= 4 bytes) in question */
70 movl $0xfefefeff, %edi /* magic value */
72 /* If you compare this with the algorithm in memchr.S you will
73 notice that here is an `xorl' statement missing. But you must
74 not forget that we are looking for C == 0 and `xorl $0, %eax'
77 addl %eax, %edi /* add the magic value to the word. We get
78 carry bits reported for each byte which
81 /* According to the algorithm we had to reverse the effect of the
82 XOR first and then test the overflow bits. But because the
83 following XOR would destroy the carry flag and it would (in a
84 representation with more than 32 bits) not alter then last
85 overflow, we can now test this condition. If no carry is signaled
86 no overflow must have occurred in the last byte => it was 0. */
89 /* We are only interested in carry bits that change due to the
90 previous add, so remove original bits */
91 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
93 /* Now test for the other three overflow bits. */
94 orl $0xfefefeff, %edi /* set all non-carry bits */
95 incl %edi /* add 1: if one carry bit was *not* set
96 the addition will not result in 0. */
98 /* If at least one byte of the word is C we don't get 0 in %ecx. */
101 movl 4(%edx), %eax /* get word from source */
102 movl $0xfefefeff, %edi /* magic value */
103 addl %eax, %edi /* add the magic value to the word. We get
104 carry bits reported for each byte which
106 jnc L(5) /* highest byte is C => stop copying */
107 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
108 orl $0xfefefeff, %edi /* set all non-carry bits */
109 incl %edi /* add 1: if one carry bit was *not* set
110 the addition will not result in 0. */
111 jnz L(5) /* one byte is NUL => stop copying */
113 movl 8(%edx), %eax /* get word from source */
114 movl $0xfefefeff, %edi /* magic value */
115 addl %eax, %edi /* add the magic value to the word. We get
116 carry bits reported for each byte which
118 jnc L(6) /* highest byte is C => stop copying */
119 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
120 orl $0xfefefeff, %edi /* set all non-carry bits */
121 incl %edi /* add 1: if one carry bit was *not* set
122 the addition will not result in 0. */
123 jnz L(6) /* one byte is NUL => stop copying */
125 movl 12(%edx), %eax /* get word from source */
126 movl $0xfefefeff, %edi /* magic value */
127 addl %eax, %edi /* add the magic value to the word. We get
128 carry bits reported for each byte which
130 jnc L(7) /* highest byte is C => stop copying */
131 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
132 orl $0xfefefeff, %edi /* set all non-carry bits */
133 incl %edi /* add 1: if one carry bit was *not* set
134 the addition will not result in 0. */
135 jz L(4) /* no byte is NUL => carry on copying */
137 L(7): addl $4, %edx /* adjust source pointer */
141 L(3): testb %al, %al /* is first byte NUL? */
142 jz L(2) /* yes => start copying */
143 incl %edx /* increment source pointer */
145 testb %ah, %ah /* is second byte NUL? */
146 jz L(2) /* yes => start copying */
147 incl %edx /* increment source pointer */
149 testl $0xff0000, %eax /* is third byte NUL? */
150 jz L(2) /* yes => start copying */
151 incl %edx /* increment source pointer */
153 L(2): subl %ecx, %edx /* reduce number of loop variants */
155 /* Now we have to align the source pointer. */
156 testl $3, %ecx /* pointer correctly aligned? */
157 jz L(29) /* yes => start copy loop */
158 movb (%ecx), %al /* get first byte */
159 movb %al, (%ecx,%edx) /* and store it */
160 andb %al, %al /* is byte NUL? */
161 jz L(8) /* yes => return */
162 incl %ecx /* increment pointer */
164 testl $3, %ecx /* pointer correctly aligned? */
165 jz L(29) /* yes => start copy loop */
166 movb (%ecx), %al /* get first byte */
167 movb %al, (%ecx,%edx) /* and store it */
168 andb %al, %al /* is byte NUL? */
169 jz L(8) /* yes => return */
170 incl %ecx /* increment pointer */
172 testl $3, %ecx /* pointer correctly aligned? */
173 jz L(29) /* yes => start copy loop */
174 movb (%ecx), %al /* get first byte */
175 movb %al, (%ecx,%edx) /* and store it */
176 andb %al, %al /* is byte NUL? */
177 jz L(8) /* yes => return */
178 incl %ecx /* increment pointer */
180 /* Now we are aligned. */
181 jmp L(29) /* start copy loop */
185 L(28): movl %eax, 12(%ecx,%edx)/* store word at destination */
186 addl $16, %ecx /* adjust pointer for full round */
188 L(29): movl (%ecx), %eax /* get word from source */
189 movl $0xfefefeff, %edi /* magic value */
190 addl %eax, %edi /* add the magic value to the word. We get
191 carry bits reported for each byte which
193 jnc L(9) /* highest byte is C => stop copying */
194 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
195 orl $0xfefefeff, %edi /* set all non-carry bits */
196 incl %edi /* add 1: if one carry bit was *not* set
197 the addition will not result in 0. */
198 jnz L(9) /* one byte is NUL => stop copying */
199 movl %eax, (%ecx,%edx) /* store word to destination */
201 movl 4(%ecx), %eax /* get word from source */
202 movl $0xfefefeff, %edi /* magic value */
203 addl %eax, %edi /* add the magic value to the word. We get
204 carry bits reported for each byte which
206 jnc L(91) /* highest byte is C => stop copying */
207 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
208 orl $0xfefefeff, %edi /* set all non-carry bits */
209 incl %edi /* add 1: if one carry bit was *not* set
210 the addition will not result in 0. */
211 jnz L(91) /* one byte is NUL => stop copying */
212 movl %eax, 4(%ecx,%edx) /* store word to destination */
214 movl 8(%ecx), %eax /* get word from source */
215 movl $0xfefefeff, %edi /* magic value */
216 addl %eax, %edi /* add the magic value to the word. We get
217 carry bits reported for each byte which
219 jnc L(92) /* highest byte is C => stop copying */
220 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
221 orl $0xfefefeff, %edi /* set all non-carry bits */
222 incl %edi /* add 1: if one carry bit was *not* set
223 the addition will not result in 0. */
224 jnz L(92) /* one byte is NUL => stop copying */
225 movl %eax, 8(%ecx,%edx) /* store word to destination */
227 movl 12(%ecx), %eax /* get word from source */
228 movl $0xfefefeff, %edi /* magic value */
229 addl %eax, %edi /* add the magic value to the word. We get
230 carry bits reported for each byte which
232 jnc L(93) /* highest byte is C => stop copying */
233 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
234 orl $0xfefefeff, %edi /* set all non-carry bits */
235 incl %edi /* add 1: if one carry bit was *not* set
236 the addition will not result in 0. */
237 jz L(28) /* no is NUL => carry on copying */
239 L(93): addl $4, %ecx /* adjust pointer */
243 L(9): movb %al, (%ecx,%edx) /* store first byte of last word */
244 orb %al, %al /* is it NUL? */
245 jz L(8) /* yes => return */
247 movb %ah, 1(%ecx,%edx) /* store second byte of last word */
248 orb %ah, %ah /* is it NUL? */
249 jz L(8) /* yes => return */
251 shrl $16, %eax /* make upper bytes accessible */
252 movb %al, 2(%ecx,%edx) /* store third byte of last word */
253 orb %al, %al /* is it NUL? */
254 jz L(8) /* yes => return */
256 movb %ah, 3(%ecx,%edx) /* store fourth byte of last word */
258 L(8): movl DEST(%esp), %eax /* start address of destination is result */
259 popl %edi /* restore saved register */
260 cfi_adjust_cfa_offset (-4)
265 libc_hidden_builtin_def (strcat)