1 /* strcat(dest, src) -- Append SRC on the end of DEST.
3 Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
4 Contributed by Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de>.
5 Optimised a little by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
6 This file is part of the GNU C Library.
8 The GNU C Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 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 Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public
19 License along with the GNU C Library; see the file COPYING.LIB. If
20 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
24 #include "asm-syntax.h"
34 pushl %edi /* Save callee-safe register. */
36 movl 12(%esp), %ecx /* load source pointer */
37 movl 8(%esp), %edx /* load destination pointer */
39 testb $0xff, (%ecx) /* Is source string empty? */
40 jz L8 /* yes => return */
42 /* Test the first bytes separately until destination is aligned. */
43 testl $3, %edx /* destination pointer aligned? */
44 jz L1 /* yes => begin scan loop */
45 testb $0xff, (%edx) /* is end of string? */
46 jz L2 /* yes => start appending */
47 incl %edx /* increment source pointer */
49 testl $3, %edx /* destination pointer aligned? */
50 jz L1 /* yes => begin scan loop */
51 testb $0xff, (%edx) /* is end of string? */
52 jz L2 /* yes => start appending */
53 incl %edx /* increment source pointer */
55 testl $3, %edx /* destination pointer aligned? */
56 jz L1 /* yes => begin scan loop */
57 testb $0xff, (%edx) /* is end of string? */
58 jz L2 /* yes => start appending */
59 incl %edx /* increment source pointer */
61 /* Now we are aligned. Begin scan loop. */
66 L4: addl $16,%edx /* increment destination pointer for round */
68 L1: movl (%edx), %eax /* get word (= 4 bytes) in question */
69 movl $0xfefefeff, %edi /* magic value */
71 /* If you compare this with the algorithm in memchr.S you will
72 notice that here is an `xorl' statement missing. But you must
73 not forget that we are looking for C == 0 and `xorl $0, %eax'
76 addl %eax, %edi /* add the magic value to the word. We get
77 carry bits reported for each byte which
80 /* According to the algorithm we had to reverse the effect of the
81 XOR first and then test the overflow bits. But because the
82 following XOR would destroy the carry flag and it would (in a
83 representation with more than 32 bits) not alter then last
84 overflow, we can now test this condition. If no carry is signaled
85 no overflow must have occured in the last byte => it was 0. */
88 /* We are only interested in carry bits that change due to the
89 previous add, so remove original bits */
90 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
92 /* Now test for the other three overflow bits. */
93 orl $0xfefefeff, %edi /* set all non-carry bits */
94 incl %edi /* add 1: if one carry bit was *not* set
95 the addition will not result in 0. */
97 /* If at least one byte of the word is C we don't get 0 in %ecx. */
100 movl 4(%edx), %eax /* get word from source */
101 movl $0xfefefeff, %edi /* magic value */
102 addl %eax, %edi /* add the magic value to the word. We get
103 carry bits reported for each byte which
105 jnc L5 /* highest byte is C => stop copying */
106 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
107 orl $0xfefefeff, %edi /* set all non-carry bits */
108 incl %edi /* add 1: if one carry bit was *not* set
109 the addition will not result in 0. */
110 jnz L5 /* one byte is NUL => stop copying */
112 movl 8(%edx), %eax /* get word from source */
113 movl $0xfefefeff, %edi /* magic value */
114 addl %eax, %edi /* add the magic value to the word. We get
115 carry bits reported for each byte which
117 jnc L6 /* highest byte is C => stop copying */
118 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
119 orl $0xfefefeff, %edi /* set all non-carry bits */
120 incl %edi /* add 1: if one carry bit was *not* set
121 the addition will not result in 0. */
122 jnz L6 /* one byte is NUL => stop copying */
124 movl 12(%edx), %eax /* get word from source */
125 movl $0xfefefeff, %edi /* magic value */
126 addl %eax, %edi /* add the magic value to the word. We get
127 carry bits reported for each byte which
129 jnc L7 /* highest byte is C => stop copying */
130 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
131 orl $0xfefefeff, %edi /* set all non-carry bits */
132 incl %edi /* add 1: if one carry bit was *not* set
133 the addition will not result in 0. */
134 jz L4 /* no byte is NUL => carry on copying */
136 L7: addl $4, %edx /* adjust source pointer */
140 L3: testb %al, %al /* is first byte NUL? */
141 jz L2 /* yes => start copying */
142 incl %edx /* increment source pointer */
144 testb %ah, %ah /* is second byte NUL? */
145 jz L2 /* yes => start copying */
146 incl %edx /* increment source pointer */
148 testl $0xff0000, %eax /* is third byte NUL? */
149 jz L2 /* yes => start copying */
150 incl %edx /* increment source pointer */
152 L2: subl %ecx, %edx /* reduce number of loop variants */
154 /* Now we have to align the source pointer. */
155 testl $3, %ecx /* pointer correctly aligned? */
156 jz L29 /* yes => start copy loop */
157 movb (%ecx), %al /* get first byte */
158 movb %al, (%ecx,%edx) /* and store it */
159 andb %al, %al /* is byte NUL? */
160 jz L8 /* yes => return */
161 incl %ecx /* increment pointer */
163 testl $3, %ecx /* pointer correctly aligned? */
164 jz L29 /* yes => start copy loop */
165 movb (%ecx), %al /* get first byte */
166 movb %al, (%ecx,%edx) /* and store it */
167 andb %al, %al /* is byte NUL? */
168 jz L8 /* yes => return */
169 incl %ecx /* increment pointer */
171 testl $3, %ecx /* pointer correctly aligned? */
172 jz L29 /* yes => start copy loop */
173 movb (%ecx), %al /* get first byte */
174 movb %al, (%ecx,%edx) /* and store it */
175 andb %al, %al /* is byte NUL? */
176 jz L8 /* yes => return */
177 incl %ecx /* increment pointer */
179 /* Now we are aligned. */
180 jmp L29 /* start copy loop */
184 L28: movl %eax, 12(%ecx,%edx)/* store word at destination */
185 addl $16, %ecx /* adjust pointer for full round */
187 L29: movl (%ecx), %eax /* get word from source */
188 movl $0xfefefeff, %edi /* magic value */
189 addl %eax, %edi /* add the magic value to the word. We get
190 carry bits reported for each byte which
192 jnc L9 /* highest byte is C => stop copying */
193 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
194 orl $0xfefefeff, %edi /* set all non-carry bits */
195 incl %edi /* add 1: if one carry bit was *not* set
196 the addition will not result in 0. */
197 jnz L9 /* one byte is NUL => stop copying */
198 movl %eax, (%ecx,%edx) /* store word to destination */
200 movl 4(%ecx), %eax /* get word from source */
201 movl $0xfefefeff, %edi /* magic value */
202 addl %eax, %edi /* add the magic value to the word. We get
203 carry bits reported for each byte which
205 jnc L91 /* highest byte is C => stop copying */
206 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
207 orl $0xfefefeff, %edi /* set all non-carry bits */
208 incl %edi /* add 1: if one carry bit was *not* set
209 the addition will not result in 0. */
210 jnz L91 /* one byte is NUL => stop copying */
211 movl %eax, 4(%ecx,%edx) /* store word to destination */
213 movl 8(%ecx), %eax /* get word from source */
214 movl $0xfefefeff, %edi /* magic value */
215 addl %eax, %edi /* add the magic value to the word. We get
216 carry bits reported for each byte which
218 jnc L92 /* highest byte is C => stop copying */
219 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
220 orl $0xfefefeff, %edi /* set all non-carry bits */
221 incl %edi /* add 1: if one carry bit was *not* set
222 the addition will not result in 0. */
223 jnz L92 /* one byte is NUL => stop copying */
224 movl %eax, 8(%ecx,%edx) /* store word to destination */
226 movl 12(%ecx), %eax /* get word from source */
227 movl $0xfefefeff, %edi /* magic value */
228 addl %eax, %edi /* add the magic value to the word. We get
229 carry bits reported for each byte which
231 jnc L93 /* highest byte is C => stop copying */
232 xorl %eax, %edi /* ((word^charmask)+magic)^(word^charmask) */
233 orl $0xfefefeff, %edi /* set all non-carry bits */
234 incl %edi /* add 1: if one carry bit was *not* set
235 the addition will not result in 0. */
236 jz L28 /* no is NUL => carry on copying */
238 L93: addl $4, %ecx /* adjust pointer */
242 L9: movb %al, (%ecx,%edx) /* store first byte of last word */
243 orb %al, %al /* is it NUL? */
244 jz L8 /* yes => return */
246 movb %ah, 1(%ecx,%edx) /* store second byte of last word */
247 orb %ah, %ah /* is it NUL? */
248 jz L8 /* yes => return */
250 shrl $16, %eax /* make upper bytes accessible */
251 movb %al, 2(%ecx,%edx) /* store third byte of last word */
252 orb %al, %al /* is it NUL? */
253 jz L8 /* yes => return */
255 movb %ah, 3(%ecx,%edx) /* store fourth byte of last word */
257 L8: movl 8(%esp), %eax /* start address of destination is result */
258 popl %edi /* restore saved register */