Blame sysdeps/powerpc/powerpc64/le/power9/strcpy.S

Packit Service 8a06ac
/* Optimized strcpy implementation for PowerPC64/POWER9.
Packit Service 8a06ac
   Copyright (C) 2020 Free Software Foundation, Inc.
Packit Service 8a06ac
   This file is part of the GNU C Library.
Packit Service 8a06ac
Packit Service 8a06ac
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 8a06ac
   modify it under the terms of the GNU Lesser General Public
Packit Service 8a06ac
   License as published by the Free Software Foundation; either
Packit Service 8a06ac
   version 2.1 of the License, or (at your option) any later version.
Packit Service 8a06ac
Packit Service 8a06ac
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 8a06ac
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 8a06ac
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 8a06ac
   Lesser General Public License for more details.
Packit Service 8a06ac
Packit Service 8a06ac
   You should have received a copy of the GNU Lesser General Public
Packit Service 8a06ac
   License along with the GNU C Library; if not, see
Packit Service 8a06ac
   <https://www.gnu.org/licenses/>.  */
Packit Service 8a06ac
Packit Service 8a06ac
#include <sysdep.h>
Packit Service 8a06ac
Packit Service fed76d
#ifdef USE_AS_STPCPY
Packit Service fed76d
# ifndef STPCPY
Packit Service fed76d
#   define FUNC_NAME __stpcpy
Packit Service fed76d
# else
Packit Service fed76d
#   define FUNC_NAME STPCPY
Packit Service fed76d
# endif
Packit Service fed76d
#else
Packit Service fed76d
# ifndef STRCPY
Packit Service fed76d
#  define FUNC_NAME strcpy
Packit Service fed76d
# else
Packit Service fed76d
#  define FUNC_NAME STRCPY
Packit Service fed76d
# endif
Packit Service fed76d
#endif  /* !USE_AS_STPCPY  */
Packit Service 8a06ac
Packit Service 8a06ac
/* Implements the function
Packit Service 8a06ac
Packit Service 8a06ac
   char * [r3] strcpy (char *dest [r3], const char *src [r4])
Packit Service 8a06ac
Packit Service fed76d
   or
Packit Service fed76d
Packit Service fed76d
   char * [r3] stpcpy (char *dest [r3], const char *src [r4])
Packit Service fed76d
Packit Service fed76d
   if USE_AS_STPCPY is defined.
Packit Service fed76d
Packit Service 8a06ac
   The implementation can load bytes past a null terminator, but only
Packit Service 8a06ac
   up to the next 16B boundary, so it never crosses a page.  */
Packit Service 8a06ac
Packit Service 8a06ac
.machine power9
Packit Service fed76d
ENTRY_TOCLESS (FUNC_NAME, 4)
Packit Service 8a06ac
	CALL_MCOUNT 2
Packit Service 8a06ac
Packit Service 8a06ac
	/* NULL string optimisation  */
Packit Service 8a06ac
	lbz	r0,0(r4)
Packit Service 8a06ac
	stb	r0,0(r3)
Packit Service 8a06ac
	cmpwi	r0,0
Packit Service 8a06ac
	beqlr
Packit Service 8a06ac
Packit Service 8a06ac
	addi	r4,r4,1
Packit Service 8a06ac
	addi	r11,r3,1
Packit Service 8a06ac
Packit Service 8a06ac
	vspltisb v18,0		/* Zeroes in v18  */
Packit Service 8a06ac
Packit Service 8a06ac
	neg	r5,r4
Packit Service 8a06ac
	rldicl	r9,r5,0,60	/* How many bytes to get source 16B aligned?  */
Packit Service 8a06ac
Packit Service 8a06ac
	/* Get source 16B aligned  */
Packit Service 8a06ac
	lvx	v0,0,r4
Packit Service 8a06ac
	lvsr	v1,0,r4
Packit Service 8a06ac
	vperm	v0,v18,v0,v1
Packit Service 8a06ac
Packit Service 8a06ac
	vcmpequb v6,v0,v18	/* 0xff if byte is NULL, 0x00 otherwise  */
Packit Service fed76d
	vctzlsbb r7,v6		/* Number of trailing zeroes  */
Packit Service fed76d
	addi	r8,r7,1		/* Add null terminator  */
Packit Service 8a06ac
Packit Service 8a06ac
	/* r8 = bytes including null
Packit Service 8a06ac
	   r9 = bytes to get source 16B aligned
Packit Service 8a06ac
	   if r8 > r9
Packit Service 8a06ac
	      no null, copy r9 bytes
Packit Service 8a06ac
	   else
Packit Service 8a06ac
	      there is a null, copy r8 bytes and return.  */
Packit Service 8a06ac
	cmpd	r8,r9
Packit Service 8a06ac
	bgt	L(no_null)
Packit Service 8a06ac
Packit Service 8a06ac
	sldi	r10,r8,56	/* stxvl wants size in top 8 bits  */
Packit Service 8a06ac
	stxvl	32+v0,r11,r10	/* Partial store  */
Packit Service 8a06ac
Packit Service fed76d
#ifdef USE_AS_STPCPY
Packit Service fed76d
	/* stpcpy returns the dest address plus the size not counting the
Packit Service fed76d
	   final '\0'.  */
Packit Service fed76d
	add	r3,r11,r7
Packit Service fed76d
#endif
Packit Service 8a06ac
	blr
Packit Service 8a06ac
Packit Service 8a06ac
L(no_null):
Packit Service 8a06ac
	sldi	r10,r9,56	/* stxvl wants size in top 8 bits  */
Packit Service 8a06ac
	stxvl	32+v0,r11,r10	/* Partial store  */
Packit Service 8a06ac
Packit Service 8a06ac
	add	r4,r4,r9
