summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-11-08 02:20:41 +0000
committerRoland McGrath <roland@gnu.org>2002-11-08 02:20:41 +0000
commitc6481412ff19d5c551aba9330082a19a4a93260f (patch)
tree335acb22df9e06295318ebe74d3dc8d6dac03968 /sysdeps
parentdfe4c900cb1d03533702c453c3a9abe6d41e545d (diff)
downloadglibc-c6481412ff19d5c551aba9330082a19a4a93260f.tar.gz
glibc-c6481412ff19d5c551aba9330082a19a4a93260f.tar.xz
glibc-c6481412ff19d5c551aba9330082a19a4a93260f.zip
* configure.in (ASM_ALPHA_NG_SYMBOL_PREFIX): Remove test.
	* configure: Regenerated.
	* config.h.in (ASM_ALPHA_NG_SYMBOL_PREFIX): Remove #undef.
	* sysdeps/alpha/dl-machine.h (TRAMPOLINE_TEMPLATE): Use !samegp.
	(RTLD_START): Likewise.  Access _dl_skip_args, _rtld_local, and
	_dl_fini via gp-relative relocations.
	* sysdeps/alpha/fpu/e_sqrt.c: Use !samegp.

	* elf/tls-macros.h: Add alpha versions.
	* sysdeps/alpha/dl-machine.h (elf_machine_rela): Handle TLS relocs.
	* sysdeps/unix/alpha/sysdep.S: Support USE___THREAD.
	* sysdeps/unix/alpha/sysdep.h: Likewise.  Add SYSCALL_ERROR_HANDLER.
	* sysdeps/unix/sysv/linux/alpha/brk.S: Use it.
	* sysdeps/unix/sysv/linux/alpha/clone.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/getitimer.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/getrusage.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/gettimeofday.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/rt_sigaction.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/select.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/setitimer.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/settimeofday.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/sigsuspend.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/syscall.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/utimes.S: Likewise.
	* sysdeps/unix/sysv/linux/alpha/wait4.S: Likewise.

	* sysdeps/unix/sysv/linux/alpha/sysdep.h: Re-include protect.
	Kill argument registers across the inline syscall.

	* sysdeps/unix/sysv/linux/alpha/clone.S: Add user_tid and tls args.

	* linuxthreads/sysdeps/alpha/tls.h: New file.
	* sysdeps/alpha/dl-tls.h: New file.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/alpha/dl-machine.h57
-rw-r--r--sysdeps/alpha/dl-tls.h29
-rw-r--r--sysdeps/alpha/fpu/e_sqrt.c2
-rw-r--r--sysdeps/unix/alpha/sysdep.S58
-rw-r--r--sysdeps/unix/alpha/sysdep.h100
-rw-r--r--sysdeps/unix/sysv/linux/alpha/brk.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/clone.S23
-rw-r--r--sysdeps/unix/sysv/linux/alpha/getitimer.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/getrusage.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/gettimeofday.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/rt_sigaction.S4
-rw-r--r--sysdeps/unix/sysv/linux/alpha/select.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/setitimer.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/settimeofday.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/sigsuspend.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/syscall.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/sysdep.h202
-rw-r--r--sysdeps/unix/sysv/linux/alpha/utimes.S2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/wait4.S2
21 files changed, 316 insertions, 185 deletions
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 05d988274b..711bf10fdd 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -228,7 +228,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	mov	$26, $18					\n\
 	addq	$17, $17, $17					\n\
 	/* Do the fixup */					\n\
-	bsr	$26, " ASM_ALPHA_NG_SYMBOL_PREFIX #fixup_name "..ng\n\
+	bsr	$26, " #fixup_name "	!samegp			\n\
 	/* Move the destination address into position.  */	\n\
 	mov	$0, $27						\n\
 	/* Restore program registers.  */			\n\
@@ -308,7 +308,7 @@ _start:								\n\
 	.prologue 0						\n\
 	/* Pass pointer to argument block to _dl_start.  */	\n\
 	mov	$sp, $16					\n\
-	bsr	$26, "ASM_ALPHA_NG_SYMBOL_PREFIX"_dl_start..ng	\n\
+	bsr	$26, _dl_start		!samegp			\n\
 	.end _start						\n\
 	/* FALLTHRU */						\n\
 	.globl _dl_start_user					\n\
@@ -322,7 +322,7 @@ _dl_start_user:							\n\
 	stq	$30, __libc_stack_end				\n\
 	/* See if we were run as a command with the executable	\n\
 	   file name as an extra leading argument.  */		\n\
