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>
* 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. */
#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

10
configure vendored
View File

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

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})
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}

View File

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

View File

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

View File

@ -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); \

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 <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" \
@ -148,7 +148,7 @@ elf_machine_dynamic (void)
" std 10,104(1)\n" \
/* 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" \
" 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,14 +258,14 @@ 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" \
" .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!). */ \
"._dl_start_user:\n" \
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. */ \
@ -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; */ \
@ -325,13 +324,13 @@ DL_STARTING_UP_DEF \
".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

View File

@ -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
@ -54,23 +55,45 @@ __mcount: \
#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) \
#define ENTRY_1(name) \
.section ".text"; \
.align ALIGNARG(2); \
.globl DOT_LABEL(name); \
.type DOT_LABEL(name),@function ; \
.type BODY_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):
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; \
ENTRY_2(name) \
.align ALIGNARG(alignt); \
EALIGN_W_##words; \
DOT_LABEL(name): \
BODY_LABEL(name): \
CALL_MCOUNT \
b 0f; \
.align ALIGNARG(alignt); \
EALIGN_W_##words; \
0:
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; \
ENTRY_2(name) \
.align ALIGNARG(alignt); \
EALIGN_W_##words; \
DOT_LABEL(name):
BODY_LABEL(name):
#endif
/* Local labels stripped out by the linker. */
@ -163,7 +166,7 @@ DOT_LABEL(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) ; \
@ -185,13 +188,12 @@ LT_LABELSUFFIX(name,_name_end): ; \
#undef END
#define END(name) \
TRACEBACK(name) \
ASM_SIZE_DIRECTIVE(DOT_LABEL(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__ */