about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure10
-rw-r--r--configure.in7
-rw-r--r--nptl/ChangeLog3
-rw-r--r--nptl/DESIGN-barrier.txt2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h14
-rw-r--r--sysdeps/powerpc/powerpc64/configure68
-rw-r--r--sysdeps/powerpc/powerpc64/configure.in42
-rw-r--r--sysdeps/powerpc/powerpc64/dl-machine.h79
-rw-r--r--sysdeps/powerpc/powerpc64/sysdep.h201
11 files changed, 292 insertions, 151 deletions
diff --git a/ChangeLog b/ChangeLog
index 703e89b683..e108e01ef7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2004-09-07  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/powerpc/powerpc64/configure.in: New file.
+	* config.h.in (USE_PPC64_OVERLAPPING_OPD): Add.
+	* configure.in (HAVE_ASM_GLOBAL_DOT_NAME): Remove.
+	* sysdeps/powerpc/powerpc64/sysdep.h: Formatting.
+	(OPD_ENT, BODY_LABEL, ENTRY_1, ENTRY_2, END_2, DOT_PREFIX,
+	BODY_PREFIX): Define.
+	(ENTRY, DOT_LABEL, END, TRACEBACK, END_GEN_TB, EALIGN): Support
+	HAVE_ASM_GLOBAL_DOT_NAME or no dot symbols,
+	USE_PPC64_OVERLAPPING_OPD or never overlapping .opd entries.
+	* sysdeps/powerpc/powerpc64/dl-machine.h: Include sysdep.h.
+	(TRAMPOLINE_TEMPLATE, RTLD_START): Use the new sysdep.h macros.
+
 2004-09-07  Ulrich Drepper  <drepper@redhat.com>
 
 	* malloc/malloc.h: Don't define __THROW if it is already defined.
diff --git a/config.h.in b/config.h.in
index c02d691883..bd990c6627 100644
--- a/config.h.in
+++ b/config.h.in
@@ -61,6 +61,9 @@
 /* Define a symbol_name as a global .symbol_name for ld.  */
 #undef	HAVE_ASM_GLOBAL_DOT_NAME
 
+/* On powerpc64, use overlapping .opd entries.  */
+#undef  USE_PPC64_OVERLAPPING_OPD
+
 /* Define if the assembler generates debugging information directly.  */
 #undef	HAVE_CPP_ASM_DEBUGINFO
 
diff --git a/configure b/configure
index 985118daa5..625d507715 100755
--- a/configure
+++ b/configure
@@ -5031,16 +5031,6 @@ _ACEOF
 
 fi
 
-# The Aix ld uses global .symbol_names instead of symbol_names.
-# Unfortunately also used in the PPC64 ELF ABI.
-case "${os}${machine}" in
-aix4.3* | linux*powerpc/powerpc64*)
-  cat >>confdefs.h <<\_ACEOF
-#define HAVE_ASM_GLOBAL_DOT_NAME 1
-_ACEOF
-
-esac
-
 echo "$as_me:$LINENO: checking for .symver assembler directive" >&5
 echo $ECHO_N "checking for .symver assembler directive... $ECHO_C" >&6
 if test "${libc_cv_asm_symver_directive+set}" = set; then
diff --git a/configure.in b/configure.in
index 3941aba967..24e6cb948f 100644
--- a/configure.in
+++ b/configure.in
@@ -1030,13 +1030,6 @@ if test "x$libc_cv_asm_type_prefix" != xno; then
   AC_DEFINE_UNQUOTED(ASM_TYPE_DIRECTIVE_PREFIX, ${libc_cv_asm_type_prefix})
 fi
 