-	ldl	$1, _dl_skip_args				\n\
+	ldl	$1, _dl_skip_args($gp)	!gprel			\n\
 	bne	$1, $fixup_stack				\n\
 $fixup_stack_ret:						\n\
 	/* The special initializer gets called with the stack	\n\
@@ -332,14 +332,16 @@ $fixup_stack_ret:						\n\
 " RTLD_START_SPECIAL_INIT "					\n\
 	/* Call _dl_init(_dl_loaded, argc, argv, envp) to run	\n\
 	   initializers.  */					\n\
-	ldq	$16, _rtld_local				\n\
+	ldah	$16, _rtld_local($gp)	!gprelhigh		\n\
+	ldq	$16, _rtld_local($16)	!gprellow		\n\
 	ldq	$17, 0($sp)					\n\
 	lda	$18, 8($sp)					\n\
 	s8addq	$17, 8, $19					\n\
 	addq	$19, $18, $19					\n\
-	jsr	$26, _dl_init_internal				\n\
+	bsr	$26, _dl_init_internal	!samegp			\n\
 	/* Pass our finalizer function to the user in $0. */	\n\
-	lda	$0, _dl_fini					\n\
+	ldah	$0, _dl_fini($gp)	!gprelhigh		\n\
+	lda	$0, _dl_fini($0)	!gprellow		\n\
 	/* Jump to the user's entry point.  */			\n\
 	mov	$9, $27						\n\
 	jmp	($9)						\n\
