x86-64 __longjmp implementation.
authoraj <aj>
Wed, 19 Sep 2001 10:12:07 +0000 (10:12 +0000)
committeraj <aj>
Wed, 19 Sep 2001 10:12:07 +0000 (10:12 +0000)
17 files changed:
sysdeps/x86_64/__longjmp.S [new file with mode: 0644]
sysdeps/x86_64/abort-instr.h [new file with mode: 0644]
sysdeps/x86_64/atomicity.h [new file with mode: 0644]
sysdeps/x86_64/bp-asm.h [new file with mode: 0644]
sysdeps/x86_64/bsd-_setjmp.S [new file with mode: 0644]
sysdeps/x86_64/bsd-setjmp.S [new file with mode: 0644]
sysdeps/x86_64/dl-machine.h [new file with mode: 0644]
sysdeps/x86_64/ffs.c [new file with mode: 0644]
sysdeps/x86_64/ffsll.c [new file with mode: 0644]
sysdeps/x86_64/gmp-mparam.h [new file with mode: 0644]
sysdeps/x86_64/hp-timing.c [new file with mode: 0644]
sysdeps/x86_64/hp-timing.h [new file with mode: 0644]
sysdeps/x86_64/htonl.S [new file with mode: 0644]
sysdeps/x86_64/memusage.h [new file with mode: 0644]
sysdeps/x86_64/setjmp.S [new file with mode: 0644]
sysdeps/x86_64/stackinfo.h [new file with mode: 0644]
sysdeps/x86_64/sysdep.h [new file with mode: 0644]

