Blame sysdeps/x86_64/strcpy.S

Packit Service 82fcde
/* strcpy/stpcpy implementation for x86-64.
Packit Service 82fcde
   Copyright (C) 2002-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Andreas Jaeger <aj@suse.de>, 2002.
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
#ifndef USE_AS_STPCPY
Packit Service 82fcde
# define STRCPY strcpy
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
	.text
Packit Service 82fcde
ENTRY (STRCPY)
Packit Service 82fcde
	movq %rsi, %rcx		/* Source register. */
Packit Service 82fcde
	andl $7, %ecx		/* mask alignment bits */
Packit Service 82fcde
	movq %rdi, %rdx		/* Duplicate destination pointer.  */
Packit Service 82fcde
Packit Service 82fcde
	jz 5f			/* aligned => start loop */
Packit Service 82fcde
Packit Service 82fcde
	neg %ecx		/* We need to align to 8 bytes.  */
Packit Service 82fcde
	addl $8,%ecx
Packit Service 82fcde
	/* Search the first bytes directly.  */
Packit Service 82fcde
0:
Packit Service 82fcde
	movb	(%rsi), %al	/* Fetch a byte */
Packit Service 82fcde
	testb	%al, %al	/* Is it NUL? */
Packit Service 82fcde
	movb	%al, (%rdx)	/* Store it */
Packit Service 82fcde
	jz	4f		/* If it was NUL, done! */
Packit Service 82fcde
	incq	%rsi
Packit Service 82fcde
	incq	%rdx
Packit Service 82fcde
	decl	%ecx
Packit Service 82fcde
	jnz	0b
Packit Service 82fcde
Packit Service 82fcde
5:
Packit Service 82fcde
	movq $0xfefefefefefefeff,%r8
Packit Service 82fcde
Packit Service 82fcde
	/* Now the sources is aligned.  Unfortunatly we cannot force
Packit Service 82fcde
	   to have both source and destination aligned, so ignore the
Packit Service 82fcde
	   alignment of the destination.  */
Packit Service 82fcde
	.p2align 4
Packit Service 82fcde
1:
Packit Service 82fcde
	/* 1st unroll.  */
Packit Service 82fcde
	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
Packit Service 82fcde
	addq	$8, %rsi	/* Adjust pointer for next word.  */
Packit Service 82fcde
	movq	%rax, %r9	/* Save a copy for NUL finding.  */
Packit Service 82fcde
	addq	%r8, %r9	/* 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	3f		/* highest byte is NUL => return pointer */
Packit Service 82fcde
	xorq	%rax, %r9	/* (word+magic)^word */
Packit Service 82fcde
	orq	%r8, %r9	/* set all non-carry bits */
Packit Service 82fcde
	incq	%r9		/* 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
	jnz	3f		/* found NUL => return pointer */
Packit Service 82fcde
Packit Service 82fcde
	movq	%rax, (%rdx)	/* Write value to destination.  */
Packit Service 82fcde
	addq	$8, %rdx	/* Adjust pointer.  */
Packit Service 82fcde
Packit Service 82fcde
	/* 2nd unroll.  */
Packit Service 82fcde
	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
Packit Service 82fcde
	addq	$8, %rsi	/* Adjust pointer for next word.  */
Packit Service 82fcde
	movq	%rax, %r9	/* Save a copy for NUL finding.  */
Packit Service 82fcde
	addq	%r8, %r9	/* 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	3f		/* highest byte is NUL => return pointer */
Packit Service 82fcde
	xorq	%rax, %r9	/* (word+magic)^word */
Packit Service 82fcde
	orq	%r8, %r9	/* set all non-carry bits */
Packit Service 82fcde
	incq	%r9		/* 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
	jnz	3f		/* found NUL => return pointer */
Packit Service 82fcde
Packit Service 82fcde
	movq	%rax, (%rdx)	/* Write value to destination.  */