@@ -541,10 +543,15 @@ elf_machine_rela (struct link_map *map,
       return;
   else
     {
-      Elf64_Addr loadbase, sym_value;
+      Elf64_Addr sym_value;
 
-      loadbase = RESOLVE (&sym, version, r_type);
+#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      sym_value = sym ? sym_map->l_addr + sym->st_value : 0;
+#else
+      Elf64_Addr loadbase = RESOLVE (&sym, version, r_type);
       sym_value = sym ? loadbase + sym->st_value : 0;
+#endif
       sym_value += reloc->r_addend;
 
       if (r_type == R_ALPHA_GLOB_DAT)
@@ -575,6 +582,40 @@ elf_machine_rela (struct link_map *map,
 	  memcpy (reloc_addr_1, &sym_value, 8);
 	}
 #endif
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+      else if (r_type == R_ALPHA_DTPMOD64)
+	{
+#ifdef RTLD_BOOTSTRAP
+	  /* During startup the dynamic linker is always index 1.  */
+	  *reloc_addr = 1;
+#else
+	  /* Get the information from the link map returned by the
+	     resolv function.  */
+	  if (sym_map != NULL)
+	    *reloc_addr = sym_map->l_tls_modid;
+#endif
+	}
+      else if (r_type == R_ALPHA_DTPREL64)
+	{
+#ifndef RTLD_BOOTSTRAP
+	  /* During relocation all TLS symbols are defined and used.
+	     Therefore the offset is already correct.  */
+	  *reloc_addr = sym_value;
+#endif
+	}
+      else if (r_type == R_ALPHA_TPREL64)
+	{
+#ifdef RTLD_BOOTSTRAP
+	  *reloc_addr = sym_value - map->l_tls_offset;
+#else
+	  if (sym_map)
+	    {
+	      *reloc_addr = sym_value - sym_map->l_tls_offset;
+	      CHECK_STATIC_TLS (map, sym_map);
+	    }
+#endif
+	}
+#endif /* USE_TLS */
       else
 	_dl_reloc_bad_type (map, r_type, 0);
     }
diff --git a/sysdeps/alpha/dl-tls.h b/sysdeps/alpha/dl-tls.h
new file mode 100644
index 0000000000..f81f95d75e
--- /dev/null
+++ b/sysdeps/alpha/dl-tls.h
@@ -0,0 +1,29 @@
+/* Thread-local storage handling in the ELF dynamic linker.  Alpha version.
+   Copyright (C) 2002 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.  */
+
+
+/* Type used for the representation of TLS information in the GOT.  */
+typedef struct
+{
+  unsigned long int ti_module;
+  unsigned long int ti_offset;
+} tls_index;
+
+
+extern void *__tls_get_addr (tls_index *ti);
diff --git a/sysdeps/alpha/fpu/e_sqrt.c b/sysdeps/alpha/fpu/e_sqrt.c
index c6262c8f69..a371896765 100644
--- a/sysdeps/alpha/fpu/e_sqrt.c
+++ b/sysdeps/alpha/fpu/e_sqrt.c
@@ -153,7 +153,7 @@ __ieee754_sqrt:								\n\
 	.align 4							\n\
 $fixup:									\n\
 	addq	$sp, 16, $sp						\n\
-	br	"ASM_ALPHA_NG_SYMBOL_PREFIX"__full_ieee754_sqrt..ng	\n\
+	br	__full_ieee754_sqrt	!samegp				\n\
 									\n\
 	.end	__ieee754_sqrt");
 
diff --git a/sysdeps/unix/alpha/sysdep.S b/sysdeps/unix/alpha/sysdep.S
index 05c00918e6..50c84c1166 100644
--- a/sysdeps/unix/alpha/sysdep.S
+++ b/sysdeps/unix/alpha/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1996, 1998, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Brendan Kehoe (brendan@zen.org).
 
@@ -20,24 +20,59 @@
 #include <sysdep.h>
 #include <features.h>
 
+#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
+#else
+# define LOADGP		ldgp gp, 0(pv)
+# define PROLOGUE	.prologue 1
+#endif
 
+	.align 4
 	.globl __syscall_error
 	.ent __syscall_error
 __syscall_error:
-	ldgp	gp, 0(pv)
+
+#if defined(_LIBC_REENTRANT) && defined(USE___THREAD)
+
+	LOADGP
+	PROLOGUE
+	mov	v0, t0
+	call_pal PAL_rduniq
+	ldq	t1, __libc_errno(gp) !gottprel
+	addq	v0, t1, v0
+	stl	t0, 0(v0)
+	lda	v0, -1
+	ret
+
+#elif defined(_LIBC_REENTRANT)
+
+	LOADGP
 	lda	sp, -16(sp)
 	.frame	sp, 16, ra, 0
 	stq	ra, 0(sp)
 	stq	v0, 8(sp)
 	.mask	0x4000001, -16
-	.prologue 1
+	PROLOGUE
 
 	/* Find our per-thread errno address  */
+#ifdef PIC
+	bsr	ra, __errno_location	!samegp
+#else
 	jsr	ra, __errno_location
+#endif
 
 	/* Store the error value.  */
 	ldq	t0, 8(sp)
@@ -49,16 +84,15 @@ __syscall_error:
 	ldq	ra, 0(sp)
 	lda	sp, 16(sp)
 	ret
-	.end __syscall_error
-#else
 
-ENTRY(__syscall_error)
-	ldgp	gp, 0(t12)
-	.prologue 1
+#else
 
+	LOADGP
+	PROLOGUE
 	stl	v0, errno
 	lda	v0, -1
 	ret
-	END(__syscall_error)
 
-#endif /* _LIBC_REENTRANT */
+#endif
+
+	.end __syscall_error
diff --git a/sysdeps/unix/alpha/sysdep.h b/sysdeps/unix/alpha/sysdep.h
index 46b5214987..f9aba3ffa2 100644
--- a/sysdeps/unix/alpha/sysdep.h
+++ b/sysdeps/unix/alpha/sysdep.h
@@ -27,6 +27,13 @@
 # include <regdef.h>
 #endif
 
+#include <tls.h>		/* Defines USE___THREAD.  */
+
+#ifdef IS_IN_rtld
+# include <dl-sysdep.h>         /* Defines RTLD_PRIVATE_ERRNO.  */
+#endif
+
+
 #ifdef __STDC__
 #define __LABEL(x)	x##:
 #else
@@ -55,54 +62,65 @@
    label of that number between those two macros!  */
 
 #ifdef PROF
-#define PSEUDO(name, syscall_name, args)	\
-    .globl name;				\
-    .align 3;					\
-    .ent name,0;				\
+# define PSEUDO_PROLOGUE			\
+	.frame sp, 0, ra;			\
+	ldgp	gp,0(pv);			\
+	.set noat;				\
+	lda	AT,_mcount;			\
+	jsr	AT,(AT),_mcount;		\
+	.set at;				\
+	.prologue 1
+# define PSEUDO_LOADGP
+#else
+# define PSEUDO_PROLOGUE			\
+	.frame sp, 0, ra;			\
+	.prologue 0
+# define PSEUDO_LOADGP				\
+	br	gp, 2f;				\
+2:	ldgp	gp, 0(gp)
+#endif /* PROF */
+
+#if RTLD_PRIVATE_ERRNO
+# define SYSCALL_ERROR_HANDLER			\
+	stl	v0, errno(gp)	!gprel;		\
+	lda	v0, -1;				\
+	ret
+#else
+# define SYSCALL_ERROR_HANDLER \
+	jmp	$31, __syscall_error
+#endif /* RTLD_PRIVATE_ERRNO */
+
+#if defined(PIC) && !RTLD_PRIVATE_ERRNO
+# define PSEUDO(name, syscall_name, args)	\
+	.globl name;				\
+	.align 4;				\
+	.ent name,0;				\
 __LABEL(name)					\
-    .frame sp, 0, ra;				\
-    ldgp gp,0(pv);				\
-    .set noat;					\
-    lda AT,_mcount;				\
-    jsr AT,(AT),_mcount;			\
-    .set at;					\
-    .prologue 1;				\
-    ldiq	v0, SYS_ify(syscall_name);	\
-    .set noat;					\
-    call_pal	PAL_callsys;			\
-    .set at;					\
-    bne		a3, 1996f;			\
+	PSEUDO_PROLOGUE;			\
+	lda	v0, SYS_ify(syscall_name);	\
+	call_pal PAL_callsys;			\
+	bne	a3, __syscall_error !samegp;	\
 3:
+# undef PSEUDO_END
+# define PSEUDO_END(sym)  END(sym)
 #else
-#define PSEUDO(name, syscall_name, args)	\
-    .globl name;				\
-    .align 3;					\
-    .ent name,0;				\
+# define PSEUDO(name, syscall_name, args)	\
+	.globl name;				\
+	.align 4;				\
+	.ent name,0;				\
 __LABEL(name)					\
-    .frame sp, 0, ra				\
-    .prologue 0;				\
-    ldiq	v0, SYS_ify(syscall_name);	\
-    .set noat;					\
-    call_pal	PAL_callsys;			\
-    .set at;					\
-    bne		a3, 1996f;			\
+	lda	v0, SYS_ify(syscall_name);	\
+	call_pal PAL_callsys;			\
+	bne	a3, 1996f;			\
 3:
-#endif
 
-#undef PSEUDO_END
-#ifdef PROF
-#define PSEUDO_END(sym)				\
+# undef PSEUDO_END
+# define PSEUDO_END(sym)			\
 1996:						\
-    jmp		zero, __syscall_error;		\
-    END(sym)
-#else
-#define PSEUDO_END(sym)				\
-1996:						\
-    br		gp, 2f;				\
-2:  ldgp	gp, 0(gp);			\
-    jmp		zero, __syscall_error;		\
-    END(sym)
-#endif
+	PSEUDO_LOADGP;				\
+	SYSCALL_ERROR_HANDLER;			\
+	END(sym)
+#endif /* PIC && !RTLD_PRIVATE_ERRNO */
 
 #define r0	v0
 #define r1	a4
diff --git a/sysdeps/unix/sysv/linux/alpha/brk.S b/sysdeps/unix/sysv/linux/alpha/brk.S
index 3cd1ae0fbd..e01abebe0e 100644
--- a/sysdeps/unix/sysv/linux/alpha/brk.S
+++ b/sysdeps/unix/sysv/linux/alpha/brk.S
@@ -74,7 +74,7 @@ $ok:	stq	a0, __curbrk
 	/* What a horrible way to die.  */
 $err0:	ldi	v0, ENOMEM
 $err1:	addq	sp, 8, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 	END(__brk)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/clone.S b/sysdeps/unix/sysv/linux/alpha/clone.S
index f1f62146ac..42df98a9b4 100644
--- a/sysdeps/unix/sysv/linux/alpha/clone.S
+++ b/sysdeps/unix/sysv/linux/alpha/clone.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson <rth@tamu.edu>, 1996.
 
@@ -24,7 +24,9 @@
 #define _ERRNO_H	1
 #include <bits/errno.h>
 
-/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+		       pid_t *tid, void *tls);
+ */
 
         .text
 ENTRY(__clone)