-# The Aix ld uses global .symbol_names instead of symbol_names.
-# Unfortunately also used in the PPC64 ELF ABI.
-case "${os}${machine}" in
-aix4.3* | linux*powerpc/powerpc64*)
-  AC_DEFINE(HAVE_ASM_GLOBAL_DOT_NAME)
-esac
-
 AC_CACHE_CHECK(for .symver assembler directive, libc_cv_asm_symver_directive,
 [cat > conftest.s <<EOF
 ${libc_cv_dot_text}
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 6857273d9c..f382a0080c 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,5 +1,8 @@
 2004-09-07  Ulrich Drepper  <drepper@redhat.com>
 
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Allow
+	PSEUDO to be used with . prefix.
+
 	* sysdeps/unix/sysv/linux/alpha/pthread_once.c (__pthread_once):
 	Use atomic_increment instead of atomic_exchange_and_add.
 	* sysdeps/unix/sysv/linux/sparc/pthread_once.c (__pthread_once):
diff --git a/nptl/DESIGN-barrier.txt b/nptl/DESIGN-barrier.txt
index b0fbf14fb1..23463c6b7e 100644
--- a/nptl/DESIGN-barrier.txt
+++ b/nptl/DESIGN-barrier.txt
@@ -37,7 +37,7 @@ pthread_barrier_wait(barrier_t *barrier)
     } while (event == barrier->curr_event);
   }
 
-  if (atomic_exchange_and_add (barrier->left, 1) == barrier->init_count - 1)
+  if (atomic_increment_val (barrier->left) == barrier->init_count)
     lll_unlock(barrier->lock);
 
   return result;
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
index aa993b9a58..226aaafdce 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
@@ -26,6 +26,12 @@
 
 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
 
+# ifdef HAVE_ASM_GLOBAL_DOT_NAME
+#  define DASHDASHPFX(str) .__##str
+# else
+#  define DASHDASHPFX(str) __##str
+# endif
+
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				\
   .section ".text";							\
@@ -33,12 +39,12 @@
     cfi_startproc;							\
     SINGLE_THREAD_P;							\
     bne- .Lpseudo_cancel;						\
