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.
This commit is contained in:
Ulrich Drepper 2004-09-08 07:02:28 +00:00
parent 67254a97d9
commit 590b40f7ec
11 changed files with 292 additions and 151 deletions

View File

@ -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> 2004-09-07 Ulrich Drepper <drepper@redhat.com>
* malloc/malloc.h: Don't define __THROW if it is already defined. * malloc/malloc.h: Don't define __THROW if it is already defined.

View File

@ -61,6 +61,9 @@
/* Define a symbol_name as a global .symbol_name for ld. */ /* Define a symbol_name as a global .symbol_name for ld. */
#undef HAVE_ASM_GLOBAL_DOT_NAME #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. */ /* Define if the assembler generates debugging information directly. */
#undef HAVE_CPP_ASM_DEBUGINFO #undef HAVE_CPP_ASM_DEBUGINFO

10
configure vendored
View File

@ -5031,16 +5031,6 @@ _ACEOF
fi 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 "$as_me:$LINENO: checking for .symver assembler directive" >&5
echo $ECHO_N "checking for .symver assembler directive... $ECHO_C" >&6 echo $ECHO_N "checking for .symver assembler directive... $ECHO_C" >&6
if test "${libc_cv_asm_symver_directive+set}" = set; then if test "${libc_cv_asm_symver_directive+set}" = set; then

View File

@ -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}) AC_DEFINE_UNQUOTED(ASM_TYPE_DIRECTIVE_PREFIX, ${libc_cv_asm_type_prefix})
fi 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, AC_CACHE_CHECK(for .symver assembler directive, libc_cv_asm_symver_directive,
[cat > conftest.s <<EOF [cat > conftest.s <<EOF
${libc_cv_dot_text} ${libc_cv_dot_text}

View File

@ -1,5 +1,8 @@
2004-09-07 Ulrich Drepper <drepper@redhat.com> 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): * sysdeps/unix/sysv/linux/alpha/pthread_once.c (__pthread_once):
Use atomic_increment instead of atomic_exchange_and_add. Use atomic_increment instead of atomic_exchange_and_add.
* sysdeps/unix/sysv/linux/sparc/pthread_once.c (__pthread_once): * sysdeps/unix/sysv/linux/sparc/pthread_once.c (__pthread_once):

View File

@ -37,7 +37,7 @@ pthread_barrier_wait(barrier_t *barrier)
} while (event == barrier->curr_event); } 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); lll_unlock(barrier->lock);
return result; return result;

View File

@ -26,6 +26,12 @@
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt #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 # undef PSEUDO
# define PSEUDO(name, syscall_name, args) \ # define PSEUDO(name, syscall_name, args) \
.section ".text"; \ .section ".text"; \
@ -33,12 +39,12 @@
cfi_startproc; \ cfi_startproc; \
SINGLE_THREAD_P; \ SINGLE_THREAD_P; \
bne- .Lpseudo_cancel; \ bne- .Lpseudo_cancel; \
.type .__##syscall_name##_nocancel,@function; \ .type DASHDASHPFX(syscall_name##_nocancel),@function; \
.globl .__##syscall_name##_nocancel; \ .globl DASHDASHPFX(syscall_name##_nocancel); \
.__##syscall_name##_nocancel: \ DASHDASHPFX(syscall_name##_nocancel): \
DO_CALL (SYS_ify (syscall_name)); \ DO_CALL (SYS_ify (syscall_name)); \
PSEUDO_RET; \ PSEUDO_RET; \
.size .__##syscall_name##_nocancel,.-.__##syscall_name##_nocancel; \ .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel); \
.Lpseudo_cancel: \ .Lpseudo_cancel: \
stdu 1,-128(1); \ stdu 1,-128(1); \
cfi_adjust_cfa_offset (128); \ cfi_adjust_cfa_offset (128); \

68
sysdeps/powerpc/powerpc64/configure vendored Normal file
View File

@ -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

View File

@ -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

View File

