Blame sysdeps/i386/strcat.S

Packit Service 82fcde
/* strcat(dest, src) -- Append SRC on the end of DEST.
Packit Service 82fcde
   For Intel 80x86, x>=4.
Packit Service 82fcde
   Copyright (C) 1994-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de>.
Packit Service 82fcde
   Optimised a little by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
#include "asm-syntax.h"
Packit Service 82fcde
Packit Service 82fcde
#define PARMS	4+4	/* space for 1 saved reg */
Packit Service 82fcde
#define RTN	PARMS
Packit Service 82fcde
#define DEST	RTN
Packit Service 82fcde
#define SRC	DEST+4
Packit Service 82fcde
Packit Service 82fcde
	.text
Packit Service 82fcde
ENTRY (strcat)
Packit Service 82fcde
Packit Service 82fcde
	pushl %edi		/* Save callee-safe register.  */
Packit Service 82fcde
	cfi_adjust_cfa_offset (4)
Packit Service 82fcde
Packit Service 82fcde
	movl DEST(%esp), %edx
Packit Service 82fcde
	movl SRC(%esp), %ecx
Packit Service 82fcde
Packit Service 82fcde
	testb $0xff, (%ecx)	/* Is source string empty? */
Packit Service 82fcde
	jz L(8)			/* yes => return */
Packit Service 82fcde
Packit Service 82fcde
	/* Test the first bytes separately until destination is aligned.  */
Packit Service 82fcde
	testl $3, %edx		/* destination pointer aligned? */
Packit Service 82fcde
	jz L(1)			/* yes => begin scan loop */
Packit Service 82fcde
	testb $0xff, (%edx)	/* is end of string? */
Packit Service 82fcde
	jz L(2)			/* yes => start appending */
Packit Service 82fcde
	incl %edx		/* increment source pointer */
Packit Service 82fcde
Packit Service 82fcde
	testl $3, %edx		/* destination pointer aligned? */
Packit Service 82fcde
	jz L(1)			/* yes => begin scan loop */
Packit Service 82fcde
	testb $0xff, (%edx)	/* is end of string? */
Packit Service 82fcde
	jz L(2)			/* yes => start appending */
Packit Service 82fcde
	incl %edx		/* increment source pointer */
Packit Service 82fcde
Packit Service 82fcde
	testl $3, %edx		/* destination pointer aligned? */
Packit Service 82fcde
	jz L(1)			/* yes => begin scan loop */
Packit Service 82fcde
	testb $0xff, (%edx)	/* is end of string? */
Packit Service 82fcde
	jz L(2)			/* yes => start appending */
Packit Service 82fcde
	incl %edx		/* increment source pointer */
Packit Service 82fcde
Packit Service 82fcde
	/* Now we are aligned.  Begin scan loop.  */
Packit Service 82fcde
	jmp L(1)
Packit Service 82fcde
Packit Service 82fcde
	cfi_rel_offset (edi, 0)
Packit Service 82fcde
	ALIGN(4)
Packit Service 82fcde
Packit Service 82fcde
L(4):	addl $16,%edx		/* increment destination pointer for round */
Packit Service 82fcde
Packit Service 82fcde
L(1):	movl (%edx), %eax	/* get word (= 4 bytes) in question */
Packit Service 82fcde
	movl $0xfefefeff, %edi	/* magic value */
Packit Service 82fcde
Packit Service 82fcde
	/* If you compare this with the algorithm in memchr.S you will
Packit Service 82fcde
	   notice that here is an `xorl' statement missing.  But you must
Packit Service 82fcde
	   not forget that we are looking for C == 0 and `xorl $0, %eax'
Packit Service 82fcde
	   is a no-op.  */
Packit Service 82fcde
Packit Service 82fcde
	addl %eax, %edi		/* add the magic value to the word.  We get
Packit Service 82fcde
				   carry bits reported for each byte which
Packit Service 82fcde
				   is *not* 0 */
Packit Service 82fcde
Packit Service 82fcde
	/* According to the algorithm we had to reverse the effect of the
Packit Service 82fcde
	   XOR first and then test the overflow bits.  But because the
Packit Service 82fcde
	   following XOR would destroy the carry flag and it would (in a
Packit Service 82fcde
	   representation with more than 32 bits) not alter then last
Packit Service 82fcde
	   overflow, we can now test this condition.  If no carry is signaled
Packit Service 82fcde
	   no overflow must have occurred in the last byte => it was 0.	*/