@@ -49,24 +51,29 @@ ENTRY(__clone)
 	stq	a0,0(a1)
 	stq	a3,8(a1)
 
-	/* Do the system call */
+	/* Shift the flags, tid and tls arguments into place; the
+	   child_stack argument is already correct.  */
 	mov	a2,a0
+	mov	a4,a2
+	mov	a5,a3
+
+	/* Do the system call.  */
 	ldiq	v0,__NR_clone
 	call_pal PAL_callsys
 
 	bne	a3,$error
 	beq	v0,thread_start
 
-	/* Successful return from the parent */
+	/* Successful return from the parent.  */
 	ret
 
-	/* Something bad happened -- no child created */
+	/* Something bad happened -- no child created.  */
 $error:
 #ifndef PROF
 	br	gp,1f
 1:	ldgp	gp,0(gp)
 #endif
-	jmp	zero,__syscall_error
+	SYSCALL_ERROR_HANDLER
 
 	END(__clone)
 
@@ -85,11 +92,11 @@ thread_start:
 	ldq	a0,8(sp)
 	addq	sp,16,sp
 
-	/* Call the user's function */
+	/* Call the user's function.  */
 	jsr	ra,(pv)
 	ldgp	gp,0(ra)
 
-	/* Call _exit rather than doing it inline for breakpoint purposes */
+	/* Call _exit rather than doing it inline for breakpoint purposes.  */
 	mov	v0,a0
 	jsr	ra,_exit
 
