(EPILOGUE, GPSAVEREG): New.
[kopensolaris-gnu/glibc.git] / sysdeps / unix / alpha / sysdep.S
index 5279b86..ce848f4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1996, 1998, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Brendan Kehoe (brendan@zen.org).
 
 #include <sysdep.h>
 #include <features.h>
 
-       .section .bss
-       .globl errno
-       .align 2
-errno: .space 4
-#ifdef __ELF__
-       .type errno, @object
-       .size errno, 4
-#endif
-       .globl __errno
-__errno = errno
-       .globl _errno
-_errno = errno
-
+#if defined(__ELF__) && defined(PIC)
+       /* Put this at the end of libc's text segment so that all of
+          the direct branches from the syscalls are forward, and 
+          thus predicted not taken.  */
+       .section .text.last, "ax", @progbits
+#else
        .text
-       .align 2
+#endif
 
-#ifdef _LIBC_REENTRANT
+#ifdef PIC
+       /* When building a shared library, we branch here without
+          having loaded the GP.  Nor, since it was a direct branch,
+          have we loaded PV with our address.  Do both.  */
+# define LOADGP                br pv, 1f; 1: ldgp gp, 0(pv)
+# define PROLOGUE      .prologue 0
+# define EPILOGUE
+#else
+       /* When building the static library, we tail call here from
+          elsewhere, which might use a different GP.  The entertaining
+          part is that we have to return with the GP of our caller
+          in place, so that linker relaxation works properly.  */
+       /* ??? This is so ugly.  Consider always putting the errno
+          setting code with the syscall in the static case.  */
+# define GPSAVEREG     t10
+# define LOADGP                ldah    t11, 0(pv) !gpdisp!1;           \
+                       br      1f;                             \
+                       .subsection 2;                          \
+                       1: mov  gp, GPSAVEREG;                  \
+                       lda     gp, 0(t11) !gpdisp!1;           \
+                       br      2f;                             \
+                       .previous;                              \
+                       mov     gp, GPSAVEREG;                  \
+                       2:
+# define PROLOGUE      .prologue 1
+# define EPILOGUE      mov     GPSAVEREG, gp
+#endif
 
+       .align 4
        .globl __syscall_error
        .ent __syscall_error
 __syscall_error:
-       ldgp    gp, 0(pv)
-       lda     sp, -16(sp)
-       .frame  sp, 16, ra, 0
+
+#if defined(_LIBC_REENTRANT) && USE___THREAD
+
+#ifndef NOT_IN_libc
+# define SYSCALL_ERROR_ERRNO __libc_errno
+#else
+# define SYSCALL_ERROR_ERRNO errno
+#endif
+
+       LOADGP
+       PROLOGUE
+       mov     v0, t0
+       call_pal PAL_rduniq
+       ldq     t1, SYSCALL_ERROR_ERRNO(gp) !gottprel
+       addq    v0, t1, v0
+       stl     t0, 0(v0)
+       lda     v0, -1
+       EPILOGUE
+       ret
+
+#elif defined(_LIBC_REENTRANT)
+
+       LOADGP
+       lda     sp, -32(sp)
+       .frame  sp, 32, ra, 0
        stq     ra, 0(sp)
        stq     v0, 8(sp)
-       .mask   0x4000001, -16
-       .prologue 1
+#ifdef GPSAVEREG
+       stq     GPSAVEREG, 16(sp)
+#endif
+       .mask   0x4000001, -32
+       PROLOGUE
 
        /* Find our per-thread errno address  */
+#ifdef PIC
+       bsr     ra, __errno_location    !samegp
+#else
        jsr     ra, __errno_location
+#ifndef GPSAVEREG
+       ldgp    gp, 0(ra)
+#endif
+#endif
 
        /* Store the error value.  */
        ldq     t0, 8(sp)
@@ -59,19 +111,24 @@ __syscall_error:
        /* And kick back a -1.  */
        ldi     v0, -1
 
+#ifdef GPSAVEREG
+       ldq     GPSAVEREG, 16(sp)
+#endif
        ldq     ra, 0(sp)
-       lda     sp, 16(sp)
+       lda     sp, 32(sp)
+       EPILOGUE
        ret
-       .end __syscall_error
-#else
 
-ENTRY(__syscall_error)
-       ldgp    gp, 0(t12)
-       .prologue 1
+#else
 
+       LOADGP
+       PROLOGUE
        stl     v0, errno
        lda     v0, -1
+       EPILOGUE
        ret
-       END(__syscall_error)
 
-#endif /* _LIBC_REENTRANT */
+#endif
+
+       .subsection 3
+       .end __syscall_error