From b9a1c5edef80d40ac06a318d521caaa39ffe6a1b Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Sep 04 2012 15:48:09 +0000 Subject: - Pick up s390/s390x IFUNC support. --- diff --git a/glibc-rh805093.patch b/glibc-rh805093.patch new file mode 100644 index 0000000..fdc81fe --- /dev/null +++ b/glibc-rh805093.patch @@ -0,0 +1,1615 @@ +commit 08f43f9bbf97c03ec4d2754c69fd9d7efce6ef96 +Author: Andreas Krebbel +Date: Thu Jul 12 13:04:55 2012 +0200 + + S/390: Add support for STT_GNU_IFUNC symbols. + + Add support for STT_GNU_IFUNC symbols and the new R_390_IRELATIVE + relocation. Provide optimized version of memcpy, memset, and memcmp + for z10 and z196. + +2012-07-19 Andreas Krebbel + + * elf/elf.h (R_390_IRELATIVE): New definition. + * sysdeps/s390/s390-64/dl-machine.h (elf_machine_rela): Invoke the + resolver function for IFUNC symbols. Support R_390_IRELATIVE. + (elf_machine_lazy_rel): Support R_390_IRELATIVE. + * sysdeps/s390/s390-32/dl-machine.h (elf_machine_rela): + (elf_machine_lazy_rel): Likewise. + * sysdeps/s390/dl-irel.h: New file. + * sysdeps/s390/s390-64/memcpy.S: New asm code. + * sysdeps/s390/s390-64/memset.S: New asm code. + * sysdeps/s390/s390-64/memcmp.S: New asm code. + * sysdeps/s390/s390-64/multiarch/memset.S: New file. + * sysdeps/s390/s390-64/multiarch/ifunc-resolve.c: New file. + * sysdeps/s390/s390-64/multiarch/memcmp.S: New file. + * sysdeps/s390/s390-64/multiarch/memcpy.S: New file. + * sysdeps/s390/s390-64/multiarch/Makefile: New file. + * sysdeps/s390/s390-32/multiarch/ifunc-resolve.c: New file. + * sysdeps/s390/s390-32/multiarch/Makefile: New file. + * sysdeps/s390/s390-32/multiarch/memcmp.S: New file. + * sysdeps/s390/s390-32/multiarch/memcpy.S: New file. + * sysdeps/s390/s390-32/multiarch/memset.S: New file. + * sysdeps/s390/s390-32/memcpy.S: New asm code. + * sysdeps/s390/s390-32/memset.S: New asm code. + * sysdeps/s390/s390-32/memcmp.S: New asm code. + +diff --git a/elf/elf.h b/elf/elf.h +index 6522ea6..71cfdb8 100644 +--- a/elf/elf.h ++++ b/elf/elf.h +@@ -2627,8 +2627,9 @@ typedef Elf32_Addr Elf32_Conflict; + #define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ + #define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS + block offset. */ ++#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */ + /* Keep this the last entry. */ +-#define R_390_NUM 61 ++#define R_390_NUM 62 + + + /* CRIS relocations. */ +diff --git a/sysdeps/s390/dl-irel.h b/sysdeps/s390/dl-irel.h +new file mode 100644 +index 0000000..bc1a10e +--- /dev/null ++++ b/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 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 ++ . */ ++ ++#ifndef _DL_IREL_H ++#define _DL_IREL_H ++ ++#include ++#include ++#include ++ ++#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 (__builtin_expect (r_type == R_390_IRELATIVE, 1)) ++ { ++ 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/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h +index 3eb7e41..e56ad67 100644 +--- a/sysdeps/s390/s390-32/dl-machine.h ++++ b/sysdeps/s390/s390-32/dl-machine.h +@@ -1,6 +1,5 @@ + /* Machine-dependent ELF dynamic relocation inline functions. S390 Version. +- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2011 +- Free Software Foundation, Inc. ++ Copyright (C) 2000-2012 Free Software Foundation, Inc. + Contributed by Carl Pederson & Martin Schwidefsky. + This file is part of the GNU C Library. + +@@ -27,6 +26,7 @@ + #include + #include + #include ++#include + + /* This is an older, now obsolete value. */ + #define EM_S390_OLD 0xA390 +@@ -305,8 +305,21 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, + 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 (__builtin_expect (!skip_ifunc, 1)) ++ 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; +@@ -444,6 +457,13 @@ elf_machine_lazy_rel (struct link_map *map, + map->l_mach.plt + + (((Elf32_Addr) reloc_addr) - map->l_mach.gotplt) * 8; + } ++ else if (__builtin_expect (r_type == R_390_IRELATIVE, 1)) ++ { ++ Elf32_Addr value = map->l_addr + reloc->r_addend; ++ if (__builtin_expect (!skip_ifunc, 1)) ++ value = elf_ifunc_invoke (value); ++ *reloc_addr = value; ++ } + else + _dl_reloc_bad_type (map, r_type, 1); + } +diff --git a/sysdeps/s390/s390-32/memcmp.S b/sysdeps/s390/s390-32/memcmp.S +new file mode 100644 +index 0000000..9ff84a3 +--- /dev/null ++++ b/sysdeps/s390/s390-32/memcmp.S +@@ -0,0 +1,66 @@ ++/* memcmp - compare two memory blocks. 32 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++ ++#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_g5) ++#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_g5) ++#else ++END(memcmp) ++libc_hidden_builtin_def (memcmp) ++weak_alias(memcmp, bcmp) ++#endif +diff --git a/sysdeps/s390/s390-32/memcpy.S b/sysdeps/s390/s390-32/memcpy.S +index b2a688e..90cc4cb 100644 +--- a/sysdeps/s390/s390-32/memcpy.S ++++ b/sysdeps/s390/s390-32/memcpy.S +@@ -1,7 +1,6 @@ + /* memcpy - copy a block from source to destination. S/390 version. +- Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. ++ Copyright (C) 2012 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 +@@ -17,42 +16,67 @@ + License along with the GNU C Library; if not, see + . */ + ++ ++#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. */ + +-#include "sysdep.h" +-#include "asm-syntax.h" +- +- .text ++#ifdef USE_MULTIARCH ++ENTRY(memcpy_g5) ++#else + ENTRY(memcpy) +- ltr %r4,%r4 +- jz .L3 +- ahi %r4,-1 # length - 1 +- lr %r1,%r2 # copy destination address +- lr %r5,%r4 +- srl %r5,8 +- ltr %r5,%r5 # < 256 bytes to move ? +- jz .L1 +- chi %r5,255 # > 1MB to move ? +- jh .L4 +-.L0: mvc 0(256,%r1),0(%r3) # move in 256 byte chunks +- la %r1,256(%r1) +- la %r3,256(%r3) +- brct %r5,.L0 +-.L1: bras %r5,.L2 # setup base pointer for execute +- mvc 0(1,%r1),0(%r3) # instruction for execute +-.L2: ex %r4,0(%r5) # execute mvc with length ((%r4)&255)+1 +-.L3: br %r14 +- # data copies > 1MB are faster with mvcle. +-.L4: ahi %r4,1 # length + 1 +- lr %r5,%r4 # source length +- lr %r4,%r3 # source address +- lr %r3,%r5 # destination length = source length +-.L5: mvcle %r2,%r4,0 # thats it, MVCLE is your friend +- jo .L5 +- lr %r2,%r1 # return destination address +- br %r14 ++#endif ++ .machine "g5" ++ st %r13,52(%r15) ++ .cfi_offset 13, -44 ++ basr %r13,0 ++.L_G5_16: ++ ltr %r4,%r4 ++ je .L_G5_4 ++ ahi %r4,-1 ++ lr %r5,%r4 ++ srl %r5,8 ++ ltr %r5,%r5 ++ lr %r1,%r2 ++ jne .L_G5_12 ++ ex %r4,.L_G5_17-.L_G5_16(%r13) ++.L_G5_4: ++ l %r13,52(%r15) ++ br %r14 ++.L_G5_13: ++ chi %r5,4096 # Switch to mvcle for copies >1MB ++ 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 ++ ex %r4,.L_G5_17-.L_G5_16(%r13) ++ j .L_G5_4 ++.L_G5_17: ++ mvc 0(1,%r1),0(%r3) ++#ifdef USE_MULTIARCH ++END(memcpy_g5) ++#else + END(memcpy) + libc_hidden_builtin_def (memcpy) ++#endif ++ ++ENTRY(memcpy_mvcle) ++ # Using as standalone function will result in unexpected ++ # results since the length field is incremented by 1 in order to ++ # compensate the changes already done in the functions above. ++ ahi %r4,1 # length + 1 ++ lr %r5,%r4 # source length ++ lr %r4,%r3 # source address ++ lr %r3,%r5 # destination length = source length ++.L_MVCLE_1: ++ mvcle %r2,%r4,0 # thats it, MVCLE is your friend ++ jo .L_MVCLE_1 ++ lr %r2,%r1 # return destination address ++ br %r14 ++END(memcpy_mvcle) +diff --git a/sysdeps/s390/s390-32/memset.S b/sysdeps/s390/s390-32/memset.S +index 00e9082..31a70f0 100644 +--- a/sysdeps/s390/s390-32/memset.S ++++ b/sysdeps/s390/s390-32/memset.S +@@ -1,7 +1,6 @@ + /* Set a block of memory to some byte value. For IBM S390 +- Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. ++ Copyright (C) 2012 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 +@@ -17,28 +16,50 @@ + License along with the GNU C Library; if not, see + . */ + +-/* +- * R2 = address to memory area +- * R3 = byte to fill memory with +- * R4 = number of bytes to fill +- */ + + #include "sysdep.h" + #include "asm-syntax.h" + +- .text ++/* 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_g5) ++#else + ENTRY(memset) +- ltr %r4,%r4 +- jz .L1 +- 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 ++#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_g5) ++#else + END(memset) + libc_hidden_builtin_def (memset) ++#endif +diff --git a/sysdeps/s390/s390-32/multiarch/Makefile b/sysdeps/s390/s390-32/multiarch/Makefile +new file mode 100644 +index 0000000..5b0cd49 +--- /dev/null ++++ b/sysdeps/s390/s390-32/multiarch/Makefile +@@ -0,0 +1,9 @@ ++ASFLAGS-.o += -Wa,-mzarch ++ASFLAGS-.os += -Wa,-mzarch ++ASFLAGS-.op += -Wa,-mzarch ++ASFLAGS-.og += -Wa,-mzarch ++ASFLAGS-.ob += -Wa,-mzarch ++ASFLAGS-.oS += -Wa,-mzarch ++ifeq ($(subdir),string) ++sysdep_routines += ifunc-resolve memset memcpy memcmp ++endif +diff --git a/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c b/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c +new file mode 100644 +index 0000000..fd6e367 +--- /dev/null ++++ b/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c +@@ -0,0 +1,69 @@ ++/* IFUNC resolver function for CPU specific functions. ++ 32 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++#include ++#include ++ ++#define STFLE_BITS_Z10 34 /* General instructions extension */ ++#define STFLE_BITS_Z196 45 /* Distinct operands, pop ... */ ++ ++#ifndef NOT_IN_libc ++ ++#define IFUNC_RESOLVE(FUNC) \ ++ asm (".globl " #FUNC "\n\t" \ ++ ".type " #FUNC ",@gnu_indirect_function\n\t" \ ++ ".set " #FUNC ",resolve_" #FUNC "\n\t" \ ++ ".globl __GI_" #FUNC "\n\t" \ ++ ".set __GI_" #FUNC "," #FUNC "\n"); \ ++ \ ++ extern void *FUNC##_z10; \ ++ extern void *FUNC##_z196; \ ++ extern void *FUNC##_g5; \ ++ \ ++ void *resolve_##FUNC (unsigned long int dl_hwcap) \ ++ { \ ++ if ((dl_hwcap & HWCAP_S390_STFLE) \ ++ && (dl_hwcap & HWCAP_S390_HIGH_GPRS)) /* Implies zarch */ \ ++ { \ ++ /* We want just 1 double word to be returned. */ \ ++ register unsigned long reg0 asm("0") = 0; \ ++ unsigned long long stfle_bits; \ ++ \ ++ asm volatile(".insn s,0xb2b00000,%0" "\n\t" /* stfle */ \ ++ : "=QS" (stfle_bits), "+d" (reg0) \ ++ : : "cc"); \ ++ \ ++ if ((stfle_bits & (1ULL << (63 - STFLE_BITS_Z196))) != 0) \ ++ return &FUNC##_z196; \ ++ else if ((stfle_bits & (1ULL << (63 - STFLE_BITS_Z10))) != 0) \ ++ return &FUNC##_z10; \ ++ } \ ++ return &FUNC##_g5; \ ++ } ++ ++IFUNC_RESOLVE(memset) ++IFUNC_RESOLVE(memcmp) ++asm(".weak bcmp ; bcmp = memcmp"); ++ ++/* In the static lib memcpy is needed before the reloc is resolved. */ ++#ifdef SHARED ++IFUNC_RESOLVE(memcpy) ++#endif ++ ++#endif +diff --git a/sysdeps/s390/s390-32/multiarch/memcmp.S b/sysdeps/s390/s390-32/multiarch/memcmp.S +new file mode 100644 +index 0000000..cd8ea86 +--- /dev/null ++++ b/sysdeps/s390/s390-32/multiarch/memcmp.S +@@ -0,0 +1,102 @@ ++/* CPU specific memcmp implementations. 32 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++ ++#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 ++ ++#ifndef NOT_IN_libc ++ ++ENTRY(memcmp_z196) ++ .machine "z196" ++ 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" ++ 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 ++ ++#include "../memcmp.S" ++ ++#ifdef NOT_IN_libc ++.globl memcmp ++.set memcmp,memcmp_g5 ++.weak bcmp ++.set bcmp,memcmp_g5 ++#endif +diff --git a/sysdeps/s390/s390-32/multiarch/memcpy.S b/sysdeps/s390/s390-32/multiarch/memcpy.S +new file mode 100644 +index 0000000..40f4acf +--- /dev/null ++++ b/sysdeps/s390/s390-32/multiarch/memcpy.S +@@ -0,0 +1,96 @@ ++/* CPU specific memcpy implementations. 32 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++ ++#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 && !defined NOT_IN_libc ++ ++ENTRY(memcpy_z196) ++ .machine "z196" ++ llgfr %r4,%r4 ++ ltgr %r4,%r4 ++ je .L_Z196_4 ++ aghi %r4,-1 ++ lr %r1,%r2 ++ srlg %r5,%r4,8 ++ ltgr %r5,%r5 ++ jne .L_Z196_5 ++.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(memcpy_z10) ++ .machine "z10" ++ llgfr %r4,%r4 ++ cgije %r4,0,.L_Z10_4 ++ aghi %r4,-1 ++ lr %r1,%r2 ++ srlg %r5,%r4,8 ++ cgijlh %r5,0,.L_Z10_13 ++.L_Z10_3: ++ 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) ++ ++#endif ++ ++#include "../memcpy.S" ++ ++#if !defined SHARED || defined NOT_IN_libc ++.globl memcpy ++.set memcpy,memcpy_g5 ++#endif +diff --git a/sysdeps/s390/s390-32/multiarch/memset.S b/sysdeps/s390/s390-32/multiarch/memset.S +new file mode 100644 +index 0000000..5ce7b4d +--- /dev/null ++++ b/sysdeps/s390/s390-32/multiarch/memset.S +@@ -0,0 +1,111 @@ ++/* Set a block of memory to some byte value. 32 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++ ++#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 ++ ++#ifndef NOT_IN_libc ++ ++ENTRY(memset_z196) ++ .machine "z196" ++ 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" ++ 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 ++ ++#include "../memset.S" ++ ++#ifdef NOT_IN_libc ++.globl memset ++.set memset,memset_g5 ++#endif +diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h +index 908c024..067336e 100644 +--- a/sysdeps/s390/s390-64/dl-machine.h ++++ b/sysdeps/s390/s390-64/dl-machine.h +@@ -1,6 +1,6 @@ + /* Machine-dependent ELF dynamic relocation inline functions. + 64 bit S/390 Version. +- Copyright (C) 2001-2005, 2006, 2011 Free Software Foundation, Inc. ++ Copyright (C) 2001-2012 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + +@@ -26,6 +26,9 @@ + #include + #include + #include ++#include ++ ++#define ELF_MACHINE_IRELATIVE R_390_IRELATIVE + + /* This is an older, now obsolete value. */ + #define EM_S390_OLD 0xA390 +@@ -280,8 +283,21 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, + 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 (__builtin_expect (!skip_ifunc, 1)) ++ 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; +@@ -426,6 +442,13 @@ elf_machine_lazy_rel (struct link_map *map, + map->l_mach.plt + + (((Elf64_Addr) reloc_addr) - map->l_mach.gotplt) * 4; + } ++ else if (__builtin_expect (r_type == R_390_IRELATIVE, 1)) ++ { ++ Elf64_Addr value = map->l_addr + reloc->r_addend; ++ if (__builtin_expect (!skip_ifunc, 1)) ++ value = elf_ifunc_invoke (value); ++ *reloc_addr = value; ++ } + else + _dl_reloc_bad_type (map, r_type, 1); + } +diff --git a/sysdeps/s390/s390-64/memcmp.S b/sysdeps/s390/s390-64/memcmp.S +new file mode 100644 +index 0000000..e0b62e3 +--- /dev/null ++++ b/sysdeps/s390/s390-64/memcmp.S +@@ -0,0 +1,64 @@ ++/* memcmp - compare two memory blocks. 64 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++ ++#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_z900) ++#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_z900) ++#else ++END(memcmp) ++libc_hidden_builtin_def (memcmp) ++weak_alias (memcmp, bcmp) ++#endif +diff --git a/sysdeps/s390/s390-64/memcpy.S b/sysdeps/s390/s390-64/memcpy.S +index be916fe..1e5f050 100644 +--- a/sysdeps/s390/s390-64/memcpy.S ++++ b/sysdeps/s390/s390-64/memcpy.S +@@ -1,7 +1,6 @@ + /* memcpy - copy a block from source to destination. 64 bit S/390 version. +- Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. ++ Copyright (C) 2012 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 +@@ -17,41 +16,66 @@ + License along with the GNU C Library; if not, see + . */ + ++ ++#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. */ + +-#include "sysdep.h" +-#include "asm-syntax.h" + +- .text ++ .text ++ ++#ifdef USE_MULTIARCH ++ENTRY(memcpy_z900) ++#else + ENTRY(memcpy) +- ltgr %r4,%r4 +- jz .L3 +- aghi %r4,-1 # length - 1 +- lgr %r1,%r2 # copy destination address +- srlg %r5,%r4,8 +- ltgr %r5,%r5 # < 256 bytes to mvoe ? +- jz .L1 +- chi %r5,255 # > 1 MB to move ? +- jh .L4 +-.L0: mvc 0(256,%r1),0(%r3) # move in 256 byte chunks +- la %r1,256(%r1) +- la %r3,256(%r3) +- brctg %r5,.L0 +-.L1: bras %r5,.L2 # setup base pointer for execute +- mvc 0(1,%r1),0(%r3) # instruction for execute +-.L2: ex %r4,0(%r5) # execute mvc with length ((%r4)&255)+1 +-.L3: br %r14 +- # data copies > 1MB are faster with mvcle. +-.L4: aghi %r4,1 # length + 1 +- lgr %r5,%r4 # source length +- lgr %r4,%r3 # source address +- lgr %r3,%r5 # destination length = source length +-.L5: mvcle %r2,%r4,0 # thats it, MVCLE is your friend +- jo .L5 +- lgr %r2,%r1 # return destination address +- br %r14 ++#endif ++ .machine "z900" ++ ltgr %r4,%r4 ++ je .L_Z900_4 ++ aghi %r4,-1 ++ srlg %r5,%r4,8 ++ ltgr %r5,%r5 ++ lgr %r1,%r2 ++ jne .L_Z900_13 ++.L_Z900_3: ++ larl %r5,.L_Z900_15 ++ ex %r4,0(%r5) ++.L_Z900_4: ++ br %r14 ++.L_Z900_13: ++ chi %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) ++ ++#ifdef USE_MULTIARCH ++END(memcpy_z900) ++#else + END(memcpy) + libc_hidden_builtin_def (memcpy) ++#endif ++ ++ENTRY(memcpy_mvcle) ++ # Using as standalone function will result in unexpected ++ # results since the length field is incremented by 1 in order to ++ # compensate the changes already done in the functions above. ++ aghi %r4,1 # length + 1 ++ lgr %r5,%r4 # source length ++ lgr %r4,%r3 # source address ++ lgr %r3,%r5 # destination length = source length ++.L_MVCLE_1: ++ mvcle %r2,%r4,0 # thats it, MVCLE is your friend ++ jo .L_MVCLE_1 ++ lgr %r2,%r1 # return destination address ++ br %r14 ++END(memcpy_mvcle) +diff --git a/sysdeps/s390/s390-64/memset.S b/sysdeps/s390/s390-64/memset.S +index 03a77ee..6b3007b 100644 +--- a/sysdeps/s390/s390-64/memset.S ++++ b/sysdeps/s390/s390-64/memset.S +@@ -17,27 +17,48 @@ + License along with the GNU C Library; if not, see + . */ + ++ ++#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. */ + +-#include "sysdep.h" +-#include "asm-syntax.h" ++ .text + +- .text ++#ifdef USE_MULTIARCH ++ENTRY(memset_z900) ++#else + ENTRY(memset) +- ltgr %r4,%r4 +- jz .L1 +- lgr %r0,%r2 # save source address +- lgr %r1,%r3 # move pad byte to R1 +- lgr %r3,%r4 +- 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 ++#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_z900) ++#else + END(memset) + libc_hidden_builtin_def (memset) ++#endif +diff --git a/sysdeps/s390/s390-64/multiarch/Makefile b/sysdeps/s390/s390-64/multiarch/Makefile +new file mode 100644 +index 0000000..9baeecd +--- /dev/null ++++ b/sysdeps/s390/s390-64/multiarch/Makefile +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),string) ++sysdep_routines += ifunc-resolve memset memcpy memcmp ++endif +diff --git a/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c b/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c +new file mode 100644 +index 0000000..f980bc9 +--- /dev/null ++++ b/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c +@@ -0,0 +1,74 @@ ++/* IFUNC resolver function for CPU specific functions. ++ 64 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++#include ++#include ++ ++#define STFLE_BITS_Z10 34 /* General instructions extension */ ++#define STFLE_BITS_Z196 45 /* Distinct operands, pop ... */ ++ ++#ifndef NOT_IN_libc ++ ++#define IFUNC_RESOLVE(FUNC) \ ++ asm (".globl " #FUNC "\n\t" \ ++ ".type " #FUNC ",@gnu_indirect_function\n\t" \ ++ ".set " #FUNC ",resolve_" #FUNC "\n\t" \ ++ ".globl __GI_" #FUNC "\n\t" \ ++ ".set __GI_" #FUNC "," #FUNC "\n"); \ ++ \ ++ extern void *FUNC##_z10; \ ++ extern void *FUNC##_z196; \ ++ extern void *FUNC##_z900; \ ++ \ ++ void *resolve_##FUNC (unsigned long int dl_hwcap) \ ++ { \ ++ if (dl_hwcap & HWCAP_S390_STFLE) \ ++ { \ ++ /* We want just 1 double word to be returned. */ \ ++ register unsigned long reg0 asm("0") = 0; \ ++ unsigned long stfle_bits; \ ++ \ ++ asm volatile(".machine push" "\n\t" \ ++ ".machine \"z9-109\"" "\n\t" \ ++ "stfle %0" "\n\t" \ ++ ".machine pop" "\n" \ ++ : "=QS" (stfle_bits), "+d" (reg0) \ ++ : : "cc"); \ ++ \ ++ if ((stfle_bits & (1UL << (63 - STFLE_BITS_Z196))) != 0) \ ++ return &FUNC##_z196; \ ++ else if ((stfle_bits & (1UL << (63 - STFLE_BITS_Z10))) != 0) \ ++ return &FUNC##_z10; \ ++ else \ ++ return &FUNC##_z900; \ ++ } \ ++ else \ ++ return &FUNC##_z900; \ ++ } ++ ++IFUNC_RESOLVE(memset) ++IFUNC_RESOLVE(memcmp) ++asm(".weak bcmp ; bcmp = memcmp"); ++ ++/* In the static lib memcpy is needed before the reloc is resolved. */ ++#ifdef SHARED ++IFUNC_RESOLVE(memcpy) ++#endif ++ ++#endif +diff --git a/sysdeps/s390/s390-64/multiarch/memcmp.S b/sysdeps/s390/s390-64/multiarch/memcmp.S +new file mode 100644 +index 0000000..f40a3c1 +--- /dev/null ++++ b/sysdeps/s390/s390-64/multiarch/memcmp.S +@@ -0,0 +1,101 @@ ++/* CPU specific memcmp implementations. 64 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++ ++#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 ++ ++#ifndef NOT_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 ++ ++#include "../memcmp.S" ++ ++#ifdef NOT_IN_libc ++.globl memcmp ++.set memcmp,memcmp_z900 ++.weak bcmp ++.set bcmp,memcmp_z900 ++#endif +diff --git a/sysdeps/s390/s390-64/multiarch/memcpy.S b/sysdeps/s390/s390-64/multiarch/memcpy.S +new file mode 100644 +index 0000000..b00ffc1 +--- /dev/null ++++ b/sysdeps/s390/s390-64/multiarch/memcpy.S +@@ -0,0 +1,94 @@ ++/* CPU specific memcpy implementations. 64 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++ ++#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 && !defined NOT_IN_libc ++ ++ENTRY(memcpy_z196) ++ .machine "z196" ++ ltgr %r4,%r4 ++ je .L_Z196_4 ++ aghi %r4,-1 ++ lgr %r1,%r2 ++ 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(memcpy_z10) ++ .machine "z10" ++ cgije %r4,0,.L_Z10_4 ++ aghi %r4,-1 ++ lgr %r1,%r2 ++ srlg %r5,%r4,8 ++ cgijlh %r5,0,.L_Z10_13 ++.L_Z10_3: ++ 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) ++ ++#endif ++ ++#include "../memcpy.S" ++ ++#if !defined SHARED || defined NOT_IN_libc ++.globl memcpy ++.set memcpy,memcpy_z900 ++#endif +diff --git a/sysdeps/s390/s390-64/multiarch/memset.S b/sysdeps/s390/s390-64/multiarch/memset.S +new file mode 100644 +index 0000000..1f9064d +--- /dev/null ++++ b/sysdeps/s390/s390-64/multiarch/memset.S +@@ -0,0 +1,109 @@ ++/* Set a block of memory to some byte value. 64 bit S/390 version. ++ Copyright (C) 2012 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 ++ . */ ++ ++ ++#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 ++ ++#ifndef NOT_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 ++ ++#include "../memset.S" ++ ++#ifdef NOT_IN_libc ++.globl memset ++.set memset,memset_z900 ++#endif +commit 511fa2864a8d01a09b23a6b8b9a599429b7055f6 +Author: Andreas Krebbel +Date: Mon Sep 3 14:06:27 2012 +0200 + + S/390: Make IFUNC optimized mem* functions hidden. + +2012-09-03 Andreas Krebbel + + * sysdeps/s390/s390-32/multiarch/ifunc-resolve.c + (IFUNC_RESOLVE): Make pointers to the specialized implementations + hidden. + * sysdeps/s390/s390-64/multiarch/ifunc-resolve.c: Likewise. + +diff --git a/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c b/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c +index fd6e367..6a86c03 100644 +--- a/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c ++++ b/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c +@@ -32,9 +32,11 @@ + ".globl __GI_" #FUNC "\n\t" \ + ".set __GI_" #FUNC "," #FUNC "\n"); \ + \ +- extern void *FUNC##_z10; \ +- extern void *FUNC##_z196; \ +- extern void *FUNC##_g5; \ ++ /* Make the declarations of the optimized functions hidden in order ++ to prevent GOT slots being generated for them. */ \ ++ extern __attribute__((visibility("hidden"))) void *FUNC##_z196; \ ++ extern __attribute__((visibility("hidden"))) void *FUNC##_z10; \ ++ extern __attribute__((visibility("hidden"))) void *FUNC##_g5; \ + \ + void *resolve_##FUNC (unsigned long int dl_hwcap) \ + { \ +diff --git a/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c b/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c +index f980bc9..5f56764 100644 +--- a/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c ++++ b/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c +@@ -32,9 +32,11 @@ + ".globl __GI_" #FUNC "\n\t" \ + ".set __GI_" #FUNC "," #FUNC "\n"); \ + \ +- extern void *FUNC##_z10; \ +- extern void *FUNC##_z196; \ +- extern void *FUNC##_z900; \ ++ /* Make the declarations of the optimized functions hidden in order ++ to prevent GOT slots being generated for them. */ \ ++ extern __attribute__((visibility("hidden"))) void *FUNC##_z196; \ ++ extern __attribute__((visibility("hidden"))) void *FUNC##_z10; \ ++ extern __attribute__((visibility("hidden"))) void *FUNC##_z900; \ + \ + void *resolve_##FUNC (unsigned long int dl_hwcap) \ + { \ diff --git a/glibc.spec b/glibc.spec index 503ebf8..8c9f8f4 100644 --- a/glibc.spec +++ b/glibc.spec @@ -28,7 +28,7 @@ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 11%{?dist} +Release: 12%{?dist} # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries. # Things that are linked directly into dynamically linked programs # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional @@ -111,7 +111,7 @@ Patch0034: %{name}-rh841318.patch # Patch1035: %{name}-rh845960.patch Patch1037: %{name}-rh849203.patch - +Patch1038: %{name}-rh805093.patch # # Patches submitted, but not yet approved upstream. @@ -430,6 +430,7 @@ rm -rf %{glibcportsdir} %patch1035 -p1 %patch2036 -p1 %patch1037 -p1 +%patch1038 -p1 # On powerpc32, hp timing is only available in power4/power6 # libs, not in base, so pre-power4 dynamic linker is incompatible @@ -1306,6 +1307,9 @@ rm -f *.filelist* %endif %changelog +* Tue Sep 4 2012 Jeff Law - 2.16-12 + - Pick up s390/s390x IFUNC support. + * Tue Aug 21 2012 Jeff Law - 2.16-11 - Replace manual systemd scriptlets with macroized scriptlets (#850129)