diff --git a/sysdeps/unix/sysv/linux/alpha/getitimer.S b/sysdeps/unix/sysv/linux/alpha/getitimer.S
index 03ceea10f0..543256272c 100644
--- a/sysdeps/unix/sysv/linux/alpha/getitimer.S
+++ b/sysdeps/unix/sysv/linux/alpha/getitimer.S
@@ -97,7 +97,7 @@ $do32:	ldi	v0, SYS_ify(osf_getitimer)
 	.align 3
 $error:
 	addq	sp, 16, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(GETITIMER)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/getrusage.S b/sysdeps/unix/sysv/linux/alpha/getrusage.S
index 13762a87b1..dd3eced775 100644
--- a/sysdeps/unix/sysv/linux/alpha/getrusage.S
+++ b/sysdeps/unix/sysv/linux/alpha/getrusage.S
@@ -129,7 +129,7 @@ $do32:	ldi	v0, SYS_ify(osf_getrusage)
 	.align 3
 $error:
 	addq	sp, 16, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(GETRUSAGE)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/gettimeofday.S b/sysdeps/unix/sysv/linux/alpha/gettimeofday.S
index 60d642a125..71b8c134dc 100644
--- a/sysdeps/unix/sysv/linux/alpha/gettimeofday.S
+++ b/sysdeps/unix/sysv/linux/alpha/gettimeofday.S
@@ -94,7 +94,7 @@ $do32:	ldi	v0, SYS_ify(osf_gettimeofday)
 	.align 3
 $error:
 	addq	sp, 16, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(GETTIMEOFDAY)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S b/sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S
index 650f7c0715..89e08b3dc9 100644
--- a/sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S
+++ b/sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S
@@ -53,7 +53,7 @@ $error:
 1:	ldgp	gp, 0(gp)
 #endif
 	lda	sp, 16(sp)
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 	END(__ieee_get_fp_control)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S b/sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S
index 53838fe84e..dc1bbbb962 100644
--- a/sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S
+++ b/sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S
@@ -52,7 +52,7 @@ $error:
 1:	ldgp	gp, 0(gp)
 #endif
 	lda	sp, 16(sp)
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 	END(__ieee_set_fp_control)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/rt_sigaction.S b/sysdeps/unix/sysv/linux/alpha/rt_sigaction.S
index e3d01af928..5f166a7094 100644
--- a/sysdeps/unix/sysv/linux/alpha/rt_sigaction.S
+++ b/sysdeps/unix/sysv/linux/alpha/rt_sigaction.S
@@ -56,7 +56,7 @@ ENTRY(__syscall_rt_sigaction)
 	br	gp,2f
 2:	ldgp	gp,0(gp)
 #endif
-	jmp	__syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(__syscall_rt_sigaction)
 
@@ -82,6 +82,6 @@ ENTRY(__syscall_rt_sigaction)
 	ldgp $29,0($27)
 	.prologue 1
 	ldi $0,ENOSYS
-	jmp __syscall_error
+	SYSCALL_ERROR_HANDLER
 END(__syscall_rt_sigaction)
 #endif
diff --git a/sysdeps/unix/sysv/linux/alpha/select.S b/sysdeps/unix/sysv/linux/alpha/select.S
index 57030aaa4e..d3b206df6e 100644
--- a/sysdeps/unix/sysv/linux/alpha/select.S
+++ b/sysdeps/unix/sysv/linux/alpha/select.S
@@ -112,7 +112,7 @@ $do32:
 	.align 3
 $error:
 	addq	sp, 64, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(SELECT)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/setitimer.S b/sysdeps/unix/sysv/linux/alpha/setitimer.S
index 2cc126337d..fdc3d27a8c 100644
--- a/sysdeps/unix/sysv/linux/alpha/setitimer.S
+++ b/sysdeps/unix/sysv/linux/alpha/setitimer.S
@@ -113,7 +113,7 @@ $do32:
 	.align 3
 $error:
 	addq	sp, 48, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(SETITIMER)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/settimeofday.S b/sysdeps/unix/sysv/linux/alpha/settimeofday.S
index 03e9206d48..339913ff51 100644
--- a/sysdeps/unix/sysv/linux/alpha/settimeofday.S
+++ b/sysdeps/unix/sysv/linux/alpha/settimeofday.S
@@ -94,7 +94,7 @@ $do32:
 	.align 3
 $error:
 	addq	sp, 16, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(SETTIMEOFDAY)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/sigsuspend.S b/sysdeps/unix/sysv/linux/alpha/sigsuspend.S
