about summary refs log tree commit diff
path: root/sysdeps/alpha
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/alpha')
-rw-r--r--sysdeps/alpha/Makefile75
-rw-r--r--sysdeps/alpha/__longjmp.c20
-rw-r--r--sysdeps/alpha/__math.h20
-rw-r--r--sysdeps/alpha/_mcount.S112
-rw-r--r--sysdeps/alpha/bb_init_func.S85
-rw-r--r--sysdeps/alpha/divl.S61
-rw-r--r--sysdeps/alpha/divlu.S61
-rw-r--r--sysdeps/alpha/divq.S58
-rw-r--r--sysdeps/alpha/divqu.S64
-rw-r--r--sysdeps/alpha/divrem.S169
-rw-r--r--sysdeps/alpha/divrem.m451
-rw-r--r--sysdeps/alpha/ffs.S71
-rw-r--r--sysdeps/alpha/htonl.S42
-rw-r--r--sysdeps/alpha/htons.S36
-rw-r--r--sysdeps/alpha/machine-gmon.h (renamed from sysdeps/alpha/fabs.c)17
-rw-r--r--sysdeps/alpha/macros.m434
-rw-r--r--sysdeps/alpha/ntohl.s2
-rw-r--r--sysdeps/alpha/ntohs.s2
-rw-r--r--sysdeps/alpha/reml.S64
-rw-r--r--sysdeps/alpha/remlu.S64
-rw-r--r--sysdeps/alpha/remq.S61
-rw-r--r--sysdeps/alpha/remqu.S67
-rw-r--r--sysdeps/alpha/setjmp.S4
-rw-r--r--sysdeps/alpha/setjmp_aux.c2
-rw-r--r--sysdeps/alpha/strlen.S75
-rw-r--r--sysdeps/alpha/strlen.c55
26 files changed, 681 insertions, 691 deletions
diff --git a/sysdeps/alpha/Makefile b/sysdeps/alpha/Makefile
index 8573ca811c..4bb1f299e1 100644
--- a/sysdeps/alpha/Makefile
+++ b/sysdeps/alpha/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+# Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
 # Contributed by Brendan Kehoe (brendan@zen.org).
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -16,79 +16,16 @@
 # not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 # Cambridge, MA 02139, USA.
 
+ifeq ($(subdir),gmon)
+sysdep_routines := bb_init_func _mcount
+endif
+
 ifeq ($(subdir),setjmp)
 sysdep_routines := $(sysdep_routines) setjmp_aux
 endif
 
 ifeq ($(subdir),gnulib)
-routines = $(divrem) 
+routines = $(divrem)
 endif	# gnulib
 
-# We distribute these files, even though they are generated,
-# so as to avoid the need for a functioning m4 to build the library.
 divrem := divl divlu divq divqu reml remlu remq remqu
-
-+divrem-NAME-divl := divl
-+divrem-NAME-divlu := divlu
-+divrem-NAME-divq := divq
-+divrem-NAME-divqu := divqu
-+divrem-NAME-reml := reml
-+divrem-NAME-remlu := remlu
-+divrem-NAME-remq := remq
-+divrem-NAME-remqu := remqu
-+divrem-NAME = $(+divrem-NAME-$(basename $(notdir $@)))
-
-+divrem-OP-divl := divl
-+divrem-OP-divlu := divlu
-+divrem-OP-divq := divq
-+divrem-OP-divqu := divqu
-+divrem-OP-reml := reml
-+divrem-OP-remlu := remlu
-+divrem-OP-remq := remq
-+divrem-OP-remqu := remqu
-+divrem-BASEOP-divl := div
-+divrem-BASEOP-divlu := div
-+divrem-BASEOP-divq := div
-+divrem-BASEOP-divqu := div
-+divrem-BASEOP-reml := rem
-+divrem-BASEOP-remlu := rem
-+divrem-BASEOP-remq := rem
-+divrem-BASEOP-remqu := rem
-+divrem-S-divl := true
-+divrem-S-divlu := false
-+divrem-S-divq := true
-+divrem-S-divqu := false
-+divrem-S-reml := true
-+divrem-S-remlu := false
-+divrem-S-remq := true
-+divrem-S-remqu := false
-+divrem-SIZE-divl := l
-+divrem-SIZE-divlu := l
-+divrem-SIZE-divq := q
-+divrem-SIZE-divqu := q
-+divrem-SIZE-reml := l
-+divrem-SIZE-remlu := l
-+divrem-SIZE-remq := q
-+divrem-SIZE-remqu := q
-+divrem-MODE-divl := l
-+divrem-MODE-divlu := lu
-+divrem-MODE-divq := q
-+divrem-MODE-divqu := qu
-+divrem-MODE-reml := l
-+divrem-MODE-remlu := lu
-+divrem-MODE-remq := q
-+divrem-MODE-remqu := qu
-
-$(divrem:%=$(sysdep_dir)/alpha/%.S): $(sysdep_dir)/alpha/divrem.m4 $(sysdep_dir)/alpha/DEFS.h $(sysdep_dir)/alpha/macros.m4
-	(echo "define(OP,\`$(+divrem-NAME)')\
-	       define(BASEOP,\`$(+divrem-BASEOP-$(+divrem-NAME))')\
-	       define(MODE,\`$(+divrem-MODE-$(+divrem-NAME))')\
-	       define(SIZE,\`$(+divrem-SIZE-$(+divrem-NAME))')\
-	       define(SIGNED,\`$(+divrem-S-$(+divrem-NAME))')\
-	       define(SYSDEP_DIR, \`$(sysdep_dir)/alpha')\
-	       /* This file is generated from divrem.m4; DO NOT EDIT! */"; \
-	 cat $<) | $(M4) > $@-tmp
-# Make it unwritable so noone will edit it by mistake.
-	-chmod a-w $@-tmp
-	mv -f $@-tmp $@
-	test ! -d CVS || cvs commit -m'Regenerated from $<' $@
diff --git a/sysdeps/alpha/__longjmp.c b/sysdeps/alpha/__longjmp.c
index f3f35eec9c..65b6804bd3 100644
--- a/sysdeps/alpha/__longjmp.c
+++ b/sysdeps/alpha/__longjmp.c
@@ -38,6 +38,8 @@ register double
 void
 __longjmp (__jmp_buf env, int val)
 {
+  register long int retval asm ("$0");
+
   /* Restore the integer registers.  */
   r9 = env[0].__9;
   r10 = env[0].__10;
@@ -73,18 +75,18 @@ __longjmp (__jmp_buf env, int val)
      precisely the FP and SP the desired environment needs,
      we must avoid the compiler doing anything with the stack.  */
 
+
+  asm volatile
+    ("cmoveq %1, 1, %0\n\t"	/* $0 = val ?: 1; */
+     "ret $31, (%2), 1"	/* return $0 */
+     : "=r" (retval)
+     /* The "0" constraint should force VAL into $0.  */
+     : "0" (val), "r" (retpc));
+
   while (1)
     {
       /* The loop is just to avoid `volatile function does return' warnings.
 	 The instruction will only be executed once.  */
-
-      register long int retval asm ("$0");
-
-      asm volatile
-	("cmoveq %1, 1, %0\n\t"	/* $0 = val ?: 1; */
-	 "ret $31, (%2), 1"	/* return $0 */
-	 : "=r" (retval)
-	 /* The "0" constraint should force VAL into $0.  */
-	 : "0" (val), "r" (retpc));
+      asm volatile ("");
     }
 }