Packit Service 82fcde
	addq	$8, %rdx	/* Adjust pointer.  */
Packit Service 82fcde
Packit Service 82fcde
	/* 3rd unroll.  */
Packit Service 82fcde
	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
Packit Service 82fcde
	addq	$8, %rsi	/* Adjust pointer for next word.  */
Packit Service 82fcde
	movq	%rax, %r9	/* Save a copy for NUL finding.  */
Packit Service 82fcde
	addq	%r8, %r9	/* 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	3f		/* highest byte is NUL => return pointer */
Packit Service 82fcde
	xorq	%rax, %r9	/* (word+magic)^word */
Packit Service 82fcde
	orq	%r8, %r9	/* set all non-carry bits */
Packit Service 82fcde
	incq	%r9		/* 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
	jnz	3f		/* found NUL => return pointer */
Packit Service 82fcde
Packit Service 82fcde
	movq	%rax, (%rdx)	/* Write value to destination.  */
Packit Service 82fcde
	addq	$8, %rdx	/* Adjust pointer.  */
Packit Service 82fcde
Packit Service 82fcde
	/* 4th unroll.  */
Packit Service 82fcde
	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
Packit Service 82fcde
	addq	$8, %rsi	/* Adjust pointer for next word.  */
Packit Service 82fcde
	movq	%rax, %r9	/* Save a copy for NUL finding.  */
Packit Service 82fcde
	addq	%r8, %r9	/* 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	3f		/* highest byte is NUL => return pointer */
Packit Service 82fcde
	xorq	%rax, %r9	/* (word+magic)^word */
Packit Service 82fcde
	orq	%r8, %r9	/* set all non-carry bits */
Packit Service 82fcde
	incq	%r9		/* 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
	jnz	3f		/* found NUL => return pointer */
Packit Service 82fcde
Packit Service 82fcde
	movq	%rax, (%rdx)	/* Write value to destination.  */
Packit Service 82fcde
	addq	$8, %rdx	/* Adjust pointer.  */
Packit Service 82fcde
	jmp	1b		/* Next iteration.  */
Packit Service 82fcde
Packit Service 82fcde
	/* Do the last few bytes. %rax contains the value to write.
Packit Service 82fcde
	   The loop is unrolled twice.  */
Packit Service 82fcde
	.p2align 4
Packit Service 82fcde
3:
Packit Service 82fcde
	/* Note that stpcpy needs to return with the value of the NUL
Packit Service 82fcde
	   byte.  */
Packit Service 82fcde
	movb	%al, (%rdx)	/* 1st byte.  */
Packit Service 82fcde
	testb	%al, %al	/* Is it NUL.  */
Packit Service 82fcde
	jz	4f		/* yes, finish.  */
Packit Service 82fcde
	incq	%rdx		/* Increment destination.  */
Packit Service 82fcde
	movb	%ah, (%rdx)	/* 2nd byte.  */
Packit Service 82fcde
	testb	%ah, %ah	/* Is it NUL?.  */
Packit Service 82fcde
	jz	4f		/* yes, finish.  */
Packit Service 82fcde
	incq	%rdx		/* Increment destination.  */
Packit Service 82fcde
	shrq	$16, %rax	/* Shift...  */
Packit Service 82fcde
	jmp	3b		/* and look at next two bytes in %rax.  */
Packit Service 82fcde
Packit Service 82fcde
4:
Packit Service 82fcde
#ifdef USE_AS_STPCPY
Packit Service 82fcde
	movq	%rdx, %rax	/* Destination is return value.  */
Packit Service 82fcde
#else
Packit Service 82fcde
	movq	%rdi, %rax	/* Source is return value.  */
Packit Service 82fcde
#endif
Packit Service 82fcde
	retq
Packit Service 82fcde
END (STRCPY)
Packit Service 82fcde
#ifndef USE_AS_STPCPY
Packit Service 82fcde
libc_hidden_builtin_def (strcpy)
Packit Service 82fcde
#endif