Packit Service 82fcde
	jnc L(3)
Packit Service 82fcde
Packit Service 82fcde
	/* We are only interested in carry bits that change due to the
Packit Service 82fcde
	   previous add, so remove original bits */
Packit Service 82fcde
	xorl %eax, %edi		/* ((word^charmask)+magic)^(word^charmask) */
Packit Service 82fcde
Packit Service 82fcde
	/* Now test for the other three overflow bits.  */
Packit Service 82fcde
	orl $0xfefefeff, %edi	/* set all non-carry bits */
Packit Service 82fcde
	incl %edi		/* add 1: if one carry bit was *not* set
Packit Service 82fcde
				   the addition will not result in 0.  */
Packit Service 82fcde
Packit Service 82fcde
	/* If at least one byte of the word is C we don't get 0 in %ecx.  */
Packit Service 82fcde
	jnz L(3)
Packit Service 82fcde
Packit Service 82fcde
	movl 4(%edx), %eax	/* get word from source */
Packit Service 82fcde
	movl $0xfefefeff, %edi	/* magic value */
Packit Service 82fcde
	addl %eax, %edi		/* add the magic value to the word.  We get
Packit Service 82fcde
				   carry bits reported for each byte which
Packit Service 82fcde
				   is *not* 0 */
Packit Service 82fcde
	jnc L(5)		/* highest byte is C => stop copying */
Packit Service 82fcde
	xorl %eax, %edi		/* ((word^charmask)+magic)^(word^charmask) */
Packit Service 82fcde
	orl $0xfefefeff, %edi	/* set all non-carry bits */
Packit Service 82fcde
	incl %edi		/* add 1: if one carry bit was *not* set
Packit Service 82fcde
				   the addition will not result in 0.  */
Packit Service 82fcde
	jnz L(5)		/* one byte is NUL => stop copying */
Packit Service 82fcde
Packit Service 82fcde
	movl 8(%edx), %eax	/* get word from source */
Packit Service 82fcde
	movl $0xfefefeff, %edi	/* magic value */
Packit Service 82fcde
	addl %eax, %edi		/* add the magic value to the word.  We get
Packit Service 82fcde
				   carry bits reported for each byte which
Packit Service 82fcde
				   is *not* 0 */
Packit Service 82fcde
	jnc L(6)		/* highest byte is C => stop copying */
Packit Service 82fcde
	xorl %eax, %edi		/* ((word^charmask)+magic)^(word^charmask) */
Packit Service 82fcde
	orl $0xfefefeff, %edi	/* set all non-carry bits */
Packit Service 82fcde
	incl %edi		/* add 1: if one carry bit was *not* set
Packit Service 82fcde
				   the addition will not result in 0.  */
Packit Service 82fcde
	jnz L(6)		/* one byte is NUL => stop copying */
Packit Service 82fcde
Packit Service 82fcde
	movl 12(%edx), %eax	/* get word from source */
Packit Service 82fcde
	movl $0xfefefeff, %edi	/* magic value */
Packit Service 82fcde
	addl %eax, %edi		/* add the magic value to the word.  We get
Packit Service 82fcde
				   carry bits reported for each byte which
Packit Service 82fcde
				   is *not* 0 */
Packit Service 82fcde
	jnc L(7)		/* highest byte is C => stop copying */
Packit Service 82fcde
	xorl %eax, %edi		/* ((word^charmask)+magic)^(word^charmask) */
Packit Service 82fcde
	orl $0xfefefeff, %edi	/* set all non-carry bits */
Packit Service 82fcde
	incl %edi		/* add 1: if one carry bit was *not* set
Packit Service 82fcde
				   the addition will not result in 0.  */
Packit Service 82fcde
	jz L(4)			/* no byte is NUL => carry on copying */
Packit Service 82fcde
Packit Service 82fcde
L(7):	addl $4, %edx		/* adjust source pointer */
Packit Service 82fcde
L(6):	addl $4, %edx
Packit Service 82fcde
L(5):	addl $4, %edx
Packit Service 82fcde
Packit Service 82fcde
L(3):	testb %al, %al		/* is first byte NUL? */
Packit Service 82fcde
	jz L(2)			/* yes => start copying */
Packit Service 82fcde
	incl %edx		/* increment source pointer */
Packit Service 82fcde
Packit Service 82fcde
	testb %ah, %ah		/* is second byte NUL? */