@ -27,6 +27,7 @@
#include <assert.h> #include <assert.h>
#include <sys/param.h> #include <sys/param.h>
#include <dl-tls.h> #include <dl-tls.h>
#include <sysdep.h>
/* Translate a processor specific dynamic tag to the index /* Translate a processor specific dynamic tag to the index
in l_info array. */ in l_info array. */
@ -117,16 +118,15 @@ elf_machine_dynamic (void)
#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \ #define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
asm (".section \".text\"\n" \ asm (".section \".text\"\n" \
" .align 2\n" \ " .align 2\n" \
" .globl ." #tramp_name "\n" \ " .type " BODY_PREFIX #tramp_name ",@function\n" \
" .type ." #tramp_name ",@function\n" \
" .section \".opd\",\"aw\"\n" \ " .section \".opd\",\"aw\"\n" \
" .align 3\n" \ " .align 3\n" \
" .globl " #tramp_name "\n" \ " .globl " #tramp_name "\n" \
" .size " #tramp_name ",24\n" \ " " ENTRY_2(tramp_name) "\n" \
#tramp_name ":\n" \ #tramp_name ":\n" \
" .quad ." #tramp_name ",.TOC.@tocbase,0\n" \ " " OPD_ENT(tramp_name) "\n" \
" .previous\n" \ " .previous\n" \
"." #tramp_name ":\n" \ BODY_PREFIX #tramp_name ":\n" \
/* We need to save the registers used to pass parameters, ie. r3 thru \ /* We need to save the registers used to pass parameters, ie. r3 thru \
r10; the registers are saved in a stack frame. */ \ r10; the registers are saved in a stack frame. */ \
" stdu 1,-128(1)\n" \ " stdu 1,-128(1)\n" \
@ -141,14 +141,14 @@ elf_machine_dynamic (void)
" std 7,80(1)\n" \ " std 7,80(1)\n" \
" mflr 0\n" \ " mflr 0\n" \
" std 8,88(1)\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" \ " std 0,128+16(1)\n" \
" mfcr 0\n" \ " mfcr 0\n" \
" std 9,96(1)\n" \ " std 9,96(1)\n" \
" std 10,104(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" \ " std 0,8(1)\n" \
" bl ." #fixup_name "\n" \ " bl " DOT_PREFIX #fixup_name "\n" \
/* Put the registers back. */ \ /* Put the registers back. */ \
" ld 0,128+16(1)\n" \ " ld 0,128+16(1)\n" \
" ld 10,104(1)\n" \ " ld 10,104(1)\n" \
@ -174,13 +174,13 @@ elf_machine_dynamic (void)
".LT_" #tramp_name ":\n" \ ".LT_" #tramp_name ":\n" \
" .long 0\n" \ " .long 0\n" \
" .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\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" \ " .short .LT_" #tramp_name "_name_end-.LT_" #tramp_name "_name_start\n" \
".LT_" #tramp_name "_name_start:\n" \ ".LT_" #tramp_name "_name_start:\n" \
" .ascii \"" #tramp_name "\"\n" \ " .ascii \"" #tramp_name "\"\n" \
".LT_" #tramp_name "_name_end:\n" \ ".LT_" #tramp_name "_name_end:\n" \
" .align 2\n" \ " .align 2\n" \
" .size ." #tramp_name ",. - ." #tramp_name "\n" \ " " END_2(tramp_name) "\n" \
" .previous"); " .previous");
#ifndef PROF #ifndef PROF
@ -210,16 +210,15 @@ elf_machine_dynamic (void)
#define RTLD_START \ #define RTLD_START \
asm (".section \".text\"\n" \ asm (".section \".text\"\n" \
" .align 2\n" \ " .align 2\n" \
" .globl ._start\n" \ " .type " BODY_PREFIX "_start,@function\n" \
" .type ._start,@function\n" \
" .section \".opd\",\"aw\"\n" \ " .section \".opd\",\"aw\"\n" \
" .align 3\n" \ " .align 3\n" \
" .globl _start\n" \ " .globl _start\n" \
" .size _start,24\n" \ " " ENTRY_2(_start) "\n" \
"_start:\n" \ "_start:\n" \
" .quad ._start,.TOC.@tocbase,0\n" \ " " OPD_ENT(_start) "\n" \
" .previous\n" \ " .previous\n" \
"._start:\n" \ BODY_PREFIX "_start:\n" \
/* We start with the following on the stack, from top: \ /* We start with the following on the stack, from top: \
argc (4 bytes); \ argc (4 bytes); \
arguments for program (terminated by NULL); \ arguments for program (terminated by NULL); \
@ -229,24 +228,24 @@ elf_machine_dynamic (void)
" li 4,0\n" \ " li 4,0\n" \
" stdu 4,-128(1)\n" \ " stdu 4,-128(1)\n" \
/* Call _dl_start with one parameter pointing at argc. */ \ /* Call _dl_start with one parameter pointing at argc. */ \
" bl ._dl_start\n" \ " bl " DOT_PREFIX "_dl_start\n" \
" nop\n" \ " nop\n" \
/* Transfer control to _dl_start_user! */ \ /* Transfer control to _dl_start_user! */ \
" b ._dl_start_user\n" \ " b " DOT_PREFIX "_dl_start_user\n" \
".LT__start:\n" \ ".LT__start:\n" \
" .long 0\n" \ " .long 0\n" \
" .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\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" \ " .short .LT__start_name_end-.LT__start_name_start\n" \
".LT__start_name_start:\n" \ ".LT__start_name_start:\n" \
" .ascii \"_start\"\n" \ " .ascii \"_start\"\n" \
".LT__start_name_end:\n" \ ".LT__start_name_end:\n" \
" .align 2\n" \ " .align 2\n" \
" .size ._start,.-._start\n" \ " " END_2(_start) "\n" \
" .globl _dl_start_user\n" \ " .globl _dl_start_user\n" \
" .section \".opd\",\"aw\"\n" \ " .section \".opd\",\"aw\"\n" \
"_dl_start_user:\n" \ "_dl_start_user:\n" \
" .quad ._dl_start_user, .TOC.@tocbase, 0\n" \ " " OPD_ENT(_dl_start_user) "\n" \
" .previous\n" \ " .previous\n" \
" .section \".toc\",\"aw\"\n" \ " .section \".toc\",\"aw\"\n" \
DL_STARTING_UP_DEF \ DL_STARTING_UP_DEF \
@ -259,20 +258,20 @@ DL_STARTING_UP_DEF \
".LC__dl_fini:\n" \ ".LC__dl_fini:\n" \
" .tc _dl_fini[TC],_dl_fini\n" \ " .tc _dl_fini[TC],_dl_fini\n" \
" .previous\n" \ " .previous\n" \
" .globl ._dl_start_user\n" \ " .type " BODY_PREFIX "_dl_start_user,@function\n" \
" .type ._dl_start_user,@function\n" \ " " ENTRY_2(_dl_start_user) "\n" \
/* Now, we do our main work of calling initialisation procedures. \ /* Now, we do our main work of calling initialisation procedures. \
The ELF ABI doesn't say anything about parameters for these, \ The ELF ABI doesn't say anything about parameters for these, \
so we just pass argc, argv, and the environment. \ so we just pass argc, argv, and the environment. \
Changing these is strongly discouraged (not least because argc is \ Changing these is strongly discouraged (not least because argc is \
passed by value!). */ \ passed by value!). */ \
"._dl_start_user:\n" \ BODY_PREFIX "_dl_start_user:\n" \
/* the address of _start in r30. */ \ /* the address of _start in r30. */ \
" mr 30,3\n" \ " mr 30,3\n" \
/* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ \ /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ \
" ld 28,.LC__rtld_global@toc(2)\n" \ " ld 28,.LC__rtld_global@toc(2)\n" \
" ld 29,.LC__dl_argc@toc(2)\n" \ " ld 29,.LC__dl_argc@toc(2)\n" \
" ld 27,.LC__dl_argv@toc(2)\n" \ " ld 27,.LC__dl_argv@toc(2)\n" \
/* _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1). */ \ /* _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1). */ \
" ld 3,0(28)\n" \ " ld 3,0(28)\n" \
" lwa 4,0(29)\n" \ " lwa 4,0(29)\n" \
@ -280,7 +279,7 @@ DL_STARTING_UP_DEF \
" sldi 6,4,3\n" \ " sldi 6,4,3\n" \
" add 6,5,6\n" \ " add 6,5,6\n" \
" addi 6,6,8\n" \ " addi 6,6,8\n" \
" bl ._dl_init\n" \ " bl " DOT_PREFIX "_dl_init\n" \
" nop\n" \ " nop\n" \
/* Now, to conform to the ELF ABI, we have to: \ /* Now, to conform to the ELF ABI, we have to: \
Pass argc (actually _dl_argc) in r3; */ \ 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 \ linked statically, which linux will call with argc on top of the \
stack which will hopefully never be zero, and a dynamically linked \ stack which will hopefully never be zero, and a dynamically linked \
program which will always have a NULL on the top of the stack. \ 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 \ returns from _start gets SEGV. Also clear the next few words of \
the stack. */ \ the stack. */ \
" li 31,0\n" \ " li 31,0\n" \
@ -315,23 +314,23 @@ DL_STARTING_UP_DEF \
" std 31,16(1)\n" \ " std 31,16(1)\n" \
" std 31,24(1)\n" \ " std 31,24(1)\n" \
/* Now, call the start function descriptor at r30... */ \ /* Now, call the start function descriptor at r30... */ \
" .globl ._dl_main_dispatch\n" \ " .globl ._dl_main_dispatch\n" \
"._dl_main_dispatch:\n" \ "._dl_main_dispatch:\n" \
" ld 0,0(30)\n" \ " ld 0,0(30)\n" \
" ld 2,8(30)\n" \ " ld 2,8(30)\n" \
" mtctr 0\n" \ " mtctr 0\n" \
" ld 11,16(30)\n" \ " ld 11,16(30)\n" \
" bctr\n" \ " bctr\n" \
".LT__dl_start_user:\n" \ ".LT__dl_start_user:\n" \
" .long 0\n" \ " .long 0\n" \
" .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\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" \ " .short .LT__dl_start_user_name_end-.LT__dl_start_user_name_start\n" \
".LT__dl_start_user_name_start:\n" \ ".LT__dl_start_user_name_start:\n" \
" .ascii \"_dl_start_user\"\n" \ " .ascii \"_dl_start_user\"\n" \
".LT__dl_start_user_name_end:\n" \ ".LT__dl_start_user_name_end:\n" \
" .align 2\n" \ " .align 2\n" \
" .size ._dl_start_user,.-._dl_start_user\n" \ " " END_2(_dl_start_user) "\n" \
" .previous"); " .previous");
/* Nonzero iff TYPE should not be allowed to resolve to one of /* Nonzero iff TYPE should not be allowed to resolve to one of

View File

@ -1,5 +1,5 @@
/* Assembly macros for 64-bit PowerPC. /* 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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -19,9 +19,10 @@
#include <sysdeps/powerpc/sysdep.h> #include <sysdeps/powerpc/sysdep.h>
#ifdef __ELF__
#ifdef __ASSEMBLER__ #ifdef __ASSEMBLER__
#ifdef __ELF__
/* If compiled for profiling, call `_mcount' at the start of each function. /* If compiled for profiling, call `_mcount' at the start of each function.
see ppc-mcount.S for more details. */ see ppc-mcount.S for more details. */
#ifdef PROF #ifdef PROF
@ -29,48 +30,70 @@
to locate our caller and so it can restore it; so store one just to locate our caller and so it can restore it; so store one just
for its benefit. */ for its benefit. */
#ifdef SYSV_ELF_PROFILING #ifdef SYSV_ELF_PROFILING
#define CALL_MCOUNT \ #define CALL_MCOUNT \
.pushsection; \ .pushsection; \
.section ".data"; \ .section ".data"; \
.align ALIGNARG(2); \ .align ALIGNARG(2); \
__mcount: \ __mcount: \
.long 0; \ .long 0; \
.previous; \ .previous; \
.section ".toc","aw"; \ .section ".toc","aw"; \
.LC__mcount:; \ .LC__mcount:; \
.tc __mcount[TC],__mcount; \ .tc __mcount[TC],__mcount; \
.previous; \ .previous; \
mflr r0; \ mflr r0; \
std r0,16(r1); \ std r0,16(r1); \
ld r0,.LC__mcount@toc(r2); \ ld r0,.LC__mcount@toc(r2); \
bl JUMPTARGET(_mcount); bl JUMPTARGET(_mcount);
#else /* SYSV_ELF_PROFILING */ #else /* SYSV_ELF_PROFILING */
#define CALL_MCOUNT \ #define CALL_MCOUNT \
mflr r0; \ mflr r0; \
std r0,16(r1); \ std r0,16(r1); \
bl JUMPTARGET(_mcount); bl JUMPTARGET(_mcount);
#endif /* SYSV_ELF_PROFILING */ #endif /* SYSV_ELF_PROFILING */
#else /* PROF */ #else /* PROF */
#define CALL_MCOUNT /* Do nothing. */ #define CALL_MCOUNT /* Do nothing. */
#endif /* PROF */ #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_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) \ #define ENTRY(name) \
.section ".text"; \ ENTRY_2(name) \
.align ALIGNARG(2); \ .align ALIGNARG(2); \
.globl DOT_LABEL(name); \ BODY_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 EALIGN_W_0 /* No words to insert. */ #define EALIGN_W_0 /* No words to insert. */
#define EALIGN_W_1 nop #define EALIGN_W_1 nop
@ -82,44 +105,24 @@ DOT_LABEL(name):
#define EALIGN_W_7 EALIGN_W_6;nop #define EALIGN_W_7 EALIGN_W_6;nop
/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
past a 2^align boundary. */ past a 2^alignt boundary. */
#ifdef PROF #ifdef PROF
#define EALIGN(name, alignt, words) \ #define EALIGN(name, alignt, words) \
.section ".text"; \ ENTRY_2(name) \
.globl DOT_LABEL(name); \ .align ALIGNARG(alignt); \
.type DOT_LABEL(name),@function ; \ EALIGN_W_##words; \
.globl name; \ BODY_LABEL(name): \
.section ".opd","aw"; \ CALL_MCOUNT \
.align 3; \ b 0f; \
.size name,24; \ .align ALIGNARG(alignt); \
name##: ; \ EALIGN_W_##words; \
.quad DOT_LABEL(name) ; \ 0:
.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:
#else /* PROF */ #else /* PROF */
#define EALIGN(name, alignt, words) \ #define EALIGN(name, alignt, words) \
.section ".text"; \ ENTRY_2(name) \
.globl DOT_LABEL(name); \ .align ALIGNARG(alignt); \
.type DOT_LABEL(name),@function ; \ EALIGN_W_##words; \
.globl name; \ BODY_LABEL(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):
#endif #endif
/* Local labels stripped out by the linker. */ /* Local labels stripped out by the linker. */
@ -135,35 +138,35 @@ DOT_LABEL(name):
/* Support Traceback tables */ /* Support Traceback tables */
#define TB_ASM 0x000c000000000000 #define TB_ASM 0x000c000000000000
#define TB_GLOBALLINK 0x0000800000000000 #define TB_GLOBALLINK 0x0000800000000000
#define TB_IS_EPROL 0x0000400000000000 #define TB_IS_EPROL 0x0000400000000000
#define TB_HAS_TBOFF 0x0000200000000000 #define TB_HAS_TBOFF 0x0000200000000000
#define TB_INT_PROC 0x0000100000000000 #define TB_INT_PROC 0x0000100000000000
#define TB_HAS_CTL 0x0000080000000000 #define TB_HAS_CTL 0x0000080000000000
#define TB_TOCLESS 0x0000040000000000 #define TB_TOCLESS 0x0000040000000000
#define TB_FP_PRESENT 0x0000020000000000 #define TB_FP_PRESENT 0x0000020000000000
#define TB_LOG_ABORT 0x0000010000000000 #define TB_LOG_ABORT 0x0000010000000000
#define TB_INT_HANDL 0x0000008000000000 #define TB_INT_HANDL 0x0000008000000000
#define TB_NAME_PRESENT 0x0000004000000000 #define TB_NAME_PRESENT 0x0000004000000000
#define TB_USES_ALLOCA 0x0000002000000000 #define TB_USES_ALLOCA 0x0000002000000000
#define TB_SAVES_CR 0x0000000200000000 #define TB_SAVES_CR 0x0000000200000000
#define TB_SAVES_LR 0x0000000100000000 #define TB_SAVES_LR 0x0000000100000000
#define TB_STORES_BC 0x0000000080000000 #define TB_STORES_BC 0x0000000080000000
#define TB_FIXUP 0x0000000040000000 #define TB_FIXUP 0x0000000040000000
#define TB_FP_SAVED(fprs) (((fprs) & 0x3f) << 24) #define TB_FP_SAVED(fprs) (((fprs) & 0x3f) << 24)
#define TB_GPR_SAVED(gprs) (((fprs) & 0x3f) << 16) #define TB_GPR_SAVED(gprs) (((fprs) & 0x3f) << 16)
#define TB_FIXEDPARMS(parms) (((parms) & 0xff) << 8) #define TB_FIXEDPARMS(parms) (((parms) & 0xff) << 8)
#define TB_FLOATPARMS(parms) (((parms) & 0x7f) << 1) #define TB_FLOATPARMS(parms) (((parms) & 0x7f) << 1)
#define TB_PARMSONSTK 0x0000000000000001 #define TB_PARMSONSTK 0x0000000000000001
#define PPC_HIGHER(v) (((v) >> 32) & 0xffff) #define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
#define TB_DEFAULT TB_ASM | TB_HAS_TBOFF | TB_NAME_PRESENT #define TB_DEFAULT TB_ASM | TB_HAS_TBOFF | TB_NAME_PRESENT
#define TRACEBACK(name) \ #define TRACEBACK(name) \
LT_LABEL(name): ; \ LT_LABEL(name): ; \
.long 0 ; \ .long 0 ; \
.quad TB_DEFAULT ; \ .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) ; \ .short LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \
LT_LABELSUFFIX(name,_name_start): ;\ LT_LABELSUFFIX(name,_name_start): ;\
.ascii stringify(name) ; \ .ascii stringify(name) ; \
@ -174,7 +177,7 @@ LT_LABELSUFFIX(name,_name_end): ; \
LT_LABEL(name): ; \ LT_LABEL(name): ; \
.long 0 ; \ .long 0 ; \
.quad TB_DEFAULT | mask ; \ .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) ; \ .short LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \
LT_LABELSUFFIX(name,_name_start): ;\ LT_LABELSUFFIX(name,_name_start): ;\
.ascii stringify(name) ; \ .ascii stringify(name) ; \
@ -184,14 +187,13 @@ LT_LABELSUFFIX(name,_name_end): ; \
/* END generates Traceback tables */ /* END generates Traceback tables */
#undef END #undef END
#define END(name) \ #define END(name) \
TRACEBACK(name) \ TRACEBACK(name) \
ASM_SIZE_DIRECTIVE(DOT_LABEL(name)) END_2(name)
/* This form supports more informative traceback tables */ /* This form supports more informative traceback tables */
#define END_GEN_TB(name,mask) \ #define END_GEN_TB(name,mask) \
TRACEBACK_MASK(name,mask) \ TRACEBACK_MASK(name,mask) \
ASM_SIZE_DIRECTIVE(DOT_LABEL(name)) END_2(name)
#define DO_CALL(syscall) \ #define DO_CALL(syscall) \
li 0,syscall; \ li 0,syscall; \
@ -244,10 +246,31 @@ LT_LABELSUFFIX(name,_name_end): ; \
#define PSEUDO_END_ERRVAL(name) \ #define PSEUDO_END_ERRVAL(name) \
END (name) END (name)
/* Label in text section. */ #else /* !__ASSEMBLER__ */
/* ppc64 function descriptors which requires . notation */
#define C_TEXT(name) .##name
#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 /* __ASSEMBLER__ */
#endif /* __ELF__ */