This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch, master, updated. glibc-2.16-ports-merge-57-g08f43f9


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  08f43f9bbf97c03ec4d2754c69fd9d7efce6ef96 (commit)
      from  a98430587c57da2832fa9abe336c5a8f8137e89c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=08f43f9bbf97c03ec4d2754c69fd9d7efce6ef96

commit 08f43f9bbf97c03ec4d2754c69fd9d7efce6ef96
Author: Andreas Krebbel <krebbel@linux.vnet.ibm.com>
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.

diff --git a/ChangeLog b/ChangeLog
index de09a44..3dee64d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2012-07-19  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
+	* 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.
+
 2012-07-17  Marek Polacek  <polacek@redhat.com>
 
 	[BZ #14349]
diff --git a/NEWS b/NEWS
index 3837299..416bf89 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,11 @@ Version 2.17
   6778, 14042, 14151, 14154, 14157, 14173, 14283, 14328, 14331, 14337,
   14347, 14349
 
+* Support for STT_GNU_IFUNC symbols added for s390 and s390x.
+  Optimized versions of memcpy, memset, and memcmp added for System z10 and
+  zEnterprise z196.
+  Implemented by Andreas Krebbel.
+
 
 Version 2.16
 
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
+   <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 (__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 <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
@@ -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
+   <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_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
    <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.  */
 
-#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
    <http://www.gnu.org/licenses/>.  */
 
-/*
- * 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <dl-procinfo.h>
+
+#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
+   <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
+
+#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
+   <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 && !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
+   <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
+
+#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 <sys/param.h>
 #include <string.h>
 #include <link.h>
+#include <dl-irel.h>
+
+#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
+   <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_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
    <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.  */
 
-#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
    <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.  */
 
-#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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <dl-procinfo.h>
+
+#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
+   <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
+
+#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
+   <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 && !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
+   <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
+
+#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

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                      |   26 ++++++
 NEWS                                           |    5 +
 elf/elf.h                                      |    3 +-
 sysdeps/s390/dl-irel.h                         |   52 +++++++++++
 sysdeps/s390/s390-32/dl-machine.h              |   24 +++++-
 sysdeps/s390/s390-32/memcmp.S                  |   66 ++++++++++++++
 sysdeps/s390/s390-32/memcpy.S                  |   90 ++++++++++++-------
 sysdeps/s390/s390-32/memset.S                  |   61 +++++++++----
 sysdeps/s390/s390-32/multiarch/Makefile        |    9 ++
 sysdeps/s390/s390-32/multiarch/ifunc-resolve.c |   69 +++++++++++++++
 sysdeps/s390/s390-32/multiarch/memcmp.S        |  102 ++++++++++++++++++++++
 sysdeps/s390/s390-32/multiarch/memcpy.S        |   96 ++++++++++++++++++++
 sysdeps/s390/s390-32/multiarch/memset.S        |  111 ++++++++++++++++++++++++
 sysdeps/s390/s390-64/dl-machine.h              |   25 +++++-
 sysdeps/s390/s390-64/memcmp.S                  |   64 ++++++++++++++
 sysdeps/s390/s390-64/memcpy.S                  |   86 ++++++++++++-------
 sysdeps/s390/s390-64/memset.S                  |   51 ++++++++---
 sysdeps/s390/s390-64/multiarch/Makefile        |    3 +
 sysdeps/s390/s390-64/multiarch/ifunc-resolve.c |   74 ++++++++++++++++
 sysdeps/s390/s390-64/multiarch/memcmp.S        |  101 +++++++++++++++++++++
 sysdeps/s390/s390-64/multiarch/memcpy.S        |   94 ++++++++++++++++++++
 sysdeps/s390/s390-64/multiarch/memset.S        |  109 +++++++++++++++++++++++
 22 files changed, 1218 insertions(+), 103 deletions(-)
 create mode 100644 sysdeps/s390/dl-irel.h
 create mode 100644 sysdeps/s390/s390-32/memcmp.S
 create mode 100644 sysdeps/s390/s390-32/multiarch/Makefile
 create mode 100644 sysdeps/s390/s390-32/multiarch/ifunc-resolve.c
 create mode 100644 sysdeps/s390/s390-32/multiarch/memcmp.S
 create mode 100644 sysdeps/s390/s390-32/multiarch/memcpy.S
 create mode 100644 sysdeps/s390/s390-32/multiarch/memset.S
 create mode 100644 sysdeps/s390/s390-64/memcmp.S
 create mode 100644 sysdeps/s390/s390-64/multiarch/Makefile
 create mode 100644 sysdeps/s390/s390-64/multiarch/ifunc-resolve.c
 create mode 100644 sysdeps/s390/s390-64/multiarch/memcmp.S
 create mode 100644 sysdeps/s390/s390-64/multiarch/memcpy.S
 create mode 100644 sysdeps/s390/s390-64/multiarch/memset.S


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]