diff options
Diffstat (limited to 'REORG.TODO/sysdeps/s390')
290 files changed, 25677 insertions, 0 deletions
diff --git a/REORG.TODO/sysdeps/s390/Implies b/REORG.TODO/sysdeps/s390/Implies new file mode 100644 index 0000000000..1945b1f4bb --- /dev/null +++ b/REORG.TODO/sysdeps/s390/Implies @@ -0,0 +1,3 @@ +ieee754/ldbl-128 +ieee754/dbl-64 +ieee754/flt-32 diff --git a/REORG.TODO/sysdeps/s390/Makefile b/REORG.TODO/sysdeps/s390/Makefile new file mode 100644 index 0000000000..8a54f88cd7 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/Makefile @@ -0,0 +1,31 @@ +ifeq ($(subdir),iconvdata) +ISO-8859-1_CP037_Z900-routines := iso-8859-1_cp037_z900 +ISO-8859-1_CP037_Z900-map := gconv.map + +UTF8_UTF32_Z9-routines := utf8-utf32-z9 +UTF8_UTF32_Z9-map := gconv.map + +UTF16_UTF32_Z9-routines := utf16-utf32-z9 +UTF16_UTF32_Z9-map := gconv.map + +UTF8_UTF16_Z9-routines := utf8-utf16-z9 +UTF8_UTF16_Z9-map := gconv.map + +s390x-iconv-modules = ISO-8859-1_CP037_Z900 UTF8_UTF16_Z9 UTF16_UTF32_Z9 UTF8_UTF32_Z9 + +extra-modules-left += $(s390x-iconv-modules) +include extra-module.mk + +cpp-srcs-left := $(foreach mod,$(s390x-iconv-modules),$($(mod)-routines)) +lib := iconvdata +include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) + +extra-objs += $(addsuffix .so, $(s390x-iconv-modules)) +install-others += $(patsubst %, $(inst_gconvdir)/%.so, $(s390x-iconv-modules)) + +$(patsubst %, $(inst_gconvdir)/%.so, $(s390x-iconv-modules)) : \ +$(inst_gconvdir)/%.so: $(objpfx)%.so $(+force) + $(do-install-program) + +sysdeps-gconv-modules = ../sysdeps/s390/gconv-modules +endif diff --git a/REORG.TODO/sysdeps/s390/Versions b/REORG.TODO/sysdeps/s390/Versions new file mode 100644 index 0000000000..8417623353 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/Versions @@ -0,0 +1,17 @@ +libc { + GLIBC_2.19 { + setjmp; _setjmp; __sigsetjmp; + longjmp; _longjmp; siglongjmp; + } +} + +ld { + GLIBC_2.3 { + # runtime interface to TLS + __tls_get_offset; + } + GLIBC_PRIVATE { + # Exported by ld used by libc. + __tls_get_addr_internal; + } +} diff --git a/REORG.TODO/sysdeps/s390/abort-instr.h b/REORG.TODO/sysdeps/s390/abort-instr.h new file mode 100644 index 0000000000..825601ad50 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/abort-instr.h @@ -0,0 +1,2 @@ +/* An op-code of 0 should crash any program. */ +#define ABORT_INSTRUCTION __asm__ (".word 0") diff --git a/REORG.TODO/sysdeps/s390/asm-syntax.h b/REORG.TODO/sysdeps/s390/asm-syntax.h new file mode 100644 index 0000000000..00b6338a7b --- /dev/null +++ b/REORG.TODO/sysdeps/s390/asm-syntax.h @@ -0,0 +1,24 @@ +/* Definitions for S/390 syntax variations. + Copyright (C) 1992-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in the GNU MP 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/>. */ + +#undef ALIGN +#define ALIGN(log) .align 1<<log + +#undef L +#define L(body) .L##body diff --git a/REORG.TODO/sysdeps/s390/atomic-machine.h b/REORG.TODO/sysdeps/s390/atomic-machine.h new file mode 100644 index 0000000000..adaca40798 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/atomic-machine.h @@ -0,0 +1,161 @@ +/* Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. + + 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/>. */ + +#include <stdint.h> + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +/* Activate all C11 atomic builtins. + + Note: + E.g. in nptl/pthread_key_delete.c if compiled with GCCs 6 and before, + an extra stack-frame is generated and the old value is stored on stack + before cs instruction but it never loads this value from stack. + An unreleased GCC 7 omit those stack operations. + + E.g. in nptl/pthread_once.c the condition code of cs instruction is + evaluated by a sequence of ipm, sra, compare and jump instructions instead + of one conditional jump instruction. This also occurs with an unreleased + GCC 7. + + The atomic_fetch_abc_def C11 builtins are now using load-and-abc instructions + on z196 zarch and higher cpus instead of a loop with compare-and-swap + instruction. */ +#define USE_ATOMIC_COMPILER_BUILTINS 1 + +#ifdef __s390x__ +# define __HAVE_64B_ATOMICS 1 +#else +# define __HAVE_64B_ATOMICS 0 +#endif + +#define ATOMIC_EXCHANGE_USES_CAS 1 + +/* Implement some of the non-C11 atomic macros from include/atomic.h + with help of the C11 atomic builtins. The other non-C11 atomic macros + are using the macros defined here. */ + +/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL. + Return the old *MEM value. */ +#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + ({ __atomic_check_size((mem)); \ + typeof ((__typeof (*(mem))) *(mem)) __atg1_oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__atg1_oldval, \ + newval, 1, __ATOMIC_ACQUIRE, \ + __ATOMIC_RELAXED); \ + __atg1_oldval; }) +#define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \ + ({ __atomic_check_size((mem)); \ + typeof ((__typeof (*(mem))) *(mem)) __atg1_2_oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__atg1_2_oldval, \ + newval, 1, __ATOMIC_RELEASE, \ + __ATOMIC_RELAXED); \ + __atg1_2_oldval; }) + +/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL. + Return zero if *MEM was changed or non-zero if no exchange happened. */ +#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + ({ __atomic_check_size((mem)); \ + typeof ((__typeof (*(mem))) *(mem)) __atg2_oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__atg2_oldval, newval, \ + 1, __ATOMIC_ACQUIRE, \ + __ATOMIC_RELAXED); }) +#define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + atomic_compare_and_exchange_bool_acq (mem, newval, oldval) + +/* Store NEWVALUE in *MEM and return the old value. */ +#define atomic_exchange_acq(mem, newvalue) \ + ({ __atomic_check_size((mem)); \ + __atomic_exchange_n (mem, newvalue, __ATOMIC_ACQUIRE); }) +#define atomic_exchange_rel(mem, newvalue) \ + ({ __atomic_check_size((mem)); \ + __atomic_exchange_n (mem, newvalue, __ATOMIC_RELEASE); }) + +/* Add VALUE to *MEM and return the old value of *MEM. */ +/* The gcc builtin uses load-and-add instruction on z196 zarch and higher cpus + instead of a loop with compare-and-swap instruction. */ +# define atomic_exchange_and_add_acq(mem, operand) \ + ({ __atomic_check_size((mem)); \ + __atomic_fetch_add ((mem), (operand), __ATOMIC_ACQUIRE); }) +# define atomic_exchange_and_add_rel(mem, operand) \ + ({ __atomic_check_size((mem)); \ + __atomic_fetch_add ((mem), (operand), __ATOMIC_RELEASE); }) +#define catomic_exchange_and_add(mem, value) \ + atomic_exchange_and_add (mem, value) + +/* Atomically *mem |= mask and return the old value of *mem. */ +/* The gcc builtin uses load-and-or instruction on z196 zarch and higher cpus + instead of a loop with compare-and-swap instruction. */ +#define atomic_or_val(mem, operand) \ + ({ __atomic_check_size((mem)); \ + __atomic_fetch_or ((mem), (operand), __ATOMIC_ACQUIRE); }) +/* Atomically *mem |= mask. */ +#define atomic_or(mem, mask) \ + do { \ + atomic_or_val (mem, mask); \ + } while (0) +#define catomic_or(mem, mask) \ + atomic_or (mem, mask) + +/* Atomically *mem |= 1 << bit and return true if the bit was set in old value + of *mem. */ +/* The load-and-or instruction is used on z196 zarch and higher cpus + instead of a loop with compare-and-swap instruction. */ +#define atomic_bit_test_set(mem, bit) \ + ({ __typeof (*(mem)) __atg14_old; \ + __typeof (mem) __atg14_memp = (mem); \ + __typeof (*(mem)) __atg14_mask = ((__typeof (*(mem))) 1 << (bit)); \ + __atg14_old = atomic_or_val (__atg14_memp, __atg14_mask); \ + __atg14_old & __atg14_mask; }) + +/* Atomically *mem &= mask and return the old value of *mem. */ +/* The gcc builtin uses load-and-and instruction on z196 zarch and higher cpus + instead of a loop with compare-and-swap instruction. */ +#define atomic_and_val(mem, operand) \ + ({ __atomic_check_size((mem)); \ + __atomic_fetch_and ((mem), (operand), __ATOMIC_ACQUIRE); }) +/* Atomically *mem &= mask. */ +#define atomic_and(mem, mask) \ + do { \ + atomic_and_val (mem, mask); \ + } while (0) +#define catomic_and(mem, mask) \ + atomic_and(mem, mask) diff --git a/REORG.TODO/sysdeps/s390/bits/byteswap-16.h b/REORG.TODO/sysdeps/s390/bits/byteswap-16.h new file mode 100644 index 0000000000..85ae5f5505 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/bits/byteswap-16.h @@ -0,0 +1,65 @@ +/* Macros to swap the order of bytes in 16-bit integer values. s390 version + Copyright (C) 2012-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#ifndef _BITS_BYTESWAP_H +# error "Never use <bits/byteswap-16.h> directly; include <byteswap.h> instead." +#endif + +#include <bits/wordsize.h> + +/* Swap bytes in 16 bit value. */ +#if defined __GNUC__ && __GNUC__ >= 2 +# if __WORDSIZE == 64 +# define __bswap_16(x) \ + (__extension__ \ + ({ unsigned short int __v, __x = (unsigned short int) (x); \ + if (__builtin_constant_p (x)) \ + __v = __bswap_constant_16 (__x); \ + else { \ + unsigned short int __tmp = (unsigned short int) (__x); \ + __asm__ __volatile__ ( \ + "lrvh %0,%1" \ + : "=&d" (__v) : "m" (__tmp) ); \ + } \ + __v; })) +# else +# define __bswap_16(x) \ + (__extension__ \ + ({ unsigned short int __v, __x = (unsigned short int) (x); \ + if (__builtin_constant_p (x)) \ + __v = __bswap_constant_16 (__x); \ + else { \ + unsigned short int __tmp = (unsigned short int) (__x); \ + __asm__ __volatile__ ( \ + "sr %0,%0\n" \ + "la 1,%1\n" \ + "icm %0,2,1(1)\n" \ + "ic %0,0(1)" \ + : "=&d" (__v) : "m" (__tmp) : "1"); \ + } \ + __v; })) +# endif +#else +/* This is better than nothing. */ +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif diff --git a/REORG.TODO/sysdeps/s390/bits/byteswap.h b/REORG.TODO/sysdeps/s390/bits/byteswap.h new file mode 100644 index 0000000000..6d5f65e6f8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/bits/byteswap.h @@ -0,0 +1,134 @@ +/* Macros to swap the order of bytes in integer values. s390 version. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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 _BYTESWAP_H && !defined _NETINET_IN_H && !defined _ENDIAN_H +# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead." +#endif + +#include <bits/wordsize.h> + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +#define __bswap_constant_16(x) \ + ((unsigned short int) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) + +/* Get __bswap_16. */ +#include <bits/byteswap-16.h> + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# if __WORDSIZE == 64 +# define __bswap_32(x) \ + (__extension__ \ + ({ unsigned int __v, __x = (x); \ + if (__builtin_constant_p (x)) \ + __v = __bswap_constant_32 (__x); \ + else { \ + unsigned int __tmp = (unsigned int) (__x); \ + __asm__ __volatile__ ( \ + "lrv %0,%1" \ + : "=&d" (__v) : "m" (__tmp)); \ + } \ + __v; })) +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ unsigned int __v, __x = (x); \ + if (__builtin_constant_p (x)) \ + __v = __bswap_constant_32 (__x); \ + else { \ + unsigned int __tmp = (unsigned int) (__x); \ + __asm__ __volatile__ ( \ + "la 1,%1\n" \ + "icm %0,8,3(1)\n" \ + "icm %0,4,2(1)\n" \ + "icm %0,2,1(1)\n" \ + "ic %0,0(1)" \ + : "=&d" (__v) : "m" (__tmp) : "1"); \ + } \ + __v; })) +# endif +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + +/* Swap bytes in 64 bit value. */ +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_constant_64(x) \ + (__extension__ ((((x) & 0xff00000000000000ul) >> 56) \ + | (((x) & 0x00ff000000000000ul) >> 40) \ + | (((x) & 0x0000ff0000000000ul) >> 24) \ + | (((x) & 0x000000ff00000000ul) >> 8) \ + | (((x) & 0x00000000ff000000ul) << 8) \ + | (((x) & 0x0000000000ff0000ul) << 24) \ + | (((x) & 0x000000000000ff00ul) << 40) \ + | (((x) & 0x00000000000000fful) << 56))) + +# if __WORDSIZE == 64 +# define __bswap_64(x) \ + (__extension__ \ + ({ unsigned long __w, __x = (x); \ + if (__builtin_constant_p (x)) \ + __w = __bswap_constant_64 (__x); \ + else { \ + unsigned long __tmp = (unsigned long) (__x); \ + __asm__ __volatile__ ( \ + "lrvg %0,%1" \ + : "=&d" (__w) : "m" (__tmp)); \ + } \ + __w; })) +# else +# define __bswap_64(x) \ + __extension__ \ + ({ union { unsigned long long int __ll; \ + unsigned long int __l[2]; } __w, __r; \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + __r.__ll; }) +# endif +#else +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +__extension__ +static __inline unsigned long long int +__bswap_64 (unsigned long long int __bsx) +{ + return __bswap_constant_64 (__bsx); +} +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/REORG.TODO/sysdeps/s390/bits/endian.h b/REORG.TODO/sysdeps/s390/bits/endian.h new file mode 100644 index 0000000000..ac27f0119a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/bits/endian.h @@ -0,0 +1,7 @@ +/* s390 is big-endian */ + +#ifndef _ENDIAN_H +# error "Never use <bits/endian.h> directly; include <endian.h> instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/REORG.TODO/sysdeps/s390/bits/flt-eval-method.h b/REORG.TODO/sysdeps/s390/bits/flt-eval-method.h new file mode 100644 index 0000000000..c0fc68af06 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/bits/flt-eval-method.h @@ -0,0 +1,24 @@ +/* Define __GLIBC_FLT_EVAL_METHOD. S/390 version. + Copyright (C) 2016-2017 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/>. */ + +#ifndef _MATH_H +# error "Never use <bits/flt-eval-method.h> directly; include <math.h> instead." +#endif + +/* This value is used because of a historical mistake. */ +#define __GLIBC_FLT_EVAL_METHOD 1 diff --git a/REORG.TODO/sysdeps/s390/bits/link.h b/REORG.TODO/sysdeps/s390/bits/link.h new file mode 100644 index 0000000000..5960b9642c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/bits/link.h @@ -0,0 +1,139 @@ +/* Copyright (C) 2005-2017 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/>. */ + +#ifndef _LINK_H +# error "Never include <bits/link.h> directly; use <link.h> instead." +#endif + +#if defined HAVE_S390_VX_ASM_SUPPORT +typedef char La_s390_vr[16]; +#endif + +#if __ELF_NATIVE_CLASS == 32 + +/* Registers for entry into PLT on s390-32. */ +typedef struct La_s390_32_regs +{ + uint32_t lr_r2; + uint32_t lr_r3; + uint32_t lr_r4; + uint32_t lr_r5; + uint32_t lr_r6; + double lr_fp0; + double lr_fp2; +# if defined HAVE_S390_VX_ASM_SUPPORT + La_s390_vr lr_v24; + La_s390_vr lr_v25; + La_s390_vr lr_v26; + La_s390_vr lr_v27; + La_s390_vr lr_v28; + La_s390_vr lr_v29; + La_s390_vr lr_v30; + La_s390_vr lr_v31; +# endif +} La_s390_32_regs; + +/* Return values for calls from PLT on s390-32. */ +typedef struct La_s390_32_retval +{ + uint32_t lrv_r2; + uint32_t lrv_r3; + double lrv_fp0; +# if defined HAVE_S390_VX_ASM_SUPPORT + La_s390_vr lrv_v24; +# endif +} La_s390_32_retval; + + +__BEGIN_DECLS + +extern Elf32_Addr la_s390_32_gnu_pltenter (Elf32_Sym *__sym, + unsigned int __ndx, + uintptr_t *__refcook, + uintptr_t *__defcook, + La_s390_32_regs *__regs, + unsigned int *__flags, + const char *__symname, + long int *__framesizep); +extern unsigned int la_s390_32_gnu_pltexit (Elf32_Sym *__sym, + unsigned int __ndx, + uintptr_t *__refcook, + uintptr_t *__defcook, + const La_s390_32_regs *__inregs, + La_s390_32_retval *__outregs, + const char *symname); + +__END_DECLS + +#else + +/* Registers for entry into PLT on s390-64. */ +typedef struct La_s390_64_regs +{ + uint64_t lr_r2; + uint64_t lr_r3; + uint64_t lr_r4; + uint64_t lr_r5; + uint64_t lr_r6; + double lr_fp0; + double lr_fp2; + double lr_fp4; + double lr_fp6; +# if defined HAVE_S390_VX_ASM_SUPPORT + La_s390_vr lr_v24; + La_s390_vr lr_v25; + La_s390_vr lr_v26; + La_s390_vr lr_v27; + La_s390_vr lr_v28; + La_s390_vr lr_v29; + La_s390_vr lr_v30; + La_s390_vr lr_v31; +# endif +} La_s390_64_regs; + +/* Return values for calls from PLT on s390-64. */ +typedef struct La_s390_64_retval +{ + uint64_t lrv_r2; + double lrv_fp0; +# if defined HAVE_S390_VX_ASM_SUPPORT + La_s390_vr lrv_v24; +# endif +} La_s390_64_retval; + + +__BEGIN_DECLS + +extern Elf64_Addr la_s390_64_gnu_pltenter (Elf64_Sym *__sym, + unsigned int __ndx, + uintptr_t *__refcook, + uintptr_t *__defcook, + La_s390_64_regs *__regs, + unsigned int *__flags, + const char *__symname, + long int *__framesizep); +extern unsigned int la_s390_64_gnu_pltexit (Elf64_Sym *__sym, + unsigned int __ndx, + uintptr_t *__refcook, + uintptr_t *__defcook, + const La_s390_64_regs *__inregs, + La_s390_64_retval *__outregs, + const char *__symname); + +__END_DECLS + +#endif diff --git a/REORG.TODO/sysdeps/s390/bits/setjmp.h b/REORG.TODO/sysdeps/s390/bits/setjmp.h new file mode 100644 index 0000000000..9aa3fe204f --- /dev/null +++ b/REORG.TODO/sysdeps/s390/bits/setjmp.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2000-2017 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/>. */ + +/* Define the machine-dependent type `jmp_buf'. IBM s390 version. */ + +#ifndef __S390_SETJMP_H__ +#define __S390_SETJMP_H__ + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead." +#endif + +#include <bits/wordsize.h> + +#ifndef _ASM + +typedef struct __s390_jmp_buf +{ + /* We save registers 6-15. */ + long int __gregs[10]; + +# if __WORDSIZE == 64 + /* We save fpu registers f8 - f15. */ + long __fpregs[8]; +# else + /* We save fpu registers 4 and 6. */ + long __fpregs[4]; +# endif +} __jmp_buf[1]; + +#endif + +#endif /* __S390_SETJMP_H__ */ diff --git a/REORG.TODO/sysdeps/s390/bits/string.h b/REORG.TODO/sysdeps/s390/bits/string.h new file mode 100644 index 0000000000..1e794f925d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/bits/string.h @@ -0,0 +1,252 @@ +/* Optimized, inlined string functions. S/390 version. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#ifndef _STRING_H +# error "Never use <bits/string.h> directly; include <string.h> instead." +#endif + +/* Use the unaligned string inline ABI. */ +#define _STRING_INLINE_unaligned 1 + +/* We only provide optimizations if the user selects them and if + GNU CC is used. */ +#if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \ + && defined __GNUC__ && __GNUC__ >= 2 + +#ifndef __STRING_INLINE +# ifndef __extern_inline +# define __STRING_INLINE inline +# else +# define __STRING_INLINE __extern_inline +# endif +#endif + +#define _HAVE_STRING_ARCH_strlen 1 +#ifndef _FORCE_INLINES +#define strlen(str) __strlen_g ((str)) + +__STRING_INLINE size_t __strlen_g (const char *) __asm__ ("strlen"); + +__STRING_INLINE size_t +__strlen_g (const char *__str) +{ + char *__ptr, *__tmp; + + __ptr = (char *) 0; + __tmp = (char *) __str; + __asm__ __volatile__ (" la 0,0\n" + "0: srst %0,%1\n" + " jo 0b\n" + : "+&a" (__ptr), "+&a" (__tmp) : + : "cc", "memory", "0" ); + return (size_t) (__ptr - __str); +} +#endif + +/* Copy SRC to DEST. */ +#define _HAVE_STRING_ARCH_strcpy 1 +#ifndef _FORCE_INLINES +#define strcpy(dest, src) __strcpy_g ((dest), (src)) + +__STRING_INLINE char *__strcpy_g (char *, const char *) __asm__ ("strcpy"); + +__STRING_INLINE char * +__strcpy_g (char *__dest, const char *__src) +{ + char *tmp = __dest; + + __asm__ __volatile__ (" la 0,0\n" + "0: mvst %0,%1\n" + " jo 0b" + : "+&a" (__dest), "+&a" (__src) : + : "cc", "memory", "0" ); + return tmp; +} +#endif + +#define _HAVE_STRING_ARCH_strncpy 1 +#ifndef _FORCE_INLINES +#define strncpy(dest, src, n) __strncpy_g ((dest), (src), (n)) + +__STRING_INLINE char *__strncpy_g (char *, const char *, size_t) + __asm__ ("strncpy"); + +__STRING_INLINE char * +__strncpy_g (char *__dest, const char *__src, size_t __n) +{ + char *__ret = __dest; + char *__ptr; + size_t __diff; + + if (__n > 0) { + __diff = (size_t) (__dest - __src); + __ptr = (char *) __src; + __asm__ __volatile__ (" j 1f\n" + "0: la %0,1(%0)\n" + "1: icm 0,1,0(%0)\n" + " stc 0,0(%2,%0)\n" + " jz 3f\n" +#if defined(__s390x__) + " brctg %1,0b\n" +#else + " brct %1,0b\n" +#endif + " j 4f\n" + "2: la %0,1(%0)\n" + " stc 0,0(%2,%0)\n" +#if defined(__s390x__) + "3: brctg %1,2b\n" +#else + "3: brct %1,2b\n" +#endif + "4:" + : "+&a" (__ptr), "+&a" (__n) : "a" (__diff) + : "cc", "memory", "0" ); + } + return __ret; +} +#endif + +/* Append SRC onto DEST. */ +#define _HAVE_STRING_ARCH_strcat 1 +#ifndef _FORCE_INLINES +#define strcat(dest, src) __strcat_g ((dest), (src)) + +__STRING_INLINE char *__strcat_g (char *, const char *) __asm__ ("strcat"); + +__STRING_INLINE char * +__strcat_g (char *__dest, const char *__src) +{ + char *__ret = __dest; + char *__ptr, *__tmp; + + /* Move __ptr to the end of __dest. */ + __ptr = (char *) 0; + __tmp = __dest; + __asm__ __volatile__ (" la 0,0\n" + "0: srst %0,%1\n" + " jo 0b\n" + : "+&a" (__ptr), "+&a" (__tmp) : + : "cc", "0" ); + + /* Now do the copy. */ + __asm__ __volatile__ (" la 0,0\n" + "0: mvst %0,%1\n" + " jo 0b" + : "+&a" (__ptr), "+&a" (__src) : + : "cc", "memory", "0" ); + return __ret; +} +#endif + +/* Append no more than N characters from SRC onto DEST. */ +#define _HAVE_STRING_ARCH_strncat 1 +#ifndef _FORCE_INLINES +#define strncat(dest, src, n) __strncat_g ((dest), (src), (n)) + +__STRING_INLINE char *__strncat_g (char *, const char *, size_t) + __asm__ ("strncat"); + +__STRING_INLINE char * +__strncat_g (char *__dest, const char *__src, size_t __n) +{ + char *__ret = __dest; + char *__ptr, *__tmp; + size_t __diff; + + if (__n > 0) { + /* Move __ptr to the end of __dest. */ + __ptr = (char *) 0; + __tmp = __dest; + __asm__ __volatile__ (" la 0,0\n" + "0: srst %0,%1\n" + " jo 0b\n" + : "+&a" (__ptr), "+&a" (__tmp) : + : "cc", "memory", "0" ); + + __diff = (size_t) (__ptr - __src); + __tmp = (char *) __src; + __asm__ __volatile__ (" j 1f\n" + "0: la %0,1(%0)\n" + "1: icm 0,1,0(%0)\n" + " stc 0,0(%2,%0)\n" + " jz 2f\n" +#if defined(__s390x__) + " brctg %1,0b\n" +#else + " brct %1,0b\n" +#endif + " slr 0,0\n" + " stc 0,1(%2,%0)\n" + "2:" + : "+&a" (__tmp), "+&a" (__n) : "a" (__diff) + : "cc", "memory", "0" ); + + } + return __ret; +} +#endif + +/* Search N bytes of S for C. */ +#define _HAVE_STRING_ARCH_memchr 1 +#ifndef _FORCE_INLINES +__STRING_INLINE void * +memchr (const void *__str, int __c, size_t __n) +{ + char *__ptr, *__tmp; + + __tmp = (char *) __str; + __ptr = (char *) __tmp + __n; + __asm__ __volatile__ (" lhi 0,0xff\n" + " nr 0,%2\n" + "0: srst %0,%1\n" + " jo 0b\n" + " brc 13,1f\n" + " la %0,0\n" + "1:" + : "+&a" (__ptr), "+&a" (__tmp) : "d" (__c) + : "cc", "memory", "0" ); + return __ptr; +} +#endif + +/* Compare S1 and S2. */ +#define _HAVE_STRING_ARCH_strcmp 1 +#ifndef _FORCE_INLINES +__STRING_INLINE int +strcmp (const char *__s1, const char *__s2) +{ + char *__p1, *__p2; + int __ret; + + __p1 = (char *) __s1; + __p2 = (char *) __s2; + __asm__ __volatile__ (" slr 0,0\n" + "0: clst %1,%2\n" + " jo 0b\n" + " ipm %0\n" + " srl %0,28" + : "=d" (__ret), "+&a" (__p1), "+&a" (__p2) : + : "cc", "memory", "0" ); + __ret = (__ret == 0) ? 0 : (__ret == 1) ? -1 : 1; + return __ret; +} +#endif + +#endif /* Use string inlines && GNU CC. */ diff --git a/REORG.TODO/sysdeps/s390/bits/xtitypes.h b/REORG.TODO/sysdeps/s390/bits/xtitypes.h new file mode 100644 index 0000000000..dd3fe43880 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/bits/xtitypes.h @@ -0,0 +1,33 @@ +/* bits/xtitypes.h -- Define some types used by <bits/stropts.h>. S390/S390x + Copyright (C) 2002-2017 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/>. */ + +#ifndef _STROPTS_H +# error "Never include <bits/xtitypes.h> directly; use <stropts.h> instead." +#endif + +#ifndef _BITS_XTITYPES_H +#define _BITS_XTITYPES_H 1 + +#include <bits/types.h> + +/* This type is used by some structs in <bits/stropts.h>. */ +typedef __S32_TYPE __t_scalar_t; +typedef __U32_TYPE __t_uscalar_t; + + +#endif /* bits/xtitypes.h */ diff --git a/REORG.TODO/sysdeps/s390/configure b/REORG.TODO/sysdeps/s390/configure new file mode 100644 index 0000000000..347ac28528 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/configure @@ -0,0 +1,217 @@ +# This file is generated from configure.ac by Autoconf. DO NOT EDIT! + # Local configure fragment for sysdeps/s390. + +$as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h + + +for ac_prog in $AS +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AS="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AS" && break +done + +if test -z "$AS"; then + ac_verc_fail=yes +else + # Found it, now check the version. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $AS" >&5 +$as_echo_n "checking version of $AS... " >&6; } + ac_prog_version=`$AS --version 2>&1 | sed -n 's/^.*GNU assembler.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 2.2[4-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*) + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5 +$as_echo "$ac_prog_version" >&6; } +fi +if test $ac_verc_fail = yes; then + critic_missing="$critic_missing The program AS is required in version >= 2.24 for target S390." +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_tbegin" >&5 +$as_echo_n "checking for __builtin_tbegin... " >&6; } +if ${libc_cv_gcc_builtin_tbegin+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<\EOF +#include <htmintrin.h> +void testtransaction () +{ + if (__builtin_tbegin (0) == _HTM_TBEGIN_STARTED) + { + __builtin_tend (); + } +} +EOF +if { ac_try='${CC-cc} -mhtm -O2 -S conftest.c -o - | grep -w tbegin > /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } ; +then + libc_cv_gcc_builtin_tbegin=yes +else + libc_cv_gcc_builtin_tbegin=no +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_builtin_tbegin" >&5 +$as_echo "$libc_cv_gcc_builtin_tbegin" >&6; } + +if test "$enable_lock_elision" = yes && test "$libc_cv_gcc_builtin_tbegin" = no ; then + critic_missing="$critic_missing The used GCC has no support for __builtin_tbegin, which is needed for lock-elision on target S390." +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 vector instruction support" >&5 +$as_echo_n "checking for S390 vector instruction support... " >&6; } +if ${libc_cv_asm_s390_vx+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<\EOF +void testvecinsn () +{ + __asm__ (".machine \"z13\" \n\t" + ".machinemode \"zarch_nohighgprs\" \n\t" + "vistrbs %%v16,%%v17 \n\t" + "locghie %%r1,0" : :); +} +EOF +if { ac_try='${CC-cc} --shared conftest.c -o conftest.o &> /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } ; +then + libc_cv_asm_s390_vx=yes +else + libc_cv_asm_s390_vx=no +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_vx" >&5 +$as_echo "$libc_cv_asm_s390_vx" >&6; } + +if test "$libc_cv_asm_s390_vx" = yes ; +then + $as_echo "#define HAVE_S390_VX_ASM_SUPPORT 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Use binutils with vector-support in order to use optimized implementations." >&5 +$as_echo "$as_me: WARNING: Use binutils with vector-support in order to use optimized implementations." >&2;} +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 vector support in gcc" >&5 +$as_echo_n "checking for S390 vector support in gcc... " >&6; } +if ${libc_cv_gcc_s390_vx+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<\EOF +void testvecclobber () +{ + __asm__ ("" : : : "v16"); +} +EOF +if { ac_try='${CC-cc} --shared conftest.c -o conftest.o &> /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } ; +then + libc_cv_gcc_s390_vx=yes +else + libc_cv_gcc_s390_vx=no +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_s390_vx" >&5 +$as_echo "$libc_cv_gcc_s390_vx" >&6; } + +if test "$libc_cv_gcc_s390_vx" = yes ; +then + $as_echo "#define HAVE_S390_VX_GCC_SUPPORT 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 z196 zarch instruction support as default" >&5 +$as_echo_n "checking for S390 z196 zarch instruction support as default... " >&6; } +if ${libc_cv_asm_s390_min_z196_zarch+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<\EOF +float testinsn (double e) +{ + float d; + __asm__ ("ledbra %0,5,%1,4" : "=f" (d) : "f" (e) ); + return d; +} +EOF +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c + -o conftest.o &> /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } ; +then + libc_cv_asm_s390_min_z196_zarch=yes +else + libc_cv_asm_s390_min_z196_zarch=no +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_min_z196_zarch" >&5 +$as_echo "$libc_cv_asm_s390_min_z196_zarch" >&6; } + +if test "$libc_cv_asm_s390_min_z196_zarch" = yes ; +then + $as_echo "#define HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT 1" >>confdefs.h + +fi + +test -n "$critic_missing" && as_fn_error $? " +*** $critic_missing" "$LINENO" 5 diff --git a/REORG.TODO/sysdeps/s390/configure.ac b/REORG.TODO/sysdeps/s390/configure.ac new file mode 100644 index 0000000000..8a782e7c3a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/configure.ac @@ -0,0 +1,116 @@ +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. +# Local configure fragment for sysdeps/s390. + +dnl It is always possible to access static and hidden symbols in an +dnl position independent way. +AC_DEFINE(PI_STATIC_AND_HIDDEN) + +dnl Accept as 2.24 or newer. +AC_CHECK_PROG_VER(AS, $AS, --version, + [GNU assembler.* \([0-9]*\.[0-9.]*\)], + [2.2[4-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*], critic_missing="$critic_missing The program AS is required in version >= 2.24 for target S390.") + + +AC_CACHE_CHECK(for __builtin_tbegin, libc_cv_gcc_builtin_tbegin, [dnl +cat > conftest.c <<\EOF +#include <htmintrin.h> +void testtransaction () +{ + if (__builtin_tbegin (0) == _HTM_TBEGIN_STARTED) + { + __builtin_tend (); + } +} +EOF +dnl +dnl test, if the tbegin instruction is used by __builtin_tbegin +if AC_TRY_COMMAND([${CC-cc} -mhtm -O2 -S conftest.c -o - | grep -w tbegin > /dev/null]) ; +then + libc_cv_gcc_builtin_tbegin=yes +else + libc_cv_gcc_builtin_tbegin=no +fi +rm -f conftest* ]) + +if test "$enable_lock_elision" = yes && test "$libc_cv_gcc_builtin_tbegin" = no ; then + critic_missing="$critic_missing The used GCC has no support for __builtin_tbegin, which is needed for lock-elision on target S390." +fi + + +AC_CACHE_CHECK(for S390 vector instruction support, libc_cv_asm_s390_vx, [dnl +cat > conftest.c <<\EOF +void testvecinsn () +{ + __asm__ (".machine \"z13\" \n\t" + ".machinemode \"zarch_nohighgprs\" \n\t" + "vistrbs %%v16,%%v17 \n\t" + "locghie %%r1,0" : :); +} +EOF +dnl +dnl test, if assembler supports S390 vector instructions +if AC_TRY_COMMAND([${CC-cc} --shared conftest.c -o conftest.o &> /dev/null]) ; +then + libc_cv_asm_s390_vx=yes +else + libc_cv_asm_s390_vx=no +fi +rm -f conftest* ]) + +if test "$libc_cv_asm_s390_vx" = yes ; +then + AC_DEFINE(HAVE_S390_VX_ASM_SUPPORT) +else + AC_MSG_WARN([Use binutils with vector-support in order to use optimized implementations.]) +fi + +AC_CACHE_CHECK(for S390 vector support in gcc, libc_cv_gcc_s390_vx, [dnl +cat > conftest.c <<\EOF +void testvecclobber () +{ + __asm__ ("" : : : "v16"); +} +EOF +dnl +dnl test, if gcc supports S390 vector registers as clobber in inline assembly +if AC_TRY_COMMAND([${CC-cc} --shared conftest.c -o conftest.o &> /dev/null]) ; +then + libc_cv_gcc_s390_vx=yes +else + libc_cv_gcc_s390_vx=no +fi +rm -f conftest* ]) + +if test "$libc_cv_gcc_s390_vx" = yes ; +then + AC_DEFINE(HAVE_S390_VX_GCC_SUPPORT) +fi + +AC_CACHE_CHECK(for S390 z196 zarch instruction support as default, + libc_cv_asm_s390_min_z196_zarch, [dnl +cat > conftest.c <<\EOF +float testinsn (double e) +{ + float d; + __asm__ ("ledbra %0,5,%1,4" : "=f" (d) : "f" (e) ); + return d; +} +EOF +dnl +dnl test, if assembler supports S390 z196 zarch instructions as default +if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c + -o conftest.o &> /dev/null]) ; +then + libc_cv_asm_s390_min_z196_zarch=yes +else + libc_cv_asm_s390_min_z196_zarch=no +fi +rm -f conftest* ]) + +if test "$libc_cv_asm_s390_min_z196_zarch" = yes ; +then + AC_DEFINE(HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT) +fi + +test -n "$critic_missing" && AC_MSG_ERROR([ +*** $critic_missing]) diff --git a/REORG.TODO/sysdeps/s390/dl-irel.h b/REORG.TODO/sysdeps/s390/dl-irel.h new file mode 100644 index 0000000000..731e3070f2 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/dl-irel.h @@ -0,0 +1,52 @@ +/* Machine-dependent ELF indirect relocation inline functions. + Version for S/390 32 and 64 bit. + Copyright (C) 2012-2017 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/>. */ + +#ifndef _DL_IREL_H +#define _DL_IREL_H + +#include <stdio.h> +#include <unistd.h> +#include <ldsodefs.h> + +#define ELF_MACHINE_IRELA 1 + +static inline ElfW(Addr) +__attribute ((always_inline)) +elf_ifunc_invoke (ElfW(Addr) addr) +{ + return ((ElfW(Addr) (*) (unsigned long int)) (addr)) (GLRO(dl_hwcap)); +} + +static inline void +__attribute ((always_inline)) +elf_irela (const ElfW(Rela) *reloc) +{ + ElfW(Addr) *const reloc_addr = (void *) reloc->r_offset; + const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info); + + if (__glibc_likely (r_type == R_390_IRELATIVE)) + { + ElfW(Addr) value = elf_ifunc_invoke(reloc->r_addend); + *reloc_addr = value; + } + else + __libc_fatal ("unexpected reloc type in static binary"); +} + +#endif /* dl-irel.h */ diff --git a/REORG.TODO/sysdeps/s390/dl-procinfo.c b/REORG.TODO/sysdeps/s390/dl-procinfo.c new file mode 100644 index 0000000000..4fcde8e889 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/dl-procinfo.c @@ -0,0 +1,79 @@ +/* Data for s390 version of processor capability information. + Copyright (C) 2006-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2006. + + 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/>. */ + +/* This information must be kept in sync with the _DL_HWCAP_COUNT and + _DL_PLATFORM_COUNT definitions in procinfo.h. + + If anything should be added here check whether the size of each string + is still ok with the given array size. + + All the #ifdefs in the definitions are quite irritating but + necessary if we want to avoid duplicating the information. There + are three different modes: + + - PROCINFO_DECL is defined. This means we are only interested in + declarations. + + - PROCINFO_DECL is not defined: + + + if SHARED is defined the file is included in an array + initializer. The .element = { ... } syntax is needed. + + + if SHARED is not defined a normal array initialization is + needed. + */ + +#ifndef PROCINFO_CLASS +# define PROCINFO_CLASS +#endif + +#if !defined PROCINFO_DECL && defined SHARED + ._dl_s390_cap_flags +#else +PROCINFO_CLASS const char _dl_s390_cap_flags[12][9] +#endif +#ifndef PROCINFO_DECL += { + "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", "highgprs", "te", "vx" + } +#endif +#if !defined SHARED || defined PROCINFO_DECL +; +#else +, +#endif + +#if !defined PROCINFO_DECL && defined SHARED + ._dl_s390_platforms +#else +PROCINFO_CLASS const char _dl_s390_platforms[8][7] +#endif +#ifndef PROCINFO_DECL += { + "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13" + } +#endif +#if !defined SHARED || defined PROCINFO_DECL +; +#else +, +#endif + +#undef PROCINFO_DECL +#undef PROCINFO_CLASS diff --git a/REORG.TODO/sysdeps/s390/dl-procinfo.h b/REORG.TODO/sysdeps/s390/dl-procinfo.h new file mode 100644 index 0000000000..c99789629a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/dl-procinfo.h @@ -0,0 +1,98 @@ +/* s390 version of processor capability information handling macros. + Copyright (C) 2006-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2006. + + 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/>. */ + +#ifndef _DL_PROCINFO_H +#define _DL_PROCINFO_H 1 +#include <ldsodefs.h> + +#define _DL_HWCAP_COUNT 12 + +#define _DL_PLATFORMS_COUNT 8 + +/* The kernel provides up to 32 capability bits with elf_hwcap. */ +#define _DL_FIRST_PLATFORM 32 +/* Mask to filter out platforms. */ +#define _DL_HWCAP_PLATFORM (((1ULL << _DL_PLATFORMS_COUNT) - 1) \ + << _DL_FIRST_PLATFORM) + +/* Hardware capability bit numbers are derived directly from the + facility indications as stored by the "store facility list" (STFL) + instruction. + highgprs is an alien in that list. It describes a *kernel* + capability. */ + +enum +{ + HWCAP_S390_ESAN3 = 1 << 0, + HWCAP_S390_ZARCH = 1 << 1, + HWCAP_S390_STFLE = 1 << 2, + HWCAP_S390_MSA = 1 << 3, + HWCAP_S390_LDISP = 1 << 4, + HWCAP_S390_EIMM = 1 << 5, + HWCAP_S390_DFP = 1 << 6, + HWCAP_S390_HPAGE = 1 << 7, + HWCAP_S390_ETF3EH = 1 << 8, + HWCAP_S390_HIGH_GPRS = 1 << 9, + HWCAP_S390_TE = 1 << 10, + HWCAP_S390_VX = 1 << 11, +}; + +#define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \ + | HWCAP_S390_EIMM | HWCAP_S390_DFP) + +/* We cannot provide a general printing function. */ +#define _dl_procinfo(type, word) -1 + +static inline const char * +__attribute__ ((unused)) +_dl_hwcap_string (int idx) +{ + return GLRO(dl_s390_cap_flags)[idx]; +}; + +static inline int +__attribute__ ((unused, always_inline)) +_dl_string_hwcap (const char *str) +{ + int i; + + for (i = 0; i < _DL_HWCAP_COUNT; i++) + { + if (strcmp (str, GLRO(dl_s390_cap_flags)[i]) == 0) + return i; + } + return -1; +}; + +static inline int +__attribute__ ((unused, always_inline)) +_dl_string_platform (const char *str) +{ + int i; + + if (str != NULL) + for (i = 0; i < _DL_PLATFORMS_COUNT; ++i) + { + if (strcmp (str, GLRO(dl_s390_platforms)[i]) == 0) + return _DL_FIRST_PLATFORM + i; + } + return -1; +}; + +#endif /* dl-procinfo.h */ diff --git a/REORG.TODO/sysdeps/s390/dl-tls.h b/REORG.TODO/sysdeps/s390/dl-tls.h new file mode 100644 index 0000000000..3298acfbcf --- /dev/null +++ b/REORG.TODO/sysdeps/s390/dl-tls.h @@ -0,0 +1,104 @@ +/* Thread-local storage handling in the ELF dynamic linker. s390 version. + Copyright (C) 2003-2017 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/>. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +#ifdef SHARED + +extern unsigned long __tls_get_offset (unsigned long got_offset); + +# if IS_IN (rtld) + +# include <shlib-compat.h> + +/* dl-tls.c declares __tls_get_addr as an exported symbol if it is not defined + as a macro. It seems suitable to do that in the generic code because all + architectures other than s390 export __tls_get_addr. The declaration causes + problems in s390 though, so we define __tls_get_addr here to avoid declaring + __tls_get_addr again. */ +# define __tls_get_addr __tls_get_addr + +extern void *__tls_get_addr (tls_index *ti) attribute_hidden; +/* Make a temporary alias of __tls_get_addr to remove the hidden + attribute. Then export __tls_get_addr as __tls_get_addr_internal + for use from libc. We do not want to export __tls_get_addr, but we + do need to use it from libc when looking up the address of a TLS + variable. We don't use __tls_get_offset because it requires r12 to + be setup and that might not always be true. Either way it's more + optimal to use __tls_get_addr directly (that's what + __tls_get_offset does anyways). */ +strong_alias (__tls_get_addr, __tls_get_addr_internal_tmp); +versioned_symbol (ld, __tls_get_addr_internal_tmp, + __tls_get_addr_internal, GLIBC_PRIVATE); + +/* The special thing about the s390 TLS ABI is that we do not have the + standard __tls_get_addr function but the __tls_get_offset function + which differs in two important aspects: + 1) __tls_get_offset gets a got offset instead of a pointer to the + tls_index structure + 2) __tls_get_offset returns the offset of the requested variable to + the thread descriptor instead of a pointer to the variable. + */ +# ifdef __s390x__ +__asm__("\n\ + .text\n\ + .globl __tls_get_offset\n\ + .type __tls_get_offset, @function\n\ + .align 4\n\ +__tls_get_offset:\n\ + la %r2,0(%r2,%r12)\n\ + jg __tls_get_addr\n\ +"); +# elif defined __s390__ +__asm__("\n\ + .text\n\ + .globl __tls_get_offset\n\ + .type __tls_get_offset, @function\n\ + .align 4\n\ +__tls_get_offset:\n\ + basr %r3,0\n\ +0: la %r2,0(%r2,%r12)\n\ + l %r4,1f-0b(%r3)\n\ + b 0(%r4,%r3)\n\ +1: .long __tls_get_addr - 0b\n\ +"); +# endif +# else /* IS_IN (rtld) */ +extern void *__tls_get_addr_internal (tls_index *ti); +# endif /* !IS_IN (rtld) */ + +# define GET_ADDR_OFFSET \ + (ti->ti_offset - (unsigned long) __builtin_thread_pointer ()) + +/* Use the privately exported __tls_get_addr_internal instead of + __tls_get_offset in order to avoid the __tls_get_offset special + linkage requiring the GOT pointer to be set up in r12. The + compiler will take care of setting up r12 only if itself issued the + __tls_get_offset call. */ +# define __TLS_GET_ADDR(__ti) \ + ({ __tls_get_addr_internal (__ti) \ + + (unsigned long) __builtin_thread_pointer (); }) + +#endif diff --git a/REORG.TODO/sysdeps/s390/ffs.c b/REORG.TODO/sysdeps/s390/ffs.c new file mode 100644 index 0000000000..c36f60045b --- /dev/null +++ b/REORG.TODO/sysdeps/s390/ffs.c @@ -0,0 +1,70 @@ +/* ffs -- find first set bit in a word, counted from least significant end. + S/390 version. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#include <limits.h> +#define ffsl __something_else +#include <string.h> + +#undef ffs + +/* ffs: find first bit set. This is defined the same way as + the libc and compiler builtin ffs routines, therefore + differs in spirit from the above ffz (man ffs). */ + +int +__ffs (int x) +{ + int r; + + if (x == 0) + return 0; + __asm__(" lr %%r1,%1\n" + " sr %0,%0\n" + " tml %%r1,0xFFFF\n" + " jnz 0f\n" + " ahi %0,16\n" + " srl %%r1,16\n" + "0: tml %%r1,0x00FF\n" + " jnz 1f\n" + " ahi %0,8\n" + " srl %%r1,8\n" + "1: tml %%r1,0x000F\n" + " jnz 2f\n" + " ahi %0,4\n" + " srl %%r1,4\n" + "2: tml %%r1,0x0003\n" + " jnz 3f\n" + " ahi %0,2\n" + " srl %%r1,2\n" + "3: tml %%r1,0x0001\n" + " jnz 4f\n" + " ahi %0,1\n" + "4:" + : "=&d" (r) : "d" (x) : "cc", "1" ); + return r+1; +} + +weak_alias (__ffs, ffs) +libc_hidden_def (__ffs) +libc_hidden_builtin_def (ffs) +#if ULONG_MAX == UINT_MAX +#undef ffsl +weak_alias (__ffs, ffsl) +#endif diff --git a/REORG.TODO/sysdeps/s390/fix-fp-int-convert-overflow.h b/REORG.TODO/sysdeps/s390/fix-fp-int-convert-overflow.h new file mode 100644 index 0000000000..cef804e259 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fix-fp-int-convert-overflow.h @@ -0,0 +1,33 @@ +/* Fix for conversion of floating point to integer overflow. S390 version. + Copyright (C) 2016-2017 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/>. */ + +#ifndef FIX_FP_INT_CONVERT_OVERFLOW_H +#define FIX_FP_INT_CONVERT_OVERFLOW_H 1 + +/* GCC emits "convert to fixed" instructions for casting floating point values + to integer values. These instructions raise invalid and inexact exceptions + if the floating point value exceeds the integer type ranges. */ +#define FIX_FLT_LLONG_CONVERT_OVERFLOW 1 +#define FIX_DBL_LLONG_CONVERT_OVERFLOW 1 +#define FIX_LDBL_LLONG_CONVERT_OVERFLOW 1 + +#define FIX_FLT_LONG_CONVERT_OVERFLOW 1 +#define FIX_DBL_LONG_CONVERT_OVERFLOW 1 +#define FIX_LDBL_LONG_CONVERT_OVERFLOW 1 + +#endif /* fix-fp-int-convert-overflow.h */ diff --git a/REORG.TODO/sysdeps/s390/fpu/bits/fenv.h b/REORG.TODO/sysdeps/s390/fpu/bits/fenv.h new file mode 100644 index 0000000000..3110ed71d4 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/bits/fenv.h @@ -0,0 +1,100 @@ +/* Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow <djbarrow@de.ibm.com>. + + 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/>. */ + +#ifndef _FENV_H +# error "Never use <bits/fenv.h> directly; include <fenv.h> instead." +#endif + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INVALID = +#define FE_INVALID 0x80 + FE_INVALID, + FE_DIVBYZERO = +#define FE_DIVBYZERO 0x40 + FE_DIVBYZERO, + FE_OVERFLOW = +#define FE_OVERFLOW 0x20 + FE_OVERFLOW, + FE_UNDERFLOW = +#define FE_UNDERFLOW 0x10 + FE_UNDERFLOW, + FE_INEXACT = +#define FE_INEXACT 0x08 + FE_INEXACT + }; +/* We dont use the y bit of the DXC in the floating point control register + as glibc has no FE encoding for fe inexact incremented + or fe inexact truncated. + We currently use the flag bits in the fpc + as these are sticky for feholdenv & feupdatenv as it is defined + in the HP Manpages. */ + + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +enum + { + FE_TONEAREST = +#define FE_TONEAREST 0 + FE_TONEAREST, + FE_DOWNWARD = +#define FE_DOWNWARD 0x3 + FE_DOWNWARD, + FE_UPWARD = +#define FE_UPWARD 0x2 + FE_UPWARD, + FE_TOWARDZERO = +#define FE_TOWARDZERO 0x1 + FE_TOWARDZERO + }; + + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; /* size of fpc */ + + +/* Type representing floating-point environment. This function corresponds + to the layout of the block written by the `fstenv'. */ +typedef struct +{ + fexcept_t __fpc; + void *__unused; + /* The field __unused (formerly __ieee_instruction_pointer) is a relict from + commit "Remove PTRACE_PEEKUSER" (87b9b50f0d4b92248905e95a06a13c513dc45e59) + and isn´t used anymore. */ +} fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +# define FE_NOMASK_ENV ((const fenv_t *) -2) +#endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/REORG.TODO/sysdeps/s390/fpu/bits/mathinline.h b/REORG.TODO/sysdeps/s390/fpu/bits/mathinline.h new file mode 100644 index 0000000000..52e21db98d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/bits/mathinline.h @@ -0,0 +1,100 @@ +/* Inline math functions for s390. + Copyright (C) 2004-2017 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/>. */ + +#ifndef _MATH_H +# error "Never use <bits/mathinline.h> directly; include <math.h> instead." +#endif + +#ifndef __extern_inline +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE __extern_inline +#endif + +#if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ + && defined __OPTIMIZE__ + +#ifdef __USE_ISOC99 + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} + +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; long __i; } __u = { __d: __x }; + return __u.__i < 0; +} + +# ifndef __NO_LONG_DOUBLE_MATH +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[4]; } __u = { __l: __x }; + return __u.__i[0] < 0; +} +# else +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + return __signbit ((double) __x); +} +# endif + +#endif /* C99 */ + +/* This code is used internally in the GNU libc. */ +#ifdef __LIBC_INTERNAL_MATH_INLINES + +__MATH_INLINE double +__NTH (__ieee754_sqrt (double x)) +{ + double res; + + __asm__ ( "sqdbr %0,%1" : "=f" (res) : "f" (x) ); + return res; +} + +__MATH_INLINE float +__NTH (__ieee754_sqrtf (float x)) +{ + float res; + + __asm__ ( "sqebr %0,%1" : "=f" (res) : "f" (x) ); + return res; +} + +# if !defined __NO_LONG_DOUBLE_MATH +__MATH_INLINE long double +__NTH (sqrtl (long double __x)) +{ + long double res; + + __asm__ ( "sqxbr %0,%1" : "=f" (res) : "f" (__x) ); + return res; +} +# endif /* !__NO_LONG_DOUBLE_MATH */ + +#endif /* __LIBC_INTERNAL_MATH_INLINES */ + +#endif /* __NO_MATH_INLINES */ diff --git a/REORG.TODO/sysdeps/s390/fpu/e_sqrt.c b/REORG.TODO/sysdeps/s390/fpu/e_sqrt.c new file mode 100644 index 0000000000..bcb93098c3 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/e_sqrt.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2004-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>. + 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/>. */ + +#include <math_private.h> + +double +__ieee754_sqrt (double x) +{ + double res; + + __asm__ ( "sqdbr %0,%1" : "=f" (res) : "f" (x) ); + return res; +} +strong_alias (__ieee754_sqrt, __sqrt_finite) diff --git a/REORG.TODO/sysdeps/s390/fpu/e_sqrtf.c b/REORG.TODO/sysdeps/s390/fpu/e_sqrtf.c new file mode 100644 index 0000000000..42dad4389a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/e_sqrtf.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2004-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>. + 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/>. */ + +#include <math_private.h> + +float +__ieee754_sqrtf (float x) +{ + float res; + + __asm__ ( "sqebr %0,%1" : "=f" (res) : "f" (x) ); + return res; +} +strong_alias (__ieee754_sqrtf, __sqrtf_finite) diff --git a/REORG.TODO/sysdeps/s390/fpu/e_sqrtl.c b/REORG.TODO/sysdeps/s390/fpu/e_sqrtl.c new file mode 100644 index 0000000000..8eab5f0b6a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/e_sqrtl.c @@ -0,0 +1,30 @@ +/* Square root. S/390 FPU version. + Copyright (C) 2004-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>. + 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/>. */ + +#include <math_private.h> + +long double +__ieee754_sqrtl (long double x) +{ + long double res; + + __asm__ ( "sqxbr %0,%1" : "=f" (res) : "f" (x) ); + return res; +} +strong_alias (__ieee754_sqrtl, __sqrtl_finite) diff --git a/REORG.TODO/sysdeps/s390/fpu/fclrexcpt.c b/REORG.TODO/sysdeps/s390/fpu/fclrexcpt.c new file mode 100644 index 0000000000..06c66279ff --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fclrexcpt.c @@ -0,0 +1,45 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 2000-2017 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ + fexcept_t temp; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + _FPU_GETCW (temp); + /* Clear the relevant bits. */ + temp &= ~(excepts << FPC_FLAGS_SHIFT); + if ((temp & FPC_NOT_FPU_EXCEPTION) == 0) + /* Bits 6, 7 of dxc-byte are zero, + thus bits 0-5 of dxc-byte correspond to the flag-bits. + Clear the relevant bits in flags and dxc-field. */ + temp &= ~(excepts << FPC_DXC_SHIFT); + + /* Put the new data in effect. */ + _FPU_SETCW (temp); + + /* Success. */ + return 0; +} +libm_hidden_def (feclearexcept) diff --git a/REORG.TODO/sysdeps/s390/fpu/fedisblxcpt.c b/REORG.TODO/sysdeps/s390/fpu/fedisblxcpt.c new file mode 100644 index 0000000000..2fdb413968 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fedisblxcpt.c @@ -0,0 +1,34 @@ +/* Disable floating-point exceptions. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +fedisableexcept (int excepts) +{ + fexcept_t temp, old_exc, new_flags; + + _FPU_GETCW (temp); + old_exc = (temp & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT; + new_flags = (temp & (~((excepts & FE_ALL_EXCEPT) << FPC_EXCEPTION_MASK_SHIFT))); + _FPU_SETCW (new_flags); + + return old_exc; +} diff --git a/REORG.TODO/sysdeps/s390/fpu/feenablxcpt.c b/REORG.TODO/sysdeps/s390/fpu/feenablxcpt.c new file mode 100644 index 0000000000..4a9e64dc30 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/feenablxcpt.c @@ -0,0 +1,34 @@ +/* Enable floating-point exceptions. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +feenableexcept (int excepts) +{ + fexcept_t temp, old_exc, new_flags; + + _FPU_GETCW (temp); + old_exc = (temp & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT; + new_flags = (temp | ((excepts & FE_ALL_EXCEPT) << FPC_EXCEPTION_MASK_SHIFT)); + _FPU_SETCW (new_flags); + + return old_exc; +} diff --git a/REORG.TODO/sysdeps/s390/fpu/fegetenv.c b/REORG.TODO/sysdeps/s390/fpu/fegetenv.c new file mode 100644 index 0000000000..d3455a0df3 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fegetenv.c @@ -0,0 +1,33 @@ +/* Store current floating-point environment. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +__fegetenv (fenv_t *envp) +{ + _FPU_GETCW (envp->__fpc); + + /* Success. */ + return 0; +} +libm_hidden_def (__fegetenv) +weak_alias (__fegetenv, fegetenv) +libm_hidden_weak (fegetenv) diff --git a/REORG.TODO/sysdeps/s390/fpu/fegetexcept.c b/REORG.TODO/sysdeps/s390/fpu/fegetexcept.c new file mode 100644 index 0000000000..95cd133c5b --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fegetexcept.c @@ -0,0 +1,30 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +fegetexcept (void) +{ + fexcept_t exc; + + _FPU_GETCW (exc); + return ((exc & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT); +} diff --git a/REORG.TODO/sysdeps/s390/fpu/fegetmode.c b/REORG.TODO/sysdeps/s390/fpu/fegetmode.c new file mode 100644 index 0000000000..9286df3576 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fegetmode.c @@ -0,0 +1,27 @@ +/* Store current floating-point control modes. S/390 version. + Copyright (C) 2016-2017 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/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (*modep); + return 0; +} diff --git a/REORG.TODO/sysdeps/s390/fpu/fegetround.c b/REORG.TODO/sysdeps/s390/fpu/fegetround.c new file mode 100644 index 0000000000..81d2ef6e41 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fegetround.c @@ -0,0 +1,34 @@ +/* Return current rounding direction. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +__fegetround (void) +{ + fexcept_t cw; + + _FPU_GETCW (cw); + + return cw & FPC_RM_MASK; +} +libm_hidden_def (__fegetround) +weak_alias (__fegetround, fegetround) +libm_hidden_weak (fegetround) diff --git a/REORG.TODO/sysdeps/s390/fpu/feholdexcpt.c b/REORG.TODO/sysdeps/s390/fpu/feholdexcpt.c new file mode 100644 index 0000000000..1cd1d445c7 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/feholdexcpt.c @@ -0,0 +1,37 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int __feholdexcept (fenv_t *envp) +{ + fexcept_t fpc; + /* Store the environment. */ + fegetenv (envp); + /* Clear the current sticky bits as more than one exception + may be generated. */ + fpc = envp->__fpc & ~(FPC_FLAGS_MASK | FPC_DXC_MASK); + /* Hold from generating fpu exceptions temporarily. */ + _FPU_SETCW ((fpc & ~(FE_ALL_EXCEPT << FPC_EXCEPTION_MASK_SHIFT))); + return 0; +} +libm_hidden_def (__feholdexcept) +weak_alias (__feholdexcept, feholdexcept) +libm_hidden_weak (feholdexcept) diff --git a/REORG.TODO/sysdeps/s390/fpu/fenv_libc.h b/REORG.TODO/sysdeps/s390/fpu/fenv_libc.h new file mode 100644 index 0000000000..4d088e4613 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fenv_libc.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#ifndef _FENV_LIBC_H +#define _FENV_LIBC_H 1 + +#include <fenv.h> + +/* Definitions from asm/s390-regs-common.h that are needed in glibc. */ + + +#define FPC_EXCEPTION_MASK 0xF8000000 +#define FPC_FLAGS_MASK 0x00F80000 +#define FPC_DXC_MASK 0x0000FF00 +#define FPC_RM_MASK 0x00000003 +#define FPC_VALID_MASK ((FPC_EXCEPTION_MASK|FPC_FLAGS_MASK| \ + FPC_DXC_MASK|FPC_RM_MASK)) + +#define FPC_EXCEPTION_MASK_SHIFT 24 +#define FPC_FLAGS_SHIFT 16 +#define FPC_DXC_SHIFT 8 +#define FPC_NOT_FPU_EXCEPTION 0x300 + +#endif /* _FENV_LIBC_H */ diff --git a/REORG.TODO/sysdeps/s390/fpu/fesetenv.c b/REORG.TODO/sysdeps/s390/fpu/fesetenv.c new file mode 100644 index 0000000000..4c9bcf0629 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fesetenv.c @@ -0,0 +1,50 @@ +/* Install given floating-point environment. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> +#include <stddef.h> +#include <asm/ptrace.h> +#include <sys/ptrace.h> +#include <unistd.h> + +int +__fesetenv (const fenv_t *envp) +{ + fenv_t env; + + if (envp == FE_DFL_ENV) + { + env.__fpc = _FPU_DEFAULT; + } + else if (envp == FE_NOMASK_ENV) + { + env.__fpc = FPC_EXCEPTION_MASK; + } + else + env = (*envp); + + _FPU_SETCW (env.__fpc); + + /* Success. */ + return 0; +} +libm_hidden_def (__fesetenv) +weak_alias (__fesetenv, fesetenv) +libm_hidden_weak (fesetenv) diff --git a/REORG.TODO/sysdeps/s390/fpu/fesetexcept.c b/REORG.TODO/sysdeps/s390/fpu/fesetexcept.c new file mode 100644 index 0000000000..0b4d1f33f3 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fesetexcept.c @@ -0,0 +1,33 @@ +/* Set given exception flags. S/390 version. + Copyright (C) 2016-2017 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/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include <fenv_libc.h> + +int +fesetexcept (int excepts) +{ + fexcept_t temp; + + _FPU_GETCW (temp); + temp |= (excepts & FE_ALL_EXCEPT) << FPC_FLAGS_SHIFT; + _FPU_SETCW (temp); + + return 0; +} diff --git a/REORG.TODO/sysdeps/s390/fpu/fesetmode.c b/REORG.TODO/sysdeps/s390/fpu/fesetmode.c new file mode 100644 index 0000000000..14b7457fa5 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fesetmode.c @@ -0,0 +1,39 @@ +/* Install given floating-point control modes. S/390 version. + Copyright (C) 2016-2017 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/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include <fenv_libc.h> + +#define FPC_STATUS (FPC_FLAGS_MASK | FPC_DXC_MASK) + +int +fesetmode (const femode_t *modep) +{ + fpu_control_t fpc; + + _FPU_GETCW (fpc); + fpc &= FPC_STATUS; + if (modep == FE_DFL_MODE) + fpc |= _FPU_DEFAULT; + else + fpc |= *modep & ~FPC_STATUS; + _FPU_SETCW (fpc); + + return 0; +} diff --git a/REORG.TODO/sysdeps/s390/fpu/fesetround.c b/REORG.TODO/sysdeps/s390/fpu/fesetround.c new file mode 100644 index 0000000000..5ed14fac06 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fesetround.c @@ -0,0 +1,39 @@ +/* Set current rounding direction. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +__fesetround (int round) +{ + if ((round|FPC_RM_MASK) != FPC_RM_MASK) + { + /* ROUND is not a valid rounding mode. */ + return 1; + } + __asm__ __volatile__ ("srnm 0(%0)" + : + : "a" (round)); + + return 0; +} +libm_hidden_def (__fesetround) +weak_alias (__fesetround, fesetround) +libm_hidden_weak (fesetround) diff --git a/REORG.TODO/sysdeps/s390/fpu/fetestexceptflag.c b/REORG.TODO/sysdeps/s390/fpu/fetestexceptflag.c new file mode 100644 index 0000000000..21fe64de8a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fetestexceptflag.c @@ -0,0 +1,31 @@ +/* Test exception in saved exception state. S/390 version. + Copyright (C) 2016-2017 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/>. */ + +#include <fenv.h> +#include <fenv_libc.h> + +int +fetestexceptflag (const fexcept_t *flagp, int excepts) +{ + /* As *flagp is obtained by an earlier call of fegetexceptflag the + bits 0-5 of dxc-byte are either zero or correspond to the + flag-bits. Evaluate flags and last dxc-exception-code. */ + return (((*flagp >> FPC_FLAGS_SHIFT) | (*flagp >> FPC_DXC_SHIFT)) + & excepts + & FE_ALL_EXCEPT); +} diff --git a/REORG.TODO/sysdeps/s390/fpu/feupdateenv.c b/REORG.TODO/sysdeps/s390/fpu/feupdateenv.c new file mode 100644 index 0000000000..de764b029e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/feupdateenv.c @@ -0,0 +1,42 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +__feupdateenv (const fenv_t *envp) +{ + fexcept_t temp; + + _FPU_GETCW (temp); + temp = (temp & FPC_FLAGS_MASK) >> FPC_FLAGS_SHIFT; + + /* Raise the exceptions since the last call to feholdenv */ + /* re install saved environment. */ + __fesetenv (envp); + __feraiseexcept ((int) temp); + + /* Success. */ + return 0; +} +libm_hidden_def (__feupdateenv) +weak_alias (__feupdateenv, feupdateenv) +libm_hidden_weak (feupdateenv) diff --git a/REORG.TODO/sysdeps/s390/fpu/fgetexcptflg.c b/REORG.TODO/sysdeps/s390/fpu/fgetexcptflg.c new file mode 100644 index 0000000000..f49410550e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fgetexcptflg.c @@ -0,0 +1,41 @@ +/* Store current representation for exceptions. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fexcept_t temp, newexcepts; + + /* Get the current exceptions. */ + _FPU_GETCW (temp); + newexcepts = excepts << FPC_FLAGS_SHIFT; + if ((temp & FPC_NOT_FPU_EXCEPTION) == 0) + /* Bits 6, 7 of dxc-byte are zero, + thus bits 0-5 of dxc-byte correspond to the flag-bits. + Evaluate flags and last dxc-exception-code. */ + newexcepts |= excepts << FPC_DXC_SHIFT; + + *flagp = temp & newexcepts; + + /* Success. */ + return 0; +} diff --git a/REORG.TODO/sysdeps/s390/fpu/fix-fp-int-compare-invalid.h b/REORG.TODO/sysdeps/s390/fpu/fix-fp-int-compare-invalid.h new file mode 100644 index 0000000000..bccdf8d56b --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fix-fp-int-compare-invalid.h @@ -0,0 +1,36 @@ +/* Fix for missing "invalid" exceptions from floating-point + comparisons. s390 version. + Copyright (C) 2016-2017 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/>. */ + +#ifndef FIX_FP_INT_COMPARE_INVALID_H +#define FIX_FP_INT_COMPARE_INVALID_H 1 + +/* GCC uses unordered comparison instructions like cebr (Short BFP COMPARE) + when it should use ordered comparison instructions like kebr + (Short BFP COMPARE AND SIGNAL) in order to raise invalid exceptions if + any operand is quiet (or signaling) NAN. See gcc bugzilla: + <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77918>. + There exists an equivalent gcc bugzilla for Intel: + <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52451>. + Once the s390 gcc bug is fixed, the definition of FIX_COMPARE_INVALID + should have a __GNUC_PREREQ conditional added so that e.g. the workaround + to call feraiseexcept (FE_INVALID) in math/s_iseqsig_template.c can be + avoided. */ +#define FIX_COMPARE_INVALID 1 + +#endif /* fix-fp-int-compare-invalid.h */ diff --git a/REORG.TODO/sysdeps/s390/fpu/fpu_control.h b/REORG.TODO/sysdeps/s390/fpu/fpu_control.h new file mode 100644 index 0000000000..c855b014cb --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fpu_control.h @@ -0,0 +1,43 @@ +/* FPU control word definitions. Stub version. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com) and + Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#include <features.h> + +/* These bits are reserved are not changed. */ +#define _FPU_RESERVED 0x0707FFFC + +/* The fdlibm code requires no interrupts for exceptions. Don't + change the rounding mode, it would break long double I/O! */ +#define _FPU_DEFAULT 0x00000000 /* Default value. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ __volatile__ ("efpc %0,0" : "=d" (cw)) +#define _FPU_SETCW(cw) __asm__ __volatile__ ("sfpc %0,0" : : "d" (cw)) + +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; + +#endif /* _FPU_CONTROL_H */ diff --git a/REORG.TODO/sysdeps/s390/fpu/fraiseexcpt.c b/REORG.TODO/sysdeps/s390/fpu/fraiseexcpt.c new file mode 100644 index 0000000000..d0d93dd5a9 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fraiseexcpt.c @@ -0,0 +1,107 @@ +/* Raise given exceptions. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com) and + Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <float.h> +#include <math.h> + + +static __inline__ void +fexceptdiv (float d, float e) +{ + __asm__ __volatile__ ("debr %0,%1" : : "f" (d), "f" (e) ); +} + +static __inline__ void +fexceptadd (float d, float e) +{ + __asm__ __volatile__ ("aebr %0,%1" : : "f" (d), "f" (e) ); +} + +#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT +static __inline__ void +fexceptround (double e) +{ + float d; + /* Load rounded from double to float with M3 = round toward 0, M4 = Suppress + IEEE-inexact exception. + In case of e=0x1p128 and the overflow-mask bit is zero, only the + IEEE-overflow flag is set. If overflow-mask bit is one, DXC field is set to + 0x20 "IEEE overflow, exact". + In case of e=0x1p-150 and the underflow-mask bit is zero, only the + IEEE-underflow flag is set. If underflow-mask bit is one, DXC field is set + to 0x10 "IEEE underflow, exact". + This instruction is available with a zarch machine >= z196. */ + __asm__ __volatile__ ("ledbra %0,5,%1,4" : "=f" (d) : "f" (e) ); +} +#endif + +int +__feraiseexcept (int excepts) +{ + /* Raise exceptions represented by EXPECTS. But we must raise only + one signal at a time. It is important that if the overflow/underflow + exception and the inexact exception are given at the same time, + the overflow/underflow exception follows the inexact exception. */ + + /* First: invalid exception. */ + if (FE_INVALID & excepts) + fexceptdiv (0.0, 0.0); + + /* Next: division by zero. */ + if (FE_DIVBYZERO & excepts) + fexceptdiv (1.0, 0.0); + + /* Next: overflow. */ + if (FE_OVERFLOW & excepts) + { +#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT + fexceptround (0x1p128); +#else + /* If overflow-mask bit is zero, both IEEE-overflow and IEEE-inexact flags + are set. If overflow-mask bit is one, DXC field is set to 0x2C "IEEE + overflow, inexact and incremented". */ + fexceptadd (FLT_MAX, 1.0e32); +#endif + } + + /* Next: underflow. */ + if (FE_UNDERFLOW & excepts) + { +#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT + fexceptround (0x1p-150); +#else + /* If underflow-mask bit is zero, both IEEE-underflow and IEEE-inexact + flags are set. If underflow-mask bit is one, DXC field is set to 0x1C + "IEEE underflow, inexact and incremented". */ + fexceptdiv (FLT_MIN, 3.0); +#endif + } + + /* Last: inexact. */ + if (FE_INEXACT & excepts) + fexceptdiv (2.0, 3.0); + + /* Success. */ + return 0; +} +libm_hidden_def (__feraiseexcept) +weak_alias (__feraiseexcept, feraiseexcept) +libm_hidden_weak (feraiseexcept) diff --git a/REORG.TODO/sysdeps/s390/fpu/fsetexcptflg.c b/REORG.TODO/sysdeps/s390/fpu/fsetexcptflg.c new file mode 100644 index 0000000000..58e462fb5a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/fsetexcptflg.c @@ -0,0 +1,53 @@ +/* Set floating-point environment exception handling. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <math.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fexcept_t temp, newexcepts; + + /* Get the current environment. We have to do this since we cannot + separately set the status word. */ + _FPU_GETCW (temp); + /* Install the new exception bits in the Accrued Exception Byte. */ + excepts = excepts & FE_ALL_EXCEPT; + newexcepts = excepts << FPC_FLAGS_SHIFT; + temp &= ~newexcepts; + if ((temp & FPC_NOT_FPU_EXCEPTION) == 0) + /* Bits 6, 7 of dxc-byte are zero, + thus bits 0-5 of dxc-byte correspond to the flag-bits. + Clear given exceptions in dxc-field. */ + temp &= ~(excepts << FPC_DXC_SHIFT); + + /* Integrate dxc-byte of flagp into flags. The dxc-byte of flagp contains + either an ieee-exception or 0 (see fegetexceptflag). */ + temp |= (*flagp | ((*flagp >> FPC_DXC_SHIFT) << FPC_FLAGS_SHIFT)) + & newexcepts; + + /* Store the new status word (along with the rest of the environment. + Possibly new exceptions are set but they won't get executed. */ + _FPU_SETCW (temp); + + /* Success. */ + return 0; +} diff --git a/REORG.TODO/sysdeps/s390/fpu/ftestexcept.c b/REORG.TODO/sysdeps/s390/fpu/ftestexcept.c new file mode 100644 index 0000000000..8c56f78a40 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/ftestexcept.c @@ -0,0 +1,39 @@ +/* Test exception in current environment. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com). + + 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/>. */ + +#include <fenv_libc.h> +#include <fpu_control.h> + +int +fetestexcept (int excepts) +{ + fexcept_t temp, res; + + /* Get current exceptions. */ + _FPU_GETCW (temp); + res = temp >> FPC_FLAGS_SHIFT; + if ((temp & FPC_NOT_FPU_EXCEPTION) == 0) + /* Bits 6, 7 of dxc-byte are zero, + thus bits 0-5 of dxc-byte correspond to the flag-bits. + Evaluate flags and last dxc-exception-code. */ + res |= temp >> FPC_DXC_SHIFT; + + return res & excepts & FE_ALL_EXCEPT; +} +libm_hidden_def (fetestexcept) diff --git a/REORG.TODO/sysdeps/s390/fpu/get-rounding-mode.h b/REORG.TODO/sysdeps/s390/fpu/get-rounding-mode.h new file mode 100644 index 0000000000..7fffa0a947 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/get-rounding-mode.h @@ -0,0 +1,37 @@ +/* Determine floating-point rounding mode within libc. S/390 version. + Copyright (C) 2012-2017 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/>. */ + +#ifndef _S390_GET_ROUNDING_MODE_H +#define _S390_GET_ROUNDING_MODE_H 1 + +#include <fenv.h> +#include <fenv_libc.h> +#include <fpu_control.h> + +/* Return the floating-point rounding mode. */ + +static inline int +get_rounding_mode (void) +{ + fpu_control_t fc; + + _FPU_GETCW (fc); + return fc & FPC_RM_MASK; +} + +#endif /* get-rounding-mode.h */ diff --git a/REORG.TODO/sysdeps/s390/fpu/libm-test-ulps b/REORG.TODO/sysdeps/s390/fpu/libm-test-ulps new file mode 100644 index 0000000000..dad5205ae7 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/libm-test-ulps @@ -0,0 +1,2270 @@ +# Begin of automatic generation + +# Maximal error of functions: +Function: "acos": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "acos_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "acos_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "acos_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "acosh": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "acosh_downward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "acosh_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "acosh_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "asin": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "asin_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "asin_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "asin_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "asinh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "asinh_downward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: "asinh_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "asinh_upward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: "atan": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "atan2": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "atan2_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "atan2_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "atan2_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "atan_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "atan_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "atan_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "atanh": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "atanh_downward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: "atanh_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "atanh_upward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: "cabs": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "cabs_downward": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "cabs_towardzero": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "cabs_upward": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "cacos": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "cacos": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "cacos_downward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "cacos_downward": +double: 5 +float: 3 +idouble: 5 +ifloat: 3 +ildouble: 6 +ldouble: 6 + +Function: Real part of "cacos_towardzero": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "cacos_towardzero": +double: 4 +float: 2 +idouble: 4 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: Real part of "cacos_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "cacos_upward": +double: 5 +float: 5 +idouble: 5 +ifloat: 5 +ildouble: 7 +ldouble: 7 + +Function: Real part of "cacosh": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "cacosh": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "cacosh_downward": +double: 4 +float: 2 +idouble: 4 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "cacosh_downward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: Real part of "cacosh_towardzero": +double: 4 +float: 2 +idouble: 4 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "cacosh_towardzero": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Real part of "cacosh_upward": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 6 +ldouble: 6 + +Function: Imaginary part of "cacosh_upward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: "carg": +float: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "carg_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "carg_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "carg_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Real part of "casin": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "casin": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "casin_downward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "casin_downward": +double: 5 +float: 3 +idouble: 5 +ifloat: 3 +ildouble: 6 +ldouble: 6 + +Function: Real part of "casin_towardzero": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "casin_towardzero": +double: 4 +float: 2 +idouble: 4 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: Real part of "casin_upward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "casin_upward": +double: 5 +float: 5 +idouble: 5 +ifloat: 5 +ildouble: 7 +ldouble: 7 + +Function: Real part of "casinh": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "casinh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Real part of "casinh_downward": +double: 5 +float: 3 +idouble: 5 +ifloat: 3 +ildouble: 6 +ldouble: 6 + +Function: Imaginary part of "casinh_downward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Real part of "casinh_towardzero": +double: 4 +float: 2 +idouble: 4 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "casinh_towardzero": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: Real part of "casinh_upward": +double: 5 +float: 5 +idouble: 5 +ifloat: 5 +ildouble: 7 +ldouble: 7 + +Function: Imaginary part of "casinh_upward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Real part of "catan": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "catan": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "catan_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "catan_downward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "catan_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "catan_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "catan_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "catan_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Real part of "catanh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "catanh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "catanh_downward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "catanh_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "catanh_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "catanh_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "catanh_upward": +double: 4 +float: 4 +idouble: 4 +ifloat: 4 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "catanh_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "cbrt": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "cbrt_downward": +double: 4 +float: 1 +idouble: 4 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "cbrt_towardzero": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "cbrt_upward": +double: 5 +float: 1 +idouble: 5 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "ccos": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "ccos": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "ccos_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "ccos_downward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "ccos_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "ccos_towardzero": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "ccos_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "ccos_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "ccosh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "ccosh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "ccosh_downward": +double: 1 +float: 3 +idouble: 1 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "ccosh_downward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "ccosh_towardzero": +double: 1 +float: 3 +idouble: 1 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "ccosh_towardzero": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "ccosh_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "ccosh_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "cexp": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "cexp": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: Real part of "cexp_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "cexp_downward": +double: 1 +float: 3 +idouble: 1 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "cexp_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "cexp_towardzero": +double: 1 +float: 3 +idouble: 1 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "cexp_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "cexp_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Real part of "clog": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "clog": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "clog10": +double: 3 +float: 4 +idouble: 3 +ifloat: 4 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "clog10": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog10_downward": +double: 5 +float: 4 +idouble: 5 +ifloat: 4 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "clog10_downward": +double: 2 +float: 4 +idouble: 2 +ifloat: 4 +ildouble: 3 +ldouble: 3 + +Function: Real part of "clog10_towardzero": +double: 5 +float: 5 +idouble: 5 +ifloat: 5 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog10_towardzero": +double: 2 +float: 4 +idouble: 2 +ifloat: 4 +ildouble: 3 +ldouble: 3 + +Function: Real part of "clog10_upward": +double: 6 +float: 5 +idouble: 6 +ifloat: 5 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog10_upward": +double: 2 +float: 4 +idouble: 2 +ifloat: 4 +ildouble: 3 +ldouble: 3 + +Function: Real part of "clog_downward": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "clog_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog_towardzero": +double: 4 +float: 4 +idouble: 4 +ifloat: 4 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "clog_towardzero": +double: 1 +float: 3 +idouble: 1 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog_upward": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "cos": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "cos_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "cos_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "cos_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "cosh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "cosh_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 2 + +Function: "cosh_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 2 + +Function: "cosh_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 1 +ldouble: 3 + +Function: Real part of "cpow": +double: 2 +float: 5 +idouble: 2 +ifloat: 5 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "cpow": +float: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: Real part of "cpow_downward": +double: 4 +float: 8 +idouble: 4 +ifloat: 8 +ildouble: 6 +ldouble: 6 + +Function: Imaginary part of "cpow_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "cpow_towardzero": +double: 4 +float: 8 +idouble: 4 +ifloat: 8 +ildouble: 6 +ldouble: 6 + +Function: Imaginary part of "cpow_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "cpow_upward": +double: 4 +float: 1 +idouble: 4 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "cpow_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csin": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "csin": +ildouble: 1 +ldouble: 1 + +Function: Real part of "csin_downward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "csin_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csin_towardzero": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "csin_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csin_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "csin_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Real part of "csinh": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "csinh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "csinh_downward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "csinh_downward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csinh_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "csinh_towardzero": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csinh_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "csinh_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csqrt": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "csqrt": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csqrt_downward": +double: 5 +float: 4 +idouble: 5 +ifloat: 4 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "csqrt_downward": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: Real part of "csqrt_towardzero": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "csqrt_towardzero": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: Real part of "csqrt_upward": +double: 5 +float: 4 +idouble: 5 +ifloat: 4 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "csqrt_upward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: Real part of "ctan": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "ctan": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: Real part of "ctan_downward": +double: 6 +float: 5 +idouble: 6 +ifloat: 5 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "ctan_downward": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 5 +ldouble: 5 + +Function: Real part of "ctan_towardzero": +double: 5 +float: 3 +idouble: 5 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "ctan_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: Real part of "ctan_upward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "ctan_upward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 5 +ldouble: 5 + +Function: Real part of "ctanh": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Imaginary part of "ctanh": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: Real part of "ctanh_downward": +double: 4 +float: 1 +idouble: 4 +ifloat: 1 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "ctanh_downward": +double: 6 +float: 5 +idouble: 6 +ifloat: 5 +ildouble: 4 +ldouble: 4 + +Function: Real part of "ctanh_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "ctanh_towardzero": +double: 5 +float: 2 +idouble: 5 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: Real part of "ctanh_upward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "ctanh_upward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 5 +ldouble: 5 + +Function: "erf": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "erf_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "erf_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "erf_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "erfc": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "erfc_downward": +double: 3 +float: 4 +idouble: 3 +ifloat: 4 +ildouble: 5 +ldouble: 5 + +Function: "erfc_towardzero": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: "erfc_upward": +double: 3 +float: 4 +idouble: 3 +ifloat: 4 +ildouble: 5 +ldouble: 5 + +Function: "exp": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "exp10": +double: 2 +idouble: 2 +ildouble: 2 +ldouble: 2 + +Function: "exp10_downward": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "exp10_towardzero": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "exp10_upward": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "exp2": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "exp2_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "exp2_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "exp2_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "exp_downward": +double: 1 +idouble: 1 + +Function: "exp_towardzero": +double: 1 +idouble: 1 + +Function: "exp_upward": +double: 1 +idouble: 1 + +Function: "expm1": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "expm1_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "expm1_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: "expm1_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "gamma": +double: 3 +float: 4 +idouble: 3 +ifloat: 4 +ildouble: 5 +ldouble: 5 + +Function: "gamma_downward": +double: 4 +float: 4 +idouble: 4 +ifloat: 4 +ildouble: 8 +ldouble: 8 + +Function: "gamma_towardzero": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 5 +ldouble: 5 + +Function: "gamma_upward": +double: 4 +float: 5 +idouble: 4 +ifloat: 5 +ildouble: 8 +ldouble: 8 + +Function: "hypot": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "hypot_downward": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "hypot_towardzero": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "hypot_upward": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "j0": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "j0_downward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: "j0_towardzero": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "j0_upward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: "j1": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: "j1_downward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: "j1_towardzero": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: "j1_upward": +double: 3 +float: 4 +idouble: 3 +ifloat: 4 +ildouble: 3 +ldouble: 3 + +Function: "jn": +double: 4 +float: 4 +idouble: 4 +ifloat: 4 +ildouble: 7 +ldouble: 7 + +Function: "jn_downward": +double: 4 +float: 5 +idouble: 4 +ifloat: 5 +ildouble: 8 +ldouble: 8 + +Function: "jn_towardzero": +double: 4 +float: 5 +idouble: 4 +ifloat: 5 +ildouble: 8 +ldouble: 8 + +Function: "jn_upward": +double: 5 +float: 4 +idouble: 5 +ifloat: 4 +ildouble: 7 +ldouble: 7 + +Function: "lgamma": +double: 3 +float: 4 +idouble: 3 +ifloat: 4 +ildouble: 5 +ldouble: 5 + +Function: "lgamma_downward": +double: 4 +float: 4 +idouble: 4 +ifloat: 4 +ildouble: 8 +ldouble: 8 + +Function: "lgamma_towardzero": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 5 +ldouble: 5 + +Function: "lgamma_upward": +double: 4 +float: 5 +idouble: 4 +ifloat: 5 +ildouble: 8 +ldouble: 8 + +Function: "log": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log10": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: "log10_downward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 1 +ldouble: 1 + +Function: "log10_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: "log10_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: "log1p": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "log1p_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "log1p_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "log1p_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "log2": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "log2_downward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: "log2_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: "log2_upward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 1 +ldouble: 1 + +Function: "log_downward": +float: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: "log_towardzero": +float: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "log_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: "pow": +float: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "pow10": +double: 2 +idouble: 2 +ildouble: 2 +ldouble: 2 + +Function: "pow10_downward": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "pow10_towardzero": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "pow10_upward": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "pow_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "pow_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "pow_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "sin": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "sin_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "sin_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "sin_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "sincos": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "sincos_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "sincos_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "sincos_upward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "sinh": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "sinh_downward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: "sinh_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "sinh_upward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: "tan": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "tan_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: "tan_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "tan_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "tanh": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "tanh_downward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: "tanh_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "tanh_upward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: "tgamma": +double: 5 +float: 4 +idouble: 5 +ifloat: 4 +ildouble: 4 +ldouble: 4 + +Function: "tgamma_downward": +double: 5 +float: 5 +idouble: 5 +ifloat: 5 +ildouble: 5 +ldouble: 5 + +Function: "tgamma_towardzero": +double: 5 +float: 4 +idouble: 5 +ifloat: 4 +ildouble: 5 +ldouble: 5 + +Function: "tgamma_upward": +double: 4 +float: 4 +idouble: 4 +ifloat: 4 +ildouble: 4 +ldouble: 4 + +Function: "y0": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 3 +ldouble: 3 + +Function: "y0_downward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: "y0_towardzero": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: "y0_upward": +double: 2 +float: 3 +idouble: 2 +ifloat: 3 +ildouble: 3 +ldouble: 3 + +Function: "y1": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "y1_downward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: "y1_towardzero": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "y1_upward": +double: 5 +float: 2 +idouble: 5 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: "yn": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: "yn_downward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: "yn_towardzero": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 5 +ldouble: 5 + +Function: "yn_upward": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 5 +ldouble: 5 + +# end of automatic generation diff --git a/REORG.TODO/sysdeps/s390/fpu/libm-test-ulps-name b/REORG.TODO/sysdeps/s390/fpu/libm-test-ulps-name new file mode 100644 index 0000000000..4a55100a0e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/libm-test-ulps-name @@ -0,0 +1 @@ +S/390 diff --git a/REORG.TODO/sysdeps/s390/fpu/s_fma.c b/REORG.TODO/sysdeps/s390/fpu/s_fma.c new file mode 100644 index 0000000000..fb7210b19a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/s_fma.c @@ -0,0 +1,36 @@ +/* Compute x * y + z as ternary operation. S/390 version. + Copyright (C) 2010-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2010. + + 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/>. */ + +#include <math.h> + +double +__fma (double x, double y, double z) +{ + double r; + __asm__ ("madbr %0,%1,%2" : "=f" (r) : "%f" (x), "fR" (y), "0" (z)); + return r; +} +#ifndef __fma +weak_alias (__fma, fma) +#endif + +#ifdef NO_LONG_DOUBLE +strong_alias (__fma, __fmal) +weak_alias (__fmal, fmal) +#endif diff --git a/REORG.TODO/sysdeps/s390/fpu/s_fmaf.c b/REORG.TODO/sysdeps/s390/fpu/s_fmaf.c new file mode 100644 index 0000000000..c56cc040e8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/fpu/s_fmaf.c @@ -0,0 +1,31 @@ +/* Compute x * y + z as ternary operation. S/390 version. + Copyright (C) 2010-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2010. + + 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/>. */ + +#include <math.h> + +float +__fmaf (float x, float y, float z) +{ + float r; + __asm__ ("maebr %0,%1,%2" : "=f" (r) : "%f" (x), "fR" (y), "0" (z)); + return r; +} +#ifndef __fmaf +weak_alias (__fmaf, fmaf) +#endif diff --git a/REORG.TODO/sysdeps/s390/gccframe.h b/REORG.TODO/sysdeps/s390/gccframe.h new file mode 100644 index 0000000000..2a8b92fdeb --- /dev/null +++ b/REORG.TODO/sysdeps/s390/gccframe.h @@ -0,0 +1,21 @@ +/* Definition of object in frame unwind info. s390 version. + Copyright (C) 2001-2017 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/>. */ + +#define FIRST_PSEUDO_REGISTER 34 + +#include <sysdeps/generic/gccframe.h> diff --git a/REORG.TODO/sysdeps/s390/gconv-modules b/REORG.TODO/sysdeps/s390/gconv-modules new file mode 100644 index 0000000000..16ab030626 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/gconv-modules @@ -0,0 +1,50 @@ +# GNU libc iconv configuration. +# Copyright (C) 1997-2017 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/>. + +# All lines contain the following information: + +# If the lines start with `module' +# fromset: either a name triple or a regular expression triple. +# toset: a name triple or an expression with \N to get regular +# expression matching results. +# filename: filename of the module implementing the transformation. +# If it is not absolute the path is made absolute by prepending +# the directory the configuration file is found in. +# cost: optional cost of the transformation. Default is 1. + +# If the lines start with `alias' +# alias: alias name which is not really recognized. +# name: the real name of the character set + +# S/390 hardware accelerated modules +# from to module cost +module ISO-8859-1// IBM037// ISO-8859-1_CP037_Z900 1 +module IBM037// ISO-8859-1// ISO-8859-1_CP037_Z900 1 +module ISO-10646/UTF8/ UTF-32// UTF8_UTF32_Z9 1 +module UTF-32BE// ISO-10646/UTF8/ UTF8_UTF32_Z9 1 +module ISO-10646/UTF8/ UTF-32BE// UTF8_UTF32_Z9 1 +module UTF-16BE// UTF-32// UTF16_UTF32_Z9 1 +module UTF-32BE// UTF-16// UTF16_UTF32_Z9 1 +module INTERNAL UTF-16// UTF16_UTF32_Z9 1 +module UTF-32BE// UTF-16BE// UTF16_UTF32_Z9 1 +module INTERNAL UTF-16BE// UTF16_UTF32_Z9 1 +module UTF-16BE// UTF-32BE// UTF16_UTF32_Z9 1 +module UTF-16BE// INTERNAL UTF16_UTF32_Z9 1 +module UTF-16BE// ISO-10646/UTF8/ UTF8_UTF16_Z9 1 +module ISO-10646/UTF8/ UTF-16// UTF8_UTF16_Z9 1 +module ISO-10646/UTF8/ UTF-16BE// UTF8_UTF16_Z9 1 diff --git a/REORG.TODO/sysdeps/s390/gmp-mparam.h b/REORG.TODO/sysdeps/s390/gmp-mparam.h new file mode 100644 index 0000000000..ec0139ade8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/gmp-mparam.h @@ -0,0 +1,30 @@ +/* gmp-mparam.h -- Compiler/machine parameter header file. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + This file is part of the GNU MP Library. + + The GNU MP 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 MP 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; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <bits/wordsize.h> + +#define BITS_PER_MP_LIMB __WORDSIZE +#define BYTES_PER_MP_LIMB (__WORDSIZE / 8) +#define BITS_PER_LONGINT __WORDSIZE +#define BITS_PER_INT 32 +#define BITS_PER_SHORTINT 16 +#define BITS_PER_CHAR 8 + +#define IEEE_DOUBLE_BIG_ENDIAN 0 diff --git a/REORG.TODO/sysdeps/s390/iso-8859-1_cp037_z900.c b/REORG.TODO/sysdeps/s390/iso-8859-1_cp037_z900.c new file mode 100644 index 0000000000..f4a5b14fd7 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/iso-8859-1_cp037_z900.c @@ -0,0 +1,262 @@ +/* Conversion between ISO 8859-1 and IBM037. + + This module uses the translate instruction. + Copyright (C) 1997-2017 Free Software Foundation, Inc. + + Author: Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + Based on the work by Ulrich Drepper <drepper@cygnus.com>, 1997. + + Thanks to Daniel Appich who covered the relevant performance work + in his diploma thesis. + + This 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. + + This 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/>. */ + +#include <dlfcn.h> +#include <stdint.h> + +// conversion table from ISO-8859-1 to IBM037 +static const unsigned char table_iso8859_1_to_cp037[256] +__attribute__ ((aligned (8))) = +{ + [0x00] = 0x00, [0x01] = 0x01, [0x02] = 0x02, [0x03] = 0x03, + [0x04] = 0x37, [0x05] = 0x2D, [0x06] = 0x2E, [0x07] = 0x2F, + [0x08] = 0x16, [0x09] = 0x05, [0x0A] = 0x25, [0x0B] = 0x0B, + [0x0C] = 0x0C, [0x0D] = 0x0D, [0x0E] = 0x0E, [0x0F] = 0x0F, + [0x10] = 0x10, [0x11] = 0x11, [0x12] = 0x12, [0x13] = 0x13, + [0x14] = 0x3C, [0x15] = 0x3D, [0x16] = 0x32, [0x17] = 0x26, + [0x18] = 0x18, [0x19] = 0x19, [0x1A] = 0x3F, [0x1B] = 0x27, + [0x1C] = 0x1C, [0x1D] = 0x1D, [0x1E] = 0x1E, [0x1F] = 0x1F, + [0x20] = 0x40, [0x21] = 0x5A, [0x22] = 0x7F, [0x23] = 0x7B, + [0x24] = 0x5B, [0x25] = 0x6C, [0x26] = 0x50, [0x27] = 0x7D, + [0x28] = 0x4D, [0x29] = 0x5D, [0x2A] = 0x5C, [0x2B] = 0x4E, + [0x2C] = 0x6B, [0x2D] = 0x60, [0x2E] = 0x4B, [0x2F] = 0x61, + [0x30] = 0xF0, [0x31] = 0xF1, [0x32] = 0xF2, [0x33] = 0xF3, + [0x34] = 0xF4, [0x35] = 0xF5, [0x36] = 0xF6, [0x37] = 0xF7, + [0x38] = 0xF8, [0x39] = 0xF9, [0x3A] = 0x7A, [0x3B] = 0x5E, + [0x3C] = 0x4C, [0x3D] = 0x7E, [0x3E] = 0x6E, [0x3F] = 0x6F, + [0x40] = 0x7C, [0x41] = 0xC1, [0x42] = 0xC2, [0x43] = 0xC3, + [0x44] = 0xC4, [0x45] = 0xC5, [0x46] = 0xC6, [0x47] = 0xC7, + [0x48] = 0xC8, [0x49] = 0xC9, [0x4A] = 0xD1, [0x4B] = 0xD2, + [0x4C] = 0xD3, [0x4D] = 0xD4, [0x4E] = 0xD5, [0x4F] = 0xD6, + [0x50] = 0xD7, [0x51] = 0xD8, [0x52] = 0xD9, [0x53] = 0xE2, + [0x54] = 0xE3, [0x55] = 0xE4, [0x56] = 0xE5, [0x57] = 0xE6, + [0x58] = 0xE7, [0x59] = 0xE8, [0x5A] = 0xE9, [0x5B] = 0xBA, + [0x5C] = 0xE0, [0x5D] = 0xBB, [0x5E] = 0xB0, [0x5F] = 0x6D, + [0x60] = 0x79, [0x61] = 0x81, [0x62] = 0x82, [0x63] = 0x83, + [0x64] = 0x84, [0x65] = 0x85, [0x66] = 0x86, [0x67] = 0x87, + [0x68] = 0x88, [0x69] = 0x89, [0x6A] = 0x91, [0x6B] = 0x92, + [0x6C] = 0x93, [0x6D] = 0x94, [0x6E] = 0x95, [0x6F] = 0x96, + [0x70] = 0x97, [0x71] = 0x98, [0x72] = 0x99, [0x73] = 0xA2, + [0x74] = 0xA3, [0x75] = 0xA4, [0x76] = 0xA5, [0x77] = 0xA6, + [0x78] = 0xA7, [0x79] = 0xA8, [0x7A] = 0xA9, [0x7B] = 0xC0, + [0x7C] = 0x4F, [0x7D] = 0xD0, [0x7E] = 0xA1, [0x7F] = 0x07, + [0x80] = 0x20, [0x81] = 0x21, [0x82] = 0x22, [0x83] = 0x23, + [0x84] = 0x24, [0x85] = 0x15, [0x86] = 0x06, [0x87] = 0x17, + [0x88] = 0x28, [0x89] = 0x29, [0x8A] = 0x2A, [0x8B] = 0x2B, + [0x8C] = 0x2C, [0x8D] = 0x09, [0x8E] = 0x0A, [0x8F] = 0x1B, + [0x90] = 0x30, [0x91] = 0x31, [0x92] = 0x1A, [0x93] = 0x33, + [0x94] = 0x34, [0x95] = 0x35, [0x96] = 0x36, [0x97] = 0x08, + [0x98] = 0x38, [0x99] = 0x39, [0x9A] = 0x3A, [0x9B] = 0x3B, + [0x9C] = 0x04, [0x9D] = 0x14, [0x9E] = 0x3E, [0x9F] = 0xFF, + [0xA0] = 0x41, [0xA1] = 0xAA, [0xA2] = 0x4A, [0xA3] = 0xB1, + [0xA4] = 0x9F, [0xA5] = 0xB2, [0xA6] = 0x6A, [0xA7] = 0xB5, + [0xA8] = 0xBD, [0xA9] = 0xB4, [0xAA] = 0x9A, [0xAB] = 0x8A, + [0xAC] = 0x5F, [0xAD] = 0xCA, [0xAE] = 0xAF, [0xAF] = 0xBC, + [0xB0] = 0x90, [0xB1] = 0x8F, [0xB2] = 0xEA, [0xB3] = 0xFA, + [0xB4] = 0xBE, [0xB5] = 0xA0, [0xB6] = 0xB6, [0xB7] = 0xB3, + [0xB8] = 0x9D, [0xB9] = 0xDA, [0xBA] = 0x9B, [0xBB] = 0x8B, + [0xBC] = 0xB7, [0xBD] = 0xB8, [0xBE] = 0xB9, [0xBF] = 0xAB, + [0xC0] = 0x64, [0xC1] = 0x65, [0xC2] = 0x62, [0xC3] = 0x66, + [0xC4] = 0x63, [0xC5] = 0x67, [0xC6] = 0x9E, [0xC7] = 0x68, + [0xC8] = 0x74, [0xC9] = 0x71, [0xCA] = 0x72, [0xCB] = 0x73, + [0xCC] = 0x78, [0xCD] = 0x75, [0xCE] = 0x76, [0xCF] = 0x77, + [0xD0] = 0xAC, [0xD1] = 0x69, [0xD2] = 0xED, [0xD3] = 0xEE, + [0xD4] = 0xEB, [0xD5] = 0xEF, [0xD6] = 0xEC, [0xD7] = 0xBF, + [0xD8] = 0x80, [0xD9] = 0xFD, [0xDA] = 0xFE, [0xDB] = 0xFB, + [0xDC] = 0xFC, [0xDD] = 0xAD, [0xDE] = 0xAE, [0xDF] = 0x59, + [0xE0] = 0x44, [0xE1] = 0x45, [0xE2] = 0x42, [0xE3] = 0x46, + [0xE4] = 0x43, [0xE5] = 0x47, [0xE6] = 0x9C, [0xE7] = 0x48, + [0xE8] = 0x54, [0xE9] = 0x51, [0xEA] = 0x52, [0xEB] = 0x53, + [0xEC] = 0x58, [0xED] = 0x55, [0xEE] = 0x56, [0xEF] = 0x57, + [0xF0] = 0x8C, [0xF1] = 0x49, [0xF2] = 0xCD, [0xF3] = 0xCE, + [0xF4] = 0xCB, [0xF5] = 0xCF, [0xF6] = 0xCC, [0xF7] = 0xE1, + [0xF8] = 0x70, [0xF9] = 0xDD, [0xFA] = 0xDE, [0xFB] = 0xDB, + [0xFC] = 0xDC, [0xFD] = 0x8D, [0xFE] = 0x8E, [0xFF] = 0xDF +}; + +// conversion table from IBM037 to ISO-8859-1 +static const unsigned char table_cp037_iso8859_1[256] +__attribute__ ((aligned (8))) = +{ + [0x00] = 0x00, [0x01] = 0x01, [0x02] = 0x02, [0x03] = 0x03, + [0x04] = 0x9C, [0x05] = 0x09, [0x06] = 0x86, [0x07] = 0x7F, + [0x08] = 0x97, [0x09] = 0x8D, [0x0A] = 0x8E, [0x0B] = 0x0B, + [0x0C] = 0x0C, [0x0D] = 0x0D, [0x0E] = 0x0E, [0x0F] = 0x0F, + [0x10] = 0x10, [0x11] = 0x11, [0x12] = 0x12, [0x13] = 0x13, + [0x14] = 0x9D, [0x15] = 0x85, [0x16] = 0x08, [0x17] = 0x87, + [0x18] = 0x18, [0x19] = 0x19, [0x1A] = 0x92, [0x1B] = 0x8F, + [0x1C] = 0x1C, [0x1D] = 0x1D, [0x1E] = 0x1E, [0x1F] = 0x1F, + [0x20] = 0x80, [0x21] = 0x81, [0x22] = 0x82, [0x23] = 0x83, + [0x24] = 0x84, [0x25] = 0x0A, [0x26] = 0x17, [0x27] = 0x1B, + [0x28] = 0x88, [0x29] = 0x89, [0x2A] = 0x8A, [0x2B] = 0x8B, + [0x2C] = 0x8C, [0x2D] = 0x05, [0x2E] = 0x06, [0x2F] = 0x07, + [0x30] = 0x90, [0x31] = 0x91, [0x32] = 0x16, [0x33] = 0x93, + [0x34] = 0x94, [0x35] = 0x95, [0x36] = 0x96, [0x37] = 0x04, + [0x38] = 0x98, [0x39] = 0x99, [0x3A] = 0x9A, [0x3B] = 0x9B, + [0x3C] = 0x14, [0x3D] = 0x15, [0x3E] = 0x9E, [0x3F] = 0x1A, + [0x40] = 0x20, [0x41] = 0xA0, [0x42] = 0xE2, [0x43] = 0xE4, + [0x44] = 0xE0, [0x45] = 0xE1, [0x46] = 0xE3, [0x47] = 0xE5, + [0x48] = 0xE7, [0x49] = 0xF1, [0x4A] = 0xA2, [0x4B] = 0x2E, + [0x4C] = 0x3C, [0x4D] = 0x28, [0x4E] = 0x2B, [0x4F] = 0x7C, + [0x50] = 0x26, [0x51] = 0xE9, [0x52] = 0xEA, [0x53] = 0xEB, + [0x54] = 0xE8, [0x55] = 0xED, [0x56] = 0xEE, [0x57] = 0xEF, + [0x58] = 0xEC, [0x59] = 0xDF, [0x5A] = 0x21, [0x5B] = 0x24, + [0x5C] = 0x2A, [0x5D] = 0x29, [0x5E] = 0x3B, [0x5F] = 0xAC, + [0x60] = 0x2D, [0x61] = 0x2F, [0x62] = 0xC2, [0x63] = 0xC4, + [0x64] = 0xC0, [0x65] = 0xC1, [0x66] = 0xC3, [0x67] = 0xC5, + [0x68] = 0xC7, [0x69] = 0xD1, [0x6A] = 0xA6, [0x6B] = 0x2C, + [0x6C] = 0x25, [0x6D] = 0x5F, [0x6E] = 0x3E, [0x6F] = 0x3F, + [0x70] = 0xF8, [0x71] = 0xC9, [0x72] = 0xCA, [0x73] = 0xCB, + [0x74] = 0xC8, [0x75] = 0xCD, [0x76] = 0xCE, [0x77] = 0xCF, + [0x78] = 0xCC, [0x79] = 0x60, [0x7A] = 0x3A, [0x7B] = 0x23, + [0x7C] = 0x40, [0x7D] = 0x27, [0x7E] = 0x3D, [0x7F] = 0x22, + [0x80] = 0xD8, [0x81] = 0x61, [0x82] = 0x62, [0x83] = 0x63, + [0x84] = 0x64, [0x85] = 0x65, [0x86] = 0x66, [0x87] = 0x67, + [0x88] = 0x68, [0x89] = 0x69, [0x8A] = 0xAB, [0x8B] = 0xBB, + [0x8C] = 0xF0, [0x8D] = 0xFD, [0x8E] = 0xFE, [0x8F] = 0xB1, + [0x90] = 0xB0, [0x91] = 0x6A, [0x92] = 0x6B, [0x93] = 0x6C, + [0x94] = 0x6D, [0x95] = 0x6E, [0x96] = 0x6F, [0x97] = 0x70, + [0x98] = 0x71, [0x99] = 0x72, [0x9A] = 0xAA, [0x9B] = 0xBA, + [0x9C] = 0xE6, [0x9D] = 0xB8, [0x9E] = 0xC6, [0x9F] = 0xA4, + [0xA0] = 0xB5, [0xA1] = 0x7E, [0xA2] = 0x73, [0xA3] = 0x74, + [0xA4] = 0x75, [0xA5] = 0x76, [0xA6] = 0x77, [0xA7] = 0x78, + [0xA8] = 0x79, [0xA9] = 0x7A, [0xAA] = 0xA1, [0xAB] = 0xBF, + [0xAC] = 0xD0, [0xAD] = 0xDD, [0xAE] = 0xDE, [0xAF] = 0xAE, + [0xB0] = 0x5E, [0xB1] = 0xA3, [0xB2] = 0xA5, [0xB3] = 0xB7, + [0xB4] = 0xA9, [0xB5] = 0xA7, [0xB6] = 0xB6, [0xB7] = 0xBC, + [0xB8] = 0xBD, [0xB9] = 0xBE, [0xBA] = 0x5B, [0xBB] = 0x5D, + [0xBC] = 0xAF, [0xBD] = 0xA8, [0xBE] = 0xB4, [0xBF] = 0xD7, + [0xC0] = 0x7B, [0xC1] = 0x41, [0xC2] = 0x42, [0xC3] = 0x43, + [0xC4] = 0x44, [0xC5] = 0x45, [0xC6] = 0x46, [0xC7] = 0x47, + [0xC8] = 0x48, [0xC9] = 0x49, [0xCA] = 0xAD, [0xCB] = 0xF4, + [0xCC] = 0xF6, [0xCD] = 0xF2, [0xCE] = 0xF3, [0xCF] = 0xF5, + [0xD0] = 0x7D, [0xD1] = 0x4A, [0xD2] = 0x4B, [0xD3] = 0x4C, + [0xD4] = 0x4D, [0xD5] = 0x4E, [0xD6] = 0x4F, [0xD7] = 0x50, + [0xD8] = 0x51, [0xD9] = 0x52, [0xDA] = 0xB9, [0xDB] = 0xFB, + [0xDC] = 0xFC, [0xDD] = 0xF9, [0xDE] = 0xFA, [0xDF] = 0xFF, + [0xE0] = 0x5C, [0xE1] = 0xF7, [0xE2] = 0x53, [0xE3] = 0x54, + [0xE4] = 0x55, [0xE5] = 0x56, [0xE6] = 0x57, [0xE7] = 0x58, + [0xE8] = 0x59, [0xE9] = 0x5A, [0xEA] = 0xB2, [0xEB] = 0xD4, + [0xEC] = 0xD6, [0xED] = 0xD2, [0xEE] = 0xD3, [0xEF] = 0xD5, + [0xF0] = 0x30, [0xF1] = 0x31, [0xF2] = 0x32, [0xF3] = 0x33, + [0xF4] = 0x34, [0xF5] = 0x35, [0xF6] = 0x36, [0xF7] = 0x37, + [0xF8] = 0x38, [0xF9] = 0x39, [0xFA] = 0xB3, [0xFB] = 0xDB, + [0xFC] = 0xDC, [0xFD] = 0xD9, [0xFE] = 0xDA, [0xFF] = 0x9F +}; + +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "ISO-8859-1//" +#define FROM_LOOP iso8859_1_to_cp037_z900 +#define TO_LOOP cp037_to_iso8859_1_z900 +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MIN_NEEDED_TO 1 + +# if defined __s390x__ +# define BRANCH_ON_COUNT(REG,LBL) "brctg %" #REG "," #LBL "\n\t" +# else +# define BRANCH_ON_COUNT(REG,LBL) "brct %" #REG "," #LBL "\n\t" +# endif + +#define TR_LOOP(TABLE) \ + { \ + size_t length = (inend - inptr < outend - outptr \ + ? inend - inptr : outend - outptr); \ + \ + /* Process in 256 byte blocks. */ \ + if (__builtin_expect (length >= 256, 0)) \ + { \ + size_t blocks = length / 256; \ + __asm__ __volatile__("0: mvc 0(256,%[R_OUT]),0(%[R_IN])\n\t" \ + " tr 0(256,%[R_OUT]),0(%[R_TBL])\n\t" \ + " la %[R_IN],256(%[R_IN])\n\t" \ + " la %[R_OUT],256(%[R_OUT])\n\t" \ + BRANCH_ON_COUNT ([R_LI], 0b) \ + : /* outputs */ [R_IN] "+a" (inptr) \ + , [R_OUT] "+a" (outptr), [R_LI] "+d" (blocks) \ + : /* inputs */ [R_TBL] "a" (TABLE) \ + : /* clobber list */ "memory" \ + ); \ + length = length % 256; \ + } \ + \ + /* Process remaining 0...248 bytes in 8byte blocks. */ \ + if (length >= 8) \ + { \ + size_t blocks = length / 8; \ + for (int i = 0; i < blocks; i++) \ + { \ + outptr[0] = TABLE[inptr[0]]; \ + outptr[1] = TABLE[inptr[1]]; \ + outptr[2] = TABLE[inptr[2]]; \ + outptr[3] = TABLE[inptr[3]]; \ + outptr[4] = TABLE[inptr[4]]; \ + outptr[5] = TABLE[inptr[5]]; \ + outptr[6] = TABLE[inptr[6]]; \ + outptr[7] = TABLE[inptr[7]]; \ + inptr += 8; \ + outptr += 8; \ + } \ + length = length % 8; \ + } \ + \ + /* Process remaining 0...7 bytes. */ \ + switch (length) \ + { \ + case 7: outptr[6] = TABLE[inptr[6]]; \ + case 6: outptr[5] = TABLE[inptr[5]]; \ + case 5: outptr[4] = TABLE[inptr[4]]; \ + case 4: outptr[3] = TABLE[inptr[3]]; \ + case 3: outptr[2] = TABLE[inptr[2]]; \ + case 2: outptr[1] = TABLE[inptr[1]]; \ + case 1: outptr[0] = TABLE[inptr[0]]; \ + case 0: break; \ + } \ + inptr += length; \ + outptr += length; \ + } + + +/* First define the conversion function from ISO 8859-1 to CP037. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY TR_LOOP (table_iso8859_1_to_cp037) + +#include <iconv/loop.c> + + +/* Next, define the conversion function from CP037 to ISO 8859-1. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY TR_LOOP (table_cp037_iso8859_1); + +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/REORG.TODO/sysdeps/s390/jmpbuf-offsets.h b/REORG.TODO/sysdeps/s390/jmpbuf-offsets.h new file mode 100644 index 0000000000..e175801ffa --- /dev/null +++ b/REORG.TODO/sysdeps/s390/jmpbuf-offsets.h @@ -0,0 +1,28 @@ +/* Private macros for accessing __jmp_buf contents. S/390 version. + Copyright (C) 2006-2017 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/>. */ + +#define __JB_GPR6 0 +#define __JB_GPR7 1 +#define __JB_GPR8 2 +#define __JB_GPR9 3 +#define __JB_GPR10 4 +#define __JB_GPR11 5 +#define __JB_GPR12 6 +#define __JB_GPR13 7 +#define __JB_GPR14 8 +#define __JB_GPR15 9 diff --git a/REORG.TODO/sysdeps/s390/jmpbuf-unwind.h b/REORG.TODO/sysdeps/s390/jmpbuf-unwind.h new file mode 100644 index 0000000000..4c8e91cea7 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/jmpbuf-unwind.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + + 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/>. */ + +#include <setjmp.h> +#include <jmpbuf-offsets.h> +#include <stdint.h> +#include <unwind.h> +#include <bits/wordsize.h> +#include <sysdep.h> + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \ + ((void *) (address) < (void *) demangle ((jmpbuf)->__gregs[__JB_GPR15])) + + +/* On s390{,x}, CFA is always 96 (resp. 160) bytes above actual + %r15. */ +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, \ + (void *) (_Unwind_GetCFA (_context) \ + - 32 - 2 * __WORDSIZE), _adj) + +static inline uintptr_t __attribute__ ((unused)) +_jmpbuf_sp (__jmp_buf regs) +{ + void *sp = (void *) (uintptr_t) regs[0].__gregs[__JB_GPR15]; +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (sp); +#endif + return (uintptr_t) sp; +} + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj)) + +/* We use the normal longjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/REORG.TODO/sysdeps/s390/ldsodefs.h b/REORG.TODO/sysdeps/s390/ldsodefs.h new file mode 100644 index 0000000000..706f57dc9c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/ldsodefs.h @@ -0,0 +1,57 @@ +/* Run-time dynamic linker data structures for loaded ELF shared objects. + Copyright (C) 1995-2017 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/>. */ + +#ifndef _S390_LDSODEFS_H +#define _S390_LDSODEFS_H 1 + +#include <elf.h> + +struct La_s390_32_regs; +struct La_s390_32_retval; +struct La_s390_64_regs; +struct La_s390_64_retval; + +#define ARCH_PLTENTER_MEMBERS \ + Elf32_Addr (*s390_32_gnu_pltenter) (Elf32_Sym *, unsigned int, \ + uintptr_t *, \ + uintptr_t *, \ + struct La_s390_32_regs *, \ + unsigned int *, const char *name, \ + long int *framesizep); \ + Elf64_Addr (*s390_64_gnu_pltenter) (Elf64_Sym *, unsigned int, \ + uintptr_t *, \ + uintptr_t *, \ + struct La_s390_64_regs *, \ + unsigned int *, const char *name, \ + long int *framesizep) + +#define ARCH_PLTEXIT_MEMBERS \ + unsigned int (*s390_32_gnu_pltexit) (Elf32_Sym *, unsigned int, \ + uintptr_t *, uintptr_t *, \ + const struct La_s390_32_regs *, \ + struct La_s390_32_retval *, \ + const char *); \ + unsigned int (*s390_64_gnu_pltexit) (Elf64_Sym *, unsigned int, \ + uintptr_t *, uintptr_t *, \ + const struct La_s390_64_regs *, \ + struct La_s390_64_retval *, \ + const char *) + +#include_next <ldsodefs.h> + +#endif diff --git a/REORG.TODO/sysdeps/s390/libc-tls.c b/REORG.TODO/sysdeps/s390/libc-tls.c new file mode 100644 index 0000000000..d19632f7fb --- /dev/null +++ b/REORG.TODO/sysdeps/s390/libc-tls.c @@ -0,0 +1,32 @@ +/* Thread-local storage handling in the ELF dynamic linker. S390 version. + Copyright (C) 2003-2017 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/>. */ + +#include <stdlib.h> +#include <csu/libc-tls.c> + +/* On s390, the literal pool entry that refers to __tls_get_offset + is not removed, even if all branches that use the literal pool + entry gets removed by TLS optimizations. To get binaries + statically linked __tls_get_offset is defined here but + aborts if it is used. */ + +void * +__tls_get_offset (size_t m, size_t offset) +{ + abort (); +} diff --git a/REORG.TODO/sysdeps/s390/linkmap.h b/REORG.TODO/sysdeps/s390/linkmap.h new file mode 100644 index 0000000000..283615b99a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/linkmap.h @@ -0,0 +1,13 @@ +#if __WORDSIZE == 64 +struct link_map_machine + { + Elf64_Addr plt; /* Address of .plt + 0x2e */ + const Elf64_Rela *jmprel; /* Address of first JMP_SLOT reloc */ + }; +#else +struct link_map_machine + { + Elf32_Addr plt; /* Address of .plt + 0x2c */ + const Elf32_Rela *jmprel; /* Address of first JMP_SLOT reloc */ + }; +#endif diff --git a/REORG.TODO/sysdeps/s390/longjmp.c b/REORG.TODO/sysdeps/s390/longjmp.c new file mode 100644 index 0000000000..d108669ecc --- /dev/null +++ b/REORG.TODO/sysdeps/s390/longjmp.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2014-2017 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/>. + + Versioned copy of setjmp/longjmp.c modified for versioning + the reverted jmpbuf extension. */ + +#include <shlib-compat.h> + +#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20) +/* We don't want the weak alias to longjmp, _longjmp, siglongjmp here, + because we create the default/versioned symbols later. */ +# define __libc_siglongjmp __libc_siglongjmp +#endif /* SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20) */ + +#include <setjmp/longjmp.c> + +#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20) +/* In glibc release 2.19 new versions of longjmp-functions were introduced, + but were reverted before 2.20. Thus both versions are the same function. */ + +strong_alias (__libc_siglongjmp, __libc_longjmp) +libc_hidden_def (__libc_longjmp) + +weak_alias (__libc_siglongjmp, __v1_longjmp) +weak_alias (__libc_siglongjmp, __v2_longjmp) +versioned_symbol (libc, __v1_longjmp, _longjmp, GLIBC_2_0); +compat_symbol (libc, __v2_longjmp, _longjmp, GLIBC_2_19); + +weak_alias (__libc_siglongjmp, __v1longjmp) +weak_alias (__libc_siglongjmp, __v2longjmp) +versioned_symbol (libc, __v1longjmp, longjmp, GLIBC_2_0); +compat_symbol (libc, __v2longjmp, longjmp, GLIBC_2_19); + +weak_alias (__libc_siglongjmp, __v1siglongjmp) +weak_alias (__libc_siglongjmp, __v2siglongjmp) +versioned_symbol (libc, __v1siglongjmp, siglongjmp, GLIBC_2_0); +compat_symbol (libc, __v2siglongjmp, siglongjmp, GLIBC_2_19); +#endif /* SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20) */ diff --git a/REORG.TODO/sysdeps/s390/machine-gmon.h b/REORG.TODO/sysdeps/s390/machine-gmon.h new file mode 100644 index 0000000000..dac340cf7e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/machine-gmon.h @@ -0,0 +1,35 @@ +/* s390-specific implementation of profiling support. + Copyright (C) 2000-2017 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/>. */ + +#include <sysdep.h> + +/* We need a special version of the `mcount' function since for S/390 it + must not clobber any register. */ + +/* We must not pollute the global namespace. */ +#define mcount_internal __mcount_internal + +void mcount_internal (u_long frompc, u_long selfpc); + +#define _MCOUNT_DECL(frompc, selfpc) \ +void mcount_internal (u_long frompc, u_long selfpc) + + +/* Define MCOUNT as empty since we have the implementation in another + file. */ +#define MCOUNT diff --git a/REORG.TODO/sysdeps/s390/mempcpy.S b/REORG.TODO/sysdeps/s390/mempcpy.S new file mode 100644 index 0000000000..acb90bb260 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/mempcpy.S @@ -0,0 +1,19 @@ +/* CPU specific mempcpy without multiarch - 32/64 bit S/390 version. + Copyright (C) 2016-2017 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/REORG.TODO/sysdeps/s390/memusage.h b/REORG.TODO/sysdeps/s390/memusage.h new file mode 100644 index 0000000000..347272c483 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/memusage.h @@ -0,0 +1,20 @@ +/* Copyright (C) 2000-2017 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/>. */ + +#define GETSP() ({ register uintptr_t stack_ptr __asm__ ("15"); stack_ptr; }) + +#include <sysdeps/generic/memusage.h> diff --git a/REORG.TODO/sysdeps/s390/multiarch/8bit-generic.c b/REORG.TODO/sysdeps/s390/multiarch/8bit-generic.c new file mode 100644 index 0000000000..49f0ed8ae5 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/8bit-generic.c @@ -0,0 +1,398 @@ +/* Generic conversion to and from 8bit charsets - S390 version. + Copyright (C) 2016-2017 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 HAVE_S390_VX_ASM_SUPPORT + +# if defined HAVE_S390_VX_GCC_SUPPORT +# define ASM_CLOBBER_VR(NR) , NR +# else +# define ASM_CLOBBER_VR(NR) +# endif + +/* Generate the conversion loop routines without vector instructions as + fallback, if vector instructions aren't available at runtime. */ +# define IGNORE_ICONV_SKELETON +# define from_generic __from_generic_c +# define to_generic __to_generic_c +# include "iconvdata/8bit-generic.c" +# undef IGNORE_ICONV_SKELETON +# undef from_generic +# undef to_generic + +/* Generate the converion routines with vector instructions. The vector + routines can only be used with charsets where the maximum UCS4 value + fits in 1 byte size. Then the hardware translate-instruction is used + to translate between multiple generic characters and "1 byte UCS4" + characters at once. The vector instructions are used to convert between + the "1 byte UCS4" and UCS4. */ +# include <ifunc-resolve.h> + +# undef FROM_LOOP +# undef TO_LOOP +# define FROM_LOOP __from_generic_vx +# define TO_LOOP __to_generic_vx + +# define MIN_NEEDED_FROM 1 +# define MIN_NEEDED_TO 4 +# define ONE_DIRECTION 0 + +/* First define the conversion function from the 8bit charset to UCS4. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define LOOPFCT FROM_LOOP +# define BODY_FROM_ORIG \ + { \ + uint32_t ch = to_ucs4[*inptr]; \ + \ + if (HAS_HOLES && __builtin_expect (ch == L'\0', 0) && *inptr != '\0') \ + { \ + /* This is an illegal character. */ \ + STANDARD_FROM_LOOP_ERR_HANDLER (1); \ + } \ + \ + put32 (outptr, ch); \ + outptr += 4; \ + ++inptr; \ + } + +# define BODY \ + { \ + if (__builtin_expect (inend - inptr < 16, 1) \ + || outend - outptr < 64) \ + /* Convert remaining bytes with c code. */ \ + BODY_FROM_ORIG \ + else \ + { \ + /* Convert 16 ... 256 bytes at once with tr-instruction. */ \ + size_t index; \ + char buf[256]; \ + size_t loop_count = (inend - inptr) / 16; \ + if (loop_count > (outend - outptr) / 64) \ + loop_count = (outend - outptr) / 64; \ + if (loop_count > 16) \ + loop_count = 16; \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + " sllk %[R_I],%[R_LI],4\n\t" \ + " ahi %[R_I],-1\n\t" \ + /* Execute mvc and tr with correct len. */ \ + " exrl %[R_I],21f\n\t" \ + " exrl %[R_I],22f\n\t" \ + /* Post-processing. */ \ + " lghi %[R_I],0\n\t" \ + " vzero %%v0\n\t" \ + "0: \n\t" \ + /* Find invalid character - value is zero. */ \ + " vl %%v16,0(%[R_I],%[R_BUF])\n\t" \ + " vceqbs %%v23,%%v0,%%v16\n\t" \ + " jle 10f\n\t" \ + "1: \n\t" \ + /* Enlarge to UCS4. */ \ + " vuplhb %%v17,%%v16\n\t" \ + " vupllb %%v18,%%v16\n\t" \ + " vuplhh %%v19,%%v17\n\t" \ + " vupllh %%v20,%%v17\n\t" \ + " vuplhh %%v21,%%v18\n\t" \ + " vupllh %%v22,%%v18\n\t" \ + /* Store 64bytes to buf_out. */ \ + " vstm %%v19,%%v22,0(%[R_OUT])\n\t" \ + " aghi %[R_I],16\n\t" \ + " la %[R_OUT],64(%[R_OUT])\n\t" \ + " brct %[R_LI],0b\n\t" \ + " la %[R_IN],0(%[R_I],%[R_IN])\n\t" \ + " j 20f\n\t" \ + "21: mvc 0(1,%[R_BUF]),0(%[R_IN])\n\t" \ + "22: tr 0(1,%[R_BUF]),0(%[R_TBL])\n\t" \ + /* Possibly invalid character found. */ \ + "10: \n\t" \ + /* Test if input was zero, too. */ \ + " vl %%v24,0(%[R_I],%[R_IN])\n\t" \ + " vceqb %%v24,%%v0,%%v24\n\t" \ + /* Zeros in buf (v23) and inptr (v24) are marked \ + with one bits. After xor, invalid characters \ + are marked as one bits. Proceed, if no \ + invalid characters are found. */ \ + " vx %%v24,%%v23,%%v24\n\t" \ + " vfenebs %%v24,%%v24,%%v0\n\t" \ + " jo 1b\n\t" \ + /* Found an invalid translation. \ + Store the preceding chars. */ \ + " la %[R_IN],0(%[R_I],%[R_IN])\n\t" \ + " vlgvb %[R_I],%%v24,7\n\t" \ + " la %[R_IN],0(%[R_I],%[R_IN])\n\t" \ + " sll %[R_I],2\n\t" \ + " ahi %[R_I],-1\n\t" \ + " jl 20f\n\t" \ + " lgr %[R_LI],%[R_I]\n\t" \ + " vuplhb %%v17,%%v16\n\t" \ + " vuplhh %%v19,%%v17\n\t" \ + " vstl %%v19,%[R_I],0(%[R_OUT])\n\t" \ + " ahi %[R_I],-16\n\t" \ + " jl 11f\n\t" \ + " vupllh %%v20,%%v17\n\t" \ + " vstl %%v20,%[R_I],16(%[R_OUT])\n\t" \ + " ahi %[R_I],-16\n\t" \ + " jl 11f\n\t" \ + " vupllb %%v18,%%v16\n\t" \ + " vuplhh %%v21,%%v18\n\t" \ + " vstl %%v21,%[R_I],32(%[R_OUT])\n\t" \ + " ahi %[R_I],-16\n\t" \ + " jl 11f\n\t" \ + " vupllh %%v22,%%v18\n\t" \ + " vstl %%v22,%[R_I],48(%[R_OUT])\n\t" \ + "11: \n\t" \ + " la %[R_OUT],1(%[R_LI],%[R_OUT])\n\t" \ + "20: \n\t" \ + ".machine pop" \ + : /* outputs */ [R_IN] "+a" (inptr) \ + , [R_OUT] "+a" (outptr), [R_I] "=&a" (index) \ + , [R_LI] "+a" (loop_count) \ + : /* inputs */ [R_BUF] "a" (buf) \ + , [R_TBL] "a" (to_ucs1) \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v0") ASM_CLOBBER_VR ("v16") \ + ASM_CLOBBER_VR ("v17") ASM_CLOBBER_VR ("v18") \ + ASM_CLOBBER_VR ("v19") ASM_CLOBBER_VR ("v20") \ + ASM_CLOBBER_VR ("v21") ASM_CLOBBER_VR ("v22") \ + ASM_CLOBBER_VR ("v23") ASM_CLOBBER_VR ("v24") \ + ); \ + /* Error occured? */ \ + if (loop_count != 0) \ + { \ + /* Found an invalid character! */ \ + STANDARD_FROM_LOOP_ERR_HANDLER (1); \ + } \ + } \ + } + +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> + +/* Next, define the other direction - from UCS4 to 8bit charset. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_TO +# define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +# define LOOPFCT TO_LOOP +# define BODY_TO_ORIG \ + { \ + uint32_t ch = get32 (inptr); \ + \ + if (__builtin_expect (ch >= sizeof (from_ucs4) / sizeof (from_ucs4[0]), 0)\ + || (__builtin_expect (from_ucs4[ch], '\1') == '\0' && ch != 0)) \ + { \ + UNICODE_TAG_HANDLER (ch, 4); \ + \ + /* This is an illegal character. */ \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } \ + \ + *outptr++ = from_ucs4[ch]; \ + inptr += 4; \ + } +# define BODY \ + { \ + if (__builtin_expect (inend - inptr < 64, 1) \ + || outend - outptr < 16) \ + /* Convert remaining bytes with c code. */ \ + BODY_TO_ORIG \ + else \ + { \ + /* Convert 64 ... 1024 bytes at once with tr-instruction. */ \ + size_t index, tmp; \ + char buf[256]; \ + size_t loop_count = (inend - inptr) / 64; \ + uint32_t max = sizeof (from_ucs4) / sizeof (from_ucs4[0]); \ + if (loop_count > (outend - outptr) / 16) \ + loop_count = (outend - outptr) / 16; \ + if (loop_count > 16) \ + loop_count = 16; \ + size_t remaining_loop_count = loop_count; \ + /* Step 1: Check for ch>=max, ch == 0 and shorten to bytes. \ + (ch == 0 is no error, but is handled differently) */ \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + /* Setup to check for ch >= max. */ \ + " vzero %%v21\n\t" \ + " vleih %%v21,-24576,0\n\t" /* element 0: > */ \ + " vleih %%v21,-8192,2\n\t" /* element 1: =<> */ \ + " vlvgf %%v20,%[R_MAX],0\n\t" /* element 0: val */ \ + /* Process in 64byte - 16 characters blocks. */ \ + " lghi %[R_I],0\n\t" \ + " lghi %[R_TMP],0\n\t" \ + "0: \n\t" \ + " vlm %%v16,%%v19,0(%[R_IN])\n\t" \ + /* Test for ch >= max and ch == 0. */ \ + " vstrczfs %%v22,%%v16,%%v20,%%v21\n\t" \ + " jno 10f\n\t" \ + " vstrczfs %%v22,%%v17,%%v20,%%v21\n\t" \ + " jno 11f\n\t" \ + " vstrczfs %%v22,%%v18,%%v20,%%v21\n\t" \ + " jno 12f\n\t" \ + " vstrczfs %%v22,%%v19,%%v20,%%v21\n\t" \ + " jno 13f\n\t" \ + /* Shorten to byte values. */ \ + " vpkf %%v16,%%v16,%%v17\n\t" \ + " vpkf %%v18,%%v18,%%v19\n\t" \ + " vpkh %%v16,%%v16,%%v18\n\t" \ + /* Store 16bytes to buf. */ \ + " vst %%v16,0(%[R_I],%[R_BUF])\n\t" \ + /* Loop until all blocks are processed. */ \ + " la %[R_IN],64(%[R_IN])\n\t" \ + " aghi %[R_I],16\n\t" \ + " brct %[R_LI],0b\n\t" \ + " j 20f\n\t" \ + /* Found error ch >= max or ch == 0. */ \ + "13: aghi %[R_TMP],4\n\t" \ + "12: aghi %[R_TMP],4\n\t" \ + "11: aghi %[R_TMP],4\n\t" \ + "10: vlgvb %[R_I],%%v22,7\n\t" \ + " srlg %[R_I],%[R_I],2\n\t" \ + " agr %[R_I],%[R_TMP]\n\t" \ + "20: \n\t" \ + ".machine pop" \ + : /* outputs */ [R_IN] "+a" (inptr) \ + , [R_I] "=&a" (index) \ + , [R_TMP] "=d" (tmp) \ + , [R_LI] "+d" (remaining_loop_count) \ + : /* inputs */ [R_BUF] "a" (buf) \ + , [R_MAX] "d" (max) \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ASM_CLOBBER_VR ("v22") \ + ); \ + /* Error occured in step 1? An error (ch >= max || ch == 0) \ + occured, if remaining_loop_count > 0. The error occured \ + at character-index (index) after already processed blocks. */ \ + loop_count -= remaining_loop_count; \ + if (loop_count > 0) \ + { \ + /* Step 2: Translate already processed blocks in buf and \ + check for errors (from_ucs4[ch] == 0). */ \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + " sllk %[R_I],%[R_LI],4\n\t" \ + " ahi %[R_I],-1\n\t" \ + /* Execute tr with correct len. */ \ + " exrl %[R_I],21f\n\t" \ + /* Post-processing. */ \ + " lghi %[R_I],0\n\t" \ + "0: \n\t" \ + /* Find invalid character - value == 0. */ \ + " vl %%v16,0(%[R_I],%[R_BUF])\n\t" \ + " vfenezbs %%v17,%%v16,%%v16\n\t" \ + " je 10f\n\t" \ + /* Store 16bytes to buf_out. */ \ + " vst %%v16,0(%[R_I],%[R_OUT])\n\t" \ + " aghi %[R_I],16\n\t" \ + " brct %[R_LI],0b\n\t" \ + " la %[R_OUT],0(%[R_I],%[R_OUT])\n\t" \ + " j 20f\n\t" \ + "21: tr 0(1,%[R_BUF]),0(%[R_TBL])\n\t" \ + /* Found an error: from_ucs4[ch] == 0. */ \ + "10: la %[R_OUT],0(%[R_I],%[R_OUT])\n\t" \ + " vlgvb %[R_I],%%v17,7\n\t" \ + "20: \n\t" \ + ".machine pop" \ + : /* outputs */ [R_OUT] "+a" (outptr) \ + , [R_I] "=&a" (tmp) \ + , [R_LI] "+d" (loop_count) \ + : /* inputs */ [R_BUF] "a" (buf) \ + , [R_TBL] "a" (from_ucs4) \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") \ + ASM_CLOBBER_VR ("v17") \ + ); \ + /* Error occured in processed bytes of step 2? \ + Thus possible error in step 1 is obselete.*/ \ + if (tmp < 16) \ + { \ + index = tmp; \ + inptr -= loop_count * 64; \ + } \ + } \ + /* Error occured in step 1/2? */ \ + if (index < 16) \ + { \ + /* Found an invalid character (see step 2) or zero \ + (see step 1) at index! Convert the chars before index \ + manually. If there is a zero at index detected by step 1, \ + there could be invalid characters before this zero. */ \ + int i; \ + uint32_t ch; \ + for (i = 0; i < index; i++) \ + { \ + ch = get32 (inptr); \ + if (__builtin_expect (from_ucs4[ch], '\1') == '\0') \ + break; \ + *outptr++ = from_ucs4[ch]; \ + inptr += 4; \ + } \ + if (i == index) \ + { \ + ch = get32 (inptr); \ + if (ch == 0) \ + { \ + /* This is no error, but handled differently. */ \ + *outptr++ = from_ucs4[ch]; \ + inptr += 4; \ + continue; \ + } \ + } \ + \ + UNICODE_TAG_HANDLER (ch, 4); \ + \ + /* This is an illegal character. */ \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } \ + } \ + } + +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> + + +/* Generate ifunc'ed loop function. */ +s390_libc_ifunc_expr (__from_generic_c, __from_generic, + (sizeof (from_ucs4) / sizeof (from_ucs4[0]) <= 256 + && hwcap & HWCAP_S390_VX) + ? __from_generic_vx + : __from_generic_c); + +s390_libc_ifunc_expr (__to_generic_c, __to_generic, + (sizeof (from_ucs4) / sizeof (from_ucs4[0]) <= 256 + && hwcap & HWCAP_S390_VX) + ? __to_generic_vx + : __to_generic_c); + +strong_alias (__to_generic_c_single, __to_generic_single) + +# undef FROM_LOOP +# undef TO_LOOP +# define FROM_LOOP __from_generic +# define TO_LOOP __to_generic +# include <iconv/skeleton.c> + +#else +/* Generate this module without ifunc if build environment lacks vector + support. Instead the common 8bit-generic.c is used. */ +# include "iconvdata/8bit-generic.c" +#endif /* !defined HAVE_S390_VX_ASM_SUPPORT */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/Makefile b/REORG.TODO/sysdeps/s390/multiarch/Makefile new file mode 100644 index 0000000000..c893ebc565 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/Makefile @@ -0,0 +1,59 @@ +ifeq ($(subdir),string) +sysdep_routines += strlen strlen-vx strlen-c \ + strnlen strnlen-vx strnlen-c \ + strcpy strcpy-vx \ + stpcpy stpcpy-vx stpcpy-c \ + strncpy strncpy-vx \ + stpncpy stpncpy-vx stpncpy-c \ + strcat strcat-vx strcat-c \ + strncat strncat-vx strncat-c \ + strcmp strcmp-vx \ + strncmp strncmp-vx strncmp-c \ + strchr strchr-vx strchr-c \ + strchrnul strchrnul-vx strchrnul-c \ + strrchr strrchr-vx strrchr-c \ + strspn strspn-vx strspn-c \ + strpbrk strpbrk-vx strpbrk-c \ + strcspn strcspn-vx strcspn-c \ + memchr memchr-vx \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c \ + mempcpy +endif + +ifeq ($(subdir),wcsmbs) +sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsnlen wcsnlen-vx wcsnlen-c \ + wcscpy wcscpy-vx wcscpy-c \ + wcpcpy wcpcpy-vx wcpcpy-c \ + wcsncpy wcsncpy-vx wcsncpy-c \ + wcpncpy wcpncpy-vx wcpncpy-c \ + wcscat wcscat-vx wcscat-c \ + wcsncat wcsncat-vx wcsncat-c \ + wcscmp wcscmp-vx wcscmp-c \ + wcsncmp wcsncmp-vx wcsncmp-c \ + wcschr wcschr-vx wcschr-c \ + wcschrnul wcschrnul-vx wcschrnul-c \ + wcsrchr wcsrchr-vx wcsrchr-c \ + wcsspn wcsspn-vx wcsspn-c \ + wcspbrk wcspbrk-vx wcspbrk-c \ + wcscspn wcscspn-vx wcscspn-c \ + wmemchr wmemchr-vx wmemchr-c \ + wmemset wmemset-vx wmemset-c \ + wmemcmp wmemcmp-vx wmemcmp-c +endif + +ifeq ($(subdir),iconvdata) +override define generate-8bit-table +$(make-target-directory) +LC_ALL=C $(SHELL) ./gen-8bit.sh $< > $(@:stmp=T) +LC_ALL=C $(SHELL) ../sysdeps/s390/multiarch/gen-8bit.sh $< >> $(@:stmp=T) +$(move-if-change) $(@:stmp=T) $(@:stmp=h) +touch $@ +endef +endif + +ifeq ($(subdir),iconv) +sysdep_routines += gconv_simple +endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/gconv_simple.c b/REORG.TODO/sysdeps/s390/multiarch/gconv_simple.c new file mode 100644 index 0000000000..75632873e3 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/gconv_simple.c @@ -0,0 +1,1266 @@ +/* Simple transformations functions - s390 version. + Copyright (C) 2016-2017 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 HAVE_S390_VX_ASM_SUPPORT +# include <ifunc-resolve.h> + +# if defined HAVE_S390_VX_GCC_SUPPORT +# define ASM_CLOBBER_VR(NR) , NR +# else +# define ASM_CLOBBER_VR(NR) +# endif + +# define ICONV_C_NAME(NAME) __##NAME##_c +# define ICONV_VX_NAME(NAME) __##NAME##_vx +# define ICONV_VX_IFUNC(FUNC) \ + extern __typeof (ICONV_C_NAME (FUNC)) __##FUNC; \ + s390_vx_libc_ifunc (__##FUNC) \ + int FUNC (struct __gconv_step *step, struct __gconv_step_data *data, \ + const unsigned char **inptrp, const unsigned char *inend, \ + unsigned char **outbufstart, size_t *irreversible, \ + int do_flush, int consume_incomplete) \ + { \ + return __##FUNC (step, data, inptrp, inend,outbufstart, \ + irreversible, do_flush, consume_incomplete); \ + } +# define ICONV_VX_SINGLE(NAME) \ + static __typeof (NAME##_single) __##NAME##_vx_single __attribute__((alias(#NAME "_single"))); + +/* Generate the transformations which are used, if the target machine does not + support vector instructions. */ +# define __gconv_transform_ascii_internal \ + ICONV_C_NAME (__gconv_transform_ascii_internal) +# define __gconv_transform_internal_ascii \ + ICONV_C_NAME (__gconv_transform_internal_ascii) +# define __gconv_transform_internal_ucs4le \ + ICONV_C_NAME (__gconv_transform_internal_ucs4le) +# define __gconv_transform_ucs4_internal \ + ICONV_C_NAME (__gconv_transform_ucs4_internal) +# define __gconv_transform_ucs4le_internal \ + ICONV_C_NAME (__gconv_transform_ucs4le_internal) +# define __gconv_transform_ucs2_internal \ + ICONV_C_NAME (__gconv_transform_ucs2_internal) +# define __gconv_transform_ucs2reverse_internal \ + ICONV_C_NAME (__gconv_transform_ucs2reverse_internal) +# define __gconv_transform_internal_ucs2 \ + ICONV_C_NAME (__gconv_transform_internal_ucs2) +# define __gconv_transform_internal_ucs2reverse \ + ICONV_C_NAME (__gconv_transform_internal_ucs2reverse) + + +# include <iconv/gconv_simple.c> + +# undef __gconv_transform_ascii_internal +# undef __gconv_transform_internal_ascii +# undef __gconv_transform_internal_ucs4le +# undef __gconv_transform_ucs4_internal +# undef __gconv_transform_ucs4le_internal +# undef __gconv_transform_ucs2_internal +# undef __gconv_transform_ucs2reverse_internal +# undef __gconv_transform_internal_ucs2 +# undef __gconv_transform_internal_ucs2reverse + +/* Now define the functions with vector support. */ +# if defined __s390x__ +# define CONVERT_32BIT_SIZE_T(REG) +# else +# define CONVERT_32BIT_SIZE_T(REG) "llgfr %" #REG ",%" #REG "\n\t" +# endif + +/* Convert from ISO 646-IRV to the internal (UCS4-like) format. */ +# define DEFINE_INIT 0 +# define DEFINE_FINI 0 +# define MIN_NEEDED_FROM 1 +# define MIN_NEEDED_TO 4 +# define FROM_DIRECTION 1 +# define FROM_LOOP ICONV_VX_NAME (ascii_internal_loop) +# define TO_LOOP ICONV_VX_NAME (ascii_internal_loop) /* This is not used. */ +# define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_ascii_internal) +# define ONE_DIRECTION 1 + +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define LOOPFCT FROM_LOOP +# define BODY_ORIG_ERROR \ + /* The value is too large. We don't try transliteration here since \ + this is not an error because of the lack of possibilities to \ + represent the result. This is a genuine bug in the input since \ + ASCII does not allow such values. */ \ + STANDARD_FROM_LOOP_ERR_HANDLER (1); + +# define BODY_ORIG \ + { \ + if (__glibc_unlikely (*inptr > '\x7f')) \ + { \ + BODY_ORIG_ERROR \ + } \ + else \ + { \ + /* It's an one byte sequence. */ \ + *((uint32_t *) outptr) = *inptr++; \ + outptr += sizeof (uint32_t); \ + } \ + } +# define BODY \ + { \ + size_t len = inend - inptr; \ + if (len > (outend - outptr) / 4) \ + len = (outend - outptr) / 4; \ + size_t loop_count, tmp; \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + CONVERT_32BIT_SIZE_T ([R_LEN]) \ + " vrepib %%v30,0x7f\n\t" /* For compare > 0x7f. */ \ + " srlg %[R_LI],%[R_LEN],4\n\t" \ + " vrepib %%v31,0x20\n\t" \ + " clgije %[R_LI],0,1f\n\t" \ + "0: \n\t" /* Handle 16-byte blocks. */ \ + " vl %%v16,0(%[R_IN])\n\t" \ + /* Checking for values > 0x7f. */ \ + " vstrcbs %%v17,%%v16,%%v30,%%v31\n\t" \ + " jno 10f\n\t" \ + /* Enlarge to UCS4. */ \ + " vuplhb %%v17,%%v16\n\t" \ + " vupllb %%v18,%%v16\n\t" \ + " vuplhh %%v19,%%v17\n\t" \ + " vupllh %%v20,%%v17\n\t" \ + " vuplhh %%v21,%%v18\n\t" \ + " vupllh %%v22,%%v18\n\t" \ + /* Store 64bytes to buf_out. */ \ + " vstm %%v19,%%v22,0(%[R_OUT])\n\t" \ + " la %[R_IN],16(%[R_IN])\n\t" \ + " la %[R_OUT],64(%[R_OUT])\n\t" \ + " brctg %[R_LI],0b\n\t" \ + " lghi %[R_LI],15\n\t" \ + " ngr %[R_LEN],%[R_LI]\n\t" \ + " je 20f\n\t" /* Jump away if no remaining bytes. */ \ + /* Handle remaining bytes. */ \ + "1: aghik %[R_LI],%[R_LEN],-1\n\t" \ + " jl 20f\n\t" /* Jump away if no remaining bytes. */ \ + " vll %%v16,%[R_LI],0(%[R_IN])\n\t" \ + /* Checking for values > 0x7f. */ \ + " vstrcbs %%v17,%%v16,%%v30,%%v31\n\t" \ + " vlgvb %[R_TMP],%%v17,7\n\t" \ + " clr %[R_TMP],%[R_LI]\n\t" \ + " locrh %[R_TMP],%[R_LEN]\n\t" \ + " locghih %[R_LEN],0\n\t" \ + " j 12f\n\t" \ + "10:\n\t" \ + /* Found a value > 0x7f. \ + Store the preceding chars. */ \ + " vlgvb %[R_TMP],%%v17,7\n\t" \ + "12: la %[R_IN],0(%[R_TMP],%[R_IN])\n\t" \ + " sllk %[R_TMP],%[R_TMP],2\n\t" \ + " ahi %[R_TMP],-1\n\t" \ + " jl 20f\n\t" \ + " lgr %[R_LI],%[R_TMP]\n\t" \ + " vuplhb %%v17,%%v16\n\t" \ + " vuplhh %%v19,%%v17\n\t" \ + " vstl %%v19,%[R_LI],0(%[R_OUT])\n\t" \ + " ahi %[R_LI],-16\n\t" \ + " jl 11f\n\t" \ + " vupllh %%v20,%%v17\n\t" \ + " vstl %%v20,%[R_LI],16(%[R_OUT])\n\t" \ + " ahi %[R_LI],-16\n\t" \ + " jl 11f\n\t" \ + " vupllb %%v18,%%v16\n\t" \ + " vuplhh %%v21,%%v18\n\t" \ + " vstl %%v21,%[R_LI],32(%[R_OUT])\n\t" \ + " ahi %[R_LI],-16\n\t" \ + " jl 11f\n\t" \ + " vupllh %%v22,%%v18\n\t" \ + " vstl %%v22,%[R_LI],48(%[R_OUT])\n\t" \ + "11:\n\t" \ + " la %[R_OUT],1(%[R_TMP],%[R_OUT])\n\t" \ + "20:\n\t" \ + ".machine pop" \ + : /* outputs */ [R_OUT] "+a" (outptr) \ + , [R_IN] "+a" (inptr) \ + , [R_LEN] "+d" (len) \ + , [R_LI] "=d" (loop_count) \ + , [R_TMP] "=a" (tmp) \ + : /* inputs */ \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ASM_CLOBBER_VR ("v22") ASM_CLOBBER_VR ("v30") \ + ASM_CLOBBER_VR ("v31") \ + ); \ + if (len > 0) \ + { \ + /* Found an invalid character at the next input byte. */ \ + BODY_ORIG_ERROR \ + } \ + } + +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +# include <iconv/skeleton.c> +# undef BODY_ORIG +# undef BODY_ORIG_ERROR +ICONV_VX_IFUNC (__gconv_transform_ascii_internal) + +/* Convert from the internal (UCS4-like) format to ISO 646-IRV. */ +# define DEFINE_INIT 0 +# define DEFINE_FINI 0 +# define MIN_NEEDED_FROM 4 +# define MIN_NEEDED_TO 1 +# define FROM_DIRECTION 1 +# define FROM_LOOP ICONV_VX_NAME (internal_ascii_loop) +# define TO_LOOP ICONV_VX_NAME (internal_ascii_loop) /* This is not used. */ +# define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_internal_ascii) +# define ONE_DIRECTION 1 + +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define LOOPFCT FROM_LOOP +# define BODY_ORIG_ERROR \ + UNICODE_TAG_HANDLER (*((const uint32_t *) inptr), 4); \ + STANDARD_TO_LOOP_ERR_HANDLER (4); + +# define BODY_ORIG \ + { \ + if (__glibc_unlikely (*((const uint32_t *) inptr) > 0x7f)) \ + { \ + BODY_ORIG_ERROR \ + } \ + else \ + { \ + /* It's an one byte sequence. */ \ + *outptr++ = *((const uint32_t *) inptr); \ + inptr += sizeof (uint32_t); \ + } \ + } +# define BODY \ + { \ + size_t len = (inend - inptr) / 4; \ + if (len > outend - outptr) \ + len = outend - outptr; \ + size_t loop_count, tmp, tmp2; \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + CONVERT_32BIT_SIZE_T ([R_LEN]) \ + /* Setup to check for ch > 0x7f. */ \ + " vzero %%v21\n\t" \ + " srlg %[R_LI],%[R_LEN],4\n\t" \ + " vleih %%v21,8192,0\n\t" /* element 0: > */ \ + " vleih %%v21,-8192,2\n\t" /* element 1: =<> */ \ + " vleif %%v20,127,0\n\t" /* element 0: 127 */ \ + " lghi %[R_TMP],0\n\t" \ + " clgije %[R_LI],0,1f\n\t" \ + "0:\n\t" \ + " vlm %%v16,%%v19,0(%[R_IN])\n\t" \ + /* Shorten to byte values. */ \ + " vpkf %%v23,%%v16,%%v17\n\t" \ + " vpkf %%v24,%%v18,%%v19\n\t" \ + " vpkh %%v23,%%v23,%%v24\n\t" \ + /* Checking for values > 0x7f. */ \ + " vstrcfs %%v22,%%v16,%%v20,%%v21\n\t" \ + " jno 10f\n\t" \ + " vstrcfs %%v22,%%v17,%%v20,%%v21\n\t" \ + " jno 11f\n\t" \ + " vstrcfs %%v22,%%v18,%%v20,%%v21\n\t" \ + " jno 12f\n\t" \ + " vstrcfs %%v22,%%v19,%%v20,%%v21\n\t" \ + " jno 13f\n\t" \ + /* Store 16bytes to outptr. */ \ + " vst %%v23,0(%[R_OUT])\n\t" \ + " la %[R_IN],64(%[R_IN])\n\t" \ + " la %[R_OUT],16(%[R_OUT])\n\t" \ + " brctg %[R_LI],0b\n\t" \ + " lghi %[R_LI],15\n\t" \ + " ngr %[R_LEN],%[R_LI]\n\t" \ + " je 20f\n\t" /* Jump away if no remaining bytes. */ \ + /* Handle remaining bytes. */ \ + "1: sllg %[R_LI],%[R_LEN],2\n\t" \ + " aghi %[R_LI],-1\n\t" \ + " jl 20f\n\t" /* Jump away if no remaining bytes. */ \ + /* Load remaining 1...63 bytes. */ \ + " vll %%v16,%[R_LI],0(%[R_IN])\n\t" \ + " ahi %[R_LI],-16\n\t" \ + " jl 2f\n\t" \ + " vll %%v17,%[R_LI],16(%[R_IN])\n\t" \ + " ahi %[R_LI],-16\n\t" \ + " jl 2f\n\t" \ + " vll %%v18,%[R_LI],32(%[R_IN])\n\t" \ + " ahi %[R_LI],-16\n\t" \ + " jl 2f\n\t" \ + " vll %%v19,%[R_LI],48(%[R_IN])\n\t" \ + "2:\n\t" \ + /* Shorten to byte values. */ \ + " vpkf %%v23,%%v16,%%v17\n\t" \ + " vpkf %%v24,%%v18,%%v19\n\t" \ + " vpkh %%v23,%%v23,%%v24\n\t" \ + " sllg %[R_LI],%[R_LEN],2\n\t" \ + " aghi %[R_LI],-16\n\t" \ + " jl 3f\n\t" /* v16 is not fully loaded. */ \ + " vstrcfs %%v22,%%v16,%%v20,%%v21\n\t" \ + " jno 10f\n\t" \ + " aghi %[R_LI],-16\n\t" \ + " jl 4f\n\t" /* v17 is not fully loaded. */ \ + " vstrcfs %%v22,%%v17,%%v20,%%v21\n\t" \ + " jno 11f\n\t" \ + " aghi %[R_LI],-16\n\t" \ + " jl 5f\n\t" /* v18 is not fully loaded. */ \ + " vstrcfs %%v22,%%v18,%%v20,%%v21\n\t" \ + " jno 12f\n\t" \ + " aghi %[R_LI],-16\n\t" \ + /* v19 is not fully loaded. */ \ + " lghi %[R_TMP],12\n\t" \ + " vstrcfs %%v22,%%v19,%%v20,%%v21\n\t" \ + "6: vlgvb %[R_I],%%v22,7\n\t" \ + " aghi %[R_LI],16\n\t" \ + " clrjl %[R_I],%[R_LI],14f\n\t" \ + " lgr %[R_I],%[R_LEN]\n\t" \ + " lghi %[R_LEN],0\n\t" \ + " j 15f\n\t" \ + "3: vstrcfs %%v22,%%v16,%%v20,%%v21\n\t" \ + " j 6b\n\t" \ + "4: vstrcfs %%v22,%%v17,%%v20,%%v21\n\t" \ + " lghi %[R_TMP],4\n\t" \ + " j 6b\n\t" \ + "5: vstrcfs %%v22,%%v17,%%v20,%%v21\n\t" \ + " lghi %[R_TMP],8\n\t" \ + " j 6b\n\t" \ + /* Found a value > 0x7f. */ \ + "13: ahi %[R_TMP],4\n\t" \ + "12: ahi %[R_TMP],4\n\t" \ + "11: ahi %[R_TMP],4\n\t" \ + "10: vlgvb %[R_I],%%v22,7\n\t" \ + "14: srlg %[R_I],%[R_I],2\n\t" \ + " agr %[R_I],%[R_TMP]\n\t" \ + " je 20f\n\t" \ + /* Store characters before invalid one... */ \ + "15: aghi %[R_I],-1\n\t" \ + " vstl %%v23,%[R_I],0(%[R_OUT])\n\t" \ + /* ... and update pointers. */ \ + " la %[R_OUT],1(%[R_I],%[R_OUT])\n\t" \ + " sllg %[R_I],%[R_I],2\n\t" \ + " la %[R_IN],4(%[R_I],%[R_IN])\n\t" \ + "20:\n\t" \ + ".machine pop" \ + : /* outputs */ [R_OUT] "+a" (outptr) \ + , [R_IN] "+a" (inptr) \ + , [R_LEN] "+d" (len) \ + , [R_LI] "=d" (loop_count) \ + , [R_I] "=a" (tmp2) \ + , [R_TMP] "=d" (tmp) \ + : /* inputs */ \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ASM_CLOBBER_VR ("v22") ASM_CLOBBER_VR ("v23") \ + ASM_CLOBBER_VR ("v24") \ + ); \ + if (len > 0) \ + { \ + /* Found an invalid character > 0x7f at next character. */ \ + BODY_ORIG_ERROR \ + } \ + } +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +# include <iconv/skeleton.c> +# undef BODY_ORIG +# undef BODY_ORIG_ERROR +ICONV_VX_IFUNC (__gconv_transform_internal_ascii) + + +/* Convert from internal UCS4 to UCS4 little endian form. */ +# define DEFINE_INIT 0 +# define DEFINE_FINI 0 +# define MIN_NEEDED_FROM 4 +# define MIN_NEEDED_TO 4 +# define FROM_DIRECTION 1 +# define FROM_LOOP ICONV_VX_NAME (internal_ucs4le_loop) +# define TO_LOOP ICONV_VX_NAME (internal_ucs4le_loop) /* This is not used. */ +# define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_internal_ucs4le) +# define ONE_DIRECTION 0 + +static inline int +__attribute ((always_inline)) +ICONV_VX_NAME (internal_ucs4le_loop) (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, + unsigned char **outptrp, + unsigned char *outend, + size_t *irreversible) +{ + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; + int result; + size_t len = MIN (inend - inptr, outend - outptr) / 4; + size_t loop_count; + __asm__ volatile (".machine push\n\t" + ".machine \"z13\"\n\t" + ".machinemode \"zarch_nohighgprs\"\n\t" + CONVERT_32BIT_SIZE_T ([R_LEN]) + " bras %[R_LI],1f\n\t" + /* Vector permute mask: */ + " .long 0x03020100,0x7060504,0x0B0A0908,0x0F0E0D0C\n\t" + "1: vl %%v20,0(%[R_LI])\n\t" + /* Process 64byte (16char) blocks. */ + " srlg %[R_LI],%[R_LEN],4\n\t" + " clgije %[R_LI],0,10f\n\t" + "0: vlm %%v16,%%v19,0(%[R_IN])\n\t" + " vperm %%v16,%%v16,%%v16,%%v20\n\t" + " vperm %%v17,%%v17,%%v17,%%v20\n\t" + " vperm %%v18,%%v18,%%v18,%%v20\n\t" + " vperm %%v19,%%v19,%%v19,%%v20\n\t" + " vstm %%v16,%%v19,0(%[R_OUT])\n\t" + " la %[R_IN],64(%[R_IN])\n\t" + " la %[R_OUT],64(%[R_OUT])\n\t" + " brctg %[R_LI],0b\n\t" + " llgfr %[R_LEN],%[R_LEN]\n\t" + " nilf %[R_LEN],15\n\t" + /* Process 16byte (4char) blocks. */ + "10: srlg %[R_LI],%[R_LEN],2\n\t" + " clgije %[R_LI],0,20f\n\t" + "11: vl %%v16,0(%[R_IN])\n\t" + " vperm %%v16,%%v16,%%v16,%%v20\n\t" + " vst %%v16,0(%[R_OUT])\n\t" + " la %[R_IN],16(%[R_IN])\n\t" + " la %[R_OUT],16(%[R_OUT])\n\t" + " brctg %[R_LI],11b\n\t" + " nill %[R_LEN],3\n\t" + /* Process <16bytes. */ + "20: sll %[R_LEN],2\n\t" + " ahi %[R_LEN],-1\n\t" + " jl 30f\n\t" + " vll %%v16,%[R_LEN],0(%[R_IN])\n\t" + " vperm %%v16,%%v16,%%v16,%%v20\n\t" + " vstl %%v16,%[R_LEN],0(%[R_OUT])\n\t" + " la %[R_IN],1(%[R_LEN],%[R_IN])\n\t" + " la %[R_OUT],1(%[R_LEN],%[R_OUT])\n\t" + "30: \n\t" + ".machine pop" + : /* outputs */ [R_OUT] "+a" (outptr) + , [R_IN] "+a" (inptr) + , [R_LI] "=a" (loop_count) + , [R_LEN] "+a" (len) + : /* inputs */ + : /* clobber list*/ "memory", "cc" + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") + ASM_CLOBBER_VR ("v20") + ); + *inptrp = inptr; + *outptrp = outptr; + + /* Determine the status. */ + if (*inptrp == inend) + result = __GCONV_EMPTY_INPUT; + else if (*outptrp + 4 > outend) + result = __GCONV_FULL_OUTPUT; + else + result = __GCONV_INCOMPLETE_INPUT; + + return result; +} + +ICONV_VX_SINGLE (internal_ucs4le_loop) +# include <iconv/skeleton.c> +ICONV_VX_IFUNC (__gconv_transform_internal_ucs4le) + + +/* Transform from UCS4 to the internal, UCS4-like format. Unlike + for the other direction we have to check for correct values here. */ +# define DEFINE_INIT 0 +# define DEFINE_FINI 0 +# define MIN_NEEDED_FROM 4 +# define MIN_NEEDED_TO 4 +# define FROM_DIRECTION 1 +# define FROM_LOOP ICONV_VX_NAME (ucs4_internal_loop) +# define TO_LOOP ICONV_VX_NAME (ucs4_internal_loop) /* This is not used. */ +# define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_ucs4_internal) +# define ONE_DIRECTION 0 + + +static inline int +__attribute ((always_inline)) +ICONV_VX_NAME (ucs4_internal_loop) (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, + unsigned char **outptrp, + unsigned char *outend, + size_t *irreversible) +{ + int flags = step_data->__flags; + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; + int result; + size_t len, loop_count; + do + { + len = MIN (inend - inptr, outend - outptr) / 4; + __asm__ volatile (".machine push\n\t" + ".machine \"z13\"\n\t" + ".machinemode \"zarch_nohighgprs\"\n\t" + CONVERT_32BIT_SIZE_T ([R_LEN]) + /* Setup to check for ch > 0x7fffffff. */ + " larl %[R_LI],9f\n\t" + " vlm %%v20,%%v21,0(%[R_LI])\n\t" + " srlg %[R_LI],%[R_LEN],2\n\t" + " clgije %[R_LI],0,1f\n\t" + /* Process 16byte (4char) blocks. */ + "0: vl %%v16,0(%[R_IN])\n\t" + " vstrcfs %%v22,%%v16,%%v20,%%v21\n\t" + " jno 10f\n\t" + " vst %%v16,0(%[R_OUT])\n\t" + " la %[R_IN],16(%[R_IN])\n\t" + " la %[R_OUT],16(%[R_OUT])\n\t" + " brctg %[R_LI],0b\n\t" + " llgfr %[R_LEN],%[R_LEN]\n\t" + " nilf %[R_LEN],3\n\t" + /* Process <16bytes. */ + "1: sll %[R_LEN],2\n\t" + " ahik %[R_LI],%[R_LEN],-1\n\t" + " jl 20f\n\t" /* No further bytes available. */ + " vll %%v16,%[R_LI],0(%[R_IN])\n\t" + " vstrcfs %%v22,%%v16,%%v20,%%v21\n\t" + " vlgvb %[R_LI],%%v22,7\n\t" + " clr %[R_LI],%[R_LEN]\n\t" + " locgrhe %[R_LI],%[R_LEN]\n\t" + " locghihe %[R_LEN],0\n\t" + " j 11f\n\t" + /* v20: Vector string range compare values. */ + "9: .long 0x7fffffff,0x0,0x0,0x0\n\t" + /* v21: Vector string range compare control-bits. + element 0: >; element 1: =<> (always true) */ + " .long 0x20000000,0xE0000000,0x0,0x0\n\t" + /* Found a value > 0x7fffffff. */ + "10: vlgvb %[R_LI],%%v22,7\n\t" + /* Store characters before invalid one. */ + "11: aghi %[R_LI],-1\n\t" + " jl 20f\n\t" + " vstl %%v16,%[R_LI],0(%[R_OUT])\n\t" + " la %[R_IN],1(%[R_LI],%[R_IN])\n\t" + " la %[R_OUT],1(%[R_LI],%[R_OUT])\n\t" + "20:\n\t" + ".machine pop" + : /* outputs */ [R_OUT] "+a" (outptr) + , [R_IN] "+a" (inptr) + , [R_LI] "=a" (loop_count) + , [R_LEN] "+d" (len) + : /* inputs */ + : /* clobber list*/ "memory", "cc" + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v20") + ASM_CLOBBER_VR ("v21") ASM_CLOBBER_VR ("v22") + ); + if (len > 0) + { + /* The value is too large. We don't try transliteration here since + this is not an error because of the lack of possibilities to + represent the result. This is a genuine bug in the input since + UCS4 does not allow such values. */ + if (irreversible == NULL) + /* We are transliterating, don't try to correct anything. */ + return __GCONV_ILLEGAL_INPUT; + + if (flags & __GCONV_IGNORE_ERRORS) + { + /* Just ignore this character. */ + ++*irreversible; + inptr += 4; + continue; + } + + *inptrp = inptr; + *outptrp = outptr; + return __GCONV_ILLEGAL_INPUT; + } + } + while (len > 0); + + *inptrp = inptr; + *outptrp = outptr; + + /* Determine the status. */ + if (*inptrp == inend) + result = __GCONV_EMPTY_INPUT; + else if (*outptrp + 4 > outend) + result = __GCONV_FULL_OUTPUT; + else + result = __GCONV_INCOMPLETE_INPUT; + + return result; +} + +ICONV_VX_SINGLE (ucs4_internal_loop) +# include <iconv/skeleton.c> +ICONV_VX_IFUNC (__gconv_transform_ucs4_internal) + + +/* Transform from UCS4-LE to the internal encoding. */ +# define DEFINE_INIT 0 +# define DEFINE_FINI 0 +# define MIN_NEEDED_FROM 4 +# define MIN_NEEDED_TO 4 +# define FROM_DIRECTION 1 +# define FROM_LOOP ICONV_VX_NAME (ucs4le_internal_loop) +# define TO_LOOP ICONV_VX_NAME (ucs4le_internal_loop) /* This is not used. */ +# define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_ucs4le_internal) +# define ONE_DIRECTION 0 + +static inline int +__attribute ((always_inline)) +ICONV_VX_NAME (ucs4le_internal_loop) (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, + unsigned char **outptrp, + unsigned char *outend, + size_t *irreversible) +{ + int flags = step_data->__flags; + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; + int result; + size_t len, loop_count; + do + { + len = MIN (inend - inptr, outend - outptr) / 4; + __asm__ volatile (".machine push\n\t" + ".machine \"z13\"\n\t" + ".machinemode \"zarch_nohighgprs\"\n\t" + CONVERT_32BIT_SIZE_T ([R_LEN]) + /* Setup to check for ch > 0x7fffffff. */ + " larl %[R_LI],9f\n\t" + " vlm %%v20,%%v22,0(%[R_LI])\n\t" + " srlg %[R_LI],%[R_LEN],2\n\t" + " clgije %[R_LI],0,1f\n\t" + /* Process 16byte (4char) blocks. */ + "0: vl %%v16,0(%[R_IN])\n\t" + " vperm %%v16,%%v16,%%v16,%%v22\n\t" + " vstrcfs %%v23,%%v16,%%v20,%%v21\n\t" + " jno 10f\n\t" + " vst %%v16,0(%[R_OUT])\n\t" + " la %[R_IN],16(%[R_IN])\n\t" + " la %[R_OUT],16(%[R_OUT])\n\t" + " brctg %[R_LI],0b\n\t" + " llgfr %[R_LEN],%[R_LEN]\n\t" + " nilf %[R_LEN],3\n\t" + /* Process <16bytes. */ + "1: sll %[R_LEN],2\n\t" + " ahik %[R_LI],%[R_LEN],-1\n\t" + " jl 20f\n\t" /* No further bytes available. */ + " vll %%v16,%[R_LI],0(%[R_IN])\n\t" + " vperm %%v16,%%v16,%%v16,%%v22\n\t" + " vstrcfs %%v23,%%v16,%%v20,%%v21\n\t" + " vlgvb %[R_LI],%%v23,7\n\t" + " clr %[R_LI],%[R_LEN]\n\t" + " locgrhe %[R_LI],%[R_LEN]\n\t" + " locghihe %[R_LEN],0\n\t" + " j 11f\n\t" + /* v20: Vector string range compare values. */ + "9: .long 0x7fffffff,0x0,0x0,0x0\n\t" + /* v21: Vector string range compare control-bits. + element 0: >; element 1: =<> (always true) */ + " .long 0x20000000,0xE0000000,0x0,0x0\n\t" + /* v22: Vector permute mask. */ + " .long 0x03020100,0x7060504,0x0B0A0908,0x0F0E0D0C\n\t" + /* Found a value > 0x7fffffff. */ + "10: vlgvb %[R_LI],%%v23,7\n\t" + /* Store characters before invalid one. */ + "11: aghi %[R_LI],-1\n\t" + " jl 20f\n\t" + " vstl %%v16,%[R_LI],0(%[R_OUT])\n\t" + " la %[R_IN],1(%[R_LI],%[R_IN])\n\t" + " la %[R_OUT],1(%[R_LI],%[R_OUT])\n\t" + "20:\n\t" + ".machine pop" + : /* outputs */ [R_OUT] "+a" (outptr) + , [R_IN] "+a" (inptr) + , [R_LI] "=a" (loop_count) + , [R_LEN] "+d" (len) + : /* inputs */ + : /* clobber list*/ "memory", "cc" + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v20") + ASM_CLOBBER_VR ("v21") ASM_CLOBBER_VR ("v22") + ASM_CLOBBER_VR ("v23") + ); + if (len > 0) + { + /* The value is too large. We don't try transliteration here since + this is not an error because of the lack of possibilities to + represent the result. This is a genuine bug in the input since + UCS4 does not allow such values. */ + if (irreversible == NULL) + /* We are transliterating, don't try to correct anything. */ + return __GCONV_ILLEGAL_INPUT; + + if (flags & __GCONV_IGNORE_ERRORS) + { + /* Just ignore this character. */ + ++*irreversible; + inptr += 4; + continue; + } + + *inptrp = inptr; + *outptrp = outptr; + return __GCONV_ILLEGAL_INPUT; + } + } + while (len > 0); + + *inptrp = inptr; + *outptrp = outptr; + + /* Determine the status. */ + if (*inptrp == inend) + result = __GCONV_EMPTY_INPUT; + else if (*inptrp + 4 > inend) + result = __GCONV_INCOMPLETE_INPUT; + else + { + assert (*outptrp + 4 > outend); + result = __GCONV_FULL_OUTPUT; + } + + return result; +} +ICONV_VX_SINGLE (ucs4le_internal_loop) +# include <iconv/skeleton.c> +ICONV_VX_IFUNC (__gconv_transform_ucs4le_internal) + +/* Convert from UCS2 to the internal (UCS4-like) format. */ +# define DEFINE_INIT 0 +# define DEFINE_FINI 0 +# define MIN_NEEDED_FROM 2 +# define MIN_NEEDED_TO 4 +# define FROM_DIRECTION 1 +# define FROM_LOOP ICONV_VX_NAME (ucs2_internal_loop) +# define TO_LOOP ICONV_VX_NAME (ucs2_internal_loop) /* This is not used. */ +# define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_ucs2_internal) +# define ONE_DIRECTION 1 + +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define LOOPFCT FROM_LOOP +# define BODY_ORIG_ERROR \ + /* Surrogate characters in UCS-2 input are not valid. Reject \ + them. (Catching this here is not security relevant.) */ \ + STANDARD_FROM_LOOP_ERR_HANDLER (2); +# define BODY_ORIG \ + { \ + uint16_t u1 = get16 (inptr); \ + \ + if (__glibc_unlikely (u1 >= 0xd800 && u1 < 0xe000)) \ + { \ + BODY_ORIG_ERROR \ + } \ + \ + *((uint32_t *) outptr) = u1; \ + outptr += sizeof (uint32_t); \ + inptr += 2; \ + } +# define BODY \ + { \ + size_t len, tmp, tmp2; \ + len = MIN ((inend - inptr) / 2, (outend - outptr) / 4); \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + CONVERT_32BIT_SIZE_T ([R_LEN]) \ + /* Setup to check for ch >= 0xd800 && ch < 0xe000. */ \ + " larl %[R_TMP],9f\n\t" \ + " vlm %%v20,%%v21,0(%[R_TMP])\n\t" \ + " srlg %[R_TMP],%[R_LEN],3\n\t" \ + " clgije %[R_TMP],0,1f\n\t" \ + /* Process 16byte (8char) blocks. */ \ + "0: vl %%v16,0(%[R_IN])\n\t" \ + " vstrchs %%v19,%%v16,%%v20,%%v21\n\t" \ + /* Enlarge UCS2 to UCS4. */ \ + " vuplhh %%v17,%%v16\n\t" \ + " vupllh %%v18,%%v16\n\t" \ + " jno 10f\n\t" \ + /* Store 32bytes to buf_out. */ \ + " vstm %%v17,%%v18,0(%[R_OUT])\n\t" \ + " la %[R_IN],16(%[R_IN])\n\t" \ + " la %[R_OUT],32(%[R_OUT])\n\t" \ + " brctg %[R_TMP],0b\n\t" \ + " llgfr %[R_LEN],%[R_LEN]\n\t" \ + " nilf %[R_LEN],7\n\t" \ + /* Process <16bytes. */ \ + "1: sll %[R_LEN],1\n\t" \ + " ahik %[R_TMP],%[R_LEN],-1\n\t" \ + " jl 20f\n\t" /* No further bytes available. */ \ + " vll %%v16,%[R_TMP],0(%[R_IN])\n\t" \ + " vstrchs %%v19,%%v16,%%v20,%%v21\n\t" \ + /* Enlarge UCS2 to UCS4. */ \ + " vuplhh %%v17,%%v16\n\t" \ + " vupllh %%v18,%%v16\n\t" \ + " vlgvb %[R_TMP],%%v19,7\n\t" \ + " clr %[R_TMP],%[R_LEN]\n\t" \ + " locgrhe %[R_TMP],%[R_LEN]\n\t" \ + " locghihe %[R_LEN],0\n\t" \ + " j 11f\n\t" \ + /* v20: Vector string range compare values. */ \ + "9: .short 0xd800,0xe000,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \ + /* v21: Vector string range compare control-bits. \ + element 0: =>; element 1: < */ \ + " .short 0xa000,0x4000,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \ + /* Found an element: ch >= 0xd800 && ch < 0xe000 */ \ + "10: vlgvb %[R_TMP],%%v19,7\n\t" \ + "11: la %[R_IN],0(%[R_TMP],%[R_IN])\n\t" \ + " sll %[R_TMP],1\n\t" \ + " lgr %[R_TMP2],%[R_TMP]\n\t" \ + " ahi %[R_TMP],-1\n\t" \ + " jl 20f\n\t" \ + " vstl %%v17,%[R_TMP],0(%[R_OUT])\n\t" \ + " ahi %[R_TMP],-16\n\t" \ + " jl 19f\n\t" \ + " vstl %%v18,%[R_TMP],16(%[R_OUT])\n\t" \ + "19: la %[R_OUT],0(%[R_TMP2],%[R_OUT])\n\t" \ + "20: \n\t" \ + ".machine pop" \ + : /* outputs */ [R_OUT] "+a" (outptr) \ + , [R_IN] "+a" (inptr) \ + , [R_TMP] "=a" (tmp) \ + , [R_TMP2] "=a" (tmp2) \ + , [R_LEN] "+d" (len) \ + : /* inputs */ \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ); \ + if (len > 0) \ + { \ + /* Found an invalid character at next input-char. */ \ + BODY_ORIG_ERROR \ + } \ + } + +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +# include <iconv/skeleton.c> +# undef BODY_ORIG +# undef BODY_ORIG_ERROR +ICONV_VX_IFUNC (__gconv_transform_ucs2_internal) + +/* Convert from UCS2 in other endianness to the internal (UCS4-like) format. */ +# define DEFINE_INIT 0 +# define DEFINE_FINI 0 +# define MIN_NEEDED_FROM 2 +# define MIN_NEEDED_TO 4 +# define FROM_DIRECTION 1 +# define FROM_LOOP ICONV_VX_NAME (ucs2reverse_internal_loop) +# define TO_LOOP ICONV_VX_NAME (ucs2reverse_internal_loop) /* This is not used.*/ +# define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_ucs2reverse_internal) +# define ONE_DIRECTION 1 + +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define LOOPFCT FROM_LOOP +# define BODY_ORIG_ERROR \ + /* Surrogate characters in UCS-2 input are not valid. Reject \ + them. (Catching this here is not security relevant.) */ \ + if (! ignore_errors_p ()) \ + { \ + result = __GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + inptr += 2; \ + ++*irreversible; \ + continue; + +# define BODY_ORIG \ + { \ + uint16_t u1 = bswap_16 (get16 (inptr)); \ + \ + if (__glibc_unlikely (u1 >= 0xd800 && u1 < 0xe000)) \ + { \ + BODY_ORIG_ERROR \ + } \ + \ + *((uint32_t *) outptr) = u1; \ + outptr += sizeof (uint32_t); \ + inptr += 2; \ + } +# define BODY \ + { \ + size_t len, tmp, tmp2; \ + len = MIN ((inend - inptr) / 2, (outend - outptr) / 4); \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + CONVERT_32BIT_SIZE_T ([R_LEN]) \ + /* Setup to check for ch >= 0xd800 && ch < 0xe000. */ \ + " larl %[R_TMP],9f\n\t" \ + " vlm %%v20,%%v22,0(%[R_TMP])\n\t" \ + " srlg %[R_TMP],%[R_LEN],3\n\t" \ + " clgije %[R_TMP],0,1f\n\t" \ + /* Process 16byte (8char) blocks. */ \ + "0: vl %%v16,0(%[R_IN])\n\t" \ + " vperm %%v16,%%v16,%%v16,%%v22\n\t" \ + " vstrchs %%v19,%%v16,%%v20,%%v21\n\t" \ + /* Enlarge UCS2 to UCS4. */ \ + " vuplhh %%v17,%%v16\n\t" \ + " vupllh %%v18,%%v16\n\t" \ + " jno 10f\n\t" \ + /* Store 32bytes to buf_out. */ \ + " vstm %%v17,%%v18,0(%[R_OUT])\n\t" \ + " la %[R_IN],16(%[R_IN])\n\t" \ + " la %[R_OUT],32(%[R_OUT])\n\t" \ + " brctg %[R_TMP],0b\n\t" \ + " llgfr %[R_LEN],%[R_LEN]\n\t" \ + " nilf %[R_LEN],7\n\t" \ + /* Process <16bytes. */ \ + "1: sll %[R_LEN],1\n\t" \ + " ahik %[R_TMP],%[R_LEN],-1\n\t" \ + " jl 20f\n\t" /* No further bytes available. */ \ + " vll %%v16,%[R_TMP],0(%[R_IN])\n\t" \ + " vperm %%v16,%%v16,%%v16,%%v22\n\t" \ + " vstrchs %%v19,%%v16,%%v20,%%v21\n\t" \ + /* Enlarge UCS2 to UCS4. */ \ + " vuplhh %%v17,%%v16\n\t" \ + " vupllh %%v18,%%v16\n\t" \ + " vlgvb %[R_TMP],%%v19,7\n\t" \ + " clr %[R_TMP],%[R_LEN]\n\t" \ + " locgrhe %[R_TMP],%[R_LEN]\n\t" \ + " locghihe %[R_LEN],0\n\t" \ + " j 11f\n\t" \ + /* v20: Vector string range compare values. */ \ + "9: .short 0xd800,0xe000,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \ + /* v21: Vector string range compare control-bits. \ + element 0: =>; element 1: < */ \ + " .short 0xa000,0x4000,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \ + /* v22: Vector permute mask. */ \ + " .short 0x0100,0x0302,0x0504,0x0706\n\t" \ + " .short 0x0908,0x0b0a,0x0d0c,0x0f0e\n\t" \ + /* Found an element: ch >= 0xd800 && ch < 0xe000 */ \ + "10: vlgvb %[R_TMP],%%v19,7\n\t" \ + "11: la %[R_IN],0(%[R_TMP],%[R_IN])\n\t" \ + " sll %[R_TMP],1\n\t" \ + " lgr %[R_TMP2],%[R_TMP]\n\t" \ + " ahi %[R_TMP],-1\n\t" \ + " jl 20f\n\t" \ + " vstl %%v17,%[R_TMP],0(%[R_OUT])\n\t" \ + " ahi %[R_TMP],-16\n\t" \ + " jl 19f\n\t" \ + " vstl %%v18,%[R_TMP],16(%[R_OUT])\n\t" \ + "19: la %[R_OUT],0(%[R_TMP2],%[R_OUT])\n\t" \ + "20: \n\t" \ + ".machine pop" \ + : /* outputs */ [R_OUT] "+a" (outptr) \ + , [R_IN] "+a" (inptr) \ + , [R_TMP] "=a" (tmp) \ + , [R_TMP2] "=a" (tmp2) \ + , [R_LEN] "+d" (len) \ + : /* inputs */ \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ASM_CLOBBER_VR ("v22") \ + ); \ + if (len > 0) \ + { \ + /* Found an invalid character at next input-char. */ \ + BODY_ORIG_ERROR \ + } \ + } +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +# include <iconv/skeleton.c> +# undef BODY_ORIG +# undef BODY_ORIG_ERROR +ICONV_VX_IFUNC (__gconv_transform_ucs2reverse_internal) + +/* Convert from the internal (UCS4-like) format to UCS2. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 4 +#define MIN_NEEDED_TO 2 +#define FROM_DIRECTION 1 +#define FROM_LOOP ICONV_VX_NAME (internal_ucs2_loop) +#define TO_LOOP ICONV_VX_NAME (internal_ucs2_loop) /* This is not used. */ +#define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_internal_ucs2) +#define ONE_DIRECTION 1 + +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY_ORIG \ + { \ + uint32_t val = *((const uint32_t *) inptr); \ + \ + if (__glibc_unlikely (val >= 0x10000)) \ + { \ + UNICODE_TAG_HANDLER (val, 4); \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } \ + else if (__glibc_unlikely (val >= 0xd800 && val < 0xe000)) \ + { \ + /* Surrogate characters in UCS-4 input are not valid. \ + We must catch this, because the UCS-2 output might be \ + interpreted as UTF-16 by other programs. If we let \ + surrogates pass through, attackers could make a security \ + hole exploit by synthesizing any desired plane 1-16 \ + character. */ \ + result = __GCONV_ILLEGAL_INPUT; \ + if (! ignore_errors_p ()) \ + break; \ + inptr += 4; \ + ++*irreversible; \ + continue; \ + } \ + else \ + { \ + put16 (outptr, val); \ + outptr += sizeof (uint16_t); \ + inptr += 4; \ + } \ + } +# define BODY \ + { \ + if (__builtin_expect (inend - inptr < 32, 1) \ + || outend - outptr < 16) \ + /* Convert remaining bytes with c code. */ \ + BODY_ORIG \ + else \ + { \ + /* Convert in 32 byte blocks. */ \ + size_t loop_count = (inend - inptr) / 32; \ + size_t tmp, tmp2; \ + if (loop_count > (outend - outptr) / 16) \ + loop_count = (outend - outptr) / 16; \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + CONVERT_32BIT_SIZE_T ([R_LI]) \ + " larl %[R_I],3f\n\t" \ + " vlm %%v20,%%v23,0(%[R_I])\n\t" \ + "0: \n\t" \ + " vlm %%v16,%%v17,0(%[R_IN])\n\t" \ + /* Shorten UCS4 to UCS2. */ \ + " vpkf %%v18,%%v16,%%v17\n\t" \ + " vstrcfs %%v19,%%v16,%%v20,%%v21\n\t" \ + " jno 11f\n\t" \ + "1: vstrcfs %%v19,%%v17,%%v20,%%v21\n\t" \ + " jno 10f\n\t" \ + /* Store 16bytes to buf_out. */ \ + "2: vst %%v18,0(%[R_OUT])\n\t" \ + " la %[R_IN],32(%[R_IN])\n\t" \ + " la %[R_OUT],16(%[R_OUT])\n\t" \ + " brctg %[R_LI],0b\n\t" \ + " j 20f\n\t" \ + /* Setup to check for ch >= 0xd800. (v20, v21) */ \ + "3: .long 0xd800,0xd800,0x0,0x0\n\t" \ + " .long 0xa0000000,0xa0000000,0x0,0x0\n\t" \ + /* Setup to check for ch >= 0xe000 \ + && ch < 0x10000. (v22,v23) */ \ + " .long 0xe000,0x10000,0x0,0x0\n\t" \ + " .long 0xa0000000,0x40000000,0x0,0x0\n\t" \ + /* v16 contains only valid chars. Check in v17: \ + ch >= 0xe000 && ch <= 0xffff. */ \ + "10: vstrcfs %%v19,%%v17,%%v22,%%v23,8\n\t" \ + " jo 2b\n\t" /* All ch's in this range, proceed. */ \ + " lghi %[R_TMP],16\n\t" \ + " j 12f\n\t" \ + /* Maybe v16 contains invalid chars. \ + Check ch >= 0xe000 && ch <= 0xffff. */ \ + "11: vstrcfs %%v19,%%v16,%%v22,%%v23,8\n\t" \ + " jo 1b\n\t" /* All ch's in this range, proceed. */ \ + " lghi %[R_TMP],0\n\t" \ + "12: vlgvb %[R_I],%%v19,7\n\t" \ + " agr %[R_I],%[R_TMP]\n\t" \ + " la %[R_IN],0(%[R_I],%[R_IN])\n\t" \ + " srl %[R_I],1\n\t" \ + " ahi %[R_I],-1\n\t" \ + " jl 20f\n\t" \ + " vstl %%v18,%[R_I],0(%[R_OUT])\n\t" \ + " la %[R_OUT],1(%[R_I],%[R_OUT])\n\t" \ + "20:\n\t" \ + ".machine pop" \ + : /* outputs */ [R_OUT] "+a" (outptr) \ + , [R_IN] "+a" (inptr) \ + , [R_LI] "+d" (loop_count) \ + , [R_I] "=a" (tmp2) \ + , [R_TMP] "=d" (tmp) \ + : /* inputs */ \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ASM_CLOBBER_VR ("v22") ASM_CLOBBER_VR ("v23") \ + ); \ + if (loop_count > 0) \ + { \ + /* Found an invalid character at next character. */ \ + BODY_ORIG \ + } \ + } \ + } +#define LOOP_NEED_FLAGS +#include <iconv/loop.c> +#include <iconv/skeleton.c> +# undef BODY_ORIG +ICONV_VX_IFUNC (__gconv_transform_internal_ucs2) + +/* Convert from the internal (UCS4-like) format to UCS2 in other endianness. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 4 +#define MIN_NEEDED_TO 2 +#define FROM_DIRECTION 1 +#define FROM_LOOP ICONV_VX_NAME (internal_ucs2reverse_loop) +#define TO_LOOP ICONV_VX_NAME (internal_ucs2reverse_loop)/* This is not used.*/ +#define FUNCTION_NAME ICONV_VX_NAME (__gconv_transform_internal_ucs2reverse) +#define ONE_DIRECTION 1 + +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY_ORIG \ + { \ + uint32_t val = *((const uint32_t *) inptr); \ + if (__glibc_unlikely (val >= 0x10000)) \ + { \ + UNICODE_TAG_HANDLER (val, 4); \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } \ + else if (__glibc_unlikely (val >= 0xd800 && val < 0xe000)) \ + { \ + /* Surrogate characters in UCS-4 input are not valid. \ + We must catch this, because the UCS-2 output might be \ + interpreted as UTF-16 by other programs. If we let \ + surrogates pass through, attackers could make a security \ + hole exploit by synthesizing any desired plane 1-16 \ + character. */ \ + if (! ignore_errors_p ()) \ + { \ + result = __GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + inptr += 4; \ + ++*irreversible; \ + continue; \ + } \ + else \ + { \ + put16 (outptr, bswap_16 (val)); \ + outptr += sizeof (uint16_t); \ + inptr += 4; \ + } \ + } +# define BODY \ + { \ + if (__builtin_expect (inend - inptr < 32, 1) \ + || outend - outptr < 16) \ + /* Convert remaining bytes with c code. */ \ + BODY_ORIG \ + else \ + { \ + /* Convert in 32 byte blocks. */ \ + size_t loop_count = (inend - inptr) / 32; \ + size_t tmp, tmp2; \ + if (loop_count > (outend - outptr) / 16) \ + loop_count = (outend - outptr) / 16; \ + __asm__ volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + CONVERT_32BIT_SIZE_T ([R_LI]) \ + " larl %[R_I],3f\n\t" \ + " vlm %%v20,%%v24,0(%[R_I])\n\t" \ + "0: \n\t" \ + " vlm %%v16,%%v17,0(%[R_IN])\n\t" \ + /* Shorten UCS4 to UCS2 and byteswap. */ \ + " vpkf %%v18,%%v16,%%v17\n\t" \ + " vperm %%v18,%%v18,%%v18,%%v24\n\t" \ + " vstrcfs %%v19,%%v16,%%v20,%%v21\n\t" \ + " jno 11f\n\t" \ + "1: vstrcfs %%v19,%%v17,%%v20,%%v21\n\t" \ + " jno 10f\n\t" \ + /* Store 16bytes to buf_out. */ \ + "2: vst %%v18,0(%[R_OUT])\n\t" \ + " la %[R_IN],32(%[R_IN])\n\t" \ + " la %[R_OUT],16(%[R_OUT])\n\t" \ + " brctg %[R_LI],0b\n\t" \ + " j 20f\n\t" \ + /* Setup to check for ch >= 0xd800. (v20, v21) */ \ + "3: .long 0xd800,0xd800,0x0,0x0\n\t" \ + " .long 0xa0000000,0xa0000000,0x0,0x0\n\t" \ + /* Setup to check for ch >= 0xe000 \ + && ch < 0x10000. (v22,v23) */ \ + " .long 0xe000,0x10000,0x0,0x0\n\t" \ + " .long 0xa0000000,0x40000000,0x0,0x0\n\t" \ + /* Vector permute mask (v24) */ \ + " .short 0x0100,0x0302,0x0504,0x0706\n\t" \ + " .short 0x0908,0x0b0a,0x0d0c,0x0f0e\n\t" \ + /* v16 contains only valid chars. Check in v17: \ + ch >= 0xe000 && ch <= 0xffff. */ \ + "10: vstrcfs %%v19,%%v17,%%v22,%%v23,8\n\t" \ + " jo 2b\n\t" /* All ch's in this range, proceed. */ \ + " lghi %[R_TMP],16\n\t" \ + " j 12f\n\t" \ + /* Maybe v16 contains invalid chars. \ + Check ch >= 0xe000 && ch <= 0xffff. */ \ + "11: vstrcfs %%v19,%%v16,%%v22,%%v23,8\n\t" \ + " jo 1b\n\t" /* All ch's in this range, proceed. */ \ + " lghi %[R_TMP],0\n\t" \ + "12: vlgvb %[R_I],%%v19,7\n\t" \ + " agr %[R_I],%[R_TMP]\n\t" \ + " la %[R_IN],0(%[R_I],%[R_IN])\n\t" \ + " srl %[R_I],1\n\t" \ + " ahi %[R_I],-1\n\t" \ + " jl 20f\n\t" \ + " vstl %%v18,%[R_I],0(%[R_OUT])\n\t" \ + " la %[R_OUT],1(%[R_I],%[R_OUT])\n\t" \ + "20:\n\t" \ + ".machine pop" \ + : /* outputs */ [R_OUT] "+a" (outptr) \ + , [R_IN] "+a" (inptr) \ + , [R_LI] "+d" (loop_count) \ + , [R_I] "=a" (tmp2) \ + , [R_TMP] "=d" (tmp) \ + : /* inputs */ \ + : /* clobber list*/ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ASM_CLOBBER_VR ("v22") ASM_CLOBBER_VR ("v23") \ + ASM_CLOBBER_VR ("v24") \ + ); \ + if (loop_count > 0) \ + { \ + /* Found an invalid character at next character. */ \ + BODY_ORIG \ + } \ + } \ + } +#define LOOP_NEED_FLAGS +#include <iconv/loop.c> +#include <iconv/skeleton.c> +# undef BODY_ORIG +ICONV_VX_IFUNC (__gconv_transform_internal_ucs2reverse) + + +#else +/* Generate the internal transformations without ifunc if build environment + lacks vector support. Instead simply include the common version. */ +# include <iconv/gconv_simple.c> +#endif /* !defined HAVE_S390_VX_ASM_SUPPORT */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/gen-8bit.sh b/REORG.TODO/sysdeps/s390/multiarch/gen-8bit.sh new file mode 100644 index 0000000000..6f88c4bd9d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/gen-8bit.sh @@ -0,0 +1,6 @@ +#!/bin/sh +echo "static const uint8_t to_ucs1[256] = {" +sed -ne '/^[^[:space:]]*[[:space:]]*.x00/d;/^END/q' \ + -e 's/^<U00\(..\)>[[:space:]]*.x\(..\).*/ [0x\2] = 0x\1,/p' \ + "$@" | sort -u +echo "};" diff --git a/REORG.TODO/sysdeps/s390/multiarch/iconv/skeleton.c b/REORG.TODO/sysdeps/s390/multiarch/iconv/skeleton.c new file mode 100644 index 0000000000..ca9ad1206f --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/iconv/skeleton.c @@ -0,0 +1,21 @@ +/* Skeleton for a conversion module - S390 version. + Copyright (C) 2016-2017 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/>. */ + +#ifndef IGNORE_ICONV_SKELETON +# include_next <iconv/skeleton.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/ifunc-impl-list.c b/REORG.TODO/sysdeps/s390/multiarch/ifunc-impl-list.c new file mode 100644 index 0000000000..6210f50acb --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/ifunc-impl-list.c @@ -0,0 +1,152 @@ +/* Enumerate available IFUNC implementations of a function. s390/s390x version. + Copyright (C) 2015-2017 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/>. */ + +#include <assert.h> +#include <string.h> +#include <wchar.h> +#include <ifunc-impl-list.h> +#include <ifunc-resolve.h> + +/* Maximum number of IFUNC implementations. */ +#define MAX_IFUNC 3 + +/* Fill ARRAY of MAX elements with IFUNC implementations for function + NAME supported on target machine and return the number of valid + entries. */ +size_t +__libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + size_t max) +{ + assert (max >= MAX_IFUNC); + + size_t i = 0; + + /* Get hardware information. */ + unsigned long int dl_hwcap = GLRO (dl_hwcap); + unsigned long long stfle_bits = 0ULL; + if ((dl_hwcap & HWCAP_S390_STFLE) + && (dl_hwcap & HWCAP_S390_ZARCH) + && (dl_hwcap & HWCAP_S390_HIGH_GPRS)) + { + S390_STORE_STFLE (stfle_bits); + } + + IFUNC_IMPL (i, name, memset, + IFUNC_IMPL_ADD (array, i, memset, + S390_IS_Z196 (stfle_bits), __memset_z196) + IFUNC_IMPL_ADD (array, i, memset, + S390_IS_Z10 (stfle_bits), __memset_z10) + IFUNC_IMPL_ADD (array, i, memset, 1, __memset_default)) + + IFUNC_IMPL (i, name, memcmp, + IFUNC_IMPL_ADD (array, i, memcmp, + S390_IS_Z196 (stfle_bits), __memcmp_z196) + IFUNC_IMPL_ADD (array, i, memcmp, + S390_IS_Z10 (stfle_bits), __memcmp_z10) + IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_default)) + +#ifdef SHARED + + IFUNC_IMPL (i, name, memcpy, + IFUNC_IMPL_ADD (array, i, memcpy, + S390_IS_Z196 (stfle_bits), __memcpy_z196) + IFUNC_IMPL_ADD (array, i, memcpy, + 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 + +# define IFUNC_VX_IMPL(FUNC) \ + IFUNC_IMPL (i, name, FUNC, \ + IFUNC_IMPL_ADD (array, i, FUNC, dl_hwcap & HWCAP_S390_VX, \ + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + + IFUNC_VX_IMPL (strlen); + IFUNC_VX_IMPL (wcslen); + + IFUNC_VX_IMPL (strnlen); + IFUNC_VX_IMPL (wcsnlen); + + IFUNC_VX_IMPL (strcpy); + IFUNC_VX_IMPL (wcscpy); + + IFUNC_VX_IMPL (stpcpy); + IFUNC_VX_IMPL (wcpcpy); + + IFUNC_VX_IMPL (strncpy); + IFUNC_VX_IMPL (wcsncpy); + + IFUNC_VX_IMPL (stpncpy); + IFUNC_VX_IMPL (wcpncpy); + + IFUNC_VX_IMPL (strcat); + IFUNC_VX_IMPL (wcscat); + + IFUNC_VX_IMPL (strncat); + IFUNC_VX_IMPL (wcsncat); + + IFUNC_VX_IMPL (strcmp); + IFUNC_VX_IMPL (wcscmp); + + IFUNC_VX_IMPL (strncmp); + IFUNC_VX_IMPL (wcsncmp); + + IFUNC_VX_IMPL (strchr); + IFUNC_VX_IMPL (wcschr); + + IFUNC_VX_IMPL (strchrnul); + IFUNC_VX_IMPL (wcschrnul); + + IFUNC_VX_IMPL (strrchr); + IFUNC_VX_IMPL (wcsrchr); + + IFUNC_VX_IMPL (strspn); + IFUNC_VX_IMPL (wcsspn); + + IFUNC_VX_IMPL (strpbrk); + IFUNC_VX_IMPL (wcspbrk); + + IFUNC_VX_IMPL (strcspn); + IFUNC_VX_IMPL (wcscspn); + + IFUNC_VX_IMPL (memchr); + IFUNC_VX_IMPL (wmemchr); + IFUNC_VX_IMPL (rawmemchr); + + IFUNC_VX_IMPL (memccpy); + + IFUNC_VX_IMPL (wmemset); + + IFUNC_VX_IMPL (wmemcmp); + + IFUNC_VX_IMPL (memrchr); + +#endif /* HAVE_S390_VX_ASM_SUPPORT */ + + return i; +} diff --git a/REORG.TODO/sysdeps/s390/multiarch/ifunc-resolve.h b/REORG.TODO/sysdeps/s390/multiarch/ifunc-resolve.h new file mode 100644 index 0000000000..adbd08a6ee --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/ifunc-resolve.h @@ -0,0 +1,90 @@ +/* IFUNC resolver function for CPU specific functions. + 32/64 bit S/390 version. + Copyright (C) 2015-2017 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/>. */ + +#include <unistd.h> +#include <dl-procinfo.h> + +#define S390_STFLE_BITS_Z10 34 /* General instructions extension */ +#define S390_STFLE_BITS_Z196 45 /* Distinct operands, pop ... */ + +#define S390_IS_Z196(STFLE_BITS) \ + ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_Z196))) != 0) + +#define S390_IS_Z10(STFLE_BITS) \ + ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_Z10))) != 0) + +#define S390_STORE_STFLE(STFLE_BITS) \ + /* We want just 1 double word to be returned. */ \ + register unsigned long reg0 __asm__("0") = 0; \ + \ + __asm__ __volatile__(".machine push" "\n\t" \ + ".machine \"z9-109\"" "\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + "stfle %0" "\n\t" \ + ".machine pop" "\n" \ + : "=QS" (STFLE_BITS), "+d" (reg0) \ + : : "cc"); +#define s390_libc_ifunc_init() \ + unsigned long long stfle_bits = 0ULL; \ + if (__glibc_likely((dl_hwcap & HWCAP_S390_STFLE) \ + && (dl_hwcap & HWCAP_S390_ZARCH) \ + && (dl_hwcap & HWCAP_S390_HIGH_GPRS))) \ + { \ + S390_STORE_STFLE (stfle_bits); \ + } + +#define s390_libc_ifunc(TYPE_FUNC, RESOLVERFUNC, FUNC) \ + /* Make the declarations of the optimized functions hidden in order + to prevent GOT slots being generated for them. */ \ + extern __typeof (TYPE_FUNC) RESOLVERFUNC##_z196 attribute_hidden; \ + extern __typeof (TYPE_FUNC) RESOLVERFUNC##_z10 attribute_hidden; \ + extern __typeof (TYPE_FUNC) RESOLVERFUNC##_default attribute_hidden; \ + __ifunc (TYPE_FUNC, FUNC, \ + __glibc_likely (S390_IS_Z196 (stfle_bits)) \ + ? RESOLVERFUNC##_z196 \ + : __glibc_likely (S390_IS_Z10 (stfle_bits)) \ + ? RESOLVERFUNC##_z10 \ + : RESOLVERFUNC##_default, \ + unsigned long int dl_hwcap, s390_libc_ifunc_init); + +#define s390_vx_libc_ifunc(FUNC) \ + s390_vx_libc_ifunc2_redirected(FUNC, FUNC, FUNC) + +#define s390_vx_libc_ifunc_redirected(TYPE_FUNC, FUNC) \ + s390_vx_libc_ifunc2_redirected(TYPE_FUNC, FUNC, FUNC) + +#define s390_vx_libc_ifunc2(RESOLVERFUNC, FUNC) \ + s390_vx_libc_ifunc2_redirected(FUNC, RESOLVERFUNC, FUNC) + +#define s390_vx_libc_ifunc_init() +#define s390_vx_libc_ifunc2_redirected(TYPE_FUNC, RESOLVERFUNC, FUNC) \ + /* Make the declarations of the optimized functions hidden in order + to prevent GOT slots being generated for them. */ \ + extern __typeof (TYPE_FUNC) RESOLVERFUNC##_vx attribute_hidden; \ + extern __typeof (TYPE_FUNC) RESOLVERFUNC##_c attribute_hidden; \ + __ifunc (TYPE_FUNC, FUNC, \ + (dl_hwcap & HWCAP_S390_VX) \ + ? RESOLVERFUNC##_vx \ + : RESOLVERFUNC##_c, \ + unsigned long int dl_hwcap, s390_vx_libc_ifunc_init); + +#define s390_libc_ifunc_expr_init() +#define s390_libc_ifunc_expr(TYPE_FUNC, FUNC, EXPR) \ + __ifunc (TYPE_FUNC, FUNC, EXPR, unsigned long int hwcap, \ + s390_libc_ifunc_expr_init); diff --git a/REORG.TODO/sysdeps/s390/multiarch/memccpy-c.c b/REORG.TODO/sysdeps/s390/multiarch/memccpy-c.c new file mode 100644 index 0000000000..73069ae502 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/memccpy-c.c @@ -0,0 +1,25 @@ +/* Default memccpy implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define MEMCCPY __memccpy_c + +# include <string.h> +extern __typeof (__memccpy) __memccpy_c; +# include <string/memccpy.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/memccpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/memccpy-vx.S new file mode 100644 index 0000000000..f60aecef77 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/memccpy-vx.S @@ -0,0 +1,156 @@ +/* Vector optimized 32/64 bit S/390 version of memccpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* void *memccpy (void * dest, const void *src, int c, size_t n) + Copies no more than n bytes from src to dest, + stopping when the character c is found + and returns pointer next to c in dest or null if c not found. + + Register usage: + -r0=tmp + -r1=tmp + -r2=dest + -r3=src + -r4=c + -r5=n + -r6=current_len + -v16=part of s + -v17=index of found c + -v18=c replicated + -v19=part #2 of s + -v31=save area for r6 +*/ +ENTRY(__memccpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r5,%r5 +# endif /* !defined __s390x__ */ + + vlvgp %v31,%r6,%r7 /* Save registers. */ + clgije %r5,0,.Lnf_end /* If len == 0 then exit. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r0,%r0 /* Convert 32bit to 64bit. */ + + vlvgb %v18,%r4,0 /* Generate vector which elements are all c. + if c > 255, c will be truncated. */ + vrepb %v18,%v18,0 + lghi %r6,0 /* current_len = 0. */ + + clgrjle %r5,%r0,.Lremaining_v16 /* If maxlen <= loaded-bytes + -> Process remaining. */ + + vfeebs %v17,%v16,%v18 /* Find c. */ + vlgvb %r1,%v17,7 /* Load byte index of c. */ + clgrjl %r1,%r0,.Lfound_v16 /* Found c is within loaded bytes. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r6,15 /* current_len = 15. */ + slr %r6,%r1 /* Compute highest index to 16byte boundary. */ + + vstl %v16,%r6,0(%r2) /* Store prcessed bytes */ + ahi %r6,1 + +.Lpreloop1: + /* Now we are 16byte aligned, so we can load + a full vreg without page fault. */ + vl %v16,0(%r6,%r3) /* Load s. */ + clgijl %r5,17,.Lremaining_v16 /* If n <= 16, + process remaining bytes. */ + lgr %r7,%r5 + slgfi %r7,16 /* border_len = n - 16. */ + j .Lloop1 + +.Lloop2: + vl %v16,16(%r6,%r3) + vst %v19,0(%r6,%r2) + aghi %r6,16 + +.Lloop1: + clgrjhe %r6,%r7,.Lremaining_v16 /* If current_len >= border + then process remaining bytes. */ + vfeebs %v17,%v16,%v18 /* Find c. */ + jl .Lfound_v16 /* Jump away if c was found. */ + vl %v19,16(%r6,%r3) /* Load next s part. */ + vst %v16,0(%r6,%r2) /* Store previous part without c. */ + aghi %r6,16 + + clgrjhe %r6,%r7,.Lremaining_v19 + vfeebs %v17,%v19,%v18 + jl .Lfound_v19 + vl %v16,16(%r6,%r3) + vst %v19,0(%r6,%r2) + aghi %r6,16 + + clgrjhe %r6,%r7,.Lremaining_v16 + vfeebs %v17,%v16,%v18 + jl .Lfound_v16 + vl %v19,16(%r6,%r3) + vst %v16,0(%r6,%r2) + aghi %r6,16 + + clgrjhe %r6,%r7,.Lremaining_v19 + vfeebs %v17,%v19,%v18 + jo .Lloop2 + +.Lfound_v19: + vlr %v16,%v19 +.Lfound_v16: + /* v16 contains c. Store remaining bytes to c. currlen hasn´t + reached border, thus checking for maxlen is not needed! */ + vlgvb %r1,%v17,7 /* Load byte index of c. */ + la %r2,0(%r6,%r2) /* vstl has no support for index-register. */ +.Lfound_v16_store: + vstl %v16,%r1,0(%r2) /* Copy bytes including c. */ + la %r2,1(%r1,%r2) /* Return pointer next to c in dest. */ + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + br %r14 + +.Lremaining_v19: + vlr %v16,%v19 +.Lremaining_v16: + /* v16 contains the remaining bytes [1...16]. + Check and store remaining bytes. */ + vfeebs %v17,%v16,%v18 + slgrk %r7,%r5,%r6 /* Remaining bytes = maxlen - current_len. */ + aghi %r7,-1 /* vstl needs highest index. */ + la %r2,0(%r6,%r2) /* vstl has no index register. */ + vlgvb %r1,%v17,7 /* Load index of c or 16 if not found. */ + /* c in remaining bytes? -> Jump away (c-index <= max-index) */ + clrjle %r1,%r7,.Lfound_v16_store + vstl %v16,%r7,0(%r2) /* Store remaining bytes. */ + +.Lnf_end: + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + lghi %r2,0 /* Return null. */ + br %r14 +END(__memccpy_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/memccpy.c b/REORG.TODO/sysdeps/s390/multiarch/memccpy.c new file mode 100644 index 0000000000..5adc1a8063 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/memccpy.c @@ -0,0 +1,28 @@ +/* Multiple versions of memccpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <string.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__memccpy) +weak_alias (__memccpy, memccpy) + +#else +# include <string/memccpy.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/memchr-vx.S b/REORG.TODO/sysdeps/s390/multiarch/memchr-vx.S new file mode 100644 index 0000000000..e9cb06f948 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/memchr-vx.S @@ -0,0 +1,159 @@ +/* Vector optimized 32/64 bit S/390 version of memchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* void *memchr (const void *s, int c, size_t n) + Scans memory for character c + and returns pointer to first c. + + Register usage: + -r0=tmp + -r1=tmp + -r2=s + -r3=c + -r4=n + -r5=current_len + -v16=part of s + -v17=index of found c + -v18=c replicated +*/ +ENTRY(__memchr_vx) + + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgije %r4,0,.Lnf_end /* If len == 0 then exit. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r0,%r0 /* Convert 32bit to 64bit. */ + + vlvgb %v18,%r3,0 /* Generate vector which elements are all c. + if c > 255, c will be truncated. */ + vrepb %v18,%v18,0 + lghi %r5,16 /* current_len = 16. */ + + clgrjhe %r0,%r4,.Llastcmp /* If (bytes to boundary) >= n, + jump to lastcmp. */ + + vfeebs %v17,%v16,%v18 /* Find c. */ + vlgvb %r1,%v17,7 /* Load byte index of c. */ + clgrjl %r1,%r0,.Lfound2 /* Found c is within loaded bytes. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + slr %r5,%r1 /* Compute bytes to 16bytes boundary. */ + + lgr %r0,%r5 /* If %r5 + 64 < n? -> loop64. */ + aghi %r0,64 + clgrjl %r0,%r4,.Lloop64 +.Llt64: + vl %v16,0(%r5,%r2) + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp /* Do last compare if curr-len >= n. */ + vfeebs %v17,%v16,%v18 /* Find c. */ + jl .Lfound /* Jump away if c was found. */ + + vl %v16,0(%r5,%r2) + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp + vfeebs %v17,%v16,%v18 + jl .Lfound + + vl %v16,0(%r5,%r2) + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp + vfeebs %v17,%v16,%v18 + jl .Lfound + + vl %v16,0(%r5,%r2) + aghi %r5,16 + +.Llastcmp: + /* Use comparision result only if located within first n characters. + %r5: current_len; + %r4: n; + (current_len - n): [0...16[ + first ignored match index: vr-width - (current_len - n) ]0...16] + */ + vfeebs %v17,%v16,%v18 /* Find c. */ + slgrk %r4,%r5,%r4 /* %r5 = current_len - n. */ + lghi %r0,16 /* Register width = 16. */ + vlgvb %r1,%v17,7 /* Extract found index or 16 if all equal. */ + slr %r0,%r4 /* %r0 = first ignored match index. */ + clrjl %r1,%r0,.Lfound2 /* Go away if miscompare is below n bytes. */ + /* c not found within n-bytes. */ +.Lnf_end: + lghi %r2,0 /* Return null. */ + br %r14 + +.Lfound48: + aghi %r5,16 +.Lfound32: + aghi %r5,16 +.Lfound16: + aghi %r5,16 +.Lfound0: + aghi %r5,16 +.Lfound: + vlgvb %r1,%v17,7 /* Load byte index of c. */ +.Lfound2: + slgfi %r5,16 /* current_len -=16 */ + algr %r5,%r1 /* Zero byte index is added to current len. */ + la %r2,0(%r5,%r2) /* Return pointer to c. */ + br %r14 + + +.Lloop64: + vl %v16,0(%r5,%r2) + vfeebs %v17,%v16,%v18 /* Find c. */ + jl .Lfound0 /* Jump away if c was found. */ + vl %v16,16(%r5,%r2) + vfeebs %v17,%v16,%v18 + jl .Lfound16 + vl %v16,32(%r5,%r2) + vfeebs %v17,%v16,%v18 + jl .Lfound32 + vl %v16,48(%r5,%r2) + vfeebs %v17,%v16,%v18 + jl .Lfound48 + + aghi %r5,64 + lgr %r0,%r5 /* If %r5 + 64 < n? -> loop64. */ + aghi %r0,64 + clgrjl %r0,%r4,.Lloop64 + + j .Llt64 +END(__memchr_vx) + +# define memchr __memchr_c +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) strong_alias(__memchr_c, __GI_memchr) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ + +#include <memchr.S> diff --git a/REORG.TODO/sysdeps/s390/multiarch/memchr.c b/REORG.TODO/sysdeps/s390/multiarch/memchr.c new file mode 100644 index 0000000000..f0bf41f8e4 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/memchr.c @@ -0,0 +1,27 @@ +/* Multiple versions of memchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define memchr __redirect_memchr +# include <string.h> +# undef memchr +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_memchr, __memchr, memchr) + +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/mempcpy.c b/REORG.TODO/sysdeps/s390/multiarch/mempcpy.c new file mode 100644 index 0000000000..bf111a3aea --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/mempcpy.c @@ -0,0 +1,32 @@ +/* Multiple versions of mempcpy. + Copyright (C) 2016-2017 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) +# define mempcpy __redirect_mempcpy +# define __mempcpy __redirect___mempcpy +/* Omit the mempcpy inline definitions because it would redefine mempcpy. */ +# define _HAVE_STRING_ARCH_mempcpy 1 +# include <string.h> +# undef mempcpy +# undef __mempcpy +# include <ifunc-resolve.h> + +s390_libc_ifunc (__redirect___mempcpy, ____mempcpy, __mempcpy) +weak_alias (__mempcpy, mempcpy); +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/memrchr-c.c b/REORG.TODO/sysdeps/s390/multiarch/memrchr-c.c new file mode 100644 index 0000000000..7382b7ff05 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/memrchr-c.c @@ -0,0 +1,25 @@ +/* Default memrchr implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define MEMRCHR __memrchr_c + +# include <string.h> +extern __typeof (__memrchr) __memrchr_c; +# include <string/memrchr.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/memrchr-vx.S b/REORG.TODO/sysdeps/s390/multiarch/memrchr-vx.S new file mode 100644 index 0000000000..c6b0d34692 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/memrchr-vx.S @@ -0,0 +1,160 @@ +/* Vector optimized 32/64 bit S/390 version of memrchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* void *memrchr (const void *s, int c, size_t n) + Scans memory for character c backwards + and returns pointer to first c. + + Register usage: + -r0=tmp + -r1=tmp + -r2=s + -r3=c + -r4=n + -r5=s in loop + + -v16=part of s + -v17=index of found c + -v18=c replicated + -v20=permute pattern +*/ +ENTRY(__memrchr_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + clgije %r4,0,.Lnot_found + + vlvgb %v18,%r3,0 /* Generate vector which elements are all c. + If c > 255, c will be truncated. */ + vrepb %v18,%v18,0 + + llcr %r3,%r3 /* char c_char = (char) c. */ + + /* check byte n - 1. */ + llc %r0,-1(%r4,%r2) + slgfi %r4,1 + clrje %r0,%r3,.Lfound_end + jh .Lnot_found /* Return NULL if n is now 0. */ + + larl %r1,.Lpermute_mask /* Load permute mask. */ + vl %v20,0(%r1) + + /* check byte n - 2. */ + llc %r0,-1(%r4,%r2) + slgfi %r4,1 + clrje %r0,%r3,.Lfound_end + jh .Lnot_found /* Return NULL if n is now 0. */ + + clgijhe %r4,64,.Lloop64 /* If n >= 64 -> loop64. */ + +.Llt64: + /* Process n < 64 bytes. */ + clgijl %r4,16,.Llt16 /* Jump away if n < 16. */ + aghi %r4,-16 + vl %v16,0(%r4,%r2) + vfeebs %v17,%v16,%v18 + jno .Lfound0 + clgijl %r4,16,.Llt16 + aghi %r4,-16 + vl %v16,0(%r4,%r2) + vfeebs %v17,%v16,%v18 + jno .Lfound0 + clgijl %r4,16,.Llt16 + aghi %r4,-16 + vl %v16,0(%r4,%r2) + vfeebs %v17,%v16,%v18 + jno .Lfound0 +.Llt16: + clgfi %r4,0 /* if remaining bytes == 0, return NULL. */ + locghie %r2,0 + ber %r14 + + aghi %r4,-1 /* vll needs highest index. */ + vll %v16,%r4,0(%r2) /* Load remaining bytes. */ + + /* Right-shift of v16 to mask bytes after highest index. */ + lhi %r0,15 + slr %r0,%r4 /* Compute byte count for vector shift right. */ + sll %r0,3 /* Convert to bit count. */ + vlvgb %v17,%r0,7 + vsrlb %v16,%v16,%v17 /* Vector shift right by byte by number of bytes + specified in bits 1-4 of byte 7 in v17. */ + j .Lfound_permute + +.Lfound48: + aghi %r4,16 +.Lfound32: + aghi %r4,16 +.Lfound16: + aghi %r4,16 +.Lfound0: + la %r2,0(%r4,%r2) /* Set pointer to start of v16. */ + lghi %r4,15 /* Set highest index in v16 to last index. */ +.Lfound_permute: + /* Search for a c in v16 in reversed byte order. v16 contains %r4 + 1 + bytes. If v16 was not fully loaded, the bytes are already + right shifted, so that the bytes in v16 can simply be reversed. */ + vperm %v16,%v16,%v16,%v20 /* Permute v16 to reversed order. */ + vfeeb %v16,%v16,%v18 /* Find c in reversed v16. */ + vlgvb %r1,%v16,7 /* Index of c or 16 if not found. */ + + /* Return NULL if there is no c in loaded bytes. */ + clrjh %r1,%r4,.Lnot_found + + slgr %r4,%r1 +.Lfound_end: + la %r2,0(%r4,%r2) /* Return pointer to c. */ + br %r14 + +.Lnot_found: + lghi %r2,0 + br %r14 + +.Lpermute_mask: + .byte 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08 + .byte 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 + +.Lloop64: + aghi %r4,-64 + vl %v16,48(%r4,%r2) /* Load 16bytes of memory area. */ + vfeebs %v17,%v16,%v18 /* Find c. */ + jno .Lfound48 /* Jump away if c was found. */ + vl %v16,32(%r4,%r2) + vfeebs %v17,%v16,%v18 + jno .Lfound32 + vl %v16,16(%r4,%r2) + vfeebs %v17,%v16,%v18 + jno .Lfound16 + vl %v16,0(%r4,%r2) + vfeebs %v17,%v16,%v18 + jno .Lfound0 + + clgijhe %r4,64,.Lloop64 /* If n >= 64 -> loop64. */ + j .Llt64 +END(__memrchr_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/memrchr.c b/REORG.TODO/sysdeps/s390/multiarch/memrchr.c new file mode 100644 index 0000000000..3a76c62376 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/memrchr.c @@ -0,0 +1,28 @@ +/* Multiple versions of memrchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <string.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__memrchr) +weak_alias (__memrchr, memrchr) + +#else +# include <string/memrchr.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/rawmemchr-c.c b/REORG.TODO/sysdeps/s390/multiarch/rawmemchr-c.c new file mode 100644 index 0000000000..12a64d338d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/rawmemchr-c.c @@ -0,0 +1,34 @@ +/* Default rawmemchr implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <string.h> + +# define RAWMEMCHR __rawmemchr_c +# undef weak_alias +# define weak_alias(a, b) +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__rawmemchr_c, __GI___rawmemchr, __rawmemchr_c); +# endif /* SHARED */ + +extern __typeof (rawmemchr) __rawmemchr_c attribute_hidden; + +# include <string/rawmemchr.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/rawmemchr-vx.S b/REORG.TODO/sysdeps/s390/multiarch/rawmemchr-vx.S new file mode 100644 index 0000000000..e2ac9a88e1 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/rawmemchr-vx.S @@ -0,0 +1,92 @@ +/* Vector optimized 32/64 bit S/390 version of rawmemchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* void *rawmemchr (const void *s, int c) + Scans memory for character c + and returns pointer to first c. + + Register usage: + -r1=tmp + -r2=s + -r3=c + -r4=tmp + -r5=current_len + -v16=part of s + -v17=index of unequal + -v18=c replicated +*/ +ENTRY(__rawmemchr_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vlvgb %v18,%r3,0 /* Generate vector which elements are all c. + If c > 255, c will be truncated. */ + vrepb %v18,%v18,0 + + vfeeb %v17,%v16,%v18 /* Vector find element equal. */ + vlgvb %r5,%v17,7 /* Load byte index of character or zero. */ + clrjl %r5,%r1,.Lend_found /* If found c is in loaded bytes, end. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 + slr %r5,%r1 /* Compute bytes to 16bytes boundary. */ + + /* Find c in a 16byte aligned loop. */ +.Lloop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfeebs %v17,%v16,%v18 /* Vector find element equal. */ + jno .Lcharacter /* Jump away if element found. */ + vl %v16,16(%r5,%r2) + vfeebs %v17,%v16,%v18 + jno .Lcharacter16 + vl %v16,32(%r5,%r2) + vfeebs %v17,%v16,%v18 + jno .Lcharacter32 + vl %v16,48(%r5,%r2) + vfeebs %v17,%v16,%v18 + jno .Lcharacter48 + + aghi %r5,64 + j .Lloop /* No character found -> loop. */ + + /* Found character. */ +.Lcharacter48: + aghi %r5,16 +.Lcharacter32: + aghi %r5,16 +.Lcharacter16: + aghi %r5,16 +.Lcharacter: + vlgvb %r1,%v17,7 /* Load byte index of character. */ + algr %r5,%r1 +.Lend_found: + la %r2,0(%r5,%r2) /* Return pointer to character. */ + br %r14 +END(__rawmemchr_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/rawmemchr.c b/REORG.TODO/sysdeps/s390/multiarch/rawmemchr.c new file mode 100644 index 0000000000..74b0accb33 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/rawmemchr.c @@ -0,0 +1,31 @@ +/* Multiple versions of rawmemchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define __rawmemchr __redirect___rawmemchr +# include <string.h> +# undef __rawmemchr +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect___rawmemchr, __rawmemchr + , __rawmemchr) +weak_alias (__rawmemchr, rawmemchr) + +#else +# include <string/rawmemchr.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/stpcpy-c.c b/REORG.TODO/sysdeps/s390/multiarch/stpcpy-c.c new file mode 100644 index 0000000000..3818cfc24a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/stpcpy-c.c @@ -0,0 +1,35 @@ +/* Default stpcpy implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STPCPY __stpcpy_c +# undef weak_alias +# define weak_alias(a, b) +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__stpcpy_c, __GI___stpcpy, __stpcpy_c); +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + strong_alias (__stpcpy_c, __stpcpy_c_1); \ + __hidden_ver1 (__stpcpy_c_1, __GI_stpcpy, __stpcpy_c_1); +# endif /* SHARED */ + + +# include <string/stpcpy.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/stpcpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/stpcpy-vx.S new file mode 100644 index 0000000000..a9e5be2e68 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/stpcpy-vx.S @@ -0,0 +1,104 @@ +/* Vector optimized 32/64 bit S/390 version of stpcpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char * stpcpy (const char *dest, const char *src) + Copy string src to dest returning a pointer to its end. + + Register usage: + -r1=tmp + -r2=dest and return value + -r3=src + -r4=tmp + -r5=current_len + -v16=part of src + -v17=index of zero + -v18=part of src +*/ +ENTRY(__stpcpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Lfound_align /* If found zero within loaded bytes, + copy bytes before and return. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r4 /* Compute highest index to 16byte boundary. */ + + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Find zero in 16byte aligned loop. */ +.Lloop: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16_0 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezbs %v17,%v18,%v18 + je .Lfound_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezbs %v17,%v16,%v16 + je .Lfound_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezbs %v17,%v18,%v18 + je .Lfound_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + j .Lloop /* No zero found -> loop. */ + +.Lfound_v16_32: + aghi %r5,32 +.Lfound_v16_0: + la %r3,0(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + vstl %v16,%r1,0(%r3) /* Copy characters including zero. */ + la %r2,0(%r1,%r3) /* Return pointer to zero. */ + br %r14 + +.Lfound_v18_48: + aghi %r5,32 +.Lfound_v18_16: + la %r3,16(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + vstl %v18,%r1,0(%r3) /* Copy characters including zero. */ + la %r2,0(%r1,%r3) /* Return pointer to zero. */ + br %r14 + +.Lfound_align: + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + la %r2,0(%r5,%r2) /* Return pointer to zero. */ + br %r14 +END(__stpcpy_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/stpcpy.c b/REORG.TODO/sysdeps/s390/multiarch/stpcpy.c new file mode 100644 index 0000000000..611cf0765e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/stpcpy.c @@ -0,0 +1,35 @@ +/* Multiple versions of stpcpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define stpcpy __redirect_stpcpy +# define __stpcpy __redirect___stpcpy +/* Omit the stpcpy inline definitions because it would redefine stpcpy. */ +# define __NO_STRING_INLINES +# define NO_MEMPCPY_STPCPY_REDIRECT +# include <string.h> +# undef stpcpy +# undef __stpcpy +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc_redirected (__redirect___stpcpy, __stpcpy); +weak_alias (__stpcpy, stpcpy) + +#else +# include <string/stpcpy.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/stpncpy-c.c b/REORG.TODO/sysdeps/s390/multiarch/stpncpy-c.c new file mode 100644 index 0000000000..95efa38895 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/stpncpy-c.c @@ -0,0 +1,28 @@ +/* Default stpncpy implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STPNCPY __stpncpy_c +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__stpncpy_c, __GI___stpncpy, __stpncpy_c); +# endif /* SHARED */ + +# include <string/stpncpy.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/stpncpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/stpncpy-vx.S new file mode 100644 index 0000000000..869e8f7aef --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/stpncpy-vx.S @@ -0,0 +1,200 @@ +/* Vector optimized 32/64 bit S/390 version of stpncpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char * stpncpy (char *dest, const char *src, size_t n) + Copies at most n characters of string src to dest + returning a pointer to its end or dest+n + if src is smaller than n. + + Register usage: + -%r0 = return value + -%r1 = zero byte index + -%r2 = curr dst pointer + -%r3 = curr src pointer + -%r4 = n + -%r5 = current_len + -%r6 = loaded bytes + -%r7 = border, tmp +*/ +ENTRY(__stpncpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgfi %r4,0 + ber %r14 /* Nothing to do, if n == 0. */ + + la %r0,0(%r4,%r2) /* Save destination pointer + n for return. */ + vlvgp %v31,%r6,%r7 /* Save registers. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r6,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r6,%r6 /* Convert 32bit to 64bit. */ + + lghi %r5,0 /* current_len = 0. */ + + clgrjle %r4,%r6,.Lremaining_v16 /* If n <= loaded-bytes + -> process remaining. */ + + /* n > loaded-byte-count */ + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r1,%r6,.Lfound_v16_store /* Found zero within loaded bytes, + copy and return. */ + + /* Align s to 16 byte. */ + risbgn %r7,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r7 /* Compute highest index to 16byte boundary. */ + + /* Zero not found and n > loaded-byte-count. */ + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Now we are 16byte aligned, so we can load a full vreg + without page fault. */ + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lloop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + clgijl %r4,17,.Lremaining_v16 /* If n <= 16, process remaining + bytes. */ +.Llt64: + lgr %r7,%r4 + slgfi %r7,16 /* border_len = n - 16. */ + + clgrjhe %r5,%r7,.Lremaining_v16 /* If current_len >= border + then process remaining bytes. */ + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Save previous part without zero to dst. */ + aghi %r5,16 + + clgrjhe %r5,%r7,.Lremaining_v18 + vfenezbs %v17,%v18,%v18 + je .Lfound_v18 + vl %v16,16(%r5,%r3) + vst %v18,0(%r5,%r2) + aghi %r5,16 + + clgrjhe %r5,%r7,.Lremaining_v16 + vfenezbs %v17,%v16,%v16 + je .Lfound_v16 + vl %v18,16(%r5,%r3) + vst %v16,0(%r5,%r2) + aghi %r5,16 + +.Lremaining_v18: + vlr %v16,%v18 +.Lremaining_v16: + /* v16 contains the remaining bytes [1...16]. + Store remaining bytes and append string-termination. */ + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + slgrk %r7,%r4,%r5 /* Remaining bytes = maxlen - current_len */ + aghi %r7,-1 /* vstl needs highest index. */ + la %r2,0(%r5,%r2) /* vstl has no index register. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + /* Zero in remaining bytes? -> jump away (zero-index <= max-index). */ + clrjle %r1,%r7,.Lfound_v16_store + vstl %v16,%r7,0(%r2) /* Store remaining bytes without null + termination! */ +.Lend: + /* Restore saved registers. */ + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lfound_v16_32: + aghi %r5,32 + j .Lfound_v16 +.Lfound_v18_48: + aghi %r5,32 +.Lfound_v18_16: + aghi %r5,16 +.Lfound_v18: + vlr %v16,%v18 +.Lfound_v16: + /* v16 contains a zero. Store remaining bytes to zero. current_len + has not reached border, thus checking for n is not needed! */ + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + la %r2,0(%r5,%r2) /* vstl has no support for index-register. */ +.Lfound_v16_store: + vstl %v16,%r1,0(%r2) /* Copy characters including zero. */ + /* Fill remaining bytes with zero - remaining count always > 0. */ + algr %r5,%r1 /* Remaining bytes (=%r4) = ... */ + slgr %r4,%r5 /* = maxlen - (currlen + zero_index + 1) */ + la %r2,0(%r1,%r2) /* Pointer to zero. start filling beyond. */ + lgr %r0,%r2 /* Save return-pointer to found zero. */ + clgije %r4,1,.Lend /* Skip zero-filling, if found zero is last + possible character. + (1 is substracted from r4 below!). */ + aghi %r4,-2 /* mvc with exrl needs count - 1. + (additional -1, see remaining bytes above) */ + srlg %r6,%r4,8 /* Split into 256 byte blocks. */ + ltgr %r6,%r6 + je .Lzero_lt256 +.Lzero_loop256: + mvc 1(256,%r2),0(%r2) /* Fill 256 zeros at once. */ + la %r2,256(%r2) + brctg %r6,.Lzero_loop256 /* Loop until all blocks are processed. */ +.Lzero_lt256: + exrl %r4,.Lmvc_lt256 + j .Lend +.Lmvc_lt256: + mvc 1(1,%r2),0(%r2) + +.Lloop64: + vl %v16,0(%r5,%r3) + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Save previous part without zero to dst. */ + vfenezbs %v17,%v18,%v18 + je .Lfound_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezbs %v17,%v16,%v16 + je .Lfound_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezbs %v17,%v18,%v18 + je .Lfound_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lloop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Llt64 +END(__stpncpy_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/stpncpy.c b/REORG.TODO/sysdeps/s390/multiarch/stpncpy.c new file mode 100644 index 0000000000..74f5ddc25e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/stpncpy.c @@ -0,0 +1,32 @@ +/* Multiple versions of stpncpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define stpncpy __redirect_stpncpy +# define __stpncpy __redirect___stpncpy +# include <string.h> +# undef stpncpy +# undef __stpncpy +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc_redirected (__redirect___stpncpy, __stpncpy) +weak_alias (__stpncpy, stpncpy) + +#else +# include <string/stpncpy.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcat-c.c b/REORG.TODO/sysdeps/s390/multiarch/strcat-c.c new file mode 100644 index 0000000000..0b88c1fc28 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcat-c.c @@ -0,0 +1,28 @@ +/* Default strcat implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRCAT __strcat_c +# ifdef SHARED +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strcat_c, __GI_strcat, __strcat_c); +# endif /* SHARED */ + +# include <string/strcat.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcat-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strcat-vx.S new file mode 100644 index 0000000000..65c19c21c8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcat-vx.S @@ -0,0 +1,161 @@ +/* Vector optimized 32/64 bit S/390 version of strcat. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char * strcat (const char *dest, const char *src) + Concatenate two strings. + + Register usage: + -r0=saved dest pointer for return + -r1=tmp + -r2=dest + -r3=src + -r4=tmp + -r5=current_len + -v16=part of src + -v17=index of zero + -v18=part of src +*/ +ENTRY(__strcat_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + lgr %r0,%r2 /* Save destination pointer for return. */ + + /* STRLEN + r1 = loaded bytes (tmp) + r4 = zero byte index (tmp) + r2 = dst + */ + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfenezb %v16,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v16,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Llen_end /* Found zero within loaded bytes, end. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r1 /* Compute bytes to 16bytes boundary. */ + + /* Find zero in 16byte aligned loop. */ +.Llen_loop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezbs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Llen_found /* Jump away if zero was found. */ + vl %v16,16(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Llen_found16 + vl %v16,32(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Llen_found32 + vl %v16,48(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Llen_found48 + + aghi %r5,64 + j .Llen_loop /* No zero -> loop. */ + +.Llen_found48: + aghi %r5,16 +.Llen_found32: + aghi %r5,16 +.Llen_found16: + aghi %r5,16 +.Llen_found: + vlgvb %r4,%v16,7 /* Load byte index of zero. */ + algr %r5,%r4 + +.Llen_end: + /* STRCPY + %r1 = loaded bytes (tmp) + %r4 = zero byte index (tmp) + %r3 = curr src pointer + %r2 = curr dst pointer + */ + la %r2,0(%r5,%r2) /* strcpy at end of dst-string. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Lcpy_found_align /* If found zero within loaded bytes, + copy bytes before and return. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r4 /* Compute highest index to 16byte boundary. */ + + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Find zero in 16byte aligned loop. */ +.Lcpy_loop: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lcpy_found_v16_0 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3)/* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezbs %v17,%v18,%v18 + je .Lcpy_found_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezbs %v17,%v16,%v16 + je .Lcpy_found_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezbs %v17,%v18,%v18 + je .Lcpy_found_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + j .Lcpy_loop /* No zero -> loop. */ + +.Lcpy_found_v16_32: + aghi %r5,32 +.Lcpy_found_v16_0: + la %r4,0(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + vstl %v16,%r1,0(%r4) /* Copy characters including zero. */ + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lcpy_found_v18_48: + aghi %r5,32 +.Lcpy_found_v18_16: + la %r4,16(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + vstl %v18,%r1,0(%r4) /* Copy characters including zero. */ + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lcpy_found_align: + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 +END(__strcat_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcat.c b/REORG.TODO/sysdeps/s390/multiarch/strcat.c new file mode 100644 index 0000000000..d1c5d4c55e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcat.c @@ -0,0 +1,29 @@ +/* Multiple versions of strcat. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strcat __redirect_strcat +# include <string.h> +# undef strcat +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strcat, __strcat, strcat) + +#else +# include <string/strcat.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strchr-c.c b/REORG.TODO/sysdeps/s390/multiarch/strchr-c.c new file mode 100644 index 0000000000..636d8dd016 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strchr-c.c @@ -0,0 +1,29 @@ +/* Default strchr implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRCHR __strchr_c +# undef weak_alias +# ifdef SHARED +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strchr_c, __GI_strchr, __strchr_c); +# endif /* SHARED */ + +# include <string/strchr.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strchr-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strchr-vx.S new file mode 100644 index 0000000000..bd2109bc05 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strchr-vx.S @@ -0,0 +1,100 @@ +/* Vector optimized 32/64 bit S/390 version of strchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char *strchr (const char *s, int c) + Locate character in string. + + Register usage: + -r1=tmp + -r2=s + -r3=c + -r4=tmp + -r5=current_len + -v16=part of s + -v17=index of unequal + -v18=replicated c +*/ +ENTRY(__strchr_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + lghi %r5,0 /* current_len = 0. */ + + vlvgb %v18,%r3,0 /* Generate vector which elements are all c. + If c > 255, c will be truncated. */ + vrepb %v18,%v18,0 + + vfeezbs %v16,%v16,%v18 /* Find element equal with zero search. */ + vlgvb %r4,%v16,7 /* Load byte index of character or zero. */ + clrjl %r4,%r1,.Lfound /* Return if c/zero is in loaded bytes. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ + + /* Find c/zero in 16 byte aligned loop */ +.Lloop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfeezbs %v16,%v16,%v18 /* Find element equal with zero search. */ + jno .Lfound /* Found c/zero (cc=0|1|2). */ + vl %v16,16(%r5,%r2) + vfeezbs %v16,%v16,%v18 + jno .Lfound16 + vl %v16,32(%r5,%r2) + vfeezbs %v16,%v16,%v18 + jno .Lfound32 + vl %v16,48(%r5,%r2) + vfeezbs %v16,%v16,%v18 + jno .Lfound48 + + aghi %r5,64 + j .Lloop /* No character and no zero -> loop. */ + +.Lfound48: + la %r5,16(%r5) /* Use la since aghi would clobber cc. */ +.Lfound32: + la %r5,16(%r5) +.Lfound16: + la %r5,16(%r5) +.Lfound: + je .Lzero /* Found zero, but no c before that zero. */ + +.Lcharacter: + vlgvb %r4,%v16,7 /* Load byte index of character. */ + algr %r5,%r4 + la %r2,0(%r5,%r2) /* Return pointer to character. */ + br %r14 + +.Lzero: + llgcr %r3,%r3 /* char c_char = (char) c. */ + clije %r3,0,.Lcharacter /* Found zero and c is zero. */ + lghi %r2,0 /* Return null if character not found. */ + br %r14 +END(__strchr_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strchr.c b/REORG.TODO/sysdeps/s390/multiarch/strchr.c new file mode 100644 index 0000000000..3df90aff14 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strchr.c @@ -0,0 +1,32 @@ +/* Multiple versions of strchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strchr __redirect_strchr +/* Omit the strchr inline definitions because it would redefine strchr. */ +# define __NO_STRING_INLINES +# include <string.h> +# undef strchr +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strchr, __strchr, strchr) +weak_alias (strchr, index) + +#else +# include <string/strchr.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strchrnul-c.c b/REORG.TODO/sysdeps/s390/multiarch/strchrnul-c.c new file mode 100644 index 0000000000..cd43d3a450 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strchrnul-c.c @@ -0,0 +1,26 @@ +/* Default strchrnul implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRCHRNUL __strchrnul_c +# define __strchrnul STRCHRNUL +# undef weak_alias +# define weak_alias(name, alias) + +# include <string/strchrnul.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/strchrnul-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strchrnul-vx.S new file mode 100644 index 0000000000..cfc8cbf6e9 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strchrnul-vx.S @@ -0,0 +1,93 @@ +/* Vector optimized 32/64 bit S/390 version of strchrnul. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char *strchrnul (const char *s, int c) + Returns pointer to first c or to \0 if c not found. + + Register usage: + -r1=tmp + -r2=s and return pointer + -r3=c + -r4=tmp + -r5=current_len + -v16=part of s + -v18=vector with c replicated in every byte +*/ +ENTRY(__strchrnul_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + lghi %r5,0 /* current_len = 0. */ + + vlvgb %v18,%r3,0 /* Generate vector which elements are all c. + If c > 255, c will be truncated. */ + vrepb %v18,%v18,0 + + vfeezbs %v16,%v16,%v18 /* Find element equal with zero search. */ + vlgvb %r4,%v16,7 /* Load byte index of character or zero. */ + clrjl %r4,%r1,.Lfound /* Return if c/zero is in loaded bytes. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ + + /* Find c/zero in 16byte aligned loop */ +.Lloop: + vl %v16,0(%r5,%r2) /* Load s */ + vfeezbs %v16,%v16,%v18 /* Find element equal with zero search. */ + jno .Lfound /* Found c/zero (cc=0|1|2). */ + vl %v16,16(%r5,%r2) + vfeezbs %v16,%v16,%v18 + jno .Lfound16 + vl %v16,32(%r5,%r2) + vfeezbs %v16,%v16,%v18 + jno .Lfound32 + vl %v16,48(%r5,%r2) + vfeezbs %v16,%v16,%v18 + jno .Lfound48 + + aghi %r5,64 + j .Lloop /* No character and no zero -> loop. */ + + /* Found character or zero */ +.Lfound48: + aghi %r5,16 +.Lfound32: + aghi %r5,16 +.Lfound16: + aghi %r5,16 +.Lfound: + vlgvb %r1,%v16,7 /* Load byte index of character. */ + algr %r5,%r1 + la %r2,0(%r5,%r2) /* Return pointer to character. */ + +.Lend: + br %r14 +END(__strchrnul_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strchrnul.c b/REORG.TODO/sysdeps/s390/multiarch/strchrnul.c new file mode 100644 index 0000000000..9447523f25 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strchrnul.c @@ -0,0 +1,28 @@ +/* Multiple versions of strchrnul. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <string.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__strchrnul) +weak_alias (__strchrnul, strchrnul) + +#else +# include <string/strchrnul.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcmp-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strcmp-vx.S new file mode 100644 index 0000000000..640e4d6b4c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcmp-vx.S @@ -0,0 +1,116 @@ +/* Vector optimized 32/64 bit S/390 version of strcmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* int strcmp (const char *s1, const char *s2) + Compare two strings + + Register usage: + -r1=loaded byte count s1 + -r2=s1 + -r3=s2 + -r4=loaded byte coutn s2, tmp + -r5=current_len + -v16=part of s1 + -v17=part of s2 + -v18=index of unequal +*/ +ENTRY(__strcmp_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + lghi %r5,0 /* current_len = 0. */ + +.Lloop: + vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */ + vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */ + lcbb %r1,0(%r5,%r2),6 /* Get loaded byte count of s1. */ + jo .Llt16_1 /* Jump away if vr is not fully loaded. */ + lcbb %r4,0(%r5,%r3),6 + jo .Llt16_2 /* Jump away if vr is not fully loaded. */ + /* Both vrs are fully loaded. */ + aghi %r5,16 + vfenezbs %v18,%v16,%v17 /* Compare not equal with zero search. */ + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r1,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r4,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezbs %v18,%v16,%v17 + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r1,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r4,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezbs %v18,%v16,%v17 + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r1,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r4,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezbs %v18,%v16,%v17 + jno .Lfound + j .Lloop + +.Llt16_1: + lcbb %r4,0(%r5,%r3),6 /* Get loaded byte count of s2. */ +.Llt16_2: + clr %r1,%r4 + locrh %r1,%r4 /* Get minimum of bytes loaded in s1/2. */ + algfr %r5,%r1 /* Add smallest loaded bytes to current_len. */ + vfenezbs %v18,%v16,%v17 /* Compare not equal with zero search. */ + vlgvb %r4,%v18,7 /* Get not equal index or 16 if all equal. */ + clrjl %r4,%r1,.Lfound /* Jump away if miscompare is within loaded + bytes. */ + j .Lloop + +.Lfound: + je .Lend_equal + lghi %r2,1 + lghi %r1,-1 + locgrl %r2,%r1 + br %r14 +.Lend_equal: + lghi %r2,0 + br %r14 +END(__strcmp_vx) + +# define strcmp __strcmp_c +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) strong_alias(__strcmp_c, __GI_strcmp) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ + +#include <strcmp.S> diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcmp.c b/REORG.TODO/sysdeps/s390/multiarch/strcmp.c new file mode 100644 index 0000000000..19e6d02597 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcmp.c @@ -0,0 +1,29 @@ +/* Multiple versions of strcmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strcmp __redirect_strcmp +/* Omit the strcmp inline definitions because it would redefine strcmp. */ +# define __NO_STRING_INLINES +# include <string.h> +# include <ifunc-resolve.h> +# undef strcmp + +s390_vx_libc_ifunc2_redirected (__redirect_strcmp, __strcmp, strcmp) + +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strcpy-vx.S new file mode 100644 index 0000000000..1ae9860a01 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcpy-vx.S @@ -0,0 +1,109 @@ +/* Vector optimized 32/64 bit S/390 version of strcpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char * strcpy (const char *dest, const char *src) + Copy string src to dest. + + Register usage: + -r1=tmp + -r2=dest and return_value + -r3=src + -r4=tmp + -r5=current_len + -v16=part of src + -v17=index of zero + -v18=part of src +*/ +ENTRY(__strcpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Lfound_align /* If found zero within loaded bytes, + copy bytes before and return. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r4 /* Compute highest index to 16byte boundary. */ + + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Find zero in 16byte aligned loop. */ +.Lloop: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16_0 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3)/* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezbs %v17,%v18,%v18 + je .Lfound_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezbs %v17,%v16,%v16 + je .Lfound_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezbs %v17,%v18,%v18 + je .Lfound_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + j .Lloop /* No zero found -> loop. */ + +.Lfound_v16_32: + aghi %r5,32 +.Lfound_v16_0: + la %r3,0(%r5,%r2) + vlgvb %r4,%v17,7 /* Load byte index of zero. */ + vstl %v16,%r4,0(%r3) /* Store characters including zero. */ + br %r14 + +.Lfound_v18_48: + aghi %r5,32 +.Lfound_v18_16: + la %r3,16(%r5,%r2) + vlgvb %r4,%v17,7 /* Load byte index of zero. */ + vstl %v18,%r4,0(%r3) /* Store characters including zero. */ + br %r14 + +.Lfound_align: + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + br %r14 +END(__strcpy_vx) + +/* Use mvst-strcpy-implementation as default implementation. */ +# define strcpy __strcpy_c +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) strong_alias(__strcpy_c, __GI_strcpy) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ + +/* Include mvst-strcpy-implementation in s390-32/s390-64 subdirectory. */ +#include <strcpy.S> diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcpy.c b/REORG.TODO/sysdeps/s390/multiarch/strcpy.c new file mode 100644 index 0000000000..5a5107690b --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcpy.c @@ -0,0 +1,27 @@ +/* Multiple versions of strcpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strcpy __redirect_strcpy +# include <string.h> +# undef strcpy +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strcpy, __strcpy, strcpy) + +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcspn-c.c b/REORG.TODO/sysdeps/s390/multiarch/strcspn-c.c new file mode 100644 index 0000000000..f67e30d031 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcspn-c.c @@ -0,0 +1,28 @@ +/* Default strcspn implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRCSPN __strcspn_c +# ifdef SHARED +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strcspn_c, __GI_strcspn, __strcspn_c); +# endif /* SHARED */ + +# include <string/strcspn.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcspn-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strcspn-vx.S new file mode 100644 index 0000000000..840d94ab10 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcspn-vx.S @@ -0,0 +1,281 @@ +/* Vector optimized 32/64 bit S/390 version of strcspn. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* size_t strcspn (const char *s, const char * reject) + The strcspn() function calculates the length of the initial segment + of s which consists entirely of characters not in reject. + + This method checks the length of reject string. If it fits entirely + in one vector register, a fast algorithm is used, which does not need + to check multiple parts of accept-string. Otherwise a slower full + check of accept-string is used. + + register overview: + r3: pointer to start of reject-string + r2: pointer to start of search-string + r0: loaded byte count of vlbb search-string + r4: found byte index + r1: current return len + v16: search-string + v17: reject-string + v18: temp-vreg + + ONLY FOR SLOW: + v19: first reject-string + v20: zero for preparing acc-vector + v21: global mask; 1 indicates a match between + search-string-vreg and any reject-character + v22: current mask; 1 indicates a match between + search-string-vreg and any reject-character in current acc-vreg + v24: one for result-checking of former string-part + v30, v31: for re-/storing registers r6, r8, r9 + r5: current len of reject-string + r6: zero-index in search-string or 16 if no zero + or min(zero-index, loaded byte count) + r8: >0, if former reject-string-part contains a zero, + otherwise =0; + r9: loaded byte count of vlbb reject-string +*/ +ENTRY(__strcspn_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + /* + Check if reject-string fits in one vreg: + ---------------------------------------- + */ + vlbb %v17,0(%r3),6 /* Load reject. */ + lghi %r1,0 /* Zero out current len. */ + lcbb %r0,0(%r3),6 + jo .Lcheck_onbb /* Special case if reject + lays on block-boundary. */ +.Lcheck_notonbb: + vistrbs %v17,%v17 /* Fill with zeros after first zero. */ + je .Lfast /* Zero found -> reject fits in one vreg. */ + j .Lslow /* No zero -> reject exceeds one vreg. */ + + +.Lcheck_onbb: + /* Reject lays on block-boundary. */ + vfenezb %v18,%v17,%v17 /* Search zero in loaded reject bytes. */ + vlgvb %r4,%v18,7 /* Get index of zero or 16 if not found. */ + clrjl %r4,%r0,.Lcheck_notonbb /* Zero index < loaded bytes count -> + Reject fits in one vreg; + Fill with zeros and proceed + with FAST. */ + vl %v17,0(%r3) /* Load reject, which exceeds loaded bytes. */ + j .Lcheck_notonbb /* Check if reject fits in one vreg. */ + + + /* + Search s for reject in one vreg + ------------------------------- + */ +.Lfast: + /* Complete reject-string in v17 and remaining bytes are zero. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfaezbs %v18,%v16,%v17,0 /* Find first element in v16 + unequal to any in v17 + or first zero element. */ + + vlgvb %r4,%v18,7 /* Load byte index of found element. */ + clrjl %r4,%r0,.Lfast_loop_found2 /* If found index is within loaded + bytes, return with found element + index (=equal count). */ + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r1,16 /* current_len = 16. */ + slr %r1,%r4 /* Compute bytes to 16bytes boundary. */ + + /* Process s in 16byte aligned loop. */ +.Lfast_loop: + vl %v16,0(%r1,%r2) /* Load search-string. */ + vfaezbs %v18,%v16,%v17,0 /* Find first element in v16 equal to any + in v17 or first zero element. */ + jno .Lfast_loop_found + + vl %v16,16(%r1,%r2) + vfaezbs %v18,%v16,%v17,0 + jno .Lfast_loop_found16 + + vl %v16,32(%r1,%r2) + vfaezbs %v18,%v16,%v17,0 + jno .Lfast_loop_found32 + + vl %v16,48(%r1,%r2) + vfaezbs %v18,%v16,%v17,0 + jno .Lfast_loop_found48 + + aghi %r1,64 + j .Lfast_loop /* Loop if no element was unequal to reject + and not zero. */ + + /* Found equal or zero element. */ +.Lfast_loop_found48: + aghi %r1,16 +.Lfast_loop_found32: + aghi %r1,16 +.Lfast_loop_found16: + aghi %r1,16 +.Lfast_loop_found: + vlgvb %r4,%v18,7 /* Load byte index of found element or zero. */ +.Lfast_loop_found2: + algrk %r2,%r1,%r4 /* Add found index to current len. */ + br %r14 + + + + /* + Search s for reject in multiple vregs + ------------------------------------- + */ +.Lslow: + /* Save registers. */ + vlvgg %v30,%r6,0 + vlvgp %v31,%r8,%r9 + + /* Reject in v17 without zero. */ + vlr %v19,%v17 /* Save first acc-part for a fast reload. */ + vzero %v20 /* Zero for preparing acc-vector. */ + vone %v24 /* One for checking result of former + string-part. */ + + /* Align s to 16 byte. */ + risbg %r4,%r2,60,128+63,0 /* Test if s is aligned and + %r4 = bits 60-63 'and' 15. */ + je .Lslow_loop_str /* If s is aligned, loop aligned. */ + lghi %r0,15 + slr %r0,%r4 /* Compute highest index to load (15-x). */ + vll %v16,%r0,0(%r2) /* Load up to 16 byte boundary (vll needs + highest index, remaining bytes are 0). */ + ahi %r0,1 /* Work with loaded byte count. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of reject-string to zero. */ + vfenezb %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first reject-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + clije %r6,0,.Lslow_end /* If first element is zero -> return 0. */ + clr %r0,%r6 /* cc==1 if loaded byte count < zero-index. */ + locrl %r6,%r0 /* Load on cc==1; zero-index = lbc. */ + j .Lslow_loop_acc + + + /* Process s in 16byte aligned loop. */ +.Lslow_next_str: + /* Check results of former processed str-part. */ + vfeeb %v18,%v21,%v24 /* Find first equal match in global mask + (ones in element). */ + vlgvb %r4,%v18,7 /* Get index of first one (=equal) or 16. */ + /* Equal-index < min(zero-index, loaded byte count) + -> Return pointer to equal element. */ + clrjl %r4,%r6,.Lslow_index_found + /* Zero-index < loaded byte count + -> Former str-part was last str-part + -> Return null */ + clrjl %r6,%r0,.Lslow_end_not_found + + /* All elements are zero (=no match) -> Proceed with next str-part. */ + vlr %v17,%v19 /* Load first part of reject (no zero). */ + algfr %r1,%r0 /* Add loaded byte count to current len. */ + +.Lslow_loop_str: + vl %v16,0(%r1,%r2) /* Load search-string. */ + lghi %r0,16 /* Loaded byte count is 16. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of reject to zero. */ + vfenezb %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first reject-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + clije %r6,0,.Lslow_end /* If first element is zero (end of string) + -> Return current length. */ + +.Lslow_loop_acc: + vfaeb %v22,%v16,%v17,4 /* Create matching-mask (1 in mask -> + Character matches any rejected character in + this reject-string-part) IN=0, RT=1. */ + vlgvb %r4,%v22,0 /* Get result of first element. */ + /* First element is equal to any rejected characters? + (all other parts of reject cannot lead to a match before this one) + -> Return current len, which is pointing to this element. */ + clijh %r4,0,.Lslow_end + vo %v21,%v21,%v22 /* Global-mask = global-|matching-mask. */ + /* Proceed with next acc until end of acc is reached. */ + + +.Lslow_next_acc: + clijh %r8,0,.Lslow_next_str /* There was a zero in last reject-part + -> Add found index to current len + and end. */ + vlbb %v17,16(%r5,%r3),6 /* Load next reject part. */ + aghi %r5,16 /* Increment current len of reject-string. */ + lcbb %r9,0(%r5,%r3),6 /* Get loaded byte count of reject-string. */ + jo .Lslow_next_acc_onbb /* Jump away if reject-string is + on block-boundary. */ +.Lslow_next_acc_notonbb: + vistrbs %v17,%v17 /* Fill with zeros after first zero. */ + jo .Lslow_loop_acc /* No zero found -> no preparation needed. */ + +.Lslow_next_acc_prepare_zero: + /* Zero in reject-part: fill zeros with first-reject-character. */ + vlgvb %r8,%v17,0 /* Load first element of reject-part. */ + clije %r8,0,.Lslow_next_str /* Process next str-part if first + character in this part of reject + is a zero. */ + /* r8>0 -> zero found in this acc-part. */ + vrepb %v18,%v17,0 /* Replicate first char accross all chars. */ + vceqb %v22,%v20,%v17 /* Create a mask (v22) of null chars + by comparing with 0 (v20). */ + vsel %v17,%v18,%v17,%v22 /* Replace null chars with first char. */ + j .Lslow_loop_acc /* Reject-string part is prepared. */ + +.Lslow_next_acc_onbb: + vfenezb %v18,%v17,%v17 /* Find zero in loaded bytes of reject part. */ + vlgvb %r8,%v18,7 /* Load byte index of zero. */ + clrjl %r8,%r9,.Lslow_next_acc_notonbb /* Found a zero in loaded bytes + -> Prepare vreg. */ + vl %v17,0(%r5,%r3) /* Load over boundary ... */ + lghi %r8,0 /* r8=0 -> no zero in this part of acc, + check for zero is in jump-target. */ + j .Lslow_next_acc_notonbb /* ... and search for zero in + fully loaded vreg again. */ + +.Lslow_end_not_found: + algfr %r1,%r6 /* Add zero-index to current len. */ + j .Lslow_end +.Lslow_index_found: + algfr %r1,%r4 /* Add found index of char to current len. */ +.Lslow_end: + lgr %r2,%r1 + /* Restore registers. */ + vlgvg %r6,%v30,0 + vlgvg %r8,%v31,0 + vlgvg %r9,%v31,1 + br %r14 +END(__strcspn_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strcspn.c b/REORG.TODO/sysdeps/s390/multiarch/strcspn.c new file mode 100644 index 0000000000..414f313c75 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strcspn.c @@ -0,0 +1,31 @@ +/* Multiple versions of strcspn. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strcspn __redirect_strcspn +/* Omit the strcspn inline definitions because it would redefine strcspn. */ +# define __NO_STRING_INLINES +# include <string.h> +# undef strcspn +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strcspn, __strcspn, strcspn) + +#else +# include <string/strcspn.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strlen-c.c b/REORG.TODO/sysdeps/s390/multiarch/strlen-c.c new file mode 100644 index 0000000000..b72366920c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strlen-c.c @@ -0,0 +1,28 @@ +/* Default strlen implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRLEN __strlen_c +# ifdef SHARED +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strlen_c, __GI_strlen, __strlen_c); +# endif /* SHARED */ + +# include <string/strlen.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strlen-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strlen-vx.S new file mode 100644 index 0000000000..a779d6521a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strlen-vx.S @@ -0,0 +1,84 @@ +/* Vector optimized 32/64 bit S/390 version of strlen. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* size_t strlen (const char *s) + Returns length of string s. + + Register usage: + -r1=bytes to 4k-byte boundary + -r2=s + -r3=tmp + -r4=tmp + -r5=current_len and return_value + -v16=part of s +*/ +ENTRY(__strlen_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfenezb %v16,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r4,%v16,7 /* Load zero index or 16 if not found. */ + clr %r4,%r1 /* If found zero within loaded bytes? */ + locgrl %r2,%r4 /* Then copy return value. */ + blr %r14 /* And return. */ + + /* Align s to 16 byte. */ + risbgn %r3,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r3 /* Compute bytes to 16bytes boundary. */ + + /* Find zero in 16 byte aligned loop. */ +.Lloop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezbs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound /* Jump away if zero was found. */ + vl %v16,16(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Lfound16 + vl %v16,32(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Lfound32 + vl %v16,48(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Lfound48 + + aghi %r5,64 + j .Lloop /* No zero found -> loop. */ + +.Lfound48: + aghi %r5,16 +.Lfound32: + aghi %r5,16 +.Lfound16: + aghi %r5,16 +.Lfound: + vlgvb %r2,%v16,7 /* Load byte index of zero. */ + algr %r2,%r5 + br %r14 +END(__strlen_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strlen.c b/REORG.TODO/sysdeps/s390/multiarch/strlen.c new file mode 100644 index 0000000000..615274e4b8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strlen.c @@ -0,0 +1,29 @@ +/* Multiple versions of strlen. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strlen __redirect_strlen +# include <string.h> +# include <ifunc-resolve.h> +# undef strlen + +s390_vx_libc_ifunc2_redirected (__redirect_strlen, __strlen, strlen) + +#else +# include <string/strlen.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strncat-c.c b/REORG.TODO/sysdeps/s390/multiarch/strncat-c.c new file mode 100644 index 0000000000..e72d778fb4 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strncat-c.c @@ -0,0 +1,23 @@ +/* Default strncat implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRNCAT __strncat_c + +# include <string/strncat.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/strncat-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strncat-vx.S new file mode 100644 index 0000000000..c41509ceb5 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strncat-vx.S @@ -0,0 +1,239 @@ +/* Vector optimized 32/64 bit S/390 version of strncat. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char * strncat (const char *dest, const char *src, size_t n) + Concatenate two strings - at most n characters of src. + + Register usage: + -r0=saved dest pointer for return + -r1=tmp + -r2=dest + -r3=src + -r4=n + -r5=current_len + -r6=tmp + -r7=tmp + -v16=part of src + -v17=index of zero + -v18=part of src + -v31=register save area for r6, r7 +*/ +ENTRY(__strncat_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgfi %r4,0 + ber %r14 /* Nothing to do, if n == 0. */ + lgr %r0,%r2 /* Save destination pointer for return. */ + vlvgp %v31,%r6,%r7 /* Save registers. */ + + /* STRLEN + %r1 = loaded bytes (tmp) + %r6 = zero byte index (tmp) + %r2 = dst + */ + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfenezb %v16,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v16,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Llen_end /* Found zero within loaded bytes, end. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r1 /* Compute bytes to 16bytes boundary. */ + + /* Find zero in 16byte aligned loop. */ +.Llen_loop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezbs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Llen_found /* Jump away if zero was found. */ + vl %v16,16(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Llen_found16 + vl %v16,32(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Llen_found32 + vl %v16,48(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Llen_found48 + + aghi %r5,64 + j .Llen_loop /* No zero -> loop. */ + +.Llen_found48: + aghi %r5,16 +.Llen_found32: + aghi %r5,16 +.Llen_found16: + aghi %r5,16 +.Llen_found: + vlgvb %r1,%v16,7 /* Load byte index of zero. */ + algr %r5,%r1 + +.Llen_end: + /* STRCPY + %r1 = zero byte index (tmp) + %r6 = loaded bytes (tmp) + %r3 = curr src pointer + %r2 = curr dst pointer + %r7 = border, tmp + */ + la %r2,0(%r5,%r2) /* strcpy at end of dst-string. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r6,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r6,%r6 /* Convert 32bit to 64bit. */ + + lghi %r5,0 /* current_len = 0. */ + + clgrjle %r4,%r6,.Lcpy_remaining_v16 /* If n <= loaded-bytes + -> process remaining. */ + + /* n > loaded-byte-count. */ + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r1,%r6,.Lcpy_found_v16_store /* Found zero within loaded + bytes, copy and return. */ + + /* Align s to 16 byte. */ + risbgn %r7,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r7 /* Compute highest index to 16byte boundary. */ + + /* Zero not found and n > loaded-byte-count. */ + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* + Now we are 16byte aligned, so we can load a full vreg + without page fault. + */ + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lcpy_loop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + clgijl %r4,17,.Lcpy_remaining_v16 /* If n <=16, + process remaining bytes. */ +.Lcpy_lt64: + lgr %r7,%r4 + slgfi %r7,16 /* border_len = n - 16. */ + + /* If current_len >= border then process remaining bytes. */ + clgrjhe %r5,%r7,.Lcpy_remaining_v16 + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lcpy_found_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + aghi %r5,16 + + clgrjhe %r5,%r7,.Lcpy_remaining_v18 + vfenezbs %v17,%v18,%v18 + je .Lcpy_found_v18 + vl %v16,16(%r5,%r3) + vst %v18,0(%r5,%r2) + aghi %r5,16 + + clgrjhe %r5,%r7,.Lcpy_remaining_v16 + vfenezbs %v17,%v16,%v16 + je .Lcpy_found_v16 + vl %v18,16(%r5,%r3) + vst %v16,0(%r5,%r2) + aghi %r5,16 + +.Lcpy_remaining_v18: + vlr %v16,%v18 +.Lcpy_remaining_v16: + /* v16 contains the remaining bytes [1...16]. + Store remaining bytes and append string-termination. */ + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + slgrk %r7,%r4,%r5 /* Remaining bytes = maxlen - current_len. */ + aghi %r7,-1 /* vstl needs highest index. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + la %r2,0(%r5,%r2) /* vstl has no index register. */ + /* Zero-index within remaining-bytes, store up to zero and end. */ + clgrjle %r1,%r7,.Lcpy_found_v16_store + vstl %v16,%r7,0(%r2) /* Store remaining bytes. */ + lghi %r1,0 + stc %r1,1(%r7,%r2) /* Store string-null-termination beyond n. */ +.Lcpy_end: + /* Restore saved registers. */ + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lcpy_found_v16_32: + aghi %r5,32 + j .Lcpy_found_v16 +.Lcpy_found_v18_48: + aghi %r5,32 +.Lcpy_found_v18_16: + aghi %r5,16 +.Lcpy_found_v18: + vlr %v16,%v18 +.Lcpy_found_v16: + /* v16 contains a zero. Store remaining bytes to zero. current_len + has not reached border, thus checking for n is not needed! */ + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + la %r2,0(%r5,%r2) +.Lcpy_found_v16_store: + vstl %v16,%r1,0(%r2) /* Copy characters including zero. */ + j .Lcpy_end + + /* Find zero in 16byte aligned loop. */ +.Lcpy_loop64: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lcpy_found_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezbs %v17,%v18,%v18 + je .Lcpy_found_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezbs %v17,%v16,%v16 + je .Lcpy_found_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezbs %v17,%v18,%v18 + je .Lcpy_found_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lcpy_loop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Lcpy_lt64 +END(__strncat_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strncat.c b/REORG.TODO/sysdeps/s390/multiarch/strncat.c new file mode 100644 index 0000000000..d931ca6c85 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strncat.c @@ -0,0 +1,27 @@ +/* Multiple versions of strncat. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <string.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2 (__strncat, strncat) + +#else +# include <string/strncat.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strncmp-c.c b/REORG.TODO/sysdeps/s390/multiarch/strncmp-c.c new file mode 100644 index 0000000000..fddd5ed97e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strncmp-c.c @@ -0,0 +1,28 @@ +/* Default strncmp implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRNCMP __strncmp_c +# ifdef SHARED +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strncmp_c, __GI_strncmp, __strncmp_c); +# endif /* SHARED */ + +# include <string/strncmp.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strncmp-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strncmp-vx.S new file mode 100644 index 0000000000..ee35d2debf --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strncmp-vx.S @@ -0,0 +1,137 @@ +/* Vector optimized 32/64 bit S/390 version of strncmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* int strncmp (const char *s1, const char *s2, size_t n) + Compare at most n characters of two strings. + + Register usage: + -r0=tmp + -r1=tmp + -r2=s1 + -r3=s2 + -r4=n + -r5=current_len + -v16=part of s1 + -v17=part of s2 + -v18=index of unequal +*/ +ENTRY(__strncmp_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgije %r4,0,.Lend_equal /* Nothing to do if n == 0, */ + lghi %r5,0 /* current_len = 0. */ + +.Lloop: + vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */ + vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */ + lcbb %r0,0(%r5,%r2),6 /* Get loaded byte count of s1. */ + jo .Llt16_1 /* Jump away if vr is not fully loaded. */ + lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count of s2. */ + jo .Llt16_2 /* Jump away if vr is not fully loaded. */ + aghi %r5,16 /* Both vrs are fully loaded. */ + clgrjhe %r5,%r4,.Llastcmp /* If current_len >= n ->last compare. */ + vfenezbs %v18,%v16,%v17 /* Compare not equal with zero search. */ + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r0,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r1,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp + vfenezbs %v18,%v16,%v17 + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r0,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r1,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp + vfenezbs %v18,%v16,%v17 + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r0,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r1,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp + vfenezbs %v18,%v16,%v17 + jno .Lfound + j .Lloop + +.Llt16_1: + lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count ofs2. */ +.Llt16_2: + clr %r0,%r1 /* Compare logical. */ + locrh %r0,%r1 /* Compute minimum of bytes loaded. */ + algfr %r5,%r0 /* Add smallest loaded bytes to current_len. */ + clgrj %r5,%r4,10,.Llastcmp /* If current_len >= n ->last compare. */ + vfenezbs %v18,%v16,%v17 /* Compare not equal with zero search. */ + vlgvb %r1,%v18,7 /* Get not equal index or 16 if all equal. */ + clrjl %r1,%r0,.Lfound /* Jump away if miscompare is within + loaded bytes (index < loaded-bytes) */ + j .Lloop + +.Llastcmp: + /* Use comparision result only if located within first n characters. + %r0: loaded byte count in vreg; + %r5: current_len; + %r4: n; + (current_len - n): [0...16[ + First ignored match index: loaded bytes - (current_len-n): ]0...16] + */ + slgr %r5,%r4 /* %r5 = current_len - n. */ + slr %r0,%r5 /* %r0 = first ignored match index. */ + vfenezbs %v18,%v16,%v17 /* Compare not equal with zero search. */ + vlgvb %r1,%v18,7 /* Get not equal index or 16 if all equal. */ + clrjl %r1,%r0,.Lfound /* Jump away if miscompare is within + loaded bytes and below n bytes. */ + j .Lend_equal /* Miscompare after n-bytes -> end equal. */ + +.Lfound: + /* Difference or end of string. */ + je .Lend_equal + lghi %r2,1 + lghi %r1,-1 + locgrl %r2,%r1 + br %r14 +.Lend_equal: + lghi %r2,0 + br %r14 +END(__strncmp_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strncmp.c b/REORG.TODO/sysdeps/s390/multiarch/strncmp.c new file mode 100644 index 0000000000..c97753cc70 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strncmp.c @@ -0,0 +1,31 @@ +/* Multiple versions of strncmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strncmp __redirect_strncmp +/* Omit the strncmp inline definitions because it would redefine strncmp. */ +# define __NO_STRING_INLINES +# include <string.h> +# undef strncmp +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strncmp, __strncmp, strncmp) + +#else +# include <string/strncmp.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strncpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strncpy-vx.S new file mode 100644 index 0000000000..4f58977b9b --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strncpy-vx.S @@ -0,0 +1,207 @@ +/* Vector optimized 32/64 bit S/390 version of strncpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char * strncpy (const char *dest, const char *src, size_t n) + Copy at most n characters of string src to dest. + + Register usage: + -r0=dest pointer for return + -r1=tmp, zero byte index + -r2=dest + -r3=src + -r4=n + -r5=current_len + -r6=tmp, loaded bytes + -r7=tmp, border + -v16=part of src + -v17=index of zero + -v18=part of src + -v31=register save area for r6, r7 +*/ +ENTRY(__strncpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgfi %r4,0 + ber %r14 /* Nothing to do, if n == 0. */ + lgr %r0,%r2 /* Save destination pointer for return. */ + vlvgp %v31,%r6,%r7 /* Save registers. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r6,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r6,%r6 /* Convert 32bit to 64bit. */ + + lghi %r5,0 /* current_len = 0. */ + + clgrjle %r4,%r6,.Lremaining_v16 /* If n <= loaded-bytes + -> process remaining. */ + + /* n > loaded-byte-count. */ + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r1,%r6,.Lfound_v16_store /* Found zero within loaded bytes, + copy and return. */ + + /* Align s to 16 byte. */ + risbgn %r7,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r7 /* Compute highest index to 16byte boundary. */ + + /* Zero not found and n > loaded-byte-count. */ + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Now we are 16byte aligned, so we can load + a full vreg without page fault. */ + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lloop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + clgijl %r4,17,.Lremaining_v16 /* If n <= 16, process remaining + bytes. */ +.Llt64: + lgr %r7,%r4 + slgfi %r7,16 /* border_len = n - 16. */ + + clgrjhe %r5,%r7,.Lremaining_v16 /* If current_len >= border + then process remaining bytes. */ + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + aghi %r5,16 + + clgrjhe %r5,%r7,.Lremaining_v18 + vfenezbs %v17,%v18,%v18 + je .Lfound_v18 + vl %v16,16(%r5,%r3) + vst %v18,0(%r5,%r2) + aghi %r5,16 + + clgrjhe %r5,%r7,.Lremaining_v16 + vfenezbs %v17,%v16,%v16 + je .Lfound_v16 + vl %v18,16(%r5,%r3) + vst %v16,0(%r5,%r2) + aghi %r5,16 + +.Lremaining_v18: + vlr %v16,%v18 +.Lremaining_v16: + /* v16 contains the remaining bytes [1...16]. + Store remaining bytes and append string-termination. */ + vfenezb %v17,%v16,%v16 /* Find element not equal with zero search. */ + slgrk %r7,%r4,%r5 /* Remaining bytes = maxlen - current_len. */ + aghi %r7,-1 /* vstl needs highest index. */ + la %r2,0(%r5,%r2) /* vstl has no index register. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + /* Zero in remaining bytes? -> jump away (zero-index < max-index) + Do not jump away if zero-index == max-index, + but simply copy zero with vstl below. */ + clrjl %r1,%r7,.Lfound_v16_store + vstl %v16,%r7,0(%r2) /* Store remaining bytes without null + termination!. */ +.Lend: + /* Restore saved registers. */ + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + + +.Lfound_v16_32: + aghi %r5,32 + j .Lfound_v16 +.Lfound_v18_48: + aghi %r5,32 +.Lfound_v18_16: + aghi %r5,16 +.Lfound_v18: + vlr %v16,%v18 +.Lfound_v16: + /* v16 contains a zero. Store remaining bytes to zero. current_len + has not reached border, thus checking for n is not needed! */ + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + la %r2,0(%r5,%r2) /* vstl has no support for index-register. */ +.Lfound_v16_store: + vstl %v16,%r1,0(%r2) /* Copy characters including zero. */ + /* Fill remaining bytes with zero - remaining count always > 0. */ + algr %r5,%r1 /* Remaining bytes (=%r4) = ... */ + slgr %r4,%r5 /* = n - (current_len + zero_index + 1). */ + la %r2,0(%r1,%r2) /* Pointer to zero. start filling beyond. */ + aghi %r4,-2 /* mvc with exrl needs count - 1. + (additional -1, see remaining bytes above) */ + srlg %r6,%r4,8 /* Split into 256 byte blocks. */ + ltgr %r6,%r6 + je .Lzero_lt256 +.Lzero_loop256: + mvc 1(256,%r2),0(%r2) /* Fill 256 zeros at once. */ + la %r2,256(%r2) + brctg %r6,.Lzero_loop256 /* Loop until all blocks are processed. */ +.Lzero_lt256: + exrl %r4,.Lmvc_lt256 + j .Lend +.Lmvc_lt256: + mvc 1(1,%r2),0(%r2) + +.Lloop64: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezbs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezbs %v17,%v18,%v18 + je .Lfound_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezbs %v17,%v16,%v16 + je .Lfound_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezbs %v17,%v18,%v18 + je .Lfound_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lloop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Llt64 +END(__strncpy_vx) + +# define strncpy __strncpy_c +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) strong_alias(__strncpy_c, __GI_strncpy) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ + +/* Include strncpy-implementation in s390-32/s390-64 subdirectory. */ +#include <strncpy.S> diff --git a/REORG.TODO/sysdeps/s390/multiarch/strncpy.c b/REORG.TODO/sysdeps/s390/multiarch/strncpy.c new file mode 100644 index 0000000000..d44b459093 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strncpy.c @@ -0,0 +1,29 @@ +/* Multiple versions of strncpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strncpy __redirect_strncpy +/* Omit the strncpy inline definitions because it would redefine strncpy. */ +# define __NO_STRING_INLINES +# include <string.h> +# undef strncpy +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strncpy, __strncpy, strncpy); + +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/strnlen-c.c b/REORG.TODO/sysdeps/s390/multiarch/strnlen-c.c new file mode 100644 index 0000000000..46e2cac342 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strnlen-c.c @@ -0,0 +1,30 @@ +/* Default strnlen implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRNLEN __strnlen_c +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__strnlen_c, __GI_strnlen, __strnlen_c); \ + strong_alias (__strnlen_c, __strnlen_c_1); \ + __hidden_ver1 (__strnlen_c_1, __GI___strnlen, __strnlen_c_1); +# endif /* SHARED */ + +# include <string/strnlen.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strnlen-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strnlen-vx.S new file mode 100644 index 0000000000..da83a0d4f0 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strnlen-vx.S @@ -0,0 +1,134 @@ +/* Vector optimized 32/64 bit S/390 version of strnlen. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* size_t strnlen (const char *s, size_t maxlen) + Returns the number of characters in s or at most maxlen. + + Register usage: + -r1=tmp + -r2=address of string + -r3=maxlen (number of characters to be read) + -r4=tmp + -r5=current_len and return_value + -v16=part of s +*/ +ENTRY(__strnlen_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r3,%r3 +# endif /* !defined __s390x__ */ + + clgfi %r3,0 /* if maxlen == 0, return 0. */ + locgre %r2,%r3 + ber %r14 + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r1,%r1 /* Convert 32bit to 64bit. */ + + vfenezb %v16,%v16,%v16 /* Find element not equal with zero search. */ + clgr %r1,%r3 + locgrh %r1,%r3 /* loaded_byte_count + = min (loaded_byte_count, maxlen) */ + + vlgvb %r5,%v16,7 /* Load zero index or 16 if not found. */ + clr %r5,%r1 /* If found zero within loaded bytes? */ + locgrl %r2,%r5 /* Then copy return value. */ + blr %r14 /* And return. */ + + clgr %r1,%r3 /* If loaded_byte_count == maxlen? */ + locgre %r2,%r3 /* Then copy return value. */ + ber %r14 /* And return. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ + + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r3,.Lloop64 + + /* Find zero in max 64byte with aligned s. */ +.Llt64: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezbs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound /* Jump away if zero was found. */ + aghi %r5,16 + clgrjhe %r5,%r3,.Lfound /* current_len >= maxlen -> end. */ + vl %v16,0(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Lfound + aghi %r5,16 + clgrjhe %r5,%r3,.Lfound + vl %v16,0(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Lfound + aghi %r5,16 + clgrjhe %r5,%r3,.Lfound + vl %v16,0(%r5,%r2) + vfenezbs %v16,%v16,%v16 + j .Lfound + +.Lfound48: + aghi %r5,16 +.Lfound32: + aghi %r5,16 +.Lfound16: + aghi %r5,16 +.Lfound: + vlgvb %r4,%v16,7 /* Load byte index of zero or 16 if no zero. */ + algr %r5,%r4 + + clgr %r5,%r3 + locgrh %r5,%r3 /* Return min (current_len, maxlen). */ + lgr %r2,%r5 + br %r14 + + /* Find zero in 16 byte aligned loop. */ +.Lloop64: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezbs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound /* Jump away if zero was found. */ + vl %v16,16(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Lfound16 + vl %v16,32(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Lfound32 + vl %v16,48(%r5,%r2) + vfenezbs %v16,%v16,%v16 + je .Lfound48 + + aghi %r5,64 + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r3,.Lloop64 + + j .Llt64 +END(__strnlen_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strnlen.c b/REORG.TODO/sysdeps/s390/multiarch/strnlen.c new file mode 100644 index 0000000000..6ebcafbd16 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strnlen.c @@ -0,0 +1,32 @@ +/* Multiple versions of strnlen. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strnlen __redirect_strnlen +# define __strnlen __redirect___strnlen +# include <string.h> +# undef strnlen +# undef __strnlen +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc_redirected (__redirect___strnlen, __strnlen) +weak_alias (__strnlen, strnlen) + +#else +# include <string/strnlen.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strpbrk-c.c b/REORG.TODO/sysdeps/s390/multiarch/strpbrk-c.c new file mode 100644 index 0000000000..f099c0607f --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strpbrk-c.c @@ -0,0 +1,28 @@ +/* Default strpbrk implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRPBRK __strpbrk_c +# ifdef SHARED +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strpbrk_c, __GI_strpbrk, __strpbrk_c); +# endif /* SHARED */ + +# include <string/strpbrk.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strpbrk-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strpbrk-vx.S new file mode 100644 index 0000000000..dd24d5e9db --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strpbrk-vx.S @@ -0,0 +1,302 @@ +/* Vector optimized 32/64 bit S/390 version of strpbrk. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char *strpbrk (const char *s, const char * accept) + The strpbrk() function locates the first occurrence in the string s + of any of the characters in the string accept and returns a pointer + to that character or NULL if not found. + + This method checks the length of accept string. If it fits entirely + in one vector register, a fast algorithm is used, which does not need + to check multiple parts of accept-string. Otherwise a slower full + check of accept-string is used. + + register overview: + r3: pointer to start of accept-string + r2: pointer to start of search-string + r0: loaded byte count of vlbb search-string (32bit unsigned) + r4: found byte index (32bit unsigned) + r1: current return len (64bit unsigned) + v16: search-string + v17: accept-string + v18: temp-vreg + + ONLY FOR SLOW: + v19: first accept-string + v20: zero for preparing acc-vector + v21: global mask; 1 indicates a match between + search-string-vreg and any accept-character + v22: current mask; 1 indicates a match between + search-string-vreg and any accept-character in current acc-vreg + v24: one for result-checking of former string-part + v30, v31: for re-/storing registers r6, r8, r9 + r5: current len of accept-string + r6: zero-index in search-string or 16 if no zero + or min(zero-index, loaded byte count) + r8: >0, if former accept-string-part contains a zero, + otherwise =0; + r9: loaded byte count of vlbb accept-string +*/ +ENTRY(__strpbrk_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + /* + Check if accept-string fits in one vreg: + ---------------------------------------- + */ + vlbb %v17,0(%r3),6 /* Load accept. */ + lghi %r1,0 /* Zero out current len. */ + vlgvb %r0,%v17,0 /* Get first element. */ + clije %r0,0,.Lfast_end_null /* Return null if accept is empty. */ + lcbb %r0,0(%r3),6 + jo .Lcheck_onbb /* Special case if accept lays + on block-boundary. */ +.Lcheck_notonbb: + vistrbs %v17,%v17 /* Fill with zeros after first zero. */ + je .Lfast /* Zero found -> accept fits in one vreg. */ + j .Lslow /* No zero -> accept exceeds one vreg */ + + +.Lcheck_onbb: + /* Accept lays on block-boundary. */ + vfenezb %v18,%v17,%v17 /* Search zero in loaded accept bytes. */ + vlgvb %r4,%v18,7 /* Get index of zero or 16 if not found. */ + clrjl %r4,%r0,.Lcheck_notonbb /* Zero index < loaded bytes count -> + Accept fits in one vreg; + Fill with zeros and proceed + with FAST. */ + vl %v17,0(%r3) /* Load accept, which exceeds loaded bytes. */ + j .Lcheck_notonbb /* Check if accept fits in one vreg. */ + + + /* + Search s for accept in one vreg + ------------------------------- + */ +.Lfast: + /* Complete accept-string in v17 and remaining bytes are zero. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfaezbs %v18,%v16,%v17,0 /* Find first element in v16 unequal to any + in v17 or first zero element. */ + + vlgvb %r4,%v18,7 /* Load byte index of found element. */ + /* If found index is within loaded bytes, return with found + element index (=equal count). */ + clrjl %r4,%r0,.Lfast_loop_found2 + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r1,16 /* current_len = 16. */ + slr %r1,%r4 /* Compute bytes to 16bytes boundary. */ + + /* Process s in 16byte aligned loop. */ +.Lfast_loop: + vl %v16,0(%r1,%r2) /* Load search-string. */ + vfaezbs %v18,%v16,%v17,0 /* Find first element in v16 equal to any + in v17 or first zero element. */ + jno .Lfast_loop_found + + vl %v16,16(%r1,%r2) + vfaezbs %v18,%v16,%v17,0 + jno .Lfast_loop_found16 + + vl %v16,32(%r1,%r2) + vfaezbs %v18,%v16,%v17,0 + jno .Lfast_loop_found32 + + vl %v16,48(%r1,%r2) + vfaezbs %v18,%v16,%v17,0 + jno .Lfast_loop_found48 + + aghi %r1,64 + j .Lfast_loop /* Loop if no element was unequal to accept + and not zero. */ + + /* Found equal or zero element. */ +.Lfast_loop_found48: + aghi %r1,16 +.Lfast_loop_found32: + aghi %r1,16 +.Lfast_loop_found16: + aghi %r1,16 +.Lfast_loop_found: + vlgvb %r4,%v18,7 /* Load byte index of found element. */ +.Lfast_loop_found2: + vlgvb %r0,%v16,0(%r4) /* Get found element. */ + clije %r0,0,.Lfast_end_null /* Return null if no accept-char found */ + algfr %r1,%r4 /* Add found index of char to current len. */ + la %r2,0(%r1,%r2) /* And return pointer to first equal char. */ + br %r14 + +.Lfast_end_null: + lghi %r2,0 /* Return null if no character is equal. */ + br %r14 + + + + + /* + Search s for accept in multiple vregs + ------------------------------------- + */ +.Lslow: + /* Save registers. */ + vlvgg %v30,%r6,0 + vlvgp %v31,%r8,%r9 + + /* accept in v17 without zero. */ + vlr %v19,%v17 /* Save first acc-part for a fast reload. */ + vzero %v20 /* Zero for preparing acc-vector. */ + vone %v24 /* One for checking result of former string. */ + + /* Align s to 16 byte. */ + risbg %r4,%r2,60,128+63,0 /* Test if s is aligned and + %r4 = bits 60-63 'and' 15. */ + je .Lslow_loop_str /* If s is aligned, loop aligned. */ + lghi %r0,15 + slr %r0,%r4 /* Compute highest index to load (15-x). */ + vll %v16,%r0,0(%r2) /* Load up to 16 byte boundary (vll needs + highest index, remaining bytes are 0). */ + ahi %r0,1 /* Work with loaded byte count. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of accept-string to zero. */ + vfenezb %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first accept-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + clije %r6,0,.Lslow_end_null /* If first element is zero + (end of string) -> return null */ + clr %r0,%r6 /* cc==1 if loaded byte count < zero-index. */ + locrl %r6,%r0 /* Load on cc==1; zero-index = lbc. */ + j .Lslow_loop_acc + + + /* Process s in 16byte aligned loop. */ +.Lslow_next_str: + /* Check results of former processed str-part. */ + vfeeb %v18,%v21,%v24 /* Find first equal match in global mask + (ones in element). */ + vlgvb %r4,%v18,7 /* Get index of first one (=equal) + or 16 if no match. */ + /* Equal-index < min(zero-index, loaded byte count) + -> return pointer to equal element. */ + clrjl %r4,%r6,.Lslow_index_found + /* Zero-index < loaded byte count + -> former str-part was last str-part + -> return null */ + clrjl %r6,%r0,.Lslow_end_null + /* All elements are zero (=no match) -> proceed with next str-part. */ + + vlr %v17,%v19 /* Load first part of accept (no zero). */ + algfr %r1,%r0 /* Add loaded byte count to current len. */ + +.Lslow_loop_str: + vl %v16,0(%r1,%r2) /* Load search-string */ + lghi %r0,16 /* Loaded byte count is 16. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of accept to zero. */ + vfenezb %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first accept-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + clije %r6,0,.Lslow_end_null /* If first element is zero + (end of string) -> return null. */ + +.Lslow_loop_acc: + vfaeb %v22,%v16,%v17,4 /* Create matching-mask (1 in mask -> + Character matches any accepted character in + this accept-string-part) IN=0, RT=1. */ + vlgvb %r4,%v22,0 /* Get result of first element. */ + /* First element is equal to any accepted characters + (all other parts of accept cannot lead to a match before this one) + -> current len is pointing to first element + -> return found */ + clijh %r4,0,.Lslow_end_found + vo %v21,%v21,%v22 /* Global-mask = global-|matching-mask. */ + /* Proceed with next acc until end of acc is reached. */ + + +.Lslow_next_acc: + clijh %r8,0,.Lslow_next_str /* There was a zero in the last acc-part + -> add index to current_len and + end. */ + vlbb %v17,16(%r5,%r3),6 /* Load next accept part. */ + aghi %r5,16 /* Increment current len of accept-string. */ + lcbb %r9,0(%r5,%r3),6 /* Get loaded byte count of accept-string. */ + jo .Lslow_next_acc_onbb /* Jump away ifaccept-string is + on block-boundary. */ +.Lslow_next_acc_notonbb: + vistrbs %v17,%v17 /* Fill with zeros after first zero. */ + jo .Lslow_loop_acc /* No zero found -> no preparation needed. */ + +.Lslow_next_acc_prepare_zero: + /* Zero in accept-part: fill zeros with first-accept-character. */ + vlgvb %r8,%v17,0 /* Load first element of acc-part. */ + clije %r8,0,.Lslow_next_str /* Proceed with next string-part, + if first char in this part of accept + is a zero. */ + /* r8>0 -> zero found in this acc-part. */ + vrepb %v18,%v17,0 /* Replicate first char accross all chars. */ + vceqb %v22,%v20,%v17 /* Create a mask (v22) of null chars + by comparing with 0 (v20). */ + vsel %v17,%v18,%v17,%v22 /* Replace null chars with first char. */ + j .Lslow_loop_acc /* Accept part is prepared -> process. */ + +.Lslow_next_acc_onbb: + vfenezb %v18,%v17,%v17 /* Find zero in loaded bytes of accept part. */ + vlgvb %r8,%v18,7 /* Load byte index of zero. */ + clrjl %r8,%r9,.Lslow_next_acc_notonbb /* Found a zero in loaded bytes + -> Prepare vreg. */ + vl %v17,0(%r5,%r3) /* Load over boundary ... */ + lghi %r8,0 /* r8=0 -> no zero in this part of acc, + check for zero is in jump-target. */ + j .Lslow_next_acc_notonbb /* ... and search for zero in + fully loaded vreg again. */ + +.Lslow_end_null: + lghi %r1,0 /* Return null if no character is equal. */ + j .Lslow_end + +.Lslow_loop_found: + vlgvb %r4,%v18,7 /* Load byte index of found element. */ + vlgvb %r0,%v16,0(%r4) /* Get found element. */ + clije %r0,0,.Lslow_end_null /* Return null if no acc-char found. */ + +.Lslow_index_found: + algfr %r1,%r4 /* Add found index of char to current len. */ +.Lslow_end_found: + la %r1,0(%r1,%r2) /* And return pointer to first equal char. */ + +.Lslow_end: + /* Restore registers. */ + vlgvg %r6,%v30,0 + vlgvg %r8,%v31,0 + vlgvg %r9,%v31,1 + lgr %r2,%r1 + br %r14 +END(__strpbrk_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strpbrk.c b/REORG.TODO/sysdeps/s390/multiarch/strpbrk.c new file mode 100644 index 0000000000..89bdb2b26c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strpbrk.c @@ -0,0 +1,31 @@ +/* Multiple versions of strpbrk. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strpbrk __redirect_strpbrk +/* Omit the strpbrk inline definitions because it would redefine strpbrk. */ +# define __NO_STRING_INLINES +# include <string.h> +# undef strpbrk +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strpbrk, __strpbrk, strpbrk) + +#else +# include <string/strpbrk.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strrchr-c.c b/REORG.TODO/sysdeps/s390/multiarch/strrchr-c.c new file mode 100644 index 0000000000..d1a8c4bd31 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strrchr-c.c @@ -0,0 +1,29 @@ +/* Default strrchr implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRRCHR __strrchr_c +# undef weak_alias +# ifdef SHARED +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strrchr_c, __GI_strrchr, __strrchr_c); +# endif /* SHARED */ + +# include <string/strrchr.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strrchr-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strrchr-vx.S new file mode 100644 index 0000000000..89a8f5f14c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strrchr-vx.S @@ -0,0 +1,180 @@ +/* Vector optimized 32/64 bit S/390 version of strrchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char *strrchr (const char *s, int c) + Locate the last character c in string. + + Register usage: + -r0=loaded bytes in first part of s. + -r1=pointer to last occurence of c or NULL if not found. + -r2=s + -r3=c + -r4=tmp + -r5=current_len + -v16=part of s + -v17=index of found element + -v18=replicated c + -v19=part of s with last occurence of c. + -v20=permute pattern +*/ +ENTRY(__strrchr_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vlvgb %v18,%r3,0 /* Generate vector which elements are all c. + if c > 255, c will be truncated. */ + vrepb %v18,%v18,0 + + lghi %r1,-1 /* Currently no c found. */ + lghi %r5,0 /* current_len = 0. */ + + vfeezbs %v17,%v16,%v18 /* Find element equal or zero. */ + vlgvb %r4,%v17,7 /* Load byte index of c/zero or 16. */ + clrjl %r4,%r0,.Lfound_first_part /* Found c/zero in loaded bytes. */ +.Lalign: + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ + +.Lloop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfeezbs %v17,%v16,%v18 /* Find element equal with zero search. */ + jno .Lfound /* Found c/zero (cc=0|1|2). */ + vl %v16,16(%r5,%r2) + vfeezbs %v17,%v16,%v18 + jno .Lfound16 + vl %v16,32(%r5,%r2) + vfeezbs %v17,%v16,%v18 + jno .Lfound32 + vl %v16,48(%r5,%r2) + vfeezbs %v17,%v16,%v18 + jno .Lfound48 + + aghi %r5,64 + j .Lloop /* No character and no zero -> loop. */ + +.Lfound48: + la %r5,16(%r5) /* Use la since aghi would clobber cc. */ +.Lfound32: + la %r5,16(%r5) +.Lfound16: + la %r5,16(%r5) +.Lfound: + je .Lzero /* Found zero, but no c before that zero. */ + /* Save this part of s to check for further matches after reaching + the end of the complete string. */ + vlr %v19,%v16 + lgr %r1,%r5 + + jh .Lzero /* Found a zero after the found c. */ + aghi %r5,16 /* Start search of next part of s. */ + j .Lloop + +.Lfound_first_part: + /* This code is only executed if the found c/zero is whithin loaded + bytes. If no c/zero was found (cc==3) the found index = 16, thus + this code is not called. + Resulting condition code of vector find element equal: + cc==0: no c, found zero + cc==1: c found, no zero + cc==2: c found, found zero after c + cc==3: no c, no zero (this case can be ignored). */ + je .Lzero /* Found zero, but no c before that zero. */ + + locgrne %r1,%r5 /* Mark c as found in first part of s. */ + vlr %v19,%v16 + + jl .Lalign /* No zero (e.g. if vr was fully loaded) + -> Align and loop afterwards. */ + + /* Found a zero in vr. If vr was not fully loaded due to block + boundary, the remaining bytes are filled with zero and we can't + rely on zero indication of condition code here! */ + + vfenezb %v17,%v16,%v16 /* Find zero. */ + vlgvb %r4,%v17,7 /* Load byte index of zero or 16. */ + clrjl %r4,%r0,.Lzero /* Zero within loaded bytes -> end. */ + j .Lalign /* Align and loop afterwards. */ + +.Lend_searched_zero: + vlgvb %r4,%v17,7 /* Load byte index of zero. */ + algr %r5,%r4 + la %r2,0(%r5,%r2) /* Return pointer to zero. */ + br %r14 + +.Lzero: + /* Reached end of string. Check if one c was found before. */ + clije %r3,0,.Lend_searched_zero /* Found zero and c is zero. */ + + cgfi %r1,-1 /* No c found -> return NULL. */ + locghie %r2,0 + ber %r14 + + larl %r3,.Lpermute_mask /* Load permute mask. */ + vl %v20,0(%r3) + + /* c was found and is part of v19. */ + vfenezb %v17,%v19,%v19 /* Find zero. */ + vlgvb %r4,%v17,7 /* Load byte index of zero or 16. */ + + clgfi %r5,0 /* Loaded byte count in v19 is 16, ... */ + lochine %r0,16 /* ... if v19 is not the first part of s. */ + ahi %r0,-1 /* Convert byte count to highest index. */ + + clr %r0,%r4 + locrl %r4,%r0 /* r4 = min (zero-index, highest-index). */ + + /* Right-shift of v19 to mask bytes after zero. */ + clije %r4,15,.Lzero_permute /* No shift is needed if highest index + in vr is 15. */ + lhi %r0,15 + slr %r0,%r4 /* Compute byte count for vector shift right. */ + sll %r0,3 /* Convert to bit count. */ + vlvgb %v17,%r0,7 + vsrlb %v19,%v19,%v17 /* Vector shift right by byte by number of bytes + specified in bits 1-4 of byte 7 in v17. */ + + /* Reverse bytes in v19. */ +.Lzero_permute: + vperm %v19,%v19,%v19,%v20 /* Permute v19 to reversed order. */ + + /* Find c in reversed v19. */ + vfeeb %v19,%v19,%v18 /* Find c. */ + la %r2,0(%r1,%r2) + vlgvb %r3,%v19,7 /* Load byte index of c. */ + + /* Compute index in real s and return. */ + slgr %r4,%r3 + la %r2,0(%r4,%r2) /* Return pointer to zero. */ + br %r14 +.Lpermute_mask: + .byte 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08 + .byte 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 +END(__strrchr_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strrchr.c b/REORG.TODO/sysdeps/s390/multiarch/strrchr.c new file mode 100644 index 0000000000..edb8ce6caf --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strrchr.c @@ -0,0 +1,30 @@ +/* Multiple versions of strrchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strrchr __redirect_strrchr +# include <string.h> +# undef strrchr +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strrchr, __strrchr, strrchr) +weak_alias (strrchr, rindex); + +#else +# include <string/strrchr.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strspn-c.c b/REORG.TODO/sysdeps/s390/multiarch/strspn-c.c new file mode 100644 index 0000000000..99e1f20da4 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strspn-c.c @@ -0,0 +1,28 @@ +/* Default strspn implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define STRSPN __strspn_c +# ifdef SHARED +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strspn_c, __GI_strspn, __strspn_c); +# endif /* SHARED */ + +# include <string/strspn.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strspn-vx.S b/REORG.TODO/sysdeps/s390/multiarch/strspn-vx.S new file mode 100644 index 0000000000..1cb3d0d598 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strspn-vx.S @@ -0,0 +1,256 @@ +/* Vector optimized 32/64 bit S/390 version of strspn. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* size_t strspn (const char *s, const char * accept) + The strspn() function calculates the length of the initial segment + of s which consists entirely of characters in accept. + + This method checks the length of accept string. If it fits entirely + in one vector register, a fast algorithm is used, which does not need + to check multiple parts of accept-string. Otherwise a slower full + check of accept-string is used. + + register overview: + r3: pointer to start of accept-string + r2: pointer to start of search-string + r4: loaded byte count of vl search-string + r0: found byte index + r1: current return len of s + v16: search-string + v17: accept-string + v18: temp-vreg + + ONLY FOR SLOW: + v19: first accept-string + v20: zero for preparing acc-vector + v21: global mask; 1 indicates a match between + search-string-vreg and any accept-character + v22: current mask; 1 indicates a match between + search-string-vreg and any accept-character in current acc-vreg + v30, v31: for re-/storing registers r6, r8, r9 + r5: current len of accept-string + r6: zero-index in search-string or 16 if no zero + or min(zero-index, loaded byte count) + r8: >0, if former accept-string-part contains a zero, + otherwise =0; + r9: loaded byte count of vlbb accept-string +*/ +ENTRY(__strspn_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + /* + Check if accept-string fits in one vreg: + ---------------------------------------- + */ + vlbb %v17,0(%r3),6 /* Load accept. */ + lcbb %r4,0(%r3),6 + jo .Lcheck_onbb /* Special case if accept lays + on block-boundary. */ +.Lcheck_notonbb: + vistrbs %v17,%v17 /* Fill with zeros after first zero. */ + je .Lfast /* Zero found -> accept fits in one vreg. */ + j .Lslow /* No zero -> accept exceeds one vreg. */ + +.Lcheck_onbb: + /* Accept lays on block-boundary. */ + vfenezb %v18,%v17,%v17 /* Search zero in loaded accept bytes. */ + vlgvb %r0,%v18,7 /* Get index of zero or 16 if not found. */ + clrjl %r0,%r4,.Lcheck_notonbb /* Zero index < loaded bytes count -> + Accept fits in one vreg; + Fill with zeros and proceed + with FAST. */ + vl %v17,0(%r3) /* Load accept, which exceeds loaded bytes. */ + j .Lcheck_notonbb /* Check if accept fits in one vreg. */ + + + /* + Search s for accept in one vreg + ------------------------------- + */ +.Lfast: + /* Complete accept-string is in v17 and remaining bytes are zero. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfaezbs %v16,%v16,%v17,8 /* Find first element in v16 + unequal to any in v17 + or first zero element. */ + vlgvb %r0,%v16,7 /* Load byte index of found element. */ + /* If found index is within loaded bytes (%r0 < %r1), + return with found element index (=equal count). */ + clr %r0,%r1 + locgrl %r2,%r0 + blr %r14 + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r1,16 /* current_len = 16. */ + slr %r1,%r4 /* Compute bytes to 16bytes boundary. */ + +.Lfast_loop: + vl %v16,0(%r1,%r2) /* Load search-string. */ + vfaezbs %v16,%v16,%v17,8 /* Find first element in v16 + unequal to any in v17 + or first zero element. */ + jno .Lfast_loop_found + vl %v16,16(%r1,%r2) + vfaezbs %v16,%v16,%v17,8 + jno .Lfast_loop_found16 + vl %v16,32(%r1,%r2) + vfaezbs %v16,%v16,%v17,8 + jno .Lfast_loop_found32 + vl %v16,48(%r1,%r2) + vfaezbs %v16,%v16,%v17,8 + jno .Lfast_loop_found48 + + aghi %r1,64 + j .Lfast_loop /* Loop if no element was unequal to accept + and not zero. */ + + /* Found unequal or zero element. */ +.Lfast_loop_found48: + aghi %r1,16 +.Lfast_loop_found32: + aghi %r1,16 +.Lfast_loop_found16: + aghi %r1,16 +.Lfast_loop_found: + vlgvb %r0,%v16,7 /* Load byte index of found element. */ + algrk %r2,%r1,%r0 /* And add it to current len. */ + br %r14 + + + /* + Search s for accept in multiple vregs + ------------------------------------- + */ +.Lslow: + /* Save registers. */ + vlvgg %v30,%r6,0 + vlvgp %v31,%r8,%r9 + lghi %r1,0 /* current_len = 0. */ + + /* Accept in v17 without zero. */ + vlr %v19,%v17 /* Save first acc-part for a fast reload. */ + vzero %v20 /* Zero for preparing acc-vector. */ + + /* Align s to 16 byte. */ + risbg %r0,%r2,60,128+63,0 /* Test if s is aligned and + %r0 = bits 60-63 'and' 15 */ + je .Lslow_loop_str /* If s is aligned, loop aligned */ + lghi %r4,15 + slr %r4,%r0 /* Compute highest index to load (15-x). */ + vll %v16,%r4,0(%r2) /* Load up to 16byte boundary (vll needs + highest index, left bytes are 0). */ + ahi %r4,1 /* Work with loaded byte count. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of accept-string to zero. */ + vfenezb %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first accept-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 + if there is no zero. */ + clr %r4,%r6 /* cc==1 if loaded byte count < zero-index. */ + locrl %r6,%r4 /* Load on cc==1. */ + j .Lslow_loop_acc + + /* Process s in 16byte aligned loop. */ +.Lslow_next_str: + vlr %v17,%v19 /* Load first part of accept (no zero). */ + algfr %r1,%r4 /* Add loaded byte count to current len. */ +.Lslow_loop_str: + vl %v16,0(%r1,%r2) /* Load search-string. */ + lghi %r4,16 /* Loaded byte count is 16. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of accept-string to zero. */ + vfenezb %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first accept-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + +.Lslow_loop_acc: + vfaeb %v22,%v16,%v17,4 /* Create matching-mask (1 in mask -> + character matches any accepted character in + this accept-string-part) IN=0, RT=1. */ + vo %v21,%v21,%v22 /* global-mask = global- | matching-mask. */ + vfenezb %v18,%v21,%v21 /* Find first zero in global-mask. */ + vlgvb %r0,%v18,7 /* Get first found zero-index + (= first mismatch). */ + clrjl %r0,%r6,.Lslow_next_acc /* Mismatch-index < min(lbc,zero-index) + -> Process this string-part + with next acc-part. */ + clrjhe %r0,%r4,.Lslow_next_str /* Found-index >= loaded byte count + -> All loaded bytes are matching + any accept-character + and are not zero. */ + /* All bytes are matching any characters in accept-string + and search-string is fully processed (found-index == zero-index) */ +.Lslow_add_lbc_end: + algrk %r2,%r1,%r0 /* Add matching characters to current_len. */ + /* Restore registers. */ + vlgvg %r6,%v30,0 + vlgvg %r8,%v31,0 + vlgvg %r9,%v31,1 + br %r14 + + + +.Lslow_next_acc: + clijh %r8,0,.Lslow_add_lbc_end /* There was a zero in last acc-part + -> Add found index to current len + and end. */ + vlbb %v17,16(%r5,%r3),6 /* Load next accept part. */ + aghi %r5,16 /* Add current_len of accept-string. */ + lcbb %r9,0(%r5,%r3),6 /* Get loaded byte count of accept-string. */ + jo .Lslow_next_acc_onbb /* Jump away if accept-string is + on block-boundary. */ +.Lslow_next_acc_notonbb: + vistrbs %v17,%v17 /* Fill with zeros after first zero. */ + jo .Lslow_loop_acc /* No zero found -> no preparation needed. */ + +.Lslow_next_acc_prepare_zero: + /* Zero in accept-part: fill zeros with first-accept-character. */ + vlgvb %r8,%v17,0 /* Load first element of acc-part. */ + clije %r8,0,.Lslow_add_lbc_end /* End if zero is first character + in this part of accept-string. */ + /* r8>0 -> zero found in this acc-part. */ + vrepb %v18,%v17,0 /* Replicate first char accross all chars. */ + vceqb %v22,%v20,%v17 /* Create a mask (v22) of null chars + by comparing with 0 (v20). */ + vsel %v17,%v18,%v17,%v22 /* Replace null chars with first char. */ + j .Lslow_loop_acc /* Accept part is prepared -> process. */ + +.Lslow_next_acc_onbb: + vfenezb %v18,%v17,%v17 /* Find zero in loaded bytes of accept part. */ + vlgvb %r8,%v18,7 /* Load byte index of zero. */ + clrjl %r8,%r9,.Lslow_next_acc_notonbb /* Found a zero in loaded bytes + -> Prepare vr. */ + vl %v17,0(%r5,%r3) /* Load over boundary ... */ + lghi %r8,0 /* r8=0 -> no zero in this part of acc, + Check for zero is in jump-target. */ + j .Lslow_next_acc_notonbb /* ... and search for zero in + fully loaded vreg again. */ +END(__strspn_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/strspn.c b/REORG.TODO/sysdeps/s390/multiarch/strspn.c new file mode 100644 index 0000000000..b9cf295fb3 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/strspn.c @@ -0,0 +1,31 @@ +/* Multiple versions of strspn. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define strspn __redirect_strspn +/* Omit the strspn inline definitions because it would redefine strspn. */ +# define __NO_STRING_INLINES +# include <string.h> +# undef strspn +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_strspn, __strspn, strspn) + +#else +# include <string/strspn.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/utf16-utf32-z9.c b/REORG.TODO/sysdeps/s390/multiarch/utf16-utf32-z9.c new file mode 100644 index 0000000000..6e64169835 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/utf16-utf32-z9.c @@ -0,0 +1,44 @@ +/* Conversion between UTF-16 and UTF-32 BE/internal - multiarch s390 version. + + Copyright (C) 2017 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/>. */ + +#include <sysdeps/s390/utf16-utf32-z9.c> +#include <ifunc-resolve.h> + +#undef FROM_LOOP +#define FROM_LOOP __from_utf16_loop +#undef TO_LOOP +#define TO_LOOP __to_utf16_loop + +#define _SINGLE_NAME(NAME) NAME##_single +#define SINGLE_NAME(NAME) _SINGLE_NAME(NAME) +strong_alias (SINGLE_NAME (FROM_LOOP_DEFAULT), SINGLE_NAME (FROM_LOOP)) +strong_alias (SINGLE_NAME (TO_LOOP_DEFAULT), SINGLE_NAME (TO_LOOP)) + +/* Generate ifunc'ed loop functions for FROM/TO_LOOP. */ +s390_libc_ifunc_expr (FROM_LOOP_DEFAULT, FROM_LOOP, + (HAVE_FROM_VX && (hwcap & HWCAP_S390_VX)) + ? FROM_LOOP_VX + : FROM_LOOP_DEFAULT); + +s390_libc_ifunc_expr (TO_LOOP_DEFAULT, TO_LOOP, + (HAVE_TO_VX && (hwcap & HWCAP_S390_VX)) + ? TO_LOOP_VX + : TO_LOOP_DEFAULT); + +#include <iconv/skeleton.c> diff --git a/REORG.TODO/sysdeps/s390/multiarch/utf8-utf16-z9.c b/REORG.TODO/sysdeps/s390/multiarch/utf8-utf16-z9.c new file mode 100644 index 0000000000..b55ef1aaec --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/utf8-utf16-z9.c @@ -0,0 +1,48 @@ +/* Conversion between UTF-8 and UTF-16 - multiarch s390 version. + + Copyright (C) 2017 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/>. */ + +#include <sysdeps/s390/utf8-utf16-z9.c> +#include <ifunc-resolve.h> + +#undef FROM_LOOP +#define FROM_LOOP __from_utf8_loop +#undef TO_LOOP +#define TO_LOOP __to_utf8_loop + +#define _SINGLE_NAME(NAME) NAME##_single +#define SINGLE_NAME(NAME) _SINGLE_NAME(NAME) +strong_alias (SINGLE_NAME (FROM_LOOP_DEFAULT), SINGLE_NAME (FROM_LOOP)) +strong_alias (SINGLE_NAME (TO_LOOP_DEFAULT), SINGLE_NAME (TO_LOOP)) + +/* Generate ifunc'ed loop functions for FROM/TO_LOOP. */ +s390_libc_ifunc_expr (FROM_LOOP_DEFAULT, FROM_LOOP, + (HAVE_FROM_VX && (hwcap & HWCAP_S390_VX)) + ? FROM_LOOP_VX + : (HAVE_FROM_CU && (hwcap & HWCAP_S390_ZARCH + && hwcap & HWCAP_S390_HIGH_GPRS + && hwcap & HWCAP_S390_ETF3EH)) + ? FROM_LOOP_CU + : FROM_LOOP_DEFAULT); + +s390_libc_ifunc_expr (TO_LOOP_DEFAULT, TO_LOOP, + (HAVE_TO_VX && (hwcap & HWCAP_S390_VX)) + ? TO_LOOP_VX + : TO_LOOP_DEFAULT); + +#include <iconv/skeleton.c> diff --git a/REORG.TODO/sysdeps/s390/multiarch/utf8-utf32-z9.c b/REORG.TODO/sysdeps/s390/multiarch/utf8-utf32-z9.c new file mode 100644 index 0000000000..faf1f46aa9 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/utf8-utf32-z9.c @@ -0,0 +1,48 @@ +/* Conversion between UTF-8 and UTF-32 - multiarch s390 version. + + Copyright (C) 2017 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/>. */ + +#include <sysdeps/s390/utf8-utf32-z9.c> +#include <ifunc-resolve.h> + +#undef FROM_LOOP +#define FROM_LOOP __from_utf8_loop +#undef TO_LOOP +#define TO_LOOP __to_utf8_loop + +#define _SINGLE_NAME(NAME) NAME##_single +#define SINGLE_NAME(NAME) _SINGLE_NAME(NAME) +strong_alias (SINGLE_NAME (FROM_LOOP_DEFAULT), SINGLE_NAME (FROM_LOOP)) +strong_alias (SINGLE_NAME (TO_LOOP_DEFAULT), SINGLE_NAME (TO_LOOP)) + +/* Generate ifunc'ed loop functions for FROM/TO_LOOP. */ +s390_libc_ifunc_expr (FROM_LOOP_DEFAULT, FROM_LOOP, + (HAVE_FROM_VX && (hwcap & HWCAP_S390_VX)) + ? FROM_LOOP_VX + : (HAVE_FROM_CU && (hwcap & HWCAP_S390_ZARCH + && hwcap & HWCAP_S390_HIGH_GPRS + && hwcap & HWCAP_S390_ETF3EH)) + ? FROM_LOOP_CU + : FROM_LOOP_DEFAULT); + +s390_libc_ifunc_expr (TO_LOOP_DEFAULT, TO_LOOP, + (HAVE_TO_VX && (hwcap & HWCAP_S390_VX)) + ? TO_LOOP_VX + : TO_LOOP_DEFAULT); + +#include <iconv/skeleton.c> diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcpcpy-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcpcpy-c.c new file mode 100644 index 0000000000..6eadde5441 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcpcpy-c.c @@ -0,0 +1,25 @@ +/* Default wcslen implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCPCPY __wcpcpy_c + +# include <wchar.h> +extern __typeof (__wcpcpy) __wcpcpy_c; +# include <wcsmbs/wcpcpy.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcpcpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcpcpy-vx.S new file mode 100644 index 0000000000..73b2670786 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcpcpy-vx.S @@ -0,0 +1,114 @@ +/* Vector optimized 32/64 bit S/390 version of wcpcpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t * wcpcpy (const wchar_t *dest, const wchar_t *src) + Copy string src to dest returning a pointer to its end. + + Register usage: + -r0=border-len for switching to vector-instructions + -r1=tmp + -r2=dest and return value + -r3=src + -r4=tmp + -r5=current_len + -v16=part of src + -v17=index of zero + -v18=part of src +*/ +ENTRY(__wcpcpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + + tmll %r3,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Lfound_align /* If found zero within loaded bytes, + copy bytes before and return. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r4 /* Compute highest index to 16byte boundary. */ + + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Find zero in 16byte aligned loop. */ +.Lloop: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16_0 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezfs %v17,%v18,%v18 + je .Lfound_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezfs %v17,%v16,%v16 + je .Lfound_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezfs %v17,%v18,%v18 + je .Lfound_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + j .Lloop /* No zero found -> loop. */ + +.Lfound_v16_32: + aghi %r5,32 +.Lfound_v16_0: + la %r3,0(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + vstl %v16,%r1,0(%r3) /* Copy characters including zero. */ + lay %r2,-3(%r1,%r3) /* Return pointer to zero. */ + br %r14 + +.Lfound_v18_48: + aghi %r5,32 +.Lfound_v18_16: + la %r3,16(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + vstl %v18,%r1,0(%r3) /* Copy characters including zero. */ + lay %r2,-3(%r1,%r3) /* Return pointer to zero. */ + br %r14 + +.Lfound_align: + aghi %r5,3 /* Also copy remaining bytes of zero. */ + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + lay %r2,-3(%r5,%r2) /* Return pointer to zero. */ + br %r14 + +.Lfallback: + jg __wcpcpy_c +END(__wcpcpy_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcpcpy.c b/REORG.TODO/sysdeps/s390/multiarch/wcpcpy.c new file mode 100644 index 0000000000..79d1641606 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcpcpy.c @@ -0,0 +1,28 @@ +/* Multiple versions of wcpcpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__wcpcpy) +weak_alias (__wcpcpy, wcpcpy) + +#else +# include <wcsmbs/wcpcpy.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcpncpy-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcpncpy-c.c new file mode 100644 index 0000000000..7cb834bba8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcpncpy-c.c @@ -0,0 +1,25 @@ +/* Default wcsncpy implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCPNCPY __wcpncpy_c + +# include <wchar.h> +extern __typeof (__wcpncpy) __wcpncpy_c; +# include <wcsmbs/wcpncpy.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcpncpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcpncpy-vx.S new file mode 100644 index 0000000000..6a1b587f0e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcpncpy-vx.S @@ -0,0 +1,222 @@ +/* Vector optimized 32/64 bit S/390 version of wcpncpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t * wcpncpy (wchar_t *dest, const wchar_t *src, size_t n) + Copies at most n characters of string src to dest + returning a pointer to its end or dest+n + if src is smaller than n. + + Register usage: + -%r0 = return value + -%r1 = zero byte index + -%r2 = curr dst pointer + -%r3 = curr src pointer + -%r4 = n + -%r5 = current_len + -%r6 = loaded bytes + -%r7 = border, tmp +*/ +ENTRY(__wcpncpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgfi %r4,0 + ber %r14 /* Nothing to do, if n == 0. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + + tmll %r3,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + vlvgp %v31,%r6,%r7 /* Save registers. */ + lghi %r5,0 /* current_len = 0. */ + + lcbb %r6,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r6,%r6 /* Convert 32bit to 64bit. */ + + /* Check range of maxlen and convert to byte-count. */ +# ifdef __s390x__ + tmhh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + lghi %r1,-4 /* Max byte-count is 18446744073709551612. */ +# else + tmlh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + llilf %r1,4294967292 /* Max byte-count is 4294967292. */ +# endif /* !__s390x__ */ + sllg %r4,%r4,2 /* Convert character-count to byte-count. */ + locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ + + la %r0,0(%r4,%r2) /* Save destination pointer + n for return. */ + + clgrjle %r4,%r6,.Lremaining_v16 /* If n <= loaded-bytes + -> process remaining. */ + + /* n > loaded-byte-count */ + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + clrjl %r1,%r6,.Lfound_v16_store /* Found zero within loaded bytes, + copy and return. */ + + /* Align s to 16 byte. */ + risbgn %r7,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r7 /* Compute highest index to 16byte boundary. */ + + /* Zero not found and n > loaded-byte-count. */ + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Now we are 16byte aligned, so we can load a full vreg + without page fault. */ + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lloop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + clgijl %r4,17,.Lremaining_v16 /* If n <=16, + process remaining bytes. */ +.Llt64: + lgr %r7,%r4 + slgfi %r7,16 /* border_len = n - 16. */ + + clgrjhe %r5,%r7,.Lremaining_v16 /* If current_len >= border + then process remaining bytes. */ + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + aghi %r5,16 + + clgrjhe %r5,%r7,.Lremaining_v18 + vfenezfs %v17,%v18,%v18 + je .Lfound_v18 + vl %v16,16(%r5,%r3) + vst %v18,0(%r5,%r2) + aghi %r5,16 + + clgrjhe %r5,%r7,.Lremaining_v16 + vfenezfs %v17,%v16,%v16 + je .Lfound_v16 + vl %v18,16(%r5,%r3) + vst %v16,0(%r5,%r2) + aghi %r5,16 + +.Lremaining_v18: + vlr %v16,%v18 +.Lremaining_v16: + /* v16 contains the remaining bytes [1...16]. + Store remaining bytes and append string-termination. */ + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + slgrk %r7,%r4,%r5 /* Remaining bytes = maxlen - current_len */ + aghi %r7,-1 /* vstl needs highest index. */ + la %r2,0(%r5,%r2) /* vstl has no index register. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + /* Zero in remaining bytes? -> jump away (zero-index <= max-index). */ + clrjle %r1,%r7,.Lfound_v16_store + vstl %v16,%r7,0(%r2) /* Store remaining bytes without null + termination! */ +.Lend: + /* Restore saved registers. */ + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lfound_v16_32: + aghi %r5,32 + j .Lfound_v16 +.Lfound_v18_48: + aghi %r5,32 +.Lfound_v18_16: + aghi %r5,16 +.Lfound_v18: + vlr %v16,%v18 +.Lfound_v16: + /* v16 contains a zero. Store remaining bytes to zero. current_len + has not reached border, thus checking for n is not needed! */ + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + la %r2,0(%r5,%r2) /* vstl has no support for index-register. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ +.Lfound_v16_store: + vstl %v16,%r1,0(%r2) /* Copy characters including zero. */ + /* Fill remaining bytes with zero - remaining byte count always > 0. */ + algr %r5,%r1 /* Remaining bytes (=%r4) = ... */ + slgr %r4,%r5 /* = n - (currlen + zero_index + 1) */ + la %r2,0(%r1,%r2) /* Pointer to zero. start filling beyond. */ + lay %r0,-3(%r2) /* Save return-pointer to found zero. */ + clgije %r4,1,.Lend /* Skip zero-filling, if found-zero is last + possible character. + (1 is substracted from r4 below!). */ + aghi %r4,-2 /* mvc with exrl needs count - 1. + (additional -1, see remaining bytes above) */ + srlg %r6,%r4,8 /* Split into 256 byte blocks. */ + ltgr %r6,%r6 + je .Lzero_lt256 +.Lzero_loop256: + mvc 1(256,%r2),0(%r2) /* Fill 256 zeros at once. */ + la %r2,256(%r2) + brctg %r6,.Lzero_loop256 /* Loop until all blocks are processed. */ +.Lzero_lt256: + exrl %r4,.Lmvc_lt256 + j .Lend +.Lmvc_lt256: + mvc 1(1,%r2),0(%r2) + + /* Find zero in 16byte aligned loop. */ +.Lloop64: + vl %v16,0(%r5,%r3) + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezfs %v17,%v18,%v18 + je .Lfound_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezfs %v17,%v16,%v16 + je .Lfound_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezfs %v17,%v18,%v18 + je .Lfound_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lloop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Llt64 + +.Lfallback: + jg __wcpncpy_c +END(__wcpncpy_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcpncpy.c b/REORG.TODO/sysdeps/s390/multiarch/wcpncpy.c new file mode 100644 index 0000000000..1a19a9939a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcpncpy.c @@ -0,0 +1,28 @@ +/* Multiple versions of wcpncpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__wcpncpy) +weak_alias (__wcpncpy, wcpncpy) + +#else +# include <wcsmbs/wcpncpy.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscat-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcscat-c.c new file mode 100644 index 0000000000..ef7c000455 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscat-c.c @@ -0,0 +1,25 @@ +/* Default wcscat implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSCAT __wcscat_c + +# include <wchar.h> +extern __typeof (__wcscat) __wcscat_c; +# include <wcsmbs/wcscat.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscat-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcscat-vx.S new file mode 100644 index 0000000000..604a849906 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscat-vx.S @@ -0,0 +1,175 @@ +/* Vector optimized 32/64 bit S/390 version of wcscat. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t * wcscat (wchar_t *dest, const wchar_t *src) + Concatenate two strings. + + Register usage: + -r0=saved dest pointer for return + -r1=tmp + -r2=dest + -r3=src + -r4=tmp + -r5=current_len + -v16=part of src + -v17=index of zero + -v18=part of src +*/ +ENTRY(__wcscat_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + /* __wcslen_c can handle non 4byte aligned pointers, + but __wcscpy_c not. Thus if either src or dest is + not 4byte aligned, use __wcscat_c. */ + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + tmll %r3,3 /* Test if src is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + lgr %r0,%r2 /* Save destination pointer for return. */ + + /* WCSLEN + r1 = loaded bytes (tmp) + r4 = zero byte index (tmp) + r2 = dst + */ + + vfenezf %v16,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v16,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Llen_end /* Found zero within loaded bytes, end. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r1 /* Compute bytes to 16bytes boundary. */ + + /* Find zero in 16byte aligned loop. */ +.Llen_loop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezfs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Llen_found /* Jump away if zero was found. */ + vl %v16,16(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Llen_found16 + vl %v16,32(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Llen_found32 + vl %v16,48(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Llen_found48 + + aghi %r5,64 + j .Llen_loop /* No zero -> loop. */ + +.Llen_found48: + aghi %r5,16 +.Llen_found32: + aghi %r5,16 +.Llen_found16: + aghi %r5,16 +.Llen_found: + vlgvb %r4,%v16,7 /* Load byte index of zero. */ + algr %r5,%r4 + +.Llen_end: + /* WCSCPY + %r1 = loaded bytes (tmp) + %r4 = zero byte index (tmp) + %r3 = curr src pointer + %r2 = curr dst pointer + */ + la %r2,0(%r5,%r2) /* strcpy at end of dst-string. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Lcpy_found_align /* If found zero within loaded bytes, + copy bytes before and return. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r4 /* Compute highest index to 16byte boundary. */ + + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Find zero in 16byte aligned loop. */ +.Lcpy_loop: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lcpy_found_v16_0 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Save previous part without zero to dst. */ + vfenezfs %v17,%v18,%v18 + je .Lcpy_found_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezfs %v17,%v16,%v16 + je .Lcpy_found_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezfs %v17,%v18,%v18 + je .Lcpy_found_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + j .Lcpy_loop /* No zero -> loop. */ + +.Lcpy_found_v16_32: + aghi %r5,32 +.Lcpy_found_v16_0: + la %r4,0(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + vstl %v16,%r1,0(%r4) /* Copy characters including zero. */ + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lcpy_found_v18_48: + aghi %r5,32 +.Lcpy_found_v18_16: + la %r4,16(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + vstl %v18,%r1,0(%r4) /* Copy characters including zero. */ + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lcpy_found_align: + aghi %r5,3 /* Also copy remaining bytes of found zero. */ + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 +.Lfallback: + jg __wcscat_c +END(__wcscat_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscat.c b/REORG.TODO/sysdeps/s390/multiarch/wcscat.c new file mode 100644 index 0000000000..2e7fdedf22 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscat.c @@ -0,0 +1,28 @@ +/* Multiple versions of wcscat. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__wcscat) +weak_alias (__wcscat, wcscat) + +#else +# include <wcsmbs/wcscat.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcschr-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcschr-c.c new file mode 100644 index 0000000000..b084983dd8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcschr-c.c @@ -0,0 +1,37 @@ +/* Default wcschr implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSCHR __wcschr_c + +# include <wchar.h> +extern __typeof (__wcschr) __wcschr_c; +# undef weak_alias +# define weak_alias(name, alias) +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__wcschr_c, __GI_wcschr, __wcschr_c); \ + strong_alias (__wcschr_c, __wcschr_c_1); \ + __hidden_ver1 (__wcschr_c_1, __GI___wcschr, __wcschr_c_1); +# undef libc_hidden_weak +# define libc_hidden_weak(name) +# endif /* SHARED */ + +# include <wcsmbs/wcschr.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcschr-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcschr-vx.S new file mode 100644 index 0000000000..5a04d44dde --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcschr-vx.S @@ -0,0 +1,103 @@ +/* Vector optimized 32/64 bit S/390 version of wcschr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t *wcschr (const wchar_t *s, wchar_t c) + Locate character in string. + + Register usage: + -r1=tmp + -r2=s + -r3=c + -r4=tmp + -r5=current_len + -v16=part of s + -v17=index of unequal + -v18=replicated c +*/ +ENTRY(__wcschr_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + lghi %r5,0 /* current_len = 0. */ + + vlvgf %v18,%r3,0 /* Generate vector which elements are all c. */ + vrepf %v18,%v18,0 + + vfeezfs %v16,%v16,%v18 /* Find element equal with zero search. */ + vlgvb %r4,%v16,7 /* Load byte index of character or zero. */ + clrjl %r4,%r1,.Lfound /* Return if c/zero is in loaded bytes. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ + + /* Find c/zero in 16byte aligned loop */ +.Lloop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfeezfs %v16,%v16,%v18 /* Find element equal with zero search. */ + jno .Lfound /* Found c/zero (cc=0|1|2). */ + vl %v16,16(%r5,%r2) + vfeezfs %v16,%v16,%v18 + jno .Lfound16 + vl %v16,32(%r5,%r2) + vfeezfs %v16,%v16,%v18 + jno .Lfound32 + vl %v16,48(%r5,%r2) + vfeezfs %v16,%v16,%v18 + jno .Lfound48 + + aghi %r5,64 + j .Lloop /* No character and no zero -> loop. */ + +.Lfound48: + la %r5,16(%r5) /* Use la since aghi would clobber cc. */ +.Lfound32: + la %r5,16(%r5) +.Lfound16: + la %r5,16(%r5) +.Lfound: + je .Lzero /* Found zero, but no c before that zero. */ + +.Lcharacter: + vlgvb %r4,%v16,7 /* Load byte index of character. */ + algr %r5,%r4 + la %r2,0(%r5,%r2) /* Return pointer to character. */ + br %r14 + +.Lzero: + clije %r3,0,.Lcharacter /* Found zero and c is zero. */ + lghi %r2,0 /* Return null if character not found. */ + br %r14 +.Lfallback: + jg __wcschr_c +END(__wcschr_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcschr.c b/REORG.TODO/sysdeps/s390/multiarch/wcschr.c new file mode 100644 index 0000000000..59e5df5706 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcschr.c @@ -0,0 +1,32 @@ +/* Multiple versions of wcschr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define wcschr __redirect_wcschr +# define __wcschr __redirect___wcschr +# include <wchar.h> +# undef wcschr +# undef __wcschr +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc_redirected (__redirect___wcschr, __wcschr) +weak_alias (__wcschr, wcschr) + +#else +# include <wcsmbs/wcschr.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcschrnul-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcschrnul-c.c new file mode 100644 index 0000000000..095ea1202c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcschrnul-c.c @@ -0,0 +1,25 @@ +/* Default wcschrnul implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSCHRNUL __wcschrnul_c + +# include <wchar.h> +extern __typeof (__wcschrnul) __wcschrnul_c; +# include <wcsmbs/wcschrnul.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcschrnul-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcschrnul-vx.S new file mode 100644 index 0000000000..6aa94823ab --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcschrnul-vx.S @@ -0,0 +1,97 @@ +/* Vector optimized 32/64 bit S/390 version of wcschrnul. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t* wcschrnul (const wchar_t *s, wchar_t c) + Returns pointer to first c or to \0 if c not found. + + Register usage: + -r1=tmp + -r2=s and return pointer + -r3=c + -r4=tmp + -r5=current_len + -v16=part of s + -v18=vector with c replicated in every byte +*/ +ENTRY(__wcschrnul_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + lghi %r5,0 /* current_len = 0. */ + + vlvgf %v18,%r3,0 /* Generate vector which elements are all c. */ + vrepf %v18,%v18,0 + + vfeezfs %v16,%v16,%v18 /* Find element equal with zero search. */ + vlgvb %r4,%v16,7 /* Load byte index of character or zero. */ + clrjl %r4,%r1,.Lfound /* Return if c/zero is in loaded bytes. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ + + /* Find c/zero in 16byte aligned loop */ +.Lloop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfeezfs %v16,%v16,%v18 /* Find element equal with zero search. */ + jno .Lfound /* Found c/zero (cc=0|1|2). */ + vl %v16,16(%r5,%r2) + vfeezfs %v16,%v16,%v18 + jno .Lfound16 + vl %v16,32(%r5,%r2) + vfeezfs %v16,%v16,%v18 + jno .Lfound32 + vl %v16,48(%r5,%r2) + vfeezfs %v16,%v16,%v18 + jno .Lfound48 + + aghi %r5,64 + j .Lloop /* No character and no zero -> loop. */ + + /* Found character or zero */ +.Lfound48: + aghi %r5,16 +.Lfound32: + aghi %r5,16 +.Lfound16: + aghi %r5,16 +.Lfound: + vlgvb %r1,%v16,7 /* Load byte index of character. */ + algr %r5,%r1 + la %r2,0(%r5,%r2) /* Return pointer to character. */ + +.Lend: + br %r14 +.Lfallback: + jg __wcschrnul_c +END(__wcschrnul_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcschrnul.c b/REORG.TODO/sysdeps/s390/multiarch/wcschrnul.c new file mode 100644 index 0000000000..f01ea9f9ac --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcschrnul.c @@ -0,0 +1,28 @@ +/* Multiple versions of wcschrnul. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__wcschrnul) +weak_alias (__wcschrnul, wcschrnul) + +#else +# include <wcsmbs/wcschrnul.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscmp-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcscmp-c.c new file mode 100644 index 0000000000..7a148f41bb --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscmp-c.c @@ -0,0 +1,32 @@ +/* Default wcscmp implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSCMP __wcscmp_c + +# include <wchar.h> +extern __typeof (wcscmp) __wcscmp_c; +# undef weak_alias +# define weak_alias(name, alias) +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__wcscmp_c, __GI___wcscmp, __wcscmp_c); +# endif /* SHARED */ +# include <wcsmbs/wcscmp.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscmp-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcscmp-vx.S new file mode 100644 index 0000000000..3b92bbd515 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscmp-vx.S @@ -0,0 +1,131 @@ +/* Vector optimized 32/64 bit S/390 version of wcscmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* int wcscmp (const wchar_t *s1, const wchar_t *s2) + Compare two strings + + Register usage: + -r1=loaded byte count s1 + -r2=s1 + -r3=s2 + -r4=loaded byte coutn s2, tmp + -r5=current_len + -v16=part of s1 + -v17=part of s2 + -v18=index of unequal +*/ +ENTRY(__wcscmp_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + lghi %r5,0 /* current_len = 0. */ + +.Lloop: + vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */ + vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */ + lcbb %r1,0(%r5,%r2),6 /* Get loaded byte count of s1. */ + jo .Llt16_1 /* Jump away if vr is not fully loaded. */ + lcbb %r4,0(%r5,%r3),6 + jo .Llt16_2 /* Jump away if vr is not fully loaded. */ + /* Both vrs are fully loaded. */ + aghi %r5,16 + vfenezfs %v18,%v16,%v17 /* Compare not equal with zero search. */ + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r1,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r4,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezfs %v18,%v16,%v17 + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r1,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r4,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezfs %v18,%v16,%v17 + jno .Lfound + + vlbb %v16,0(%r5,%r2),6 + vlbb %v17,0(%r5,%r3),6 + lcbb %r1,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r4,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezfs %v18,%v16,%v17 + jno .Lfound + j .Lloop + +.Lcmp_one_char: + /* At least one of both strings is not 4-byte aligned + and there is no full character before next block-boundary. + Compare one character to get over the boundary and + proceed with normal loop! */ + vlef %v16,0(%r5,%r2),0 /* Load one character. */ + vlef %v17,0(%r5,%r3),0 + lghi %r1,4 /* Loaded byte count is 4. */ + j .Llt_cmp /* Proceed with comparision. */ + +.Llt16_1: + lcbb %r4,0(%r5,%r3),6 /* Get loaded byte count of s2. */ +.Llt16_2: + clr %r1,%r4 + locrh %r1,%r4 /* Get minimum of bytes loaded in s1/2. */ + nill %r1,65532 /* Align bytes loaded to full characters. */ + jz .Lcmp_one_char /* Jump away if no full char is available. */ +.Llt_cmp: + algfr %r5,%r1 /* Add smallest loaded bytes to current_len. */ + vfenezfs %v18,%v16,%v17 /* Compare not equal with zero search. */ + vlgvb %r4,%v18,7 /* Get not equal index or 16 if all equal. */ + clrjl %r4,%r1,.Lfound /* Jump away if miscompare is within loaded + bytes. */ + j .Lloop + +.Lfound: + /* vfenezf found an unequal element or zero. + This instruction compares unsigned words, but wchar_t is signed. + Thus we have to compare the found element again. */ + vlgvb %r4,%v18,7 /* Extract not equal byte-index, */ + srl %r4,2 /* Convert it to character-index. */ + vlgvf %r3,%v16,0(%r4) /* Load character-values. */ + vlgvf %r4,%v17,0(%r4) + cr %r3,%r4 + je .Lend_equal + lghi %r2,1 + lghi %r1,-1 + locgrl %r2,%r1 + br %r14 +.Lend_equal: + lghi %r2,0 + br %r14 +END(__wcscmp_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscmp.c b/REORG.TODO/sysdeps/s390/multiarch/wcscmp.c new file mode 100644 index 0000000000..a5c2b69a29 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscmp.c @@ -0,0 +1,30 @@ +/* Multiple versions of wcscmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define __wcscmp __redirect___wcscmp +# include <wchar.h> +# undef __wcscmp +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc_redirected (__redirect___wcscmp, __wcscmp) +weak_alias (__wcscmp, wcscmp) + +#else +# include <wcsmbs/wcscmp.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscpy-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcscpy-c.c new file mode 100644 index 0000000000..342c247a8f --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscpy-c.c @@ -0,0 +1,25 @@ +/* Default wcscpy implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSCPY __wcscpy_c + +# include <wchar.h> +extern __typeof (wcscpy) __wcscpy_c; +# include <wcsmbs/wcscpy.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcscpy-vx.S new file mode 100644 index 0000000000..a8adc20dea --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscpy-vx.S @@ -0,0 +1,111 @@ +/* Vector optimized 32/64 bit S/390 version of wcscpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* char * wcscpy (const wchar_t *dest, const wchar_t *src) + Copy string src to dest. + + Register usage: + -r0=border-len for switching to vector-instructions + -r1=tmp + -r2=dest and return value + -r3=src + -r4=tmp + -r5=current_len + -v16=part of src + -v17=index of zero + -v18=part of src +*/ +ENTRY(__wcscpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + + tmll %r3,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Lfound_align /* If found zero within loaded bytes, + copy bytes before and return. */ + + /* Align s to 16 byte. */ + risbgn %r4,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r4 /* Compute highest index to 16byte boundary. */ + + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Find zero in 16byte aligned loop. */ +.Lloop: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16_0 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezfs %v17,%v18,%v18 + je .Lfound_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezfs %v17,%v16,%v16 + je .Lfound_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezfs %v17,%v18,%v18 + je .Lfound_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + j .Lloop /* No zero found -> loop. */ + +.Lfound_v16_32: + aghi %r5,32 +.Lfound_v16_0: + la %r3,0(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + vstl %v16,%r1,0(%r3) /* Copy characters including zero. */ + br %r14 + +.Lfound_v18_48: + aghi %r5,32 +.Lfound_v18_16: + la %r3,16(%r5,%r2) + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + vstl %v18,%r1,0(%r3) /* Copy characters including zero. */ + br %r14 + +.Lfound_align: + aghi %r5,3 /* Also copy remaining bytes of zero. */ + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + br %r14 + +.Lfallback: + jg __wcscpy_c +END(__wcscpy_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscpy.c b/REORG.TODO/sysdeps/s390/multiarch/wcscpy.c new file mode 100644 index 0000000000..bd68b1725d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscpy.c @@ -0,0 +1,27 @@ +/* Multiple versions of wcscpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2 (__wcscpy, wcscpy) + +#else +# include <wcsmbs/wcscpy.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscspn-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcscspn-c.c new file mode 100644 index 0000000000..937e1d1963 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscspn-c.c @@ -0,0 +1,26 @@ +/* Default wcscscpn implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSCSPN __wcscspn_c + +# include <wchar.h> +extern __typeof (wcscspn) __wcscspn_c; + +# include <wcsmbs/wcscspn.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscspn-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcscspn-vx.S new file mode 100644 index 0000000000..cd528907d6 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscspn-vx.S @@ -0,0 +1,293 @@ +/* Vector optimized 32/64 bit S/390 version of wcscspn. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* size_t wcscspn (const wchar_t *s, const wchar_t * reject) + The wcscspn() function calculates the length of the initial segment + of s which consists entirely of characters not in reject. + + This method checks the length of reject string. If it fits entirely + in one vector register, a fast algorithm is used, which does not need + to check multiple parts of accept-string. Otherwise a slower full + check of accept-string is used. + + register overview: + r3: pointer to start of reject-string + r2: pointer to start of search-string + r0: loaded byte count of vlbb search-string + r4: found byte index + r1: current return len + v16: search-string + v17: reject-string + v18: temp-vreg + + ONLY FOR SLOW: + v19: first reject-string + v20: zero for preparing acc-vector + v21: global mask; 1 indicates a match between + search-string-vreg and any reject-character + v22: current mask; 1 indicates a match between + search-string-vreg and any reject-character in current acc-vreg + v30, v31: for re-/storing registers r6, r8, r9 + r5: current len of reject-string + r6: zero-index in search-string or 16 if no zero + or min(zero-index, loaded byte count) + r8: >0, if former reject-string-part contains a zero, + otherwise =0; + r9: loaded byte count of vlbb reject-string +*/ +ENTRY(__wcscspn_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + /* + Check if reject-string fits in one vreg: + ---------------------------------------- + */ + vlbb %v17,0(%r3),0 /* Load reject. */ + lcbb %r0,0(%r3),0 + jo .Lcheck_onbb /* Special case if reject + lays on block-boundary. */ + +.Lcheck_notonbb: + lghi %r1,0 /* Zero out current len. */ + vistrfs %v17,%v17 /* Fill with zeros after first zero. */ + je .Lfast /* Zero found -> reject fits in one vreg. */ + j .Lslow /* No zero -> reject exceeds one vreg. */ + + +.Lcheck_onbb: + /* Reject lays on block-boundary. */ + nill %r0,65532 /* Recognize only fully loaded characters. */ + je .Lcheck_onbb2 /* Reload vr, if we loaded no full wchar_t. */ + vfenezf %v18,%v17,%v17 /* Search zero in loaded reject bytes. */ + vlgvb %r4,%v18,7 /* Get index of zero or 16 if not found. */ + clrjl %r4,%r0,.Lcheck_notonbb /* Zero index < loaded bytes count -> + Reject fits in one vreg; + Fill with zeros and proceed + with FAST. */ +.Lcheck_onbb2: + vl %v17,0(%r3) /* Load reject, which exceeds loaded bytes. */ + j .Lcheck_notonbb /* Check if reject fits in one vreg. */ + + + /* + Search s for reject in one vreg + ------------------------------- + */ +.Lfast: + /* Complete reject-string in v17 and remaining bytes are zero. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfaezfs %v18,%v16,%v17,0 /* Find first element in v16 + unequal to any in v17 + or first zero element. */ + vlgvb %r4,%v18,7 /* Load byte index of found element. */ + clrjl %r4,%r0,.Lfast_loop_found2 /* If found index is within loaded + bytes, return with found element + index (=equal count). */ + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r1,16 /* current_len = 16. */ + slr %r1,%r4 /* Compute bytes to 16bytes boundary. */ + + /* Process s in 16byte aligned loop. */ +.Lfast_loop: + vl %v16,0(%r1,%r2) /* Load search-string. */ + vfaezfs %v18,%v16,%v17,0 /* Find first element in v16 equal to any + in v17 or first zero element. */ + jno .Lfast_loop_found + + vl %v16,16(%r1,%r2) + vfaezfs %v18,%v16,%v17,0 + jno .Lfast_loop_found16 + + vl %v16,32(%r1,%r2) + vfaezfs %v18,%v16,%v17,0 + jno .Lfast_loop_found32 + + vl %v16,48(%r1,%r2) + vfaezfs %v18,%v16,%v17,0 + jno .Lfast_loop_found48 + + aghi %r1,64 + j .Lfast_loop /* Loop if no element was unequal to reject + and not zero. */ + + /* Found equal or zero element. */ +.Lfast_loop_found48: + aghi %r1,16 +.Lfast_loop_found32: + aghi %r1,16 +.Lfast_loop_found16: + aghi %r1,16 +.Lfast_loop_found: + vlgvb %r4,%v18,7 /* Load byte index of found element or zero. */ +.Lfast_loop_found2: + algrk %r2,%r1,%r4 /* Add found index to current len. */ + srlg %r2,%r2,2 /* Convert byte-count to character-count. */ + br %r14 + + + + /* + Search s for reject in multiple vregs + ------------------------------------- + */ +.Lslow: + /* Save registers. */ + vlvgg %v30,%r6,0 + vlvgp %v31,%r8,%r9 + + /* Reject in v17 without zero. */ + vlr %v19,%v17 /* Save first acc-part for a fast reload. */ + vzero %v20 /* Zero for preparing acc-vector. */ + vone %v24 /* One for checking result of former + string-part. */ + + /* Align s to 16 byte. */ + risbg %r4,%r2,60,128+63,0 /* Test if s is aligned and + %r4 = bits 60-63 'and' 15. */ + je .Lslow_loop_str /* If s is aligned, loop aligned. */ + lghi %r0,15 + slr %r0,%r4 /* Compute highest index to load (15-x). */ + vll %v16,%r0,0(%r2) /* Load up to 16byte boundary (vll needs + highest index, remaining bytes are 0). */ + ahi %r0,1 /* Work with loaded byte count. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of reject-string to zero. */ + vfenezf %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first reject-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + clije %r6,0,.Lslow_end /* If first element is zero -> return 0. */ + clr %r0,%r6 /* cc==1 if loaded byte count < zero-index. */ + locrl %r6,%r0 /* Load on cc==1; zero-index = lbc. */ + j .Lslow_loop_acc + + + /* Process s in 16byte aligned loop. */ +.Lslow_next_str: + /* Check results of former processed str-part. */ + vfeef %v18,%v21,%v24 /* Find first equal match in global mask + (ones in element). */ + vlgvb %r4,%v18,7 /* Get index of first one (=equal) or 16. */ + /* Equal-index < min(zero-index, loaded byte count) + -> Return pointer to equal element. */ + clrjl %r4,%r6,.Lslow_index_found + /* Zero-index < loaded byte count + -> Former str-part was last str-part + -> Return null */ + clrjl %r6,%r0,.Lslow_end_not_found + + /* All elements are zero (=no match) -> proceed with next str-part. */ + vlr %v17,%v19 /* Load first part of reject (no zero). */ + algfr %r1,%r0 /* Add loaded byte count to current len. */ + +.Lslow_loop_str: + vl %v16,0(%r1,%r2) /* Load search-string. */ + lghi %r0,16 /* Loaded byte count is 16. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of reject to zero. */ + vfenezf %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first reject-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + clije %r6,0,.Lslow_end /* If first element is zero (end of string) + -> Return current length. */ + +.Lslow_loop_acc: + vfaef %v22,%v16,%v17,4 /* Create matching-mask (1 in mask -> + Character matches any rejected character in + this reject-string-part) IN=0, RT=1. */ + vlgvf %r4,%v22,0 /* Get result of first element. */ + /* First element is equal to any rejected characters? + (All other parts of reject cannot lead to a match before this one) + -> Return current len, which is pointing to this element. */ + clijh %r4,0,.Lslow_end + vo %v21,%v21,%v22 /* Global-mask = global-|matching-mask. */ + /* Proceed with next acc until end of acc is reached. */ + + +.Lslow_next_acc: + clijh %r8,0,.Lslow_next_str /* There was a zero in last reject-part + -> Add found index to current len + and end. */ + vlbb %v17,16(%r5,%r3),6 /* Load next reject part. */ + aghi %r5,16 /* Increment current len of reject-string. */ + lcbb %r9,0(%r5,%r3),6 /* Get loaded byte count of reject-string. */ + jo .Lslow_next_acc_onbb /* Jump away if reject-string is + on block-boundary. */ +.Lslow_next_acc_notonbb: + vistrfs %v17,%v17 /* Fill with zeros after first zero. */ + jo .Lslow_loop_acc /* No zero found -> no preparation needed. */ + +.Lslow_next_acc_prepare_zero: + /* Zero in reject-part: fill zeros with first-reject-character. */ + vlgvf %r8,%v17,0 /* Load first element of reject-part. */ + clije %r8,0,.Lslow_next_str /* Process next str-part if first + character in this part of reject + is a zero. */ + /* r8>0 -> zero found in this acc-part. */ + vrepf %v18,%v17,0 /* Replicate first char accross all chars. */ + vceqf %v22,%v20,%v17 /* Create a mask (v22) of null chars + by comparing with 0 (v20). */ + vsel %v17,%v18,%v17,%v22 /* Replace null chars with first char. */ + j .Lslow_loop_acc /* Reject-string part is prepared. */ + +.Lslow_next_acc_onbb: + nill %r9,65532 /* Recognize only fully loaded characters. */ + je .Lslow_next_acc_onbb2 /* Reload vr, if no full wchar_t + loaded. */ + vfenezf %v18,%v17,%v17 /* Find zero in loaded bytes of reject part. */ + vlgvb %r8,%v18,7 /* Load byte index of zero. */ + clrjl %r8,%r9,.Lslow_next_acc_notonbb /* Found a zero in loaded bytes + -> Prepare vreg. */ +.Lslow_next_acc_onbb2: + vl %v17,0(%r5,%r3) /* Load over boundary ... */ + lghi %r8,0 /* r8=0 -> no zero in this part of acc, + check for zero is in jump-target. */ + j .Lslow_next_acc_notonbb /* ... and search for zero in + fully loaded vreg again. */ + +.Lslow_end_not_found: + algfr %r1,%r6 /* Add zero-index to current len. */ + j .Lslow_end +.Lslow_index_found: + algfr %r1,%r4 /* Add found index of char to current len. */ +.Lslow_end: + srlg %r2,%r1,2 /* Convert byte-count to character-count. */ + /* Restore registers. */ + vlgvg %r6,%v30,0 + vlgvg %r8,%v31,0 + vlgvg %r9,%v31,1 + br %r14 +.Lfallback: + jg __wcscspn_c +END(__wcscspn_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcscspn.c b/REORG.TODO/sysdeps/s390/multiarch/wcscspn.c new file mode 100644 index 0000000000..f38ed9c7f4 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcscspn.c @@ -0,0 +1,27 @@ +/* Multiple versions of wcscspn. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2 (__wcscspn, wcscspn) + +#else +# include <wcsmbs/wcscspn.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcslen-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcslen-c.c new file mode 100644 index 0000000000..9626a76da5 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcslen-c.c @@ -0,0 +1,25 @@ +/* Default wcslen implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSLEN __wcslen_c + +# include <wchar.h> +extern __typeof (__wcslen) __wcslen_c; +# include <wcsmbs/wcslen.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcslen-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcslen-vx.S new file mode 100644 index 0000000000..7539303fbd --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcslen-vx.S @@ -0,0 +1,91 @@ +/* Vector optimized 32/64 bit S/390 version of wcslen. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* size_t wcslen (const wchar_t *s) + Returns length of string s. + + Register usage: + -r1=bytes to 4k-byte boundary + -r2=s + -r3=tmp + -r4=tmp + -r5=current_len and return_value + -v16=part of s +*/ +ENTRY(__wcslen_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + vfenezf %v16,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r4,%v16,7 /* Load zero index or 16 if not found. */ + clr %r4,%r1 /* If found zero within loaded bytes? */ + locgrl %r2,%r4 /* Then copy return value. */ + jl .Lend /* And return. */ + + /* Align s to 16 byte. */ + risbgn %r3,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r3 /* Compute bytes to 16bytes boundary. */ + + /* Find zero in 16byte aligned loop. */ +.Lloop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezfs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound /* Jump away if zero was found. */ + vl %v16,16(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Lfound16 + vl %v16,32(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Lfound32 + vl %v16,48(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Lfound48 + + aghi %r5,64 + j .Lloop /* No zero found -> loop. */ + +.Lfound48: + aghi %r5,16 +.Lfound32: + aghi %r5,16 +.Lfound16: + aghi %r5,16 +.Lfound: + vlgvb %r2,%v16,7 /* Load byte index of zero. */ + algr %r2,%r5 +.Lend: + srlg %r2,%r2,2 /* Convert byte-count to character-count. */ + br %r14 +.Lfallback: + jg __wcslen_c +END(__wcslen_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcslen.c b/REORG.TODO/sysdeps/s390/multiarch/wcslen.c new file mode 100644 index 0000000000..bfb577797e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcslen.c @@ -0,0 +1,28 @@ +/* Multiple versions of wcslen. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__wcslen) +weak_alias (__wcslen, wcslen) + +#else +# include <wcsmbs/wcslen.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncat-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcsncat-c.c new file mode 100644 index 0000000000..84b3eb1124 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncat-c.c @@ -0,0 +1,25 @@ +/* Default wcsncat implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSNCAT __wcsncat_c + +# include <wchar.h> +extern __typeof (wcsncat) __wcsncat_c; +# include <wcsmbs/wcsncat.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncat-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcsncat-vx.S new file mode 100644 index 0000000000..5c49a1e499 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncat-vx.S @@ -0,0 +1,265 @@ +/* Vector optimized 32/64 bit S/390 version of wcsncat. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t * wcsncat (wchar_t *dest, const wchar_t *src, size_t n) + Concatenate two strings - at most n characters of src. + + Register usage: + -r0=saved dest pointer for return + -r1=tmp + -r2=dest + -r3=src + -r4=n + -r5=current_len + -r6=tmp + -r7=tmp + -v16=part of src + -v17=index of zero + -v18=part of src + -v31=register save area for r6, r7 +*/ +ENTRY(__wcsncat_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgfi %r4,0 + ber %r14 /* Nothing to do, if n == 0. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + /* If either src or dest is not 4byte aligned, use __wcsncat_c. */ + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + tmll %r3,3 /* Test if src is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + lgr %r0,%r2 /* Save destination pointer for return. */ + vlvgp %v31,%r6,%r7 /* Save registers. */ + + /* WCSLEN + %r1 = loaded bytes (tmp) + %r6 = zero byte index (tmp) + %r2 = dst + */ + vfenezf %v16,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r5,%v16,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Llen_end /* Found zero within loaded bytes, end. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r1 /* Compute bytes to 16bytes boundary. */ + + /* Find zero in 16byte aligned loop. */ +.Llen_loop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezfs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Llen_found /* Jump away if zero was found. */ + vl %v16,16(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Llen_found16 + vl %v16,32(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Llen_found32 + vl %v16,48(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Llen_found48 + + aghi %r5,64 + j .Llen_loop /* No zero -> loop. */ + +.Llen_found48: + aghi %r5,16 +.Llen_found32: + aghi %r5,16 +.Llen_found16: + aghi %r5,16 +.Llen_found: + vlgvb %r1,%v16,7 /* Load byte index of zero. */ + algr %r5,%r1 + +.Llen_end: + /* WCSNCPY + %r1 = zero byte index (tmp) + %r6 = loaded bytes (tmp) + %r3 = curr src pointer + %r2 = curr dst pointer + %r7 = border, tmp + */ + la %r2,0(%r5,%r2) /* strcpy at end of dst-string. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + lcbb %r6,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r6,%r6 /* Convert 32bit to 64bit. */ + + lghi %r5,0 /* current_len = 0. */ + + /* Check range of maxlen and convert to byte-count. */ +# ifdef __s390x__ + tmhh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + lghi %r1,-4 /* Max byte-count is 18446744073709551612. */ +# else + tmlh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + llilf %r1,4294967292 /* Max byte-count is 4294967292. */ +# endif /* !__s390x__ */ + sllg %r4,%r4,2 /* Convert character-count to byte-count. */ + locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ + + clgrjle %r4,%r6,.Lcpy_remaining_v16 /* If n <= loaded-bytes + -> process remaining. */ + + /* n > loaded-byte-count. */ + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + clrjl %r1,%r6,.Lcpy_found_v16_store /* Found zero within loaded bytes, + copy and return. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r1 /* Compute highest index to 16byte boundary. * + + /* Zero not found and maxlen > loaded-byte-count. */ + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* + Now we are 16byte aligned, so we can load a full vreg + without page fault. + */ + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lcpy_loop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + clgijl %r4,17,.Lcpy_remaining_v16 /* If n <=16, + process remaining bytes. */ +.Lcpy_lt64: + lgr %r7,%r4 + slgfi %r7,16 /* border_len = n - 16. */ + + clgrjhe %r5,%r7,.Lcpy_remaining_v16 + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lcpy_found_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Save previous part without zero to dst. */ + aghi %r5,16 + + clgrjhe %r5,%r7,.Lcpy_remaining_v18 + vfenezfs %v17,%v18,%v18 + je .Lcpy_found_v18 + vl %v16,16(%r5,%r3) + vst %v18,0(%r5,%r2) + aghi %r5,16 + + clgrjhe %r5,%r7,.Lcpy_remaining_v16 + vfenezfs %v17,%v16,%v16 + je .Lcpy_found_v16 + vl %v18,16(%r5,%r3) + vst %v16,0(%r5,%r2) + aghi %r5,16 + +.Lcpy_remaining_v18: + vlr %v16,%v18 +.Lcpy_remaining_v16: + /* v16 contains the remaining bytes [1...16]. + Store remaining bytes and append string-termination. */ + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + slgrk %r7,%r4,%r5 /* Remaining bytes = maxlen - current_len. */ + aghi %r7,-1 /* vstl needs highest index. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + la %r2,0(%r5,%r2) /* vstl has no index register. */ + /* Zero-index within remaining-bytes, store up to zero and end. */ + clgrjle %r1,%r7,.Lcpy_found_v16_store + vstl %v16,%r7,0(%r2) /* Store remaining bytes. */ + lghi %r1,0 + st %r1,1(%r7,%r2) /* Store string-null-termination beyond n. */ +.Lcpy_end: + /* Restore saved registers. */ + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lcpy_found_v16_32: + aghi %r5,32 + j .Lcpy_found_v16 +.Lcpy_found_v18_48: + aghi %r5,32 +.Lcpy_found_v18_16: + aghi %r5,16 +.Lcpy_found_v18: + vlr %v16,%v18 +.Lcpy_found_v16: + /* v16 contains a zero. Store remaining bytes to zero. current_len + has not reached border, thus checking for n is not needed! */ + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + la %r2,0(%r5,%r2) +.Lcpy_found_v16_store: + aghi %r1,3 /* Also copy remaining bytes of zero. */ + vstl %v16,%r1,0(%r2) /* Copy characters including zero. */ + j .Lcpy_end + + /* Find zero in 16byte aligned loop. */ +.Lcpy_loop2: + vl %v16,16(%r5,%r3) + vst %v18,0(%r5,%r2) + aghi %r5,16 + +.Lcpy_loop64: + vl %v16,0(%r5,%r3) + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lcpy_found_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Save previous part without zero to dst. */ + vfenezfs %v17,%v18,%v18 + je .Lcpy_found_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezfs %v17,%v16,%v16 + je .Lcpy_found_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezfs %v17,%v18,%v18 + je .Lcpy_found_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lcpy_loop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Lcpy_lt64 + +.Lfallback: + jg __wcsncat_c +END(__wcsncat_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncat.c b/REORG.TODO/sysdeps/s390/multiarch/wcsncat.c new file mode 100644 index 0000000000..be545d091d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncat.c @@ -0,0 +1,27 @@ +/* Multiple versions of wcsncat. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2 (__wcsncat, wcsncat) + +#else +# include <wcsmbs/wcsncat.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncmp-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcsncmp-c.c new file mode 100644 index 0000000000..72ee85ab7a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncmp-c.c @@ -0,0 +1,25 @@ +/* Default wcsncmp implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSNCMP __wcsncmp_c + +# include <wchar.h> +extern __typeof (wcsncmp) __wcsncmp_c; +# include <wcsmbs/wcsncmp.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncmp-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcsncmp-vx.S new file mode 100644 index 0000000000..e44c53a1a9 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncmp-vx.S @@ -0,0 +1,177 @@ +/* Vector optimized 32/64 bit S/390 version of wcsncmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* int wcsncmp (const wchar_t *s1, const wchar_t *s2, size_t n) + Compare at most n characters of two strings. + + Register usage: + -r0=tmp + -r1=tmp + -r2=s1 + -r3=s2 + -r4=n + -r5=current_len + -v16=part of s1 + -v17=part of s2 + -v18=index of unequal +*/ +ENTRY(__wcsncmp_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgije %r4,0,.Lend_equal /* Nothing to do if n == 0. */ + + /* Check range of n and convert to byte-count. */ +# ifdef __s390x__ + tmhh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + lghi %r1,-4 /* Max byte-count is 18446744073709551612. */ +# else + tmlh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + llilf %r1,4294967292 /* Max byte-count is 4294967292. */ +# endif /* !__s390x__ */ + sllg %r4,%r4,2 /* Convert character-count to byte-count. */ + locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ + + /* Check first character without vector load. */ + lghi %r5,4 /* current_len = 4 bytes. */ + /* Check s1/2[0]. */ + lt %r0,0(%r2) + l %r1,0(%r3) + je .Lend_cmp_one_char + crjne %r0,%r1,.Lend_cmp_one_char + +.Lloop: + vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */ + vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */ + lcbb %r0,0(%r5,%r2),6 /* Get loaded byte count of s1. */ + jo .Llt16_1 /* Jump away if vector not fully loaded. */ + lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count of s2. */ + jo .Llt16_2 /* Jump away if vector not fully loaded. */ + aghi %r5,16 /* Both vectors are fully loaded. */ + vfenezfs %v18,%v16,%v17 /* Compare not equal with zero search. */ + clgrjhe %r5,%r4,.Llastcmp /* If current_len >= n ->last compare. */ + jno .Lfound + + vlbb %v17,0(%r5,%r3),6 + vlbb %v16,0(%r5,%r2),6 + lcbb %r0,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r1,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezfs %v18,%v16,%v17 + clgrjhe %r5,%r4,.Llastcmp + jno .Lfound + + vlbb %v17,0(%r5,%r3),6 + vlbb %v16,0(%r5,%r2),6 + lcbb %r0,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r1,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezfs %v18,%v16,%v17 + clgrjhe %r5,%r4,.Llastcmp + jno .Lfound + + vlbb %v17,0(%r5,%r3),6 + vlbb %v16,0(%r5,%r2),6 + lcbb %r0,0(%r5,%r2),6 + jo .Llt16_1 + lcbb %r1,0(%r5,%r3),6 + jo .Llt16_2 + aghi %r5,16 + vfenezfs %v18,%v16,%v17 + clgrjhe %r5,%r4,.Llastcmp + jno .Lfound + + j .Lloop + +.Llt16_1: + lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count of s2. */ +.Llt16_2: + clr %r0,%r1 /* Compare logical. */ + locrh %r0,%r1 /* Compute minimum of bytes loaded. */ + nill %r0,65532 /* Align bytes loaded to full characters. */ + jz .Lcmp_one_char /* Jump away if no full char is available. */ +.Llt_cmp: + algfr %r5,%r0 /* Add smallest loaded bytes to current_len. */ + vfenezfs %v18,%v16,%v17 /* Compare not equal with zero search. */ + clgrj %r5,%r4,10,.Llastcmp /* If current_len >= n -> last compare */ + vlgvb %r1,%v18,7 /* Get not equal index or 16 if all equal. */ + clrjl %r1,%r0,.Lfound /* Jump away if miscompare is within + loaded bytes; (index < loaded-bytes) */ + j .Lloop + +.Lcmp_one_char: + /* At least one of both strings is not 4-byte aligned + and there is no full character before next block-boundary. + Compare one character to get over the boundary and + proceed with normal loop! */ + vlef %v16,0(%r5,%r2),0 /* Load one character. */ + lghi %r0,4 /* Loaded byte count is 4. */ + vlef %v17,0(%r5,%r3),0 + j .Llt_cmp /* Proceed with comparision. */ + +.Llastcmp: + /* Use comparision result only if located within first n characters. + %r0: loaded byte count in vreg; + %r5: current_len; + %r4: n; + (current_len - n): [0...16[ + First ignored match index: loaded bytes - (current_len-n): ]0...16] + */ + slgr %r5,%r4 /* %r5 = current_len - n. */ + slr %r0,%r5 /* %r0 = first ignored match index. */ + vlgvb %r4,%v18,7 /* Get not equal index or 16 if all equal. */ + clrjl %r4,%r0,.Lfound2 /* Jump away if miscompare is within + loaded bytes and below n bytes. */ +.Lend_equal: + lghi %r2,0 + br %r14 + +.Lfound: + /* Difference or end of string. */ + /* vfenezf found an unequal element or zero. + This instruction compares unsigned words, but wchar_t is signed. + Thus we have to compare the found element again. */ + vlgvb %r4,%v18,7 /* Extract not equal byte-index. */ +.Lfound2: + srl %r4,2 /* And convert it to character-index. */ + vlgvf %r0,%v16,0(%r4) /* Load character-values. */ + vlgvf %r1,%v17,0(%r4) +.Lend_cmp_one_char: + cr %r0,%r1 + je .Lend_equal + lghi %r2,1 + lghi %r1,-1 + locgrl %r2,%r1 + br %r14 +END(__wcsncmp_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncmp.c b/REORG.TODO/sysdeps/s390/multiarch/wcsncmp.c new file mode 100644 index 0000000000..9b8e968d1f --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncmp.c @@ -0,0 +1,27 @@ +/* Multiple versions of wcsncmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2 (__wcsncmp, wcsncmp) + +#else +# include <wcsmbs/wcsncmp.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncpy-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcsncpy-c.c new file mode 100644 index 0000000000..32ec8ffe64 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncpy-c.c @@ -0,0 +1,25 @@ +/* Default wcsncpy implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSNCPY __wcsncpy_c + +# include <wchar.h> +extern __typeof (__wcsncpy) __wcsncpy_c; +# include <wcsmbs/wcsncpy.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncpy-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcsncpy-vx.S new file mode 100644 index 0000000000..3d1a67e0d6 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncpy-vx.S @@ -0,0 +1,223 @@ +/* Vector optimized 32/64 bit S/390 version of wcsncpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t *wcsncpy (const wchar_t *dest, const wchar_t *src, size_t n) + Copy at most n characters of string src to dest. + + Register usage: + -r0=dest pointer for return + -r1=tmp, zero byte index + -r2=dest + -r3=src + -r4=n + -r5=current_len + -r6=tmp, loaded bytes + -r7=tmp, border + -v16=part of src + -v17=index of zero + -v18=part of src + -v31=register save area for r6, r7 +*/ +ENTRY(__wcsncpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgfi %r4,0 + ber %r14 /* Nothing to do, if n == 0. */ + + vlbb %v16,0(%r3),6 /* Load s until next 4k-byte boundary. */ + + tmll %r3,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + vlvgp %v31,%r6,%r7 /* Save registers. */ + lgr %r0,%r2 /* Save destination pointer for return. */ + + lcbb %r6,0(%r3),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r6,%r6 /* Convert 32bit to 64bit. */ + + lghi %r5,0 /* current_len = 0. */ + + /* Check range of maxlen and convert to byte-count. */ +# ifdef __s390x__ + tmhh %r4,49152 /* Test bit 0 or 1 of n. */ + lghi %r1,-4 /* Max byte-count is 18446744073709551612. */ +# else + tmlh %r4,49152 /* Test bit 0 or 1 of n. */ + llilf %r1,4294967292 /* Max byte-count is 4294967292. */ +# endif /* !__s390x__ */ + sllg %r4,%r4,2 /* Convert character-count to byte-count. */ + locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ + + clgrjle %r4,%r6,.Lremaining_v16 /* If n <= loaded-bytes + -> process remaining. */ + + /* n > loaded-byte-count. */ + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + clrjl %r1,%r6,.Lfound_v16_store /* Found zero within loaded bytes, + copy and return. */ + + /* Align s to 16 byte. */ + risbgn %r7,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,15 /* current_len = 15. */ + slr %r5,%r7 /* Compute highest index to 16byte boundary. */ + + /* Zero not found and n > loaded-byte-count. */ + vstl %v16,%r5,0(%r2) /* Copy loaded characters - no zero. */ + ahi %r5,1 /* Start loop at next character. */ + + /* Now we are 16byte aligned, so we can load + a full vreg without page fault. */ + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lloop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + clgijl %r4,17,.Lremaining_v16 /* If n <=16, process remaining + bytes. */ +.Llt64: + lgr %r7,%r4 + slgfi %r7,16 /* border_len = maxlen - 16. */ + + clgrjhe %r5,%r7,.Lremaining_v16 /* If current_len >= border + then process remaining bytes. */ + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + aghi %r5,16 + + clgrjhe %r5,%r7,.Lremaining_v18 + vfenezfs %v17,%v18,%v18 + je .Lfound_v18 + vl %v16,16(%r5,%r3) + vst %v18,0(%r5,%r2) + aghi %r5,16 + + clgrjhe %r5,%r7,.Lremaining_v16 + vfenezfs %v17,%v16,%v16 + je .Lfound_v16 + vl %v18,16(%r5,%r3) + vst %v16,0(%r5,%r2) + aghi %r5,16 + +.Lremaining_v18: + vlr %v16,%v18 +.Lremaining_v16: + /* v16 contains the remaining bytes [1...16]. + Store remaining bytes and append string-termination. */ + vfenezf %v17,%v16,%v16 /* Find element not equal with zero search. */ + slgrk %r7,%r4,%r5 /* Remaining bytes = maxlen - current_len. */ + aghi %r7,-1 /* vstl needs highest index. */ + la %r2,0(%r5,%r2) /* vstl has no index register. */ + vlgvb %r1,%v17,7 /* Load zero index or 16 if not found. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ + /* Zero in remaining bytes? -> jump away (zero-index < max-index) + Do not jump away if zero-index == max-index, + but simply copy zero with vstl below. */ + clrjl %r1,%r7,.Lfound_v16_store + vstl %v16,%r7,0(%r2) /* Store remaining bytes without null + termination!. */ +.Lend: + /* Restore saved registers. */ + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + +.Lfound_v16_32: + aghi %r5,32 + j .Lfound_v16 +.Lfound_v18_48: + aghi %r5,32 +.Lfound_v18_16: + aghi %r5,16 +.Lfound_v18: + vlr %v16,%v18 +.Lfound_v16: + /* v16 contains a zero. Store remaining bytes to zero. current_len + has not reached border, thus checking for n is not needed! */ + vlgvb %r1,%v17,7 /* Load byte index of zero. */ + la %r2,0(%r5,%r2) /* vstl has no support for index-register. */ + aghi %r1,3 /* Also copy remaining bytes of zero. */ +.Lfound_v16_store: + vstl %v16,%r1,0(%r2) /* Copy characters including zero. */ + /* Fill remaining bytes with zero - remaining count always > 0. */ + algr %r5,%r1 /* Remaining bytes (=%r4) = ... */ + slgr %r4,%r5 /* = maxlen - (currlen + zero_index + 1). */ + la %r2,0(%r1,%r2) /* Pointer to zero. start filling beyond. */ + aghi %r4,-2 /* mvc with exrl needs count - 1. + (additional -1, see remaining bytes above) */ + srlg %r6,%r4,8 /* Split into 256 byte blocks. */ + ltgr %r6,%r6 + je .Lzero_lt256 +.Lzero_loop256: + mvc 1(256,%r2),0(%r2) /* Fill 256 zeros at once. */ + la %r2,256(%r2) + brctg %r6,.Lzero_loop256 /* Loop until all blocks are processed. */ +.Lzero_lt256: + exrl %r4,.Lmvc_lt256 + j .Lend +.Lmvc_lt256: + mvc 1(1,%r2),0(%r2) + + /* Find zero in 16byte aligned loop. */ +.Lloop64: + vl %v16,0(%r5,%r3) /* Load s. */ + vfenezfs %v17,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound_v16 /* Jump away if zero was found. */ + vl %v18,16(%r5,%r3) /* Load next part of s. */ + vst %v16,0(%r5,%r2) /* Store previous part without zero to dst. */ + vfenezfs %v17,%v18,%v18 + je .Lfound_v18_16 + vl %v16,32(%r5,%r3) + vst %v18,16(%r5,%r2) + vfenezfs %v17,%v16,%v16 + je .Lfound_v16_32 + vl %v18,48(%r5,%r3) + vst %v16,32(%r5,%r2) + vfenezfs %v17,%v18,%v18 + je .Lfound_v18_48 + vst %v18,48(%r5,%r2) + + aghi %r5,64 + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r4,.Lloop64 + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Llt64 + +.Lfallback: + jg __wcsncpy_c +END(__wcsncpy_vx) + +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsncpy.c b/REORG.TODO/sysdeps/s390/multiarch/wcsncpy.c new file mode 100644 index 0000000000..6e1e8f01fb --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsncpy.c @@ -0,0 +1,28 @@ +/* Multiple versions of wcsncpy. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__wcsncpy) +weak_alias (__wcsncpy, wcsncpy) + +#else +# include <wcsmbs/wcsncpy.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsnlen-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcsnlen-c.c new file mode 100644 index 0000000000..e86ca654e0 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsnlen-c.c @@ -0,0 +1,25 @@ +/* Default wcsnlen implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSNLEN __wcsnlen_c + +# include <wchar.h> +extern __typeof (__wcsnlen) __wcsnlen_c; +# include <wcsmbs/wcsnlen.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsnlen-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcsnlen-vx.S new file mode 100644 index 0000000000..c678b94cac --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsnlen-vx.S @@ -0,0 +1,151 @@ +/* Vector optimized 32/64 bit S/390 version of wcsnlen. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* size_t wcsnlen (const wchar_t *s, size_t maxlen) + Returns the number of characters in s or at most maxlen. + + Register usage: + -r1=tmp + -r2=address of string + -r3=maxlen (number of characters to be read) + -r4=tmp + -r5=current_len and return_value + -v16=part of s +*/ +ENTRY(__wcsnlen_vx) + + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r3,%r3 +# endif /* !defined __s390x__ */ + + clgfi %r3,0 /* if maxlen == 0, return 0. */ + locgre %r2,%r3 + ber %r14 + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r1,%r1 /* Convert 32bit to 64bit. */ + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + /* Check range of maxlen and convert to byte-count. */ +# ifdef __s390x__ + tmhh %r3,49152 /* Test bit 0 or 1 of maxlen. */ + lghi %r4,-4 /* Max byte-count is 18446744073709551612. */ +# else + tmlh %r3,49152 /* Test bit 0 or 1 of maxlen. */ + llilf %r4,4294967292 /* Max byte-count is 4294967292. */ +# endif /* !__s390x__ */ + sllg %r3,%r3,2 /* Convert character-count to byte-count. */ + locgrne %r3,%r4 /* Use max byte-count, if bit 0/1 was one. */ + + vfenezf %v16,%v16,%v16 /* Find element not equal with zero search. */ + clgr %r1,%r3 + locgrh %r1,%r3 /* loaded_byte_count + = min (loaded_byte_count, maxlen) */ + + vlgvb %r5,%v16,7 /* Load zero index or 16 if not found. */ + clrjl %r5,%r1,.Lend /* Found zero within loaded bytes -> return. */ + + clgr %r1,%r3 /* If loaded_byte_count == maxlen -> end. */ + locgre %r5,%r3 + je .Lend + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ + + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r3,.Lloop64 + + /* Find zero in max 64byte with aligned s. */ +.Llt64: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezfs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound /* Jump away if zero was found. */ + aghi %r5,16 + clgrjhe %r5,%r3,.Lfound /* If current_len >= maxlen -> end. */ + vl %v16,0(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Lfound + aghi %r5,16 + clgrjhe %r5,%r3,.Lfound + vl %v16,0(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Lfound + aghi %r5,16 + clgrjhe %r5,%r3,.Lfound + vl %v16,0(%r5,%r2) + vfenezfs %v16,%v16,%v16 + j .Lfound + +.Lfound48: + aghi %r5,16 +.Lfound32: + aghi %r5,16 +.Lfound16: + aghi %r5,16 +.Lfound: + vlgvb %r4,%v16,7 /* Load byte index of zero or 16 if no zero. */ + algr %r5,%r4 + + clgr %r5,%r3 + locgrh %r5,%r3 /* Return min (current_len, maxlen). */ +.Lend: + srlg %r2,%r5,2 /* Convert byte-count to character-count. */ + br %r14 + + /* Find zero in 16byte aligned loop. */ +.Lloop64: + vl %v16,0(%r5,%r2) /* Load s. */ + vfenezfs %v16,%v16,%v16 /* Find element not equal with zero search. */ + je .Lfound /* Jump away if zero was found. */ + vl %v16,16(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Lfound16 + vl %v16,32(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Lfound32 + vl %v16,48(%r5,%r2) + vfenezfs %v16,%v16,%v16 + je .Lfound48 + + aghi %r5,64 + lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ + aghi %r1,64 + clgrjl %r1,%r3,.Lloop64 + + j .Llt64 + +.Lfallback: + jg __wcsnlen_c +END(__wcsnlen_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsnlen.c b/REORG.TODO/sysdeps/s390/multiarch/wcsnlen.c new file mode 100644 index 0000000000..54486b9158 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsnlen.c @@ -0,0 +1,28 @@ +/* Multiple versions of wcsnlen. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc (__wcsnlen) +weak_alias (__wcsnlen, wcsnlen) + +#else +# include <wcsmbs/wcsnlen.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcspbrk-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcspbrk-c.c new file mode 100644 index 0000000000..0a2e4c8e4d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcspbrk-c.c @@ -0,0 +1,31 @@ +/* Default wcspbrk implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSPBRK __wcspbrk_c + +# include <wchar.h> +extern __typeof (wcspbrk) __wcspbrk_c; +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__wcspbrk_c, __GI_wcspbrk, __wcspbrk_c); +# endif /* SHARED */ + +# include <wcsmbs/wcspbrk.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcspbrk-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcspbrk-vx.S new file mode 100644 index 0000000000..267baf091d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcspbrk-vx.S @@ -0,0 +1,315 @@ +/* Vector optimized 32/64 bit S/390 version of wcspbrk. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t *wcspbrk (const wchar_t *s, const wchar_t * accept) + The wcspbrk() function locates the first occurrence in the string s + of any of the characters in the string accept and returns a pointer + to that character or NULL if not found. + + This method checks the length of accept string. If it fits entirely + in one vector register, a fast algorithm is used, which does not need + to check multiple parts of accept-string. Otherwise a slower full + check of accept-string is used. + + register overview: + r3: pointer to start of accept-string + r2: pointer to start of search-string + r0: loaded byte count of vlbb search-string (32bit unsigned) + r4: found byte index (32bit unsigned) + r1: current return len (64bit unsigned) + v16: search-string + v17: accept-string + v18: temp-vreg + + ONLY FOR SLOW: + v19: first accept-string + v20: zero for preparing acc-vector + v21: global mask; 1 indicates a match between + search-string-vreg and any accept-character + v22: current mask; 1 indicates a match between + search-string-vreg and any accept-character in current acc-vreg + v24: one for result-checking of former string-part + v30, v31: for re-/storing registers r6, r8, r9 + r5: current len of accept-string + r6: zero-index in search-string or 16 if no zero + or min(zero-index, loaded byte count) + r8: >0, if former accept-string-part contains a zero, + otherwise =0; + r9: loaded byte count of vlbb accept-string +*/ +ENTRY(__wcspbrk_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + /* + Check if accept-string fits in one vreg: + ---------------------------------------- + */ + vlbb %v17,0(%r3),6 /* Load accept. */ + lcbb %r0,0(%r3),6 + jo .Lcheck_onbb /* Special case if accept lays + on block-boundary. */ + +.Lcheck_notonbb: + lghi %r1,0 /* Zero out current len. */ + vlgvf %r0,%v17,0 /* Get first element. */ + clije %r0,0,.Lfast_end_null /* Return null if accept is empty. */ + + vistrfs %v17,%v17 /* Fill with zeros after first zero. */ + je .Lfast /* Zero found -> accept fits in one vreg. */ + j .Lslow /* No zero -> accept exceeds one vreg */ + + +.Lcheck_onbb: + /* Accept lays on block-boundary. */ + nill %r0,65532 /* Recognize only fully loaded characters. */ + je .Lcheck_onbb2 /* Reload vr, if we loaded no full wchar_t. */ + vfenezf %v18,%v17,%v17 /* Search zero in loaded accept bytes. */ + vlgvb %r4,%v18,7 /* Get index of zero or 16 if not found. */ + clrjl %r4,%r0,.Lcheck_notonbb /* Zero index < loaded bytes count -> + accept fits in one vreg; + Fill with zeros and proceed + with FAST. */ +.Lcheck_onbb2: + vl %v17,0(%r3) /* Load accept, which exceeds loaded bytes. */ + j .Lcheck_notonbb /* Check if accept fits in one vreg. */ + + + /* + Search s for accept in one vreg + ------------------------------- + */ +.Lfast: + /* Complete accept-string in v17 and remaining bytes are zero. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfaezfs %v18,%v16,%v17,0 /* Find first element in v16 unequal to any + in v17 or first zero element. */ + vlgvb %r4,%v18,7 /* Load byte index of found element. */ + /* If found index is within loaded bytes, return with found + element index (=equal count). */ + clrjl %r4,%r0,.Lfast_loop_found2 + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r1,16 /* current_len = 16. */ + slr %r1,%r4 /* Compute bytes to 16bytes boundary. */ + +.Lfast_loop: + vl %v16,0(%r1,%r2) /* Load search-string. */ + vfaezfs %v18,%v16,%v17,0 /* Find first element in v16 equal to any + in v17 or first zero element. */ + jno .Lfast_loop_found + + vl %v16,16(%r1,%r2) + vfaezfs %v18,%v16,%v17,0 + jno .Lfast_loop_found16 + + vl %v16,32(%r1,%r2) + vfaezfs %v18,%v16,%v17,0 + jno .Lfast_loop_found32 + + vl %v16,48(%r1,%r2) + vfaezfs %v18,%v16,%v17,0 + jno .Lfast_loop_found48 + + aghi %r1,64 + j .Lfast_loop /* Loop if no element was unequal to accept + and not zero. */ + + /* Found equal or zero element. */ +.Lfast_loop_found48: + aghi %r1,16 +.Lfast_loop_found32: + aghi %r1,16 +.Lfast_loop_found16: + aghi %r1,16 +.Lfast_loop_found: + vlgvb %r4,%v18,7 /* Load byte index of found element. */ +.Lfast_loop_found2: + srlg %r5,%r4,2 /* Convert byte-index to character-index. */ + vlgvf %r0,%v16,0(%r5) /* Get found element. */ + clije %r0,0,.Lfast_end_null /* Return null if no accept-char found */ + algfr %r1,%r4 /* Add found index of char to current len. */ + la %r2,0(%r1,%r2) /* And return pointer to first equal char. */ + br %r14 + +.Lfast_end_null: + lghi %r2,0 /* Return null if no character is equal. */ + br %r14 + + + + + /* + Search s for accept in multiple vregs + ------------------------------------- + */ +.Lslow: + /* Save registers. */ + vlvgg %v30,%r6,0 + vlvgp %v31,%r8,%r9 + + /* Accept in v17 without zero */ + vlr %v19,%v17 /* Save first acc-part for a fast reload. */ + vzero %v20 /* Zero for preparing acc-vector. */ + vone %v24 /* One for checking result of former string. */ + + /* Align s to 16 byte. */ + risbg %r4,%r2,60,128+63,0 /* Test if s is aligned and + %r4 = bits 60-63 'and' 15. */ + je .Lslow_loop_str /* If s is aligned, loop aligned. */ + lghi %r0,15 + slr %r0,%r4 /* Compute highest index to load (15-x). */ + vll %v16,%r0,0(%r2) /* Load up to 16byte boundary; + needs highest index, left bytes are 0. */ + ahi %r0,1 /* Work with loaded byte count. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of accept-string to zero. */ + vfenezf %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first accept-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + clije %r6,0,.Lslow_end_null /* If first element is zero + (end of string) -> return null */ + clr %r0,%r6 /* cc==1 if loaded byte count < zero-index. */ + locrl %r6,%r0 /* Load on cc==1; zero-index = lbc. */ + j .Lslow_loop_acc + + + /* Process s in 16byte aligned loop. */ +.Lslow_next_str: + /* Check results of former processed str-part. */ + vfeef %v18,%v21,%v24 /* Find first equal match in global mask + (ones in element). */ + vlgvb %r4,%v18,7 /* Get index of first one (=equal) + or 16 if no match. */ + /* Equal-index < min(zero-index, loaded byte count) + -> return pointer to equal element. */ + clrjl %r4,%r6,.Lslow_index_found + /* Zero-index < loaded byte count + -> former str-part was last str-part + -> return null */ + clrjl %r6,%r0,.Lslow_end_null + /* All elements are zero (=no match) -> proceed with next str-part. */ + + vlr %v17,%v19 /* Load first part of accept (no zero). */ + algfr %r1,%r0 /* Add loaded byte count to current len. */ + +.Lslow_loop_str: + vl %v16,0(%r1,%r2) /* Load search-string */ + lghi %r0,16 /* Loaded byte count is 16. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of accept to zero. */ + vfenezf %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first accept-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + clije %r6,0,.Lslow_end_null /* If first element is zero + (end of string) -> return null. */ + +.Lslow_loop_acc: + vfaef %v22,%v16,%v17,4 /* Create matching-mask (1 in mask -> + Character matches any accepted character in + this accept-string-part) IN=0, RT=1. */ + vlgvf %r4,%v22,0 /* Get result of first element. */ + /* First element is equal to any accepted characters + (all other parts of accept cannot lead to a match before this one) + -> current len is pointing to first element + -> return found */ + clijh %r4,0,.Lslow_end_found + vo %v21,%v21,%v22 /* Global-mask = global-|matching-mask. */ + /* Proceed with next acc until end of acc is reached. */ + + +.Lslow_next_acc: + clijh %r8,0,.Lslow_next_str /* There was a zero in the last acc-part + -> add index to current len and + end. */ + vlbb %v17,16(%r5,%r3),6 /* Load next accept part. */ + aghi %r5,16 /* Increment current len of accept-string. */ + lcbb %r9,0(%r5,%r3),6 /* Get loaded byte count of accept-string. */ + jo .Lslow_next_acc_onbb /* Jump away ifaccept-string is + on block-boundary. */ +.Lslow_next_acc_notonbb: + vistrfs %v17,%v17 /* Fill with zeros after first zero. */ + jo .Lslow_loop_acc /* No zero found -> no preparation needed. */ + +.Lslow_next_acc_prepare_zero: + /* Zero in accept-part: fill zeros with first-accept-character. */ + vlgvf %r8,%v17,0 /* Load first element of acc-part. */ + clije %r8,0,.Lslow_next_str /* Proceed with next string-part, + If first char in this part of accept + is a zero. */ + /* r8>0 -> zero found in this acc-part. */ + vrepf %v18,%v17,0 /* Replicate first char accross all chars. */ + vceqf %v22,%v20,%v17 /* Create a mask (v22) of null chars + by comparing with 0 (v20). */ + vsel %v17,%v18,%v17,%v22 /* Replace null chars with first char. */ + j .Lslow_loop_acc /* Accept part is prepared -> process. */ + +.Lslow_next_acc_onbb: + nill %r9,65532 /* Recognize only fully loaded characters. */ + je .Lslow_next_acc_onbb2 /* Reload vr, if no full wchar_t. */ + vfenezf %v18,%v17,%v17 /* Find zero in loaded bytes of accept part. */ + vlgvb %r8,%v18,7 /* Load byte index of zero. */ + clrjl %r8,%r9,.Lslow_next_acc_notonbb /* Found a zero in loaded bytes + -> Prepare vreg. */ +.Lslow_next_acc_onbb2: + vl %v17,0(%r5,%r3) /* Load over boundary ... */ + lghi %r8,0 /* r8=0 -> no zero in this part of acc, + check for zero is in jump-target. */ + j .Lslow_next_acc_notonbb /* ... and search for zero in + fully loaded vreg again. */ + +.Lslow_end_null: + lghi %r1,0 /* Return null if no character is equal. */ + j .Lslow_end + +.Lslow_loop_found: + vlgvb %r4,%v18,7 /* Load byte index of found element. */ + srlg %r5,%r4,2 /* Convert byte-index to character-index. */ + vlgvf %r0,%v16,0(%r5) /* Get found element. */ + clije %r0,0,.Lslow_end_null /* Return null if no acc-char found. */ + +.Lslow_index_found: + algfr %r1,%r4 /* Add found index of char to current len. */ +.Lslow_end_found: + la %r1,0(%r1,%r2) /* And return pointer to first equal char. */ + +.Lslow_end: + /* Restore registers. */ + vlgvg %r6,%v30,0 + vlgvg %r8,%v31,0 + vlgvg %r9,%v31,1 + lgr %r2,%r1 + br %r14 +.Lfallback: + jg __wcspbrk_c +END(__wcspbrk_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcspbrk.c b/REORG.TODO/sysdeps/s390/multiarch/wcspbrk.c new file mode 100644 index 0000000000..9f14f9a4f2 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcspbrk.c @@ -0,0 +1,29 @@ +/* Multiple versions of wcspbrk. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define wcspbrk __redirect_wcspbrk +# include <wchar.h> +# undef wcspbrk +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_wcspbrk, __wcspbrk, wcspbrk) + +#else +# include <wcsmbs/wcspbrk.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsrchr-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcsrchr-c.c new file mode 100644 index 0000000000..bc462a7c71 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsrchr-c.c @@ -0,0 +1,25 @@ +/* Default wcsrchr implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSRCHR __wcsrchr_c + +# include <wchar.h> +extern __typeof (wcsrchr) __wcsrchr_c; +# include <wcsmbs/wcsrchr.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsrchr-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcsrchr-vx.S new file mode 100644 index 0000000000..ba605f579d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsrchr-vx.S @@ -0,0 +1,190 @@ +/* Vector optimized 32/64 bit S/390 version of wcsrchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t *wcsrchr (const wchar_t *s, wchar_t c) + Locate the last character c in string. + + Register usage: + -r0=loaded bytes in first part of s. + -r1=pointer to last occurence of c or NULL if not found. + -r2=s + -r3=c + -r4=tmp + -r5=current_len + -v16=part of s + -v17=index of found element + -v18=replicated c + -v19=part of s with last occurence of c. + -v20=permute pattern +*/ +ENTRY(__wcsrchr_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + vlvgf %v18,%r3,0 /* Generate vector which elements are all c. */ + vrepf %v18,%v18,0 + + lghi %r1,-1 /* Currently no c found. */ + lghi %r5,0 /* current_len = 0. */ + + vfeezfs %v17,%v16,%v18 /* Find element equal or zero. */ + vlgvb %r4,%v17,7 /* Load byte index of c/zero or 16. */ + clrjl %r4,%r0,.Lfound_first_part /* Found c/zero in loaded bytes. */ +.Lalign: + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r5,16 /* current_len = 16. */ + slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ + +.Lloop: + vl %v16,0(%r5,%r2) /* Load s. */ + vfeezfs %v17,%v16,%v18 /* Find element equal with zero search. */ + jno .Lfound /* Found c/zero (cc=0|1|2). */ + vl %v16,16(%r5,%r2) + vfeezfs %v17,%v16,%v18 + jno .Lfound16 + vl %v16,32(%r5,%r2) + vfeezfs %v17,%v16,%v18 + jno .Lfound32 + vl %v16,48(%r5,%r2) + vfeezfs %v17,%v16,%v18 + jno .Lfound48 + + aghi %r5,64 + j .Lloop /* No character and no zero -> loop. */ + +.Lfound48: + la %r5,16(%r5) /* Use la since aghi would clobber cc. */ +.Lfound32: + la %r5,16(%r5) +.Lfound16: + la %r5,16(%r5) +.Lfound: + je .Lzero /* Found zero, but no c before that zero. */ + /* Save this part of s to check for further matches after reaching + the end of the complete string. */ + vlr %v19,%v16 + lgr %r1,%r5 + + jh .Lzero /* Found a zero after the found c. */ + aghi %r5,16 /* Start search of next part of s. */ + j .Lloop + +.Lfound_first_part: + /* This code is only executed if the found c/zero is whithin loaded + bytes. If no c/zero was found (cc==3) the found index = 16, thus + this code is not called. + Resulting condition code of vector find element equal: + cc==0: no c, found zero + cc==1: c found, no zero + cc==2: c found, found zero after c + cc==3: no c, no zero (this case can be ignored). */ + je .Lzero /* Found zero, but no c before that zero. */ + + locgrne %r1,%r5 /* Mark c as found in first part of s. */ + vlr %v19,%v16 + + jl .Lalign /* No zero (e.g. if vr was fully loaded) + -> Align and loop afterwards. */ + + /* Found a zero in vr. If vr was not fully loaded due to block + boundary, the remaining bytes are filled with zero and we can't + rely on zero indication of condition code here! */ + + vfenezf %v17,%v16,%v16 + vlgvb %r4,%v17,7 /* Load byte index of zero or 16. */ + clrjl %r4,%r0,.Lzero /* Zero within loaded bytes -> end. */ + j .Lalign /* Align and loop afterwards. */ + +.Lend_searched_zero: + vlgvb %r4,%v17,7 /* Load byte index of zero. */ + algr %r5,%r4 + la %r2,0(%r5,%r2) /* Return pointer to zero. */ + br %r14 + +.Lzero: + /* Reached end of string. Check if one c was found before. */ + clije %r3,0,.Lend_searched_zero /* Found zero and c is zero. */ + + cgfi %r1,-1 /* No c found -> return NULL. */ + locghie %r2,0 + ber %r14 + + larl %r3,.Lpermute_mask /* Load permute mask. */ + vl %v20,0(%r3) + + /* c was found and is part of v19. */ + vfenezf %v17,%v19,%v19 /* Find zero. */ + vlgvb %r4,%v17,7 /* Load byte index of zero or 16. */ + ahi %r4,3 /* Found zero index is first byte, + thus highest byte index is last byte of + wchar_t zero. */ + + clgfi %r5,0 /* Loaded byte count in v19 is 16, ... */ + lochine %r0,16 /* ... if v19 is not the first part of s. */ + ahi %r0,-1 /* Convert byte count to highest index. */ + + clr %r0,%r4 + locrl %r4,%r0 /* r4 = min (zero-index, highest-index). */ + + /* Right-shift of v19 to mask bytes after zero. */ + clije %r4,15,.Lzero_permute /* No shift is needed if highest index + in vr is 15. */ + lhi %r0,15 + slr %r0,%r4 /* Compute byte count for vector shift left. */ + sll %r0,3 /* Convert to bit count. */ + vlvgb %v17,%r0,7 + vsrlb %v19,%v19,%v17 /* Vector shift right by byte by number of bytes + specified in bits 1-4 of byte 7 in v17. */ + + /* Reverse bytes in v19. */ +.Lzero_permute: + vperm %v19,%v19,%v19,%v20 /* Permute v19 to reversed order. */ + + /* Find c in reversed v19. */ + vfeef %v19,%v19,%v18 /* Find c. */ + la %r2,0(%r1,%r2) + vlgvb %r3,%v19,7 /* Load byte index of c. */ + + /* Compute index in real s and return. */ + slgr %r4,%r3 + lay %r2,-3(%r4,%r2) /* Return pointer to zero. -3 is needed, + because the found byte index is reversed in + vector-register. Thus point to first byte of + wchar_t. */ + br %r14 +.Lpermute_mask: + .byte 0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x0A,0x0B + .byte 0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03 +.Lfallback: + jg __wcsrchr_c +END(__wcsrchr_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsrchr.c b/REORG.TODO/sysdeps/s390/multiarch/wcsrchr.c new file mode 100644 index 0000000000..cd3f695117 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsrchr.c @@ -0,0 +1,27 @@ +/* Multiple versions of wcsrchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2 (__wcsrchr, wcsrchr) + +#else +# include <wcsmbs/wcsrchr.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsspn-c.c b/REORG.TODO/sysdeps/s390/multiarch/wcsspn-c.c new file mode 100644 index 0000000000..7790556b0d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsspn-c.c @@ -0,0 +1,31 @@ +/* Default wcsspn implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WCSSPN __wcsspn_c + +# include <wchar.h> +extern __typeof (wcsspn) __wcsspn_c; +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__wcsspn_c, __GI_wcsspn, __wcsspn_c); +# endif /* SHARED */ + +# include <wcsmbs/wcsspn.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsspn-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wcsspn-vx.S new file mode 100644 index 0000000000..77806c3a50 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsspn-vx.S @@ -0,0 +1,270 @@ +/* Vector optimized 32/64 bit S/390 version of wcsspn. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* size_t wcsspn (const wchar_t *s, const wchar_t * accept) + The wcsspn() function calculates the length of the initial segment + of s which consists entirely of characters in accept. + + This method checks the length of accept string. If it fits entirely + in one vector register, a fast algorithm is used, which does not need + to check multiple parts of accept-string. Otherwise a slower full + check of accept-string is used. + + register overview: + r3: pointer to start of accept-string + r2: pointer to start of search-string + r4: loaded byte count of vl search-string + r0: found byte index + r1: current return len of s + v16: search-string + v17: accept-string + v18: temp-vreg + + ONLY FOR SLOW: + v19: first accept-string + v20: zero for preparing acc-vector + v21: global mask; 1 indicates a match between + search-string-vreg and any accept-character + v22: current mask; 1 indicates a match between + search-string-vreg and any accept-character in current acc-vreg + v30, v31: for re-/storing registers r6, r8, r9 + r5: current len of accept-string + r6: zero-index in search-string or 16 if no zero + or min(zero-index, loaded byte count) + r8: >0, if former accept-string-part contains a zero, + otherwise =0; + r9: loaded byte count of vlbb accept-string +*/ +ENTRY(__wcsspn_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + /* + Check if accept-string fits in one vreg: + ---------------------------------------- + */ + vlbb %v17,0(%r3),6 /* Load accept. */ + lcbb %r4,0(%r3),6 + jo .Lcheck_onbb /* Special case if accept lays + on block-boundary. */ +.Lcheck_notonbb: + vistrfs %v17,%v17 /* Fill with zeros after first zero. */ + je .Lfast /* Zero found -> accept fits in one vreg. */ + j .Lslow /* No zero -> accept exceeds one vreg. */ + +.Lcheck_onbb: + /* Accept lays on block-boundary. */ + nill %r4,65532 /* Recognize only fully loaded characters. */ + je .Lcheck_onbb2 /* Reload vr if no full wchar_t. */ + vfenezf %v18,%v17,%v17 /* Search zero in loaded accept bytes. */ + vlgvb %r0,%v18,7 /* Get index of zero or 16 if not found. */ + clrjl %r0,%r4,.Lcheck_notonbb /* Zero index < loaded bytes count -> + Accept fits in one vreg; + Fill with zeros and proceed + with FAST. */ +.Lcheck_onbb2: + vl %v17,0(%r3) /* Load accept, which exceeds loaded bytes. */ + j .Lcheck_notonbb /* Check if accept fits in one vreg. */ + + + /* + Search s for accept in one vreg + ------------------------------- + */ +.Lfast: + /* Complete accept-string in v17 and remaining bytes are zero. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + + vfaezfs %v16,%v16,%v17,8 /* Find first element in v16 + unequal to any in v17 + or first zero element. */ + + vlgvb %r0,%v16,7 /* Load byte index of found element. */ + /* If found index is within loaded bytes (%r0 < %r1), + return with found element index (=equal count). */ + clr %r0,%r1 + srlg %r0,%r0,2 /* Convert byte-count to character-count. */ + locgrl %r2,%r0 + blr %r14 + + /* Align s to 16 byte. */ + risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + lghi %r1,16 /* current_len = 16. */ + slr %r1,%r4 /* Compute bytes to 16bytes boundary. */ + +.Lfast_loop: + vl %v16,0(%r1,%r2) /* Load search-string. */ + vfaezfs %v16,%v16,%v17,8 /* Find first element in v16 + unequal to any in v17 + or first zero element. */ + jno .Lfast_loop_found + vl %v16,16(%r1,%r2) + vfaezfs %v16,%v16,%v17,8 + jno .Lfast_loop_found16 + vl %v16,32(%r1,%r2) + vfaezfs %v16,%v16,%v17,8 + jno .Lfast_loop_found32 + vl %v16,48(%r1,%r2) + vfaezfs %v16,%v16,%v17,8 + jno .Lfast_loop_found48 + + aghi %r1,64 + j .Lfast_loop /* Loop if no element was unequal to accept + and not zero. */ + + /* Found unequal or zero element. */ +.Lfast_loop_found48: + aghi %r1,16 +.Lfast_loop_found32: + aghi %r1,16 +.Lfast_loop_found16: + aghi %r1,16 +.Lfast_loop_found: + vlgvb %r0,%v16,7 /* Load byte index of found element. */ + algrk %r2,%r1,%r0 /* And add it to current len. */ + srlg %r2,%r2,2 /* Convert byte-count to character-count. */ + br %r14 + + + /* + Search s for accept in multiple vregs + ------------------------------------- + */ +.Lslow: + /* Save registers. */ + vlvgg %v30,%r6,0 + vlvgp %v31,%r8,%r9 + lghi %r1,0 /* Zero out current len. */ + + /* accept in v17 without zero. */ + vlr %v19,%v17 /* Save first acc-part for a fast reload. */ + vzero %v20 /* Zero for preparing acc-vector. */ + + /* Align s to 16 byte. */ + risbg %r0,%r2,60,128+63,0 /* Test if s is aligned and + %r0 = bits 60-63 'and' 15. */ + je .Lslow_loop_str /* If s is aligned, loop aligned */ + lghi %r4,15 + slr %r4,%r0 /* Compute highest index to load (15-x). */ + vll %v16,%r4,0(%r2) /* Load up to 16byte boundary (vll needs + highest index, remaining bytes are 0). */ + aghi %r4,1 /* Work with loaded byte count. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of accept-string to zero. */ + vfenezf %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first accept-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 + if there is no zero. */ + clr %r4,%r6 /* cc==1 if loaded byte count < zero-index. */ + locrl %r6,%r4 /* Load on cc==1. */ + j .Lslow_loop_acc + + /* Process s in 16byte aligned loop. */ +.Lslow_next_str: + vlr %v17,%v19 /* Load first part of accept (no zero). */ + algfr %r1,%r4 /* Add loaded byte count to current len. */ +.Lslow_loop_str: + vl %v16,0(%r1,%r2) /* Load search-string. */ + lghi %r4,16 /* Loaded byte count is 16. */ + vzero %v21 /* Zero out global mask. */ + lghi %r5,0 /* Set current len of accept-string to zero. */ + vfenezf %v18,%v16,%v16 /* Find zero in current string-part. */ + lghi %r8,0 /* There is no zero in first accept-part. */ + vlgvb %r6,%v18,7 /* Load byte index of zero or 16 if no zero. */ + +.Lslow_loop_acc: + vfaef %v22,%v16,%v17,4 /* Create matching-mask (1 in mask -> + character matches any accepted character in + this accept-string-part) IN=0, RT=1. */ + vo %v21,%v21,%v22 /* global-mask = global- | matching-mask. */ + vfenezf %v18,%v21,%v21 /* Find first zero in global-mask. */ + vlgvb %r0,%v18,7 /* Get first found zero-index + (= first mismatch). */ + clrjl %r0,%r6,.Lslow_next_acc /* Mismatch-index < min(lbc,zero-index) + -> Process this string-part + with next acc-part. */ + clrjhe %r0,%r4,.Lslow_next_str /* Found-index >= loaded byte count + -> All loaded bytes are matching + any accept-character + and are not zero. */ + /* All bytes are matching any characters in accept-string + and search-string is fully processed (found-index == zero-index). */ +.Lslow_add_lbc_end: + algrk %r2,%r1,%r0 /* Add matching characters to current len. */ + srlg %r2,%r2,2 /* Convert byte-count to character-count. */ + /* Restore registers. */ + vlgvg %r6,%v30,0 + vlgvg %r8,%v31,0 + vlgvg %r9,%v31,1 + br %r14 + +.Lslow_next_acc: + clijh %r8,0,.Lslow_add_lbc_end /* There was a zero in last acc-part + -> Add found index to current len + and end. */ + vlbb %v17,16(%r5,%r3),6 /* Load next accept part. */ + aghi %r5,16 /* Increment current len of accept-string. */ + lcbb %r9,0(%r5,%r3),6 /* Get loaded byte count of accept-string. */ + jo .Lslow_next_acc_onbb /* Jump away if accept-string is + on block-boundary. */ +.Lslow_next_acc_notonbb: + vistrfs %v17,%v17 /* Fill with zeros after first zero. */ + jo .Lslow_loop_acc /* No zero found -> no preparation needed. */ + +.Lslow_next_acc_prepare_zero: + /* Zero in accept-part: fill zeros with first-accept-character. */ + vlgvf %r8,%v17,0 /* Load first element of acc-part. */ + clije %r8,0,.Lslow_add_lbc_end /* End if zero is first character + in this part of accept-string. */ + /* r8>0 -> zero found in this acc-part. */ + vrepf %v18,%v17,0 /* Replicate first char accross all chars. */ + vceqf %v22,%v20,%v17 /* Create a mask (v22) of null chars + by comparing with 0 (v20). */ + vsel %v17,%v18,%v17,%v22 /* Replace null chars with first char. */ + j .Lslow_loop_acc /* Accept part is prepared -> process. */ + +.Lslow_next_acc_onbb: + nill %r9,65532 /* Recognize only fully loaded characters. */ + je .Lslow_next_acc_onbb2 /* Reload vr, if we loaded no full + wchar_t. */ + vfenezf %v18,%v17,%v17 /* Find zero in loaded bytes of accept part. */ + vlgvb %r8,%v18,7 /* Load byte index of zero. */ + clrjl %r8,%r9,.Lslow_next_acc_notonbb /* Found a zero in loaded bytes + -> Prepare vreg. */ +.Lslow_next_acc_onbb2: + vl %v17,0(%r5,%r3) /* Load over boundary ... */ + lghi %r8,0 /* r8=0 -> no zero in this part of acc, + check for zero is in jump-target. */ + j .Lslow_next_acc_notonbb /* ... and search for zero in + fully loaded vreg again. */ +.Lfallback: + jg __wcsspn_c +END(__wcsspn_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wcsspn.c b/REORG.TODO/sysdeps/s390/multiarch/wcsspn.c new file mode 100644 index 0000000000..6eaec7dd65 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wcsspn.c @@ -0,0 +1,29 @@ +/* Multiple versions of wcsspn. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define wcsspn __redirect_wcsspn +# include <wchar.h> +# undef wcsspn +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2_redirected (__redirect_wcsspn, __wcsspn, wcsspn) + +#else +# include <wcsmbs/wcsspn.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemchr-c.c b/REORG.TODO/sysdeps/s390/multiarch/wmemchr-c.c new file mode 100644 index 0000000000..0d04494ac8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemchr-c.c @@ -0,0 +1,37 @@ +/* Default wmemchr implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WMEMCHR __wmemchr_c + +# include <wchar.h> +extern __typeof (wmemchr) __wmemchr_c; +# undef weak_alias +# define weak_alias(name, alias) +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__wmemchr_c, __GI___wmemchr, __wmemchr_c); +# undef libc_hidden_weak +# define libc_hidden_weak(name) \ + strong_alias (__wmemchr_c, __wmemchr_c_1); \ + __hidden_ver1 (__wmemchr_c_1, __GI_wmemchr, __wmemchr_c_1); +# endif /* SHARED */ + +# include <wcsmbs/wmemchr.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemchr-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wmemchr-vx.S new file mode 100644 index 0000000000..f5ab76e5bc --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemchr-vx.S @@ -0,0 +1,166 @@ +/* Vector optimized 32/64 bit S/390 version of wmemchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t *wmemchr (const wchar_t *s, wchar_t c, size_t n) + Scans memory for character c + and returns pointer to first c. + + Register usage: + -r0=tmp + -r1=tmp + -r2=s + -r3=c + -r4=n + -r5=current_len + -v16=part of s + -v17=index of found c + -v18=c replicated +*/ +ENTRY(__wmemchr_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + clgije %r4,0,.Lnf_end /* If len == 0 then exit. */ + + vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ + lcbb %r0,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ + llgfr %r0,%r0 /* Convert 32bit to 64bit. */ + + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + + vlvgf %v18,%r3,0 /* Generate vector which elements are all c. */ + vrepf %v18,%v18,0 + lghi %r5,16 /* current_len = 16. */ + + /* Check range of maxlen and convert to byte-count. */ +# ifdef __s390x__ + tmhh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + lghi %r1,-4 /* Max byte-count is 18446744073709551612. */ +# else + tmlh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + llilf %r1,4294967292 /* Max byte-count is 4294967292. */ +# endif /* !__s390x__ */ + sllg %r4,%r4,2 /* Convert character-count to byte-count. */ + locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ + + clgrjhe %r0,%r4,.Llastcmp /* If (bytes to boundary) >= n, + jump to lastcmp. */ + + vfeefs %v17,%v16,%v18 /* Find c. */ + vlgvb %r1,%v17,7 /* Load byte index of c. */ + clgrjl %r1,%r0,.Lfound2 /* Found c is within loaded bytes. */ + + /* Align s to 16 byte. */ + risbgn %r1,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ + slr %r5,%r1 /* Compute bytes to 16bytes boundary. */ + + lgr %r0,%r5 /* If %r5 + 64 < n? -> loop64. */ + aghi %r0,64 + clgrjl %r0,%r4,.Lloop64 +.Llt64: + vl %v16,0(%r5,%r2) + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp /* Do last compare if curr-len >= n. */ + vfeefs %v17,%v16,%v18 /* Find c. */ + jl .Lfound /* Jump away if c was found. */ + + vl %v16,0(%r5,%r2) + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp + vfeefs %v17,%v16,%v18 + jl .Lfound + + vl %v16,0(%r5,%r2) + aghi %r5,16 + clgrjhe %r5,%r4,.Llastcmp + vfeefs %v17,%v16,%v18 + jl .Lfound + + vl %v16,0(%r5,%r2) + aghi %r5,16 + +.Llastcmp: + /* Use comparision result only if located within first n characters. + %r5: current_len; + %r4: n; + (current_len - n): [0...16[ + first ignored match index = vr-width - (current_len - n) ]0...16] + */ + vfeefs %v17,%v16,%v18 /* Find c. */ + slgrk %r4,%r5,%r4 /* %r5 = current_len - n. */ + lghi %r0,16 /* Register width = 16. */ + vlgvb %r1,%v17,7 /* Extract found index or 16 if all equal. */ + slr %r0,%r4 /* %r0 = first ignored match index. */ + clrjl %r1,%r0,.Lfound2 /* Go away if miscompare is below n bytes. */ + /* c not found within n-bytes. */ +.Lnf_end: + lghi %r2,0 /* Return null. */ + br %r14 + +.Lfound48: + aghi %r5,16 +.Lfound32: + aghi %r5,16 +.Lfound16: + aghi %r5,16 +.Lfound0: + aghi %r5,16 +.Lfound: + vlgvb %r1,%v17,7 /* Load byte index of c. */ +.Lfound2: + slgfi %r5,16 /* current_len -=16 */ + algr %r5,%r1 /* Zero byte index is added to current len. */ + la %r2,0(%r5,%r2) /* Return pointer to c. */ + br %r14 + +.Lloop64: + vl %v16,0(%r5,%r2) + vfeefs %v17,%v16,%v18 /* Find c. */ + jl .Lfound0 /* Jump away if c was found. */ + vl %v16,16(%r5,%r2) + vfeefs %v17,%v16,%v18 + jl .Lfound16 + vl %v16,32(%r5,%r2) + vfeefs %v17,%v16,%v18 + jl .Lfound32 + vl %v16,48(%r5,%r2) + vfeefs %v17,%v16,%v18 + jl .Lfound48 + + aghi %r5,64 + lgr %r0,%r5 /* If %r5 + 64 < n? -> loop64. */ + aghi %r0,64 + clgrjl %r0,%r4,.Lloop64 + + j .Llt64 +.Lfallback: + jg __wmemchr_c +END(__wmemchr_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemchr.c b/REORG.TODO/sysdeps/s390/multiarch/wmemchr.c new file mode 100644 index 0000000000..efb4d64e2b --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemchr.c @@ -0,0 +1,32 @@ +/* Multiple versions of wmemchr. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define wmemchr __redirect_wmemchr +# define __wmemchr __redirect___wmemchr +# include <wchar.h> +# undef wmemchr +# undef __wmemchr +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc_redirected (__redirect___wmemchr, __wmemchr) +weak_alias (__wmemchr, wmemchr) + +#else +# include <wcsmbs/wmemchr.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemcmp-c.c b/REORG.TODO/sysdeps/s390/multiarch/wmemcmp-c.c new file mode 100644 index 0000000000..bdd8995634 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemcmp-c.c @@ -0,0 +1,26 @@ +/* Default wmemcmp implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WMEMCMP __wmemcmp_c + +# include <wchar.h> +extern __typeof (wmemcmp) __wmemcmp_c; + +# include <wcsmbs/wmemcmp.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemcmp-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wmemcmp-vx.S new file mode 100644 index 0000000000..40e71e5a65 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemcmp-vx.S @@ -0,0 +1,149 @@ +/* Vector Optimized 32/64 bit S/390 version of wmemcmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* int wmemcmp (const wchar_t *s1, const wchar_t *s2, size_t n) + Compare at most n characters of two wchar_t-arrays. + + Register usage: + -r0=tmp + -r1=number of blocks + -r2=s1 + -r3=s2 + -r4=n + -r5=current_len + -v16=part of s1 + -v17=part of s2 + -v18=index of unequal +*/ +ENTRY(__wmemcmp_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + clgije %r4,0,.Lend_equal /* Nothing to do if n == 0. */ + + /* Check range of maxlen and convert to byte-count. */ +# ifdef __s390x__ + tmhh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + lghi %r1,-4 /* Max byte-count is 18446744073709551612. */ +# else + tmlh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + llilf %r1,4294967292 /* Max byte-count is 4294967292. */ +# endif /* !__s390x__ */ + sllg %r4,%r4,2 /* Convert character-count to byte-count. */ + locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ + + lghi %r5,0 /* current_len = 0. */ + + clgijh %r4,16,.Lgt16 + +.Lremaining: + aghi %r4,-1 /* vstl needs highest index. */ + vll %v16,%r4,0(%r2) + vll %v17,%r4,0(%r3) + vfenef %v18,%v16,%v17 /* Compare not equal. */ + vlgvb %r1,%v18,7 /* Load unequal index or 16 if not found. */ + clrj %r1,%r4,12,.Lfound2 /* r1 <= r4 -> unequal within loaded + bytes. */ + +.Lend_equal: + lghi %r2,0 + br %r14 + +.Lfound: + /* vfenezf found an unequal element or zero. + This instruction compares unsigned words, but wchar_t is signed. + Thus we have to compare the found element again. */ + vlgvb %r1,%v18,7 /* Extract not equal byte-index. */ +.Lfound2: + srl %r1,2 /* And convert it to character-index. */ + vlgvf %r0,%v16,0(%r1) /* Load character-values. */ + vlgvf %r1,%v17,0(%r1) + cr %r0,%r1 + je .Lend_equal + lghi %r2,1 + lghi %r1,-1 + locgrl %r2,%r1 + br %r14 + +.Lgt16: + clgijh %r4,64,.Lpreloop64 + +.Lpreloop16: + srlg %r1,%r4,4 /* Split into 16byte blocks */ +.Lloop16: + vl %v16,0(%r5,%r2) + vl %v17,0(%r5,%r3) + aghi %r5,16 + vfenefs %v18,%v16,%v17 /* Compare not equal. */ + jno .Lfound + brctg %r1,.Lloop16 /* Loop until all blocks are processed. */ + + llgfr %r4,%r4 + nilf %r4,15 /* Get remaining bytes */ + locgre %r2,%r4 + ber %r14 + la %r2,0(%r5,%r2) + la %r3,0(%r5,%r3) + j .Lremaining + +.Lpreloop64: + srlg %r1,%r4,6 /* Split into 64byte blocks */ +.Lloop64: + vl %v16,0(%r5,%r2) + vl %v17,0(%r5,%r3) + vfenefs %v18,%v16,%v17 /* Compare not equal. */ + jno .Lfound + + vl %v16,16(%r5,%r2) + vl %v17,16(%r5,%r3) + vfenefs %v18,%v16,%v17 + jno .Lfound + + vl %v16,32(%r5,%r2) + vl %v17,32(%r5,%r3) + vfenefs %v18,%v16,%v17 + jno .Lfound + + vl %v16,48(%r5,%r2) + vl %v17,48(%r5,%r3) + aghi %r5,64 + vfenefs %v18,%v16,%v17 + jno .Lfound + + brctg %r1,.Lloop64 /* Loop until all blocks are processed. */ + + llgfr %r4,%r4 + nilf %r4,63 /* Get remaining bytes */ + locgre %r2,%r4 + ber %r14 + clgijh %r4,16,.Lpreloop16 + la %r2,0(%r5,%r2) + la %r3,0(%r5,%r3) + j .Lremaining +END(__wmemcmp_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemcmp.c b/REORG.TODO/sysdeps/s390/multiarch/wmemcmp.c new file mode 100644 index 0000000000..59471a36b2 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemcmp.c @@ -0,0 +1,27 @@ +/* Multiple versions of wmemcmp. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include <wchar.h> +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc2 (__wmemcmp, wmemcmp) + +#else +# include <wcsmbs/wmemcmp.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemset-c.c b/REORG.TODO/sysdeps/s390/multiarch/wmemset-c.c new file mode 100644 index 0000000000..9d5a848ec8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemset-c.c @@ -0,0 +1,37 @@ +/* Default wmemset implementation for S/390. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define WMEMSET __wmemset_c + +# include <wchar.h> +extern __typeof (__wmemset) __wmemset_c; +# undef weak_alias +# define weak_alias(name, alias) +# ifdef SHARED +# undef libc_hidden_def +# define libc_hidden_def(name) \ + __hidden_ver1 (__wmemset_c, __GI___wmemset, __wmemset_c); +# undef libc_hidden_weak +# define libc_hidden_weak(name) \ + strong_alias (__wmemset_c, __wmemset_c_1); \ + __hidden_ver1 (__wmemset_c_1, __GI_wmemset, __wmemset_c_1); +# endif /* SHARED */ + +# include <wcsmbs/wmemset.c> +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemset-vx.S b/REORG.TODO/sysdeps/s390/multiarch/wmemset-vx.S new file mode 100644 index 0000000000..6b76dead18 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemset-vx.S @@ -0,0 +1,142 @@ +/* Vector Optimized 32/64 bit S/390 version of wmemset. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* wchar_t *wmemset(wchar_t *dest, wchar_t wc, size_t n) + Fill an array of wide-characters with a constant wide character + and returns dest. + + Register usage: + -r0=tmp + -r1=tmp + -r2=dest or current-pointer + -r3=wc + -r4=n + -r5=tmp + -v16=replicated wc + -v17,v18,v19=copy of v16 for vstm + -v31=saved dest for return +*/ +ENTRY(__wmemset_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r4,%r4 +# endif /* !defined __s390x__ */ + + vlvgg %v31,%r2,0 /* Save destination pointer for return. */ + clgije %r4,0,.Lend + + vlvgf %v16,%r3,0 /* Generate vector with wchar_t wc. */ + vrepf %v16,%v16,0 + + /* Check range of maxlen and convert to byte-count. */ +# ifdef __s390x__ + tmhh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + lghi %r5,-4 /* Max byte-count is 18446744073709551612. */ +# else + tmlh %r4,49152 /* Test bit 0 or 1 of maxlen. */ + llilf %r5,4294967292 /* Max byte-count is 4294967292. */ +# endif /* !__s390x__ */ + sllg %r4,%r4,2 /* Convert character-count to byte-count. */ + locgrne %r4,%r5 /* Use max byte-count, if bit 0/1 was one. */ + + /* Align dest to 16 byte. */ + risbg %r0,%r2,60,128+63,0 /* Test if s is aligned and + %r3 = bits 60-63 'and' 15. */ + je .Lpreloop /* If s is aligned, loop aligned. */ + tmll %r2,3 /* Test if s is 4-byte aligned? */ + jne .Lfallback /* And use common-code variant if not. */ + lghi %r1,16 + slr %r1,%r0 /* Compute byte count to load (16-x). */ + clgr %r1,%r4 + locgrh %r1,%r4 /* min (byte count, n) */ + aghik %r5,%r1,-1 /* vstl needs highest index. */ + vstl %v16,%r5,0(%r2) /* Store remaining bytes. */ + clgrje %r1,%r4,.Lend /* Return if n bytes where set. */ + slgr %r4,%r1 /* Compute remaining byte count. */ + la %r2,0(%r1,%r2) + +.Lpreloop: + /* Now we are 16-byte aligned. */ + clgijl %r4,17,.Lremaining + srlg %r1,%r4,8 /* Split into 256byte blocks */ + clgije %r1,0,.Lpreloop64 + vlr %v17,%v16 + vlr %v18,%v16 + vlr %v19,%v16 + +.Lloop256: + vstm %v16,%v19,0(%r2) + vstm %v16,%v19,64(%r2) + vstm %v16,%v19,128(%r2) + vstm %v16,%v19,192(%r2) + la %r2,256(%r2) + brctg %r1,.Lloop256 /* Loop until all blocks are processed. */ + + llgfr %r4,%r4 + nilf %r4,255 /* Get remaining bytes */ + je .Lend /* Skip store remaining bytes if zero. */ + +.Lpreloop64: + clgijl %r4,17,.Lremaining + clgijl %r4,33,.Lpreloop16 + srlg %r1,%r4,5 /* Split into 32byte blocks */ + +.Lloop32: + vst %v16,0(%r2) + vst %v16,16(%r2) + la %r2,32(%r2) + brctg %r1,.Lloop32 /* Loop until all blocks are processed. */ + + llgfr %r4,%r4 + nilf %r4,31 /* Get remaining bytes */ + je .Lend /* Skip store remaining bytes if zero. */ + +.Lpreloop16: + clgijl %r4,17,.Lremaining + srlg %r1,%r4,4 /* Split into 16byte blocks */ + +.Lloop16: + vst %v16,0(%r2) + la %r2,16(%r2) + brctg %r1,.Lloop16 /* Loop until all blocks are processed. */ + + llgfr %r4,%r4 + nilf %r4,15 /* Get remaining bytes */ + je .Lend /* Skip store remaining bytes if zero. */ + +.Lremaining: + aghi %r4,-1 /* vstl needs highest index. */ + vstl %v16,%r4,0(%r2) + +.Lend: + vlgvg %r2,%v31,0 /* Load saved dest for return value. */ + br %r14 +.Lfallback: + srlg %r4,%r4,2 /* Convert byte-count to character-count. */ + jg __wmemset_c +END(__wmemset_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/REORG.TODO/sysdeps/s390/multiarch/wmemset.c b/REORG.TODO/sysdeps/s390/multiarch/wmemset.c new file mode 100644 index 0000000000..d3eea1cee0 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/multiarch/wmemset.c @@ -0,0 +1,32 @@ +/* Multiple versions of wmemset. + Copyright (C) 2015-2017 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 HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define wmemset __redirect_wmemset +# define __wmemset __redirect___wmemset +# include <wchar.h> +# undef wmemset +# undef __wmemset +# include <ifunc-resolve.h> + +s390_vx_libc_ifunc_redirected (__redirect___wmemset, __wmemset) +weak_alias (__wmemset, wmemset) + +#else +# include <wcsmbs/wmemset.c> +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ diff --git a/REORG.TODO/sysdeps/s390/nptl/Makefile b/REORG.TODO/sysdeps/s390/nptl/Makefile new file mode 100644 index 0000000000..f5957b9060 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/nptl/Makefile @@ -0,0 +1,25 @@ +# Copyright (C) 2003-2017 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/>. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif + +ifeq ($(subdir),nptl) +libpthread-routines += sysdep +libpthread-shared-only-routines += sysdep +endif diff --git a/REORG.TODO/sysdeps/s390/nptl/bits/pthreadtypes-arch.h b/REORG.TODO/sysdeps/s390/nptl/bits/pthreadtypes-arch.h new file mode 100644 index 0000000000..3a9ac57625 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/nptl/bits/pthreadtypes-arch.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2003-2017 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/>. */ + +#ifndef _BITS_PTHREADTYPES_ARCH_H +#define _BITS_PTHREADTYPES_ARCH_H 1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +#endif +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + +/* Definitions for internal mutex struct. */ +#define __PTHREAD_COMPAT_PADDING_MID +#define __PTHREAD_COMPAT_PADDING_END +#ifdef ENABLE_LOCK_ELISION +#define __PTHREAD_MUTEX_LOCK_ELISION 1 +#else +#define __PTHREAD_MUTEX_LOCK_ELISION 0 +#endif + +#define __LOCK_ALIGNMENT +#define __ONCE_ALIGNMENT + +struct __pthread_rwlock_arch_t +{ + unsigned int __readers; + unsigned int __writers; + unsigned int __wrphase_futex; + unsigned int __writers_futex; + unsigned int __pad3; + unsigned int __pad4; +#if __WORDSIZE == 64 + int __cur_writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; +# else + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + int __cur_writer; +#endif +}; + +#define __PTHREAD_RWLOCK_ELISION_EXTRA 0 + +#endif /* bits/pthreadtypes.h */ diff --git a/REORG.TODO/sysdeps/s390/nptl/bits/semaphore.h b/REORG.TODO/sysdeps/s390/nptl/bits/semaphore.h new file mode 100644 index 0000000000..976a136fd2 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/nptl/bits/semaphore.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. + + 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/>. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/REORG.TODO/sysdeps/s390/nptl/pthreaddef.h b/REORG.TODO/sysdeps/s390/nptl/pthreaddef.h new file mode 100644 index 0000000000..a5ae960c7d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/nptl/pthreaddef.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2003-2017 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/>. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. SSE requires 16 + bytes. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) diff --git a/REORG.TODO/sysdeps/s390/nptl/tcb-offsets.sym b/REORG.TODO/sysdeps/s390/nptl/tcb-offsets.sym new file mode 100644 index 0000000000..9c1c01f353 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/nptl/tcb-offsets.sym @@ -0,0 +1,6 @@ +#include <sysdep.h> +#include <tls.h> + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +STACK_GUARD offsetof (tcbhead_t, stack_guard) +TID offsetof (struct pthread, tid) diff --git a/REORG.TODO/sysdeps/s390/nptl/tls.h b/REORG.TODO/sysdeps/s390/nptl/tls.h new file mode 100644 index 0000000000..7bc6c897b3 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/nptl/tls.h @@ -0,0 +1,196 @@ +/* Definition for thread-local data handling. NPTL/s390 version. + Copyright (C) 2003-2017 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/>. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#include <dl-sysdep.h> +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> +# include <list.h> +# include <kernel-features.h> +# include <dl-dtv.h> + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; + int gscope_flag; +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#else + int __glibc_reserved1; +#endif + /* GCC split stack support. */ + void *__private_ss; +} tcbhead_t; + +# ifndef __s390x__ +# define TLS_MULTIPLE_THREADS_IN_TCB 1 +# endif + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif + + +/* Alignment requirement for the stack. For IA-32 this is governed by + the SSE memory functions. */ +#define STACK_ALIGN 16 + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 +# define TLS_DTV_AT_TP 0 + +/* Get the thread descriptor definition. */ +# include <nptl/descr.h> + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +#if defined NEED_DL_SYSINFO && defined SHARED +# define INIT_SYSINFO \ + _head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(thrdescr) \ + ({ void *_thrdescr = (thrdescr); \ + tcbhead_t *_head = _thrdescr; \ + \ + _head->tcb = _thrdescr; \ + /* For now the thread descriptor is at the same address. */ \ + _head->self = _thrdescr; \ + /* New syscall handling support. */ \ + INIT_SYSINFO; \ + \ + __builtin_set_thread_pointer (_thrdescr); \ + NULL; \ + }) + +/* Value passed to 'clone' for initialization of the thread register. */ +# define TLS_DEFINE_INIT_TP(tp, pd) void *tp = (pd) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF ((struct pthread *) __builtin_thread_pointer ()) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF REGISTER (32, 32, 18 * 4, 0) \ + REGISTER (64, __WORDSIZE, 18 * 8, 0) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + do \ + { \ + __asm__ __volatile__ ("" : : : "a0", "a1"); \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value); \ + } \ + while (0) +#define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + +/* s390 doesn't have HP_TIMING_*, so for the time being + use stack_guard as pointer_guard. */ +#define THREAD_GET_POINTER_GUARD() \ + THREAD_GETMEM (THREAD_SELF, header.stack_guard) +#define THREAD_SET_POINTER_GUARD(value) ((void) (value)) +#define THREAD_COPY_POINTER_GUARD(descr) + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/REORG.TODO/sysdeps/s390/preconfigure b/REORG.TODO/sysdeps/s390/preconfigure new file mode 100644 index 0000000000..d6302b0c15 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/preconfigure @@ -0,0 +1,6 @@ +# preconfigure fragment for s390. + +case "$machine" in +s390) base_machine=s390 machine=s390/s390-32 ;; +s390x) base_machine=s390 machine=s390/s390-64 ;; +esac diff --git a/REORG.TODO/sysdeps/s390/s390-32/Implies b/REORG.TODO/sysdeps/s390/s390-32/Implies new file mode 100644 index 0000000000..39a34c5f57 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/Implies @@ -0,0 +1 @@ +wordsize-32 diff --git a/REORG.TODO/sysdeps/s390/s390-32/Makefile b/REORG.TODO/sysdeps/s390/s390-32/Makefile new file mode 100644 index 0000000000..a07f2986ae --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/Makefile @@ -0,0 +1,9 @@ +ifeq ($(subdir),gmon) +sysdep_routines += s390-mcount +endif + +ifeq ($(subdir),elf) +CFLAGS-rtld.c += -Wno-uninitialized -Wno-unused +CFLAGS-dl-load.c += -Wno-unused +CFLAGS-dl-reloc.c += -Wno-unused +endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/Versions b/REORG.TODO/sysdeps/s390/s390-32/Versions new file mode 100644 index 0000000000..2b020f8f58 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/Versions @@ -0,0 +1,6 @@ +libc { + GLIBC_2.0 { + # Functions from libgcc. + __divdi3; __moddi3; __udivdi3; __umoddi3; + } +} diff --git a/REORG.TODO/sysdeps/s390/s390-32/__longjmp.c b/REORG.TODO/sysdeps/s390/s390-32/__longjmp.c new file mode 100644 index 0000000000..abdd9641e6 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/__longjmp.c @@ -0,0 +1,83 @@ +/* Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +#include <errno.h> +#include <sysdep.h> +#include <setjmp.h> +#include <bits/setjmp.h> +#include <stdlib.h> +#include <unistd.h> +#include <stap-probe.h> + +/* Jump to the position specified by ENV, causing the + setjmp call there to return VAL, or 1 if VAL is 0. */ +void +__longjmp (__jmp_buf env, int val) +{ +#ifdef PTR_DEMANGLE + uintptr_t guard = THREAD_GET_POINTER_GUARD (); +# ifdef CHECK_SP + CHECK_SP (env, guard); +# endif +#elif defined CHECK_SP + CHECK_SP (env, 0); +#endif + register int r2 __asm__ ("%r2") = val == 0 ? 1 : val; +#ifdef PTR_DEMANGLE + register uintptr_t r3 __asm__ ("%r3") = guard; + register void *r1 __asm__ ("%r1") = (void *) env; +#endif + /* Restore registers and jump back. */ + __asm__ __volatile__ ( + /* longjmp probe expects longjmp first argument, second + argument and target address. */ +#ifdef PTR_DEMANGLE + "lm %%r4,%%r5,32(%1)\n\t" + "xr %%r4,%2\n\t" + "xr %%r5,%2\n\t" + LIBC_PROBE_ASM (longjmp, 4@%1 -4@%0 4@%%r4) +#else + LIBC_PROBE_ASM (longjmp, 4@%1 -4@%0 4@%%r14) +#endif + + /* restore fpregs */ + "ld %%f6,48(%1)\n\t" + "ld %%f4,40(%1)\n\t" + + /* restore gregs and return to jmp_buf target */ +#ifdef PTR_DEMANGLE + "lm %%r6,%%r13,0(%1)\n\t" + "lr %%r15,%%r5\n\t" + LIBC_PROBE_ASM (longjmp_target, 4@%1 -4@%0 4@%%r4) + "br %%r4" +#else + "lm %%r6,%%r15,0(%1)\n\t" + LIBC_PROBE_ASM (longjmp_target, 4@%1 -4@%0 4@%%r14) + "br %%r14" +#endif + : : "r" (r2), +#ifdef PTR_DEMANGLE + "r" (r1), "r" (r3) +#else + "a" (env) +#endif + ); + + /* Avoid `volatile function does return' warnings. */ + for (;;); +} diff --git a/REORG.TODO/sysdeps/s390/s390-32/add_n.S b/REORG.TODO/sysdeps/s390/s390-32/add_n.S new file mode 100644 index 0000000000..ed9cc27693 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/add_n.S @@ -0,0 +1,63 @@ +/* Add two limb vectors of the same length > 0 and store sum in a third + limb vector. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU MP Library. + + The GNU MP 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 MP 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 MP Library; see the file COPYING.LIB. If not, + see <http://www.gnu.org/licenses/>. */ + +/* + INPUT PARAMETERS + res_ptr %r2 + s1_ptr %r3 + s2_ptr %r4 + size %r5 +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(__mpn_add_n) + st %r6,24(%r15) # save register 6 + cfi_offset (%r6, -72) + sr %r1,%r1 + lhi %r0,1 # cannot use ahi to add carry, use alr +.L0: l %r6,0(%r1,%r3) # .L0 -> no carry from last add + al %r6,0(%r1,%r4) + st %r6,0(%r1,%r2) + la %r1,4(0,%r1) + brc 3,.L3 +.L1: brct %r5,.L0 + slr %r2,%r2 # no last carry to return + j .Lexit +.L2: l %r6,0(%r1,%r3) # .L2 -> carry from last add + al %r6,0(%r1,%r4) + brc 3,.L4 + alr %r6,%r0 # no carry yet, add carry from last add + st %r6,0(%r1,%r2) + la %r1,4(0,%r1) + brc 12,.L1 # new carry ? +.L3: brct %r5,.L2 + lr %r2,%r0 # return last carry + j .Lexit +.L4: alr %r6,%r0 # already a carry, add carry from last add + st %r6,0(%r1,%r2) + la %r1,4(0,%r1) + brct %r5,.L2 + lr %r2,%r0 # return last carry +.Lexit: l %r6,24(%r15) # restore register 6 + br %r14 +END(__mpn_add_n) diff --git a/REORG.TODO/sysdeps/s390/s390-32/addmul_1.S b/REORG.TODO/sysdeps/s390/s390-32/addmul_1.S new file mode 100644 index 0000000000..6a4318ce49 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/addmul_1.S @@ -0,0 +1,58 @@ +/* S390 __mpn_addmul_1 -- Multiply a limb vector with a limb and add + the result to a second limb vector. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU MP Library. + + The GNU MP 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 MP 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 MP Library; see the file COPYING.LIB. If not, + see <http://www.gnu.org/licenses/>. */ + +/* + INPUT PARAMETERS + res_ptr %r2 + s1_ptr %r3 + sizeP %r4 + s2_limb %r5 +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(__mpn_addmul_1) + st %r6,24(%r15) + cfi_offset (%r6, -72) + slr %r6,%r6 # cy_limb = 0 +.L0: icm %r1,15,0(%r3) # get s1_ptr[i] + mr %r0,%r5 # umul_ppmm(prod_high,prod_low,s1_ptr[j],s2_limb) + jnm .L1 + alr %r0,%r5 +.L1: ltr %r5,%r5 + jnm .L2 + al %r0,0(%r3) +.L2: alr %r1,%r6 # prod_low += cy_limb + lr %r6,%r0 # cy_limb = prod_high + brc 12,.L3 + ahi %r6,1 # + (prod_low < cy_limb) +.L3: al %r1,0(%r2) # prod_low += res_ptr[i] + brc 12,.L4 + ahi %r6,1 # cy_limb++ +.L4: st %r1,0(%r2) + la %r2,4(0,%r2) + la %r3,4(0,%r3) + brct %r4,.L0 + lr %r2,%r6 # return cy_limb + l %r6,24(%r15) +.Lexit: br %r14 +END(__mpn_addmul_1) diff --git a/REORG.TODO/sysdeps/s390/s390-32/backtrace.c b/REORG.TODO/sysdeps/s390/s390-32/backtrace.c new file mode 100644 index 0000000000..705b05d139 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/backtrace.c @@ -0,0 +1,148 @@ +/* Return backtrace of current program state. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>. + 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/>. */ + +#include <libc-lock.h> +#include <dlfcn.h> +#include <execinfo.h> +#include <stddef.h> +#include <stdlib.h> +#include <unwind.h> + +/* This is a global variable set at program start time. It marks the + highest used stack address. */ +extern void *__libc_stack_end; + + +/* This is the stack layout we see for every non-leaf function. + size offset + %r15 -> +------------------+ + 4 | back chain | 0 + 4 | end of stack | 4 + 8 | glue | 8 + 8 | scratch | 16 + 40 | save area r6-r15 | 24 + 16 | save area f4,f6 | 64 + 16 | empty | 80 + +------------------+ + r14 in the save area holds the return address. +*/ + +struct layout +{ + int back_chain; + int end_of_stack; + int glue[2]; + int scratch[2]; + int save_grps[10]; + int save_fp[4]; + int empty[2]; +}; + +struct trace_arg +{ + void **array; + int cnt, size; +}; + +#ifdef SHARED +static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *); +static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *); + +static void +init (void) +{ + void *handle = __libc_dlopen ("libgcc_s.so.1"); + + if (handle == NULL) + return; + + unwind_backtrace = __libc_dlsym (handle, "_Unwind_Backtrace"); + unwind_getip = __libc_dlsym (handle, "_Unwind_GetIP"); + if (unwind_getip == NULL) + unwind_backtrace = NULL; +} + +static int +__backchain_backtrace (void **array, int size) +{ + /* We assume that all the code is generated with frame pointers set. */ + struct layout *stack; + int cnt = 0; + + __asm__ ("LR %0,%%r15" : "=d" (stack) ); + /* We skip the call to this function, it makes no sense to record it. */ + stack = (struct layout *) stack->back_chain; + while (cnt < size) + { + if (stack == NULL || (void *) stack > __libc_stack_end) + /* This means the address is out of range. Note that for the + toplevel we see a frame pointer with value NULL which clearly is + out of range. */ + break; + + array[cnt++] = (void *) (stack->save_grps[8] & 0x7fffffff); + + stack = (struct layout *) stack->back_chain; + } + + return cnt; +} +#else +# define unwind_backtrace _Unwind_Backtrace +# define unwind_getip _Unwind_GetIP +#endif + +static _Unwind_Reason_Code +backtrace_helper (struct _Unwind_Context *ctx, void *a) +{ + struct trace_arg *arg = a; + + /* We are first called with address in the __backtrace function. + Skip it. */ + if (arg->cnt != -1) + arg->array[arg->cnt] = (void *) unwind_getip (ctx); + if (++arg->cnt == arg->size) + return _URC_END_OF_STACK; + return _URC_NO_REASON; +} + +int +__backtrace (void **array, int size) +{ + struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; + + if (size <= 0) + return 0; + +#ifdef SHARED + __libc_once_define (static, once); + + __libc_once (once, init); + + if (unwind_backtrace == NULL) + return __backchain_backtrace (array, size); +#endif + + unwind_backtrace (backtrace_helper, &arg); + + return arg.cnt != -1 ? arg.cnt : 0; +} + +weak_alias (__backtrace, backtrace) +libc_hidden_def (__backtrace) diff --git a/REORG.TODO/sysdeps/s390/s390-32/bcopy.S b/REORG.TODO/sysdeps/s390/s390-32/bcopy.S new file mode 100644 index 0000000000..06f51f3aa7 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/bcopy.S @@ -0,0 +1,85 @@ +/* bcopy -- copy a block from source to destination. S/390 version. + This file is part of the GNU C Library. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* INPUT PARAMETERS + %r2 = address of source + %r3 = address of destination + %r4 = number of bytes to copy. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(__bcopy) + ltr %r1,%r4 # zero bcopy ? + jz .L4 + clr %r2,%r3 # check against destructive overlap + jnl .L0 + alr %r1,%r2 + clr %r1,%r3 + jh .L7 +.L0: ahi %r4,-1 # length - 1 + lr %r1,%r4 + srl %r1,8 + ltr %r1,%r1 # < 256 bytes to move ? + jz .L2 + chi %r1,255 # > 1MB to move ? + jh .L5 +.L1: mvc 0(256,%r3),0(%r2) # move in 256 byte chunks + la %r2,256(%r2) + la %r3,256(%r3) + brct %r1,.L1 +.L2: bras %r1,.L3 # setup base pointer for execute + mvc 0(1,%r3),0(%r2) # instruction for execute +.L3: ex %r4,0(%r1) # execute mvc with length ((%r4)&255)+1 +.L4: br %r14 + + # data copies > 1MB are faster with mvcle. +.L5: ahi %r4,1 # length + 1 + lr %r5,%r4 # source length + lr %r4,%r2 # source address + lr %r2,%r3 # set destination + lr %r3,%r5 # destination length = source length +.L6: mvcle %r2,%r4,0 # thats it, MVCLE is your friend + jo .L6 + br %r14 +.L7: # destructive overlay, can not use mvcle + lr %r1,%r2 # bcopy is called with source,dest + lr %r2,%r3 # memmove with dest,source! Oh, well... + lr %r3,%r1 + basr %r1,0 +.L8: +#ifdef PIC + al %r1,.L9-.L8(%r1) # get address of global offset table + # load address of memmove + l %r1,memmove@GOT(%r1) + br %r1 +.L9: .long _GLOBAL_OFFSET_TABLE_-.L8 +#else + al %r1,.L9-.L8(%r1) # load address of memmove + br %r1 # jump to memmove +.L9: .long memmove-.L8 +#endif + +END(__bcopy) + +#ifndef NO_WEAK_ALIAS +weak_alias (__bcopy, bcopy) +#endif + diff --git a/REORG.TODO/sysdeps/s390/s390-32/bits/wordsize.h b/REORG.TODO/sysdeps/s390/s390-32/bits/wordsize.h new file mode 100644 index 0000000000..129e47182b --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/bits/wordsize.h @@ -0,0 +1,11 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __s390x__ +# define __WORDSIZE 64 +#else +# define __WORDSIZE 32 +# define __WORDSIZE32_SIZE_ULONG 1 +# define __WORDSIZE32_PTRDIFF_LONG 0 +#endif + +#define __WORDSIZE_TIME64_COMPAT32 0 diff --git a/REORG.TODO/sysdeps/s390/s390-32/bsd-_setjmp.S b/REORG.TODO/sysdeps/s390/s390-32/bsd-_setjmp.S new file mode 100644 index 0000000000..1417270201 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/bsd-_setjmp.S @@ -0,0 +1 @@ +/* We don't need any code here since the setjmp.S file contains it. */ diff --git a/REORG.TODO/sysdeps/s390/s390-32/bsd-setjmp.S b/REORG.TODO/sysdeps/s390/s390-32/bsd-setjmp.S new file mode 100644 index 0000000000..1417270201 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/bsd-setjmp.S @@ -0,0 +1 @@ +/* We don't need any code here since the setjmp.S file contains it. */ diff --git a/REORG.TODO/sysdeps/s390/s390-32/bzero.S b/REORG.TODO/sysdeps/s390/s390-32/bzero.S new file mode 100644 index 0000000000..b6f85e681f --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/bzero.S @@ -0,0 +1,42 @@ +/* bzero -- set a block of memory to zero. IBM S390 version + This file is part of the GNU C Library. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* + * R2 = address to memory area + * R3 = number of bytes to fill + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(__bzero) + ltr %r3,%r3 + jz .L1 + sr %r1,%r1 # set pad byte to zero + sr %r4,%r4 # no source for MVCLE, only a pad byte + sr %r5,%r5 +.L0: mvcle %r2,%r4,0(%r1) # thats it, MVCLE is your friend + jo .L0 +.L1: br %r14 +END(__bzero) + +#ifndef NO_WEAK_ALIAS +weak_alias (__bzero, bzero) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/crti.S b/REORG.TODO/sysdeps/s390/s390-32/crti.S new file mode 100644 index 0000000000..54bd4590c0 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/crti.S @@ -0,0 +1,102 @@ +/* Special .init and .fini section support for S/390. + Copyright (C) 2000-2017 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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/>. */ + +/* crti.S puts a function prologue at the beginning of the .init and + .fini sections and defines global symbols for those addresses, so + they can be called as functions. The symbols _init and _fini are + magic and cause the linker to emit DT_INIT and DT_FINI. */ + +#include <libc-symbols.h> +#include <sysdep.h> + +#ifndef PREINIT_FUNCTION +# define PREINIT_FUNCTION __gmon_start__ +#endif + +#ifndef PREINIT_FUNCTION_WEAK +# define PREINIT_FUNCTION_WEAK 1 +#endif + +#if PREINIT_FUNCTION_WEAK + weak_extern (PREINIT_FUNCTION) +#else + .hidden PREINIT_FUNCTION +#endif + + .section .init,"ax",@progbits + .globl _init + .type _init,@function + .align 4 +_init: + stm %r6,%r15,24(%r15) + bras %r13,1f +0: +#if PREINIT_FUNCTION_WEAK + .long PREINIT_FUNCTION@GOT +#else + .long PREINIT_FUNCTION-0b +#endif + .long _GLOBAL_OFFSET_TABLE_-0b +1: lr %r1,%r15 + ahi %r15,-96 + st %r1,0(%r15) + l %r12,4(%r13) + ar %r12,%r13 + l %r1,0(%r13) +#if PREINIT_FUNCTION_WEAK + l %r1,0(%r1,%r12) + ltr %r1,%r1 + je 2f +#else + la %r1,0(%r1,%r13) +#endif + basr %r14,%r1 + .align 4,0x07 +2: + + .section .fini,"ax",@progbits + .globl _fini + .type _fini,@function + .align 4 +_fini: + stm %r6,%r15,24(%r15) + bras %r13,1f +0: .long _GLOBAL_OFFSET_TABLE_-0b +1: lr %r1,%r15 + ahi %r15,-96 + st %r1,0(%r15) + l %r12,0(%r13) + ar %r12,%r13 + .align 4,0x07 diff --git a/REORG.TODO/sysdeps/s390/s390-32/crtn.S b/REORG.TODO/sysdeps/s390/s390-32/crtn.S new file mode 100644 index 0000000000..3f5d85e2b2 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/crtn.S @@ -0,0 +1,47 @@ +/* Special .init and .fini section support for S/390. + Copyright (C) 2000-2017 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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/>. */ + +/* crtn.S puts function epilogues in the .init and .fini sections + corresponding to the prologues in crti.S. */ + + .section .init,"ax",@progbits + l %r4,152(%r15) + lm %r6,%r15,120(%r15) + br %r4 + + .section .fini,"ax",@progbits + l %r4,152(%r15) + lm %r6,%r15,120(%r15) + br %r4 diff --git a/REORG.TODO/sysdeps/s390/s390-32/dl-machine.h b/REORG.TODO/sysdeps/s390/s390-32/dl-machine.h new file mode 100644 index 0000000000..2e3c77c58e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/dl-machine.h @@ -0,0 +1,522 @@ +/* Machine-dependent ELF dynamic relocation inline functions. S390 Version. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Carl Pederson & Martin Schwidefsky. + 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/>. */ + +#ifndef dl_machine_h +#define dl_machine_h + +#define ELF_MACHINE_NAME "s390" + +#include <sys/param.h> +#include <string.h> +#include <link.h> +#include <sysdeps/s390/dl-procinfo.h> +#include <dl-irel.h> + +/* This is an older, now obsolete value. */ +#define EM_S390_OLD 0xA390 + +/* Return nonzero iff ELF header is compatible with the running host. */ +static inline int +elf_machine_matches_host (const Elf32_Ehdr *ehdr) +{ + /* Check if the kernel provides the high gpr facility if needed by + the binary. */ + if ((ehdr->e_flags & EF_S390_HIGH_GPRS) + && !(GLRO (dl_hwcap) & HWCAP_S390_HIGH_GPRS)) + return 0; + + return (ehdr->e_machine == EM_S390 || ehdr->e_machine == EM_S390_OLD) + && ehdr->e_ident[EI_CLASS] == ELFCLASS32; +} + + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ + +static inline Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got; + + __asm__( " bras %0,2f\n" + "1: .long _GLOBAL_OFFSET_TABLE_-1b\n" + "2: al %0,0(%0)" + : "=&a" (got) : : "0" ); + + return *got; +} + + +/* Return the run-time load address of the shared object. */ +static inline Elf32_Addr +elf_machine_load_address (void) +{ + Elf32_Addr addr; + + __asm__( " bras 1,2f\n" + "1: .long _GLOBAL_OFFSET_TABLE_ - 1b\n" + " .long (_dl_start - 1b - 0x80000000) & 0x00000000ffffffff\n" + "2: l %0,4(1)\n" + " ar %0,1\n" + " al 1,0(1)\n" + " sl %0,_dl_start@GOT(1)" + : "=&d" (addr) : : "1" ); + return addr; +} + +/* Set up the loaded object described by L so its unrelocated PLT + entries will jump to the on-demand fixup code in dl-runtime.c. */ + +static inline int __attribute__ ((unused)) +elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) +{ + extern void _dl_runtime_resolve (Elf32_Word); + extern void _dl_runtime_profile (Elf32_Word); +#if defined HAVE_S390_VX_ASM_SUPPORT + extern void _dl_runtime_resolve_vx (Elf32_Word); + extern void _dl_runtime_profile_vx (Elf32_Word); +#endif + + + if (l->l_info[DT_JMPREL] && lazy) + { + /* The GOT entries for functions in the PLT have not yet been filled + in. Their initial contents will arrange when called to push an + offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1], + and then jump to _GLOBAL_OFFSET_TABLE[2]. */ + Elf32_Addr *got; + got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]); + /* If a library is prelinked but we have to relocate anyway, + we have to be able to undo the prelinking of .got.plt. + The prelinker saved us here address of .plt + 0x2c. */ + if (got[1]) + { + l->l_mach.plt = got[1] + l->l_addr; + l->l_mach.jmprel = (const Elf32_Rela *) D_PTR (l, l_info[DT_JMPREL]); + } + got[1] = (Elf32_Addr) l; /* Identify this shared object. */ + + /* The got[2] entry contains the address of a function which gets + called to get the address of a so far unresolved function and + jump to it. The profiling extension of the dynamic linker allows + to intercept the calls to collect information. In this case we + don't store the address in the GOT so that all future calls also + end in this function. */ + if (__glibc_unlikely (profile)) + { +#if defined HAVE_S390_VX_ASM_SUPPORT + if (GLRO(dl_hwcap) & HWCAP_S390_VX) + got[2] = (Elf32_Addr) &_dl_runtime_profile_vx; + else + got[2] = (Elf32_Addr) &_dl_runtime_profile; +#else + got[2] = (Elf32_Addr) &_dl_runtime_profile; +#endif + + if (GLRO(dl_profile) != NULL + && _dl_name_match_p (GLRO(dl_profile), l)) + /* This is the object we are looking for. Say that we really + want profiling and the timers are started. */ + GL(dl_profile_map) = l; + } + else + { + /* This function will get called to fix up the GOT entry indicated by + the offset on the stack, and then jump to the resolved address. */ +#if defined HAVE_S390_VX_ASM_SUPPORT + if (GLRO(dl_hwcap) & HWCAP_S390_VX) + got[2] = (Elf32_Addr) &_dl_runtime_resolve_vx; + else + got[2] = (Elf32_Addr) &_dl_runtime_resolve; +#else + got[2] = (Elf32_Addr) &_dl_runtime_resolve; +#endif + } + } + + return lazy; +} + +/* Mask identifying addresses reserved for the user program, + where the dynamic linker should not map anything. */ +#define ELF_MACHINE_USER_ADDRESS_MASK 0xf8000000UL + +/* Initial entry point code for the dynamic linker. + The C function `_dl_start' is the real entry point; + its return value is the user program's entry point. */ + +#define RTLD_START __asm__ ("\n\ +.text\n\ +.align 4\n\ +.globl _start\n\ +.globl _dl_start_user\n\ +_start:\n\ + basr %r13,0\n\ +0: ahi %r13,.Llit-0b\n\ + lr %r2,%r15\n\ + # Alloc stack frame\n\ + ahi %r15,-96\n\ + # Set the back chain to zero\n\ + xc 0(4,%r15),0(%r15)\n\ + # Call _dl_start with %r2 pointing to arg on stack\n\ + l %r14,.Ladr1-.Llit(%r13)\n\ + bas %r14,0(%r14,%r13) # call _dl_start\n\ +_dl_start_user:\n\ + # Save the user entry point address in %r8.\n\ + lr %r8,%r2\n\ + # Point %r12 at the GOT.\n\ + l %r12,.Ladr0-.Llit(%r13)\n\ + ar %r12,%r13\n\ + # See if we were run as a command with the executable file\n\ + # name as an extra leading argument.\n\ + l %r1,_dl_skip_args@GOT(%r12)\n\ + l %r1,0(%r1) # load _dl_skip_args\n\ + ltr %r1,%r1\n\ + je 4f # Skip the arg adjustment if there were none.\n\ + # Get the original argument count.\n\ + l %r0,96(%r15)\n\ + # Subtract _dl_skip_args from it.\n\ + sr %r0,%r1\n\ + # Store back the modified argument count.\n\ + st %r0,96(%r15)\n\ + # Copy argv and envp forward to account for skipped argv entries.\n\ + # We skipped at least one argument or we would not get here.\n\ + la %r6,100(%r15) # Destination pointer i.e. &argv[0]\n\ + lr %r5,%r6\n\ + lr %r0,%r1\n\ + sll %r0,2\n # Number of skipped bytes.\n\ + ar %r5,%r0 # Source pointer = Dest + Skipped args.\n\ + # argv copy loop:\n\ +1: l %r7,0(%r5) # Load a word from the source.\n\ + st %r7,0(%r6) # Store the word in the destination.\n\ + ahi %r5,4\n\ + ahi %r6,4\n\ + ltr %r7,%r7\n\ + jne 1b # Stop after copying the NULL.\n\ + # envp copy loop:\n\ +2: l %r7,0(%r5) # Load a word from the source.\n\ + st %r7,0(%r6) # Store the word in the destination.\n\ + ahi %r5,4\n\ + ahi %r6,4\n\ + ltr %r7,%r7\n\ + jne 2b # Stop after copying the NULL.\n\ + # Now we have to zero out the envp entries after NULL to allow\n\ + # start.S to properly find auxv by skipping zeroes.\n\ + # zero out loop:\n\ + lhi %r7,0\n\ +3: st %r7,0(%r6) # Store zero.\n\ + ahi %r6,4 # Advance dest pointer.\n\ + ahi %r1,-1 # Subtract one from the word count.\n\ + ltr %r1,%r1\n\ + jne 3b # Keep copying if the word count is non-zero.\n\ + # Adjust _dl_argv\n\ + la %r6,100(%r15)\n\ + l %r1,_dl_argv@GOT(%r12)\n\ + st %r6,0(%r1)\n\ + # The special initializer gets called with the stack just\n\ + # as the application's entry point will see it; it can\n\ + # switch stacks if it moves these contents over.\n\ +" RTLD_START_SPECIAL_INIT "\n\ + # Call the function to run the initializers.\n\ + # Load the parameters:\n\ + # (%r2, %r3, %r4, %r5) = (_dl_loaded, argc, argv, envp)\n\ +4: l %r2,_rtld_local@GOT(%r12)\n\ + l %r2,0(%r2)\n\ + l %r3,96(%r15)\n\ + la %r4,100(%r15)\n\ + lr %r5,%r3\n\ + sll %r5,2\n\ + la %r5,104(%r5,%r15)\n\ + l %r1,.Ladr4-.Llit(%r13)\n\ + bas %r14,0(%r1,%r13)\n\ + # Pass our finalizer function to the user in %r14, as per ELF ABI.\n\ + l %r14,_dl_fini@GOT(%r12)\n\ + # Free stack frame\n\ + ahi %r15,96\n\ + # Jump to the user's entry point (saved in %r8).\n\ + br %r8\n\ +.Llit:\n\ +.Ladr0: .long _GLOBAL_OFFSET_TABLE_-.Llit\n\ +.Ladr1: .long _dl_start-.Llit\n\ +.Ladr4: .long _dl_init@PLT-.Llit\n\ +"); + +#ifndef RTLD_START_SPECIAL_INIT +#define RTLD_START_SPECIAL_INIT /* nothing */ +#endif + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_390_JMP_SLOT || (type) == R_390_TLS_DTPMOD \ + || (type) == R_390_TLS_DTPOFF || (type) == R_390_TLS_TPOFF) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ +#define ELF_MACHINE_JMP_SLOT R_390_JMP_SLOT + +/* The S390 never uses Elf32_Rel relocations. */ +#define ELF_MACHINE_NO_REL 1 +#define ELF_MACHINE_NO_RELA 0 + +/* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ +#define DL_PLATFORM_INIT dl_platform_init () + +static inline void __attribute__ ((unused)) +dl_platform_init (void) +{ + if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') + /* Avoid an empty string which would disturb us. */ + GLRO(dl_platform) = NULL; +} + +static inline Elf32_Addr +elf_machine_fixup_plt (struct link_map *map, lookup_t t, + const Elf32_Rela *reloc, + Elf32_Addr *reloc_addr, Elf32_Addr value) +{ + return *reloc_addr = value; +} + +/* Return the final value of a plt relocation. */ +static inline Elf32_Addr +elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc, + Elf32_Addr value) +{ + return value; +} + +/* Names of the architecture-specific auditing callback functions. */ +#define ARCH_LA_PLTENTER s390_32_gnu_pltenter +#define ARCH_LA_PLTEXIT s390_32_gnu_pltexit + +#endif /* !dl_machine_h */ + + +#ifdef RESOLVE_MAP + +/* Perform the relocation specified by RELOC and SYM (which is fully resolved). + MAP is the object containing the reloc. */ + +auto inline void +__attribute__ ((always_inline)) +elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, + const Elf32_Sym *sym, const struct r_found_version *version, + void *const reloc_addr_arg, int skip_ifunc) +{ + Elf32_Addr *const reloc_addr = reloc_addr_arg; + const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); + +#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC + if (__glibc_unlikely (r_type == R_390_RELATIVE)) + { +# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC + /* This is defined in rtld.c, but nowhere in the static libc.a; + make the reference weak so static programs can still link. + This declaration cannot be done when compiling rtld.c + (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the + common defn for _dl_rtld_map, which is incompatible with a + weak decl in the same file. */ +# ifndef SHARED + weak_extern (GL(dl_rtld_map)); +# endif + if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ +# endif + *reloc_addr = map->l_addr + reloc->r_addend; + } + else +#endif + if (__glibc_unlikely (r_type == R_390_NONE)) + return; + else + { +#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP + /* Only needed for R_390_COPY below. */ + const Elf32_Sym *const refsym = sym; +#endif + struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); + Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value; + + if (sym != NULL + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0) + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) + && __builtin_expect (!skip_ifunc, 1)) + value = elf_ifunc_invoke (value); + + switch (r_type) + { + case R_390_IRELATIVE: + value = map->l_addr + reloc->r_addend; + if (__glibc_likely (!skip_ifunc)) + value = elf_ifunc_invoke (value); + *reloc_addr = value; + break; + + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + *reloc_addr = value + reloc->r_addend; + break; + +#ifndef RESOLVE_CONFLICT_FIND_MAP + case R_390_TLS_DTPMOD: +# ifdef RTLD_BOOTSTRAP + /* During startup the dynamic linker is always the module + with index 1. + XXX If this relocation is necessary move before RESOLVE + call. */ + *reloc_addr = 1; +# else + /* Get the information from the link map returned by the + resolv function. */ + if (sym_map != NULL) + *reloc_addr = sym_map->l_tls_modid; +# endif + break; + case R_390_TLS_DTPOFF: +# ifndef RTLD_BOOTSTRAP + /* During relocation all TLS symbols are defined and used. + Therefore the offset is already correct. */ + if (sym != NULL) + *reloc_addr = sym->st_value + reloc->r_addend; +# endif + break; + case R_390_TLS_TPOFF: + /* The offset is negative, forward from the thread pointer. */ +# ifdef RTLD_BOOTSTRAP + *reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset; +# else + /* We know the offset of the object the symbol is contained in. + It is a negative value which will be added to the + thread pointer. */ + if (sym != NULL) + { + CHECK_STATIC_TLS (map, sym_map); + *reloc_addr = (sym->st_value + reloc->r_addend + - sym_map->l_tls_offset); + } +#endif + break; +#endif /* use TLS */ + +#ifndef RTLD_BOOTSTRAP +# ifndef RESOLVE_CONFLICT_FIND_MAP + /* Not needed in dl-conflict.c. */ + case R_390_COPY: + if (sym == NULL) + /* This can happen in trace mode if an object could not be + found. */ + break; + if (__builtin_expect (sym->st_size > refsym->st_size, 0) + || (__builtin_expect (sym->st_size < refsym->st_size, 0) + && __builtin_expect (GLRO(dl_verbose), 0))) + { + const char *strtab; + + strtab = (const char *) D_PTR(map,l_info[DT_STRTAB]); + _dl_error_printf ("\ +%s: Symbol `%s' has different size in shared object, consider re-linking\n", + RTLD_PROGNAME, strtab + refsym->st_name); + } + memcpy (reloc_addr_arg, (void *) value, + MIN (sym->st_size, refsym->st_size)); + break; +# endif + case R_390_32: + *reloc_addr = value + reloc->r_addend; + break; + case R_390_16: + *(unsigned short *) reloc_addr = value + reloc->r_addend; + break; + case R_390_8: + *(char *) reloc_addr = value + reloc->r_addend; + break; +# ifndef RESOLVE_CONFLICT_FIND_MAP + case R_390_PC32: + *reloc_addr = value + reloc->r_addend - (Elf32_Addr) reloc_addr; + break; + case R_390_PC16DBL: + *(unsigned short *) reloc_addr = (unsigned short) + ((short) (value + reloc->r_addend - (Elf32_Addr) reloc_addr) >> 1); + break; + case R_390_PC32DBL: + *(unsigned int *) reloc_addr = (unsigned int) + ((int) (value + reloc->r_addend - (Elf32_Addr) reloc_addr) >> 1); + break; + case R_390_PC16: + *(unsigned short *) reloc_addr = + value + reloc->r_addend - (Elf32_Addr) reloc_addr; + break; + case R_390_NONE: + break; +# endif +#endif +#if !defined(RTLD_BOOTSTRAP) || defined(_NDEBUG) + default: + /* We add these checks in the version to relocate ld.so only + if we are still debugging. */ + _dl_reloc_bad_type (map, r_type, 0); + break; +#endif + } + } +} + +auto inline void +__attribute__ ((always_inline)) +elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc, + void *const reloc_addr_arg) +{ + Elf32_Addr *const reloc_addr = reloc_addr_arg; + *reloc_addr = l_addr + reloc->r_addend; +} + +auto inline void +__attribute__ ((always_inline)) +elf_machine_lazy_rel (struct link_map *map, + Elf32_Addr l_addr, const Elf32_Rela *reloc, + int skip_ifunc) +{ + Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset); + const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); + /* Check for unexpected PLT reloc type. */ + if (__glibc_likely (r_type == R_390_JMP_SLOT)) + { + if (__builtin_expect (map->l_mach.plt, 0) == 0) + *reloc_addr += l_addr; + else + *reloc_addr = map->l_mach.plt + (reloc - map->l_mach.jmprel) * 32; + } + else if (__glibc_likely (r_type == R_390_IRELATIVE)) + { + Elf32_Addr value = map->l_addr + reloc->r_addend; + if (__glibc_likely (!skip_ifunc)) + value = elf_ifunc_invoke (value); + *reloc_addr = value; + } + else + _dl_reloc_bad_type (map, r_type, 1); +} + +#endif /* RESOLVE_MAP */ diff --git a/REORG.TODO/sysdeps/s390/s390-32/dl-sysdep.h b/REORG.TODO/sysdeps/s390/s390-32/dl-sysdep.h new file mode 100644 index 0000000000..f32114bf56 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/dl-sysdep.h @@ -0,0 +1,23 @@ +/* System-specific settings for dynamic linker code. S/390 version. + Copyright (C) 2014-2017 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/>. */ + +#include_next <dl-sysdep.h> + +/* _dl_argv cannot be attribute_relro, because _dl_start_user + might write into it after _dl_start returns. */ +#define DL_ARGV_NOT_RELRO 1 diff --git a/REORG.TODO/sysdeps/s390/s390-32/dl-trampoline.S b/REORG.TODO/sysdeps/s390/s390-32/dl-trampoline.S new file mode 100644 index 0000000000..34377e7c51 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/dl-trampoline.S @@ -0,0 +1,33 @@ +/* PLT trampolines. s390 version. + Copyright (C) 2005-2017 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/>. */ + +#include <sysdep.h> + + .text +/* Create variant of _dl_runtime_resolve/profile for machines before z13. + No vector registers are saved/restored. */ +#include <dl-trampoline.h> + +#if defined HAVE_S390_VX_ASM_SUPPORT +/* Create variant of _dl_runtime_resolve/profile for z13 and newer. + The vector registers are saved/restored, too.*/ +# define _dl_runtime_resolve _dl_runtime_resolve_vx +# define _dl_runtime_profile _dl_runtime_profile_vx +# define RESTORE_VRS +# include <dl-trampoline.h> +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/dl-trampoline.h b/REORG.TODO/sysdeps/s390/s390-32/dl-trampoline.h new file mode 100644 index 0000000000..19776eec8a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/dl-trampoline.h @@ -0,0 +1,231 @@ +/* PLT trampolines. s390 version. + Copyright (C) 2016-2017 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/>. */ + +/* This code is used in dl-runtime.c to call the `fixup' function + and then redirect to the address it returns. */ + +/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile + * with the following linkage: + * r2 - r6 : parameter registers + * f0, f2 : floating point parameter registers + * v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers + * 24(r15), 28(r15) : PLT arguments PLT1, PLT2 + * 96(r15) : additional stack parameters + * The normal clobber rules for function calls apply: + * r0 - r5 : call clobbered + * r6 - r13 : call saved + * r14 : return address (call clobbered) + * r15 : stack pointer (call saved) + * f4, f6 : call saved + * f0 - f3, f5, f7 - f15 : call clobbered + * v0 - v3, v5, v7 - v15 : bytes 0-7 overlap with fprs: call clobbered + bytes 8-15: call clobbered + * v4, v6 : bytes 0-7 overlap with f4, f6: call saved + bytes 8-15: call clobbered + * v16 - v31 : call clobbered + */ + + + .globl _dl_runtime_resolve + .type _dl_runtime_resolve, @function + cfi_startproc + .align 16 +_dl_runtime_resolve: + stm %r2,%r5,32(%r15) # save registers + cfi_offset (r2, -64) + cfi_offset (r3, -60) + cfi_offset (r4, -56) + cfi_offset (r5, -52) + std %f0,56(%r15) + cfi_offset (f0, -40) + std %f2,64(%r15) + cfi_offset (f2, -32) + st %r14,8(%r15) + cfi_offset (r14, -88) + lr %r0,%r15 + lm %r2,%r3,24(%r15) # load args saved by PLT +#ifdef RESTORE_VRS + ahi %r15,-224 # create stack frame + cfi_adjust_cfa_offset (224) + .machine push + .machine "z13" + .machinemode "zarch_nohighgprs" + vstm %v24,%v31,96(%r15) # store call-clobbered vr arguments + cfi_offset (v24, -224) + cfi_offset (v25, -208) + cfi_offset (v26, -192) + cfi_offset (v27, -176) + cfi_offset (v28, -160) + cfi_offset (v29, -144) + cfi_offset (v30, -128) + cfi_offset (v31, -112) + .machine pop +#else + ahi %r15,-96 # create stack frame + cfi_adjust_cfa_offset (96) +#endif + st %r0,0(%r15) # write backchain + basr %r1,0 +0: l %r14,1f-0b(%r1) + bas %r14,0(%r14,%r1) # call _dl_fixup + lr %r1,%r2 # function addr returned in r2 +#ifdef RESTORE_VRS + .machine push + .machine "z13" + .machinemode "zarch_nohighgprs" + vlm %v24,%v31,96(%r15) # restore vector registers + .machine pop + ahi %r15,224 # remove stack frame + cfi_adjust_cfa_offset (-224) +#else + ahi %r15,96 # remove stack frame + cfi_adjust_cfa_offset (-96) +#endif + l %r14,8(15) # restore registers + ld %f0,56(%r15) + ld %f2,64(%r15) + lm %r2,%r5,32(%r15) + br %r1 +1: .long _dl_fixup - 0b + cfi_endproc + .size _dl_runtime_resolve, .-_dl_runtime_resolve + + +#ifndef PROF + .globl _dl_runtime_profile + .type _dl_runtime_profile, @function + cfi_startproc + .align 16 +_dl_runtime_profile: + st %r12,12(%r15) # r12 is used as backup of r15 + cfi_offset (r12, -84) + st %r14,16(%r15) + cfi_offset (r14, -80) + lr %r12,%r15 # backup stack pointer + cfi_def_cfa_register (12) + ahi %r15,-264 # create stack frame: + # 96 + sizeof(La_s390_32_regs) + st %r12,0(%r15) # save backchain + + stm %r2,%r6,96(%r15) # save registers + cfi_offset (r2, -264) # + r6 needed as arg for + cfi_offset (r3, -260) # _dl_profile_fixup + cfi_offset (r4, -256) + cfi_offset (r5, -252) + cfi_offset (r6, -248) + std %f0,120(%r15) + cfi_offset (f0, -240) + std %f2,128(%r15) + cfi_offset (f2, -232) +#ifdef RESTORE_VRS + .machine push + .machine "z13" + .machinemode "zarch_nohighgprs" + vstm %v24,%v31,136(%r15) # store call-clobbered vr arguments + cfi_offset (v24, -224) + cfi_offset (v25, -208) + cfi_offset (v26, -192) + cfi_offset (v27, -176) + cfi_offset (v28, -160) + cfi_offset (v29, -144) + cfi_offset (v30, -128) + cfi_offset (v31, -112) + .machine pop +#endif + + lm %r2,%r3,24(%r12) # load arguments saved by PLT + lr %r4,%r14 # return address as third parameter + basr %r1,0 +0: l %r14,6f-0b(%r1) + la %r5,96(%r15) # pointer to struct La_s390_32_regs + la %r6,20(%r12) # long int * framesize + bas %r14,0(%r14,%r1) # call resolver + lr %r1,%r2 # function addr returned in r2 + ld %f0,120(%r15) # restore call-clobbered arg fprs + ld %f2,128(%r15) +#ifdef RESTORE_VRS + .machine push + .machine "z13" + .machinemode "zarch_nohighgprs" + vlm %v24,%v31,136(%r15) # restore call-clobbered arg vrs + .machine pop +#endif + icm %r0,15,20(%r12) # load & test framesize + jnm 2f + + lm %r2,%r6,96(%r15) # framesize < 0 means no pltexit call + # so we can do a tail call without + # copying the arg overflow area + lr %r15,%r12 # remove stack frame + cfi_def_cfa_register (15) + l %r14,16(%r15) # restore registers + l %r12,12(%r15) + br %r1 # tail-call to the resolved function + + cfi_def_cfa_register (12) +2: la %r4,96(%r15) # pointer to struct La_s390_32_regs + st %r4,32(%r12) + jz 4f # framesize == 0 ? + ahi %r0,7 # align framesize to 8 + lhi %r2,-8 + nr %r0,%r2 + slr %r15,%r0 # make room for framesize bytes + st %r12,0(%r15) # save backchain + la %r2,96(%r15) + la %r3,96(%r12) + srl %r0,3 +3: mvc 0(8,%r2),0(%r3) # copy additional parameters + la %r2,8(%r2) + la %r3,8(%r3) + brct %r0,3b +4: lm %r2,%r6,0(%r4) # load register parameters + basr %r14,%r1 # call resolved function + stm %r2,%r3,40(%r12) # store return values r2, r3, f0 + std %f0,48(%r12) # to struct La_s390_32_retval +#ifdef RESTORE_VRS + .machine push + .machine "z13" + vst %v24,56(%r12) # store return value v24 + .machine pop +#endif + lm %r2,%r4,24(%r12) # r2, r3: load arguments saved by PLT + # r4: pointer to struct La_s390_32_regs + basr %r1,0 +5: l %r14,7f-5b(%r1) + la %r5,40(%r12) # pointer to struct La_s390_32_retval + bas %r14,0(%r14,%r1) # call _dl_call_pltexit + + lr %r15,%r12 # remove stack frame + cfi_def_cfa_register (15) + l %r14,16(%r15) # restore registers + l %r12,12(%r15) + lm %r2,%r3,40(%r15) # restore return values + ld %f0,48(%r15) +#ifdef RESTORE_VRS + .machine push + .machine "z13" + vl %v24,56(%r15) # restore return value v24 + .machine pop +#endif + br %r14 + +6: .long _dl_profile_fixup - 0b +7: .long _dl_call_pltexit - 5b + cfi_endproc + .size _dl_runtime_profile, .-_dl_runtime_profile +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/memchr.S b/REORG.TODO/sysdeps/s390/s390-32/memchr.S new file mode 100644 index 0000000000..4ffac6061c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/memchr.S @@ -0,0 +1,41 @@ +/* Search a character in a block of memory. For IBM S390 + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* + * R2 = address to memory area + * R3 = character to find + * R4 = number of bytes to search + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(memchr) + lhi %r0,0xff + nr %r0,%r3 + lr %r1,%r2 + la %r2,0(%r4,%r1) +0: srst %r2,%r1 + jo 0b + brc 13,1f + slr %r2,%r2 +1: br %r14 +END(memchr) +libc_hidden_builtin_def (memchr) diff --git a/REORG.TODO/sysdeps/s390/s390-32/memcmp.S b/REORG.TODO/sysdeps/s390/s390-32/memcmp.S new file mode 100644 index 0000000000..ca02144a4a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/memcmp.S @@ -0,0 +1,66 @@ +/* memcmp - compare two memory blocks. 32 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of first memory area + %r3 = address of second memory area + %r4 = number of bytes to compare. */ + + .text +#ifdef USE_MULTIARCH +ENTRY(__memcmp_default) +#else +ENTRY(memcmp) +#endif + .machine "g5" + basr %r5,0 +.L_G5_16: + ltr %r4,%r4 + je .L_G5_4 + ahi %r4,-1 + lr %r1,%r4 + srl %r1,8 + ltr %r1,%r1 + jne .L_G5_12 + ex %r4,.L_G5_17-.L_G5_16(%r5) +.L_G5_4: + ipm %r2 + sll %r2,2 + sra %r2,30 + br %r14 +.L_G5_12: + clc 0(256,%r3),0(%r2) + jne .L_G5_4 + la %r3,256(%r3) + la %r2,256(%r2) + brct %r1,.L_G5_12 + ex %r4,.L_G5_17-.L_G5_16(%r5) + j .L_G5_4 +.L_G5_17: + clc 0(1,%r3),0(%r2) +#ifdef USE_MULTIARCH +END(__memcmp_default) +#else +END(memcmp) +libc_hidden_builtin_def (memcmp) +weak_alias(memcmp, bcmp) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/memcpy.S b/REORG.TODO/sysdeps/s390/s390-32/memcpy.S new file mode 100644 index 0000000000..0177f19431 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/memcpy.S @@ -0,0 +1,89 @@ +/* memcpy - copy a block from source to destination. S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of destination memory area + %r3 = address of source memory area + %r4 = number of bytes to copy. */ + + .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: + ltr %r4,%r4 + je .L_G5_99 + ahi %r4,-1 + lr %r5,%r4 + srl %r5,8 + ltr %r5,%r5 + jne .L_G5_13 +.L_G5_4: + basr %r5,0 +.L_G5_16: + ex %r4,.L_G5_17-.L_G5_16(%r5) +.L_G5_99: + br %r14 +.L_G5_13: + chi %r5,4096 # Switch to mvcle for copies >1MB + jh __memcpy_mvcle +.L_G5_12: + mvc 0(256,%r1),0(%r3) + la %r1,256(%r1) + la %r3,256(%r3) + brct %r5,.L_G5_12 + j .L_G5_4 +.L_G5_17: + mvc 0(1,%r1),0(%r3) +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. + 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,%r0 # return destination address + br %r14 +END(__memcpy_mvcle) diff --git a/REORG.TODO/sysdeps/s390/s390-32/memset.S b/REORG.TODO/sysdeps/s390/s390-32/memset.S new file mode 100644 index 0000000000..720f393c30 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/memset.S @@ -0,0 +1,65 @@ +/* Set a block of memory to some byte value. For IBM S390 + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address to memory area + %r3 = byte to fill memory with + %r4 = number of bytes to fill. */ + + .text + +#ifdef USE_MULTIARCH +ENTRY(__memset_default) +#else +ENTRY(memset) +#endif + .machine "g5" + basr %r5,0 +.L_G5_19: + ltr %r4,%r4 + je .L_G5_4 + stc %r3,0(%r2) + chi %r4,1 + lr %r1,%r2 + je .L_G5_4 + ahi %r4,-2 + lr %r3,%r4 + srl %r3,8 + ltr %r3,%r3 + jne .L_G5_14 + ex %r4,.L_G5_20-.L_G5_19(%r5) +.L_G5_4: + br %r14 +.L_G5_14: + mvc 1(256,%r1),0(%r1) + la %r1,256(%r1) + brct %r3,.L_G5_14 + ex %r4,.L_G5_20-.L_G5_19(%r5) + j .L_G5_4 +.L_G5_20: + mvc 1(1,%r1),0(%r1) +#ifdef USE_MULTIARCH +END(__memset_default) +#else +END(memset) +libc_hidden_builtin_def (memset) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/mul_1.S b/REORG.TODO/sysdeps/s390/s390-32/mul_1.S new file mode 100644 index 0000000000..4f08fa2c80 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/mul_1.S @@ -0,0 +1,55 @@ +/* __mpn_mul_1 -- Multiply a limb vector with a limb and store + the result in a second limb vector. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU MP Library. + + The GNU MP 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 MP 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 MP Library; see the file COPYING.LIB. If not, + see <http://www.gnu.org/licenses/>. */ + +/* + INPUT PARAMETERS + res_ptr %r2 + s1_ptr %r3 + size %r4 + s2_limb %r5 +*/ + +#include <sysdep.h> +#include "asm-syntax.h" + + .text +ENTRY(__mpn_mul_1) + st %r6,24(%r15) + cfi_offset (%r6, -72) + slr %r6,%r6 # cy_limb = 0 +.L0: icm %r1,15,0(%r3) # get s1_ptr[i] + mr %r0,%r5 # umul_ppmm(prod_high,prod_low,s1_ptr[j],s2_limb) + jnm .L1 + alr %r0,%r5 +.L1: ltr %r5,%r5 + jnm .L2 + al %r0,0(%r3) +.L2: alr %r1,%r6 # prod_low += cy_limb + lr %r6,%r0 # cy_limb = prod_high + brc 12,.L3 + ahi %r6,1 # + (prod_low < cy_limb) +.L3: st %r1,0(%r2) + la %r2,4(0,%r2) + la %r3,4(0,%r3) + brct %r4,.L0 + lr %r2,%r6 # return cy_limb + l %r6,24(%r15) +.Lexit: br %r14 +END(__mpn_mul_1) diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/Makefile b/REORG.TODO/sysdeps/s390/s390-32/multiarch/Makefile new file mode 100644 index 0000000000..f8aee14bbd --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/Makefile @@ -0,0 +1,4 @@ +ifeq ($(subdir),string) +sysdep_routines += memset memset-s390 memcpy memcpy-s390 \ + memcmp memcmp-s390 +endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/memchr.c b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memchr.c new file mode 100644 index 0000000000..808c3b837a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memchr.c @@ -0,0 +1,21 @@ +/* Multiple versions of memchr. + Copyright (C) 2015-2017 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/>. */ + +/* This wrapper-file is needed, because otherwise file + sysdeps/s390/s390-[32|64]/memchr.S will be used. */ +#include <sysdeps/s390/multiarch/memchr.c> diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcmp-s390.S b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcmp-s390.S new file mode 100644 index 0000000000..86a76b4c98 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcmp-s390.S @@ -0,0 +1,107 @@ +/* CPU specific memcmp implementations. 32 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of first memory area + %r3 = address of second memory area + %r4 = number of bytes to compare. */ + + .text + +#if IS_IN (libc) + +ENTRY(__memcmp_z196) + .machine "z196" + .machinemode "zarch_nohighgprs" + ltr %r4,%r4 + je .L_Z196_4 + ahi %r4,-1 + srlk %r1,%r4,8 + ltr %r1,%r1 + jne .L_Z196_2 +.L_Z196_3: + exrl %r4,.L_Z196_14 +.L_Z196_4: + ipm %r2 + sll %r2,2 + sra %r2,30 + br %r14 +.L_Z196_17: + la %r3,256(%r3) + la %r2,256(%r2) + ahi %r1,-1 + je .L_Z196_3 +.L_Z196_2: + pfd 1,512(%r3) + pfd 1,512(%r2) + clc 0(256,%r3),0(%r2) + je .L_Z196_17 + ipm %r2 + sll %r2,2 + sra %r2,30 + br %r14 +.L_Z196_14: + clc 0(1,%r3),0(%r2) +END(__memcmp_z196) + +ENTRY(__memcmp_z10) + .machine "z10" + .machinemode "zarch_nohighgprs" + ltr %r4,%r4 + je .L_Z10_4 + ahi %r4,-1 + lr %r1,%r4 + srl %r1,8 + cijlh %r1,0,.L_Z10_12 +.L_Z10_3: + exrl %r4,.L_Z10_15 +.L_Z10_4: + ipm %r2 + sll %r2,2 + sra %r2,30 + br %r14 +.L_Z10_12: + pfd 1,512(%r3) + pfd 1,512(%r2) + clc 0(256,%r3),0(%r2) + jne .L_Z10_4 + la %r3,256(%r3) + la %r2,256(%r2) + brct %r1,.L_Z10_12 + j .L_Z10_3 +.L_Z10_15: + clc 0(1,%r3),0(%r2) +END(__memcmp_z10) + +#endif /* IS_IN (libc) */ + +#include "../memcmp.S" + +#if !IS_IN (libc) +.globl memcmp +.set memcmp,__memcmp_default +.weak bcmp +.set bcmp,__memcmp_default +#elif defined SHARED && IS_IN (libc) +.globl __GI_memcmp +.set __GI_memcmp,__memcmp_default +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcmp.c b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcmp.c new file mode 100644 index 0000000000..2d8d8f4d50 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcmp.c @@ -0,0 +1,27 @@ +/* Multiple versions of memcmp. + Copyright (C) 2015-2017 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 IS_IN (libc) +# define memcmp __redirect_memcmp +# include <string.h> +# undef memcmp +# include <ifunc-resolve.h> + +s390_libc_ifunc (__redirect_memcmp, __memcmp, memcmp) +weak_alias (memcmp, bcmp); +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcpy-s390.S b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcpy-s390.S new file mode 100644 index 0000000000..bec51af110 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcpy-s390.S @@ -0,0 +1,128 @@ +/* CPU specific memcpy implementations. 32 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = target operands address + %r3 = source operands address + %r4 = number of bytes to copy. */ + + .text + +#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 + srlg %r5,%r4,8 + ltgr %r5,%r5 + jne .L_Z196_5 +.L_Z196_3: + exrl %r4,.L_Z196_14 +.L_Z196_4: + br %r14 +.L_Z196_5: + cgfi %r5,262144 # Switch to mvcle for copies >64MB + jh __memcpy_mvcle +.L_Z196_2: + pfd 1,768(%r3) + pfd 2,768(%r1) + mvc 0(256,%r1),0(%r3) + aghi %r5,-1 + la %r1,256(%r1) + la %r3,256(%r3) + jne .L_Z196_2 + j .L_Z196_3 +.L_Z196_14: + 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 + srlg %r5,%r4,8 + cgijlh %r5,0,.L_Z10_13 +.L_Z10_3: + exrl %r4,.L_Z10_15 +.L_Z10_4: + br %r14 +.L_Z10_13: + cgfi %r5,65535 # Switch to mvcle for copies >16MB + jh __memcpy_mvcle +.L_Z10_12: + pfd 1,768(%r3) + pfd 2,768(%r1) + mvc 0(256,%r1),0(%r3) + la %r1,256(%r1) + la %r3,256(%r3) + brctg %r5,.L_Z10_12 + j .L_Z10_3 +.L_Z10_15: + 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/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcpy.c b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcpy.c new file mode 100644 index 0000000000..4b8e546fb0 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memcpy.c @@ -0,0 +1,27 @@ +/* Multiple versions of memcpy. + Copyright (C) 2015-2017 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/>. */ + +/* In the static lib memcpy is needed before the reloc is resolved. */ +#if defined SHARED && IS_IN (libc) +# define memcpy __redirect_memcpy +# include <string.h> +# undef memcpy +# include <ifunc-resolve.h> + +s390_libc_ifunc (__redirect_memcpy, __memcpy, memcpy) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/memset-s390.S b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memset-s390.S new file mode 100644 index 0000000000..59660b2499 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memset-s390.S @@ -0,0 +1,116 @@ +/* Set a block of memory to some byte value. 32 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of memory area + %r3 = byte to fill memory with + %r4 = number of bytes to fill. */ + + .text + +#if IS_IN (libc) + +ENTRY(__memset_z196) + .machine "z196" + .machinemode "zarch_nohighgprs" + llgfr %r4,%r4 + ltgr %r4,%r4 + je .L_Z196_4 + stc %r3,0(%r2) + lr %r1,%r2 + cghi %r4,1 + je .L_Z196_4 + aghi %r4,-2 + srlg %r5,%r4,8 + ltgr %r5,%r5 + jne .L_Z196_1 +.L_Z196_3: + exrl %r4,.L_Z196_17 +.L_Z196_4: + br %r14 +.L_Z196_1: + cgfi %r5,1048576 + jh __memset_mvcle # Switch to mvcle for >256MB +.L_Z196_2: + pfd 2,1024(%r1) + mvc 1(256,%r1),0(%r1) + aghi %r5,-1 + la %r1,256(%r1) + jne .L_Z196_2 + j .L_Z196_3 +.L_Z196_17: + mvc 1(1,%r1),0(%r1) +END(__memset_z196) + +ENTRY(__memset_z10) + .machine "z10" + .machinemode "zarch_nohighgprs" + llgfr %r4,%r4 + cgije %r4,0,.L_Z10_4 + stc %r3,0(%r2) + lr %r1,%r2 + cgije %r4,1,.L_Z10_4 + aghi %r4,-2 + srlg %r5,%r4,8 + cgijlh %r5,0,.L_Z10_15 +.L_Z10_3: + exrl %r4,.L_Z10_18 +.L_Z10_4: + br %r14 +.L_Z10_15: + cgfi %r5,163840 # Switch to mvcle for >40MB + jh __memset_mvcle +.L_Z10_14: + pfd 2,1024(%r1) + mvc 1(256,%r1),0(%r1) + la %r1,256(%r1) + brctg %r5,.L_Z10_14 + j .L_Z10_3 +.L_Z10_18: + mvc 1(1,%r1),0(%r1) +END(__memset_z10) + +ENTRY(__memset_mvcle) + ahi %r4,2 # take back the change done by the caller + lr %r0,%r2 # save source address + lr %r1,%r3 # move pad byte to R1 + lr %r3,%r4 + sr %r4,%r4 # no source for MVCLE, only a pad byte + sr %r5,%r5 +.L0: mvcle %r2,%r4,0(%r1) # thats it, MVCLE is your friend + jo .L0 + lr %r2,%r0 # return value is source address +.L1: + br %r14 +END(__memset_mvcle) + +#endif /* IS_IN (libc) */ + +#include "../memset.S" + +#if !IS_IN (libc) +.globl memset +.set memset,__memset_default +#elif defined SHARED && IS_IN (libc) +.globl __GI_memset +.set __GI_memset,__memset_default +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/memset.c b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memset.c new file mode 100644 index 0000000000..421c0854a0 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/memset.c @@ -0,0 +1,26 @@ +/* Multiple versions of memset. + Copyright (C) 2015-2017 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 IS_IN (libc) +# define memset __redirect_memset +# include <string.h> +# undef memset +# include <ifunc-resolve.h> + +s390_libc_ifunc (__redirect_memset, __memset, memset) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/strcmp.c b/REORG.TODO/sysdeps/s390/s390-32/multiarch/strcmp.c new file mode 100644 index 0000000000..6a20a304cc --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/strcmp.c @@ -0,0 +1,21 @@ +/* Multiple versions of strcmp. + Copyright (C) 2015-2017 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/>. */ + +/* This wrapper-file is needed, because otherwise file + sysdeps/s390/s390-[32|64]/strcmp.S will be used. */ +#include <sysdeps/s390/multiarch/strcmp.c> diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/strcpy.c b/REORG.TODO/sysdeps/s390/s390-32/multiarch/strcpy.c new file mode 100644 index 0000000000..7f380a471d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/strcpy.c @@ -0,0 +1,21 @@ +/* Multiple versions of strcpy. + Copyright (C) 2015-2017 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/>. */ + +/* This wrapper-file is needed, because otherwise file + sysdeps/s390/s390-[32|64]/strcpy.S will be used. */ +#include <sysdeps/s390/multiarch/strcpy.c> diff --git a/REORG.TODO/sysdeps/s390/s390-32/multiarch/strncpy.c b/REORG.TODO/sysdeps/s390/s390-32/multiarch/strncpy.c new file mode 100644 index 0000000000..15dacec974 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/multiarch/strncpy.c @@ -0,0 +1,21 @@ +/* Multiple versions of strncpy. + Copyright (C) 2015-2017 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/>. */ + +/* This wrapper-file is needed, because otherwise file + sysdeps/s390/s390-[32|64]/strncpy.S will be used. */ +#include <sysdeps/s390/multiarch/strncpy.c> diff --git a/REORG.TODO/sysdeps/s390/s390-32/s390-mcount.S b/REORG.TODO/sysdeps/s390/s390-32/s390-mcount.S new file mode 100644 index 0000000000..fe25c5506d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/s390-mcount.S @@ -0,0 +1,89 @@ +/* S/390-specific implementation of profiling support. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com) + + 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/>. */ + +#include <sysdep.h> + +/* + * How profiling works on S/390: + * On the start of each function _mcount is called with the address of a + * data word in %r1 (initialized to 0, used for counting). The compiler + * with the option -p generates code of the form: + * + * STM 6,15,24(15) + * BRAS 13,.LTN0_0 + * .LT0_0: + * .LC12: .long _mcount + * .LC13: .long .LP0 + * .data + * .align 4 + * .LP0: .long 0 + * .text + * # function profiler + * st 14,4(15) + * l 14,.LC12-.LT0_0(13) + * l 1,.LC13-.LT0_0(13) + * basr 14,14 + * l 14,4(15) + * + * The _mcount implementation now has to call __mcount_internal with the + * address of .LP0 as first parameter and the return address as second + * parameter. &.LP0 was loaded to %r1 and the return address is in %r14. + * _mcount may not modify any register. + */ + + .globl C_SYMBOL_NAME(_mcount) + .type C_SYMBOL_NAME(_mcount), @function + cfi_startproc + .align ALIGNARG(4) +C_LABEL(_mcount) + /* Save the caller-clobbered registers. */ + ahi %r15,-128 + cfi_adjust_cfa_offset (128) + stm %r14,%r5,96(%r15) + cfi_offset (r14, 0) + cfi_offset (r15, 4) + l %r2,132(%r15) # callers address = first parameter + la %r2,0(%r2) # clear bit 0 + la %r3,0(%r14) # callees address = second parameter + +#ifdef PIC + bras %r14,0f + .long _GLOBAL_OFFSET_TABLE_-. +0: al %r14,0(%r14) + l %r14,__mcount_internal@GOT(%r14) +#else + bras %r14,0f + .long __mcount_internal +0: l %r14,0(%r14) +#endif + basr %r14,%r14 + + /* + * Pop the saved registers. Please note that `mcount' has no + * return value. + */ + lm %r14,%r5,96(%r15) + ahi %r15,128 + cfi_adjust_cfa_offset (-128) + br %r14 + cfi_endproc + ASM_SIZE_DIRECTIVE(C_SYMBOL_NAME(_mcount)) + +#undef mcount +weak_alias (_mcount, mcount) diff --git a/REORG.TODO/sysdeps/s390/s390-32/setjmp.S b/REORG.TODO/sysdeps/s390/s390-32/setjmp.S new file mode 100644 index 0000000000..1e240dbc83 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/setjmp.S @@ -0,0 +1,123 @@ +/* setjmp for s390, ELF version. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#include <sysdep.h> +#define _ASM +#define _SETJMP_H +#include <bits/setjmp.h> +#include <shlib-compat.h> +#include <stap-probe.h> + +#if !IS_IN (rtld) && defined SHARED \ + && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20) +# define NEED_COMPAT_SYMBOLS 1 +/* We need a unique name in case of symbol versioning. */ +# define setjmp __v1setjmp +# define _setjmp __v1_setjmp +# define __sigsetjmp __v1__sigsetjmp +#else +# define NEED_COMPAT_SYMBOLS 0 +#endif + + /* We include the BSD entry points here as well. */ +ENTRY (setjmp) + lhi %r3,1 /* second argument of one */ + j .Linternal_sigsetjmp /* branch relativ to __sigsetjmp */ +END (setjmp) + + /* Binary compatibility entry point. */ +ENTRY(_setjmp) + lhi %r3,0 /* second argument of zero */ + j .Linternal_sigsetjmp /* branch relativ to __sigsetjmp */ +END (_setjmp) +#if NEED_COMPAT_SYMBOLS +strong_alias (_setjmp, __GI__setjmp) +#else +libc_hidden_def (_setjmp) +#endif + +ENTRY(__setjmp) + lhi %r3,0 /* second argument of zero */ + j .Linternal_sigsetjmp /* branch relativ to __sigsetjmp */ +END (__setjmp) + +ENTRY(__sigsetjmp) +.Linternal_sigsetjmp: + /* setjmp probe expects sig/setjmp first argument (4@%r2), second + argument (-4@%r3) and target address (4@%r14). */ + LIBC_PROBE (setjmp, 3, 4@%r2, -4@%r3, 4@%r14) +#ifdef PTR_MANGLE + stm %r6,%r13,0(%r2) /* store registers in jmp_buf */ + lr %r4,%r14 + lr %r5,%r15 + PTR_MANGLE (%r4, %r1) + PTR_MANGLE2 (%r5, %r1) + stm %r4,%r5,32(%r2) +#else + stm %r6,%r15,0(%r2) /* store registers in jmp_buf */ +#endif + std %f4,40(%r2) + std %f6,48(%r2) +#if IS_IN (rtld) + /* In ld.so we never save the signal mask. */ + lhi %r2,0 + br %r14 +#elif defined PIC + /* We cannot use the PLT, because it requires that %r12 be set, but + we can't save and restore our caller's value. Instead, we do an + indirect jump through the GOT. */ + basr %r1,0 +.L0: al %r1,.L1 - .L0(0,%r1) /* get address of global offset table */ + /* get address of __sigjmp_save from got */ + l %r1,__sigjmp_save@GOT(%r1) + br %r1 +.L1: .long _GLOBAL_OFFSET_TABLE_ - .L0 +#else + basr %r1,0 +.L0: l %r1,.L1-.L0(0,%r1) /* load address of __sigjmp_save */ + br %r1 /* tail-call __sigjmp_save */ +.L1: .long __sigjmp_save +#endif +END (__sigsetjmp) +#if NEED_COMPAT_SYMBOLS +strong_alias (__sigsetjmp, __GI___sigsetjmp) +#else +libc_hidden_def (__sigsetjmp) +#endif + +#if NEED_COMPAT_SYMBOLS +/* In glibc release 2.19 new versions of setjmp-functions were introduced, + but were reverted before 2.20. Thus both versions are the same function. */ + +# undef setjmp +# undef _setjmp +# undef __sigsetjmp + +strong_alias (__v1setjmp, __v2setjmp); +versioned_symbol (libc, __v1setjmp, setjmp, GLIBC_2_0); +compat_symbol (libc, __v2setjmp, setjmp, GLIBC_2_19); + +strong_alias (__v1_setjmp, __v2_setjmp); +versioned_symbol (libc, __v1_setjmp, _setjmp, GLIBC_2_0); +compat_symbol (libc, __v2_setjmp, _setjmp, GLIBC_2_19); + +strong_alias (__v1__sigsetjmp, __v2__sigsetjmp); +versioned_symbol (libc, __v1__sigsetjmp, __sigsetjmp, GLIBC_2_0); +compat_symbol (libc, __v2__sigsetjmp, __sigsetjmp, GLIBC_2_19); +#endif /* NEED_COMPAT_SYMBOLS */ diff --git a/REORG.TODO/sysdeps/s390/s390-32/stackguard-macros.h b/REORG.TODO/sysdeps/s390/s390-32/stackguard-macros.h new file mode 100644 index 0000000000..46109744ed --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/stackguard-macros.h @@ -0,0 +1,15 @@ +#include <stdint.h> + +#define STACK_CHK_GUARD \ + ({ uintptr_t x; __asm__ ("ear %0,%%a0; l %0,0x14(%0)" : "=a" (x)); x; }) + +/* On s390/s390x there is no unique pointer guard, instead we use the + same value as the stack guard. */ +#define POINTER_CHK_GUARD \ + ({ \ + uintptr_t x; \ + __asm__ ("ear %0,%%a0; l %0,%1(%0)" \ + : "=a" (x) \ + : "i" (offsetof (tcbhead_t, stack_guard))); \ + x; \ + }) diff --git a/REORG.TODO/sysdeps/s390/s390-32/start.S b/REORG.TODO/sysdeps/s390/s390-32/start.S new file mode 100644 index 0000000000..07400f1752 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/start.S @@ -0,0 +1,211 @@ +/* Startup code compliant to the ELF s390 ABI. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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/>. */ + +/* + This is the canonical entry point, usually the first thing in the text + segment. Most registers' values are unspecified, except for: + + %r14 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %r15 The stack contains the arguments and environment: + 0(%r15) argc + 4(%r15) argv[0] + ... + (4*argc)(%r15) NULL + (4*(argc+1))(%r15) envp[0] + ... + NULL +*/ + + .text + .globl _start + .type _start,@function +_start: + /* Check if the kernel provides highgprs facility if needed by + the binary. */ + + lr %r6,%r15 + la %r6,4(%r6) /* Skip the argument counter. */ + +.L11: l %r5,0(%r6) /* Skip the argument vector. */ + la %r6,4(%r6) + ltr %r5,%r5 + jne .L11 + +.L12: l %r5,0(%r6) /* Skip the environment vector. */ + la %r6,4(%r6) + ltr %r5,%r5 + jne .L12 + + /* Usually the auxiliary vector can be expected directly after + the environment variables. But we have to skip extra zeros + because the loader might have removed unsecure variables for + setuid programs. */ + +.L26: l %r5,0(%r6) + la %r6,4(%r6) + ltr %r5,%r5 + jz .L26 + + ahi %r6,-4 + + /* Obtain the needed values from the auxiliary vector. */ + + lhi %r7,16 /* AT_HWCAP */ + lhi %r8,3 /* AT_PHDR */ + lhi %r9,5 /* AT_PHNUM */ + lhi %r2,4 /* AT_PHENT */ +.L13: l %r5,0(%r6) + clr %r5,%r7 + jne .L15 + l %r10,4(%r6) /* r10 = AT_HWCAP value. */ +.L15: clr %r5,%r8 + jne .L16 + l %r11,4(%r6) /* r11 = AT_PHDR value. */ +.L16: clr %r5,%r9 + jne .L17 + l %r12,4(%r6) /* r12 = AT_PHNUM value. */ +.L17: clr %r5,%r2 + jne .L18 + l %r0,4(%r6) /* r0 = AT_PHENT value. */ +.L18: ltr %r5,%r5 + la %r6,8(%r6) + jnz .L13 + + /* Locate the ELF header by looking for the first PT_LOAD + segment with a p_offset of zero. */ + + lr %r4,%r11 /* Backup AT_PHDR. */ + lhi %r7,1 /* PT_LOAD id */ + lhi %r8,0 +.L19: cl %r7,0(%r4) /* p_type == PT_LOAD? */ + jne .L20 + cl %r8,4(%r4) /* p_offset == 0? */ + jne .L20 + l %r9,8(%r4) /* r9 = PT_LOAD.p_vaddr <- ELF header address */ + j .L24 +.L20: alr %r4,%r0 /* r4 += AT_PHENT value */ + brct %r12,.L19 + + j .+2 /* Trap, there must be such a phdr. */ + +.L24: lr %r4,%r11 /* Backup AT_PHDR. */ + lhi %r2,6 /* PT_PHDR id */ +.L23: cl %r2,0(%r4) + jne .L22 + l %r3,8(%r4) /* r3 = PT_PHDR p_vaddr */ + j .L25 +.L22: alr %r4,%r0 /* r4 += AT_PHENT value */ + brct %r12,.L23 + + j .L14 /* No PT_PHDR found - skip checking. */ + +.L25: slr %r11,%r3 /* AT_PHDR - PT_PHDR.p_vaddr (relocation offset)*/ + alr %r9,%r11 /* PT_LOAD.p_vaddr += relocation offset */ + + l %r5,36(%r9) /* Load the e_flags field. */ + tml %r5,1 + jz .L14 /* Binary does not require highgprs facility. */ + + tml %r10,512 /* Check the AT_HWCAP value. */ + jz 2 /* Trap if no highgprs facility available. */ +.L14: + + /* Setup pointer to literal pool of _start */ + basr %r13,0 +.L0: ahi %r13,.Llit-.L0 + + /* load argc and argv from stack */ + la %r4,4(%r15) # get argv + l %r3,0(%r15) # get argc + + /* align the stack to a double word boundary */ + lhi %r0,-8 + nr %r15,%r0 + + /* Setup a stack frame and a parameter area */ + ahi %r15,-104 # make room on stack + xc 0(4,%r15),0(%r15) # clear back-chain + + /* set up arguments for __libc_start_main: + main, argc, argv, envp, _init, _fini, rtld_fini, stack_end + Note that envp will be determined later in __libc_start_main + */ + stm %r14,%r15,96(%r15) # store rtld_fini/stack_end to parameter area + la %r7,96(%r15) + l %r6,.L2-.Llit(%r13) # load pointer to __libc_csu_fini + l %r5,.L1-.Llit(%r13) # load pointer to __libc_csu_init + l %r2,.L3-.Llit(%r13) # load pointer to main + l %r1,.L4-.Llit(%r13) # load pointer to __libc_start_main +#ifdef PIC + l %r12,.L5-.Llit(%r13) # load .got pointer + la %r6,0(%r13,%r6) + la %r5,0(%r13,%r5) + la %r12,0(%r13,%r12) + l %r2,0(%r12,%r2) + la %r1,0(%r13,%r1) +#endif + + /* ok, now branch to the libc main routine */ + basr %r14,%r1 + + /* crash if __libc_start_main returns */ + .word 0 + +.Llit: +#ifndef PIC +.L1: .long __libc_csu_init +.L2: .long __libc_csu_fini +.L3: .long main +.L4: .long __libc_start_main +#else +.L1: .long __libc_csu_init-.Llit +.L2: .long __libc_csu_fini-.Llit +.L3: .long main@GOT +.L4: .long __libc_start_main@plt-.Llit +.L5: .long _GLOBAL_OFFSET_TABLE_-.Llit +#endif + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/REORG.TODO/sysdeps/s390/s390-32/strcmp.S b/REORG.TODO/sysdeps/s390/s390-32/strcmp.S new file mode 100644 index 0000000000..69754c5f5a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/strcmp.S @@ -0,0 +1,41 @@ +/* strcmp - compare two string. S/390 version. + This file is part of the GNU C Library. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* INPUT PARAMETERS + %r2 = address of string 1 + %r3 = address of string 2. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(strcmp) + slr %r0,%r0 +0: clst %r2,%r3 + jo 0b + jp 1f + jm 2f + slr %r2,%r2 + br %r14 +1: lhi %r2,1 + br %r14 +2: lhi %r2,-1 + br %r14 +END(strcmp) +libc_hidden_builtin_def (strcmp) diff --git a/REORG.TODO/sysdeps/s390/s390-32/strcpy.S b/REORG.TODO/sysdeps/s390/s390-32/strcpy.S new file mode 100644 index 0000000000..ab06ff8d72 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/strcpy.S @@ -0,0 +1,36 @@ +/* strcpy - copy a string from source to destination. For IBM S390 + This file is part of the GNU C Library. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* + * R2 = address of destination + * R3 = address of source + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(strcpy) + slr %r0,%r0 + lr %r1,%r2 +0: mvst %r1,%r3 + jo 0b + br %r14 +END(strcpy) +libc_hidden_builtin_def (strcpy) diff --git a/REORG.TODO/sysdeps/s390/s390-32/strncpy.S b/REORG.TODO/sysdeps/s390/s390-32/strncpy.S new file mode 100644 index 0000000000..c642bce90d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/strncpy.S @@ -0,0 +1,79 @@ +/* strncpy - copy at most n characters from a string from source to + destination. For IBM S390 + This file is part of the GNU C Library. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* + * R2 = address of destination (dst) + * R3 = address of source (src) + * R4 = max of bytes to copy + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +ENTRY(strncpy) + .text + st %r2,24(%r15) # save dst pointer + slr %r2,%r3 # %r3 points to src, %r2+%r3 to dst + lhi %r1,3 + nr %r1,%r4 # last 2 bits of # bytes + srl %r4,2 + ltr %r4,%r4 # less than 4 bytes to copy ? + jz .L1 + bras %r5,.L0 # enter loop & load address of a 0 + .long 0 +.L0: icm %r0,8,0(%r3) # first byte + jz .L3 + icm %r0,4,1(%r3) # second byte + jz .L4 + icm %r0,2,2(%r3) # third byte + jz .L5 + icm %r0,1,3(%r3) # fourth byte + jz .L6 + st %r0,0(%r2,%r3) # store all four to dest. + la %r3,4(%r3) + brct %r4,.L0 +.L1: ltr %r1,%r1 + jz .Lexit +.L2: icm %r0,1,0(%r3) + stc %r0,0(%r2,%r3) + la %r3,1(%r3) + jz .L7 + brct %r1,.L2 + j .Lexit +.L3: icm %r0,4,0(%r5) +.L4: icm %r0,2,0(%r5) +.L5: icm %r0,1,0(%r5) +.L6: st %r0,0(%r2,%r3) + la %r3,4(%r3) + ahi %r4,-1 + j .L8 +.L7: ahi %r1,-1 +.L8: sll %r4,2 + alr %r4,%r1 + alr %r2,%r3 # start of dst area to be zeroed + lr %r3,%r4 + slr %r4,%r4 + slr %r5,%r5 +.L9: mvcle %r2,%r4,0 # pad dst with zeroes + jo .L9 +.Lexit: l %r2,24(%r15) # return dst pointer + br %r14 +END(strncpy) +libc_hidden_builtin_def (strncpy) diff --git a/REORG.TODO/sysdeps/s390/s390-32/sub_n.S b/REORG.TODO/sysdeps/s390/s390-32/sub_n.S new file mode 100644 index 0000000000..358c8deddb --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/sub_n.S @@ -0,0 +1,62 @@ +/* __mpn_sub_n -- Add two limb vectors of the same length > 0 and store + sum in a third limb vector. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU MP Library. + + The GNU MP 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 MP 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 MP Library; see the file COPYING.LIB. If not, + see <http://www.gnu.org/licenses/>. */ + +/* + INPUT PARAMETERS + res_ptr %r2 + s1_ptr %r3 + s2_ptr %r4 + size %r5 +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +ENTRY(__mpn_sub_n) + st %r6,24(%r15) # save register 6 + cfi_offset (%r6, -72) + sr %r1,%r1 + lhi %r0,1 # cannot use ahi to add carry, use slr +.L0: l %r6,0(%r1,%r3) # .L0 -> no carry from last sub + sl %r6,0(%r1,%r4) + st %r6,0(%r1,%r2) + la %r1,4(0,%r1) + brc 4,.L3 +.L1: brct %r5,.L0 + slr %r2,%r2 # no last carry to return + j .Lexit +.L2: l %r6,0(%r1,%r3) # .L2 -> carry from last sub + sl %r6,0(%r1,%r4) + brc 4,.L4 + slr %r6,%r0 # no carry yet, add carry from last sub + st %r6,0(%r1,%r2) + la %r1,4(0,%r1) + brc 11,.L1 # new carry ? +.L3: brct %r5,.L2 + lr %r2,%r0 # return last carry + j .Lexit +.L4: slr %r6,%r0 # already a carry, add carry from last sub + st %r6,0(%r1,%r2) + la %r1,4(0,%r1) + brct %r5,.L2 + lr %r2,%r0 # return last carry +.Lexit: l %r6,24(%r15) # restore register 6 + br %r14 +END(__mpn_sub_n) diff --git a/REORG.TODO/sysdeps/s390/s390-32/symbol-hacks.h b/REORG.TODO/sysdeps/s390/s390-32/symbol-hacks.h new file mode 100644 index 0000000000..585c42365a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/symbol-hacks.h @@ -0,0 +1,21 @@ +/* Hacks needed for symbol manipulation. s390 version. + Copyright (C) 2017 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/>. */ + +#include <sysdeps/wordsize-32/divdi3-symbol-hacks.h> + +#include_next "symbol-hacks.h" diff --git a/REORG.TODO/sysdeps/s390/s390-32/sysdep.h b/REORG.TODO/sysdeps/s390/s390-32/sysdep.h new file mode 100644 index 0000000000..15a4e3e687 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/sysdep.h @@ -0,0 +1,101 @@ +/* Assembler macros for s390. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#include <sysdeps/generic/sysdep.h> + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1<<log2 +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name; + + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + .globl C_SYMBOL_NAME(name); \ + .type C_SYMBOL_NAME(name),@function; \ + .align ALIGNARG(2); \ + C_LABEL(name) \ + cfi_startproc; \ + CALL_MCOUNT + +#undef END +#define END(name) \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) \ + +/* If compiled for profiling, call `mcount' at the start of each function. */ +#ifdef PROF +#ifdef PIC +#define CALL_MCOUNT \ + lr 0,14 ; bras 14,.+12 ; .long _GLOBAL_OFFSET_TABLE_ - . ; .long 0f-. ; \ + lr 1,14 ; al 1,4(14) ; al 14,0(14) ; l 14,_mcount@GOT(14) ; \ + basr 14,14 ; lr 14,0 ; .data ; .align 4 ; 0: .long 0 ; .text ; +#else +#define CALL_MCOUNT \ + lr 0,14 ; bras 14,.+12 ; .long _mcount ; .long 0f ; \ + l 1,4(14) ; l 14,0(14) ; basr 14,14 ; lr 14,0 ; \ + .data ; .align 4 ; 0: .long 0 ; .text ; +#endif +#else +#define CALL_MCOUNT /* Do nothing. */ +#endif + +/* Since C identifiers are not normally prefixed with an underscore + on this system, the asm identifier `syscall_error' intrudes on the + C name space. Make sure we use an innocuous name. */ +#define syscall_error __syscall_error +#define mcount _mcount + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ +lose: SYSCALL_PIC_SETUP \ + basr %r1,0; \ +0: al %r1,1f-0b(%r1); \ + br %r1; \ +1: .long JUMPTARGET(syscall_error) - 0b; \ + .globl syscall_error; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + jm lose + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + END (name) + +#undef JUMPTARGET +#ifdef PIC +#define JUMPTARGET(name) name##@PLT +#define SYSCALL_PIC_SETUP \ + bras %r12,1f \ +0: .long _GLOBAL_OFFSET_TABLE_-0b \ +1: al %r12,0(%r12) +#else +#define JUMPTARGET(name) name +#define SYSCALL_PIC_SETUP /* Nothing. */ +#endif + +/* Local label name for asm code. */ +#ifndef L +#define L(name) .L##name +#endif + +#endif /* __ASSEMBLER__ */ diff --git a/REORG.TODO/sysdeps/s390/s390-32/tls-macros.h b/REORG.TODO/sysdeps/s390/s390-32/tls-macros.h new file mode 100644 index 0000000000..a4c5fffa33 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/tls-macros.h @@ -0,0 +1,104 @@ +#define TLS_LE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long " #x "@ntpoff\n" \ + "1:\tl %0,0(%0)" \ + : "=a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) + +#ifdef PIC +# define TLS_IE(x) \ + ({ unsigned long __offset, __got; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ + ".long " #x "@gotntpoff\n" \ + "1:\tl %1,0(%0)\n\t" \ + "la %1,0(%1,%0)\n\t" \ + "l %0,4(%0)\n\t" \ + "l %0,0(%0,%1):tls_load:" #x "\n" \ + : "=&a" (__offset), "=&a" (__got) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#else +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long " #x "@indntpoff\n" \ + "1:\t l %0,0(%0)\n\t" \ + "l %0,0(%0):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#endif + +#ifdef PIC +# define TLS_LD(x) \ + ({ unsigned long __offset, __save12; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ + ".long __tls_get_offset@plt-0b\n\t" \ + ".long " #x "@tlsldm\n\t" \ + ".long " #x "@dtpoff\n" \ + "1:\tlr %1,%%r12\n\t" \ + "l %%r12,0(%0)\n\t" \ + "la %%r12,0(%%r12,%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t" \ + "l %0,12(%0)\n\t" \ + "alr %0,%%r2\n\t" \ + "lr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5", "14"); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#else +# define TLS_LD(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \ + ".long __tls_get_offset@plt\n\t" \ + ".long " #x "@tlsldm\n\t" \ + ".long " #x "@dtpoff\n" \ + "1:\tl %%r12,0(%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t" \ + "l %0,12(%0)\n\t" \ + "alr %0,%%r2" \ + : "=&a" (__offset) \ + : : "cc", "0", "1", "2", "3", "4", "5", "12", "14"); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#endif + +#ifdef PIC +# define TLS_GD(x) \ + ({ unsigned long __offset, __save12; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ + ".long __tls_get_offset@plt-0b\n\t" \ + ".long " #x "@tlsgd\n" \ + "1:\tlr %1,%%r12\n\t" \ + "l %%r12,0(%0)\n\t" \ + "la %%r12,0(%%r12,%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t" \ + "lr %0,%%r2\n\t" \ + "lr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5", "14"); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#else +# define TLS_GD(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \ + ".long __tls_get_offset@plt\n\t" \ + ".long " #x "@tlsgd\n" \ + "1:\tl %%r12,0(%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t" \ + "lr %0,%%r2" \ + : "=&a" (__offset) \ + : : "cc", "0", "1", "2", "3", "4", "5", "12", "14"); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-32/tst-audit.h b/REORG.TODO/sysdeps/s390/s390-32/tst-audit.h new file mode 100644 index 0000000000..daabc70aa9 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-32/tst-audit.h @@ -0,0 +1,25 @@ +/* Definitions for testing PLT entry/exit auditing. S/390 32-bit version. + + Copyright (C) 2012-2017 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/>. */ + +#define pltenter la_s390_32_gnu_pltenter +#define pltexit la_s390_32_gnu_pltexit +#define La_regs La_s390_32_regs +#define La_retval La_s390_32_retval +#define int_retval lrv_r2 diff --git a/REORG.TODO/sysdeps/s390/s390-64/Implies b/REORG.TODO/sysdeps/s390/s390-64/Implies new file mode 100644 index 0000000000..a8cae95f9d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/Implies @@ -0,0 +1 @@ +wordsize-64 diff --git a/REORG.TODO/sysdeps/s390/s390-64/Makefile b/REORG.TODO/sysdeps/s390/s390-64/Makefile new file mode 100644 index 0000000000..b4d793bb3d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/Makefile @@ -0,0 +1,9 @@ +ifeq ($(subdir),gmon) +sysdep_routines += s390x-mcount +endif + +ifeq ($(subdir),elf) +CFLAGS-rtld.c += -Wno-uninitialized -Wno-unused +CFLAGS-dl-load.c += -Wno-unused +CFLAGS-dl-reloc.c += -Wno-unused +endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/__longjmp.c b/REORG.TODO/sysdeps/s390/s390-64/__longjmp.c new file mode 100644 index 0000000000..f7be9ddb18 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/__longjmp.c @@ -0,0 +1,89 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +#include <errno.h> +#include <sysdep.h> +#include <setjmp.h> +#include <bits/setjmp.h> +#include <stdlib.h> +#include <unistd.h> +#include <stap-probe.h> + +/* Jump to the position specified by ENV, causing the + setjmp call there to return VAL, or 1 if VAL is 0. */ +void +__longjmp (__jmp_buf env, int val) +{ +#ifdef PTR_DEMANGLE + uintptr_t guard = THREAD_GET_POINTER_GUARD (); +# ifdef CHECK_SP + CHECK_SP (env, guard); +# endif +#elif defined CHECK_SP + CHECK_SP (env, 0); +#endif + register long int r2 __asm__ ("%r2") = val == 0 ? 1 : val; +#ifdef PTR_DEMANGLE + register uintptr_t r3 __asm__ ("%r3") = guard; + register void *r1 __asm__ ("%r1") = (void *) env; +#endif + /* Restore registers and jump back. */ + __asm__ __volatile__ ( + /* longjmp probe expects longjmp first argument, second + argument and target address. */ +#ifdef PTR_DEMANGLE + "lmg %%r4,%%r5,64(%1)\n\t" + "xgr %%r4,%2\n\t" + "xgr %%r5,%2\n\t" + LIBC_PROBE_ASM (longjmp, 8@%1 -4@%0 8@%%r4) +#else + LIBC_PROBE_ASM (longjmp, 8@%1 -4@%0 8@%%r14) +#endif + + /* restore fpregs */ + "ld %%f8,80(%1)\n\t" + "ld %%f9,88(%1)\n\t" + "ld %%f10,96(%1)\n\t" + "ld %%f11,104(%1)\n\t" + "ld %%f12,112(%1)\n\t" + "ld %%f13,120(%1)\n\t" + "ld %%f14,128(%1)\n\t" + "ld %%f15,136(%1)\n\t" + + /* restore gregs and return to jmp_buf target */ +#ifdef PTR_DEMANGLE + "lmg %%r6,%%r13,0(%1)\n\t" + "lgr %%r15,%%r5\n\t" + LIBC_PROBE_ASM (longjmp_target, 8@%1 -4@%0 8@%%r4) + "br %%r4" +#else + "lmg %%r6,%%r15,0(%1)\n\t" + LIBC_PROBE_ASM (longjmp_target, 8@%1 -4@%0 8@%%r14) + "br %%r14" +#endif + : : "r" (r2), +#ifdef PTR_DEMANGLE + "r" (r1), "r" (r3) +#else + "a" (env) +#endif + ); + + /* Avoid `volatile function does return' warnings. */ + for (;;); +} diff --git a/REORG.TODO/sysdeps/s390/s390-64/add_n.S b/REORG.TODO/sysdeps/s390/s390-64/add_n.S new file mode 100644 index 0000000000..89197b2dbf --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/add_n.S @@ -0,0 +1,63 @@ +/* Add two limb vectors of the same length > 0 and store sum in a third + limb vector. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU MP Library. + + The GNU MP 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 MP 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 MP Library; see the file COPYING.LIB. If not, + see <http://www.gnu.org/licenses/>. */ + +/* + INPUT PARAMETERS + res_ptr %r2 + s1_ptr %r3 + s2_ptr %r4 + size %r5 +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(__mpn_add_n) + stg %r6,48(%r15) # save register 6 + cfi_offset (%r6,-112) + slgr %r1,%r1 + lghi %r0,1 # cannot use ahi to add carry, use alr +.L0: lg %r6,0(%r1,%r3) # .L0 -> no carry from last add + alg %r6,0(%r1,%r4) + stg %r6,0(%r1,%r2) + la %r1,8(%r1) + brc 3,.L3 +.L1: brct %r5,.L0 + slgr %r2,%r2 # no last carry to return + j .Lexit +.L2: lg %r6,0(%r1,%r3) # .L2 -> carry from last add + alg %r6,0(%r1,%r4) + brc 3,.L4 + algr %r6,%r0 # no carry yet, add carry from last add + stg %r6,0(%r1,%r2) + la %r1,8(%r1) + brc 12,.L1 # new carry ? +.L3: brct %r5,.L2 + lgr %r2,%r0 # return last carry + j .Lexit +.L4: algr %r6,%r0 # already a carry, add carry from last add + stg %r6,0(%r1,%r2) + la %r1,8(%r1) + brct %r5,.L2 + lgr %r2,%r0 # return last carry +.Lexit: lg %r6,48(%r15) # restore register 6 + br %r14 +END(__mpn_add_n) diff --git a/REORG.TODO/sysdeps/s390/s390-64/backtrace.c b/REORG.TODO/sysdeps/s390/s390-64/backtrace.c new file mode 100644 index 0000000000..4843db623a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/backtrace.c @@ -0,0 +1,147 @@ +/* Return backtrace of current program state. 64 bit S/390 version. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>. + 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/>. */ + +#include <libc-lock.h> +#include <dlfcn.h> +#include <execinfo.h> +#include <stddef.h> +#include <stdlib.h> +#include <unwind.h> + + +/* This is a global variable set at program start time. It marks the + highest used stack address. */ +extern void *__libc_stack_end; + + +/* This is the stack layout we see for every non-leaf function. + size offset + %r15 -> +------------------+ + 8 | back chain | 0 + 8 | end of stack | 8 + 32 | scratch | 16 + 80 | save area r6-r15 | 48 + 16 | save area f4,f6 | 128 + 16 | empty | 144 + +------------------+ + r14 in the save area holds the return address. +*/ + +struct layout +{ + long back_chain; + long end_of_stack; + long scratch[4]; + long save_grps[10]; + long save_fp[2]; + long empty[2]; +}; + +struct trace_arg +{ + void **array; + int cnt, size; +}; + +#ifdef SHARED +static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *); +static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *); + +static void +init (void) +{ + void *handle = __libc_dlopen ("libgcc_s.so.1"); + + if (handle == NULL) + return; + + unwind_backtrace = __libc_dlsym (handle, "_Unwind_Backtrace"); + unwind_getip = __libc_dlsym (handle, "_Unwind_GetIP"); + if (unwind_getip == NULL) + unwind_backtrace = NULL; +} + +static int +__backchain_backtrace (void **array, int size) +{ + /* We assume that all the code is generated with frame pointers set. */ + struct layout *stack; + int cnt = 0; + + __asm__ ("LGR %0,%%r15" : "=d" (stack) ); + /* We skip the call to this function, it makes no sense to record it. */ + stack = (struct layout *) stack->back_chain; + while (cnt < size) + { + if (stack == NULL || (void *) stack > __libc_stack_end) + /* This means the address is out of range. Note that for the + toplevel we see a frame pointer with value NULL which clearly is + out of range. */ + break; + + array[cnt++] = (void *) stack->save_grps[8]; + + stack = (struct layout *) stack->back_chain; + } + + return cnt; +} +#else +# define unwind_backtrace _Unwind_Backtrace +# define unwind_getip _Unwind_GetIP +#endif + +static _Unwind_Reason_Code +backtrace_helper (struct _Unwind_Context *ctx, void *a) +{ + struct trace_arg *arg = a; + + /* We are first called with address in the __backtrace function. + Skip it. */ + if (arg->cnt != -1) + arg->array[arg->cnt] = (void *) unwind_getip (ctx); + if (++arg->cnt == arg->size) + return _URC_END_OF_STACK; + return _URC_NO_REASON; +} + +int +__backtrace (void **array, int size) +{ + struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; + + if (size <= 0) + return 0; + +#ifdef SHARED + __libc_once_define (static, once); + + __libc_once (once, init); + + if (unwind_backtrace == NULL) + return __backchain_backtrace (array, size); +#endif + + unwind_backtrace (backtrace_helper, &arg); + + return arg.cnt != -1 ? arg.cnt : 0; +} + +weak_alias (__backtrace, backtrace) +libc_hidden_def (__backtrace) diff --git a/REORG.TODO/sysdeps/s390/s390-64/bcopy.S b/REORG.TODO/sysdeps/s390/s390-64/bcopy.S new file mode 100644 index 0000000000..235fc85568 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/bcopy.S @@ -0,0 +1,71 @@ +/* bcopy -- copy a block from source to destination. 64 bit S/390 version. + This file is part of the GNU C Library. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* INPUT PARAMETERS + %r2 = address of source + %r3 = address of destination + %r4 = number of bytes to copy. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(__bcopy) + ltgr %r1,%r4 # zero bcopy ? + jz .L4 + clgr %r2,%r3 # check against destructive overlap + jnl .L0 + algr %r1,%r2 + clgr %r1,%r3 + jh .L7 +.L0: aghi %r4,-1 # length - 1 + srlg %r1,%r4,8 + ltgr %r1,%r1 # < 256 bytes to move ? + jz .L2 + cghi %r1,255 # > 1MB to move ? + jh .L5 +.L1: mvc 0(256,%r3),0(%r2) # move in 256 byte chunks + la %r2,256(%r2) + la %r3,256(%r3) + brctg %r1,.L1 +.L2: bras %r1,.L3 # setup base pointer for execute + mvc 0(1,%r3),0(%r2) # instruction for execute +.L3: ex %r4,0(%r1) # execute mvc with length ((%r4)&255)+1 +.L4: br %r14 + # data copies > 1MB are faster with mvcle. +.L5: aghi %r4,1 # length + 1 + lgr %r5,%r4 # source length + lgr %r4,%r2 # source address + lgr %r2,%r3 # set destination + lgr %r3,%r5 # destination length = source length +.L6: mvcle %r2,%r4,0 # thats it, MVCLE is your friend + jo .L6 + br %r14 +.L7: # destructive overlay, can not use mvcle + lgr %r1,%r2 # bcopy is called with source,dest + lgr %r2,%r3 # memmove with dest,source! Oh, well... + lgr %r3,%r1 + jg HIDDEN_BUILTIN_JUMPTARGET(memmove) + +END(__bcopy) + +#ifndef NO_WEAK_ALIAS +weak_alias (__bcopy, bcopy) +#endif + diff --git a/REORG.TODO/sysdeps/s390/s390-64/bits/wordsize.h b/REORG.TODO/sysdeps/s390/s390-64/bits/wordsize.h new file mode 100644 index 0000000000..00e88b0628 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/bits/wordsize.h @@ -0,0 +1,11 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __s390x__ +# define __WORDSIZE 64 +#else +# define __WORDSIZE 32 +# define __WORDSIZE32_SIZE_ULONG 1 +# define __WORDSIZE32_PTRDIFF_LONG 0 +#endif + +#define __WORDSIZE_TIME64_COMPAT32 0 diff --git a/REORG.TODO/sysdeps/s390/s390-64/bsd-_setjmp.S b/REORG.TODO/sysdeps/s390/s390-64/bsd-_setjmp.S new file mode 100644 index 0000000000..1417270201 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/bsd-_setjmp.S @@ -0,0 +1 @@ +/* We don't need any code here since the setjmp.S file contains it. */ diff --git a/REORG.TODO/sysdeps/s390/s390-64/bsd-setjmp.S b/REORG.TODO/sysdeps/s390/s390-64/bsd-setjmp.S new file mode 100644 index 0000000000..1417270201 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/bsd-setjmp.S @@ -0,0 +1 @@ +/* We don't need any code here since the setjmp.S file contains it. */ diff --git a/REORG.TODO/sysdeps/s390/s390-64/bzero.S b/REORG.TODO/sysdeps/s390/s390-64/bzero.S new file mode 100644 index 0000000000..119c20dcb9 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/bzero.S @@ -0,0 +1,41 @@ +/* bzero -- set a block of memory to zero. 64 bit S/390 version. + This file is part of the GNU C Library. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* INPUT PARAMETERS + %r2 = address of memory area + %r3 = number of bytes to fill. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(__bzero) + ltgr %r3,%r3 + jz .L1 + sgr %r1,%r1 # set pad byte to zero + sgr %r4,%r4 # no source for MVCLE, only a pad byte + sgr %r5,%r5 +.L0: mvcle %r2,%r4,0(%r1) # thats it, MVCLE is your friend + jo .L0 +.L1: br %r14 +END(__bzero) + +#ifndef NO_WEAK_ALIAS +weak_alias (__bzero, bzero) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/crti.S b/REORG.TODO/sysdeps/s390/s390-64/crti.S new file mode 100644 index 0000000000..c9583bb9c9 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/crti.S @@ -0,0 +1,91 @@ +/* Special .init and .fini section support for 64 bit S/390. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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/>. */ + +/* crti.S puts a function prologue at the beginning of the .init and + .fini sections and defines global symbols for those addresses, so + they can be called as functions. The symbols _init and _fini are + magic and cause the linker to emit DT_INIT and DT_FINI. */ + +#include <libc-symbols.h> +#include <sysdep.h> + +#ifndef PREINIT_FUNCTION +# define PREINIT_FUNCTION __gmon_start__ +#endif + +#ifndef PREINIT_FUNCTION_WEAK +# define PREINIT_FUNCTION_WEAK 1 +#endif + +#if PREINIT_FUNCTION_WEAK + weak_extern (PREINIT_FUNCTION) +#else + .hidden PREINIT_FUNCTION +#endif + + .section .init,"ax",@progbits + .align 4 + .globl _init + .type _init,@function +_init: + stmg %r6,%r15,48(%r15) + lgr %r1,%r15 + aghi %r15,-160 + stg %r1,0(%r15) + larl %r12,_GLOBAL_OFFSET_TABLE_ +#if PREINIT_FUNCTION_WEAK + larl %r1,PREINIT_FUNCTION@GOTENT + lg %r1,0(%r1) + ltgr %r1,%r1 + je 1f + basr %r14,%r1 +#else + brasl %r14,PREINIT_FUNCTION +#endif + .align 4,0x07 +1: + + .section .fini,"ax",@progbits + .align 4 + .globl _fini + .type _fini,@function +_fini: + stmg %r6,%r15,48(%r15) + lgr %r1,%r15 + aghi %r15,-160 + stg %r1,0(%r15) + larl %r12,_GLOBAL_OFFSET_TABLE_ + .align 4,0x07 diff --git a/REORG.TODO/sysdeps/s390/s390-64/crtn.S b/REORG.TODO/sysdeps/s390/s390-64/crtn.S new file mode 100644 index 0000000000..2bb3211e57 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/crtn.S @@ -0,0 +1,50 @@ +/* Special .init and .fini section support for 64 bit S/390. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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/>. */ + +/* crtn.S puts function epilogues in the .init and .fini sections + corresponding to the prologues in crti.S. */ + + .section .init + .align 4 + lg %r4,272(%r15) + lmg %r6,%r15,208(%r15) + br %r4 + + .section .fini + .align 4 + lg %r4,272(%r15) + lmg %r6,%r15,208(%r15) + br %r4 diff --git a/REORG.TODO/sysdeps/s390/s390-64/dl-machine.h b/REORG.TODO/sysdeps/s390/s390-64/dl-machine.h new file mode 100644 index 0000000000..f2aeb1e78e --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/dl-machine.h @@ -0,0 +1,476 @@ +/* Machine-dependent ELF dynamic relocation inline functions. + 64 bit S/390 Version. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#ifndef dl_machine_h +#define dl_machine_h + +#define ELF_MACHINE_NAME "s390x" + +#include <sys/param.h> +#include <string.h> +#include <link.h> +#include <sysdeps/s390/dl-procinfo.h> +#include <dl-irel.h> + +#define ELF_MACHINE_IRELATIVE R_390_IRELATIVE + +/* This is an older, now obsolete value. */ +#define EM_S390_OLD 0xA390 + +/* Return nonzero iff E_MACHINE is compatible with the running host. */ +static inline int +elf_machine_matches_host (const Elf64_Ehdr *ehdr) +{ + return (ehdr->e_machine == EM_S390 || ehdr->e_machine == EM_S390_OLD) + && ehdr->e_ident[EI_CLASS] == ELFCLASS64; +} + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ + +static inline Elf64_Addr +elf_machine_dynamic (void) +{ + register Elf64_Addr *got; + + __asm__ ( " larl %0,_GLOBAL_OFFSET_TABLE_\n" + : "=&a" (got) : : "0" ); + + return *got; +} + +/* Return the run-time load address of the shared object. */ +static inline Elf64_Addr +elf_machine_load_address (void) +{ + Elf64_Addr addr; + + __asm__( " larl %0,_dl_start\n" + " larl 1,_GLOBAL_OFFSET_TABLE_\n" + " lghi 2,_dl_start@GOT\n" + " slg %0,0(2,1)" + : "=&d" (addr) : : "1", "2" ); + return addr; +} + +/* Set up the loaded object described by L so its unrelocated PLT + entries will jump to the on-demand fixup code in dl-runtime.c. */ + +static inline int __attribute__ ((unused)) +elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) +{ + extern void _dl_runtime_resolve (Elf64_Word); + extern void _dl_runtime_profile (Elf64_Word); +#if defined HAVE_S390_VX_ASM_SUPPORT + extern void _dl_runtime_resolve_vx (Elf64_Word); + extern void _dl_runtime_profile_vx (Elf64_Word); +#endif + + if (l->l_info[DT_JMPREL] && lazy) + { + /* The GOT entries for functions in the PLT have not yet been filled + in. Their initial contents will arrange when called to push an + offset into the .rela.plt section, push _GLOBAL_OFFSET_TABLE_[1], + and then jump to _GLOBAL_OFFSET_TABLE[2]. */ + Elf64_Addr *got; + got = (Elf64_Addr *) D_PTR (l, l_info[DT_PLTGOT]); + /* If a library is prelinked but we have to relocate anyway, + we have to be able to undo the prelinking of .got.plt. + The prelinker saved us here address of .plt + 0x2e. */ + if (got[1]) + { + l->l_mach.plt = got[1] + l->l_addr; + l->l_mach.jmprel = (const Elf64_Rela *) D_PTR (l, l_info[DT_JMPREL]); + } + got[1] = (Elf64_Addr) l; /* Identify this shared object. */ + + /* The got[2] entry contains the address of a function which gets + called to get the address of a so far unresolved function and + jump to it. The profiling extension of the dynamic linker allows + to intercept the calls to collect information. In this case we + don't store the address in the GOT so that all future calls also + end in this function. */ + if (__glibc_unlikely (profile)) + { +#if defined HAVE_S390_VX_ASM_SUPPORT + if (GLRO(dl_hwcap) & HWCAP_S390_VX) + got[2] = (Elf64_Addr) &_dl_runtime_profile_vx; + else + got[2] = (Elf64_Addr) &_dl_runtime_profile; +#else + got[2] = (Elf64_Addr) &_dl_runtime_profile; +#endif + + if (GLRO(dl_profile) != NULL + && _dl_name_match_p (GLRO(dl_profile), l)) + /* This is the object we are looking for. Say that we really + want profiling and the timers are started. */ + GL(dl_profile_map) = l; + } + else + { + /* This function will get called to fix up the GOT entry indicated by + the offset on the stack, and then jump to the resolved address. */ +#if defined HAVE_S390_VX_ASM_SUPPORT + if (GLRO(dl_hwcap) & HWCAP_S390_VX) + got[2] = (Elf64_Addr) &_dl_runtime_resolve_vx; + else + got[2] = (Elf64_Addr) &_dl_runtime_resolve; +#else + got[2] = (Elf64_Addr) &_dl_runtime_resolve; +#endif + } + } + + return lazy; +} + +/* Initial entry point code for the dynamic linker. + The C function `_dl_start' is the real entry point; + its return value is the user program's entry point. */ + +#define RTLD_START __asm__ ("\n\ +.text\n\ +.align 4\n\ +.globl _start\n\ +.globl _dl_start_user\n\ +_start:\n\ + lgr %r2,%r15\n\ + # Alloc stack frame\n\ + aghi %r15,-160\n\ + # Set the back chain to zero\n\ + xc 0(8,%r15),0(%r15)\n\ + # Call _dl_start with %r2 pointing to arg on stack\n\ + brasl %r14,_dl_start # call _dl_start\n\ +_dl_start_user:\n\ + # Save the user entry point address in %r8.\n\ + lgr %r8,%r2\n\ + # Point %r12 at the GOT.\n\ + larl %r12,_GLOBAL_OFFSET_TABLE_\n\ + # See if we were run as a command with the executable file\n\ + # name as an extra leading argument.\n\ + lghi %r1,_dl_skip_args@GOT\n\ + lg %r1,0(%r1,%r12)\n\ + lgf %r1,0(%r1) # load _dl_skip_args\n\ + # Get the original argument count.\n\ + lg %r0,160(%r15)\n\ + # Subtract _dl_skip_args from it.\n\ + sgr %r0,%r1\n\ + # Adjust the stack pointer to skip _dl_skip_args words.\n\ + sllg %r1,%r1,3\n\ + agr %r15,%r1\n\ + # Set the back chain to zero again\n\ + xc 0(8,%r15),0(%r15)\n\ + # Store back the modified argument count.\n\ + stg %r0,160(%r15)\n\ + # The special initializer gets called with the stack just\n\ + # as the application's entry point will see it; it can\n\ + # switch stacks if it moves these contents over.\n\ +" RTLD_START_SPECIAL_INIT "\n\ + # Call the function to run the initializers.\n\ + # Load the parameters:\n\ + # (%r2, %r3, %r4, %r5) = (_dl_loaded, argc, argv, envp)\n\ + lghi %r2,_rtld_local@GOT\n\ + lg %r2,0(%r2,%r12)\n\ + lg %r2,0(%r2)\n\ + lg %r3,160(%r15)\n\ + la %r4,168(%r15)\n\ + lgr %r5,%r3\n\ + sllg %r5,%r5,3\n\ + la %r5,176(%r5,%r15)\n\ + brasl %r14,_dl_init@PLT\n\ + # Pass our finalizer function to the user in %r14, as per ELF ABI.\n\ + lghi %r14,_dl_fini@GOT\n\ + lg %r14,0(%r14,%r12)\n\ + # Free stack frame\n\ + aghi %r15,160\n\ + # Jump to the user's entry point (saved in %r8).\n\ + br %r8\n\ +"); + +#ifndef RTLD_START_SPECIAL_INIT +#define RTLD_START_SPECIAL_INIT /* nothing */ +#endif + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_390_JMP_SLOT || (type) == R_390_TLS_DTPMOD \ + || (type) == R_390_TLS_DTPOFF || (type) == R_390_TLS_TPOFF) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ +#define ELF_MACHINE_JMP_SLOT R_390_JMP_SLOT + +/* The 64 bit S/390 never uses Elf64_Rel relocations. */ +#define ELF_MACHINE_NO_REL 1 +#define ELF_MACHINE_NO_RELA 0 + +/* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ +#define DL_PLATFORM_INIT dl_platform_init () + +static inline void __attribute__ ((unused)) +dl_platform_init (void) +{ + if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') + /* Avoid an empty string which would disturb us. */ + GLRO(dl_platform) = NULL; +} + +static inline Elf64_Addr +elf_machine_fixup_plt (struct link_map *map, lookup_t t, + const Elf64_Rela *reloc, + Elf64_Addr *reloc_addr, Elf64_Addr value) +{ + return *reloc_addr = value; +} + +/* Return the final value of a plt relocation. */ +static inline Elf64_Addr +elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc, + Elf64_Addr value) +{ + return value; +} + +/* Names of the architecture-specific auditing callback functions. */ +#define ARCH_LA_PLTENTER s390_64_gnu_pltenter +#define ARCH_LA_PLTEXIT s390_64_gnu_pltexit + +#endif /* !dl_machine_h */ + +#ifdef RESOLVE_MAP + +/* Perform the relocation specified by RELOC and SYM (which is fully resolved). + MAP is the object containing the reloc. */ + +auto inline void +__attribute__ ((always_inline)) +elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, + const Elf64_Sym *sym, const struct r_found_version *version, + void *const reloc_addr_arg, int skip_ifunc) +{ + Elf64_Addr *const reloc_addr = reloc_addr_arg; + const unsigned int r_type = ELF64_R_TYPE (reloc->r_info); + +#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC + if (__glibc_unlikely (r_type == R_390_RELATIVE)) + { +# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC + /* This is defined in rtld.c, but nowhere in the static libc.a; + make the reference weak so static programs can still link. + This declaration cannot be done when compiling rtld.c + (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the + common defn for _dl_rtld_map, which is incompatible with a + weak decl in the same file. */ +# ifndef SHARED + weak_extern (GL(dl_rtld_map)); +# endif + if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ +# endif + *reloc_addr = map->l_addr + reloc->r_addend; + } + else +#endif + if (__glibc_unlikely (r_type == R_390_NONE)) + return; + else + { +#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP + /* Only needed for R_390_COPY below. */ + const Elf64_Sym *const refsym = sym; +#endif + struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); + Elf64_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value; + + if (sym != NULL + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, + 0) + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) + && __builtin_expect (!skip_ifunc, 1)) + value = elf_ifunc_invoke (value); + + switch (r_type) + { + case R_390_IRELATIVE: + value = map->l_addr + reloc->r_addend; + if (__glibc_likely (!skip_ifunc)) + value = elf_ifunc_invoke (value); + *reloc_addr = value; + break; + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + *reloc_addr = value + reloc->r_addend; + break; + +#ifndef RESOLVE_CONFLICT_FIND_MAP + case R_390_TLS_DTPMOD: +# ifdef RTLD_BOOTSTRAP + /* During startup the dynamic linker is always the module + with index 1. + XXX If this relocation is necessary move before RESOLVE + call. */ + *reloc_addr = 1; +# else + /* Get the information from the link map returned by the + resolv function. */ + if (sym_map != NULL) + *reloc_addr = sym_map->l_tls_modid; +# endif + break; + case R_390_TLS_DTPOFF: +# ifndef RTLD_BOOTSTRAP + /* During relocation all TLS symbols are defined and used. + Therefore the offset is already correct. */ + if (sym != NULL) + *reloc_addr = sym->st_value + reloc->r_addend; +# endif + break; + case R_390_TLS_TPOFF: + /* The offset is negative, forward from the thread pointer. */ +# ifdef RTLD_BOOTSTRAP + *reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset; +# else + /* We know the offset of the object the symbol is contained in. + It is a negative value which will be added to the + thread pointer. */ + if (sym != NULL) + { + CHECK_STATIC_TLS (map, sym_map); + *reloc_addr = (sym->st_value + reloc->r_addend + - sym_map->l_tls_offset); + } +#endif + break; +#endif /* use TLS */ + +#ifndef RTLD_BOOTSTRAP +# ifndef RESOLVE_CONFLICT_FIND_MAP + /* Not needed for dl-conflict.c. */ + case R_390_COPY: + if (sym == NULL) + /* This can happen in trace mode if an object could not be + found. */ + break; + if (__builtin_expect (sym->st_size > refsym->st_size, 0) + || (__builtin_expect (sym->st_size < refsym->st_size, 0) + && __builtin_expect (GLRO(dl_verbose), 0))) + { + const char *strtab; + + strtab = (const char *) D_PTR (map,l_info[DT_STRTAB]); + _dl_error_printf ("\ +%s: Symbol `%s' has different size in shared object, consider re-linking\n", + RTLD_PROGNAME, strtab + refsym->st_name); + } + memcpy (reloc_addr_arg, (void *) value, + MIN (sym->st_size, refsym->st_size)); + break; +# endif + case R_390_64: + *reloc_addr = value + reloc->r_addend; + break; + case R_390_32: + *(unsigned int *) reloc_addr = value + reloc->r_addend; + break; + case R_390_16: + *(unsigned short *) reloc_addr = value + reloc->r_addend; + break; + case R_390_8: + *(char *) reloc_addr = value + reloc->r_addend; + break; +# ifndef RESOLVE_CONFLICT_FIND_MAP + case R_390_PC64: + *reloc_addr = value +reloc->r_addend - (Elf64_Addr) reloc_addr; + break; + case R_390_PC32DBL: + *(unsigned int *) reloc_addr = (unsigned int) + ((int) (value + reloc->r_addend - (Elf64_Addr) reloc_addr) >> 1); + break; + case R_390_PC32: + *(unsigned int *) reloc_addr = + value + reloc->r_addend - (Elf64_Addr) reloc_addr; + break; + case R_390_PC16DBL: + *(unsigned short *) reloc_addr = (unsigned short) + ((short) (value + reloc->r_addend - (Elf64_Addr) reloc_addr) >> 1); + break; + case R_390_PC16: + *(unsigned short *) reloc_addr = + value + reloc->r_addend - (Elf64_Addr) reloc_addr; + break; + case R_390_NONE: + break; +# endif +#endif +#if !defined(RTLD_BOOTSTRAP) || defined(_NDEBUG) + default: + /* We add these checks in the version to relocate ld.so only + if we are still debugging. */ + _dl_reloc_bad_type (map, r_type, 0); + break; +#endif + } + } +} + +auto inline void +__attribute__ ((always_inline)) +elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc, + void *const reloc_addr_arg) +{ + Elf64_Addr *const reloc_addr = reloc_addr_arg; + *reloc_addr = l_addr + reloc->r_addend; +} + +auto inline void +__attribute__ ((always_inline)) +elf_machine_lazy_rel (struct link_map *map, + Elf64_Addr l_addr, const Elf64_Rela *reloc, + int skip_ifunc) +{ + Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset); + const unsigned int r_type = ELF64_R_TYPE (reloc->r_info); + /* Check for unexpected PLT reloc type. */ + if (__glibc_likely (r_type == R_390_JMP_SLOT)) + { + if (__builtin_expect (map->l_mach.plt, 0) == 0) + *reloc_addr += l_addr; + else + *reloc_addr = map->l_mach.plt + (reloc - map->l_mach.jmprel) * 32; + } + else if (__glibc_likely (r_type == R_390_IRELATIVE)) + { + Elf64_Addr value = map->l_addr + reloc->r_addend; + if (__glibc_likely (!skip_ifunc)) + value = elf_ifunc_invoke (value); + *reloc_addr = value; + } + else + _dl_reloc_bad_type (map, r_type, 1); +} + +#endif /* RESOLVE_MAP */ diff --git a/REORG.TODO/sysdeps/s390/s390-64/dl-trampoline.S b/REORG.TODO/sysdeps/s390/s390-64/dl-trampoline.S new file mode 100644 index 0000000000..2e3b141e30 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/dl-trampoline.S @@ -0,0 +1,33 @@ +/* PLT trampolines. s390x version. + Copyright (C) 2005-2017 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/>. */ + +#include <sysdep.h> + + .text +/* Create variant of _dl_runtime_resolve/profile for machines before z13. + No vector registers are saved/restored. */ +#include <dl-trampoline.h> + +#if defined HAVE_S390_VX_ASM_SUPPORT +/* Create variant of _dl_runtime_resolve/profile for z13 and newer. + The vector registers are saved/restored, too.*/ +# define _dl_runtime_resolve _dl_runtime_resolve_vx +# define _dl_runtime_profile _dl_runtime_profile_vx +# define RESTORE_VRS +# include <dl-trampoline.h> +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/dl-trampoline.h b/REORG.TODO/sysdeps/s390/s390-64/dl-trampoline.h new file mode 100644 index 0000000000..e1f95e2ecd --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/dl-trampoline.h @@ -0,0 +1,225 @@ +/* PLT trampolines. s390x version. + Copyright (C) 2016-2017 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/>. */ + +/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile + * with the following linkage: + * r2 - r6 : parameter registers + * f0, f2, f4, f6 : floating point parameter registers + * v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers + * 48(r15), 56(r15) : PLT arguments PLT1, PLT2 + * 160(r15) : additional stack parameters + * The normal clobber rules for function calls apply: + * r0 - r5 : call clobbered + * r6 - r13 : call saved + * r14 : return address (call clobbered) + * r15 : stack pointer (call saved) + * f0 - f7 : call clobbered + * f8 - f15 : call saved + * v0 - v7 : bytes 0-7 overlap with f0-f7: call clobbered + bytes 8-15: call clobbered + * v8 - v15 : bytes 0-7 overlap with f8-f15: call saved + bytes 8-15: call clobbered + * v16 - v31 : call clobbered + */ + + .globl _dl_runtime_resolve + .type _dl_runtime_resolve, @function + cfi_startproc + .align 16 +_dl_runtime_resolve: + stmg %r2,%r5,64(%r15) # save call-clobbered argument registers + cfi_offset (r2, -96) + cfi_offset (r3, -88) + cfi_offset (r4, -80) + cfi_offset (r5, -72) + std %f0,104(%r15) + cfi_offset (f0, -56) + std %f2,112(%r15) + cfi_offset (f2, -48) + std %f4,120(%r15) + cfi_offset (f4, -40) + std %f6,128(%r15) + cfi_offset (f6, -32) + stg %r14,96(15) + cfi_offset (r14, -64) + lmg %r2,%r3,48(%r15) # load args for fixup saved by PLT + lgr %r0,%r15 +#ifdef RESTORE_VRS + aghi %r15,-288 # create stack frame + cfi_adjust_cfa_offset (288) + .machine push + .machine "z13" + vstm %v24,%v31,160(%r15)# store call-clobbered vector argument registers + cfi_offset (v24, -288) + cfi_offset (v25, -272) + cfi_offset (v26, -256) + cfi_offset (v27, -240) + cfi_offset (v28, -224) + cfi_offset (v29, -208) + cfi_offset (v30, -192) + cfi_offset (v31, -176) + .machine pop +#else + aghi %r15,-160 # create stack frame + cfi_adjust_cfa_offset (160) +#endif + stg %r0,0(%r15) # write backchain + brasl %r14,_dl_fixup # call _dl_fixup + lgr %r1,%r2 # function addr returned in r2 +#ifdef RESTORE_VRS + .machine push + .machine "z13" + vlm %v24,%v31,160(%r15)# restore vector registers + .machine pop + aghi %r15,288 # remove stack frame + cfi_adjust_cfa_offset (-288) +#else + aghi %r15,160 # remove stack frame + cfi_adjust_cfa_offset (-160) +#endif + lg %r14,96(%r15) # restore registers + ld %f0,104(%r15) + ld %f2,112(%r15) + ld %f4,120(%r15) + ld %f6,128(%r15) + lmg %r2,%r5,64(%r15) + br %r1 + cfi_endproc + .size _dl_runtime_resolve, .-_dl_runtime_resolve + + +#ifndef PROF + .globl _dl_runtime_profile + .type _dl_runtime_profile, @function + cfi_startproc + .align 16 +_dl_runtime_profile: + stg %r12,24(%r15) # r12 is used as backup of r15 + cfi_offset (r12, -136) + stg %r14,32(%r15) + cfi_offset (r14, -128) + lgr %r12,%r15 # backup stack pointer + cfi_def_cfa_register (12) + aghi %r15,-360 # create stack frame: + # 160 + sizeof(La_s390_64_regs) + stg %r12,0(%r15) # save backchain + + stmg %r2,%r6,160(%r15) # save call-clobbered arg regs + cfi_offset (r2, -360) # + r6 needed as arg for + cfi_offset (r3, -352) # _dl_profile_fixup + cfi_offset (r4, -344) + cfi_offset (r5, -336) + cfi_offset (r6, -328) + std %f0,200(%r15) + cfi_offset (f0, -320) + std %f2,208(%r15) + cfi_offset (f2, -312) + std %f4,216(%r15) + cfi_offset (f4, -304) + std %f6,224(%r15) + cfi_offset (f6, -296) +#ifdef RESTORE_VRS + .machine push + .machine "z13" + vstm %v24,%v31,232(%r15) # store call-clobbered vector arguments + cfi_offset (v24, -288) + cfi_offset (v25, -272) + cfi_offset (v26, -256) + cfi_offset (v27, -240) + cfi_offset (v28, -224) + cfi_offset (v29, -208) + cfi_offset (v30, -192) + cfi_offset (v31, -176) + .machine pop +#endif + lmg %r2,%r3,48(%r12) # load arguments saved by PLT + lgr %r4,%r14 # return address as third parameter + la %r5,160(%r15) # pointer to struct La_s390_64_regs + la %r6,40(%r12) # long int * framesize + brasl %r14,_dl_profile_fixup # call resolver + lgr %r1,%r2 # function addr returned in r2 + ld %f0,200(%r15) # restore call-clobbered arg fprs + ld %f2,208(%r15) + ld %f4,216(%r15) + ld %f6,224(%r15) +#ifdef RESTORE_VRS + .machine push + .machine "z13" + vlm %v24,%v31,232(%r15) # restore call-clobbered arg vrs + .machine pop +#endif + lg %r0,40(%r12) # load framesize + ltgr %r0,%r0 + jnm 1f + + lmg %r2,%r6,160(%r15) # framesize < 0 means no pltexit call + # so we can do a tail call without + # copying the arg overflow area + lgr %r15,%r12 # remove stack frame + cfi_def_cfa_register (15) + lg %r14,32(%r15) # restore registers + lg %r12,24(%r15) + br %r1 # tail-call to resolved function + + cfi_def_cfa_register (12) +1: la %r4,160(%r15) # pointer to struct La_s390_64_regs + stg %r4,64(%r12) + jz 4f # framesize == 0 ? + aghi %r0,7 # align framesize to 8 + nill %r0,0xfff8 + slgr %r15,%r0 # make room for framesize bytes + stg %r12,0(%r15) # save backchain + la %r2,160(%r15) + la %r3,160(%r12) + srlg %r0,%r0,3 +3: mvc 0(8,%r2),0(%r3) # copy additional parameters + la %r2,8(%r2) # depending on framesize + la %r3,8(%r3) + brctg %r0,3b +4: lmg %r2,%r6,0(%r4) # restore call-clobbered arg gprs + basr %r14,%r1 # call resolved function + stg %r2,72(%r12) # store return values r2, f0 + std %f0,80(%r12) # to struct La_s390_64_retval +#ifdef RESTORE_VRS + .machine push + .machine "z13" + vst %v24,88(%r12) # store return value v24 + .machine pop +#endif + lmg %r2,%r4,48(%r12) # r2, r3: load arguments saved by PLT + # r4: pointer to struct La_s390_64_regs + la %r5,72(%r12) # pointer to struct La_s390_64_retval + brasl %r14,_dl_call_pltexit + + lgr %r15,%r12 # remove stack frame + cfi_def_cfa_register (15) + lg %r14,32(%r15) # restore registers + lg %r12,24(%r15) + lg %r2,72(%r15) # restore return values + ld %f0,80(%r15) +#ifdef RESTORE_VRS + .machine push + .machine "z13" + vl %v24,88(%r15) # restore return value v24 + .machine pop +#endif + br %r14 # Jump back to caller + + cfi_endproc + .size _dl_runtime_profile, .-_dl_runtime_profile +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/memchr.S b/REORG.TODO/sysdeps/s390/s390-64/memchr.S new file mode 100644 index 0000000000..7deee3d6f3 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/memchr.S @@ -0,0 +1,40 @@ +/* Search a character in a block of memory. 64 bit S/390 version. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +/* INPUT PARAMETERS + %r2 = address to memory area + %r3 = character to find + %r4 = number of bytes to search. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(memchr) + lghi %r0,0xff + ngr %r0,%r3 + lgr %r1,%r2 + la %r2,0(%r4,%r1) +0: srst %r2,%r1 + jo 0b + brc 13,1f + slgr %r2,%r2 +1: br %r14 +END(memchr) +libc_hidden_builtin_def (memchr) diff --git a/REORG.TODO/sysdeps/s390/s390-64/memcmp.S b/REORG.TODO/sysdeps/s390/s390-64/memcmp.S new file mode 100644 index 0000000000..cecffc39f9 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/memcmp.S @@ -0,0 +1,64 @@ +/* memcmp - compare two memory blocks. 64 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include <sysdep.h> +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of first memory area + %r3 = address of second memory area + %r4 = number of bytes to compare. */ + + .text +#ifdef USE_MULTIARCH +ENTRY(__memcmp_default) +#else +ENTRY(memcmp) +#endif + .machine "z900" + ltgr %r4,%r4 + je .L_Z900_4 + aghi %r4,-1 + srlg %r1,%r4,8 + ltgr %r1,%r1 + jne .L_Z900_12 +.L_Z900_3: + larl %r1,.L_Z900_15 + ex %r4,0(%r1) +.L_Z900_4: + ipm %r2 + sllg %r2,%r2,34 + srag %r2,%r2,62 + br %r14 +.L_Z900_12: + clc 0(256,%r3),0(%r2) + jne .L_Z900_4 + la %r3,256(%r3) + la %r2,256(%r2) + brctg %r1,.L_Z900_12 + j .L_Z900_3 +.L_Z900_15: + clc 0(1,%r3),0(%r2) +#ifdef USE_MULTIARCH +END(__memcmp_default) +#else +END(memcmp) +libc_hidden_builtin_def (memcmp) +weak_alias (memcmp, bcmp) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/memcpy.S b/REORG.TODO/sysdeps/s390/s390-64/memcpy.S new file mode 100644 index 0000000000..3df07b5e23 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/memcpy.S @@ -0,0 +1,88 @@ +/* memcpy - copy a block from source to destination. 64 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include <sysdep.h> +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of destination memory area + %r3 = address of source memory area + %r4 = number of bytes to copy. */ + + + .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 + +ENTRY(memcpy) + .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 + jne .L_Z900_13 +.L_Z900_3: + larl %r5,.L_Z900_15 + ex %r4,0(%r5) +.L_Z900_4: + br %r14 +.L_Z900_13: + cghi %r5,4096 # Switch to mvcle for copies >1MB + jh __memcpy_mvcle +.L_Z900_12: + mvc 0(256,%r1),0(%r3) + la %r1,256(%r1) + la %r3,256(%r3) + brctg %r5,.L_Z900_12 + j .L_Z900_3 +.L_Z900_15: + mvc 0(1,%r1),0(%r3) +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. + 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,%r0 # return destination address + br %r14 +END(__memcpy_mvcle) diff --git a/REORG.TODO/sysdeps/s390/s390-64/memset.S b/REORG.TODO/sysdeps/s390/s390-64/memset.S new file mode 100644 index 0000000000..e653f12134 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/memset.S @@ -0,0 +1,64 @@ +/* Set a block of memory to some byte value. 64 bit S/390 version. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + + +#include <sysdep.h> +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of memory area + %r3 = byte to fill memory with + %r4 = number of bytes to fill. */ + + .text + +#ifdef USE_MULTIARCH +ENTRY(__memset_default) +#else +ENTRY(memset) +#endif + .machine "z900" + ltgr %r4,%r4 + je .L_Z900_4 + stc %r3,0(%r2) + cghi %r4,1 + lgr %r1,%r2 + je .L_Z900_4 + aghi %r4,-2 + srlg %r3,%r4,8 + ltgr %r3,%r3 + jne .L_Z900_14 +.L_Z900_3: + larl %r3,.L_Z900_18 + ex %r4,0(%r3) +.L_Z900_4: + br %r14 +.L_Z900_14: + mvc 1(256,%r1),0(%r1) + la %r1,256(%r1) + brctg %r3,.L_Z900_14 + j .L_Z900_3 +.L_Z900_18: + mvc 1(1,%r1),0(%r1) +#ifdef USE_MULTIARCH +END(__memset_default) +#else +END(memset) +libc_hidden_builtin_def (memset) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/Makefile b/REORG.TODO/sysdeps/s390/s390-64/multiarch/Makefile new file mode 100644 index 0000000000..91053b5364 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/Makefile @@ -0,0 +1,4 @@ +ifeq ($(subdir),string) +sysdep_routines += memset memset-s390x memcpy memcpy-s390x \ + memcmp memcmp-s390x +endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/memchr.c b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memchr.c new file mode 100644 index 0000000000..808c3b837a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memchr.c @@ -0,0 +1,21 @@ +/* Multiple versions of memchr. + Copyright (C) 2015-2017 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/>. */ + +/* This wrapper-file is needed, because otherwise file + sysdeps/s390/s390-[32|64]/memchr.S will be used. */ +#include <sysdeps/s390/multiarch/memchr.c> diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcmp-s390x.S b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcmp-s390x.S new file mode 100644 index 0000000000..da956d2568 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcmp-s390x.S @@ -0,0 +1,104 @@ +/* CPU specific memcmp implementations. 64 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of first memory area + %r3 = address of second memory area + %r4 = number of bytes to compare. */ + + .text + +#if IS_IN (libc) + +ENTRY(__memcmp_z196) + .machine "z196" + ltgr %r4,%r4 + je .L_Z196_4 + aghi %r4,-1 + srlg %r1,%r4,8 + ltgr %r1,%r1 + jne .L_Z196_2 +.L_Z196_3: + exrl %r4,.L_Z196_14 +.L_Z196_4: + ipm %r2 + sllg %r2,%r2,34 + srag %r2,%r2,62 + br %r14 +.L_Z196_17: + la %r3,256(%r3) + la %r2,256(%r2) + aghi %r1,-1 + je .L_Z196_3 +.L_Z196_2: + pfd 1,512(%r3) + pfd 1,512(%r2) + clc 0(256,%r3),0(%r2) + je .L_Z196_17 + ipm %r2 + sllg %r2,%r2,34 + srag %r2,%r2,62 + br %r14 +.L_Z196_14: + clc 0(1,%r3),0(%r2) +END(__memcmp_z196) + +ENTRY(__memcmp_z10) + .machine "z10" + ltgr %r4,%r4 + je .L_Z10_4 + aghi %r4,-1 + srlg %r1,%r4,8 + cgijlh %r1,0,.L_Z10_12 +.L_Z10_3: + exrl %r4,.L_Z10_15 +.L_Z10_4: + ipm %r2 + sllg %r2,%r2,34 + srag %r2,%r2,62 + br %r14 +.L_Z10_12: + pfd 1,512(%r3) + pfd 1,512(%r2) + clc 0(256,%r3),0(%r2) + jne .L_Z10_4 + la %r3,256(%r3) + la %r2,256(%r2) + brctg %r1,.L_Z10_12 + j .L_Z10_3 +.L_Z10_15: + clc 0(1,%r3),0(%r2) +END(__memcmp_z10) + +#endif /* IS_IN (libc) */ + +#include "../memcmp.S" + +#if !IS_IN (libc) +.globl memcmp +.set memcmp,__memcmp_default +.weak bcmp +.set bcmp,__memcmp_default +#elif defined SHARED && IS_IN (libc) +.globl __GI_memcmp +.set __GI_memcmp,__memcmp_default +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcmp.c b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcmp.c new file mode 100644 index 0000000000..2d8d8f4d50 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcmp.c @@ -0,0 +1,27 @@ +/* Multiple versions of memcmp. + Copyright (C) 2015-2017 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 IS_IN (libc) +# define memcmp __redirect_memcmp +# include <string.h> +# undef memcmp +# include <ifunc-resolve.h> + +s390_libc_ifunc (__redirect_memcmp, __memcmp, memcmp) +weak_alias (memcmp, bcmp); +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S new file mode 100644 index 0000000000..a9ffa9cc98 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S @@ -0,0 +1,122 @@ +/* CPU specific memcpy implementations. 64 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = target operands address + %r3 = source operands address + %r4 = number of bytes to copy. */ + + .text + +#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 + srlg %r5,%r4,8 + ltgr %r5,%r5 + jne .L_Z196_5 +.L_Z196_3: + exrl %r4,.L_Z196_14 +.L_Z196_4: + br %r14 +.L_Z196_5: + cgfi %r5,262144 # Switch to mvcle for copies >64MB + jh __memcpy_mvcle +.L_Z196_2: + pfd 1,768(%r3) + pfd 2,768(%r1) + mvc 0(256,%r1),0(%r3) + aghi %r5,-1 + la %r1,256(%r1) + la %r3,256(%r3) + jne .L_Z196_2 + j .L_Z196_3 +.L_Z196_14: + 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 + srlg %r5,%r4,8 + cgijlh %r5,0,.L_Z10_13 +.L_Z10_3: + exrl %r4,.L_Z10_15 +.L_Z10_4: + br %r14 +.L_Z10_13: + cgfi %r5,65535 # Switch to mvcle for copies >16MB + jh __memcpy_mvcle +.L_Z10_12: + pfd 1,768(%r3) + pfd 2,768(%r1) + mvc 0(256,%r1),0(%r3) + la %r1,256(%r1) + la %r3,256(%r3) + brctg %r5,.L_Z10_12 + j .L_Z10_3 +.L_Z10_15: + 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/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcpy.c b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcpy.c new file mode 100644 index 0000000000..4b8e546fb0 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memcpy.c @@ -0,0 +1,27 @@ +/* Multiple versions of memcpy. + Copyright (C) 2015-2017 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/>. */ + +/* In the static lib memcpy is needed before the reloc is resolved. */ +#if defined SHARED && IS_IN (libc) +# define memcpy __redirect_memcpy +# include <string.h> +# undef memcpy +# include <ifunc-resolve.h> + +s390_libc_ifunc (__redirect_memcpy, __memcpy, memcpy) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/memset-s390x.S b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memset-s390x.S new file mode 100644 index 0000000000..ca0c4326b1 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memset-s390x.S @@ -0,0 +1,112 @@ +/* Set a block of memory to some byte value. 64 bit S/390 version. + Copyright (C) 2012-2017 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/>. */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/* INPUT PARAMETERS + %r2 = address of memory area + %r3 = byte to fill memory with + %r4 = number of bytes to fill. */ + + .text + +#if IS_IN (libc) + +ENTRY(__memset_z196) + .machine "z196" + ltgr %r4,%r4 + je .L_Z196_4 + stc %r3,0(%r2) + lgr %r1,%r2 + cghi %r4,1 + je .L_Z196_4 + aghi %r4,-2 + srlg %r5,%r4,8 + ltgr %r5,%r5 + jne .L_Z196_1 +.L_Z196_3: + exrl %r4,.L_Z196_17 +.L_Z196_4: + br %r14 +.L_Z196_1: + cgfi %r5,1048576 + jh __memset_mvcle # Switch to mvcle for >256MB +.L_Z196_2: + pfd 2,1024(%r1) + mvc 1(256,%r1),0(%r1) + aghi %r5,-1 + la %r1,256(%r1) + jne .L_Z196_2 + j .L_Z196_3 +.L_Z196_17: + mvc 1(1,%r1),0(%r1) +END(__memset_z196) + +ENTRY(__memset_z10) + .machine "z10" + cgije %r4,0,.L_Z10_4 + stc %r3,0(%r2) + lgr %r1,%r2 + cgije %r4,1,.L_Z10_4 + aghi %r4,-2 + srlg %r5,%r4,8 + cgijlh %r5,0,.L_Z10_15 +.L_Z10_3: + exrl %r4,.L_Z10_18 +.L_Z10_4: + br %r14 +.L_Z10_15: + cgfi %r5,163840 # Switch to mvcle for >40MB + jh __memset_mvcle +.L_Z10_14: + pfd 2,1024(%r1) + mvc 1(256,%r1),0(%r1) + la %r1,256(%r1) + brctg %r5,.L_Z10_14 + j .L_Z10_3 +.L_Z10_18: + mvc 1(1,%r1),0(%r1) +END(__memset_z10) + +ENTRY(__memset_mvcle) + aghi %r4,2 # take back the change done by the caller + lgr %r0,%r2 # save source address + lgr %r1,%r3 # move pad byte to R1 + lgr %r3,%r4 # move length to r3 + sgr %r4,%r4 # no source for MVCLE, only a pad byte + sgr %r5,%r5 +.L0: mvcle %r2,%r4,0(%r1) # thats it, MVCLE is your friend + jo .L0 + lgr %r2,%r0 # return value is source address +.L1: + br %r14 +END(__memset_mvcle) + +#endif /* IS_IN (libc) */ + +#include "../memset.S" + +#if !IS_IN (libc) +.globl memset +.set memset,__memset_default +#elif defined SHARED && IS_IN (libc) +.globl __GI_memset +.set __GI_memset,__memset_default +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/memset.c b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memset.c new file mode 100644 index 0000000000..421c0854a0 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/memset.c @@ -0,0 +1,26 @@ +/* Multiple versions of memset. + Copyright (C) 2015-2017 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 IS_IN (libc) +# define memset __redirect_memset +# include <string.h> +# undef memset +# include <ifunc-resolve.h> + +s390_libc_ifunc (__redirect_memset, __memset, memset) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/strcmp.c b/REORG.TODO/sysdeps/s390/s390-64/multiarch/strcmp.c new file mode 100644 index 0000000000..6a20a304cc --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/strcmp.c @@ -0,0 +1,21 @@ +/* Multiple versions of strcmp. + Copyright (C) 2015-2017 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/>. */ + +/* This wrapper-file is needed, because otherwise file + sysdeps/s390/s390-[32|64]/strcmp.S will be used. */ +#include <sysdeps/s390/multiarch/strcmp.c> diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/strcpy.c b/REORG.TODO/sysdeps/s390/s390-64/multiarch/strcpy.c new file mode 100644 index 0000000000..7f380a471d --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/strcpy.c @@ -0,0 +1,21 @@ +/* Multiple versions of strcpy. + Copyright (C) 2015-2017 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/>. */ + +/* This wrapper-file is needed, because otherwise file + sysdeps/s390/s390-[32|64]/strcpy.S will be used. */ +#include <sysdeps/s390/multiarch/strcpy.c> diff --git a/REORG.TODO/sysdeps/s390/s390-64/multiarch/strncpy.c b/REORG.TODO/sysdeps/s390/s390-64/multiarch/strncpy.c new file mode 100644 index 0000000000..15dacec974 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/multiarch/strncpy.c @@ -0,0 +1,21 @@ +/* Multiple versions of strncpy. + Copyright (C) 2015-2017 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/>. */ + +/* This wrapper-file is needed, because otherwise file + sysdeps/s390/s390-[32|64]/strncpy.S will be used. */ +#include <sysdeps/s390/multiarch/strncpy.c> diff --git a/REORG.TODO/sysdeps/s390/s390-64/s390x-mcount.S b/REORG.TODO/sysdeps/s390/s390-64/s390x-mcount.S new file mode 100644 index 0000000000..510834aa05 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/s390x-mcount.S @@ -0,0 +1,77 @@ +/* 64 bit S/390-specific implementation of profiling support. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com) + 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/>. */ + +#include <sysdep.h> + +/* How profiling works on 64 bit S/390: + On the start of each function _mcount is called with the address of a + data word in %r1 (initialized to 0, used for counting). The compiler + with the option -p generates code of the form: + + STM 6,15,24(15) + BRAS 13,.LTN0_0 + .LT0_0: + .LC13: .long .LP0 + .data + .align 4 + .LP0: .long 0 + .text + # function profiler + stg 14,4(15) + lg 1,.LC13-.LT0_0(13) + brasl 14,_mcount + lg 14,4(15) + + The _mcount implementation now has to call __mcount_internal with the + address of .LP0 as first parameter and the return address as second + parameter. &.LP0 was loaded to %r1 and the return address is in %r14. + _mcount may not modify any register. */ + + .globl C_SYMBOL_NAME(_mcount) + .type C_SYMBOL_NAME(_mcount), @function + cfi_startproc + .align ALIGNARG(4) +C_LABEL(_mcount) + /* Save the caller-clobbered registers. */ + aghi %r15,-224 + cfi_adjust_cfa_offset (224) + stmg %r14,%r5,160(%r15) + cfi_offset (r14, 0) + cfi_offset (r15, 8) + lg %r2,232(%r15) # callers address = first parameter + la %r2,0(%r2) # clear bit 0 + la %r3,0(%r14) # callees address = second parameter + +#ifdef PIC + brasl %r14,__mcount_internal@PLT +#else + brasl %r14,__mcount_internal +#endif + + /* Pop the saved registers. Please note that `mcount' has no + return value. */ + lmg %r14,%r5,160(%r15) + aghi %r15,224 + cfi_adjust_cfa_offset (-224) + br %r14 + cfi_endproc + ASM_SIZE_DIRECTIVE(C_SYMBOL_NAME(_mcount)) + +#undef mcount +weak_alias (_mcount, mcount) diff --git a/REORG.TODO/sysdeps/s390/s390-64/setjmp.S b/REORG.TODO/sysdeps/s390/s390-64/setjmp.S new file mode 100644 index 0000000000..ac9c878346 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/setjmp.S @@ -0,0 +1,118 @@ +/* setjmp for 64 bit S/390, ELF version. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#include <sysdep.h> +#define _ASM +#define _SETJMP_H +#include <bits/setjmp.h> +#include <shlib-compat.h> +#include <stap-probe.h> + +#if !IS_IN (rtld) && defined SHARED \ + && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20) +# define NEED_COMPAT_SYMBOLS 1 +/* We need a unique name in case of symbol versioning. */ +# define setjmp __v1setjmp +# define _setjmp __v1_setjmp +# define __sigsetjmp __v1__sigsetjmp +#else +# define NEED_COMPAT_SYMBOLS 0 +#endif + + /* We include the BSD entry points here as well. */ +ENTRY (setjmp) + lghi %r3,1 /* Second argument of one. */ + j .Linternal_sigsetjmp /* Branch relativ to __sigsetjmp. */ +END (setjmp) + + /* Binary compatibility entry point. */ +ENTRY(_setjmp) + slgr %r3,%r3 /* Second argument of zero. */ + j .Linternal_sigsetjmp /* Branch relativ to __sigsetjmp. */ +END (_setjmp) +#if NEED_COMPAT_SYMBOLS +strong_alias (_setjmp, __GI__setjmp) +#else +libc_hidden_def (_setjmp) +#endif + +ENTRY(__setjmp) + slgr %r3,%r3 /* Second argument of zero. */ + j .Linternal_sigsetjmp /* Branch relativ to __sigsetjmp. */ +END (__setjmp) + +ENTRY(__sigsetjmp) +.Linternal_sigsetjmp: + /* setjmp probe expects sig/setjmp first argument (8@%r2), second + argument (-8@%r3) and target address (8@%r14). */ + LIBC_PROBE (setjmp, 3, 8@%r2, -4@%r3, 8@%r14) +#ifdef PTR_MANGLE + stmg %r6,%r13,0(%r2) /* Store registers in jmp_buf. */ + lgr %r4,%r14 + lgr %r5,%r15 + PTR_MANGLE (%r4, %r1) + PTR_MANGLE2 (%r5, %r1) + stmg %r4,%r5,64(%r2) +#else + stmg %r6,%r15,0(%r2) /* Store registers in jmp_buf. */ +#endif + std %f8,80(%r2) + std %f9,88(%r2) + std %f10,96(%r2) + std %f11,104(%r2) + std %f12,112(%r2) + std %f13,120(%r2) + std %f14,128(%r2) + std %f15,136(%r2) +#if IS_IN (rtld) + /* In ld.so we never save the signal mask. */ + lghi %r2,0 + br %r14 +#elif defined PIC + jg __sigjmp_save@PLT /* Branch to PLT of __sigsetjmp. */ +#else + jg __sigjmp_save +#endif +END (__sigsetjmp) +#if NEED_COMPAT_SYMBOLS +strong_alias (__sigsetjmp, __GI___sigsetjmp) +#else +libc_hidden_def (__sigsetjmp) +#endif + +#if NEED_COMPAT_SYMBOLS +/* In glibc release 2.19 new versions of setjmp-functions were introduced, + but were reverted before 2.20. Thus both versions are the same function. */ + +# undef setjmp +# undef _setjmp +# undef __sigsetjmp + +strong_alias (__v1setjmp, __v2setjmp); +versioned_symbol (libc, __v1setjmp, setjmp, GLIBC_2_0); +compat_symbol (libc, __v2setjmp, setjmp, GLIBC_2_19); + +strong_alias (__v1_setjmp, __v2_setjmp); +versioned_symbol (libc, __v1_setjmp, _setjmp, GLIBC_2_0); +compat_symbol (libc, __v2_setjmp, _setjmp, GLIBC_2_19); + +strong_alias (__v1__sigsetjmp, __v2__sigsetjmp); +versioned_symbol (libc, __v1__sigsetjmp, __sigsetjmp, GLIBC_2_0); +compat_symbol (libc, __v2__sigsetjmp, __sigsetjmp, GLIBC_2_19); +#endif /* NEED_COMPAT_SYMBOLS */ diff --git a/REORG.TODO/sysdeps/s390/s390-64/stackguard-macros.h b/REORG.TODO/sysdeps/s390/s390-64/stackguard-macros.h new file mode 100644 index 0000000000..2c97d3824f --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/stackguard-macros.h @@ -0,0 +1,18 @@ +#include <stdint.h> + +#define STACK_CHK_GUARD \ + ({ uintptr_t x; __asm__ ("ear %0,%%a0; sllg %0,%0,32; ear %0,%%a1; lg %0,0x28(%0)" : "=a" (x)); x; }) + +/* On s390/s390x there is no unique pointer guard, instead we use the + same value as the stack guard. */ +#define POINTER_CHK_GUARD \ + ({ \ + uintptr_t x; \ + __asm__ ("ear %0,%%a0;" \ + "sllg %0,%0,32;" \ + "ear %0,%%a1;" \ + "lg %0,%1(%0)" \ + : "=a" (x) \ + : "i" (offsetof (tcbhead_t, stack_guard))); \ + x; \ + }) diff --git a/REORG.TODO/sysdeps/s390/s390-64/start.S b/REORG.TODO/sysdeps/s390/s390-64/start.S new file mode 100644 index 0000000000..d8e65450d8 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/start.S @@ -0,0 +1,100 @@ +/* Startup code compliant to the 64 bit S/390 ELF ABI. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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/>. */ + +/* + This is the canonical entry point, usually the first thing in the text + segment. Most registers' values are unspecified, except for: + + %r14 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %r15 The stack contains the arguments and environment: + 0(%r15) argc + 8(%r15) argv[0] + ... + (8*argc)(%r15) NULL + (8*(argc+1))(%r15) envp[0] + ... + NULL +*/ + + .text + .globl _start + .type _start,@function +_start: + /* Load argc and argv from stack. */ + la %r4,8(%r15) # get argv + lg %r3,0(%r15) # get argc + + /* Align the stack to a double word boundary. */ + lghi %r0,-16 + ngr %r15,%r0 + + /* Setup a stack frame and a parameter area. */ + aghi %r15,-176 # make room on stack + xc 0(8,%r15),0(%r15) # clear back-chain + + /* Set up arguments for __libc_start_main: + main, argc, argv, envp, _init, _fini, rtld_fini, stack_end + Note that envp will be determined later in __libc_start_main. + */ + stmg %r14,%r15,160(%r15) # store rtld_fini/stack_end to parameter area + la %r7,160(%r15) + larl %r6,__libc_csu_fini # load pointer to __libc_csu_fini + larl %r5,__libc_csu_init # load pointer to __libc_csu_init + + /* Ok, now branch to the libc main routine. */ +#ifdef PIC + larl %r2,main@GOTENT # load pointer to main + lg %r2,0(%r2) + brasl %r14,__libc_start_main@plt +#else + larl %r2,main # load pointer to main + brasl %r14,__libc_start_main +#endif + + /* Crash if __libc_start_main returns. */ + .word 0 + + /* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/REORG.TODO/sysdeps/s390/s390-64/strcmp.S b/REORG.TODO/sysdeps/s390/s390-64/strcmp.S new file mode 100644 index 0000000000..640493b4df --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/strcmp.S @@ -0,0 +1,41 @@ +/* strcmp - compare two string. 64 bit S/390 version. + This file is part of the GNU C Library. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + 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/>. */ + +/* INPUT PARAMETERS + %r2 = address of string 1 + %r3 = address of string 2. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(strcmp) + slr %r0,%r0 +0: clst %r2,%r3 + jo 0b + jp 1f + jm 2f + slgr %r2,%r2 + br %r14 +1: lghi %r2,1 + br %r14 +2: lghi %r2,-1 + br %r14 +END(strcmp) +libc_hidden_builtin_def (strcmp) diff --git a/REORG.TODO/sysdeps/s390/s390-64/strcpy.S b/REORG.TODO/sysdeps/s390/s390-64/strcpy.S new file mode 100644 index 0000000000..fee1d3ede6 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/strcpy.S @@ -0,0 +1,35 @@ +/* strcpy - copy a string from source to destination. 64 bit S/390 version. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +/* INPUT PARAMETERS + %r2 = address of destination + %r3 = address of source. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY(strcpy) + slgr %r0,%r0 + lgr %r1,%r2 +0: mvst %r1,%r3 + jo 0b + br %r14 +END(strcpy) +libc_hidden_builtin_def (strcpy) diff --git a/REORG.TODO/sysdeps/s390/s390-64/strncpy.S b/REORG.TODO/sysdeps/s390/s390-64/strncpy.S new file mode 100644 index 0000000000..80aee312e4 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/strncpy.S @@ -0,0 +1,90 @@ +/* strncpy - copy at most n characters from a string from source to + destination. 64 bit S/390 version + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +/* INPUT PARAMETERS + %r2 = address of destination (dst) + %r3 = address of source (src) + %r4 = max of bytes to copy. */ + +#include "sysdep.h" +#include "asm-syntax.h" + +ENTRY(strncpy) + .text + stg %r2,48(%r15) # save dst pointer + slgr %r2,%r3 # %r3 points to src, %r2+%r3 to dst + lghi %r1,7 + ngr %r1,%r4 # last 3 bits of # bytes + srlg %r4,%r4,3 + ltgr %r4,%r4 # less than 8 bytes to copy ? + jz .L1 + bras %r5,.L0 # enter loop & load address of a 0 + .long 0 +.L0: icmh %r0,8,0(%r3) # first byte + jz .L3 + icmh %r0,4,1(%r3) # second byte + jz .L4 + icmh %r0,2,2(%r3) # third byte + jz .L5 + icmh %r0,1,3(%r3) # fourth byte + jz .L6 + icm %r0,8,4(%r3) # fifth byte + jz .L7 + icm %r0,4,5(%r3) # sixth byte + jz .L8 + icm %r0,2,6(%r3) # seventh byte + jz .L9 + icm %r0,1,7(%r3) # eigth byte + jz .L10 + stg %r0,0(%r2,%r3) # store all eight to dest. + la %r3,8(%r3) + brct %r4,.L0 +.L1: ltgr %r1,%r1 + jz .Lexit +.L2: icm %r0,1,0(%r3) + stc %r0,0(%r2,%r3) + la %r3,1(%r3) + jz .L11 + brct %r1,.L2 + j .Lexit +.L3: icmh %r0,4,0(%r5) +.L4: icmh %r0,2,0(%r5) +.L5: icmh %r0,1,0(%r5) +.L6: icm %r0,8,0(%r5) +.L7: icm %r0,4,0(%r5) +.L8: icm %r0,2,0(%r5) +.L9: icm %r0,1,0(%r5) +.L10: stg %r0,0(%r2,%r3) + la %r3,8(%r3) + aghi %r4,-1 + j .L12 +.L11: aghi %r1,-1 +.L12: sllg %r4,%r4,3 + algr %r4,%r1 + algr %r2,%r3 # start of dst area to be zeroed + lgr %r3,%r4 + slgr %r4,%r4 + slgr %r5,%r5 +.L13: mvcle %r2,%r4,0 # pad dst with zeroes + jo .L13 +.Lexit: lg %r2,48(%r15) # return dst pointer + br %r14 +END(strncpy) +libc_hidden_builtin_def (strncpy) diff --git a/REORG.TODO/sysdeps/s390/s390-64/sub_n.S b/REORG.TODO/sysdeps/s390/s390-64/sub_n.S new file mode 100644 index 0000000000..dc6572ca36 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/sub_n.S @@ -0,0 +1,60 @@ +/* __mpn_sub_n -- Add two limb vectors of the same length > 0 and store + sum in a third limb vector. 64 bit S/390 version. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU MP 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; see the file COPYING.LIB. If not, + see <http://www.gnu.org/licenses/>. */ + +/* INPUT PARAMETERS + %r2 = res_ptr + %r3 = s1_ptr + %r4 = s2_ptr + %r5 = size. */ + +#include "sysdep.h" +#include "asm-syntax.h" + +ENTRY(__mpn_sub_n) + stg %r6,48(%r15) # save register 6 + cfi_offset (%r6,-112) + sgr %r1,%r1 + lghi %r0,1 # cannot use ahi to add carry, use slr +.L0: lg %r6,0(%r1,%r3) # .L0 -> no carry from last sub + slg %r6,0(%r1,%r4) + stg %r6,0(%r1,%r2) + la %r1,8(%r1) + brc 4,.L3 +.L1: brct %r5,.L0 + slgr %r2,%r2 # no last carry to return + j .Lexit +.L2: lg %r6,0(%r1,%r3) # .L2 -> carry from last sub + slg %r6,0(%r1,%r4) + brc 4,.L4 + slgr %r6,%r0 # no carry yet, add carry from last sub + stg %r6,0(%r1,%r2) + la %r1,8(%r1) + brc 11,.L1 # new carry ? +.L3: brct %r5,.L2 + lgr %r2,%r0 # return last carry + j .Lexit +.L4: slgr %r6,%r0 # already a carry, add carry from last sub + stg %r6,0(%r1,%r2) + la %r1,8(%r1) + brct %r5,.L2 + lgr %r2,%r0 # return last carry +.Lexit: lg %r6,48(%r15) # restore register 6 + br %r14 +END(__mpn_sub_n) diff --git a/REORG.TODO/sysdeps/s390/s390-64/sysdep.h b/REORG.TODO/sysdeps/s390/s390-64/sysdep.h new file mode 100644 index 0000000000..a4dfc67178 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/sysdep.h @@ -0,0 +1,94 @@ +/* Assembler macros for 64 bit S/390. + Copyright (C) 2001-2017 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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/>. */ + +#include <sysdeps/generic/sysdep.h> + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1<<log2 +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name; + + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + .globl C_SYMBOL_NAME(name); \ + .type C_SYMBOL_NAME(name),@function; \ + .align ALIGNARG(2); \ + C_LABEL(name) \ + cfi_startproc; \ + CALL_MCOUNT + +#undef END +#define END(name) \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) \ + +/* If compiled for profiling, call `mcount' at the start of each function. */ +#ifdef PROF +#ifdef PIC +#define CALL_MCOUNT \ + lgr 0,14 ; larl 1,0f ; brasl 14,_mcount@PLT ; lgr 14,0 ; \ + .data ; .align 4 ; 0: .long 0 ; .text ; +#else +#define CALL_MCOUNT \ + lgr 0,14 ; larl 1,0f ; brasl 14,_mcount ; lgr 14,0 ; \ + .data ; .align 4 ; 0: .long 0 ; .text ; +#endif +#else +#define CALL_MCOUNT /* Do nothing. */ +#endif + +/* Since C identifiers are not normally prefixed with an underscore + on this system, the asm identifier `syscall_error' intrudes on the + C name space. Make sure we use an innocuous name. */ +#define syscall_error __syscall_error +#define mcount _mcount + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ +lose: SYSCALL_PIC_SETUP \ + jg JUMPTARGET(syscall_error); \ + .globl syscall_error; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + jm lose + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + END (name) + +#undef JUMPTARGET +#ifdef PIC +#define JUMPTARGET(name) name##@PLT +#define SYSCALL_PIC_SETUP \ + larl %r12,_GLOBAL_OFFSET_TABLE_ +#else +#define JUMPTARGET(name) name +#define SYSCALL_PIC_SETUP /* Nothing. */ +#endif + +/* Local label name for asm code. */ +#ifndef L +#define L(name) .L##name +#endif + +#endif /* __ASSEMBLER__ */ diff --git a/REORG.TODO/sysdeps/s390/s390-64/tls-macros.h b/REORG.TODO/sysdeps/s390/s390-64/tls-macros.h new file mode 100644 index 0000000000..d70ea6ce0c --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/tls-macros.h @@ -0,0 +1,88 @@ +#define TLS_LE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@ntpoff\n" \ + "1:\tlg %0,0(%0)" \ + : "=a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) + +#ifdef PIC +# define TLS_IE(x) \ + ({ unsigned long __offset, __got; \ + __asm__ ("bras %0,0f\n\t" \ + ".quad " #x "@gotntpoff\n" \ + "0:\tlarl %1,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %0,0(%0)\n\t" \ + "lg %0,0(%0,%1):tls_load:" #x "\n" \ + : "=&a" (__offset), "=&a" (__got) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#else +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@indntpoff\n" \ + "1:\t lg %0,0(%0)\n\t" \ + "lg %0,0(%0):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#endif + +#ifdef PIC +# define TLS_LD(x) \ + ({ unsigned long __offset, __save12; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsldm\n\t" \ + ".quad " #x "@dtpoff\n" \ + "1:\tlgr %1,%%r12\n\t" \ + "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \ + "lg %0,8(%0)\n\t" \ + "algr %0,%%r2\n\t" \ + "lgr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#else +# define TLS_LD(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsldm\n\t" \ + ".quad " #x "@dtpoff\n" \ + "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \ + "lg %0,8(%0)\n\t" \ + "algr %0,%%r2" \ + : "=&a" (__offset) \ + : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#endif + +#ifdef PIC +# define TLS_GD(x) \ + ({ unsigned long __offset, __save12; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsgd\n" \ + "1:\tlgr %1,%%r12\n\t" \ + "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \ + "lgr %0,%%r2\n\t" \ + "lgr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#else +# define TLS_GD(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsgd\n" \ + "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \ + "lgr %0,%%r2" \ + : "=&a" (__offset) \ + : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +#endif diff --git a/REORG.TODO/sysdeps/s390/s390-64/tst-audit.h b/REORG.TODO/sysdeps/s390/s390-64/tst-audit.h new file mode 100644 index 0000000000..67a93f51f1 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/s390-64/tst-audit.h @@ -0,0 +1,25 @@ +/* Definitions for testing PLT entry/exit auditing. S/390 64-bit version. + + Copyright (C) 2012-2017 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/>. */ + +#define pltenter la_s390_64_gnu_pltenter +#define pltexit la_s390_64_gnu_pltexit +#define La_regs La_s390_64_regs +#define La_retval La_s390_64_retval +#define int_retval lrv_r2 diff --git a/REORG.TODO/sysdeps/s390/sotruss-lib.c b/REORG.TODO/sysdeps/s390/sotruss-lib.c new file mode 100644 index 0000000000..2b9f1f31e6 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/sotruss-lib.c @@ -0,0 +1,62 @@ +/* Override generic sotruss-lib.c to define actual functions for s390. + Copyright (C) 2012-2017 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/>. */ + +#define HAVE_ARCH_PLTENTER +#define HAVE_ARCH_PLTEXIT + +#include <elf/sotruss-lib.c> + +#if __ELF_NATIVE_CLASS == 32 +# define la_s390_gnu_pltenter la_s390_32_gnu_pltenter +# define la_s390_gnu_pltexit la_s390_32_gnu_pltexit +# define La_s390_regs La_s390_32_regs +# define La_s390_retval La_s390_32_retval +#else +# define la_s390_gnu_pltenter la_s390_64_gnu_pltenter +# define la_s390_gnu_pltexit la_s390_64_gnu_pltexit +# define La_s390_regs La_s390_64_regs +# define La_s390_retval La_s390_64_retval +#endif + +ElfW(Addr) +la_s390_gnu_pltenter (ElfW(Sym) *sym, + unsigned int ndx __attribute__ ((unused)), + uintptr_t *refcook, uintptr_t *defcook, + La_s390_regs *regs, unsigned int *flags, + const char *symname, long int *framesizep) +{ + print_enter (refcook, defcook, symname, + regs->lr_r2, regs->lr_r3, regs->lr_r4, *flags); + + /* No need to copy anything, we will not need the parameters in any case. */ + *framesizep = 0; + + return sym->st_value; +} + +unsigned int +la_s390_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, + uintptr_t *defcook, + const struct La_s390_regs *inregs, + struct La_s390_retval *outregs, const char *symname) +{ + print_exit (refcook, defcook, symname, outregs->lrv_r2); + + return 0; +} diff --git a/REORG.TODO/sysdeps/s390/stackinfo.h b/REORG.TODO/sysdeps/s390/stackinfo.h new file mode 100644 index 0000000000..39da94efff --- /dev/null +++ b/REORG.TODO/sysdeps/s390/stackinfo.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2000-2017 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/>. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +#include <elf.h> + +/* On s390 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is + * present, but it is presumed absent. */ +#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X) + +#endif /* stackinfo.h */ diff --git a/REORG.TODO/sysdeps/s390/string_private.h b/REORG.TODO/sysdeps/s390/string_private.h new file mode 100644 index 0000000000..118db043f4 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/string_private.h @@ -0,0 +1,20 @@ +/* Define _STRING_ARCH_unaligned. S/390 version. + Copyright (C) 2016-2017 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/>. */ + +/* The s390 processors can access unaligned multi-byte variables. */ +#define _STRING_ARCH_unaligned 1 diff --git a/REORG.TODO/sysdeps/s390/utf16-utf32-z9.c b/REORG.TODO/sysdeps/s390/utf16-utf32-z9.c new file mode 100644 index 0000000000..7a174ea0e5 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/utf16-utf32-z9.c @@ -0,0 +1,603 @@ +/* Conversion between UTF-16 and UTF-32 BE/internal. + + This module uses the Z9-109 variants of the Convert Unicode + instructions. + Copyright (C) 1997-2017 Free Software Foundation, Inc. + + Author: Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + Based on the work by Ulrich Drepper <drepper@cygnus.com>, 1997. + + Thanks to Daniel Appich who covered the relevant performance work + in his diploma thesis. + + This 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. + + This 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/>. */ + +#include <dlfcn.h> +#include <stdint.h> +#include <unistd.h> +#include <gconv.h> +#include <string.h> + +/* Select which versions should be defined depending on support + for multiarch, vector and used minimum architecture level. */ +#define HAVE_FROM_C 1 +#define FROM_LOOP_DEFAULT FROM_LOOP_C +#define HAVE_TO_C 1 +#define TO_LOOP_DEFAULT TO_LOOP_C + +#if defined HAVE_S390_VX_ASM_SUPPORT && defined USE_MULTIARCH +# define HAVE_FROM_VX 1 +# define HAVE_TO_VX 1 +#else +# define HAVE_FROM_VX 0 +# define HAVE_TO_VX 0 +#endif + +#if defined HAVE_S390_VX_GCC_SUPPORT +# define ASM_CLOBBER_VR(NR) , NR +#else +# define ASM_CLOBBER_VR(NR) +#endif + +#if defined __s390x__ +# define CONVERT_32BIT_SIZE_T(REG) +#else +# define CONVERT_32BIT_SIZE_T(REG) "llgfr %" #REG ",%" #REG "\n\t" +#endif + +/* UTF-32 big endian byte order mark. */ +#define BOM_UTF32 0x0000feffu + +/* UTF-16 big endian byte order mark. */ +#define BOM_UTF16 0xfeff + +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 2 +#define MAX_NEEDED_FROM 4 +#define MIN_NEEDED_TO 4 +#define FROM_LOOP FROM_LOOP_DEFAULT +#define TO_LOOP TO_LOOP_DEFAULT +#define FROM_DIRECTION (dir == from_utf16) +#define ONE_DIRECTION 0 + +/* Direction of the transformation. */ +enum direction +{ + illegal_dir, + to_utf16, + from_utf16 +}; + +struct utf16_data +{ + enum direction dir; + int emit_bom; +}; + + +extern int gconv_init (struct __gconv_step *step); +int +gconv_init (struct __gconv_step *step) +{ + /* Determine which direction. */ + struct utf16_data *new_data; + enum direction dir = illegal_dir; + int emit_bom; + int result; + + emit_bom = (__strcasecmp (step->__to_name, "UTF-32//") == 0 + || __strcasecmp (step->__to_name, "UTF-16//") == 0); + + if (__strcasecmp (step->__from_name, "UTF-16BE//") == 0 + && (__strcasecmp (step->__to_name, "UTF-32//") == 0 + || __strcasecmp (step->__to_name, "UTF-32BE//") == 0 + || __strcasecmp (step->__to_name, "INTERNAL") == 0)) + { + dir = from_utf16; + } + else if ((__strcasecmp (step->__to_name, "UTF-16//") == 0 + || __strcasecmp (step->__to_name, "UTF-16BE//") == 0) + && (__strcasecmp (step->__from_name, "UTF-32BE//") == 0 + || __strcasecmp (step->__from_name, "INTERNAL") == 0)) + { + dir = to_utf16; + } + + result = __GCONV_NOCONV; + if (dir != illegal_dir) + { + new_data = (struct utf16_data *) malloc (sizeof (struct utf16_data)); + + result = __GCONV_NOMEM; + if (new_data != NULL) + { + new_data->dir = dir; + new_data->emit_bom = emit_bom; + step->__data = new_data; + + if (dir == from_utf16) + { + step->__min_needed_from = MIN_NEEDED_FROM; + step->__max_needed_from = MIN_NEEDED_FROM; + step->__min_needed_to = MIN_NEEDED_TO; + step->__max_needed_to = MIN_NEEDED_TO; + } + else + { + step->__min_needed_from = MIN_NEEDED_TO; + step->__max_needed_from = MIN_NEEDED_TO; + step->__min_needed_to = MIN_NEEDED_FROM; + step->__max_needed_to = MIN_NEEDED_FROM; + } + + step->__stateful = 0; + + result = __GCONV_OK; + } + } + + return result; +} + + +extern void gconv_end (struct __gconv_step *data); +void +gconv_end (struct __gconv_step *data) +{ + free (data->__data); +} + +#define PREPARE_LOOP \ + enum direction dir = ((struct utf16_data *) step->__data)->dir; \ + int emit_bom = ((struct utf16_data *) step->__data)->emit_bom; \ + \ + if (emit_bom && !data->__internal_use \ + && data->__invocation_counter == 0) \ + { \ + if (dir == to_utf16) \ + { \ + /* Emit the UTF-16 Byte Order Mark. */ \ + if (__glibc_unlikely (outbuf + 2 > outend)) \ + return __GCONV_FULL_OUTPUT; \ + \ + put16u (outbuf, BOM_UTF16); \ + outbuf += 2; \ + } \ + else \ + { \ + /* Emit the UTF-32 Byte Order Mark. */ \ + if (__glibc_unlikely (outbuf + 4 > outend)) \ + return __GCONV_FULL_OUTPUT; \ + \ + put32u (outbuf, BOM_UTF32); \ + outbuf += 4; \ + } \ + } + +/* Conversion function from UTF-16 to UTF-32 internal/BE. */ + +#if HAVE_FROM_C == 1 +/* The software routine is copied from utf-16.c (minus bytes + swapping). */ +# define BODY_FROM_C \ + { \ + uint16_t u1 = get16 (inptr); \ + \ + if (__builtin_expect (u1 < 0xd800, 1) || u1 > 0xdfff) \ + { \ + /* No surrogate. */ \ + put32 (outptr, u1); \ + inptr += 2; \ + } \ + else \ + { \ + /* An isolated low-surrogate was found. This has to be \ + considered ill-formed. */ \ + if (__glibc_unlikely (u1 >= 0xdc00)) \ + { \ + STANDARD_FROM_LOOP_ERR_HANDLER (2); \ + } \ + /* It's a surrogate character. At least the first word says \ + it is. */ \ + if (__glibc_unlikely (inptr + 4 > inend)) \ + { \ + /* We don't have enough input for another complete input \ + character. */ \ + result = __GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + uint16_t u2 = get16 (inptr); \ + if (__builtin_expect (u2 < 0xdc00, 0) \ + || __builtin_expect (u2 > 0xdfff, 0)) \ + { \ + /* This is no valid second word for a surrogate. */ \ + inptr -= 2; \ + STANDARD_FROM_LOOP_ERR_HANDLER (2); \ + } \ + \ + put32 (outptr, ((u1 - 0xd7c0) << 10) + (u2 - 0xdc00)); \ + inptr += 2; \ + } \ + outptr += 4; \ + } + + +/* Generate loop-function with software routing. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define FROM_LOOP_C __from_utf16_loop_c +# define LOOPFCT FROM_LOOP_C +# define LOOP_NEED_FLAGS +# define BODY BODY_FROM_C +# include <iconv/loop.c> +#else +# define FROM_LOOP_C NULL +#endif /* HAVE_FROM_C != 1 */ + +#if HAVE_FROM_VX == 1 +# define BODY_FROM_VX \ + { \ + size_t inlen = inend - inptr; \ + size_t outlen = outend - outptr; \ + unsigned long tmp, tmp2, tmp3; \ + asm volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + /* Setup to check for surrogates. */ \ + " larl %[R_TMP],9f\n\t" \ + " vlm %%v30,%%v31,0(%[R_TMP])\n\t" \ + CONVERT_32BIT_SIZE_T ([R_INLEN]) \ + CONVERT_32BIT_SIZE_T ([R_OUTLEN]) \ + /* Loop which handles UTF-16 chars <0xd800, >0xdfff. */ \ + "0: clgijl %[R_INLEN],16,2f\n\t" \ + " clgijl %[R_OUTLEN],32,2f\n\t" \ + "1: vl %%v16,0(%[R_IN])\n\t" \ + /* Check for surrogate chars. */ \ + " vstrchs %%v19,%%v16,%%v30,%%v31\n\t" \ + " jno 10f\n\t" \ + /* Enlarge to UTF-32. */ \ + " vuplhh %%v17,%%v16\n\t" \ + " la %[R_IN],16(%[R_IN])\n\t" \ + " vupllh %%v18,%%v16\n\t" \ + " aghi %[R_INLEN],-16\n\t" \ + /* Store 32 bytes to buf_out. */ \ + " vstm %%v17,%%v18,0(%[R_OUT])\n\t" \ + " aghi %[R_OUTLEN],-32\n\t" \ + " la %[R_OUT],32(%[R_OUT])\n\t" \ + " clgijl %[R_INLEN],16,2f\n\t" \ + " clgijl %[R_OUTLEN],32,2f\n\t" \ + " j 1b\n\t" \ + /* Setup to check for ch >= 0xd800 && ch <= 0xdfff. (v30, v31) */ \ + "9: .short 0xd800,0xdfff,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \ + " .short 0xa000,0xc000,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \ + /* At least one uint16_t is in range of surrogates. \ + Store the preceding chars. */ \ + "10: vlgvb %[R_TMP],%%v19,7\n\t" \ + " vuplhh %%v17,%%v16\n\t" \ + " sllg %[R_TMP3],%[R_TMP],1\n\t" /* Number of out bytes. */ \ + " ahik %[R_TMP2],%[R_TMP3],-1\n\t" /* Highest index to store. */ \ + " jl 12f\n\t" \ + " vstl %%v17,%[R_TMP2],0(%[R_OUT])\n\t" \ + " vupllh %%v18,%%v16\n\t" \ + " ahi %[R_TMP2],-16\n\t" \ + " jl 11f\n\t" \ + " vstl %%v18,%[R_TMP2],16(%[R_OUT])\n\t" \ + "11: \n\t" /* Update pointers. */ \ + " la %[R_IN],0(%[R_TMP],%[R_IN])\n\t" \ + " slgr %[R_INLEN],%[R_TMP]\n\t" \ + " la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t" \ + " slgr %[R_OUTLEN],%[R_TMP3]\n\t" \ + /* Calculate remaining uint16_t values in loaded vrs. */ \ + "12: lghi %[R_TMP2],16\n\t" \ + " slgr %[R_TMP2],%[R_TMP]\n\t" \ + " srl %[R_TMP2],1\n\t" \ + " llh %[R_TMP],0(%[R_IN])\n\t" \ + " aghi %[R_OUTLEN],-4\n\t" \ + " j 16f\n\t" \ + /* Handle remaining bytes. */ \ + "2: \n\t" \ + /* Zero, one or more bytes available? */ \ + " clgfi %[R_INLEN],1\n\t" \ + " je 97f\n\t" /* Only one byte available. */ \ + " jl 99f\n\t" /* End if no bytes available. */ \ + /* Calculate remaining uint16_t values in inptr. */ \ + " srlg %[R_TMP2],%[R_INLEN],1\n\t" \ + /* Handle remaining uint16_t values. */ \ + "13: llh %[R_TMP],0(%[R_IN])\n\t" \ + " slgfi %[R_OUTLEN],4\n\t" \ + " jl 96f \n\t" \ + " clfi %[R_TMP],0xd800\n\t" \ + " jhe 15f\n\t" \ + "14: st %[R_TMP],0(%[R_OUT])\n\t" \ + " la %[R_IN],2(%[R_IN])\n\t" \ + " aghi %[R_INLEN],-2\n\t" \ + " la %[R_OUT],4(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],13b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Handle UTF-16 surrogate pair. */ \ + "15: clfi %[R_TMP],0xdfff\n\t" \ + " jh 14b\n\t" /* Jump away if ch > 0xdfff. */ \ + "16: clfi %[R_TMP],0xdc00\n\t" \ + " jhe 98f\n\t" /* Jump away in case of low-surrogate. */ \ + " slgfi %[R_INLEN],4\n\t" \ + " jl 97f\n\t" /* Big enough input? */ \ + " llh %[R_TMP3],2(%[R_IN])\n\t" /* Load low surrogate. */ \ + " slfi %[R_TMP],0xd7c0\n\t" \ + " sll %[R_TMP],10\n\t" \ + " risbgn %[R_TMP],%[R_TMP3],54,63,0\n\t" /* Insert klmnopqrst. */ \ + " nilf %[R_TMP3],0xfc00\n\t" \ + " clfi %[R_TMP3],0xdc00\n\t" /* Check if it starts with 0xdc00. */ \ + " jne 98f\n\t" \ + " st %[R_TMP],0(%[R_OUT])\n\t" \ + " la %[R_IN],4(%[R_IN])\n\t" \ + " la %[R_OUT],4(%[R_OUT])\n\t" \ + " aghi %[R_TMP2],-2\n\t" \ + " jh 13b\n\t" /* Handle remaining uint16_t values. */ \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + "96: \n\t" /* Return full output. */ \ + " lghi %[R_RES],%[RES_OUT_FULL]\n\t" \ + " j 99f\n\t" \ + "97: \n\t" /* Return incomplete input. */ \ + " lghi %[R_RES],%[RES_IN_FULL]\n\t" \ + " j 99f\n\t" \ + "98:\n\t" /* Return Illegal character. */ \ + " lghi %[R_RES],%[RES_IN_ILL]\n\t" \ + "99:\n\t" \ + ".machine pop" \ + : /* outputs */ [R_IN] "+a" (inptr) \ + , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (outptr) \ + , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp) \ + , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3) \ + , [R_RES] "+d" (result) \ + : /* inputs */ \ + [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT) \ + , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT) \ + , [RES_IN_FULL] "i" (__GCONV_INCOMPLETE_INPUT) \ + : /* clobber list */ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v30") ASM_CLOBBER_VR ("v31") \ + ); \ + if (__glibc_likely (inptr == inend) \ + || result != __GCONV_ILLEGAL_INPUT) \ + break; \ + \ + STANDARD_FROM_LOOP_ERR_HANDLER (2); \ + } + + +/* Generate loop-function with hardware vector instructions. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define FROM_LOOP_VX __from_utf16_loop_vx +# define LOOPFCT FROM_LOOP_VX +# define LOOP_NEED_FLAGS +# define BODY BODY_FROM_VX +# include <iconv/loop.c> +#else +# define FROM_LOOP_VX NULL +#endif /* HAVE_FROM_VX != 1 */ + + +/* Conversion from UTF-32 internal/BE to UTF-16. */ + +#if HAVE_TO_C == 1 +/* The software routine is copied from utf-16.c (minus bytes + swapping). */ +# define BODY_TO_C \ + { \ + uint32_t c = get32 (inptr); \ + \ + if (__builtin_expect (c <= 0xd7ff, 1) \ + || (c > 0xdfff && c <= 0xffff)) \ + { \ + /* Two UTF-16 chars. */ \ + put16 (outptr, c); \ + } \ + else if (__builtin_expect (c >= 0x10000, 1) \ + && __builtin_expect (c <= 0x10ffff, 1)) \ + { \ + /* Four UTF-16 chars. */ \ + uint16_t zabcd = ((c & 0x1f0000) >> 16) - 1; \ + uint16_t out; \ + \ + /* Generate a surrogate character. */ \ + if (__glibc_unlikely (outptr + 4 > outend)) \ + { \ + /* Overflow in the output buffer. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + out = 0xd800; \ + out |= (zabcd & 0xff) << 6; \ + out |= (c >> 10) & 0x3f; \ + put16 (outptr, out); \ + outptr += 2; \ + \ + out = 0xdc00; \ + out |= c & 0x3ff; \ + put16 (outptr, out); \ + } \ + else \ + { \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } \ + outptr += 2; \ + inptr += 4; \ + } + +/* Generate loop-function with software routing. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_TO +# define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +# define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +# define TO_LOOP_C __to_utf16_loop_c +# define LOOPFCT TO_LOOP_C +# define LOOP_NEED_FLAGS +# define BODY BODY_TO_C +# include <iconv/loop.c> +#else +# define TO_LOOP_C NULL +#endif /* HAVE_TO_C != 1 */ + +#if HAVE_TO_VX == 1 +# define BODY_TO_VX \ + { \ + size_t inlen = inend - inptr; \ + size_t outlen = outend - outptr; \ + unsigned long tmp, tmp2, tmp3; \ + asm volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + /* Setup to check for surrogates. */ \ + " larl %[R_TMP],9f\n\t" \ + " vlm %%v30,%%v31,0(%[R_TMP])\n\t" \ + CONVERT_32BIT_SIZE_T ([R_INLEN]) \ + CONVERT_32BIT_SIZE_T ([R_OUTLEN]) \ + /* Loop which handles UTF-16 chars \ + ch < 0xd800 || (ch > 0xdfff && ch < 0x10000). */ \ + "0: clgijl %[R_INLEN],32,2f\n\t" \ + " clgijl %[R_OUTLEN],16,2f\n\t" \ + "1: vlm %%v16,%%v17,0(%[R_IN])\n\t" \ + " lghi %[R_TMP2],0\n\t" \ + /* Shorten to UTF-16. */ \ + " vpkf %%v18,%%v16,%%v17\n\t" \ + /* Check for surrogate chars. */ \ + " vstrcfs %%v19,%%v16,%%v30,%%v31\n\t" \ + " jno 10f\n\t" \ + " vstrcfs %%v19,%%v17,%%v30,%%v31\n\t" \ + " jno 11f\n\t" \ + /* Store 16 bytes to buf_out. */ \ + " vst %%v18,0(%[R_OUT])\n\t" \ + " la %[R_IN],32(%[R_IN])\n\t" \ + " aghi %[R_INLEN],-32\n\t" \ + " aghi %[R_OUTLEN],-16\n\t" \ + " la %[R_OUT],16(%[R_OUT])\n\t" \ + " clgijl %[R_INLEN],32,2f\n\t" \ + " clgijl %[R_OUTLEN],16,2f\n\t" \ + " j 1b\n\t" \ + /* Calculate remaining uint32_t values in inptr. */ \ + "2: \n\t" \ + " clgije %[R_INLEN],0,99f\n\t" \ + " clgijl %[R_INLEN],4,92f\n\t" \ + " srlg %[R_TMP2],%[R_INLEN],2\n\t" \ + " j 20f\n\t" \ + /* Setup to check for ch >= 0xd800 && ch <= 0xdfff \ + and check for ch >= 0x10000. (v30, v31) */ \ + "9: .long 0xd800,0xdfff,0x10000,0x10000\n\t" \ + " .long 0xa0000000,0xc0000000, 0xa0000000,0xa0000000\n\t" \ + /* At least on UTF32 char is in range of surrogates. \ + Store the preceding characters. */ \ + "11: ahi %[R_TMP2],16\n\t" \ + "10: vlgvb %[R_TMP],%%v19,7\n\t" \ + " agr %[R_TMP],%[R_TMP2]\n\t" \ + " srlg %[R_TMP3],%[R_TMP],1\n\t" /* Number of out bytes. */ \ + " ahik %[R_TMP2],%[R_TMP3],-1\n\t" /* Highest index to store. */ \ + " jl 12f\n\t" \ + " vstl %%v18,%[R_TMP2],0(%[R_OUT])\n\t" \ + /* Update pointers. */ \ + " la %[R_IN],0(%[R_TMP],%[R_IN])\n\t" \ + " slgr %[R_INLEN],%[R_TMP]\n\t" \ + " la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t" \ + " slgr %[R_OUTLEN],%[R_TMP3]\n\t" \ + /* Calculate remaining uint32_t values in vrs. */ \ + "12: lghi %[R_TMP2],8\n\t" \ + " srlg %[R_TMP3],%[R_TMP3],1\n\t" \ + " slgr %[R_TMP2],%[R_TMP3]\n\t" \ + /* Handle remaining UTF-32 characters. */ \ + "20: l %[R_TMP],0(%[R_IN])\n\t" \ + " aghi %[R_INLEN],-4\n\t" \ + /* Test if ch is 2byte UTF-16 char. */ \ + " clfi %[R_TMP],0xffff\n\t" \ + " jh 21f\n\t" \ + /* Handle 2 byte UTF16 char. */ \ + " lgr %[R_TMP3],%[R_TMP]\n\t" \ + " nilf %[R_TMP],0xf800\n\t" \ + " clfi %[R_TMP],0xd800\n\t" \ + " je 91f\n\t" /* Do not accept UTF-16 surrogates. */ \ + " slgfi %[R_OUTLEN],2\n\t" \ + " jl 90f \n\t" \ + " sth %[R_TMP3],0(%[R_OUT])\n\t" \ + " la %[R_IN],4(%[R_IN])\n\t" \ + " la %[R_OUT],2(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Test if ch is 4byte UTF-16 char. */ \ + "21: clfi %[R_TMP],0x10ffff\n\t" \ + " jh 91f\n\t" /* ch > 0x10ffff is not allowed! */ \ + /* Handle 4 byte UTF16 char. */ \ + " slgfi %[R_OUTLEN],4\n\t" \ + " jl 90f \n\t" \ + " slfi %[R_TMP],0x10000\n\t" /* zabcd = uvwxy - 1. */ \ + " llilf %[R_TMP3],0xd800dc00\n\t" \ + " la %[R_IN],4(%[R_IN])\n\t" \ + " risbgn %[R_TMP3],%[R_TMP],38,47,6\n\t" /* High surrogate. */ \ + " risbgn %[R_TMP3],%[R_TMP],54,63,0\n\t" /* Low surrogate. */ \ + " st %[R_TMP3],0(%[R_OUT])\n\t" \ + " la %[R_OUT],4(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + "92: lghi %[R_RES],%[RES_IN_FULL]\n\t" \ + " j 99f\n\t" \ + "91: lghi %[R_RES],%[RES_IN_ILL]\n\t" \ + " j 99f\n\t" \ + "90: lghi %[R_RES],%[RES_OUT_FULL]\n\t" \ + "99: \n\t" \ + ".machine pop" \ + : /* outputs */ [R_IN] "+a" (inptr) \ + , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (outptr) \ + , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp) \ + , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3) \ + , [R_RES] "+d" (result) \ + : /* inputs */ \ + [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT) \ + , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT) \ + , [RES_IN_FULL] "i" (__GCONV_INCOMPLETE_INPUT) \ + : /* clobber list */ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v30") ASM_CLOBBER_VR ("v31") \ + ); \ + if (__glibc_likely (inptr == inend) \ + || result != __GCONV_ILLEGAL_INPUT) \ + break; \ + \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } + +/* Generate loop-function with hardware vector instructions. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_TO +# define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +# define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +# define TO_LOOP_VX __to_utf16_loop_vx +# define LOOPFCT TO_LOOP_VX +# define LOOP_NEED_FLAGS +# define BODY BODY_TO_VX +# include <iconv/loop.c> +#else +# define TO_LOOP_VX NULL +#endif /* HAVE_TO_VX != 1 */ + +/* This file also exists in sysdeps/s390/multiarch/ which + generates ifunc resolvers for FROM/TO_LOOP functions + and includes iconv/skeleton.c afterwards. */ +#if ! defined USE_MULTIARCH +# include <iconv/skeleton.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/utf8-utf16-z9.c b/REORG.TODO/sysdeps/s390/utf8-utf16-z9.c new file mode 100644 index 0000000000..42163e7a19 --- /dev/null +++ b/REORG.TODO/sysdeps/s390/utf8-utf16-z9.c @@ -0,0 +1,825 @@ +/* Conversion between UTF-8 and UTF-16 - s390 version. + + This module uses the Z9-109 variants of the Convert Unicode + instructions. + Copyright (C) 1997-2017 Free Software Foundation, Inc. + + Author: Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + Based on the work by Ulrich Drepper <drepper@cygnus.com>, 1997. + + Thanks to Daniel Appich who covered the relevant performance work + in his diploma thesis. + + This 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. + + This 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/>. */ + +#include <dlfcn.h> +#include <stdint.h> +#include <unistd.h> +#include <gconv.h> +#include <string.h> + +/* Select which versions should be defined depending on support + for multiarch, vector and used minimum architecture level. */ +#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT +# define HAVE_FROM_C 0 +# define FROM_LOOP_DEFAULT FROM_LOOP_CU +#else +# define HAVE_FROM_C 1 +# define FROM_LOOP_DEFAULT FROM_LOOP_C +#endif + +#define HAVE_TO_C 1 +#define TO_LOOP_DEFAULT TO_LOOP_C + +#if defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT || defined USE_MULTIARCH +# define HAVE_FROM_CU 1 +#else +# define HAVE_FROM_CU 0 +#endif + +#if defined HAVE_S390_VX_ASM_SUPPORT && defined USE_MULTIARCH +# define HAVE_FROM_VX 1 +# define HAVE_TO_VX 1 +#else +# define HAVE_FROM_VX 0 +# define HAVE_TO_VX 0 +#endif + +#if defined HAVE_S390_VX_GCC_SUPPORT +# define ASM_CLOBBER_VR(NR) , NR +#else +# define ASM_CLOBBER_VR(NR) +#endif + +#if defined __s390x__ +# define CONVERT_32BIT_SIZE_T(REG) +#else +# define CONVERT_32BIT_SIZE_T(REG) "llgfr %" #REG ",%" #REG "\n\t" +#endif + +/* Defines for skeleton.c. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 4 +#define MIN_NEEDED_TO 2 +#define MAX_NEEDED_TO 4 +#define FROM_LOOP FROM_LOOP_DEFAULT +#define TO_LOOP TO_LOOP_DEFAULT +#define FROM_DIRECTION (dir == from_utf8) +#define ONE_DIRECTION 0 + + +/* UTF-16 big endian byte order mark. */ +#define BOM_UTF16 0xfeff + +/* Direction of the transformation. */ +enum direction +{ + illegal_dir, + to_utf8, + from_utf8 +}; + +struct utf8_data +{ + enum direction dir; + int emit_bom; +}; + + +extern int gconv_init (struct __gconv_step *step); +int +gconv_init (struct __gconv_step *step) +{ + /* Determine which direction. */ + struct utf8_data *new_data; + enum direction dir = illegal_dir; + int emit_bom; + int result; + + emit_bom = (__strcasecmp (step->__to_name, "UTF-16//") == 0); + + if (__strcasecmp (step->__from_name, "ISO-10646/UTF8/") == 0 + && (__strcasecmp (step->__to_name, "UTF-16//") == 0 + || __strcasecmp (step->__to_name, "UTF-16BE//") == 0)) + { + dir = from_utf8; + } + else if (__strcasecmp (step->__from_name, "UTF-16BE//") == 0 + && __strcasecmp (step->__to_name, "ISO-10646/UTF8/") == 0) + { + dir = to_utf8; + } + + result = __GCONV_NOCONV; + if (dir != illegal_dir) + { + new_data = (struct utf8_data *) malloc (sizeof (struct utf8_data)); + + result = __GCONV_NOMEM; + if (new_data != NULL) + { + new_data->dir = dir; + new_data->emit_bom = emit_bom; + step->__data = new_data; + + if (dir == from_utf8) + { + step->__min_needed_from = MIN_NEEDED_FROM; + step->__max_needed_from = MIN_NEEDED_FROM; + step->__min_needed_to = MIN_NEEDED_TO; + step->__max_needed_to = MIN_NEEDED_TO; + } + else + { + step->__min_needed_from = MIN_NEEDED_TO; + step->__max_needed_from = MIN_NEEDED_TO; + step->__min_needed_to = MIN_NEEDED_FROM; + step->__max_needed_to = MIN_NEEDED_FROM; + } + + step->__stateful = 0; + + result = __GCONV_OK; + } + } + + return result; +} + + +extern void gconv_end (struct __gconv_step *data); +void +gconv_end (struct __gconv_step *data) +{ + free (data->__data); +} + +/* The macro for the hardware loop. This is used for both + directions. */ +#define HARDWARE_CONVERT(INSTRUCTION) \ + { \ + register const unsigned char* pInput __asm__ ("8") = inptr; \ + register size_t inlen __asm__ ("9") = inend - inptr; \ + register unsigned char* pOutput __asm__ ("10") = outptr; \ + register size_t outlen __asm__("11") = outend - outptr; \ + unsigned long cc = 0; \ + \ + __asm__ __volatile__ (".machine push \n\t" \ + ".machine \"z9-109\" \n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + "0: " INSTRUCTION " \n\t" \ + ".machine pop \n\t" \ + " jo 0b \n\t" \ + " ipm %2 \n" \ + : "+a" (pOutput), "+a" (pInput), "+d" (cc), \ + "+d" (outlen), "+d" (inlen) \ + : \ + : "cc", "memory"); \ + \ + inptr = pInput; \ + outptr = pOutput; \ + cc >>= 28; \ + \ + if (cc == 1) \ + { \ + result = __GCONV_FULL_OUTPUT; \ + } \ + else if (cc == 2) \ + { \ + result = __GCONV_ILLEGAL_INPUT; \ + } \ + } + +#define PREPARE_LOOP \ + enum direction dir = ((struct utf8_data *) step->__data)->dir; \ + int emit_bom = ((struct utf8_data *) step->__data)->emit_bom; \ + \ + if (emit_bom && !data->__internal_use \ + && data->__invocation_counter == 0) \ + { \ + /* Emit the UTF-16 Byte Order Mark. */ \ + if (__glibc_unlikely (outbuf + 2 > outend)) \ + return __GCONV_FULL_OUTPUT; \ + \ + put16u (outbuf, BOM_UTF16); \ + outbuf += 2; \ + } + +/* Conversion function from UTF-8 to UTF-16. */ +#define BODY_FROM_HW(ASM) \ + { \ + ASM; \ + if (__glibc_likely (inptr == inend) \ + || result == __GCONV_FULL_OUTPUT) \ + break; \ + \ + int i; \ + for (i = 1; inptr + i < inend && i < 5; ++i) \ + if ((inptr[i] & 0xc0) != 0x80) \ + break; \ + \ + if (__glibc_likely (inptr + i == inend \ + && result == __GCONV_EMPTY_INPUT)) \ + { \ + result = __GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + STANDARD_FROM_LOOP_ERR_HANDLER (i); \ + } + +#if HAVE_FROM_VX == 1 +# define HW_FROM_VX \ + { \ + register const unsigned char* pInput asm ("8") = inptr; \ + register size_t inlen asm ("9") = inend - inptr; \ + register unsigned char* pOutput asm ("10") = outptr; \ + register size_t outlen asm("11") = outend - outptr; \ + unsigned long tmp, tmp2, tmp3; \ + asm volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + " vrepib %%v30,0x7f\n\t" /* For compare > 0x7f. */ \ + " vrepib %%v31,0x20\n\t" \ + CONVERT_32BIT_SIZE_T ([R_INLEN]) \ + CONVERT_32BIT_SIZE_T ([R_OUTLEN]) \ + /* Loop which handles UTF-8 chars <=0x7f. */ \ + "0: clgijl %[R_INLEN],16,20f\n\t" \ + " clgijl %[R_OUTLEN],32,20f\n\t" \ + "1: vl %%v16,0(%[R_IN])\n\t" \ + " vstrcbs %%v17,%%v16,%%v30,%%v31\n\t" \ + " jno 10f\n\t" /* Jump away if not all bytes are 1byte \ + UTF8 chars. */ \ + /* Enlarge to UTF-16. */ \ + " vuplhb %%v18,%%v16\n\t" \ + " la %[R_IN],16(%[R_IN])\n\t" \ + " vupllb %%v19,%%v16\n\t" \ + " aghi %[R_INLEN],-16\n\t" \ + /* Store 32 bytes to buf_out. */ \ + " vstm %%v18,%%v19,0(%[R_OUT])\n\t" \ + " aghi %[R_OUTLEN],-32\n\t" \ + " la %[R_OUT],32(%[R_OUT])\n\t" \ + " clgijl %[R_INLEN],16,20f\n\t" \ + " clgijl %[R_OUTLEN],32,20f\n\t" \ + " j 1b\n\t" \ + "10:\n\t" \ + /* At least one byte is > 0x7f. \ + Store the preceding 1-byte chars. */ \ + " vlgvb %[R_TMP],%%v17,7\n\t" \ + " sllk %[R_TMP2],%[R_TMP],1\n\t" /* Compute highest \ + index to store. */ \ + " llgfr %[R_TMP3],%[R_TMP2]\n\t" \ + " ahi %[R_TMP2],-1\n\t" \ + " jl 20f\n\t" \ + " vuplhb %%v18,%%v16\n\t" \ + " vstl %%v18,%[R_TMP2],0(%[R_OUT])\n\t" \ + " ahi %[R_TMP2],-16\n\t" \ + " jl 11f\n\t" \ + " vupllb %%v19,%%v16\n\t" \ + " vstl %%v19,%[R_TMP2],16(%[R_OUT])\n\t" \ + "11: \n\t" /* Update pointers. */ \ + " la %[R_IN],0(%[R_TMP],%[R_IN])\n\t" \ + " slgr %[R_INLEN],%[R_TMP]\n\t" \ + " la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t" \ + " slgr %[R_OUTLEN],%[R_TMP3]\n\t" \ + /* Handle multibyte utf8-char with convert instruction. */ \ + "20: cu12 %[R_OUT],%[R_IN],1\n\t" \ + " jo 0b\n\t" /* Try vector implemenation again. */ \ + " lochil %[R_RES],%[RES_OUT_FULL]\n\t" /* cc == 1. */ \ + " lochih %[R_RES],%[RES_IN_ILL]\n\t" /* cc == 2. */ \ + ".machine pop" \ + : /* outputs */ [R_IN] "+a" (pInput) \ + , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (pOutput) \ + , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp) \ + , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3) \ + , [R_RES] "+d" (result) \ + : /* inputs */ \ + [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT) \ + , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT) \ + : /* clobber list */ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v30") ASM_CLOBBER_VR ("v31") \ + ); \ + inptr = pInput; \ + outptr = pOutput; \ + } +# define BODY_FROM_VX BODY_FROM_HW (HW_FROM_VX) + +/* Generate loop-function with hardware vector and utf-convert instructions. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define MAX_NEEDED_OUTPUT MAX_NEEDED_TO +# define FROM_LOOP_VX __from_utf8_loop_vx +# define LOOPFCT FROM_LOOP_VX +# define LOOP_NEED_FLAGS +# define BODY BODY_FROM_VX +# include <iconv/loop.c> +#else +# define FROM_LOOP_VX NULL +#endif /* HAVE_FROM_VX != 1 */ + +#if HAVE_FROM_CU == 1 +# define BODY_FROM_ETF3EH BODY_FROM_HW (HARDWARE_CONVERT ("cu12 %0, %1, 1")) + +/* Generate loop-function with hardware utf-convert instruction. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define MAX_NEEDED_OUTPUT MAX_NEEDED_TO +# define FROM_LOOP_CU __from_utf8_loop_etf3eh +# define LOOPFCT FROM_LOOP_CU +# define LOOP_NEED_FLAGS +# define BODY BODY_FROM_ETF3EH +# include <iconv/loop.c> +#else +# define FROM_LOOP_CU NULL +#endif /* HAVE_FROM_CU != 1 */ + +#if HAVE_FROM_C == 1 +/* The software implementation is based on the code in gconv_simple.c. */ +# define BODY_FROM_C \ + { \ + /* Next input byte. */ \ + uint16_t ch = *inptr; \ + \ + if (__glibc_likely (ch < 0x80)) \ + { \ + /* One byte sequence. */ \ + ++inptr; \ + } \ + else \ + { \ + uint_fast32_t cnt; \ + uint_fast32_t i; \ + \ + if (ch >= 0xc2 && ch < 0xe0) \ + { \ + /* We expect two bytes. The first byte cannot be 0xc0 \ + or 0xc1, otherwise the wide character could have been \ + represented using a single byte. */ \ + cnt = 2; \ + ch &= 0x1f; \ + } \ + else if (__glibc_likely ((ch & 0xf0) == 0xe0)) \ + { \ + /* We expect three bytes. */ \ + cnt = 3; \ + ch &= 0x0f; \ + } \ + else if (__glibc_likely ((ch & 0xf8) == 0xf0)) \ + { \ + /* We expect four bytes. */ \ + cnt = 4; \ + ch &= 0x07; \ + } \ + else \ + { \ + /* Search the end of this ill-formed UTF-8 character. This \ + is the next byte with (x & 0xc0) != 0x80. */ \ + i = 0; \ + do \ + ++i; \ + while (inptr + i < inend \ + && (*(inptr + i) & 0xc0) == 0x80 \ + && i < 5); \ + \ + errout: \ + STANDARD_FROM_LOOP_ERR_HANDLER (i); \ + } \ + \ + if (__glibc_unlikely (inptr + cnt > inend)) \ + { \ + /* We don't have enough input. But before we report \ + that check that all the bytes are correct. */ \ + for (i = 1; inptr + i < inend; ++i) \ + if ((inptr[i] & 0xc0) != 0x80) \ + break; \ + \ + if (__glibc_likely (inptr + i == inend)) \ + { \ + result = __GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + goto errout; \ + } \ + \ + if (cnt == 4) \ + { \ + /* For 4 byte UTF-8 chars two UTF-16 chars (high and \ + low) are needed. */ \ + uint16_t zabcd, high, low; \ + \ + if (__glibc_unlikely (outptr + 4 > outend)) \ + { \ + /* Overflow in the output buffer. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + /* Check if tail-bytes >= 0x80, < 0xc0. */ \ + for (i = 1; i < cnt; ++i) \ + { \ + if ((inptr[i] & 0xc0) != 0x80) \ + /* This is an illegal encoding. */ \ + goto errout; \ + } \ + \ + /* See Principles of Operations cu12. */ \ + zabcd = (((inptr[0] & 0x7) << 2) | \ + ((inptr[1] & 0x30) >> 4)) - 1; \ + \ + /* z-bit must be zero after subtracting 1. */ \ + if (zabcd & 0x10) \ + STANDARD_FROM_LOOP_ERR_HANDLER (4) \ + \ + high = (uint16_t)(0xd8 << 8); /* high surrogate id */ \ + high |= zabcd << 6; /* abcd bits */ \ + high |= (inptr[1] & 0xf) << 2; /* efgh bits */ \ + high |= (inptr[2] & 0x30) >> 4; /* ij bits */ \ + \ + low = (uint16_t)(0xdc << 8); /* low surrogate id */ \ + low |= ((uint16_t)inptr[2] & 0xc) << 6; /* kl bits */ \ + low |= (inptr[2] & 0x3) << 6; /* mn bits */ \ + low |= inptr[3] & 0x3f; /* opqrst bits */ \ + \ + put16 (outptr, high); \ + outptr += 2; \ + put16 (outptr, low); \ + outptr += 2; \ + inptr += 4; \ + continue; \ + } \ + else \ + { \ + /* Read the possible remaining bytes. */ \ + for (i = 1; i < cnt; ++i) \ + { \ + uint16_t byte = inptr[i]; \ + \ + if ((byte & 0xc0) != 0x80) \ + /* This is an illegal encoding. */ \ + break; \ + \ + ch <<= 6; \ + ch |= byte & 0x3f; \ + } \ + \ + /* If i < cnt, some trail byte was not >= 0x80, < 0xc0. \ + If cnt > 2 and ch < 2^(5*cnt-4), the wide character ch could \ + have been represented with fewer than cnt bytes. */ \ + if (i < cnt || (cnt > 2 && (ch >> (5 * cnt - 4)) == 0) \ + /* Do not accept UTF-16 surrogates. */ \ + || (ch >= 0xd800 && ch <= 0xdfff)) \ + { \ + /* This is an illegal encoding. */ \ + goto errout; \ + } \ + \ + inptr += cnt; \ + } \ + } \ + /* Now adjust the pointers and store the result. */ \ + *((uint16_t *) outptr) = ch; \ + outptr += sizeof (uint16_t); \ + } + +/* Generate loop-function with software implementation. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define MAX_NEEDED_OUTPUT MAX_NEEDED_TO +# define FROM_LOOP_C __from_utf8_loop_c +# define LOOPFCT FROM_LOOP_C +# define LOOP_NEED_FLAGS +# define BODY BODY_FROM_C +# include <iconv/loop.c> +#else +# define FROM_LOOP_C NULL +#endif /* HAVE_FROM_C != 1 */ + +/* Conversion from UTF-16 to UTF-8. */ + +#if HAVE_TO_C == 1 +/* The software routine is based on the functionality of the S/390 + hardware instruction (cu21) as described in the Principles of + Operation. */ +# define BODY_TO_C \ + { \ + uint16_t c = get16 (inptr); \ + \ + if (__glibc_likely (c <= 0x007f)) \ + { \ + /* Single byte UTF-8 char. */ \ + *outptr = c & 0xff; \ + outptr++; \ + } \ + else if (c >= 0x0080 && c <= 0x07ff) \ + { \ + /* Two byte UTF-8 char. */ \ + \ + if (__glibc_unlikely (outptr + 2 > outend)) \ + { \ + /* Overflow in the output buffer. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + outptr[0] = 0xc0; \ + outptr[0] |= c >> 6; \ + \ + outptr[1] = 0x80; \ + outptr[1] |= c & 0x3f; \ + \ + outptr += 2; \ + } \ + else if ((c >= 0x0800 && c <= 0xd7ff) || c > 0xdfff) \ + { \ + /* Three byte UTF-8 char. */ \ + \ + if (__glibc_unlikely (outptr + 3 > outend)) \ + { \ + /* Overflow in the output buffer. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ + } \ + outptr[0] = 0xe0; \ + outptr[0] |= c >> 12; \ + \ + outptr[1] = 0x80; \ + outptr[1] |= (c >> 6) & 0x3f; \ + \ + outptr[2] = 0x80; \ + outptr[2] |= c & 0x3f; \ + \ + outptr += 3; \ + } \ + else if (c >= 0xd800 && c <= 0xdbff) \ + { \ + /* Four byte UTF-8 char. */ \ + uint16_t low, uvwxy; \ + \ + if (__glibc_unlikely (outptr + 4 > outend)) \ + { \ + /* Overflow in the output buffer. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ + } \ + if (__glibc_unlikely (inptr + 4 > inend)) \ + { \ + result = __GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + low = get16 (inptr); \ + \ + if ((low & 0xfc00) != 0xdc00) \ + { \ + inptr -= 2; \ + STANDARD_TO_LOOP_ERR_HANDLER (2); \ + } \ + uvwxy = ((c >> 6) & 0xf) + 1; \ + outptr[0] = 0xf0; \ + outptr[0] |= uvwxy >> 2; \ + \ + outptr[1] = 0x80; \ + outptr[1] |= (uvwxy << 4) & 0x30; \ + outptr[1] |= (c >> 2) & 0x0f; \ + \ + outptr[2] = 0x80; \ + outptr[2] |= (c & 0x03) << 4; \ + outptr[2] |= (low >> 6) & 0x0f; \ + \ + outptr[3] = 0x80; \ + outptr[3] |= low & 0x3f; \ + \ + outptr += 4; \ + } \ + else \ + { \ + STANDARD_TO_LOOP_ERR_HANDLER (2); \ + } \ + inptr += 2; \ + } + +/* Generate loop-function with software implementation. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_TO +# define MAX_NEEDED_INPUT MAX_NEEDED_TO +# define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +# define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +# define TO_LOOP_C __to_utf8_loop_c +# define LOOPFCT TO_LOOP_C +# define BODY BODY_TO_C +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +#else +# define TO_LOOP_C NULL +#endif /* HAVE_TO_C != 1 */ + +#if HAVE_TO_VX == 1 +# define BODY_TO_VX \ + { \ + size_t inlen = inend - inptr; \ + size_t outlen = outend - outptr; \ + unsigned long tmp, tmp2, tmp3; \ + asm volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + /* Setup to check for values <= 0x7f. */ \ + " larl %[R_TMP],9f\n\t" \ + " vlm %%v30,%%v31,0(%[R_TMP])\n\t" \ + CONVERT_32BIT_SIZE_T ([R_INLEN]) \ + CONVERT_32BIT_SIZE_T ([R_OUTLEN]) \ + /* Loop which handles UTF-16 chars <=0x7f. */ \ + "0: clgijl %[R_INLEN],32,2f\n\t" \ + " clgijl %[R_OUTLEN],16,2f\n\t" \ + "1: vlm %%v16,%%v17,0(%[R_IN])\n\t" \ + " lghi %[R_TMP2],0\n\t" \ + /* Check for > 1byte UTF-8 chars. */ \ + " vstrchs %%v19,%%v16,%%v30,%%v31\n\t" \ + " jno 10f\n\t" /* Jump away if not all bytes are 1byte \ + UTF8 chars. */ \ + " vstrchs %%v19,%%v17,%%v30,%%v31\n\t" \ + " jno 11f\n\t" /* Jump away if not all bytes are 1byte \ + UTF8 chars. */ \ + /* Shorten to UTF-8. */ \ + " vpkh %%v18,%%v16,%%v17\n\t" \ + " la %[R_IN],32(%[R_IN])\n\t" \ + " aghi %[R_INLEN],-32\n\t" \ + /* Store 16 bytes to buf_out. */ \ + " vst %%v18,0(%[R_OUT])\n\t" \ + " aghi %[R_OUTLEN],-16\n\t" \ + " la %[R_OUT],16(%[R_OUT])\n\t" \ + " clgijl %[R_INLEN],32,2f\n\t" \ + " clgijl %[R_OUTLEN],16,2f\n\t" \ + " j 1b\n\t" \ + /* Setup to check for ch > 0x7f. (v30, v31) */ \ + "9: .short 0x7f,0x7f,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \ + " .short 0x2000,0x2000,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \ + /* At least one byte is > 0x7f. \ + Store the preceding 1-byte chars. */ \ + "11: lghi %[R_TMP2],16\n\t" /* match was found in v17. */ \ + "10:\n\t" \ + " vlgvb %[R_TMP],%%v19,7\n\t" \ + /* Shorten to UTF-8. */ \ + " vpkh %%v18,%%v16,%%v17\n\t" \ + " ar %[R_TMP],%[R_TMP2]\n\t" /* Number of in bytes. */ \ + " srlg %[R_TMP3],%[R_TMP],1\n\t" /* Number of out bytes. */ \ + " ahik %[R_TMP2],%[R_TMP3],-1\n\t" /* Highest index to store. */ \ + " jl 13f\n\t" \ + " vstl %%v18,%[R_TMP2],0(%[R_OUT])\n\t" \ + /* Update pointers. */ \ + " la %[R_IN],0(%[R_TMP],%[R_IN])\n\t" \ + " slgr %[R_INLEN],%[R_TMP]\n\t" \ + " la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t" \ + " slgr %[R_OUTLEN],%[R_TMP3]\n\t" \ + "13: \n\t" \ + /* Calculate remaining uint16_t values in loaded vrs. */ \ + " lghi %[R_TMP2],16\n\t" \ + " slgr %[R_TMP2],%[R_TMP3]\n\t" \ + " llh %[R_TMP],0(%[R_IN])\n\t" \ + " aghi %[R_INLEN],-2\n\t" \ + " j 22f\n\t" \ + /* Handle remaining bytes. */ \ + "2: \n\t" \ + /* Zero, one or more bytes available? */ \ + " clgfi %[R_INLEN],1\n\t" \ + " locghie %[R_RES],%[RES_IN_FULL]\n\t" /* Only one byte. */ \ + " jle 99f\n\t" /* End if less than two bytes. */ \ + /* Calculate remaining uint16_t values in inptr. */ \ + " srlg %[R_TMP2],%[R_INLEN],1\n\t" \ + /* Handle multibyte utf8-char. */ \ + "20: llh %[R_TMP],0(%[R_IN])\n\t" \ + " aghi %[R_INLEN],-2\n\t" \ + /* Test if ch is 1-byte UTF-8 char. */ \ + "21: clijh %[R_TMP],0x7f,22f\n\t" \ + /* Handle 1-byte UTF-8 char. */ \ + "31: slgfi %[R_OUTLEN],1\n\t" \ + " jl 90f \n\t" \ + " stc %[R_TMP],0(%[R_OUT])\n\t" \ + " la %[R_IN],2(%[R_IN])\n\t" \ + " la %[R_OUT],1(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Test if ch is 2-byte UTF-8 char. */ \ + "22: clfi %[R_TMP],0x7ff\n\t" \ + " jh 23f\n\t" \ + /* Handle 2-byte UTF-8 char. */ \ + "32: slgfi %[R_OUTLEN],2\n\t" \ + " jl 90f \n\t" \ + " llill %[R_TMP3],0xc080\n\t" \ + " la %[R_IN],2(%[R_IN])\n\t" \ + " risbgn %[R_TMP3],%[R_TMP],51,55,2\n\t" /* 1. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],58,63,0\n\t" /* 2. byte. */ \ + " sth %[R_TMP3],0(%[R_OUT])\n\t" \ + " la %[R_OUT],2(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Test if ch is 3-byte UTF-8 char. */ \ + "23: clfi %[R_TMP],0xd7ff\n\t" \ + " jh 24f\n\t" \ + /* Handle 3-byte UTF-8 char. */ \ + "33: slgfi %[R_OUTLEN],3\n\t" \ + " jl 90f \n\t" \ + " llilf %[R_TMP3],0xe08080\n\t" \ + " la %[R_IN],2(%[R_IN])\n\t" \ + " risbgn %[R_TMP3],%[R_TMP],44,47,4\n\t" /* 1. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],50,55,2\n\t" /* 2. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],58,63,0\n\t" /* 3. byte. */ \ + " stcm %[R_TMP3],7,0(%[R_OUT])\n\t" \ + " la %[R_OUT],3(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Test if ch is 4-byte UTF-8 char. */ \ + "24: clfi %[R_TMP],0xdfff\n\t" \ + " jh 33b\n\t" /* Handle this 3-byte UTF-8 char. */ \ + " clfi %[R_TMP],0xdbff\n\t" \ + " locghih %[R_RES],%[RES_IN_ILL]\n\t" \ + " jh 99f\n\t" /* Jump away if this is a low surrogate \ + without a preceding high surrogate. */ \ + /* Handle 4-byte UTF-8 char. */ \ + "34: slgfi %[R_OUTLEN],4\n\t" \ + " jl 90f \n\t" \ + " slgfi %[R_INLEN],2\n\t" \ + " locghil %[R_RES],%[RES_IN_FULL]\n\t" \ + " jl 99f\n\t" /* Jump away if low surrogate is missing. */ \ + " llilf %[R_TMP3],0xf0808080\n\t" \ + " aghi %[R_TMP],0x40\n\t" \ + " risbgn %[R_TMP3],%[R_TMP],37,39,16\n\t" /* 1. byte: uvw */ \ + " risbgn %[R_TMP3],%[R_TMP],42,43,14\n\t" /* 2. byte: xy */ \ + " risbgn %[R_TMP3],%[R_TMP],44,47,14\n\t" /* 2. byte: efgh */ \ + " risbgn %[R_TMP3],%[R_TMP],50,51,12\n\t" /* 3. byte: ij */ \ + " llh %[R_TMP],2(%[R_IN])\n\t" /* Load low surrogate. */ \ + " risbgn %[R_TMP3],%[R_TMP],52,55,2\n\t" /* 3. byte: klmn */ \ + " risbgn %[R_TMP3],%[R_TMP],58,63,0\n\t" /* 4. byte: opqrst */ \ + " nilf %[R_TMP],0xfc00\n\t" \ + " clfi %[R_TMP],0xdc00\n\t" /* Check if it starts with 0xdc00. */ \ + " locghine %[R_RES],%[RES_IN_ILL]\n\t" \ + " jne 99f\n\t" /* Jump away if low surrogate is invalid. */ \ + " st %[R_TMP3],0(%[R_OUT])\n\t" \ + " la %[R_IN],4(%[R_IN])\n\t" \ + " la %[R_OUT],4(%[R_OUT])\n\t" \ + " aghi %[R_TMP2],-2\n\t" \ + " jh 20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Exit with __GCONV_FULL_OUTPUT. */ \ + "90: lghi %[R_RES],%[RES_OUT_FULL]\n\t" \ + "99: \n\t" \ + ".machine pop" \ + : /* outputs */ [R_IN] "+a" (inptr) \ + , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (outptr) \ + , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp) \ + , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3) \ + , [R_RES] "+d" (result) \ + : /* inputs */ \ + [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT) \ + , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT) \ + , [RES_IN_FULL] "i" (__GCONV_INCOMPLETE_INPUT) \ + : /* clobber list */ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v30") ASM_CLOBBER_VR ("v31") \ + ); \ + if (__glibc_likely (inptr == inend) \ + || result != __GCONV_ILLEGAL_INPUT) \ + break; \ + \ + STANDARD_TO_LOOP_ERR_HANDLER (2); \ + } + +/* Generate loop-function with vector implementation. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_TO +# define MAX_NEEDED_INPUT MAX_NEEDED_TO +# define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +# define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +# define TO_LOOP_VX __to_utf8_loop_vx +# define LOOPFCT TO_LOOP_VX +# define BODY BODY_TO_VX +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +#else +# define TO_LOOP_VX NULL +#endif /* HAVE_TO_VX != 1 */ + +/* This file also exists in sysdeps/s390/multiarch/ which + generates ifunc resolvers for FROM/TO_LOOP functions + and includes iconv/skeleton.c afterwards. */ +#if ! defined USE_MULTIARCH +# include <iconv/skeleton.c> +#endif diff --git a/REORG.TODO/sysdeps/s390/utf8-utf32-z9.c b/REORG.TODO/sysdeps/s390/utf8-utf32-z9.c new file mode 100644 index 0000000000..57572fa44a --- /dev/null +++ b/REORG.TODO/sysdeps/s390/utf8-utf32-z9.c @@ -0,0 +1,871 @@ +/* Conversion between UTF-8 and UTF-32 BE/internal. + + This module uses the Z9-109 variants of the Convert Unicode + instructions. + Copyright (C) 1997-2017 Free Software Foundation, Inc. + + Author: Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + Based on the work by Ulrich Drepper <drepper@cygnus.com>, 1997. + + Thanks to Daniel Appich who covered the relevant performance work + in his diploma thesis. + + This 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. + + This 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/>. */ + +#include <dlfcn.h> +#include <stdint.h> +#include <unistd.h> +#include <gconv.h> +#include <string.h> + +/* Select which versions should be defined depending on support + for multiarch, vector and used minimum architecture level. */ +#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT +# define HAVE_FROM_C 0 +# define FROM_LOOP_DEFAULT FROM_LOOP_CU +#else +# define HAVE_FROM_C 1 +# define FROM_LOOP_DEFAULT FROM_LOOP_C +#endif + +#define HAVE_TO_C 1 +#define TO_LOOP_DEFAULT TO_LOOP_C + +#if defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT || defined USE_MULTIARCH +# define HAVE_FROM_CU 1 +#else +# define HAVE_FROM_CU 0 +#endif + +#if defined HAVE_S390_VX_ASM_SUPPORT && defined USE_MULTIARCH +# define HAVE_FROM_VX 1 +# define HAVE_TO_VX 1 +#else +# define HAVE_FROM_VX 0 +# define HAVE_TO_VX 0 +#endif + +#if defined HAVE_S390_VX_GCC_SUPPORT +# define ASM_CLOBBER_VR(NR) , NR +#else +# define ASM_CLOBBER_VR(NR) +#endif + +#if defined __s390x__ +# define CONVERT_32BIT_SIZE_T(REG) +#else +# define CONVERT_32BIT_SIZE_T(REG) "llgfr %" #REG ",%" #REG "\n\t" +#endif + +/* Defines for skeleton.c. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 6 +#define MIN_NEEDED_TO 4 +#define FROM_LOOP FROM_LOOP_DEFAULT +#define TO_LOOP TO_LOOP_DEFAULT +#define FROM_DIRECTION (dir == from_utf8) +#define ONE_DIRECTION 0 + +/* UTF-32 big endian byte order mark. */ +#define BOM 0x0000feffu + +/* Direction of the transformation. */ +enum direction +{ + illegal_dir, + to_utf8, + from_utf8 +}; + +struct utf8_data +{ + enum direction dir; + int emit_bom; +}; + + +extern int gconv_init (struct __gconv_step *step); +int +gconv_init (struct __gconv_step *step) +{ + /* Determine which direction. */ + struct utf8_data *new_data; + enum direction dir = illegal_dir; + int emit_bom; + int result; + + emit_bom = (__strcasecmp (step->__to_name, "UTF-32//") == 0); + + if (__strcasecmp (step->__from_name, "ISO-10646/UTF8/") == 0 + && (__strcasecmp (step->__to_name, "UTF-32//") == 0 + || __strcasecmp (step->__to_name, "UTF-32BE//") == 0 + || __strcasecmp (step->__to_name, "INTERNAL") == 0)) + { + dir = from_utf8; + } + else if (__strcasecmp (step->__to_name, "ISO-10646/UTF8/") == 0 + && (__strcasecmp (step->__from_name, "UTF-32BE//") == 0 + || __strcasecmp (step->__from_name, "INTERNAL") == 0)) + { + dir = to_utf8; + } + + result = __GCONV_NOCONV; + if (dir != illegal_dir) + { + new_data = (struct utf8_data *) malloc (sizeof (struct utf8_data)); + + result = __GCONV_NOMEM; + if (new_data != NULL) + { + new_data->dir = dir; + new_data->emit_bom = emit_bom; + step->__data = new_data; + + if (dir == from_utf8) + { + step->__min_needed_from = MIN_NEEDED_FROM; + step->__max_needed_from = MIN_NEEDED_FROM; + step->__min_needed_to = MIN_NEEDED_TO; + step->__max_needed_to = MIN_NEEDED_TO; + } + else + { + step->__min_needed_from = MIN_NEEDED_TO; + step->__max_needed_from = MIN_NEEDED_TO; + step->__min_needed_to = MIN_NEEDED_FROM; + step->__max_needed_to = MIN_NEEDED_FROM; + } + + step->__stateful = 0; + + result = __GCONV_OK; + } + } + + return result; +} + + +extern void gconv_end (struct __gconv_step *data); +void +gconv_end (struct __gconv_step *data) +{ + free (data->__data); +} + +/* The macro for the hardware loop. This is used for both + directions. */ +#define HARDWARE_CONVERT(INSTRUCTION) \ + { \ + register const unsigned char* pInput __asm__ ("8") = inptr; \ + register size_t inlen __asm__ ("9") = inend - inptr; \ + register unsigned char* pOutput __asm__ ("10") = outptr; \ + register size_t outlen __asm__("11") = outend - outptr; \ + unsigned long cc = 0; \ + \ + __asm__ __volatile__ (".machine push \n\t" \ + ".machine \"z9-109\" \n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + "0: " INSTRUCTION " \n\t" \ + ".machine pop \n\t" \ + " jo 0b \n\t" \ + " ipm %2 \n" \ + : "+a" (pOutput), "+a" (pInput), "+d" (cc), \ + "+d" (outlen), "+d" (inlen) \ + : \ + : "cc", "memory"); \ + \ + inptr = pInput; \ + outptr = pOutput; \ + cc >>= 28; \ + \ + if (cc == 1) \ + { \ + result = __GCONV_FULL_OUTPUT; \ + } \ + else if (cc == 2) \ + { \ + result = __GCONV_ILLEGAL_INPUT; \ + } \ + } + +#define PREPARE_LOOP \ + enum direction dir = ((struct utf8_data *) step->__data)->dir; \ + int emit_bom = ((struct utf8_data *) step->__data)->emit_bom; \ + \ + if (emit_bom && !data->__internal_use \ + && data->__invocation_counter == 0) \ + { \ + /* Emit the Byte Order Mark. */ \ + if (__glibc_unlikely (outbuf + 4 > outend)) \ + return __GCONV_FULL_OUTPUT; \ + \ + put32u (outbuf, BOM); \ + outbuf += 4; \ + } + +/* Conversion function from UTF-8 to UTF-32 internal/BE. */ + +#define STORE_REST_COMMON \ + { \ + /* We store the remaining bytes while converting them into the UCS4 \ + format. We can assume that the first byte in the buffer is \ + correct and that it requires a larger number of bytes than there \ + are in the input buffer. */ \ + wint_t ch = **inptrp; \ + size_t cnt, r; \ + \ + state->__count = inend - *inptrp; \ + \ + assert (ch != 0xc0 && ch != 0xc1); \ + if (ch >= 0xc2 && ch < 0xe0) \ + { \ + /* We expect two bytes. The first byte cannot be 0xc0 or \ + 0xc1, otherwise the wide character could have been \ + represented using a single byte. */ \ + cnt = 2; \ + ch &= 0x1f; \ + } \ + else if (__glibc_likely ((ch & 0xf0) == 0xe0)) \ + { \ + /* We expect three bytes. */ \ + cnt = 3; \ + ch &= 0x0f; \ + } \ + else if (__glibc_likely ((ch & 0xf8) == 0xf0)) \ + { \ + /* We expect four bytes. */ \ + cnt = 4; \ + ch &= 0x07; \ + } \ + else if (__glibc_likely ((ch & 0xfc) == 0xf8)) \ + { \ + /* We expect five bytes. */ \ + cnt = 5; \ + ch &= 0x03; \ + } \ + else \ + { \ + /* We expect six bytes. */ \ + cnt = 6; \ + ch &= 0x01; \ + } \ + \ + /* The first byte is already consumed. */ \ + r = cnt - 1; \ + while (++(*inptrp) < inend) \ + { \ + ch <<= 6; \ + ch |= **inptrp & 0x3f; \ + --r; \ + } \ + \ + /* Shift for the so far missing bytes. */ \ + ch <<= r * 6; \ + \ + /* Store the number of bytes expected for the entire sequence. */ \ + state->__count |= cnt << 8; \ + \ + /* Store the value. */ \ + state->__value.__wch = ch; \ + } + +#define UNPACK_BYTES_COMMON \ + { \ + static const unsigned char inmask[5] = { 0xc0, 0xe0, 0xf0, 0xf8, 0xfc }; \ + wint_t wch = state->__value.__wch; \ + size_t ntotal = state->__count >> 8; \ + \ + inlen = state->__count & 255; \ + \ + bytebuf[0] = inmask[ntotal - 2]; \ + \ + do \ + { \ + if (--ntotal < inlen) \ + bytebuf[ntotal] = 0x80 | (wch & 0x3f); \ + wch >>= 6; \ + } \ + while (ntotal > 1); \ + \ + bytebuf[0] |= wch; \ + } + +#define CLEAR_STATE_COMMON \ + state->__count = 0 + +#define BODY_FROM_HW(ASM) \ + { \ + ASM; \ + if (__glibc_likely (inptr == inend) \ + || result == __GCONV_FULL_OUTPUT) \ + break; \ + \ + int i; \ + for (i = 1; inptr + i < inend && i < 5; ++i) \ + if ((inptr[i] & 0xc0) != 0x80) \ + break; \ + \ + if (__glibc_likely (inptr + i == inend \ + && result == __GCONV_EMPTY_INPUT)) \ + { \ + result = __GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + STANDARD_FROM_LOOP_ERR_HANDLER (i); \ + } + +#if HAVE_FROM_C == 1 +/* The software routine is copied from gconv_simple.c. */ +# define BODY_FROM_C \ + { \ + /* Next input byte. */ \ + uint32_t ch = *inptr; \ + \ + if (__glibc_likely (ch < 0x80)) \ + { \ + /* One byte sequence. */ \ + ++inptr; \ + } \ + else \ + { \ + uint_fast32_t cnt; \ + uint_fast32_t i; \ + \ + if (ch >= 0xc2 && ch < 0xe0) \ + { \ + /* We expect two bytes. The first byte cannot be 0xc0 or \ + 0xc1, otherwise the wide character could have been \ + represented using a single byte. */ \ + cnt = 2; \ + ch &= 0x1f; \ + } \ + else if (__glibc_likely ((ch & 0xf0) == 0xe0)) \ + { \ + /* We expect three bytes. */ \ + cnt = 3; \ + ch &= 0x0f; \ + } \ + else if (__glibc_likely ((ch & 0xf8) == 0xf0)) \ + { \ + /* We expect four bytes. */ \ + cnt = 4; \ + ch &= 0x07; \ + } \ + else \ + { \ + /* Search the end of this ill-formed UTF-8 character. This \ + is the next byte with (x & 0xc0) != 0x80. */ \ + i = 0; \ + do \ + ++i; \ + while (inptr + i < inend \ + && (*(inptr + i) & 0xc0) == 0x80 \ + && i < 5); \ + \ + errout: \ + STANDARD_FROM_LOOP_ERR_HANDLER (i); \ + } \ + \ + if (__glibc_unlikely (inptr + cnt > inend)) \ + { \ + /* We don't have enough input. But before we report \ + that check that all the bytes are correct. */ \ + for (i = 1; inptr + i < inend; ++i) \ + if ((inptr[i] & 0xc0) != 0x80) \ + break; \ + \ + if (__glibc_likely (inptr + i == inend)) \ + { \ + result = __GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + goto errout; \ + } \ + \ + /* Read the possible remaining bytes. */ \ + for (i = 1; i < cnt; ++i) \ + { \ + uint32_t byte = inptr[i]; \ + \ + if ((byte & 0xc0) != 0x80) \ + /* This is an illegal encoding. */ \ + break; \ + \ + ch <<= 6; \ + ch |= byte & 0x3f; \ + } \ + \ + /* If i < cnt, some trail byte was not >= 0x80, < 0xc0. \ + If cnt > 2 and ch < 2^(5*cnt-4), the wide character ch could \ + have been represented with fewer than cnt bytes. */ \ + if (i < cnt || (cnt > 2 && (ch >> (5 * cnt - 4)) == 0) \ + /* Do not accept UTF-16 surrogates. */ \ + || (ch >= 0xd800 && ch <= 0xdfff) \ + || (ch > 0x10ffff)) \ + { \ + /* This is an illegal encoding. */ \ + goto errout; \ + } \ + \ + inptr += cnt; \ + } \ + \ + /* Now adjust the pointers and store the result. */ \ + *((uint32_t *) outptr) = ch; \ + outptr += sizeof (uint32_t); \ + } + +/* These definitions apply to the UTF-8 to UTF-32 direction. The + software implementation for UTF-8 still supports multibyte + characters up to 6 bytes whereas the hardware variant does not. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define FROM_LOOP_C __from_utf8_loop_c +# define LOOPFCT FROM_LOOP_C + +# define LOOP_NEED_FLAGS + +# define STORE_REST STORE_REST_COMMON +# define UNPACK_BYTES UNPACK_BYTES_COMMON +# define CLEAR_STATE CLEAR_STATE_COMMON +# define BODY BODY_FROM_C +# include <iconv/loop.c> +#else +# define FROM_LOOP_C NULL +#endif /* HAVE_FROM_C != 1 */ + +#if HAVE_FROM_CU == 1 +/* This hardware routine uses the Convert UTF8 to UTF32 (cu14) instruction. */ +# define BODY_FROM_ETF3EH BODY_FROM_HW (HARDWARE_CONVERT ("cu14 %0, %1, 1")) + +/* Generate loop-function with hardware utf-convert instruction. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define FROM_LOOP_CU __from_utf8_loop_etf3eh +# define LOOPFCT FROM_LOOP_CU + +# define LOOP_NEED_FLAGS + +# define STORE_REST STORE_REST_COMMON +# define UNPACK_BYTES UNPACK_BYTES_COMMON +# define CLEAR_STATE CLEAR_STATE_COMMON +# define BODY BODY_FROM_ETF3EH +# include <iconv/loop.c> +#else +# define FROM_LOOP_CU NULL +#endif /* HAVE_FROM_CU != 1 */ + +#if HAVE_FROM_VX == 1 +# define HW_FROM_VX \ + { \ + register const unsigned char* pInput asm ("8") = inptr; \ + register size_t inlen asm ("9") = inend - inptr; \ + register unsigned char* pOutput asm ("10") = outptr; \ + register size_t outlen asm("11") = outend - outptr; \ + unsigned long tmp, tmp2, tmp3; \ + asm volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + " vrepib %%v30,0x7f\n\t" /* For compare > 0x7f. */ \ + " vrepib %%v31,0x20\n\t" \ + CONVERT_32BIT_SIZE_T ([R_INLEN]) \ + CONVERT_32BIT_SIZE_T ([R_OUTLEN]) \ + /* Loop which handles UTF-8 chars <=0x7f. */ \ + "0: clgijl %[R_INLEN],16,20f\n\t" \ + " clgijl %[R_OUTLEN],64,20f\n\t" \ + "1: vl %%v16,0(%[R_IN])\n\t" \ + " vstrcbs %%v17,%%v16,%%v30,%%v31\n\t" \ + " jno 10f\n\t" /* Jump away if not all bytes are 1byte \ + UTF8 chars. */ \ + /* Enlarge to UCS4. */ \ + " vuplhb %%v18,%%v16\n\t" \ + " vupllb %%v19,%%v16\n\t" \ + " la %[R_IN],16(%[R_IN])\n\t" \ + " vuplhh %%v20,%%v18\n\t" \ + " aghi %[R_INLEN],-16\n\t" \ + " vupllh %%v21,%%v18\n\t" \ + " aghi %[R_OUTLEN],-64\n\t" \ + " vuplhh %%v22,%%v19\n\t" \ + " vupllh %%v23,%%v19\n\t" \ + /* Store 64 bytes to buf_out. */ \ + " vstm %%v20,%%v23,0(%[R_OUT])\n\t" \ + " la %[R_OUT],64(%[R_OUT])\n\t" \ + " clgijl %[R_INLEN],16,20f\n\t" \ + " clgijl %[R_OUTLEN],64,20f\n\t" \ + " j 1b\n\t" \ + "10: \n\t" \ + /* At least one byte is > 0x7f. \ + Store the preceding 1-byte chars. */ \ + " vlgvb %[R_TMP],%%v17,7\n\t" \ + " sllk %[R_TMP2],%[R_TMP],2\n\t" /* Compute highest \ + index to store. */ \ + " llgfr %[R_TMP3],%[R_TMP2]\n\t" \ + " ahi %[R_TMP2],-1\n\t" \ + " jl 20f\n\t" \ + " vuplhb %%v18,%%v16\n\t" \ + " vuplhh %%v20,%%v18\n\t" \ + " vstl %%v20,%[R_TMP2],0(%[R_OUT])\n\t" \ + " ahi %[R_TMP2],-16\n\t" \ + " jl 11f\n\t" \ + " vupllh %%v21,%%v18\n\t" \ + " vstl %%v21,%[R_TMP2],16(%[R_OUT])\n\t" \ + " ahi %[R_TMP2],-16\n\t" \ + " jl 11f\n\t" \ + " vupllb %%v19,%%v16\n\t" \ + " vuplhh %%v22,%%v19\n\t" \ + " vstl %%v22,%[R_TMP2],32(%[R_OUT])\n\t" \ + " ahi %[R_TMP2],-16\n\t" \ + " jl 11f\n\t" \ + " vupllh %%v23,%%v19\n\t" \ + " vstl %%v23,%[R_TMP2],48(%[R_OUT])\n\t" \ + "11: \n\t" \ + /* Update pointers. */ \ + " la %[R_IN],0(%[R_TMP],%[R_IN])\n\t" \ + " slgr %[R_INLEN],%[R_TMP]\n\t" \ + " la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t" \ + " slgr %[R_OUTLEN],%[R_TMP3]\n\t" \ + /* Handle multibyte utf8-char with convert instruction. */ \ + "20: cu14 %[R_OUT],%[R_IN],1\n\t" \ + " jo 0b\n\t" /* Try vector implemenation again. */ \ + " lochil %[R_RES],%[RES_OUT_FULL]\n\t" /* cc == 1. */ \ + " lochih %[R_RES],%[RES_IN_ILL]\n\t" /* cc == 2. */ \ + ".machine pop" \ + : /* outputs */ [R_IN] "+a" (pInput) \ + , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (pOutput) \ + , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp) \ + , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3) \ + , [R_RES] "+d" (result) \ + : /* inputs */ \ + [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT) \ + , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT) \ + : /* clobber list */ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ASM_CLOBBER_VR ("v22") ASM_CLOBBER_VR ("v30") \ + ASM_CLOBBER_VR ("v31") \ + ); \ + inptr = pInput; \ + outptr = pOutput; \ + } +# define BODY_FROM_VX BODY_FROM_HW (HW_FROM_VX) + +/* Generate loop-function with hardware vector and utf-convert instructions. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define FROM_LOOP_VX __from_utf8_loop_vx +# define LOOPFCT FROM_LOOP_VX + +# define LOOP_NEED_FLAGS + +# define STORE_REST STORE_REST_COMMON +# define UNPACK_BYTES UNPACK_BYTES_COMMON +# define CLEAR_STATE CLEAR_STATE_COMMON +# define BODY BODY_FROM_VX +# include <iconv/loop.c> +#else +# define FROM_LOOP_VX NULL +#endif /* HAVE_FROM_VX != 1 */ + +#if HAVE_TO_C == 1 +/* The software routine mimics the S/390 cu41 instruction. */ +# define BODY_TO_C \ + { \ + uint32_t wc = *((const uint32_t *) inptr); \ + \ + if (__glibc_likely (wc <= 0x7f)) \ + { \ + /* Single UTF-8 char. */ \ + *outptr = (uint8_t)wc; \ + outptr++; \ + } \ + else if (wc <= 0x7ff) \ + { \ + /* Two UTF-8 chars. */ \ + if (__glibc_unlikely (outptr + 2 > outend)) \ + { \ + /* Overflow in the output buffer. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + outptr[0] = 0xc0; \ + outptr[0] |= wc >> 6; \ + \ + outptr[1] = 0x80; \ + outptr[1] |= wc & 0x3f; \ + \ + outptr += 2; \ + } \ + else if (wc <= 0xffff) \ + { \ + /* Three UTF-8 chars. */ \ + if (__glibc_unlikely (outptr + 3 > outend)) \ + { \ + /* Overflow in the output buffer. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ + } \ + if (wc >= 0xd800 && wc <= 0xdfff) \ + { \ + /* Do not accept UTF-16 surrogates. */ \ + result = __GCONV_ILLEGAL_INPUT; \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } \ + outptr[0] = 0xe0; \ + outptr[0] |= wc >> 12; \ + \ + outptr[1] = 0x80; \ + outptr[1] |= (wc >> 6) & 0x3f; \ + \ + outptr[2] = 0x80; \ + outptr[2] |= wc & 0x3f; \ + \ + outptr += 3; \ + } \ + else if (wc <= 0x10ffff) \ + { \ + /* Four UTF-8 chars. */ \ + if (__glibc_unlikely (outptr + 4 > outend)) \ + { \ + /* Overflow in the output buffer. */ \ + result = __GCONV_FULL_OUTPUT; \ + break; \ + } \ + outptr[0] = 0xf0; \ + outptr[0] |= wc >> 18; \ + \ + outptr[1] = 0x80; \ + outptr[1] |= (wc >> 12) & 0x3f; \ + \ + outptr[2] = 0x80; \ + outptr[2] |= (wc >> 6) & 0x3f; \ + \ + outptr[3] = 0x80; \ + outptr[3] |= wc & 0x3f; \ + \ + outptr += 4; \ + } \ + else \ + { \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } \ + inptr += 4; \ + } + +/* Generate loop-function with software routing. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_TO +# define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +# define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +# define TO_LOOP_C __to_utf8_loop_c +# define LOOPFCT TO_LOOP_C +# define BODY BODY_TO_C +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +#else +# define TO_LOOP_C NULL +#endif /* HAVE_TO_C != 1 */ + +#if HAVE_TO_VX == 1 +/* The hardware routine uses the S/390 vector instructions. */ +# define BODY_TO_VX \ + { \ + size_t inlen = inend - inptr; \ + size_t outlen = outend - outptr; \ + unsigned long tmp, tmp2, tmp3; \ + asm volatile (".machine push\n\t" \ + ".machine \"z13\"\n\t" \ + ".machinemode \"zarch_nohighgprs\"\n\t" \ + " vleif %%v20,127,0\n\t" /* element 0: 127 */ \ + " vzero %%v21\n\t" \ + " vleih %%v21,8192,0\n\t" /* element 0: > */ \ + " vleih %%v21,-8192,2\n\t" /* element 1: =<> */ \ + CONVERT_32BIT_SIZE_T ([R_INLEN]) \ + CONVERT_32BIT_SIZE_T ([R_OUTLEN]) \ + /* Loop which handles UTF-32 chars <=0x7f. */ \ + "0: clgijl %[R_INLEN],64,2f\n\t" \ + " clgijl %[R_OUTLEN],16,2f\n\t" \ + "1: vlm %%v16,%%v19,0(%[R_IN])\n\t" \ + " lghi %[R_TMP2],0\n\t" \ + /* Shorten to byte values. */ \ + " vpkf %%v23,%%v16,%%v17\n\t" \ + " vpkf %%v24,%%v18,%%v19\n\t" \ + " vpkh %%v23,%%v23,%%v24\n\t" \ + /* Checking for values > 0x7f. */ \ + " vstrcfs %%v22,%%v16,%%v20,%%v21\n\t" \ + " jno 10f\n\t" \ + " vstrcfs %%v22,%%v17,%%v20,%%v21\n\t" \ + " jno 11f\n\t" \ + " vstrcfs %%v22,%%v18,%%v20,%%v21\n\t" \ + " jno 12f\n\t" \ + " vstrcfs %%v22,%%v19,%%v20,%%v21\n\t" \ + " jno 13f\n\t" \ + /* Store 16bytes to outptr. */ \ + " vst %%v23,0(%[R_OUT])\n\t" \ + " aghi %[R_INLEN],-64\n\t" \ + " aghi %[R_OUTLEN],-16\n\t" \ + " la %[R_IN],64(%[R_IN])\n\t" \ + " la %[R_OUT],16(%[R_OUT])\n\t" \ + " clgijl %[R_INLEN],64,2f\n\t" \ + " clgijl %[R_OUTLEN],16,2f\n\t" \ + " j 1b\n\t" \ + /* Found a value > 0x7f. */ \ + "13: ahi %[R_TMP2],4\n\t" \ + "12: ahi %[R_TMP2],4\n\t" \ + "11: ahi %[R_TMP2],4\n\t" \ + "10: vlgvb %[R_TMP],%%v22,7\n\t" \ + " srlg %[R_TMP],%[R_TMP],2\n\t" \ + " agr %[R_TMP],%[R_TMP2]\n\t" \ + " je 16f\n\t" \ + /* Store characters before invalid one... */ \ + " slgr %[R_OUTLEN],%[R_TMP]\n\t" \ + "15: aghi %[R_TMP],-1\n\t" \ + " vstl %%v23,%[R_TMP],0(%[R_OUT])\n\t" \ + /* ... and update pointers. */ \ + " aghi %[R_TMP],1\n\t" \ + " la %[R_OUT],0(%[R_TMP],%[R_OUT])\n\t" \ + " sllg %[R_TMP2],%[R_TMP],2\n\t" \ + " la %[R_IN],0(%[R_TMP2],%[R_IN])\n\t" \ + " slgr %[R_INLEN],%[R_TMP2]\n\t" \ + /* Calculate remaining uint32_t values in loaded vrs. */ \ + "16: lghi %[R_TMP2],16\n\t" \ + " sgr %[R_TMP2],%[R_TMP]\n\t" \ + " l %[R_TMP],0(%[R_IN])\n\t" \ + " aghi %[R_INLEN],-4\n\t" \ + " j 22f\n\t" \ + /* Handle remaining bytes. */ \ + "2: clgije %[R_INLEN],0,99f\n\t" \ + " clgijl %[R_INLEN],4,92f\n\t" \ + /* Calculate remaining uint32_t values in inptr. */ \ + " srlg %[R_TMP2],%[R_INLEN],2\n\t" \ + /* Handle multibyte utf8-char. */ \ + "20: l %[R_TMP],0(%[R_IN])\n\t" \ + " aghi %[R_INLEN],-4\n\t" \ + /* Test if ch is 1byte UTF-8 char. */ \ + "21: clijh %[R_TMP],0x7f,22f\n\t" \ + /* Handle 1-byte UTF-8 char. */ \ + "31: slgfi %[R_OUTLEN],1\n\t" \ + " jl 90f \n\t" \ + " stc %[R_TMP],0(%[R_OUT])\n\t" \ + " la %[R_IN],4(%[R_IN])\n\t" \ + " la %[R_OUT],1(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Test if ch is 2byte UTF-8 char. */ \ + "22: clfi %[R_TMP],0x7ff\n\t" \ + " jh 23f\n\t" \ + /* Handle 2-byte UTF-8 char. */ \ + "32: slgfi %[R_OUTLEN],2\n\t" \ + " jl 90f \n\t" \ + " llill %[R_TMP3],0xc080\n\t" \ + " risbgn %[R_TMP3],%[R_TMP],51,55,2\n\t" /* 1. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],58,63,0\n\t" /* 2. byte. */ \ + " sth %[R_TMP3],0(%[R_OUT])\n\t" \ + " la %[R_IN],4(%[R_IN])\n\t" \ + " la %[R_OUT],2(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Test if ch is 3-byte UTF-8 char. */ \ + "23: clfi %[R_TMP],0xffff\n\t" \ + " jh 24f\n\t" \ + /* Handle 3-byte UTF-8 char. */ \ + "33: slgfi %[R_OUTLEN],3\n\t" \ + " jl 90f \n\t" \ + " llilf %[R_TMP3],0xe08080\n\t" \ + " risbgn %[R_TMP3],%[R_TMP],44,47,4\n\t" /* 1. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],50,55,2\n\t" /* 2. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],58,63,0\n\t" /* 3. byte. */ \ + /* Test if ch is a UTF-16 surrogate: ch & 0xf800 == 0xd800 */ \ + " nilf %[R_TMP],0xf800\n\t" \ + " clfi %[R_TMP],0xd800\n\t" \ + " je 91f\n\t" /* Do not accept UTF-16 surrogates. */ \ + " stcm %[R_TMP3],7,0(%[R_OUT])\n\t" \ + " la %[R_IN],4(%[R_IN])\n\t" \ + " la %[R_OUT],3(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + /* Test if ch is 4-byte UTF-8 char. */ \ + "24: clfi %[R_TMP],0x10ffff\n\t" \ + " jh 91f\n\t" /* ch > 0x10ffff is not allowed! */ \ + /* Handle 4-byte UTF-8 char. */ \ + "34: slgfi %[R_OUTLEN],4\n\t" \ + " jl 90f \n\t" \ + " llilf %[R_TMP3],0xf0808080\n\t" \ + " risbgn %[R_TMP3],%[R_TMP],37,39,6\n\t" /* 1. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],42,47,4\n\t" /* 2. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],50,55,2\n\t" /* 3. byte. */ \ + " risbgn %[R_TMP3],%[R_TMP],58,63,0\n\t" /* 4. byte. */ \ + " st %[R_TMP3],0(%[R_OUT])\n\t" \ + " la %[R_IN],4(%[R_IN])\n\t" \ + " la %[R_OUT],4(%[R_OUT])\n\t" \ + " brctg %[R_TMP2],20b\n\t" \ + " j 0b\n\t" /* Switch to vx-loop. */ \ + "92: lghi %[R_RES],%[RES_IN_FULL]\n\t" \ + " j 99f\n\t" \ + "91: lghi %[R_RES],%[RES_IN_ILL]\n\t" \ + " j 99f\n\t" \ + "90: lghi %[R_RES],%[RES_OUT_FULL]\n\t" \ + "99: \n\t" \ + ".machine pop" \ + : /* outputs */ [R_IN] "+a" (inptr) \ + , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (outptr) \ + , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp) \ + , [R_TMP2] "=a" (tmp2), [R_TMP3] "=d" (tmp3) \ + , [R_RES] "+d" (result) \ + : /* inputs */ \ + [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT) \ + , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT) \ + , [RES_IN_FULL] "i" (__GCONV_INCOMPLETE_INPUT) \ + : /* clobber list */ "memory", "cc" \ + ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \ + ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \ + ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \ + ASM_CLOBBER_VR ("v22") ASM_CLOBBER_VR ("v23") \ + ASM_CLOBBER_VR ("v24") \ + ); \ + if (__glibc_likely (inptr == inend) \ + || result != __GCONV_ILLEGAL_INPUT) \ + break; \ + \ + STANDARD_TO_LOOP_ERR_HANDLER (4); \ + } + +/* Generate loop-function with hardware vector instructions. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_TO +# define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +# define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +# define TO_LOOP_VX __to_utf8_loop_vx +# define LOOPFCT TO_LOOP_VX +# define BODY BODY_TO_VX +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +#else +# define TO_LOOP_VX NULL +#endif /* HAVE_TO_VX != 1 */ + +/* This file also exists in sysdeps/s390/multiarch/ which + generates ifunc resolvers for FROM/TO_LOOP functions + and includes iconv/skeleton.c afterwards. */ +#if ! defined USE_MULTIARCH +# include <iconv/skeleton.c> +#endif |