summaryrefslogtreecommitdiff
path: root/sysdeps/powerpc/powerpc64
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc/powerpc64')
-rw-r--r--sysdeps/powerpc/powerpc64/dl-machine.h49
-rw-r--r--sysdeps/powerpc/powerpc64/fpu/s_isnan.S57
-rw-r--r--sysdeps/powerpc/powerpc64/fpu/s_isnan.c7
-rw-r--r--sysdeps/powerpc/powerpc64/hp-timing.h6
-rw-r--r--sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S61
-rw-r--r--sysdeps/powerpc/powerpc64/power6/fpu/s_isnan.S60
-rw-r--r--sysdeps/powerpc/powerpc64/power6x/fpu/s_isnan.S59
7 files changed, 269 insertions, 30 deletions
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 89a69e1a23..c837393d79 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -246,30 +246,35 @@ BODY_PREFIX "_dl_start_user:\n" \
" " END_2(_dl_start_user) "\n" \
" .popsection");
-/* Nonzero iff TYPE should not be allowed to resolve to one of
- the main executable's symbols, as for a COPY reloc. */
-#define elf_machine_lookup_noexec_p(type) ((type) == R_PPC64_COPY)
+/* ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to
+ one of the main executable's symbols, as for a COPY reloc.
+
+ To make function pointer comparisons work on most targets, the
+ relevant ABI states that the address of a non-local function in a
+ dynamically linked executable is the address of the PLT entry for
+ that function. This is quite reasonable since using the real
+ function address in a non-PIC executable would typically require
+ dynamic relocations in .text, something to be avoided. For such
+ functions, the linker emits a SHN_UNDEF symbol in the executable
+ with value equal to the PLT entry address. Normally, SHN_UNDEF
+ symbols have a value of zero, so this is a clue to ld.so that it
+ should treat these symbols specially. For relocations not in
+ ELF_RTYPE_CLASS_PLT (eg. those on function pointers), ld.so should
+ use the value of the executable SHN_UNDEF symbol, ie. the PLT entry
+ address. For relocations in ELF_RTYPE_CLASS_PLT (eg. the relocs in
+ the PLT itself), ld.so should use the value of the corresponding
+ defined symbol in the object that defines the function, ie. the
+ real function address. This complicates ld.so in that there are
+ now two possible values for a given symbol, and it gets even worse
+ because protected symbols need yet another set of rules.
+
+ On PowerPC64 we don't need any of this. The linker won't emit
+ SHN_UNDEF symbols with non-zero values. ld.so can make all
+ relocations behave "normally", ie. always use the real address
+ like PLT relocations. So always set ELF_RTYPE_CLASS_PLT. */
-/* Nonzero iff TYPE describes relocation of a PLT entry, so
- PLT entries should not be allowed to define the value. */
-#define elf_machine_lookup_noplt_p(type) ((type) == R_PPC64_JMP_SLOT)
-
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
- PLT entries should not be allowed to define the value.
- ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
- of the main executable's symbols, as for a COPY reloc. */
-
-#if !defined RTLD_BOOTSTRAP || USE___THREAD
-#define elf_machine_type_class(type) \
- /* This covers all the TLS relocs, though most won't appear. */ \
- (((((type) >= R_PPC64_DTPMOD64 && (type) <= R_PPC64_TPREL16_HIGHESTA) \
- || (type) == R_PPC64_ADDR24) * ELF_RTYPE_CLASS_PLT) \
- | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
-#else
#define elf_machine_type_class(type) \
- ((((type) == R_PPC64_ADDR24) * ELF_RTYPE_CLASS_PLT) \
- | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
-#endif
+ (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
#define ELF_MACHINE_JMP_SLOT R_PPC64_JMP_SLOT
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_isnan.S b/sysdeps/powerpc/powerpc64/fpu/s_isnan.S
new file mode 100644
index 0000000000..9963896f2d
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/fpu/s_isnan.S
@@ -0,0 +1,57 @@
+/* isnan(). PowerPC64 version.
+ Copyright (C) 2008 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#include <math_ldbl_opt.h>
+
+/* int __isnan(x) */
+ .machine power4
+EALIGN (__isnan, 4, 0)
+ CALL_MCOUNT 0
+ mffs fp0
+ mtfsb0 4*cr6+lt /* reset_fpscr_bit (FPSCR_VE) */
+ fcmpu cr7,fp1,fp1
+ mtfsf 255,fp0
+ li r3,0
+ beqlr+ cr7 /* (x == x) then not a NAN */
+ li r3,1 /* else must be a NAN */
+ blr
+ END (__isnan)
+
+hidden_def (__isnan)
+weak_alias (__isnan, isnan)
+
+/* It turns out that the 'double' version will also always work for
+ single-precision. */
+strong_alias (__isnan, __isnanf)
+hidden_def (__isnanf)
+weak_alias (__isnanf, isnanf)
+
+#ifdef NO_LONG_DOUBLE
+strong_alias (__isnan, __isnanl)
+weak_alias (__isnan, isnanl)
+#endif
+
+#ifndef IS_IN_libm
+# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0)
+compat_symbol (libc, __isnan, __isnanl, GLIBC_2_0);
+compat_symbol (libc, isnan, isnanl, GLIBC_2_0);
+# endif
+#endif
+
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_isnan.c b/sysdeps/powerpc/powerpc64/fpu/s_isnan.c
deleted file mode 100644
index 397717ba9c..0000000000
--- a/sysdeps/powerpc/powerpc64/fpu/s_isnan.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <sysdeps/powerpc/fpu/s_isnan.c>
-#ifndef IS_IN_libm
-# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0)
-compat_symbol (libc, __isnan, __isnanl, GLIBC_2_0);
-compat_symbol (libc, isnan, isnanl, GLIBC_2_0);
-# endif
-#endif
diff --git a/sysdeps/powerpc/powerpc64/hp-timing.h b/sysdeps/powerpc/powerpc64/hp-timing.h
index b58cca9003..e107a2dd49 100644
--- a/sysdeps/powerpc/powerpc64/hp-timing.h
+++ b/sysdeps/powerpc/powerpc64/hp-timing.h
@@ -1,5 +1,5 @@
/* High precision, low overhead timing functions. powerpc64 version.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -85,7 +85,11 @@ typedef unsigned long long int hp_timing_t;
running in this moment. This could be changed by using a barrier like
'lwsync' right before the `mftb' instruciton. But we are not interested
in accurate clock cycles here so we don't do this. */
+#ifdef _ARCH_PWR4
+#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("mfspr %0,268" : "=r" (Var))
+#else
#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("mftb %0" : "=r" (Var))
+#endif
/* Use two 'mftb' instructions in a row to find out how long it takes.
On current POWER4, POWER5, and 970 processors mftb take ~10 cycles. */
diff --git a/sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S b/sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S
new file mode 100644
index 0000000000..d46d049d45
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S
@@ -0,0 +1,61 @@
+/* isnan(). PowerPC64 version.
+ Copyright (C) 2008 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#include <math_ldbl_opt.h>
+
+/* int __isnan(x) */
+ .machine power5
+EALIGN (__isnan, 4, 0)
+ CALL_MCOUNT 0
+ stfd fp1,-8(r1) /* copy FPR to GPR */
+ lis r0,0x7ff0
+ nop /* insure the following is in a different */
+ nop /* dispatch group */
+ ld r4,-8(r1)
+ sldi r0,r0,32 /* const long r0 0x7ff00000 00000000 */
+ clrldi r4,r4,1 /* x = fabs(x) */
+ cmpd cr7,r4,r0 /* if (fabs(x) <= inf) */
+ li r3,0 /* then return 0 */
+ blelr+ cr7
+ li r3,1 /* else return 1 */
+ blr
+ END (__isnan)
+
+hidden_def (__isnan)
+weak_alias (__isnan, isnan)
+
+/* It turns out that the 'double' version will also always work for
+ single-precision. */
+strong_alias (__isnan, __isnanf)
+hidden_def (__isnanf)
+weak_alias (__isnanf, isnanf)
+
+#ifdef NO_LONG_DOUBLE
+strong_alias (__isnan, __isnanl)
+weak_alias (__isnan, isnanl)
+#endif
+
+#ifndef IS_IN_libm
+# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0)
+compat_symbol (libc, __isnan, __isnanl, GLIBC_2_0);
+compat_symbol (libc, isnan, isnanl, GLIBC_2_0);
+# endif
+#endif
+
diff --git a/sysdeps/powerpc/powerpc64/power6/fpu/s_isnan.S b/sysdeps/powerpc/powerpc64/power6/fpu/s_isnan.S
new file mode 100644
index 0000000000..fe0c56ca8e
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power6/fpu/s_isnan.S
@@ -0,0 +1,60 @@
+/* isnan(). PowerPC64 version.
+ Copyright (C) 2008 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#include <math_ldbl_opt.h>
+
+/* int __isnan(x) */
+ .machine power6
+EALIGN (__isnan, 4, 0)
+ CALL_MCOUNT 0
+ stfd fp1,-8(r1) /* copy FPR to GPR */
+ ori r1,r1,0
+ ld r4,-8(r1)
+ lis r0,0x7ff0
+ sldi r0,r0,32 /* const long r0 0x7ff00000 00000000 */
+ clrldi r4,r4,1 /* x = fabs(x) */
+ cmpd cr7,r4,r0 /* if (fabs(x) <= inf) */
+ li r3,0 /* then return 0 */
+ blelr+ cr7
+ li r3,1 /* else return 1 */
+ blr
+ END (__isnan)
+
+hidden_def (__isnan)
+weak_alias (__isnan, isnan)
+
+/* It turns out that the 'double' version will also always work for
+ single-precision. */
+strong_alias (__isnan, __isnanf)
+hidden_def (__isnanf)
+weak_alias (__isnanf, isnanf)
+
+#ifdef NO_LONG_DOUBLE
+strong_alias (__isnan, __isnanl)
+weak_alias (__isnan, isnanl)
+#endif
+
+#ifndef IS_IN_libm
+# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0)
+compat_symbol (libc, __isnan, __isnanl, GLIBC_2_0);
+compat_symbol (libc, isnan, isnanl, GLIBC_2_0);
+# endif
+#endif
+
diff --git a/sysdeps/powerpc/powerpc64/power6x/fpu/s_isnan.S b/sysdeps/powerpc/powerpc64/power6x/fpu/s_isnan.S
new file mode 100644
index 0000000000..47dd49a751
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power6x/fpu/s_isnan.S
@@ -0,0 +1,59 @@
+/* isnan(). PowerPC64 version.
+ Copyright (C) 2008 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#include <math_ldbl_opt.h>
+
+/* int __isnan(x) */
+ .machine power6
+EALIGN (__isnan, 4, 0)
+ CALL_MCOUNT 0
+ mftgpr r4,fp1 /* copy FPR to GPR */
+ lis r0,0x7ff0
+ ori r1,r1,0
+ clrldi r4,r4,1 /* x = fabs(x) */
+ sldi r0,r0,32 /* const long r0 0x7ff00000 00000000 */
+ cmpd cr7,r4,r0 /* if (fabs(x) <= inf) */
+ li r3,0 /* then return 0 */
+ blelr+ cr7
+ li r3,1 /* else return 1 */
+ blr
+ END (__isnan)
+
+hidden_def (__isnan)
+weak_alias (__isnan, isnan)
+
+/* It turns out that the 'double' version will also always work for
+ single-precision. */
+strong_alias (__isnan, __isnanf)
+hidden_def (__isnanf)
+weak_alias (__isnanf, isnanf)
+
+#ifdef NO_LONG_DOUBLE
+strong_alias (__isnan, __isnanl)
+weak_alias (__isnan, isnanl)
+#endif
+
+#ifndef IS_IN_libm
+# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0)
+compat_symbol (libc, __isnan, __isnanl, GLIBC_2_0);
+compat_symbol (libc, isnan, isnanl, GLIBC_2_0);
+# endif
+#endif
+