Packit Service 82fcde
	jz L(2)			/* yes => start copying */
Packit Service 82fcde
	incl %edx		/* increment source pointer */
Packit Service 82fcde
Packit Service 82fcde
	testl $0xff0000, %eax	/* is third byte NUL? */
Packit Service 82fcde
	jz L(2)			/* yes => start copying */
Packit Service 82fcde
	incl %edx		/* increment source pointer */
Packit Service 82fcde
Packit Service 82fcde
L(2):	subl %ecx, %edx		/* reduce number of loop variants */
Packit Service 82fcde
Packit Service 82fcde
	/* Now we have to align the source pointer.  */
Packit Service 82fcde
	testl $3, %ecx		/* pointer correctly aligned? */
Packit Service 82fcde
	jz L(29)		/* yes => start copy loop */
Packit Service 82fcde
	movb (%ecx), %al	/* get first byte */
Packit Service 82fcde
	movb %al, (%ecx,%edx)	/* and store it */
Packit Service 82fcde
	andb %al, %al		/* is byte NUL? */
Packit Service 82fcde
	jz L(8)			/* yes => return */
Packit Service 82fcde
	incl %ecx		/* increment pointer */
Packit Service 82fcde
Packit Service 82fcde
	testl $3, %ecx		/* pointer correctly aligned? */
Packit Service 82fcde
	jz L(29)		/* yes => start copy loop */
Packit Service 82fcde
	movb (%ecx), %al	/* get first byte */
Packit Service 82fcde
	movb %al, (%ecx,%edx)	/* and store it */
Packit Service 82fcde
	andb %al, %al		/* is byte NUL? */
Packit Service 82fcde
	jz L(8)			/* yes => return */
Packit Service 82fcde
	incl %ecx		/* increment pointer */
Packit Service 82fcde
Packit Service 82fcde
	testl $3, %ecx		/* pointer correctly aligned? */
Packit Service 82fcde
	jz L(29)		/* yes => start copy loop */
Packit Service 82fcde
	movb (%ecx), %al	/* get first byte */
Packit Service 82fcde
	movb %al, (%ecx,%edx)	/* and store it */
Packit Service 82fcde
	andb %al, %al		/* is byte NUL? */
Packit Service 82fcde
	jz L(8)			/* yes => return */
Packit Service 82fcde
	incl %ecx		/* increment pointer */
Packit Service 82fcde
Packit Service 82fcde
	/* Now we are aligned.  */
Packit Service 82fcde
	jmp L(29)		/* start copy loop */
Packit Service 82fcde
Packit Service 82fcde
	ALIGN(4)
Packit Service 82fcde
Packit Service 82fcde
L(28):	movl %eax, 12(%ecx,%edx)/* store word at destination */
Packit Service 82fcde
	addl $16, %ecx		/* adjust pointer for full round */
Packit Service 82fcde
Packit Service 82fcde
L(29):	movl (%ecx), %eax	/* get word from source */
Packit Service 82fcde
	movl $0xfefefeff, %edi	/* magic value */
Packit Service 82fcde
	addl %eax, %edi		/* add the magic value to the word.  We get
Packit Service 82fcde
				   carry bits reported for each byte which
Packit Service 82fcde
				   is *not* 0 */
Packit Service 82fcde
	jnc L(9)		/* highest byte is C => stop copying */
Packit Service 82fcde
	xorl %eax, %edi		/* ((word^charmask)+magic)^(word^charmask) */
Packit Service 82fcde
	orl $0xfefefeff, %edi	/* set all non-carry bits */
Packit Service 82fcde
	incl %edi		/* add 1: if one carry bit was *not* set
Packit Service 82fcde
				   the addition will not result in 0.  */
Packit Service 82fcde
	jnz L(9)		/* one byte is NUL => stop copying */
Packit Service 82fcde
	movl %eax, (%ecx,%edx)	/* store word to destination */
Packit Service 82fcde
Packit Service 82fcde
	movl 4(%ecx), %eax	/* get word from source */
Packit Service 82fcde
	movl $0xfefefeff, %edi	/* magic value */
Packit Service 82fcde
	addl %eax, %edi		/* add the magic value to the word.  We get
Packit Service 82fcde
				   carry bits reported for each byte which
Packit Service 82fcde
				   is *not* 0 */
Packit Service 82fcde
	jnc L(91)		/* highest byte is C => stop copying */