Packit Service 8a06ac
	add	r11,r11,r9
Packit Service 8a06ac
Packit Service 8a06ac
L(loop):
Packit Service 8a06ac
	lxv	32+v0,0(r4)
Packit Service 8a06ac
	vcmpequb. v6,v0,v18	/* Any zero bytes?  */
Packit Service 8a06ac
	bne	cr6,L(tail1)
Packit Service 8a06ac
Packit Service 8a06ac
	lxv	32+v1,16(r4)
Packit Service 8a06ac
	vcmpequb. v6,v1,v18	/* Any zero bytes?  */
Packit Service 8a06ac
	bne	cr6,L(tail2)
Packit Service 8a06ac
Packit Service 8a06ac
	lxv	32+v2,32(r4)
Packit Service 8a06ac
	vcmpequb. v6,v2,v18	/* Any zero bytes?  */
Packit Service 8a06ac
	bne	cr6,L(tail3)
Packit Service 8a06ac
Packit Service 8a06ac
	lxv	32+v3,48(r4)
Packit Service 8a06ac
	vcmpequb. v6,v3,v18	/* Any zero bytes?  */
Packit Service 8a06ac
	bne	cr6,L(tail4)
Packit Service 8a06ac
Packit Service 8a06ac
	stxv	32+v0,0(r11)
Packit Service 8a06ac
	stxv	32+v1,16(r11)
Packit Service 8a06ac
	stxv	32+v2,32(r11)
Packit Service 8a06ac
	stxv	32+v3,48(r11)
Packit Service 8a06ac
Packit Service 8a06ac
	addi	r4,r4,64
Packit Service 8a06ac
	addi	r11,r11,64
Packit Service 8a06ac
Packit Service 8a06ac
	b	L(loop)
Packit Service 8a06ac
Packit Service 8a06ac
L(tail1):
Packit Service 8a06ac
	vctzlsbb r8,v6
Packit Service fed76d
	addi	r9,r8,1
Packit Service fed76d
	sldi	r9,r9,56	/* stxvl wants size in top 8 bits  */
Packit Service 8a06ac
	stxvl	32+v0,r11,r9
Packit Service fed76d
#ifdef USE_AS_STPCPY
Packit Service fed76d
	/* stpcpy returns the dest address plus the size not counting the
Packit Service fed76d
	   final '\0'.  */
Packit Service fed76d
	add	r3,r11,r8
Packit Service fed76d
#endif
Packit Service 8a06ac
	blr
Packit Service 8a06ac
Packit Service 8a06ac
L(tail2):
Packit Service 8a06ac
	stxv	32+v0,0(r11)
Packit Service 8a06ac
	vctzlsbb r8,v6		/* Number of trailing zeroes  */
Packit Service fed76d
	addi	r9,r8,1		/* Add null terminator  */
Packit Service fed76d
	sldi	r10,r9,56	/* stxvl wants size in top 8 bits  */
Packit Service 8a06ac
	addi	r11,r11,16
Packit Service 8a06ac
	stxvl	32+v1,r11,r10	/* Partial store  */
Packit Service fed76d
#ifdef USE_AS_STPCPY
Packit Service fed76d
	/* stpcpy returns the dest address plus the size not counting the
Packit Service fed76d
	   final '\0'.  */
Packit Service fed76d
	add	r3,r11,r8
Packit Service fed76d
#endif
Packit Service 8a06ac
	blr
Packit Service 8a06ac
Packit Service 8a06ac
L(tail3):
Packit Service 8a06ac
	stxv	32+v0,0(r11)
Packit Service 8a06ac
	stxv	32+v1,16(r11)
Packit Service 8a06ac
	vctzlsbb r8,v6		/* Number of trailing zeroes  */
Packit Service fed76d
	addi	r9,r8,1		/* Add null terminator  */
Packit Service fed76d
	sldi	r10,r9,56	/* stxvl wants size in top 8 bits  */
Packit Service 8a06ac
	addi	r11,r11,32
Packit Service 8a06ac
	stxvl	32+v2,r11,r10	/* Partial store  */
Packit Service fed76d
#ifdef USE_AS_STPCPY
Packit Service fed76d
	/* stpcpy returns the dest address plus the size not counting the
Packit Service fed76d
	   final '\0'.  */
Packit Service fed76d
	add	r3,r11,r8
Packit Service fed76d
#endif
Packit Service 8a06ac
	blr
Packit Service 8a06ac
Packit Service 8a06ac
L(tail4):
Packit Service 8a06ac
	stxv	32+v0,0(r11)
Packit Service 8a06ac
	stxv	32+v1,16(r11)
Packit Service 8a06ac
	stxv	32+v2,32(r11)
Packit Service 8a06ac
	vctzlsbb r8,v6		/* Number of trailing zeroes  */
Packit Service fed76d
	addi	r9,r8,1		/* Add null terminator  */
Packit Service fed76d
	sldi	r10,r9,56	/* stxvl wants size in top 8 bits  */
Packit Service 8a06ac
	addi	r11,r11,48
Packit Service 8a06ac
	stxvl	32+v3,r11,r10	/* Partial store  */
Packit Service fed76d
#ifdef USE_AS_STPCPY
Packit Service fed76d
	/* stpcpy returns the dest address plus the size not counting the
Packit Service fed76d
	   final '\0'.  */
Packit Service fed76d
	add	r3,r11,r8
Packit Service fed76d
#endif
Packit Service 8a06ac
	blr
Packit Service fed76d
END (FUNC_NAME)
Packit Service fed76d
#ifndef USE_AS_STPCPY
Packit Service 8a06ac
libc_hidden_builtin_def (strcpy)
Packit Service fed76d
#endif