index d6a17851ca..955d82ecc8 100644
--- a/sysdeps/unix/sysv/linux/alpha/sigsuspend.S
+++ b/sysdeps/unix/sysv/linux/alpha/sigsuspend.S
@@ -47,7 +47,7 @@ error:
 	br	gp, 1f
 1:	ldgp	gp, 0(gp)
 #endif
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 	END(__sigsuspend)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/syscall.S b/sysdeps/unix/sysv/linux/alpha/syscall.S
index c354bb6161..10a32d5dc8 100644
--- a/sysdeps/unix/sysv/linux/alpha/syscall.S
+++ b/sysdeps/unix/sysv/linux/alpha/syscall.S
@@ -70,7 +70,7 @@ $error:
 	br	gp, 2f
 2:	ldgp	gp, 0(gp)
 #endif
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(__syscall)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/sysdep.h b/sysdeps/unix/sysv/linux/alpha/sysdep.h
index e56adca8ed..3bf25e6fd2 100644
--- a/sysdeps/unix/sysv/linux/alpha/sysdep.h
+++ b/sysdeps/unix/sysv/linux/alpha/sysdep.h
@@ -17,6 +17,9 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#ifndef _LINUX_ALPHA_SYSDEP_H
+#define _LINUX_ALPHA_SYSDEP_H 1
+
 #ifdef __ASSEMBLER__
 
 #include <asm/pal.h>
@@ -88,118 +91,114 @@
    of the hard-register variables as much as possible.  Thus we copy
    in/out as close to the asm as possible.  */
 
