|
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
|