Packit Service 82fcde
	xorl %eax, %edi		/* ((word^charmask)+magic)^(word^charmask) */
Packit Service 82fcde
	orl $0xfefefeff, %edi	/* set all non-carry bits */
Packit Service 82fcde
	incl %edi		/* add 1: if one carry bit was *not* set
Packit Service 82fcde
				   the addition will not result in 0.  */
Packit Service 82fcde
	jnz L(91)		/* one byte is NUL => stop copying */
Packit Service 82fcde
	movl %eax, 4(%ecx,%edx)	/* store word to destination */
Packit Service 82fcde
Packit Service 82fcde
	movl 8(%ecx), %eax	/* get word from source */
Packit Service 82fcde
	movl $0xfefefeff, %edi	/* magic value */
Packit Service 82fcde
	addl %eax, %edi		/* add the magic value to the word.  We get
Packit Service 82fcde
				   carry bits reported for each byte which
Packit Service 82fcde
				   is *not* 0 */
Packit Service 82fcde
	jnc L(92)		/* highest byte is C => stop copying */
Packit Service 82fcde
	xorl %eax, %edi		/* ((word^charmask)+magic)^(word^charmask) */
Packit Service 82fcde
	orl $0xfefefeff, %edi	/* set all non-carry bits */
Packit Service 82fcde
	incl %edi		/* add 1: if one carry bit was *not* set
Packit Service 82fcde
				   the addition will not result in 0.  */
Packit Service 82fcde
	jnz L(92)		/* one byte is NUL => stop copying */
Packit Service 82fcde
	movl %eax, 8(%ecx,%edx)	/* store word to destination */
Packit Service 82fcde
Packit Service 82fcde
	movl 12(%ecx), %eax	/* get word from source */
Packit Service 82fcde
	movl $0xfefefeff, %edi	/* magic value */
Packit Service 82fcde
	addl %eax, %edi		/* add the magic value to the word.  We get
Packit Service 82fcde
				   carry bits reported for each byte which
Packit Service 82fcde
				   is *not* 0 */
Packit Service 82fcde
	jnc L(93)		/* highest byte is C => stop copying */
Packit Service 82fcde
	xorl %eax, %edi		/* ((word^charmask)+magic)^(word^charmask) */
Packit Service 82fcde
	orl $0xfefefeff, %edi	/* set all non-carry bits */
Packit Service 82fcde
	incl %edi		/* add 1: if one carry bit was *not* set
Packit Service 82fcde
				   the addition will not result in 0.  */
Packit Service 82fcde
	jz L(28)		/* no is NUL => carry on copying */
Packit Service 82fcde
Packit Service 82fcde
L(93):	addl $4, %ecx		/* adjust pointer */
Packit Service 82fcde
L(92):	addl $4, %ecx
Packit Service 82fcde
L(91):	addl $4, %ecx
Packit Service 82fcde
Packit Service 82fcde
L(9):	movb %al, (%ecx,%edx)	/* store first byte of last word */
Packit Service 82fcde
	orb %al, %al		/* is it NUL? */
Packit Service 82fcde
	jz L(8)			/* yes => return */
Packit Service 82fcde
Packit Service 82fcde
	movb %ah, 1(%ecx,%edx)	/* store second byte of last word */
Packit Service 82fcde
	orb %ah, %ah		/* is it NUL? */
Packit Service 82fcde
	jz L(8)			/* yes => return */
Packit Service 82fcde
Packit Service 82fcde
	shrl $16, %eax		/* make upper bytes accessible */
Packit Service 82fcde
	movb %al, 2(%ecx,%edx)	/* store third byte of last word */
Packit Service 82fcde
	orb %al, %al		/* is it NUL? */
Packit Service 82fcde
	jz L(8)			/* yes => return */
Packit Service 82fcde
Packit Service 82fcde
	movb %ah, 3(%ecx,%edx)	/* store fourth byte of last word */
Packit Service 82fcde
Packit Service 82fcde
L(8):	movl DEST(%esp), %eax	/* start address of destination is result */
Packit Service 82fcde
	popl %edi		/* restore saved register */
Packit Service 82fcde
	cfi_adjust_cfa_offset (-4)
Packit Service 82fcde
	cfi_restore (edi)
Packit Service 82fcde
Packit Service 82fcde
	ret
Packit Service 82fcde
END (strcat)
Packit Service 82fcde
libc_hidden_builtin_def (strcat)