about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>2013-03-28 16:28:56 -0500
committerAdhemerval Zanella <azanella@linux.vnet.ibm.com>2013-03-28 16:28:56 -0500
commit254d12ecfcaff6f3240447269c5c4da7a7798a0a (patch)
treea745956fef1ba44a1269da850bef27baf1d3baef
parent1ef83476d0aacae4ee0d2fd07aca2868cb1cdbcb (diff)
downloadglibc-254d12ecfcaff6f3240447269c5c4da7a7798a0a.tar.gz
glibc-254d12ecfcaff6f3240447269c5c4da7a7798a0a.tar.xz
glibc-254d12ecfcaff6f3240447269c5c4da7a7798a0a.zip
PowerPC: strnlen ifunc using C
-rw-r--r--sysdeps/powerpc/powerpc32/multiarch/init-arch.h17
-rw-r--r--sysdeps/powerpc/powerpc32/multiarch/strnlen.S70
-rw-r--r--sysdeps/powerpc/powerpc32/multiarch/strnlen.c36
3 files changed, 52 insertions, 71 deletions
diff --git a/sysdeps/powerpc/powerpc32/multiarch/init-arch.h b/sysdeps/powerpc/powerpc32/multiarch/init-arch.h
index 17f870807a..a1b20eb870 100644
--- a/sysdeps/powerpc/powerpc32/multiarch/init-arch.h
+++ b/sysdeps/powerpc/powerpc32/multiarch/init-arch.h
@@ -17,5 +17,20 @@
 
 #include <ldsodefs.h>
 
+/* The code checks if _rtld_global_ro was realocated before trying to access
+   the dl_hwcap field. The assembly is to make the compiler not optimize the
+   test (&_rtld_global_ro != NULL), which is always true in ISO C (but not
+   in that case since _rtld_global_ro might not been realocated yet.).  */
+#if defined(SHARED) && !defined(IS_IN_rtld)
+# define __GLRO(value) \
+  ({ volatile void **__p = (volatile void**)(&_rtld_global_ro);	\
+     unsigned long int __ret;					\
+     asm ("# x in %0" : "+r" (__p));				\
+     __ret = (__p) ? GLRO(value) : 0;				\
+     __ret; })
+#else
+# define __GLRO(value)  GLRO(value)
+#endif 
+
 # define INIT_ARCH() \
-  unsigned long int hwcap = GLRO(dl_hwcap);
+  unsigned long int hwcap = __GLRO(dl_hwcap);
diff --git a/sysdeps/powerpc/powerpc32/multiarch/strnlen.S b/sysdeps/powerpc/powerpc32/multiarch/strnlen.S
deleted file mode 100644
index 1b3f46eaf1..0000000000
--- a/sysdeps/powerpc/powerpc32/multiarch/strnlen.S
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (C) 2013 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 <rtld-global-offsets.h>
-
-/* Define multiple versions only for the definition in libc.  */
-#ifndef NOT_IN_libc
-	.text
-ENTRY(__strnlen)
-	.type   __strnlen, @gnu_indirect_function
-# ifdef PIC
-	mflr	r6
-	cfi_register (lr,r6)
-	SETUP_GOT_ACCESS (r5,got_label)
-	addis	r5,r5,_GLOBAL_OFFSET_TABLE_-got_label@ha
-	addi	r5,r5,_GLOBAL_OFFSET_TABLE_-got_label@l
-	mtlr	r6
-	cfi_same_value (lr)
-#  ifdef SHARED
-	lwz	r6,_rtld_global_ro@got(r5)
-	/* If _rtld_global_ro is not initialized use the default ppc32
-	   implementation.  */
-	cmplwi  r6,0
-	beq	L(ppc32)
-	lwz	r6,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r6)
-#  else
-	lwz     r6,_dl_hwcap@got(r5)
-	lwz	r6,4(r6)
-#  endif
-# else /* PIC  */
-	lis	r6,(_dl_hwcap+4)@ha
-	lwz	r6,(_dl_hwcap+4)@l(r6)
-# endif
-	andi.	r7,r6,PPC_FEATURE_HAS_VSX
-	bne	L(power7)
-L(ppc32):
-# ifdef PIC
-	lwz	r3,__strnlen_ppc32@got(r5)
-# else
-	lis	r3,__strnlen_ppc32@ha
-	lwz	r3,__strnlen_ppc32@l(r3)
-# endif
-	blr
-L(power7):
-# ifdef PIC
-	lwz	r3,__strnlen_power7@got(r5)
-# else
-	lis	r3,__strnlen_power7@ha
-	lwz	r3,__strnlen_power7@l(r3)
-# endif
-	blr
-END(__strnlen)
-
-weak_alias (__strnlen, strnlen)
-#endif
diff --git a/sysdeps/powerpc/powerpc32/multiarch/strnlen.c b/sysdeps/powerpc/powerpc32/multiarch/strnlen.c
new file mode 100644
index 0000000000..0fb946010d
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/multiarch/strnlen.c
@@ -0,0 +1,36 @@
+/* Multiple versions of strnlen.
+   Copyright (C) 2013 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 NOT_IN_libc
+# include <string.h>
+# include <shlib-compat.h>
+# include "init-arch.h"
+
+extern __typeof (__strnlen) __strnlen_ppc32 attribute_hidden;
+extern __typeof (__strnlen) __strnlen_power7 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+libc_ifunc (__strnlen,
+	    (hwcap & PPC_FEATURE_HAS_VSX)
+            ? __strnlen_power7
+            : __strnlen_ppc32);
+
+weak_alias (__strnlen, strnlen);
+libc_hidden_def (strnlen)
+#endif