-#define inline_syscall0(name)			\
-{						\
-	register long _sc_0 __asm__("$0");	\
-	register long _sc_19 __asm__("$19");	\
-						\
-	_sc_0 = __NR_##name;			\
-	__asm__("callsys # %0 %1 <= %2"		\
-		: "=r"(_sc_0), "=r"(_sc_19)	\
-		: "0"(_sc_0)			\
-		: inline_syscall_clobbers);	\
-	_sc_ret = _sc_0, _sc_err = _sc_19;	\
-}
-
-#define inline_syscall1(name,arg1)		\
-{						\
-	register long _sc_0 __asm__("$0");	\
-	register long _sc_16 __asm__("$16");	\
-	register long _sc_19 __asm__("$19");	\
-						\
-	_sc_0 = __NR_##name;			\
-	_sc_16 = (long) (arg1);			\
-	__asm__("callsys # %0 %1 <= %2 %3"	\
-		: "=r"(_sc_0), "=r"(_sc_19)	\
-		: "0"(_sc_0), "r"(_sc_16)	\
-		: inline_syscall_clobbers);	\
-	_sc_ret = _sc_0, _sc_err = _sc_19;	\
-}
-
-#define inline_syscall2(name,arg1,arg2)			\
+#define inline_syscall0(name)				\
 {							\
-	register long _sc_0 __asm__("$0");		\
-	register long _sc_16 __asm__("$16");		\
-	register long _sc_17 __asm__("$17");		\
 	register long _sc_19 __asm__("$19");		\
 							\
-	_sc_0 = __NR_##name;				\
-	_sc_16 = (long) (arg1);				\
-	_sc_17 = (long) (arg2);				\
-	__asm__("callsys # %0 %1 <= %2 %3 %4"		\
-		: "=r"(_sc_0), "=r"(_sc_19)		\
-		: "0"(_sc_0), "r"(_sc_16), "r"(_sc_17)	\
-		: inline_syscall_clobbers);		\
-	_sc_ret = _sc_0, _sc_err = _sc_19;		\
+	__asm__("callsys # %0 %1 <= %2"			\
+		: "=v"(_sc_ret), "=r"(_sc_19)		\
+		: "0"(__NR_##name)			\
+		: inline_syscall_clobbers,		\
+		  "$16", "$17", "$18", "$20", "$21");	\
+	_sc_err = _sc_19;				\
 }
 
-#define inline_syscall3(name,arg1,arg2,arg3)		\
+#define inline_syscall1(name,arg1)			\
 {							\
-	register long _sc_0 __asm__("$0");		\
 	register long _sc_16 __asm__("$16");		\
-	register long _sc_17 __asm__("$17");		\
-	register long _sc_18 __asm__("$18");		\
 	register long _sc_19 __asm__("$19");		\
 							\
-	_sc_0 = __NR_##name;				\
 	_sc_16 = (long) (arg1);				\
-	_sc_17 = (long) (arg2);				\
-	_sc_18 = (long) (arg3);				\
-	__asm__("callsys # %0 %1 <= %2 %3 %4 %5"	\
-		: "=r"(_sc_0), "=r"(_sc_19)		\
-		: "0"(_sc_0), "r"(_sc_16), "r"(_sc_17),	\
-		  "r"(_sc_18)				\
-		: inline_syscall_clobbers);		\
-	_sc_ret = _sc_0, _sc_err = _sc_19;		\
+	__asm__("callsys # %0 %1 <= %2 %3"		\
+		: "=v"(_sc_ret), "=r"(_sc_19),		\
+		  "=r"(_sc_16)				\
+		: "0"(__NR_##name), "2"(_sc_16)		\
+		: inline_syscall_clobbers,		\
+		  "$17", "$18", "$20", "$21");		\
+	_sc_err = _sc_19;				\
 }
 
-#define inline_syscall4(name,arg1,arg2,arg3,arg4)	\
-{							\
-	register long _sc_0 __asm__("$0");		\
-	register long _sc_16 __asm__("$16");		\
-	register long _sc_17 __asm__("$17");		\
-	register long _sc_18 __asm__("$18");		\
-	register long _sc_19 __asm__("$19");		\
-							\
-	_sc_0 = __NR_##name;				\
-	_sc_16 = (long) (arg1);				\
-	_sc_17 = (long) (arg2);				\
-	_sc_18 = (long) (arg3);				\
-	_sc_19 = (long) (arg4);				\
-	__asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6"	\
-		: "=r"(_sc_0), "=r"(_sc_19)		\
-		: "0"(_sc_0), "r"(_sc_16), "r"(_sc_17),	\
-		  "r"(_sc_18), "1"(_sc_19)		\
-		: inline_syscall_clobbers);		\
-	_sc_ret = _sc_0, _sc_err = _sc_19;		\
+#define inline_syscall2(name,arg1,arg2)				\
+{								\
+	register long _sc_16 __asm__("$16");			\
+	register long _sc_17 __asm__("$17");			\
+	register long _sc_19 __asm__("$19");			\
+								\
+	_sc_16 = (long) (arg1);					\
+	_sc_17 = (long) (arg2);					\
+	__asm__("callsys # %0 %1 <= %2 %3 %4"			\
+		: "=v"(_sc_ret), "=r"(_sc_19),			\
+		  "=r"(_sc_16), "=r"(_sc_17)			\
+		: "0"(__NR_##name), "2"(_sc_16), "3"(_sc_17)	\
+		: inline_syscall_clobbers,			\
+		  "$18", "$20", "$21");				\
+	_sc_err = _sc_19;					\
 }
 
-#define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5)	\
-{							\
-	register long _sc_0 __asm__("$0");		\
-	register long _sc_16 __asm__("$16");		\
-	register long _sc_17 __asm__("$17");		\
-	register long _sc_18 __asm__("$18");		\
-	register long _sc_19 __asm__("$19");		\
-	register long _sc_20 __asm__("$20");		\
-							\
-	_sc_0 = __NR_##name;				\
-	_sc_16 = (long) (arg1);				\
-	_sc_17 = (long) (arg2);				\
-	_sc_18 = (long) (arg3);				\
-	_sc_19 = (long) (arg4);				\
-	_sc_20 = (long) (arg5);				\
-	__asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7"	\
-		: "=r"(_sc_0), "=r"(_sc_19)		\
-		: "0"(_sc_0), "r"(_sc_16), "r"(_sc_17),	\
-		  "r"(_sc_18), "1"(_sc_19), "r"(_sc_20)	\
-		: inline_syscall_clobbers);		\
-	_sc_ret = _sc_0, _sc_err = _sc_19;		\
+#define inline_syscall3(name,arg1,arg2,arg3)			\
+{								\
+	register long _sc_16 __asm__("$16");			\
+	register long _sc_17 __asm__("$17");			\
+	register long _sc_18 __asm__("$18");			\
+	register long _sc_19 __asm__("$19");			\
+								\
+	_sc_16 = (long) (arg1);					\
+	_sc_17 = (long) (arg2);					\
+	_sc_18 = (long) (arg3);					\
+	__asm__("callsys # %0 %1 <= %2 %3 %4 %5"		\
+		: "=v"(_sc_ret), "=r"(_sc_19),			\
+		  "=r"(_sc_16), "=r"(_sc_17), "=r"(_sc_18)	\
+		: "0"(__NR_##name), "2"(_sc_16), "3"(_sc_17),	\
+		  "4"(_sc_18)					\
+		: inline_syscall_clobbers, "$20", "$21");	\
+	_sc_err = _sc_19;					\
+}
+
+#define inline_syscall4(name,arg1,arg2,arg3,arg4)		\
+{								\
+	register long _sc_16 __asm__("$16");			\
+	register long _sc_17 __asm__("$17");			\
+	register long _sc_18 __asm__("$18");			\
+	register long _sc_19 __asm__("$19");			\
+								\
+	_sc_16 = (long) (arg1);					\
+	_sc_17 = (long) (arg2);					\
+	_sc_18 = (long) (arg3);					\
+	_sc_19 = (long) (arg4);					\
+	__asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6"		\
+		: "=v"(_sc_ret), "=r"(_sc_19),			\
+		  "=r"(_sc_16), "=r"(_sc_17), "=r"(_sc_18)	\
+		: "0"(__NR_##name), "2"(_sc_16), "3"(_sc_17),	\
+		  "4"(_sc_18), "1"(_sc_19)			\
+		: inline_syscall_clobbers, "$20", "$21");	\
+	_sc_err = _sc_19;					\
+}
+
+#define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5)		\
+{								\
+	register long _sc_16 __asm__("$16");			\
+	register long _sc_17 __asm__("$17");			\
+	register long _sc_18 __asm__("$18");			\
+	register long _sc_19 __asm__("$19");			\
+	register long _sc_20 __asm__("$20");			\
+								\
+	_sc_16 = (long) (arg1);					\
+	_sc_17 = (long) (arg2);					\
+	_sc_18 = (long) (arg3);					\
+	_sc_19 = (long) (arg4);					\
+	_sc_20 = (long) (arg5);					\
+	__asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7"		\
+		: "=v"(_sc_ret), "=r"(_sc_19), 			\
+		  "=r"(_sc_16), "=r"(_sc_17), "=r"(_sc_18),	\
+		  "=r"(_sc_20)					\
+		: "0"(__NR_##name), "2"(_sc_16), "3"(_sc_17),	\
+		  "4"(_sc_18), "1"(_sc_19), "5"(_sc_20)		\
+		: inline_syscall_clobbers, "$21");		\
+	_sc_ret = _sc_0, _sc_err = _sc_19;			\
 }
 
 #define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6)	\
 {								\
-	register long _sc_0 __asm__("$0");			\
 	register long _sc_16 __asm__("$16");			\
 	register long _sc_17 __asm__("$17");			\
 	register long _sc_18 __asm__("$18");			\
@@ -207,7 +206,6 @@
 	register long _sc_20 __asm__("$20");			\
 	register long _sc_21 __asm__("$21");			\
 								\
-	_sc_0 = __NR_##name;					\
 	_sc_16 = (long) (arg1);					\
 	_sc_17 = (long) (arg2);					\
 	_sc_18 = (long) (arg3);					\
@@ -215,10 +213,14 @@
 	_sc_20 = (long) (arg5);					\
 	_sc_21 = (long) (arg6);					\
 	__asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8"	\
-		: "=r"(_sc_0), "=r"(_sc_19)			\
-		: "0"(_sc_0), "r"(_sc_16), "r"(_sc_17),		\
-		  "r"(_sc_18), "1"(_sc_19), "r"(_sc_20),	\
-		  "r"(_sc_21)					\
+		: "=v"(_sc_ret), "=r"(_sc_19)			\
+		  "=r"(_sc_16), "=r"(_sc_17), "=r"(_sc_18),	\
+		  "=r"(_sc_20), "=r"(_sc_21)			\
+		: "0"(__NR_##name), "2"(_sc_16), "3"(_sc_17),	\
+		  "4"(_sc_18), "1"(_sc_19), "5"(_sc_20),	\
+		  "6"(_sc_21)					\
 		: inline_syscall_clobbers);			\
-	_sc_ret = _sc_0, _sc_err = _sc_19;			\
+	_sc_err = _sc_19;					\
 }
+
+#endif /* _LINUX_ALPHA_SYSDEP_H */
diff --git a/sysdeps/unix/sysv/linux/alpha/utimes.S b/sysdeps/unix/sysv/linux/alpha/utimes.S
index e9c16db39d..a939255d27 100644
--- a/sysdeps/unix/sysv/linux/alpha/utimes.S
+++ b/sysdeps/unix/sysv/linux/alpha/utimes.S
@@ -99,7 +99,7 @@ $do32:
 	.align 3
 $error:
 	addq	sp, 16, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(UTIMES)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/wait4.S b/sysdeps/unix/sysv/linux/alpha/wait4.S
index b695047890..17c5a97952 100644
--- a/sysdeps/unix/sysv/linux/alpha/wait4.S
+++ b/sysdeps/unix/sysv/linux/alpha/wait4.S
@@ -132,7 +132,7 @@ $do32:	ldi	v0, SYS_ify(osf_wait4)
 	.align 3
 $error:
 	addq	sp, 32, sp
-	jmp	zero, __syscall_error
+	SYSCALL_ERROR_HANDLER
 
 END(WAIT4)