-  .type .__##syscall_name##_nocancel,@function;				\
-  .globl .__##syscall_name##_nocancel;					\
-  .__##syscall_name##_nocancel:						\
+  .type DASHDASHPFX(syscall_name##_nocancel),@function;			\
+  .globl DASHDASHPFX(syscall_name##_nocancel);				\
+  DASHDASHPFX(syscall_name##_nocancel):					\
     DO_CALL (SYS_ify (syscall_name));					\
     PSEUDO_RET;								\
-  .size .__##syscall_name##_nocancel,.-.__##syscall_name##_nocancel;	\
+  .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel);	\
   .Lpseudo_cancel:							\
     stdu 1,-128(1);							\
     cfi_adjust_cfa_offset (128);					\
diff --git a/sysdeps/powerpc/powerpc64/configure b/sysdeps/powerpc/powerpc64/configure
new file mode 100644
index 0000000000..9075a5c8c4
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/configure
@@ -0,0 +1,68 @@
+# This file is generated from configure.in by Autoconf.  DO NOT EDIT!
+ # Local configure fragment for sysdeps/powerpc/powerpc64.
+
+# The Aix ld uses global .symbol_names instead of symbol_names
+# and unfortunately early Linux PPC64 linkers use it as well.
+echo "$as_me:$LINENO: checking for support for omitting dot symbols" >&5
+echo $ECHO_N "checking for support for omitting dot symbols... $ECHO_C" >&6
+if test "${libc_cv_omit_dot_syms+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  libc_cv_omit_dot_syms=no
+echo 'void foo (void) {}' > conftest.c
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S conftest.c -o conftest.s 1>&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  if grep -w '\.foo' conftest.s > /dev/null; then
+    :
+  else
+    libc_cv_omit_dot_syms=yes
+  fi
+fi
+rm -f conftest.c conftest.s
+
+fi
+echo "$as_me:$LINENO: result: $libc_cv_omit_dot_syms" >&5
+echo "${ECHO_T}$libc_cv_omit_dot_syms" >&6
+if test x$libc_cv_omit_dot_syms != xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_ASM_GLOBAL_DOT_NAME 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for linker support for overlapping .opd entries" >&5
+echo $ECHO_N "checking for linker support for overlapping .opd entries... $ECHO_C" >&6
+if test "${libc_cv_overlapping_opd+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  libc_cv_overlapping_opd=no
+echo 'void foo (void) {}' > conftest.c
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S conftest.c -o conftest.s 1>&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  if grep '\.TOC\.@tocbase' conftest.s > /dev/null; then
+    if grep '\.TOC\.@tocbase[ 	]*,[ 	]*0' conftest.s > /dev/null; then
+      :
+    else
+      libc_cv_overlapping_opd=yes
+    fi
+  fi
+fi
+rm -f conftest.c conftest.s
+
+fi
+echo "$as_me:$LINENO: result: $libc_cv_overlapping_opd" >&5
+echo "${ECHO_T}$libc_cv_overlapping_opd" >&6
+if test x$libc_cv_overlapping_opd = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define USE_PPC64_OVERLAPPING_OPD 1
+_ACEOF
+
+fi
diff --git a/sysdeps/powerpc/powerpc64/configure.in b/sysdeps/powerpc/powerpc64/configure.in
new file mode 100644
index 0000000000..67aac663d8
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/configure.in
@@ -0,0 +1,42 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/powerpc/powerpc64.
+
+# The Aix ld uses global .symbol_names instead of symbol_names
+# and unfortunately early Linux PPC64 linkers use it as well.
+AC_CACHE_CHECK(for support for omitting dot symbols,
+libc_cv_omit_dot_syms, [dnl
+libc_cv_omit_dot_syms=no
+echo 'void foo (void) {}' > conftest.c
+if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
+  if grep -w '\.foo' conftest.s > /dev/null; then
+    :
+  else
+    libc_cv_omit_dot_syms=yes
+  fi
+fi
+rm -f conftest.c conftest.s
+])
+if test x$libc_cv_omit_dot_syms != xyes; then
+  AC_DEFINE(HAVE_ASM_GLOBAL_DOT_NAME)
+fi
+
+AC_CACHE_CHECK(for linker support for overlapping .opd entries,
+libc_cv_overlapping_opd, [dnl
+libc_cv_overlapping_opd=no
+echo 'void foo (void) {}' > conftest.c
+if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
+changequote(,)dnl
+  if grep '\.TOC\.@tocbase' conftest.s > /dev/null; then
+    if grep '\.TOC\.@tocbase[ 	]*,[ 	]*0' conftest.s > /dev/null; then
+      :
+    else
+      libc_cv_overlapping_opd=yes
+    fi
+  fi
+changequote([,])dnl
+fi
+rm -f conftest.c conftest.s
+])
+if test x$libc_cv_overlapping_opd = xyes; then
+  AC_DEFINE(USE_PPC64_OVERLAPPING_OPD)
+fi
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index bcaa20049d..3fcf77df71 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -27,6 +27,7 @@
 #include <assert.h>
 #include <sys/param.h>
 #include <dl-tls.h>
+#include <sysdep.h>
 
 /* Translate a processor specific dynamic tag to the index
    in l_info array.  */
@@ -117,16 +118,15 @@ elf_machine_dynamic (void)
 #define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
   asm (".section \".text\"\n"						\
 "	.align	2\n"							\
-"	.globl	." #tramp_name "\n"					\
-"	.type	." #tramp_name ",@function\n"				\
+"	.type	" BODY_PREFIX #tramp_name ",@function\n"		\
 "	.section \".opd\",\"aw\"\n"					\
 "	.align	3\n"							\
 "	.globl	" #tramp_name "\n"					\
-"	.size	" #tramp_name ",24\n"					\
+"	" ENTRY_2(tramp_name) "\n"					\
 #tramp_name ":\n"							\
-"	.quad	." #tramp_name ",.TOC.@tocbase,0\n"			\
+"	" OPD_ENT(tramp_name) "\n"					\
 "	.previous\n"							\
-"." #tramp_name ":\n"							\
+BODY_PREFIX #tramp_name ":\n"						\
 /* We need to save the registers used to pass parameters, ie. r3 thru	\
    r10; the registers are saved in a stack frame.  */			\
 "	stdu	1,-128(1)\n"						\
@@ -141,14 +141,14 @@ elf_machine_dynamic (void)
 "	std	7,80(1)\n"						\
 "	mflr	0\n"							\
 "	std	8,88(1)\n"						\
-/* Store the LR in the LR Save area of the previous frame.  */    \
+/* Store the LR in the LR Save area of the previous frame.  */    	\
 "	std	0,128+16(1)\n"						\
 "	mfcr	0\n"							\
 "	std	9,96(1)\n"						\
 "	std	10,104(1)\n"						\
-/* I'm almost certain we don't have to save cr...  be safe.  */    \
+/* I'm almost certain we don't have to save cr...  be safe.  */    	\
 "	std	0,8(1)\n"						\
-"	bl	." #fixup_name "\n"					\
+"	bl	" DOT_PREFIX #fixup_name "\n"				\
 /* Put the registers back.  */						\
 "	ld	0,128+16(1)\n"						\
 "	ld	10,104(1)\n"						\
@@ -174,13 +174,13 @@ elf_machine_dynamic (void)
 ".LT_" #tramp_name ":\n"						\
 "	.long 0\n"							\
 "	.byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n"		\
-"	.long .LT_" #tramp_name "-."#tramp_name "\n"			\
+"	.long .LT_" #tramp_name "-" BODY_PREFIX #tramp_name "\n"	\
 "	.short .LT_" #tramp_name "_name_end-.LT_" #tramp_name "_name_start\n" \
 ".LT_" #tramp_name "_name_start:\n"					\
 "	.ascii \"" #tramp_name "\"\n"					\
 ".LT_" #tramp_name "_name_end:\n"					\
 "	.align 2\n"							\
-"	.size	." #tramp_name ",. - ." #tramp_name "\n"		\
+"	" END_2(tramp_name) "\n"					\
 "	.previous");
 
 #ifndef PROF
@@ -210,16 +210,15 @@ elf_machine_dynamic (void)
 #define RTLD_START \
   asm (".section \".text\"\n"						\
 "	.align	2\n"							\
-"	.globl	._start\n"						\
-"	.type	._start,@function\n"					\
+"	.type	" BODY_PREFIX "_start,@function\n"			\
 "	.section \".opd\",\"aw\"\n"					\
 "	.align	3\n"							\
 "	.globl	_start\n"						\
-"	.size	_start,24\n"						\
+"	" ENTRY_2(_start) "\n"						\
 "_start:\n"								\
-"	.quad	._start,.TOC.@tocbase,0\n"				\
+"	" OPD_ENT(_start) "\n"						\
 "	.previous\n"							\
-"._start:\n"								\
+BODY_PREFIX "_start:\n"							\
 /* We start with the following on the stack, from top:			\
    argc (4 bytes);							\
    arguments for program (terminated by NULL);				\
@@ -229,24 +228,24 @@ elf_machine_dynamic (void)
 "	li	4,0\n"							\
 "	stdu	4,-128(1)\n"						\
 /* Call _dl_start with one parameter pointing at argc.  */		\
-"	bl	._dl_start\n"						\
+"	bl	" DOT_PREFIX "_dl_start\n"				\
 "	nop\n"								\
 /* Transfer control to _dl_start_user!  */				\
-"	b	._dl_start_user\n"					\
-".LT__start:\n"  \
-"	.long 0\n"      \
+"	b	" DOT_PREFIX "_dl_start_user\n"				\
+".LT__start:\n"								\
+"	.long 0\n"							\
 "	.byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n"		\
-"	.long .LT__start-._start\n"					\
+"	.long .LT__start-" BODY_PREFIX "_start\n"			\
 "	.short .LT__start_name_end-.LT__start_name_start\n"		\
 ".LT__start_name_start:\n"						\
 "	.ascii \"_start\"\n"						\
 ".LT__start_name_end:\n"						\
 "	.align 2\n"							\
-"	.size	._start,.-._start\n"					\
+"	" END_2(_start) "\n"						\
 "	.globl	_dl_start_user\n"					\
 "	.section \".opd\",\"aw\"\n"					\
 "_dl_start_user:\n"							\
-"	.quad	._dl_start_user, .TOC.@tocbase, 0\n"			\
+"	" OPD_ENT(_dl_start_user) "\n"					\
 "	.previous\n"							\
 "	.section	\".toc\",\"aw\"\n"				\
 DL_STARTING_UP_DEF							\
@@ -259,20 +258,20 @@ DL_STARTING_UP_DEF							\
 ".LC__dl_fini:\n"							\
 "	.tc _dl_fini[TC],_dl_fini\n"					\
 "	.previous\n"							\
-"	.globl	._dl_start_user\n"					\
-"	.type	._dl_start_user,@function\n"				\
-/* Now, we do our main work of calling initialisation procedures.  \
-   The ELF ABI doesn't say anything about parameters for these,  \
-   so we just pass argc, argv, and the environment.  \
-   Changing these is strongly discouraged (not least because argc is  \
-   passed by value!).  */  \
-"._dl_start_user:\n"  \
+"	.type	" BODY_PREFIX "_dl_start_user,@function\n"		\
+"	" ENTRY_2(_dl_start_user) "\n"					\
+/* Now, we do our main work of calling initialisation procedures.	\
+   The ELF ABI doesn't say anything about parameters for these,		\
+   so we just pass argc, argv, and the environment.			\
+   Changing these is strongly discouraged (not least because argc is	\
+   passed by value!).  */						\
+BODY_PREFIX "_dl_start_user:\n"						\
 /* the address of _start in r30.  */					\
 "	mr	30,3\n"							\
 /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28.  */		\
-"	ld	28,.LC__rtld_global@toc(2)\n"    \
-"	ld	29,.LC__dl_argc@toc(2)\n"					\
-"	ld	27,.LC__dl_argv@toc(2)\n"					\
+"	ld	28,.LC__rtld_global@toc(2)\n"				\
+"	ld	29,.LC__dl_argc@toc(2)\n"				\
+"	ld	27,.LC__dl_argv@toc(2)\n"				\
 /* _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1).  */	\
 "	ld	3,0(28)\n"						\
 "	lwa	4,0(29)\n"						\
@@ -280,7 +279,7 @@ DL_STARTING_UP_DEF							\
 "	sldi	6,4,3\n"						\
 "	add	6,5,6\n"						\
 "	addi	6,6,8\n"						\
-"	bl	._dl_init\n"						\
+"	bl	" DOT_PREFIX "_dl_init\n"				\
 "	nop\n"								\
 /* Now, to conform to the ELF ABI, we have to:				\
    Pass argc (actually _dl_argc) in r3;  */				\
@@ -305,7 +304,7 @@ DL_STARTING_UP_DEF							\
    linked statically, which linux will call with argc on top of the	\
    stack which will hopefully never be zero, and a dynamically linked	\
    program which will always have a NULL on the top of the stack.	\
-   Take the opportunity to clear LR, so anyone who accidentally  \
+   Take the opportunity to clear LR, so anyone who accidentally		\
    returns from _start gets SEGV.  Also clear the next few words of	\
    the stack.  */							\
 "	li	31,0\n"							\
@@ -315,23 +314,23 @@ DL_STARTING_UP_DEF							\
 "	std	31,16(1)\n"						\
 "	std	31,24(1)\n"						\
 /* Now, call the start function descriptor at r30...  */		\
-"	.globl	._dl_main_dispatch\n"  \
-"._dl_main_dispatch:\n"  \
+"	.globl	._dl_main_dispatch\n"					\
+"._dl_main_dispatch:\n"							\
 "	ld	0,0(30)\n"						\
 "	ld	2,8(30)\n"						\
 "	mtctr	0\n"							\
 "	ld	11,16(30)\n"						\
 "	bctr\n"								\
-".LT__dl_start_user:\n"	\
+".LT__dl_start_user:\n"							\
 "	.long 0\n"							\
 "	.byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n"		\
-"	.long .LT__dl_start_user-._dl_start_user\n"			\
+"	.long .LT__dl_start_user-" BODY_PREFIX "_dl_start_user\n"	\
 "	.short .LT__dl_start_user_name_end-.LT__dl_start_user_name_start\n" \
 ".LT__dl_start_user_name_start:\n"					\
 "	.ascii \"_dl_start_user\"\n"					\
 ".LT__dl_start_user_name_end:\n"					\
 "	.align 2\n"							\
-"	.size	._dl_start_user,.-._dl_start_user\n"			\
+"	" END_2(_dl_start_user) "\n"					\
 "	.previous");
 
 /* Nonzero iff TYPE should not be allowed to resolve to one of
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index 29c1c2c36c..4420a6dfac 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -1,5 +1,5 @@
 /* Assembly macros for 64-bit PowerPC.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 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
@@ -19,9 +19,10 @@
 
 #include <sysdeps/powerpc/sysdep.h>
 
+#ifdef __ELF__
+
 #ifdef __ASSEMBLER__
 
-#ifdef __ELF__
 /* If compiled for profiling, call `_mcount' at the start of each function.
    see ppc-mcount.S for more details.  */
 #ifdef	PROF
@@ -29,48 +30,70 @@
    to locate our caller and so it can restore it; so store one just
    for its benefit.  */
 #ifdef SYSV_ELF_PROFILING
-#define CALL_MCOUNT      \
-  .pushsection;          \
-  .section ".data";      \
-  .align ALIGNARG(2);    \
-__mcount:            \
-  .long  0;            \
-  .previous;              \
-	.section	".toc","aw";  \
-.LC__mcount:; \
-	.tc __mcount[TC],__mcount; \
-  .previous;              \
-  mflr  r0;              \
-  std   r0,16(r1);        \
-  ld    r0,.LC__mcount@toc(r2);    \
+#define CALL_MCOUNT	\
+  .pushsection;			\
+  .section ".data";		\
+  .align ALIGNARG(2);		\
+__mcount:			\
+  .long  0;			\
+  .previous;			\
+  .section ".toc","aw";		\
+.LC__mcount:;			\
+  .tc __mcount[TC],__mcount;	\
+  .previous;			\
+  mflr  r0;			\
+  std   r0,16(r1);		\
+  ld    r0,.LC__mcount@toc(r2);	\
   bl    JUMPTARGET(_mcount);
 #else /* SYSV_ELF_PROFILING */
-#define CALL_MCOUNT      \
-  mflr  r0;              \
-  std   r0,16(r1);       \
+#define CALL_MCOUNT	\
+  mflr  r0;			\
+  std   r0,16(r1);		\
   bl    JUMPTARGET(_mcount);
 #endif /* SYSV_ELF_PROFILING */
 #else  /* PROF */
 #define CALL_MCOUNT		/* Do nothing.  */
 #endif /* PROF */
 
-#define DOT_LABEL(X) .##X
+#ifdef USE_PPC64_OVERLAPPING_OPD
+# define OPD_ENT(name)	.quad BODY_LABEL (name), .TOC.@tocbase
+#else
+# define OPD_ENT(name)	.quad BODY_LABEL (name), .TOC.@tocbase, 0
+#endif
 
-#define ENTRY(name)	\
-	.section	".text"; \
-	.align ALIGNARG(2); \
-	.globl DOT_LABEL(name); \
-	.type DOT_LABEL(name),@function ; \
-	.globl name; \
-	.section	".opd","aw"; \
-	.align 3; \
-	.size name,24; \
-name##: ; \
-	.quad DOT_LABEL(name) ; \
-	.quad .TOC.@tocbase, 0; \
-	.previous; \
-DOT_LABEL(name):
+#define ENTRY_1(name)	\
+	.section	".text";		\
+	.type BODY_LABEL(name),@function;	\
+	.globl name;				\
+	.section ".opd","aw";			\
+	.align 3;				\
+name##: OPD_ENT (name);				\
+	.previous;
+
+#ifdef HAVE_ASM_GLOBAL_DOT_NAME
+# define DOT_LABEL(X) .##X
+# define BODY_LABEL(X) .##X
+# define ENTRY_2(name)	\
+	.globl BODY_LABEL(name);		\
+	ENTRY_1(name)				\
+	.size name, 24;
+# define END_2(name)	\
+	.size BODY_LABEL(name),.-BODY_LABEL(name);
+#else
+# define DOT_LABEL(X) X
+# define BODY_LABEL(X) .LY##X
+# define ENTRY_2(name)	\
+	.type name,@function;			\
+	ENTRY_1(name)
+# define END_2(name)	\
+	.size name,.-BODY_LABEL(name);		\
+	.size BODY_LABEL(name),.-BODY_LABEL(name);
+#endif
 
+#define ENTRY(name)	\
+	ENTRY_2(name)				\
+	.align ALIGNARG(2);			\
+BODY_LABEL(name):
 
 #define EALIGN_W_0  /* No words to insert.  */
 #define EALIGN_W_1  nop
@@ -82,44 +105,24 @@ DOT_LABEL(name):
 #define EALIGN_W_7  EALIGN_W_6;nop
 
 /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
-   past a 2^align boundary.  */
+   past a 2^alignt boundary.  */
 #ifdef PROF
 #define EALIGN(name, alignt, words) \
-	.section	".text"; \
-	.globl DOT_LABEL(name); \
-	.type DOT_LABEL(name),@function ; \
-	.globl name; \
-	.section	".opd","aw"; \
-	.align 3; \
-	.size name,24; \
-name##: ; \
-	.quad DOT_LABEL(name) ; \
-	.quad .TOC.@tocbase, 0; \
-	.previous; \
-	.align ALIGNARG(alignt); \
-  EALIGN_W_##words;	\
-DOT_LABEL(name):		\
-  CALL_MCOUNT  \
-  b 0f; \
-  .align ALIGNARG(alignt); \
-  EALIGN_W_##words; \
-  0:
+	ENTRY_2(name)				\
+	.align ALIGNARG(alignt);		\
+	EALIGN_W_##words;			\
+BODY_LABEL(name):				\
+	CALL_MCOUNT				\
+	b 0f;					\
+	.align ALIGNARG(alignt);		\
+	EALIGN_W_##words;			\
+0:
 #else /* PROF */
 #define EALIGN(name, alignt, words) \
-	.section	".text"; \
-	.globl DOT_LABEL(name); \
-	.type DOT_LABEL(name),@function ; \
-	.globl name; \
-	.section	".opd","aw"; \
-	.align 3; \
-	.size name,24; \
-name##: ; \
-	.quad DOT_LABEL(name) ; \
-	.quad .TOC.@tocbase, 0; \
-	.previous; \
-	.align ALIGNARG(alignt); \
-  EALIGN_W_##words; \
-DOT_LABEL(name):
+	ENTRY_2(name)				\
+	.align ALIGNARG(alignt);		\
+	EALIGN_W_##words;			\
+BODY_LABEL(name):
 #endif
 
 /* Local labels stripped out by the linker.  */
@@ -135,35 +138,35 @@ DOT_LABEL(name):
 
 /* Support Traceback tables */
 #define TB_ASM			0x000c000000000000
-#define TB_GLOBALLINK	0x0000800000000000
+#define TB_GLOBALLINK		0x0000800000000000
 #define TB_IS_EPROL		0x0000400000000000
-#define TB_HAS_TBOFF	0x0000200000000000
+#define TB_HAS_TBOFF		0x0000200000000000
 #define TB_INT_PROC		0x0000100000000000
 #define TB_HAS_CTL		0x0000080000000000
 #define TB_TOCLESS		0x0000040000000000
-#define TB_FP_PRESENT	0x0000020000000000
-#define TB_LOG_ABORT	0x0000010000000000
-#define TB_INT_HANDL	0x0000008000000000
-#define TB_NAME_PRESENT	0x0000004000000000
-#define TB_USES_ALLOCA	0x0000002000000000
+#define TB_FP_PRESENT		0x0000020000000000
+#define TB_LOG_ABORT		0x0000010000000000
+#define TB_INT_HANDL		0x0000008000000000
+#define TB_NAME_PRESENT		0x0000004000000000
+#define TB_USES_ALLOCA		0x0000002000000000
 #define TB_SAVES_CR		0x0000000200000000
 #define TB_SAVES_LR		0x0000000100000000
-#define TB_STORES_BC	0x0000000080000000
+#define TB_STORES_BC		0x0000000080000000
 #define TB_FIXUP		0x0000000040000000
 #define TB_FP_SAVED(fprs)	(((fprs) & 0x3f) << 24)
 #define TB_GPR_SAVED(gprs)	(((fprs) & 0x3f) << 16)
 #define TB_FIXEDPARMS(parms)	(((parms) & 0xff) << 8)
 #define TB_FLOATPARMS(parms)	(((parms) & 0x7f) << 1)
-#define TB_PARMSONSTK	0x0000000000000001
+#define TB_PARMSONSTK		0x0000000000000001
 
-#define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
-#define TB_DEFAULT	TB_ASM | TB_HAS_TBOFF | TB_NAME_PRESENT
+#define PPC_HIGHER(v) 		(((v) >> 32) & 0xffff)
+#define TB_DEFAULT		TB_ASM | TB_HAS_TBOFF | TB_NAME_PRESENT
 
 #define TRACEBACK(name) \
 LT_LABEL(name): ; \
 	.long	0 ; \
 	.quad	TB_DEFAULT ; \
-	.long	LT_LABEL(name)-DOT_LABEL(name) ; \
+	.long	LT_LABEL(name)-BODY_LABEL(name) ; \
 	.short	LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \
 LT_LABELSUFFIX(name,_name_start): ;\
 	.ascii	stringify(name) ; \
@@ -174,7 +177,7 @@ LT_LABELSUFFIX(name,_name_end): ; \
 LT_LABEL(name): ; \
 	.long	0 ; \
 	.quad	TB_DEFAULT | mask ; \
-	.long	LT_LABEL(name)-DOT_LABEL(name) ; \
+	.long	LT_LABEL(name)-BODY_LABEL(name) ; \
 	.short	LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \
 LT_LABELSUFFIX(name,_name_start): ;\
 	.ascii	stringify(name) ; \
@@ -184,14 +187,13 @@ LT_LABELSUFFIX(name,_name_end): ; \
 /* END generates Traceback tables */
 #undef	END
 #define END(name) \
-  TRACEBACK(name)	\
-  ASM_SIZE_DIRECTIVE(DOT_LABEL(name))
+  TRACEBACK(name)		\
+  END_2(name)
 
 /* This form supports more informative traceback tables */
 #define END_GEN_TB(name,mask)	\
   TRACEBACK_MASK(name,mask)	\
-  ASM_SIZE_DIRECTIVE(DOT_LABEL(name))
-
+  END_2(name)
 
 #define DO_CALL(syscall) \
     li 0,syscall; \
@@ -244,10 +246,31 @@ LT_LABELSUFFIX(name,_name_end): ; \
 #define	PSEUDO_END_ERRVAL(name) \
   END (name)
 
-/* Label in text section.  */
-/* ppc64 function descriptors which requires . notation */
-#define C_TEXT(name) .##name
+#else /* !__ASSEMBLER__ */
 
-#endif /* __ELF__ */
+#ifdef USE_PPC64_OVERLAPPING_OPD
+# define OPD_ENT(name)	".quad " BODY_PREFIX #name ", .TOC.@tocbase;"
+#else
+# define OPD_ENT(name)	".quad " BODY_PREFIX #name ", .TOC.@tocbase, 0;"
+#endif
+
+#ifdef HAVE_ASM_GLOBAL_DOT_NAME
+# define DOT_PREFIX "."
+# define BODY_PREFIX "."
+# define ENTRY_2(name)	\
+	".globl " BODY_PREFIX #name ";\n"				\
+	".size  " #name ", 24;"
+# define END_2(name)	\
+	".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";"
+#else
+# define DOT_PREFIX ""
+# define BODY_PREFIX ".LY"
+# define ENTRY_2(name) ".type " #name ",@function;"
+# define END_2(name)	\
+	".size " #name ",.-" BODY_PREFIX #name ";\n"			\
+	".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";"
+#endif
 
 #endif	/* __ASSEMBLER__ */
+
+#endif /* __ELF__ */