diff options
Diffstat (limited to 'sysdeps/s390')
-rw-r--r-- | sysdeps/s390/mempcpy.S | 19 | ||||
-rw-r--r-- | sysdeps/s390/multiarch/Makefile | 3 | ||||
-rw-r--r-- | sysdeps/s390/multiarch/ifunc-impl-list.c | 7 | ||||
-rw-r--r-- | sysdeps/s390/multiarch/mempcpy.c | 26 | ||||
-rw-r--r-- | sysdeps/s390/s390-32/memcpy.S | 50 | ||||
-rw-r--r-- | sysdeps/s390/s390-32/multiarch/memcpy-s390.S | 31 | ||||
-rw-r--r-- | sysdeps/s390/s390-64/memcpy.S | 47 | ||||
-rw-r--r-- | sysdeps/s390/s390-64/multiarch/memcpy-s390x.S | 29 |
8 files changed, 167 insertions, 45 deletions
diff --git a/sysdeps/s390/mempcpy.S b/sysdeps/s390/mempcpy.S new file mode 100644 index 0000000000..c62074b9b1 --- /dev/null +++ b/sysdeps/s390/mempcpy.S @@ -0,0 +1,19 @@ +/* CPU specific mempcpy without multiarch - 32/64 bit S/390 version. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* mempcpy is implemented in memcpy.S. */ diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile index 0805b07984..89324cadc4 100644 --- a/sysdeps/s390/multiarch/Makefile +++ b/sysdeps/s390/multiarch/Makefile @@ -18,7 +18,8 @@ sysdep_routines += strlen strlen-vx strlen-c \ memchr memchr-vx \ rawmemchr rawmemchr-vx rawmemchr-c \ memccpy memccpy-vx memccpy-c \ - memrchr memrchr-vx memrchr-c + memrchr memrchr-vx memrchr-c \ + mempcpy endif ifeq ($(subdir),wcsmbs) diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c index 62a435983c..89898ecdd9 100644 --- a/sysdeps/s390/multiarch/ifunc-impl-list.c +++ b/sysdeps/s390/multiarch/ifunc-impl-list.c @@ -69,6 +69,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, S390_IS_Z10 (stfle_bits), __memcpy_z10) IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_default)) + IFUNC_IMPL (i, name, mempcpy, + IFUNC_IMPL_ADD (array, i, mempcpy, + S390_IS_Z196 (stfle_bits), ____mempcpy_z196) + IFUNC_IMPL_ADD (array, i, mempcpy, + S390_IS_Z10 (stfle_bits), ____mempcpy_z10) + IFUNC_IMPL_ADD (array, i, mempcpy, 1, ____mempcpy_default)) + #endif /* SHARED */ #ifdef HAVE_S390_VX_ASM_SUPPORT diff --git a/sysdeps/s390/multiarch/mempcpy.c b/sysdeps/s390/multiarch/mempcpy.c new file mode 100644 index 0000000000..34d8329ba8 --- /dev/null +++ b/sysdeps/s390/multiarch/mempcpy.c @@ -0,0 +1,26 @@ +/* Multiple versions of mempcpy. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + + +#if defined SHARED && IS_IN (libc) +# include <ifunc-resolve.h> +s390_libc_ifunc (__mempcpy) + +__asm__ (".weak mempcpy\n\t" + ".set mempcpy,__mempcpy\n\t"); +#endif diff --git a/sysdeps/s390/s390-32/memcpy.S b/sysdeps/s390/s390-32/memcpy.S index 2ac51ab62e..6be5104b68 100644 --- a/sysdeps/s390/s390-32/memcpy.S +++ b/sysdeps/s390/s390-32/memcpy.S @@ -25,12 +25,23 @@ %r3 = address of source memory area %r4 = number of bytes to copy. */ -#ifdef USE_MULTIARCH -ENTRY(__memcpy_default) -#else -ENTRY(memcpy) + .text +ENTRY(__mempcpy) + .machine "g5" + lr %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_G5_start +END(__mempcpy) +#ifndef USE_MULTIARCH +libc_hidden_def (__mempcpy) +weak_alias (__mempcpy, mempcpy) +libc_hidden_builtin_def (mempcpy) #endif + +ENTRY(memcpy) .machine "g5" + lr %r1,%r2 # r1: Use as dest ; r2: Return dest +.L_G5_start: st %r13,52(%r15) .cfi_offset 13, -44 basr %r13,0 @@ -41,14 +52,13 @@ ENTRY(memcpy) lr %r5,%r4 srl %r5,8 ltr %r5,%r5 - lr %r1,%r2 jne .L_G5_13 ex %r4,.L_G5_17-.L_G5_16(%r13) .L_G5_4: l %r13,52(%r15) br %r14 .L_G5_13: - chi %r5,4096 # Switch to mvcle for copies >1MB + chi %r5,4096 # Switch to mvcle for copies >1MB jh __memcpy_mvcle .L_G5_12: mvc 0(256,%r1),0(%r3) @@ -59,24 +69,24 @@ ENTRY(memcpy) j .L_G5_4 .L_G5_17: mvc 0(1,%r1),0(%r3) -#ifdef USE_MULTIARCH -END(__memcpy_default) -#else END(memcpy) +#ifndef USE_MULTIARCH libc_hidden_builtin_def (memcpy) #endif ENTRY(__memcpy_mvcle) - # Using as standalone function will result in unexpected - # results since the length field is incremented by 1 in order to - # compensate the changes already done in the functions above. - ahi %r4,1 # length + 1 - lr %r5,%r4 # source length - lr %r4,%r3 # source address - lr %r3,%r5 # destination length = source length + # Using as standalone function will result in unexpected + # results since the length field is incremented by 1 in order to + # compensate the changes already done in the functions above. + lr %r0,%r2 # backup return dest [ + n ] + ahi %r4,1 # length + 1 + lr %r5,%r4 # source length + lr %r4,%r3 # source address + lr %r2,%r1 # destination address + lr %r3,%r5 # destination length = source length .L_MVCLE_1: - mvcle %r2,%r4,0 # thats it, MVCLE is your friend - jo .L_MVCLE_1 - lr %r2,%r1 # return destination address - br %r14 + mvcle %r2,%r4,0 # thats it, MVCLE is your friend + jo .L_MVCLE_1 + lr %r2,%r0 # return destination address + br %r14 END(__memcpy_mvcle) diff --git a/sysdeps/s390/s390-32/multiarch/memcpy-s390.S b/sysdeps/s390/s390-32/multiarch/memcpy-s390.S index 92ffaea5ed..297a8943b1 100644 --- a/sysdeps/s390/s390-32/multiarch/memcpy-s390.S +++ b/sysdeps/s390/s390-32/multiarch/memcpy-s390.S @@ -29,14 +29,23 @@ #if defined SHARED && IS_IN (libc) +ENTRY(____mempcpy_z196) + .machine "z196" + .machinemode "zarch_nohighgprs" + lr %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_Z196_start +END(____mempcpy_z196) + ENTRY(__memcpy_z196) .machine "z196" .machinemode "zarch_nohighgprs" + lr %r1,%r2 # r1: Use as dest ; r2: Return dest +.L_Z196_start: llgfr %r4,%r4 ltgr %r4,%r4 je .L_Z196_4 aghi %r4,-1 - lr %r1,%r2 srlg %r5,%r4,8 ltgr %r5,%r5 jne .L_Z196_5 @@ -60,13 +69,22 @@ ENTRY(__memcpy_z196) mvc 0(1,%r1),0(%r3) END(__memcpy_z196) +ENTRY(____mempcpy_z10) + .machine "z10" + .machinemode "zarch_nohighgprs" + lr %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_Z10_start +END(____mempcpy_z10) + ENTRY(__memcpy_z10) .machine "z10" .machinemode "zarch_nohighgprs" + lr %r1,%r2 # r1: Use as dest ; r2: Return dest +.L_Z10_start: llgfr %r4,%r4 cgije %r4,0,.L_Z10_4 aghi %r4,-1 - lr %r1,%r2 srlg %r5,%r4,8 cgijlh %r5,0,.L_Z10_13 .L_Z10_3: @@ -88,14 +106,23 @@ ENTRY(__memcpy_z10) mvc 0(1,%r1),0(%r3) END(__memcpy_z10) +# define __mempcpy ____mempcpy_default #endif /* SHARED && IS_IN (libc) */ +#define memcpy __memcpy_default #include "../memcpy.S" +#undef memcpy #if defined SHARED && IS_IN (libc) .globl __GI_memcpy .set __GI_memcpy,__memcpy_default +.globl __GI_mempcpy +.set __GI_mempcpy,____mempcpy_default +.globl __GI___mempcpy +.set __GI___mempcpy,____mempcpy_default #else .globl memcpy .set memcpy,__memcpy_default +.weak mempcpy +.set mempcpy,__mempcpy #endif diff --git a/sysdeps/s390/s390-64/memcpy.S b/sysdeps/s390/s390-64/memcpy.S index 9d60a14ccc..e3ace0c87b 100644 --- a/sysdeps/s390/s390-64/memcpy.S +++ b/sysdeps/s390/s390-64/memcpy.S @@ -27,19 +27,27 @@ .text +ENTRY(__mempcpy) + .machine "z900" + lgr %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_Z900_start +END(__mempcpy) +#ifndef USE_MULTIARCH +libc_hidden_def (__mempcpy) +weak_alias (__mempcpy, mempcpy) +libc_hidden_builtin_def (mempcpy) +#endif -#ifdef USE_MULTIARCH -ENTRY(__memcpy_default) -#else ENTRY(memcpy) -#endif .machine "z900" + lgr %r1,%r2 # r1: Use as dest ; r2: Return dest +.L_Z900_start: ltgr %r4,%r4 je .L_Z900_4 aghi %r4,-1 srlg %r5,%r4,8 ltgr %r5,%r5 - lgr %r1,%r2 jne .L_Z900_13 .L_Z900_3: larl %r5,.L_Z900_15 @@ -57,25 +65,24 @@ ENTRY(memcpy) j .L_Z900_3 .L_Z900_15: mvc 0(1,%r1),0(%r3) - -#ifdef USE_MULTIARCH -END(__memcpy_default) -#else END(memcpy) +#ifndef USE_MULTIARCH libc_hidden_builtin_def (memcpy) #endif ENTRY(__memcpy_mvcle) - # Using as standalone function will result in unexpected - # results since the length field is incremented by 1 in order to - # compensate the changes already done in the functions above. - aghi %r4,1 # length + 1 - lgr %r5,%r4 # source length - lgr %r4,%r3 # source address - lgr %r3,%r5 # destination length = source length + # Using as standalone function will result in unexpected + # results since the length field is incremented by 1 in order to + # compensate the changes already done in the functions above. + lgr %r0,%r2 # backup return dest [ + n ] + aghi %r4,1 # length + 1 + lgr %r5,%r4 # source length + lgr %r4,%r3 # source address + lgr %r2,%r1 # destination address + lgr %r3,%r5 # destination length = source length .L_MVCLE_1: - mvcle %r2,%r4,0 # thats it, MVCLE is your friend - jo .L_MVCLE_1 - lgr %r2,%r1 # return destination address - br %r14 + mvcle %r2,%r4,0 # thats it, MVCLE is your friend + jo .L_MVCLE_1 + lgr %r2,%r0 # return destination address + br %r14 END(__memcpy_mvcle) diff --git a/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S b/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S index 8f54526b76..0f5a36edd1 100644 --- a/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S +++ b/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S @@ -29,12 +29,20 @@ #if defined SHARED && IS_IN (libc) +ENTRY(____mempcpy_z196) + .machine "z196" + lgr %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_Z196_start +END(____mempcpy_z196) + ENTRY(__memcpy_z196) .machine "z196" + lgr %r1,%r2 # r1: Use as dest ; r2: Return dest +.L_Z196_start: ltgr %r4,%r4 je .L_Z196_4 aghi %r4,-1 - lgr %r1,%r2 srlg %r5,%r4,8 ltgr %r5,%r5 jne .L_Z196_5 @@ -58,11 +66,19 @@ ENTRY(__memcpy_z196) mvc 0(1,%r1),0(%r3) END(__memcpy_z196) +ENTRY(____mempcpy_z10) + .machine "z10" + lgr %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_Z10_start +END(____mempcpy_z10) + ENTRY(__memcpy_z10) .machine "z10" + lgr %r1,%r2 # r1: Use as dest ; r2: Return dest +.L_Z10_start: cgije %r4,0,.L_Z10_4 aghi %r4,-1 - lgr %r1,%r2 srlg %r5,%r4,8 cgijlh %r5,0,.L_Z10_13 .L_Z10_3: @@ -84,14 +100,23 @@ ENTRY(__memcpy_z10) mvc 0(1,%r1),0(%r3) END(__memcpy_z10) +# define __mempcpy ____mempcpy_default #endif /* SHARED && IS_IN (libc) */ +#define memcpy __memcpy_default #include "../memcpy.S" +#undef memcpy #if defined SHARED && IS_IN (libc) .globl __GI_memcpy .set __GI_memcpy,__memcpy_default +.globl __GI_mempcpy +.set __GI_mempcpy,____mempcpy_default +.globl __GI___mempcpy +.set __GI___mempcpy,____mempcpy_default #else .globl memcpy .set memcpy,__memcpy_default +.weak mempcpy +.set mempcpy,__mempcpy #endif |