diff --git a/sysdeps/x86_64/__longjmp.S b/sysdeps/x86_64/__longjmp.S
new file mode 100644 (file)
index 0000000..1962b7f
--- /dev/null
@@ -0,0 +1,44 @@
+/* Copyright (C) 2001 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>
+#define _ASM
+#define _SETJMP_H
+#include <bits/setjmp.h>
+#include <asm-syntax.h>
+
+/* Jump to the position specified by ENV, causing the
+   setjmp call there to return VAL, or 1 if VAL is 0.
+   void __longjmp (__jmp_buf env, int val).  */
+ENTRY(__longjmp)
+       /* Restore registers.  */
+       movq (JB_RBX*8)(%rdi),%rbx
+       movq (JB_RBP*8)(%rdi),%rbp
+       movq (JB_R12*8)(%rdi),%r12
+       movq (JB_R13*8)(%rdi),%r13
+       movq (JB_R14*8)(%rdi),%r14
+       movq (JB_R15*8)(%rdi),%r15
+       /* Set return value for setjmp.  */
+       test %esi,%esi
+       mov $01,%eax
+       cmove %eax,%esi
+       mov %esi, %eax
+       movq (JB_PC*8)(%rdi),%rdx
+       movq (JB_RSP*8)(%rdi),%rsp
+       jmpq *%rdx
+END (BP_SYM (__longjmp))
diff --git a/sysdeps/x86_64/abort-instr.h b/sysdeps/x86_64/abort-instr.h
new file mode 100644 (file)
index 0000000..810f103
--- /dev/null
@@ -0,0 +1,2 @@
+/* An instruction which should crash any program is `hlt'.  */
+#define ABORT_INSTRUCTION asm ("hlt")
diff --git a/sysdeps/x86_64/atomicity.h b/sysdeps/x86_64/atomicity.h
new file mode 100644 (file)
index 0000000..925c9f9
--- /dev/null
@@ -0,0 +1,57 @@
+/* Low-level functions for atomic operations.  x86-64 version.
+   Copyright (C) 1997, 2000, 2001 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.  */
+
+#ifndef _ATOMICITY_H
+#define _ATOMICITY_H   1
+
+#include <inttypes.h>
+
+
+static inline uint32_t
+__attribute__ ((unused))
+exchange_and_add (volatile uint32_t *mem, uint32_t val)
+{
+  register uint32_t result;
+  __asm__ __volatile__ ("lock; xaddl %0,%1"
+                       : "=r" (result), "=m" (*mem) : "0" (val), "1" (*mem));
+  return result;
+}
+
+static inline void
+__attribute__ ((unused))
+atomic_add (volatile uint32_t *mem, int val)
+{
+  __asm__ __volatile__ ("lock; addl %1,%0"
+                       : "=m" (*mem) : "er" (val), "0" (*mem));
+}
+
+static inline char
+__attribute__ ((unused))
+compare_and_swap (volatile long int *p, long int oldval, long int newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0"
+                        : "=q" (ret), "=m" (*p), "=a" (readval)
+                        : "r" (newval), "1" (*p), "a" (oldval));
+  return ret;
+}
+
+#endif /* atomicity.h */
diff --git a/sysdeps/x86_64/bp-asm.h b/sysdeps/x86_64/bp-asm.h
new file mode 100644 (file)
index 0000000..ff140ce
--- /dev/null
@@ -0,0 +1,141 @@
+/* Bounded-pointer definitions for x86-64 assembler.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   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.  */
+
+#ifndef _bp_asm_h_
+# define _bp_asm_h_ 1
+
+# if __ASSEMBLER__
+
+#  if __BOUNDED_POINTERS__
+
+/* Bounded pointers occupy three words.  */
+#   define PTR_SIZE 24
+/* Bounded pointer return values are passed back through a hidden
+   argument that points to caller-allocate space.  The hidden arg
+   occupies one word on the stack.  */
+#   define RTN_SIZE 6
+/* Although the caller pushes the hidden arg, the callee is
+   responsible for popping it.  */
+#   define RET_PTR ret $RTN_SIZE
+/* Maintain frame pointer chain in leaf assembler functions for the benefit
+   of debugging stack traces when bounds violations occur.  */
+#   define ENTER pushq %rbp; movq %rsp, %rbp
+#   define LEAVE movq %rbp, %rsp; popq %rbp
+/* Stack space overhead of procedure-call linkage: return address and
+   frame pointer.  */
+#   define LINKAGE 16
+/* Stack offset of return address after calling ENTER.  */
+#   define PCOFF 8
+
+/* Int 5 is the "bound range" exception also raised by the "bound"
+   instruction.  */
+#   define BOUNDS_VIOLATED int $5
+
+#   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)   \
+       cmpq 8+BP_MEM, VAL_REG;                 \
+       jae 0f; /* continue if value >= low */  \
+       BOUNDS_VIOLATED;                        \
+    0:
+
+#   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)     \
+       cmpq 16+BP_MEM, VAL_REG;                        \
+       Jcc 0f; /* continue if value < high */          \
+       BOUNDS_VIOLATED;                                \
+    0:
+
+#   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)  \
+       cmpq 8+BP_MEM, VAL_REG;                 \
+       jb 1f; /* die if value < low */         \
+       cmpq 16+BP_MEM, VAL_REG;                \
+       jb 0f; /* continue if value < high */   \
+    1: BOUNDS_VIOLATED;                        \
+    0:
+
+#   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)     \
+       CHECK_BOUNDS_LOW(VAL_REG, BP_MEM);                      \
+       addl LENGTH, VAL_REG;                                   \
+       cmpq 16+BP_MEM, VAL_REG;                                        \
+       jbe 0f; /* continue if value <= high */                 \
+       BOUNDS_VIOLATED;                                        \
+    0: subq LENGTH, VAL_REG /* restore value */
+
+/* Take bounds from BP_MEM and affix them to the pointer
+   value in %rax, stuffing all into memory at RTN(%esp).
+   Use %rdx as a scratch register.  */
+
+#   define RETURN_BOUNDED_POINTER(BP_MEM)      \
+       movq RTN(%rsp), %rdx;                   \
+       movq %rax, 0(%rdx);                     \
+       movq 8+BP_MEM, %rax;                    \
+       movq %rax, 4(%rdx);                     \
+       movq 16+BP_MEM, %rax;                   \
+       movq %rax, 8(%rdx)
+
+#   define RETURN_NULL_BOUNDED_POINTER         \
+       movl RTN(%rsp), %rdx;                   \
+       movl %rax, 0(%rdx);                     \
+       movl %rax, 4(%rdx);                     \
+       movl %rax, 8(%rdx)
+
+/* The caller of __errno_location is responsible for allocating space
+   for the three-word BP return-value and passing pushing its address
+   as an implicit first argument.  */
+#   define PUSH_ERRNO_LOCATION_RETURN          \
+       subl $16, %esp;                         \
+       subl $8, %esp;                          \
+       pushq %rsp
+
+/* __errno_location is responsible for popping the implicit first
+   argument, but we must pop the space for the BP itself.  We also
+   dereference the return value in order to dig out the pointer value.  */
+#   define POP_ERRNO_LOCATION_RETURN           \
+       popq %rax;                              \
+       addq $16, %rsp
+
+#  else /* !__BOUNDED_POINTERS__ */
+
+/* Unbounded pointers occupy one word.  */
+#   define PTR_SIZE 8
+/* Unbounded pointer return values are passed back in the register %rax.  */
+#   define RTN_SIZE 0
+/* Use simple return instruction for unbounded pointer values.  */
+#   define RET_PTR ret
+/* Don't maintain frame pointer chain for leaf assembler functions.  */
+#   define ENTER
+#   define LEAVE
+/* Stack space overhead of procedure-call linkage: return address only.  */
+#   define LINKAGE 8
+/* Stack offset of return address after calling ENTER.  */
+#   define PCOFF 0
+
+#   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)
+#   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)
+#   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)
+#   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)
+#   define RETURN_BOUNDED_POINTER(BP_MEM)
+
+#   define RETURN_NULL_BOUNDED_POINTER
+
+#   define PUSH_ERRNO_LOCATION_RETURN
+#   define POP_ERRNO_LOCATION_RETURN
+
+#  endif /* !__BOUNDED_POINTERS__ */
+
+# endif /* __ASSEMBLER__ */
+
+#endif /* _bp_asm_h_ */
diff --git a/sysdeps/x86_64/bsd-_setjmp.S b/sysdeps/x86_64/bsd-_setjmp.S
new file mode 100644 (file)
index 0000000..5f29adc
--- /dev/null
@@ -0,0 +1,39 @@
+/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'.  x86-64 version.
+   Copyright (C) 1994,1995,1996,1997,2000,2001 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.  */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 0)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+#include <sysdep.h>
+#define _ASM
+#define _SETJMP_H
+#include <bits/setjmp.h>
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+ENTRY (BP_SYM (_setjmp))
+       /* Set up arguments, we only need to set the second arg.  */
+       xorq %rsi, %rsi
+#ifdef PIC
+       jmp C_SYMBOL_NAME (BP_SYM (__sigsetjmp))@PLT
+#else
+       jmp BP_SYM (__sigsetjmp)
+#endif
+END (BP_SYM (_setjmp))
diff --git a/sysdeps/x86_64/bsd-setjmp.S b/sysdeps/x86_64/bsd-setjmp.S
new file mode 100644 (file)
index 0000000..c168f81
--- /dev/null
@@ -0,0 +1,38 @@
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'.  x86-64 version.
+   Copyright (C) 1994,1995,1996,1997,2000,2001 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.  */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+#include <sysdep.h>
+#define _ASM
+#define _SETJMP_H
+#include <bits/setjmp.h>
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+ENTRY (BP_SYM (setjmp))
+       /* Set up arguments, we only need to set the 2nd arg.  */
+       movq $1, %rsi
+#ifdef PIC
+#else
+       jmp BP_SYM (__sigsetjmp)
+#endif
+END (BP_SYM (setjmp))
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
new file mode 100644 (file)
index 0000000..268c2c3
--- /dev/null
@@ -0,0 +1,417 @@
+/* Machine-dependent ELF dynamic relocation inline functions.  x86-64 version.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger <aj@suse.de>.
+
+   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.  */
+
+#ifndef dl_machine_h
+#define dl_machine_h
+
+#define ELF_MACHINE_NAME "x86_64"
+
+#include <sys/param.h>
+
+/* Return nonzero iff ELF header is compatible with the running host.  */
+static inline int __attribute__ ((unused))
+elf_machine_matches_host (const Elf64_Ehdr *ehdr)
+{
+  return ehdr->e_machine == EM_X86_64;
+}
+
+
+/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
+   first element of the GOT.  This must be inlined in a function which
+   uses global data.  */
+static inline Elf64_Addr __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+  register Elf64_Addr addr;
+
+  asm ("leaq _DYNAMIC, %0\n" : "=r" (addr));
+  return addr;
+}
+
+
+/* Return the run-time load address of the shared object.  */
+static inline Elf64_Addr __attribute__ ((unused))
+elf_machine_load_address (void)
+{
+  register Elf64_Addr addr, tmp;
+
+  asm ("leaq _dl_start, %0\n"
+       "leaq _dl_start(%%rip), %1\n"
+       "subq %0, %1\n"
+       : "=r" (tmp), "=r" (addr) : : "cc");
+  return addr;
+}
+
+/* Set up the loaded object described by L so its unrelocated PLT
+   entries will jump to the on-demand fixup code in dl-runtime.c.  */
+
+static inline int __attribute__ ((unused))
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+{
+  Elf64_Addr *got;
+  extern void _dl_runtime_resolve (Elf64_Word);
+  extern void _dl_runtime_profile (Elf64_Word);
+
+  if (l->l_info[DT_JMPREL] && lazy)
+    {
+      /* The GOT entries for functions in the PLT have not yet been filled
+        in.  Their initial contents will arrange when called to push an
+        offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
+        and then jump to _GLOBAL_OFFSET_TABLE[2].  */
+      got = (Elf64_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
+      got[1] = (Elf64_Addr) l; /* Identify this shared object.  */
+
+      /* The got[2] entry contains the address of a function which gets
+        called to get the address of a so far unresolved function and
+        jump to it.  The profiling extension of the dynamic linker allows
+        to intercept the calls to collect information.  In this case we
+        don't store the address in the GOT so that all future calls also
+        end in this function.  */
+      if (__builtin_expect (profile, 0))
+       {
+         got[2] = (Elf64_Addr) &_dl_runtime_profile;
+
+         if (_dl_name_match_p (_dl_profile, l))
+           /* This is the object we are looking for.  Say that we really
+              want profiling and the timers are started.  */
+           _dl_profile_map = l;
+       }
+      else
+       /* This function will get called to fix up the GOT entry indicated by
+          the offset on the stack, and then jump to the resolved address.  */
+       got[2] = (Elf64_Addr) &_dl_runtime_resolve;
+    }
+
+  return lazy;
+}
+
+/* This code is used in dl-runtime.c to call the `fixup' function
+   and then redirect to the address it returns.  */
+#ifndef PROF
+# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
+       .text\n\
+       .globl _dl_runtime_resolve\n\
+       .type _dl_runtime_resolve, @function\n\
+       .align 16\n\
+_dl_runtime_resolve:\n\
+       pushq %rax              # Preserve registers otherwise clobbered.\n\
+       pushq %rcx\n\
+       pushq %rdx\n\
+       pushq %rsi\n\
+       pushq %rdi\n\
+       pushq %r8\n\
+       pushq %r9\n\
+       movq 64(%rsp), %rsi     # Copy args pushed by PLT in register.\n\
+       movq %rsi,%r11          # Multiply by 24\n\
+       addq %r11,%rsi\n\
+       addq %r11,%rsi\n\
+       shlq $3, %rsi\n\
+       movq 56(%rsp), %rdi     # %rdi: link_map, %rsi: reloc_offset\n\
+       call fixup              # Call resolver.\n\
+       movq %rax, %r11         # Save return value\n\
+       popq %r9                # Get register content back.\n\
+       popq %r8\n\
+       popq %rdi\n\
+       popq %rsi\n\
+       popq %rdx\n\
+       popq %rcx\n\
+       popq %rax\n\
+       addq $16,%rsp           # Adjust stack\n\
+       jmp *%r11               # Jump to function address.\n\
+       .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
+\n\
+       .globl _dl_runtime_profile\n\
+       .type _dl_runtime_profile, @function\n\
+       .align 16\n\
+_dl_runtime_profile:\n\
+       pushq %rax              # Preserve registers otherwise clobbered.\n\
+       pushq %rcx\n\
+       pushq %rdx\n\
+       pushq %rsi\n\
+       pushq %rdi\n\
+       pushq %r8\n\
+       pushq %r9\n\
+       movq 72(%rsp), %rdx     # Load return address if needed\n\
+       movq 64(%rsp), %rsi     # Copy args pushed by PLT in register.\n\
+       movq %rsi,%r11          # Multiply by 24\n\
+       addq %r11,%rsi\n\
+       addq %r11,%rsi\n\
+       shlq $3, %rsi\n\
+       movq 56(%rsp), %rdi     # %rdi: link_map, %rsi: reloc_offset\n\
+       call profile_fixup      # Call resolver.\n\
+       movq %rax, %r11         # Save return value\n\
+       popq %r9                # Get register content back.\n\
+       popq %r8\n\
+       popq %rdi\n\
+       popq %rsi\n\
+       popq %rdx\n\
+       popq %rcx\n\
+       popq %rax\n\
+       addq $16,%rsp           # Adjust stack\n\
+       jmp *%r11               # Jump to function address.\n\
+       .size _dl_runtime_profile, .-_dl_runtime_profile\n\
+       .previous\n\
+");
+#else
+# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
+       .text\n\
+       .globl _dl_runtime_resolve\n\
+       .globl _dl_runtime_profile\n\
+       .type _dl_runtime_resolve, @function\n\
+       .type _dl_runtime_profile, @function\n\
+       .align 16\n\
+_dl_runtime_resolve:\n\
+_dl_runtime_profile:\n\
+       pushq %rax              # Preserve registers otherwise clobbered.\n\
+       pushq %rcx\n\
+       pushq %rdx\n\
+       pushq %rsi\n\
+       pushq %rdi\n\
+       pushq %r8\n\
+       pushq %r9\n\
+       movq 64(%rsp), %rsi     # Copy args pushed by PLT in register.\n\
+       movq %rsi,%r11          # Multiply by 24\n\
+       addq %r11,%rsi\n\
+       addq %r11,%rsi\n\
+       shlq $3, %rsi\n\
+       movq 56(%rsp), %rdi     # %rdi: link_map, %rsi: reloc_offset\n\
+       call fixup              # Call resolver.\n\
+       movq %rax, %r11         # Save return value\n\
+       popq %r9                # Get register content back.\n\
+       popq %r8\n\
+       popq %rdi\n\
+       popq %rsi\n\
+       popq %rdx\n\
+       popq %rcx\n\
+       popq %rax\n\
+       addq $16,%rsp           # Adjust stack\n\
+       jmp *%r11               # Jump to function address.\n\
+       .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
+       .size _dl_runtime_profile, .-_dl_runtime_profile\n\
+       .previous\n\
+");
+#endif
+
+/* Initial entry point code for the dynamic linker.
+   The C function `_dl_start' is the real entry point;
+   its return value is the user program's entry point.  */
+#define RTLD_START asm ("\n\
+.text\n\
+       .align 16\n\
+.globl _start\n\
+.globl _dl_start_user\n\
+_start:\n\
+       movq %rsp, %rdi\n\
+       call _dl_start\n\
+_dl_start_user:\n\
+       # Save the user entry point address in %r12.\n\
+       movq %rax, %r12\n\
+       # Store the highest stack address\n\
+       movq __libc_stack_end@GOTPCREL(%rip), %rax\n\
+       movq %rsp, (%rax)\n\
+       # See if we were run as a command with the executable file\n\
+       # name as an extra leading argument.\n\
+       movq _dl_skip_args@GOTPCREL(%rip), %rax\n\
+       movl (%rax), %eax\n\
+       # Pop the original argument count.\n\
+       popq %rdx\n\
+       # Adjust the stack pointer to skip _dl_skip_args words.\n\
+       leaq (%rsp,%rax,8), %rsp\n\
+       # Subtract _dl_skip_args from argc.\n\
+       subl %eax, %edx\n\
+       # Push argc back on the stack.\n\
+       pushq %rdx\n\
+       # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
+       # argc -> rsi\n\
+       movq %rdx, %rsi\n\
+       # _dl_loaded -> rdi\n\
+       movq _dl_loaded@GOTPCREL(%rip), %rdi\n\
+       movq (%rdi), %rdi\n\
+       # env -> rcx\n\
+       leaq 16(%rsp,%rdx,8), %rcx\n\
+       # argv -> rdx\n\
+       leaq 8(%rsp), %rdx\n\
+       # Call the function to run the initializers.\n\
+       call _dl_init@PLT\n\
+       # Pass our finalizer function to the user in %rdx, as per ELF ABI.\n\
+       movq _dl_fini@GOTPCREL(%rip), %rdx\n\
+       # Jump to the user's entry point.\n\
+       jmp *%r12\n\
+.previous\n\
+");
+
+/* 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.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_X86_64_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT)  \
+   | (((type) == R_X86_64_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_X86_64_JUMP_SLOT
+
+/* The x86-64 never uses Elf64_Rel relocations.  */
+#define ELF_MACHINE_NO_REL 1
+
+/* We define an initialization functions.  This is called very early in
+   _dl_sysdep_start.  */
+#define DL_PLATFORM_INIT dl_platform_init ()
+
+extern const char *_dl_platform;
+
+static inline void __attribute__ ((unused))
+dl_platform_init (void)
+{
+  if (_dl_platform != NULL && *_dl_platform == '\0')
+    /* Avoid an empty string which would disturb us.  */
+    _dl_platform = NULL;
+}
+
+static inline Elf64_Addr
+elf_machine_fixup_plt (struct link_map *map, lookup_t t,
+                      const Elf64_Rela *reloc,
+                      Elf64_Addr *reloc_addr, Elf64_Addr value)
+{
+  return *reloc_addr = value;
+}
+
+/* Return the final value of a plt relocation.  On x86-64 the
+   JUMP_SLOT relocation ignores the addend. */
+static inline Elf64_Addr
+elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
+                      Elf64_Addr value)
+{
+  return value;
+}
+
+#endif /* !dl_machine_h */
+
+#ifdef RESOLVE
+
+/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
+   MAP is the object containing the reloc.  */
+
+static inline void
+elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
+                const Elf64_Sym *sym, const struct r_found_version *version,
+                Elf64_Addr *const reloc_addr)
+{
+  const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
+
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
+  if (__builtin_expect (r_type == R_X86_64_RELATIVE, 0))
+    {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+      /* This is defined in rtld.c, but nowhere in the static libc.a;
+        make the reference weak so static programs can still link.
+        This declaration cannot be done when compiling rtld.c
+        (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
+        common defn for _dl_rtld_map, which is incompatible with a
+        weak decl in the same file.  */
+      weak_extern (_dl_rtld_map);
+      if (map != &_dl_rtld_map) /* Already done in rtld itself.  */
+# endif
+       *reloc_addr = map->l_addr + reloc->r_addend;
+    }
+  else
+#endif
+  if (__builtin_expect (r_type == R_X86_64_NONE, 0))
+    return;
+  else
+    {
+#ifndef RTLD_BOOTSTRAP
+      const Elf64_Sym *const refsym = sym;
+#endif
+      Elf64_Addr value = RESOLVE (&sym, version, r_type);
+      if (sym)
+       value += sym->st_value;
+
+#ifdef RTLD_BOOTSTRAP
+      assert (r_type == R_X86_64_GLOB_DAT || r_type == R_X86_64_JUMP_SLOT);
+      *reloc_addr = value + reloc->r_addend;
+#else
+      switch (r_type)
+       {
+       case R_X86_64_GLOB_DAT:
+       case R_X86_64_JUMP_SLOT:
+         *reloc_addr = value + reloc->r_addend;
+         break;
+       case R_X86_64_64:
+         *reloc_addr = value + reloc->r_addend;
+         break;
+       case R_X86_64_32:
+         *(unsigned int *) reloc_addr = value + reloc->r_addend;
+         break;
+       case R_X86_64_PC32:
+         *(unsigned int *) reloc_addr = value + reloc->r_addend
+           - (Elf64_Addr) reloc_addr;
+         break;
+       case R_X86_64_COPY:
+         if (sym == NULL)
+           /* This can happen in trace mode if an object could not be
+              found.  */
+           break;
+         if (__builtin_expect (sym->st_size > refsym->st_size, 0)
+             || (__builtin_expect (sym->st_size < refsym->st_size, 0)
+                 && _dl_verbose))
+           {
+             const char *strtab;
+
+             strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
+             _dl_error_printf ("\
+%s: Symbol `%s' has different size in shared object, consider re-linking\n",
+                               _dl_argv[0] ?: "<program name unknown>",
+                               strtab + refsym->st_name);
+           }
+         memcpy (reloc_addr, (void *) value, MIN (sym->st_size,
+                                                  refsym->st_size));
+         break;
+       default:
+         _dl_reloc_bad_type (map, r_type, 0);
+         break;
+       }
+#endif
+    }
+}
+
+static inline void
+elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
+                          Elf64_Addr *const reloc_addr)
+{
+  assert (ELF64_R_TYPE (reloc->r_info) == R_X86_64_RELATIVE);
+  *reloc_addr = l_addr + reloc->r_addend;
+}
+
+static inline void
+elf_machine_lazy_rel (struct link_map *map,
+                     Elf64_Addr l_addr, const Elf64_Rela *reloc)
+{
+  Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
+  const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
+
+  /* Check for unexpected PLT reloc type.  */
+  if (__builtin_expect (r_type == R_X86_64_JUMP_SLOT, 1))
+    *reloc_addr += l_addr;
+  else
+    _dl_reloc_bad_type (map, r_type, 1);
+}
+
+#endif /* RESOLVE */
diff --git a/sysdeps/x86_64/ffs.c b/sysdeps/x86_64/ffs.c
new file mode 100644 (file)
index 0000000..791e6ea
--- /dev/null
@@ -0,0 +1,38 @@
+/* ffs -- find first set bit in a word, counted from least significant end.
+   For AMD x86-64.
+   This file is part of the GNU C Library.
+   Copyright (C) 1991,92,93,94,97,98,2001 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>.
+
+   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 <string.h>
+
+#undef ffs
+
+int
+__ffs (int x)
+{
+  int cnt;
+  int tmp;
+
+  asm ("bsfl %2,%0\n"          /* Count low bits in X and store in %1.  */
+       "cmovel %1,%0\n"                /* If number was zero, use -1 as result.  */
+       : "=&r" (cnt), "=r" (tmp) : "rm" (x), "1" (-1));
+
+  return cnt + 1;
+}
+weak_alias (__ffs, ffs)
diff --git a/sysdeps/x86_64/ffsll.c b/sysdeps/x86_64/ffsll.c
new file mode 100644 (file)
index 0000000..7213c03
--- /dev/null
@@ -0,0 +1,41 @@
+/* ffsll -- find first set bit in a word, counted from least significant end.
+   For AMD x86-64.
+   This file is part of the GNU C Library.
+   Copyright (C) 1991,92,93,94,97,98,2001 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>.
+
+   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.  */
+
+#define ffsl __something_else
+#include <string.h>
+
+#undef ffsll
+
+int
+ffsll (long long int x)
+{
+  long long int cnt;
+  long long int tmp;
+
+  asm ("bsfq %2,%0\n"          /* Count low bits in X and store in %1.  */
+       "cmoveq %1,%0\n"                /* If number was zero, use -1 as result.  */
+       : "=&r" (cnt), "=r" (tmp) : "rm" (x), "1" (-1));
+
+  return cnt + 1;
+}
+
+#undef ffsl
+weak_alias (ffsll, ffsl)
diff --git a/sysdeps/x86_64/gmp-mparam.h b/sysdeps/x86_64/gmp-mparam.h
new file mode 100644 (file)
index 0000000..615e23b
--- /dev/null
@@ -0,0 +1,27 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 64
+#define BYTES_PER_MP_LIMB 8
+#define BITS_PER_LONGINT 64
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
diff --git a/sysdeps/x86_64/hp-timing.c b/sysdeps/x86_64/hp-timing.c
new file mode 100644 (file)
index 0000000..289ca4c
--- /dev/null
@@ -0,0 +1,2 @@
+/* We can use the i686 implementation without changes.  */
+#include <sysdeps/i386/i686/hp-timing.c>
diff --git a/sysdeps/x86_64/hp-timing.h b/sysdeps/x86_64/hp-timing.h
new file mode 100644 (file)
index 0000000..1f24ffc
--- /dev/null
@@ -0,0 +1,2 @@
+/* We can use the i686 implementation without changes.  */
+#include <sysdeps/i386/i686/hp-timing.h>
diff --git a/sysdeps/x86_64/htonl.S b/sysdeps/x86_64/htonl.S
new file mode 100644 (file)
index 0000000..5aba9b3
--- /dev/null
@@ -0,0 +1,35 @@
+/* Change byte order in word.  For AMD x86-64.
+   Copyright (C) 1997, 2001 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 "asm-syntax.h"
+
+/*
+   INPUT PARAMETERS:
+   word                %rdi
+*/
+
+       .text
+ENTRY (htonl)
+       movl    %edi, %eax
+       bswap   %eax
+       ret
+END (htonl)
+
+weak_alias (htonl, ntohl)
diff --git a/sysdeps/x86_64/memusage.h b/sysdeps/x86_64/memusage.h
new file mode 100644 (file)
index 0000000..d267cf5
--- /dev/null
@@ -0,0 +1,22 @@
+/* Copyright (C) 2001 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.  */
+
+#define GETSP() ({ register uintptr_t stack_ptr asm ("rsp"); stack_ptr; })
+#define GETTIME(low,high) asm ("rdtsc" : "=a" (low), "=d" (high))
+
+#include <sysdeps/generic/memusage.h>
diff --git a/sysdeps/x86_64/setjmp.S b/sysdeps/x86_64/setjmp.S
new file mode 100644 (file)
index 0000000..e40381d
--- /dev/null
@@ -0,0 +1,45 @@
+/* setjmp for x86-64.
+   Copyright (C) 2001 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>
+#define _ASM
+#define _SETJMP_H
+#include <bits/setjmp.h>
+#include <asm-syntax.h>
+
+ENTRY (__sigsetjmp)
+       /* Save registers.  */
+       movq %rbx, (JB_RBX*8)(%rdi)
+       movq %rbp, (JB_RBP*8)(%rdi)
+       movq %r12, (JB_R12*8)(%rdi)
+       movq %r13, (JB_R13*8)(%rdi)
+       movq %r14, (JB_R14*8)(%rdi)
+       movq %r15, (JB_R15*8)(%rdi)
+       leaq 8(%rsp), %rdx      /* Save SP as it will be after we return.  */
+       movq %rdx, (JB_RSP*8)(%rdi)
+       movq (%rsp), %rax       /* Save PC we are returning to now.  */
+       movq %rax, (JB_PC*8)(%rdi)
+
+       /* Make a tail call to __sigjmp_save; it takes the same args.  */
+#ifdef PIC
+       jmp C_SYMBOL_NAME (BP_SYM (__sigjmp_save))@PLT
+#else
+       jmp BP_SYM (__sigjmp_save)
+#endif
+END (BP_SYM (__sigsetjmp))
diff --git a/sysdeps/x86_64/stackinfo.h b/sysdeps/x86_64/stackinfo.h
new file mode 100644 (file)
index 0000000..60668d1
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (C) 2001 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.  */
+
+/* This file contains a bit of information about the stack allocation
+   of the processor.  */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H   1
+
+/* On x86_64 the stack grows down.  */
+#define _STACK_GROWS_DOWN      1
+
+#endif /* stackinfo.h */
diff --git a/sysdeps/x86_64/sysdep.h b/sysdeps/x86_64/sysdep.h
new file mode 100644 (file)
index 0000000..2a2ad41
--- /dev/null
@@ -0,0 +1,101 @@
+/* Assembler macros for x86-64.
+   Copyright (C) 2001 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 <sysdeps/generic/sysdep.h>
+
+#ifdef __ASSEMBLER__
+
+/* Syntactic details of assembler.  */
+
+#ifdef HAVE_ELF
+
+/* ELF uses byte-counts for .align, most others use log2 of count of bytes.  */
+#define ALIGNARG(log2) 1<<log2
+/* For ELF we need the `.type' directive to make shared libs work right.  */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
+
+/* In ELF C symbols are asm symbols.  */
+#undef NO_UNDERSCORES
+#define NO_UNDERSCORES
+
+#else
+
+#define ALIGNARG(log2) log2
+#define ASM_TYPE_DIRECTIVE(name,type)  /* Nothing is specified.  */
+#define ASM_SIZE_DIRECTIVE(name)       /* Nothing is specified.  */
+
+#endif
+
+
+/* Define an entry point visible from C.  */
+#define        ENTRY(name)                                                           \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);                                  \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)                         \
+  .align ALIGNARG(4);                                                        \
+  C_LABEL(name)                                                                      \
+  CALL_MCOUNT
+
+#undef END
+#define END(name)                                                            \
+  ASM_SIZE_DIRECTIVE(name)                                                   \
+
+/* If compiled for profiling, call `mcount' at the start of each function.  */
+#ifdef PROF
+/* XXX this does not work yet!  */
+/* The mcount code relies on a normal frame pointer being on the stack
+   to locate our caller, so push one just for its benefit.  */
+#define CALL_MCOUNT \
+  pushl %ebp; movl %esp, %ebp; call JUMPTARGET(mcount); popl %ebp;
+#else
+#define CALL_MCOUNT            /* Do nothing.  */
+#endif
+
+#ifdef NO_UNDERSCORES
+/* Since C identifiers are not normally prefixed with an underscore
+   on this system, the asm identifier `syscall_error' intrudes on the
+   C name space.  Make sure we use an innocuous name.  */
+#define        syscall_error   __syscall_error
+#define mcount         _mcount
+#endif
+
+#define        PSEUDO(name, syscall_name, args)                                      \
+lose:                                                                        \
+  jmp JUMPTARGET(syscall_error)                                                      \
+  .globl syscall_error;                                                              \
+  ENTRY (name)                                                               \
+  DO_CALL (syscall_name, args);                                                      \
+  jb lose
+
+#undef PSEUDO_END
+#define        PSEUDO_END(name)                                                      \
+  END (name)
+
+#ifdef PIC
+#define JUMPTARGET(name)       name##@PLT
+#else
+#define JUMPTARGET(name)       name
+#endif
+
+/* Local label name for asm code. */
+#ifndef L
+#define L(name)                name
+#endif
+
+#endif /* __ASSEMBLER__ */