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

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