diff --git a/sysdeps/alpha/__math.h b/sysdeps/alpha/__math.h
index 5461fca2ac..9aea9d7097 100644
--- a/sysdeps/alpha/__math.h
+++ b/sysdeps/alpha/__math.h
@@ -1,5 +1,7 @@
-/* Copyright (C) 1992 Free Software Foundation, Inc.
+/* Inline math functions for Alpha.
+Copyright (C) 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by David Mosberger-Tang.
 
 The GNU C Library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public License as
@@ -32,4 +34,20 @@ fabs (double __x)
   return __x;
 }
 
+extern __inline double
+atan (double __x)
+{
+  extern double __atan2 (double, double);
+  return __atan2 (__x, 1.0);
+}
+
+#ifdef __USE_MISC
+extern __inline double
+cabs (struct __cabs_complex __z)
+{
+  extern double __hypot (double, double);
+  return __hypot(__z.__x, __z.__y);
+}
+#endif
+
 #endif
diff --git a/sysdeps/alpha/_mcount.S b/sysdeps/alpha/_mcount.S
new file mode 100644
index 0000000000..2d6e2ed532
--- /dev/null
+++ b/sysdeps/alpha/_mcount.S
@@ -0,0 +1,112 @@
+/* Machine-specific calling sequence for `mcount' profiling function.  alpha
+Copyright (C) 1995 Free Software Foundation, Inc.
+Contributed by David Mosberger (davidm@cs.arizona.edu).
+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 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 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* Assembly stub to invoke _mcount().  Compiler generated code calls
+this stub after executing a function's prologue and without saving any
+registers.  It is therefore necessary to preserve a0..a5 as they may
+contain function arguments.  To work correctly with frame- less
+functions, it is also necessary to preserve ra.  Finally, division
+routines are invoked with a special calling convention and the
+compiler treats those calls as if they were instructions.  In
+particular, it doesn't save any of the temporary registers (caller
+saved registers).  It is therefore necessary to preserve all
+caller-saved registers as well
+ 
+Upon entering _mcount, register $at holds the return address and ra
+holds the return address of the function's caller (selfpc and frompc,
+respectively in gmon.c language...). */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+# include <regdef.h>
+#endif
+
+#undef ret	/* discard `ret' as defined in sysdep.h */
+
+	.set	noat
+	.set	noreorder
+
+ENTRY(_mcount)
+	subq	 sp, 0xb0, sp
+	stq	 a0, 0x00(sp)
+	mov	 ra, a0		# a0 = caller-pc
+	stq	 a1, 0x08(sp)
+	mov	$at, a1		# a1 = self-pc
+	stq	$at, 0x10(sp)
+
+	stq	 a2, 0x18(sp)
+	stq	 a3, 0x20(sp)
+	stq	 a4, 0x28(sp)
+	stq	 a5, 0x30(sp)
+	stq	 ra, 0x38(sp)
+	stq	 gp, 0x40(sp)
+
+	br	gp, 1f
+1:	ldgp	gp, 0(gp)
+
+	stq	 t0, 0x48(sp)
+	stq	 t1, 0x50(sp)
+	stq	 t2, 0x58(sp)
+	stq	 t3, 0x60(sp)
+	stq	 t4, 0x68(sp)
+	stq	 t5, 0x70(sp)
+	stq	 t6, 0x78(sp)
+
+	lda	 pv, __mcount
+
+	stq	 t7, 0x80(sp)
+	stq	 t8, 0x88(sp)
+	stq	 t9, 0x90(sp)
+	stq	t10, 0x98(sp)
+	stq	t11, 0xa0(sp)
+	stq	 v0, 0xa8(sp)
+
+	jsr	ra, (pv), __mcount
+
+	ldq	 a0, 0x00(sp)
+	ldq	 a1, 0x08(sp)
+	ldq	$at, 0x10(sp)	# restore self-pc
+	ldq	 a2, 0x18(sp)
+	ldq	 a3, 0x20(sp)
+	ldq	 a4, 0x28(sp)
+	ldq	 a5, 0x30(sp)
+	ldq	 ra, 0x38(sp)
+	ldq	 gp, 0x40(sp)
+	mov	$at, pv		# make pv point to return address
+	ldq	 t0, 0x48(sp)	# this is important under OSF/1 to
+	ldq	 t1, 0x50(sp)	# ensure that the code that we return
+	ldq	 t2, 0x58(sp)	# can correctly compute its gp
+	ldq	 t3, 0x60(sp)
+	ldq	 t4, 0x68(sp)
+	ldq	 t5, 0x70(sp)
+	ldq	 t6, 0x78(sp)
+	ldq	 t7, 0x80(sp)
+	ldq	 t8, 0x88(sp)
+	ldq	 t9, 0x90(sp)
+	ldq	t10, 0x98(sp)
+	ldq	t11, 0xa0(sp)
+	ldq	 v0, 0xa8(sp)
+
+	addq	sp, 0xb0, sp
+	ret	zero,($at),1
+
+	.end _mcount
diff --git a/sysdeps/alpha/bb_init_func.S b/sysdeps/alpha/bb_init_func.S
new file mode 100644
index 0000000000..9bf985ccc0
--- /dev/null
+++ b/sysdeps/alpha/bb_init_func.S
@@ -0,0 +1,85 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   Contributed by David Mosberger (davidm@cs.arizona.edu).
+
+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 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 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* __bb_init_func is invoked at the beginning of each function, before
+any registers have been saved.  It is therefore safe to use any
+caller-saved (call-used) registers (except for argument registers
+a1-a5). */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+# include <regdef.h>
+#endif
+
+/*
+ * These offsets should match with "struct bb" declared in gcc/libgcc2.c.
+ */
+#define	ZERO_WORD	0x00
+#define NEXT		0x20
+
+	.set	noat
+	.set	noreorder
+
+ENTRY(__bb_init_func)
+	ldq	t0, ZERO_WORD(a0)	/* t0 <- blocks->zero_word */
+	beq	t0, init		/* not initialized yet -> */
+	ret
+
+
+init:	subq	sp, 0x38, sp
+	stq	pv, 0x30(sp)
+	br	pv, 1f
+1:	ldgp	gp, 0(pv)
+
+	lda	t1, __bb_head
+	lda	t3, _gmonparam
+	ldq	t2, 0(t1)
+	ldl	t3, 0(t3)		/* t3 = _gmonparam.state */
+	ldi	t0, 1
+	stq	t0, ZERO_WORD(a0)	/* blocks->zero_word = 1 */
+	stq	t2, NEXT(a0)		/* blocks->next = __bb_head */
+	stq	a0, 0(t1)
+	bne	t2, leave
+	beq	t3, leave		/* t3 == GMON_PROF_ON? yes -> */
+
+	/* also need to initialize destructor: */
+	stq	ra, 0x00(sp)
+	lda	a0, __bb_exit_func
+	stq	a1, 0x08(sp)
+	lda	pv, atexit
+	stq	a2, 0x10(sp)
+	stq	a3, 0x18(sp)
+	stq	a4, 0x20(sp)
+	stq	a5, 0x28(sp)
+	jsr	ra, (pv), atexit
+	ldq	ra, 0x00(sp)
+	ldq	a1, 0x08(sp)
+	ldq	a2, 0x10(sp)
+	ldq	a3, 0x18(sp)
+	ldq	a4, 0x20(sp)
+	ldq	a5, 0x28(sp)
+
+leave:	ldq	pv, 0x30(sp)
+	addq	sp, 0x38, sp
+	ret
+	
+	.end __bb_init_func
diff --git a/sysdeps/alpha/divl.S b/sysdeps/alpha/divl.S
index 5c94362cf5..7dbb5048c7 100644
--- a/sysdeps/alpha/divl.S
+++ b/sysdeps/alpha/divl.S
@@ -1,57 +1,6 @@
-      /* This file is generated from divrem.m4; DO NOT EDIT! */
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
+#define IS_REM		0
+#define SIZE		4
+#define SIGNED		1
+#define FUNC_NAME	__divl
 
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-
-
-
-
-
-FUNC__(divl)
-	/* First set up the dividend.  */
-		sextl t10, t10
-
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-	
-
-	/* Then set up the divisor.  */
-		sextl t11, t11
-
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-	
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-		sextl t12, t12
-
-
-	
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(divl)
+#include "divrem.S"
diff --git a/sysdeps/alpha/divlu.S b/sysdeps/alpha/divlu.S
index 3a7589d355..9cc71da308 100644
--- a/sysdeps/alpha/divlu.S
+++ b/sysdeps/alpha/divlu.S
@@ -1,57 +1,6 @@
-      /* This file is generated from divrem.m4; DO NOT EDIT! */
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
+#define IS_REM		0
+#define SIZE		4
+#define SIGNED		0
+#define FUNC_NAME	__divlu
 
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-
-
-
-
-
-FUNC__(divlu)
-	/* First set up the dividend.  */
-		zapnot t10, 0xf, t10
-
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-	
-
-	/* Then set up the divisor.  */
-		zapnot t11, 0xf, t11
-
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-	
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-		sextl t12, t12
-
-
-	
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(divlu)
+#include "divrem.S"
diff --git a/sysdeps/alpha/divq.S b/sysdeps/alpha/divq.S
index 730a338f63..f7af8d62a3 100644
--- a/sysdeps/alpha/divq.S
+++ b/sysdeps/alpha/divq.S
@@ -1,54 +1,6 @@
-      /* This file is generated from divrem.m4; DO NOT EDIT! */
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
+#define IS_REM		0
+#define SIZE		8
+#define SIGNED		1
+#define FUNC_NAME	__divq
 
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-
-
-
-
-
-FUNC__(divq)
-	/* First set up the dividend.  */
-	
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-	
-
-	/* Then set up the divisor.  */
-	
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-	
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-	
-
-	
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(divq)
+#include "divrem.S"
diff --git a/sysdeps/alpha/divqu.S b/sysdeps/alpha/divqu.S
index 7614742440..faf2932cb5 100644
--- a/sysdeps/alpha/divqu.S
+++ b/sysdeps/alpha/divqu.S
@@ -1,60 +1,6 @@
-      /* This file is generated from divrem.m4; DO NOT EDIT! */
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
+#define IS_REM		0
+#define SIZE		8
+#define SIGNED		0
+#define FUNC_NAME	__divqu
 
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-
-
-
-
-
-FUNC__(divqu)
-	/* First set up the dividend.  */
-	
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-		ldit	$f26, 18446744073709551616.0
-	addt	$f26, $f10, $f26
-	fcmovlt	$f10, $f26, $f10
-
-
-	/* Then set up the divisor.  */
-	
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-		ldit	$f26, 18446744073709551616.0
-	addt	$f26, $f1, $f26
-	fcmovlt	$f1, $f26, $f1
-
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-	
-
-	
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(divqu)
+#include "divrem.S"
diff --git a/sysdeps/alpha/divrem.S b/sysdeps/alpha/divrem.S
new file mode 100644
index 0000000000..e6293bf355
--- /dev/null
+++ b/sysdeps/alpha/divrem.S
@@ -0,0 +1,169 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   Contributed by David Mosberger (davidm@cs.arizona.edu).
+
+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 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 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* The current Alpha chips don't provide hardware for integer
+division.  The C compiler expects the functions
+
+	__divqu: 64-bit unsigned long divide
+	__remqu: 64-bit unsigned long remainder
+	__divqs/__remqs: signed 64-bit
+	__divlu/__remlu: unsigned 32-bit
+	__divls/__remls: signed 32-bit
+
+These are not normal C functions: instead of the normal calling
+sequence, these expect their arguments in registers t10 and t11, and
+return the result in t12 (aka pv). Registers AT and v0 may be
+clobbered (assembly temporary), anything else must be saved.  */
+
+#ifdef __linux__
+# include <alpha/regdef.h>
+# include <asm/gentrap.h>
+# include <asm/pal.h>
+#else
+# include <regdef.h>
+# include <machine/pal.h>
+#endif
+
+#ifdef DEBUG
+# define arg1		a0
+# define arg2		a1
+# define result		v0
+# define mask		t0
+# define tmp0		t1
+# define tmp1		t2
+# define sign		t3
+# define retaddr	ra
+#else
+# define arg1		t10
+# define arg2		t11
+# define result		t12
+# define mask		v0
+# define tmp0		t0
+# define tmp1		t1
+# define sign		t2
+# define retaddr	t9
+#endif
+
+# define divisor	arg2
+#if IS_REM
+# define dividend	result
+# define quotient	arg1
+# define GETDIVIDEND	bis arg1,zero,dividend
+#else
+# define dividend	arg1
+# define quotient	result
+# define GETDIVIDEND
+#endif
+
+#if SIZE == 8
+# define LONGIFYarg1	GETDIVIDEND
+# define LONGIFYarg2
+#else
+# if SIGNED
+#  define LONGIFYarg1	addl	arg1,zero,dividend
+#  define LONGIFYarg2	addl	arg2,zero,divisor
+# else
+#  define LONGIFYarg1	zapnot	arg1,0x0f,dividend
+#  define LONGIFYarg2	zapnot	arg2,0x0f,divisor
+# endif
+#endif
+
+#if SIGNED
+# define SETSIGN(sign,reg,tmp)	subq zero,reg,tmp; cmovlt sign,tmp,reg
+# if IS_REM
+#  define GETSIGN(x,y,s)	bis	x,zero,s
+# else
+#  define GETSIGN(x,y,s)	xor	x,y,s
+# endif
+#else
+# define SETSIGN(sign,reg,tmp)
+# define GETSIGN(x,y,s)
+#endif
+
+	.set noreorder
+	.set noat
+
+	.ent FUNC_NAME
+	.globl FUNC_NAME
+
+	.align 5
+FUNC_NAME:
+#	define FRAME_SIZE	0x30
+	.frame	sp,FRAME_SIZE,ra,0
+	lda	sp,-FRAME_SIZE(sp)
+	.prologue 1
+	stq	arg1,0x00(sp)
+	LONGIFYarg1
+	stq	arg2,0x08(sp)
+	LONGIFYarg2
+	stq	mask,0x10(sp)
+	bis	zero,1,mask
+	stq	tmp0,0x18(sp)
+	bis	zero,zero,quotient
+	stq	tmp1,0x20(sp)
+	beq	divisor,divbyzero
+	stq	sign,0x28(sp)
+	GETSIGN(dividend,divisor,sign)
+#if SIGNED
+	subq	zero,dividend,tmp0
+	subq	zero,divisor,tmp1
+	cmovlt	dividend,tmp0,dividend
+	cmovlt	divisor,tmp1,divisor
+#endif
+	/*
+	 * Shift divisor left until either bit 63 is set or until it
+	 * is at least as big as the dividend:
+	 */
+	.align	3
+1:	cmpule	dividend,divisor,AT
+	blt	divisor,2f
+	blbs	AT,2f
+	addq	mask,mask,mask
+	addq	divisor,divisor,divisor
+	br	1b
+
+	.align	3
+2:	addq	mask,quotient,tmp0
+	cmpule	divisor,dividend,AT
+	subq	dividend,divisor,tmp1
+	srl	divisor,1,divisor
+	srl	mask,1,mask
+	cmovlbs	AT,tmp0,quotient
+	cmovlbs	AT,tmp1,dividend
+	bne	mask,2b
+
+	ldq	arg1,0x00(sp)
+	SETSIGN(sign,result,tmp0)
+done:	ldq	arg2,0x08(sp)
+	ldq	mask,0x10(sp)
+	ldq	tmp0,0x18(sp)
+	ldq	tmp1,0x20(sp)
+	ldq	sign,0x28(sp)
+	lda	sp,FRAME_SIZE(sp)
+	ret	zero,(retaddr),0
+
+divbyzero:
+	lda	a0,GEN_INTDIV(zero)
+	call_pal PAL_gentrap
+	bis	zero,zero,result	/* if trap returns, return 0 */
+	ldq	arg1,0x00(sp)
+	br	done
+
+	.end FUNC_NAME
diff --git a/sysdeps/alpha/divrem.m4 b/sysdeps/alpha/divrem.m4
deleted file mode 100644
index d2f36383cb..0000000000
--- a/sysdeps/alpha/divrem.m4
+++ /dev/null
@@ -1,51 +0,0 @@
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
-
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-define(path, `SYSDEP_DIR/macros.m4')dnl
-include(path)
-
-FUNC__(OP)
-	/* First set up the dividend.  */
-	EXTEND(t10)
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-	ADJQU($f10)
-
-	/* Then set up the divisor.  */
-	EXTEND(t11)
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-	ADJQU($f1)
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-	FULLEXTEND(t12)
-
-	DOREM
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(OP)
diff --git a/sysdeps/alpha/ffs.S b/sysdeps/alpha/ffs.S
new file mode 100644
index 0000000000..7676b85aaa
--- /dev/null
+++ b/sysdeps/alpha/ffs.S
@@ -0,0 +1,71 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   Contributed by David Mosberger (davidm@cs.arizona.edu).
+
+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 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 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* Finds the first bit set in an integer.  Optimized for the Alpha
+architecture.  */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+#include <regdef.h>
+#endif
+
+        .set noreorder
+        .set noat
+
+ENTRY(ffs)
+	.prologue 0
+
+	ldq_u	zero, 0(sp)	# on the 21064, this helps dual-issuing
+	addl	a0, zero, a0	# the last insn and reduces the stall
+        negq    a0, t0		# due to the srl instruction
+        and     a0, t0, t0
+	clr	v0
+	beq	a0, done
+
+	# now do binary search for first non-zero bit
+
+	zapnot	t0, 0x03, t2
+        addq    v0, 16, t3
+        cmoveq  t2, t3, v0
+
+	zapnot	t0, 0x05, t2
+        addq    v0, 8, t3
+        cmoveq  t2, t3, v0
+
+	srl	t0, v0, t0
+	addq	v0, 1, v0
+
+        and     t0, 0x0f, t2
+        addq    v0, 4, t3
+        cmoveq  t2, t3, v0
+
+        and     t0, 0x33, t2
+        addq    v0, 2, t3
+        cmoveq  t2, t3, v0
+
+        and     t0, 0x55, t2
+        addq    v0, 1, t3
+        cmoveq  t2, t3, v0
+
+done:   ret
+
+        .end    ffs
diff --git a/sysdeps/alpha/htonl.S b/sysdeps/alpha/htonl.S
new file mode 100644
index 0000000000..d0bf7e1718
--- /dev/null
+++ b/sysdeps/alpha/htonl.S
@@ -0,0 +1,42 @@
+/* Copyright (C) 1996 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 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 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+#include <regdef.h>
+#endif
+
+ENTRY(__htonl)
+	extlh	a0,5,t1		# t1 = dd000000
+	zap	a0,0xfd,t2	# t2 = 0000cc00
+	sll	t2,5,t2		# t2 = 00198000
+	s8addl	t2,t1,t1	# t1 = ddcc0000
+	zap	a0,0xfb,t2	# t2 = 00bb0000
+	srl	t2,8,t2		# t2 = 0000bb00
+	extbl	a0,3,v0		# v0 = 000000aa
+	or	t1,v0,v0	# v0 = ddcc00aa
+	or	t2,v0,v0	# v0 = ddccbbaa
+	ret
+
+	.end	__htonl
+
+strong_alias_asm(__htonl, __ntohl)
+weak_alias(__htonl, htonl)
+weak_alias(__htonl, ntohl)
diff --git a/sysdeps/alpha/htons.S b/sysdeps/alpha/htons.S
new file mode 100644
index 0000000000..6e18c7c441
--- /dev/null
+++ b/sysdeps/alpha/htons.S
@@ -0,0 +1,36 @@
+/* Copyright (C) 1996 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 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 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+#include <regdef.h>
+#endif
+
+ENTRY(__htons)
+	extwh	a0,7,t1		# t1 = bb00
+	extbl	a0,1,v0		# v0 = 00aa
+	bis	v0,t1,v0	# v0 = bbaa
+	ret
+
+	.end	__htons
+
+strong_alias_asm(__htons, __ntohs)
+weak_alias(__htons, htons)
+weak_alias(__htons, ntohs)
diff --git a/sysdeps/alpha/fabs.c b/sysdeps/alpha/machine-gmon.h
index 321df0d1e1..a551e9f8b1 100644
--- a/sysdeps/alpha/fabs.c
+++ b/sysdeps/alpha/machine-gmon.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 1992 Free Software Foundation, Inc.
+/* Machine-specific calling sequence for `mcount' profiling function.  alpha
+Copyright (C) 1995 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
@@ -16,13 +17,9 @@ License along with the GNU C Library; see the file COPYING.LIB.  If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#define __NO_MATH_INLINES
+#define _MCOUNT_DECL void __mcount
 
-#include <math.h>
-
-__inline double
-fabs (double __x)
-{
-  __asm ("cpys $f31, %1, %0" : "=f" (__x) : "f" (__x));
-  return __x;
-}
+/* Call __mcount with our the return PC for our caller, and the return
+   PC our caller will return to.  Empty since we use an assembly stub
+   instead. */
+#define MCOUNT
diff --git a/sysdeps/alpha/macros.m4 b/sysdeps/alpha/macros.m4
deleted file mode 100644
index f8c1fe9662..0000000000
--- a/sysdeps/alpha/macros.m4
+++ /dev/null
@@ -1,34 +0,0 @@
-dnl NOTE: The $1 below is the argument to EXTEND, not register $1.
-define(EXTEND,
-`ifelse(SIZE, `l',
-`ifelse(SIGNED, `true',
-`	sextl $1, $1
-',dnl
-`	zapnot $1, 0xf, $1
-')')')dnl
-
-dnl FULLEXTEND -- extend the register named in the first argument
-define(FULLEXTEND,
-`ifelse(SIZE, `l',
-`	sextl $1, $1
-')')dnl
-
-dnl This is used by divqu.
-define(ADJQU,
-`ifelse(MODE, `qu',
-`	ldit	$f26, 18446744073709551616.0
-	addt	$f26, $1, $f26
-	fcmovlt	$1, $f26, $1
-')')dnl
-
-define(DOREM,
-`ifelse(BASEOP, `rem',
-`	/* Compute the remainder.  */
-ifelse(SIZE, `l',
-`	mull t11, t12, t11
-	subl t10, t11, t12
-',dnl Note mulq/subq were only really used in remq, but we will find out
-dnl   if assuming they apply to remqu as well is wrong or not.
-`	mulq t11, t12, t11
-	subq t10, t11, t12
-')')')dnl
diff --git a/sysdeps/alpha/ntohl.s b/sysdeps/alpha/ntohl.s
new file mode 100644
index 0000000000..6a99a01dc4
--- /dev/null
+++ b/sysdeps/alpha/ntohl.s
@@ -0,0 +1,2 @@
+/* This is a dummy to avoid including the generic version.  htonl and
+ntohl are identical and htonl.S defines appropriate aliases.  */
diff --git a/sysdeps/alpha/ntohs.s b/sysdeps/alpha/ntohs.s
new file mode 100644
index 0000000000..69992a894c
--- /dev/null
+++ b/sysdeps/alpha/ntohs.s
@@ -0,0 +1,2 @@
+/* This is a dummy to avoid including the generic version.  htons and
+ntohs are identical and htons.S defines appropriate aliases.  */
diff --git a/sysdeps/alpha/reml.S b/sysdeps/alpha/reml.S
index 95896fb831..cede136acd 100644
--- a/sysdeps/alpha/reml.S
+++ b/sysdeps/alpha/reml.S
@@ -1,60 +1,6 @@
-      /* This file is generated from divrem.m4; DO NOT EDIT! */
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
+#define IS_REM		1
+#define SIZE		4
+#define SIGNED		1
+#define FUNC_NAME	__reml
 
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-
-
-
-
-
-FUNC__(reml)
-	/* First set up the dividend.  */
-		sextl t10, t10
-
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-	
-
-	/* Then set up the divisor.  */
-		sextl t11, t11
-
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-	
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-		sextl t12, t12
-
-
-		/* Compute the remainder.  */
-	mull t11, t12, t11
-	subl t10, t11, t12
-
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(reml)
+#include "divrem.S"
diff --git a/sysdeps/alpha/remlu.S b/sysdeps/alpha/remlu.S
index 24e07cf327..3658d92bc1 100644
--- a/sysdeps/alpha/remlu.S
+++ b/sysdeps/alpha/remlu.S
@@ -1,60 +1,6 @@
-      /* This file is generated from divrem.m4; DO NOT EDIT! */
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
+#define IS_REM		1
+#define SIZE		4
+#define SIGNED		0
+#define FUNC_NAME	__remlu
 
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-
-
-
-
-
-FUNC__(remlu)
-	/* First set up the dividend.  */
-		zapnot t10, 0xf, t10
-
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-	
-
-	/* Then set up the divisor.  */
-		zapnot t11, 0xf, t11
-
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-	
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-		sextl t12, t12
-
-
-		/* Compute the remainder.  */
-	mull t11, t12, t11
-	subl t10, t11, t12
-
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(remlu)
+#include "divrem.S"
diff --git a/sysdeps/alpha/remq.S b/sysdeps/alpha/remq.S
index ce38c2460a..61f2067383 100644
--- a/sysdeps/alpha/remq.S
+++ b/sysdeps/alpha/remq.S
@@ -1,57 +1,6 @@
-      /* This file is generated from divrem.m4; DO NOT EDIT! */
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
+#define IS_REM		1
+#define SIZE		8
+#define SIGNED		1
+#define FUNC_NAME	__remq
 
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-
-
-
-
-
-FUNC__(remq)
-	/* First set up the dividend.  */
-	
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-	
-
-	/* Then set up the divisor.  */
-	
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-	
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-	
-
-		/* Compute the remainder.  */
-	mulq t11, t12, t11
-	subq t10, t11, t12
-
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(remq)
+#include "divrem.S"
diff --git a/sysdeps/alpha/remqu.S b/sysdeps/alpha/remqu.S
index 26bdd3b037..e22d5ac1c8 100644
--- a/sysdeps/alpha/remqu.S
+++ b/sysdeps/alpha/remqu.S
@@ -1,63 +1,6 @@
-      /* This file is generated from divrem.m4; DO NOT EDIT! */
-/* For each N divided by D, we do:
-      result = (double) N / (double) D
-   Then, for each N mod D, we do:
-      result = N - (D * divMODE (N, D))
+#define IS_REM		1
+#define SIZE		8
+#define SIGNED		0
+#define FUNC_NAME	__remqu
 
-   FIXME:
-   The q and qu versions won't deal with operands > 50 bits.  We also
-   don't check for divide by zero.  */
-
-#include "DEFS.h"
-#if 0
-/* We do not handle div by zero yet.  */
-#include <machine/pal.h>
-#endif
-#include <sysdep.h>
-
-/* Avoid the definition of ret that we set in the alpha sysdep.h.  */
-#undef ret
-
-
-
-
-
-
-FUNC__(remqu)
-	/* First set up the dividend.  */
-	
-	stq t10,0(sp)
-	ldt $f10,0(sp)
-	cvtqt $f10,$f10
-		ldit	$f26, 18446744073709551616.0
-	addt	$f26, $f10, $f26
-	fcmovlt	$f10, $f26, $f10
-
-
-	/* Then set up the divisor.  */
-	
-	stq t11,0(sp)
-	ldt $f1,0(sp)
-	cvtqt $f1,$f1
-		ldit	$f26, 18446744073709551616.0
-	addt	$f26, $f1, $f26
-	fcmovlt	$f1, $f26, $f1
-
-
-	/* Do the division.  */
-	divt $f10,$f1,$f10
-	cvttqc $f10,$f10
-
-	/* Put the result in t12.  */
-	stt $f10,0(sp)
-	ldq t12,0(sp)
-	
-
-		/* Compute the remainder.  */
-	mulq t11, t12, t11
-	subq t10, t11, t12
-
-
-	lda sp,16(sp)
-	ret zero,(t9),1
-	.end NAME__(remqu)
+#include "divrem.S"
diff --git a/sysdeps/alpha/setjmp.S b/sysdeps/alpha/setjmp.S
index 08932ccd1a..8ea2b50f87 100644
--- a/sysdeps/alpha/setjmp.S
+++ b/sysdeps/alpha/setjmp.S
@@ -23,7 +23,7 @@ Cambridge, MA 02139, USA.  */
    extra arguments.  */
 ENTRY (__sigsetjmp)
 	lda $27, __sigsetjmp_aux/* Load address to jump to.  */
-	bis $15, $15, $18	/* Pass FP as 3rd arg.  */
-	bis $30, $30, $19	/* Pass SP as 4th arg.  */
+	bis $30, $30, $18	/* Pass SP as 3rd arg.  */
+	bis $15, $15, $19	/* Pass FP as 4th arg.  */
 	jmp $31, ($27), __sigsetjmp_aux /* Call __sigsetjmp_aux.  */
 	.end __sigsetjmp
diff --git a/sysdeps/alpha/setjmp_aux.c b/sysdeps/alpha/setjmp_aux.c
index f92517be92..0f05f8b043 100644
--- a/sysdeps/alpha/setjmp_aux.c
+++ b/sysdeps/alpha/setjmp_aux.c
@@ -69,6 +69,8 @@ __sigsetjmp_aux (sigjmp_buf env, int savemask, long int *sp, long int *fp)
   /* Save the signal mask if requested.  */
   __sigjmp_save (env, savemask);
 
+  retpc = env[0].__jmpbuf[0].__pc;	/* restore ra, ugly... */
+
   /* Return to the original caller of __sigsetjmp.  */
   return 0;
 }
diff --git a/sysdeps/alpha/strlen.S b/sysdeps/alpha/strlen.S
new file mode 100644
index 0000000000..7e6a61be8c
--- /dev/null
+++ b/sysdeps/alpha/strlen.S
@@ -0,0 +1,75 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   Contributed by David Mosberger (davidm@cs.arizona.edu).
+
+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 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 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* Finds length of a 0-terminated string.  Optimized for the Alpha
+architecture:
+
+      - memory accessed as aligned quadwords only
+      - uses bcmpge to compare 8 bytes in parallel
+      - does binary search to find 0 byte in last
+        quadword (HAKMEM needed 12 instructions to
+        do this instead of the 9 instructions that
+        binary search needs).  */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+#include <regdef.h>
+#endif
+
+        .set noreorder
+        .set noat
+
+ENTRY(strlen)
+        ldq_u   t0, 0(a0)       # load first quadword (a0 may be misaligned)
+        lda     t1, -1(zero)
+        insqh   t1, a0, t1
+        andnot  a0, 7, v0
+        or      t1, t0, t0
+        cmpbge  zero, t0, t1    # t1 <- bitmask: bit i == 1 <==> i-th byte == 0
+        bne     t1, found
+
+loop:   ldq     t0, 8(v0)
+        addq    v0, 8, v0       # addr += 8
+        nop                     # helps dual issue last two insns
+        cmpbge  zero, t0, t1
+        beq     t1, loop
+
+found:  blbs    t1, done        # make aligned case fast
+        negq    t1, t2
+        and     t1, t2, t1
+
+        and     t1, 0x0f, t0
+        addq    v0, 4, t2
+        cmoveq  t0, t2, v0
+
+        and     t1, 0x33, t0
+        addq    v0, 2, t2
+        cmoveq  t0, t2, v0
+
+        and     t1, 0x55, t0
+        addq    v0, 1, t2
+        cmoveq  t0, t2, v0
+
+done:   subq    v0, a0, v0
+        ret
+
+        .end    strlen
diff --git a/sysdeps/alpha/strlen.c b/sysdeps/alpha/strlen.c
deleted file mode 100644
index 36f106c9c3..0000000000
--- a/sysdeps/alpha/strlen.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (C) 1992 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 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 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
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <string.h>
-
-/* Return the length of the null-terminated string STR.  Scan for
-   the null terminator quickly by testing eight bytes at a time.  */
-
-size_t
-strlen (const char *str)
-{
-  const char *char_ptr;
-  const unsigned long int *longword_ptr;
-
-  /* Handle the first few characters by reading one character at a time.
-     Do this until STR is aligned on a 8-byte border.  */
-  for (char_ptr = str; ((unsigned long int) char_ptr & 7) != 0; ++char_ptr)
-    if (*char_ptr == '\0')
-      return char_ptr - str;
-
-  longword_ptr = (unsigned long int *) char_ptr;
-
-  for (;;)
-    {
-      const unsigned long int longword = *longword_ptr++;
-      int mask;
-
-      /* Set bits in MASK if bytes in LONGWORD are zero.  */
-      asm ("cmpbge $31, %1, %0" : "=r" (mask) : "r" (longword));
-      if (mask)
-	{
-	  /* Which of the bytes was the zero?  */
-	  const char *cp = (const char *) (longword_ptr - 1);
-	  int i;
-
-	  for (i = 0; i < 8; i++)
-	    if (cp[i] == 0)
-	      return cp - str + i;
-	}
-    }
-}