about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/alpha/dl-machine.h13
-rw-r--r--sysdeps/alpha/elf/start.S19
-rw-r--r--sysdeps/m68k/fpu/k_cos.c12
-rw-r--r--sysdeps/m68k/fpu/k_sin.c16
-rw-r--r--sysdeps/m68k/fpu/k_tan.c16
-rw-r--r--sysdeps/mach/hurd/send.c8
-rw-r--r--sysdeps/mach/hurd/sendto.c13
-rw-r--r--sysdeps/posix/profil.c9
-rw-r--r--sysdeps/stub/ustat.c2
-rw-r--r--sysdeps/unix/Makefile8
-rw-r--r--sysdeps/unix/alpha/sysdep.S3
-rw-r--r--sysdeps/unix/make-syscalls.sh15
-rw-r--r--sysdeps/unix/sysv/linux/alpha/Dist3
-rw-r--r--sysdeps/unix/sysv/linux/alpha/Makefile2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/init-first.h39
-rw-r--r--sysdeps/unix/sysv/linux/alpha/ioperm.c47
-rw-r--r--sysdeps/unix/sysv/linux/alpha/sys/io.h59
-rw-r--r--sysdeps/unix/sysv/linux/i386/Dist2
-rw-r--r--sysdeps/unix/sysv/linux/i386/init-first.h38
-rw-r--r--sysdeps/unix/sysv/linux/i386/mmap.S8
-rw-r--r--sysdeps/unix/sysv/linux/init-first.c30
21 files changed, 240 insertions, 122 deletions
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 3704c25c3c..415549d205 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -186,13 +186,17 @@ _dl_runtime_resolve:
 #define RTLD_START asm ("\
 .text
 	.globl _start
-	.globl _dl_start_user
+	.ent _start
 _start:
-	br	$gp,0f
+	br	$gp, 0f
 0:	ldgp	$gp, 0($gp)
 	/* Pass pointer to argument block to _dl_start.  */
 	mov	$sp, $16
 	bsr	$26, _dl_start..ng
+	.end _start
+	/* FALLTHRU */
+	.globl _dl_start_user
+	.ent _dl_start_user
 _dl_start_user:
 	/* Save the user entry point address in s0.  */
 	mov	$0, $9
@@ -225,7 +229,8 @@ _dl_start_user:
 	lda	$0, _dl_fini
 	/* Jump to the user's entry point.  */
 	mov	$9, $27
-	jmp	($9)");
+	jmp	($9)
+	.end _dl_start_user");
 
 /* Nonzero iff TYPE describes relocation of a PLT entry, so
    PLT entries should not be allowed to define the value.  */
@@ -377,8 +382,6 @@ elf_machine_rela (struct link_map *map,
 	    sym_value += reloc->r_addend;
 	  *reloc_addr = sym_value;
 	}
-      else if (r_info == R_ALPHA_COPY)
-	memcpy (reloc_addr, (void *) sym_value, sym->st_size);
       else
 	assert (! "unexpected dynamic reloc type");
     }
diff --git a/sysdeps/alpha/elf/start.S b/sysdeps/alpha/elf/start.S
index 596cea6265..d20a009aa4 100644
--- a/sysdeps/alpha/elf/start.S
+++ b/sysdeps/alpha/elf/start.S
@@ -20,12 +20,9 @@ Cambridge, MA 02139, USA.  */
 #include <sysdep.h>
 
 	.text
-	.globl _start	/* what ELF wants */
-	.globl __start	/* for backwards (ECOFF) comatibility */
 	.align 3
-	.ent __start, 0
+	.ent _start, 0
 _start:
-__start:
 	.frame fp, 0, zero
 	mov	zero, fp
 	br	gp, 1f
@@ -62,7 +59,6 @@ __start:
 	mov	a1, s1
 	mov	a2, s2
 
-#ifdef HAVE_INITFINI
   /* Call _init, the entry point to our own .init section.  */
 	jsr	ra, _init
 	ldgp	gp, 0(ra)
@@ -71,16 +67,12 @@ __start:
 	lda	a0, _fini
 	jsr	ra, atexit
 	ldgp	gp, 0(ra)
-#else
-  /* initialize constructors: */
-	jsr	ra, __main
-	ldgp	gp, 0(ra)
-#endif
+
+  /* Call the user's main and exit with its return value.  */
 	mov	s0, a0
 	mov	s1, a1
 	mov	s2, a2
 
-  /* Call the user's main and exit with its return value.  */
 	jsr	ra, main
 	ldgp	gp, 0(ra)
 
@@ -90,7 +82,10 @@ __start:
   /* Die very horribly if exit returns.  Call_pal hlt is callable from
      kernel mode only; this will result in an illegal instruction trap.  */
 	call_pal 0
-END(__start)
+	.end _start
+
+/* For ECOFF backwards compatibility. */
+weak_alias(_start, __start)
 
 /* Define a symbol for the first piece of initialized data.  */
 	.data
diff --git a/sysdeps/m68k/fpu/k_cos.c b/sysdeps/m68k/fpu/k_cos.c
index 28406e8cba..61f566f6a1 100644
--- a/sysdeps/m68k/fpu/k_cos.c
+++ b/sysdeps/m68k/fpu/k_cos.c
@@ -16,7 +16,6 @@ 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 <ansidecl.h>
 #include <math.h>
 
 #ifndef FUNC
@@ -29,7 +28,14 @@ Cambridge, MA 02139, USA.  */
 #define __CONCATX(a,b) __CONCAT(a,b)
 
 float_type
-DEFUN(__CONCATX(__kernel_,FUNC), (x, y), float_type x AND float_type y)
+__CONCATX(__kernel_,FUNC) (x, y)
+     float_type x;
+     float_type y;
 {
-  return __CONCATX(__,FUNC) (x + y);
+  float_type sin_x, cos_x, sin_y, cos_y;
+  __asm__ __volatile__ ("fsincosx %2,%0:%1" : "=f" (cos_x), "=f" (sin_x)
+			: "f" (x));
+  __asm__ __volatile__ ("fsincosx %2,%0:%1" : "=f" (cos_y), "=f" (sin_y)
+			: "f" (y));
+  return cos_x * cos_y - sin_x * sin_y;
 }
diff --git a/sysdeps/m68k/fpu/k_sin.c b/sysdeps/m68k/fpu/k_sin.c
index 8c6dfef720..3eed1d466c 100644
--- a/sysdeps/m68k/fpu/k_sin.c
+++ b/sysdeps/m68k/fpu/k_sin.c
@@ -16,7 +16,6 @@ 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 <ansidecl.h>
 #include <math.h>
 
 #ifndef FUNC
@@ -29,8 +28,17 @@ Cambridge, MA 02139, USA.  */
 #define __CONCATX(a,b) __CONCAT(a,b)
 
 float_type
-DEFUN(__CONCATX(__kernel_,FUNC), (x, y, iy),
-      float_type x AND float_type y AND int iy)
+__CONCATX(__kernel_,FUNC) (x, y, iy)
+     float_type x;
+     float_type y;
+     int iy;
 {
-  return __CONCATX(__,FUNC) (x + y);
+  float_type sin_x, cos_x, sin_y, cos_y;
+  if (iy == 0)
+    return __m81_u_(__CONCATX(__,FUNC)) (x);
+  __asm__ __volatile__ ("fsincosx %2,%0:%1" : "=f" (cos_x), "=f" (sin_x)
+			: "f" (x));
+  __asm__ __volatile__ ("fsincosx %2,%0:%1" : "=f" (cos_y), "=f" (sin_y)
+			: "f" (y));
+  return sin_x * cos_y + cos_x * sin_y;
 }
diff --git a/sysdeps/m68k/fpu/k_tan.c b/sysdeps/m68k/fpu/k_tan.c
index c8fa9b780e..7f1b729b96 100644
--- a/sysdeps/m68k/fpu/k_tan.c
+++ b/sysdeps/m68k/fpu/k_tan.c
@@ -16,7 +16,6 @@ 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 <ansidecl.h>
 #include <math.h>
 
 #ifndef FUNC
@@ -29,11 +28,16 @@ Cambridge, MA 02139, USA.  */
 #define __CONCATX(a,b) __CONCAT(a,b)
 
 float_type
-DEFUN(__CONCATX(__kernel_,FUNC), (x, y, iy),
-      float_type x AND float_type y AND int iy)
+__CONCATX(__kernel_,FUNC) (x, y, iy)
+     float_type x;
+     float_type y;
+     int iy;
 {
-  if (iy == 1)
-    return __CONCATX(__,FUNC) (x + y);
+  float_type tan_x, tan_y;
+  tan_x = __m81_u_(__CONCATX(__,FUNC)) (x);
+  tan_y = __m81_u_(__CONCATX(__,FUNC)) (y);
+  if (iy > 0)
+    return (tan_x + tan_y) / (1 - tan_x * tan_y);
   else
-    return ((float_type) -1.0) / __CONCATX(__,FUNC) (x + y);
+    return (tan_x * tan_y - 1) / (tan_x + tan_y);
 }
diff --git a/sysdeps/mach/hurd/send.c b/sysdeps/mach/hurd/send.c
index 79d76fa367..e18339a8fb 100644
--- a/sysdeps/mach/hurd/send.c
+++ b/sysdeps/mach/hurd/send.c
@@ -16,7 +16,6 @@ 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 <ansidecl.h>
 #include <errno.h>
 #include <sys/socket.h>
 #include <hurd.h>
@@ -25,8 +24,11 @@ Cambridge, MA 02139, USA.  */
 
 /* Send N bytes of BUF to socket FD.  Returns the number sent or -1.  */
 int
-DEFUN(__send, (fd, buf, n, flags),
-      int fd AND const PTR buf AND size_t n AND int flags)
+__send (fd, buf, n, flags)
+     int fd;
+     const void *buf;
+     size_t n;
+     int flags;
 {
   error_t err;
   int wrote;
diff --git a/sysdeps/mach/hurd/sendto.c b/sysdeps/mach/hurd/sendto.c
index 3621cd5dd5..88026b8cf5 100644
--- a/sysdeps/mach/hurd/sendto.c
+++ b/sysdeps/mach/hurd/sendto.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 1995, 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
@@ -16,7 +16,6 @@ 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 <ansidecl.h>
 #include <errno.h>
 #include <sys/socket.h>
 #include <hurd.h>
@@ -28,9 +27,13 @@ Cambridge, MA 02139, USA.  */
 /* Send N bytes of BUF on socket FD to peer at address ADDR (which is
    ADDR_LEN bytes long).  Returns the number sent, or -1 for errors.  */
 int
-DEFUN(sendto, (fd, buf, n, flags, addr, addr_len),
-      int fd AND const PTR buf AND size_t n AND int flags AND
-      const struct sockaddr_un *addr AND size_t addr_len)
+sendto (fd, buf, n, flags, addr, addr_len)
+     int fd;
+     const void *buf;
+     size_t n;
+     int flags;
+     const struct sockaddr_un *addr;
+     size_t addr_len;
 {
   addr_port_t aport;
   error_t err;
diff --git a/sysdeps/posix/profil.c b/sysdeps/posix/profil.c
index a6786b1a13..ddbd80a505 100644
--- a/sysdeps/posix/profil.c
+++ b/sysdeps/posix/profil.c
@@ -78,6 +78,15 @@ profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
       return sigaction (SIGPROF, &oact, NULL);
     }
 
+ if (samples)
+    {
+      /* Was already turned on.  Restore old timer and signal handler
+	 first.  */
+      if (setitimer (ITIMER_PROF, &otimer, NULL) < 0
+	  || sigaction (SIGPROF, &oact, NULL) < 0)
+	return -1;
+    }
+
   samples = sample_buffer;
   nsamples = size / sizeof *samples;
   pc_offset = offset;
diff --git a/sysdeps/stub/ustat.c b/sysdeps/stub/ustat.c
index c90bd36a9d..baa98fd5e8 100644
--- a/sysdeps/stub/ustat.c
+++ b/sysdeps/stub/ustat.c
@@ -1,5 +1,5 @@
 /* Return info on filesystem.
-Copyright (C) 1995 Free Software Foundation, Inc.
+Copyright (C) 1995, 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
diff --git a/sysdeps/unix/Makefile b/sysdeps/unix/Makefile
index 627b78c70c..d3cc46ab31 100644
--- a/sysdeps/unix/Makefile
+++ b/sysdeps/unix/Makefile
@@ -284,11 +284,11 @@ export asm_CPP := $(COMPILE.S) -E -x assembler-with-cpp
 
 $(common-objpfx)sysd-syscalls: $(..)sysdeps/unix/make-syscalls.sh \
 			       $(wildcard $(+sysdep_dirs:%=%/syscalls.list))
-	for dir in $$sysdirs; do \
-	  test -f $(..)sysdeps/$$dir/syscalls.list && \
+	for dir in $(+sysdep_dirs); do \
+	  test -f $$dir/syscalls.list && \
 	  { $(SHELL) $(dir $<)$(notdir $<) \
-		     $(..)sysdeps $$dir $(object-suffixes) || exit 1; }; \
-	  test $$dir = unix && break; \
+		     $$dir $(object-suffixes) || exit 1; }; \
+	  test $$dir = sysdeps/unix && break; \
 	done > $@T
 	mv -f $@T $@
 
diff --git a/sysdeps/unix/alpha/sysdep.S b/sysdeps/unix/alpha/sysdep.S
index 2d05305ce0..336eb02029 100644
--- a/sysdeps/unix/alpha/sysdep.S
+++ b/sysdeps/unix/alpha/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 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
@@ -22,6 +22,7 @@ Cambridge, MA 02139, USA.  */
 
 	.section .bss
 	.globl errno
+	.align 2
 errno:	.space 4
 #ifdef __ELF__
 	.type errno, @object
diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh
index e2c09905d0..58e31eb468 100644
--- a/sysdeps/unix/make-syscalls.sh
+++ b/sysdeps/unix/make-syscalls.sh
@@ -3,12 +3,11 @@
 # Usage: make-syscalls.sh ../sysdeps unix/common
 # Expects $sysdirs in environment.
 
-sysbase=$1; shift
 thisdir=$1; shift
 
 # Get the list of system calls for this directory.
 calls=`sed 's/#.*$//
-/^[ 	]*$/d' $sysbase/$thisdir/syscalls.list`
+/^[ 	]*$/d' $thisdir/syscalls.list`
 
 # Check each sysdep dir with higher priority than this one,
 # and remove from $calls all the functions found in other dirs.
@@ -21,13 +20,13 @@ for dir in $sysdirs; do
   # If a syscall specified a "caller", then only compile that syscall
   # if the caller function is also implemented in this directory.
   calls=`echo "$calls" | while read file caller rest; do
-	   test -f $sysbase/$dir/$file.c && continue
-	   test -f $sysbase/$dir/$file.S && continue
-	   test -f $sysbase/$dir/$file.s && continue
+	   test -f $dir/$file.c && continue
+	   test -f $dir/$file.S && continue
+	   test -f $dir/$file.s && continue
 	   if test x$caller != x-; then
-	     test -f $sysbase/$dir/$caller.c && continue
-	     test -f $sysbase/$dir/$caller.S && continue
-	     test -f $sysbase/$dir/$caller.s && continue
+	     test -f $dir/$caller.c && continue
+	     test -f $dir/$caller.S && continue
+	     test -f $dir/$caller.s && continue
 	   fi
 	   echo $file $caller $rest
          done`
diff --git a/sysdeps/unix/sysv/linux/alpha/Dist b/sysdeps/unix/sysv/linux/alpha/Dist
index 79ac03ff90..d898d041a2 100644
--- a/sysdeps/unix/sysv/linux/alpha/Dist
+++ b/sysdeps/unix/sysv/linux/alpha/Dist
@@ -1,5 +1,6 @@
-alpha/ptrace.halpha/regdef.h
+alpha/ptrace.h alpha/regdef.h
 ieee_get_fp_control.S ieee_set_fp_control.S
 ioperm.c
 init-first.h
 clone.S
+sys/io.h
diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile
index 3908b5703c..fa433e9d8b 100644
--- a/sysdeps/unix/sysv/linux/alpha/Makefile
+++ b/sysdeps/unix/sysv/linux/alpha/Makefile
@@ -1,5 +1,5 @@
 ifeq ($(subdir), misc)
-sysdep_headers += alpha/ptrace.h alpha/regdef.h
+sysdep_headers += alpha/ptrace.h alpha/regdef.h sys/io.h
 
 sysdep_routines += ieee_get_fp_control ieee_set_fp_control \
 		   sethae ioperm osf_sigprocmask fstatfs statfs llseek
diff --git a/sysdeps/unix/sysv/linux/alpha/init-first.h b/sysdeps/unix/sysv/linux/alpha/init-first.h
index c27c589a28..ffbcaf1521 100644
--- a/sysdeps/unix/sysv/linux/alpha/init-first.h
+++ b/sysdeps/unix/sysv/linux/alpha/init-first.h
@@ -1,12 +1,29 @@
-/* This fragment is invoked in the stack context of program start.
-   Its job is to set up a pointer to argc as an argument, pass
-   control to `INIT', and, if necessary, clean up after the call
-   to leave the stack in the same condition it was found in.  */
+/* The job of this fragment it to find argc and friends for INIT.
+   This is done in one of two ways: either in the stack context
+   of program start, or having dlopen pass them in.  */
 
-#define SYSDEP_CALL_INIT(NAME, INIT)	\
-    asm(".globl " #NAME "\n"		\
-	#NAME ":\n\t"			\
-	"ldgp $29, 0($27)\n\t"		\
-	".prologue 1\n\t"		\
-	"mov $30, $16\n\t"		\
-	"br $31, " #INIT "..ng");
+#define SYSDEP_CALL_INIT(NAME, INIT)		\
+    asm(".weak _dl_starting_up\n\t"		\
+        ".globl " #NAME "\n\t"			\
+	".ent " #NAME "\n"			\
+	#NAME ":\n\t"				\
+	"ldgp	$29, 0($27)\n\t"		\
+	".prologue 1\n\t"			\
+	".set at\n\t"				\
+	/* Are we a dynamic libc being loaded into a static program?  */ \
+	"lda	$0, _dl_starting_up\n\t"	\
+	"beq	$0, 1f\n\t"			\
+	"ldl	$0, 0($0)\n"			\
+	"cmpeq	$31, $0, $0\n"			\
+	"1:\t"					\
+	"stl	$0, __libc_multiple_libcs\n\t"	\
+	/* If so, argc et al are in a0-a2 already.  Otherwise, load them.  */ \
+	"bne	$0, 2f\n\t"			\
+	"ldl	$16, 0($30)\n\t"		\
+	"lda	$17, 8($30)\n\t"		\
+	"s8addq	$16, $17, $18\n\t"		\
+	"addq	$18, 8, $18\n"			\
+	"2:\t"					\
+	"br $31, " #INIT "..ng\n\t"		\
+	".set noat\n\t"				\
+	".end " #NAME);
diff --git a/sysdeps/unix/sysv/linux/alpha/ioperm.c b/sysdeps/unix/sysv/linux/alpha/ioperm.c
index a91608ff24..731059e600 100644
--- a/sysdeps/unix/sysv/linux/alpha/ioperm.c
+++ b/sysdeps/unix/sysv/linux/alpha/ioperm.c
@@ -84,20 +84,21 @@ struct ioswtch {
 static struct platform {
   const char	*name;
   int		io_sys;
+  int		hae_shift;
   unsigned long	bus_memory_base;
   unsigned long	sparse_bus_memory_base;
 } platform[] = {
-  {"Alcor",	IOSYS_CIA,	CIA_DENSE_MEM,		CIA_SPARSE_MEM},
-  {"Avanti",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"Cabriolet",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"EB164",	IOSYS_CIA,	CIA_DENSE_MEM,		CIA_SPARSE_MEM},
-  {"EB64+",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"EB66",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"EB66P",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"Jensen",	IOSYS_JENSEN,	0,			JENSEN_SPARSE_MEM},
-  {"Mikasa",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"Mustang",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"Noname",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Alcor",	IOSYS_CIA,	5, CIA_DENSE_MEM,	CIA_SPARSE_MEM},
+  {"Avanti",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Cabriolet",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"EB164",	IOSYS_CIA,	5, CIA_DENSE_MEM,	CIA_SPARSE_MEM},
+  {"EB64+",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"EB66",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"EB66P",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Jensen",	IOSYS_JENSEN,	7, 0,			JENSEN_SPARSE_MEM},
+  {"Mikasa",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Mustang",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Noname",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
 };
 
 
@@ -109,11 +110,11 @@ static struct {
   unsigned long		base;
   struct ioswtch *	swp;
   int			sys;
+  int			hae_shift;
+  unsigned long		bus_memory_base;
+  unsigned long		sparse_bus_memory_base;
 } io;
 
-static unsigned long bus_memory_base = -1;
-static unsigned long sparse_bus_memory_base = -1;
-
 extern void __sethae (unsigned long);	/* we can't use asm/io.h */
 
 
@@ -335,8 +336,9 @@ init_iosys (void)
     {
       if (strcmp (platform[i].name, systype) == 0)
 	{
-	  bus_memory_base = platform[i].bus_memory_base;
-	  sparse_bus_memory_base = platform[i].sparse_bus_memory_base;
+	  io.hae_shift = platform[i].hae_shift;
+	  io.bus_memory_base = platform[i].bus_memory_base;
+	  io.sparse_bus_memory_base = platform[i].sparse_bus_memory_base;
 	  io.sys = platform[i].io_sys;
 	  if (io.sys == IOSYS_JENSEN)
 	    io.swp = &ioswtch[0];
@@ -500,7 +502,7 @@ _bus_base(void)
 {
   if (!io.swp && init_iosys () < 0)
     return -1;
-  return bus_memory_base;
+  return io.bus_memory_base;
 }
 
 unsigned long
@@ -508,7 +510,15 @@ _bus_base_sparse(void)
 {
   if (!io.swp && init_iosys () < 0)
     return -1;
-  return sparse_bus_memory_base;
+  return io.sparse_bus_memory_base;
+}
+
+int
+_hae_shift(void)
+{
+  if (!io.swp && init_iosys () < 0)
+    return -1;
+  return io.hae_shift;
 }
 
 weak_alias (_sethae, sethae);
@@ -522,3 +532,4 @@ weak_alias (_outw, outw);
 weak_alias (_outl, outl);
 weak_alias (_bus_base, bus_base);
 weak_alias (_bus_base_sparse, bus_base_sparse);
+weak_alias (_hae_shift, hae_shift);
diff --git a/sysdeps/unix/sysv/linux/alpha/sys/io.h b/sysdeps/unix/sysv/linux/alpha/sys/io.h
new file mode 100644
index 0000000000..a88073573c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/sys/io.h
@@ -0,0 +1,59 @@
+/* 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.  */
+
+#ifndef	_SYS_IO_H
+
+#define	_SYS_IO_H	1
+#include <features.h>
+
+__BEGIN_DECLS
+
+/* Get constants from kernel header files. */
+#include <asm/io.h>
+
+/* If TURN_ON is TRUE, request for permission to do direct i/o on the
+   port numbers in the range [FROM,FROM+NUM-1].  Otherwise, turn I/O
+   permission off for that range.  This call requires root privileges.
+
+   Portability note: not all Linux platforms support this call.  Most
+   platforms based on the PC I/O architecture probably will, however.
+   E.g., Linux/Alpha for Alpha PCs supports this.  */
+extern int ioperm __P ((unsigned long int __from, unsigned long int __num,
+			int __turn_on));
+
+/* Set the I/O privilege level to LEVEL.  If LEVEL>3, permission to
+   access any I/O port is granted.  This call requires root
+   privileges. */
+extern int iopl __P ((int __level));
+
+/* Return the physical address of the DENSE I/O memory or NULL if none
+   is available (e.g. on a jensen).  */
+extern unsigned long _bus_base __P ((void)) __attribute__ ((const));
+extern unsigned long bus_base __P ((void)) __attribute__ ((const));
+
+/* Return the physical address of the SPARSE I/O memory.  */
+extern unsigned long _bus_base_sparse __P ((void)) __attribute__ ((const));
+extern unsigned long bus_base_sparse __P ((void)) __attribute__ ((const));
+
+/* Return the HAE shift used by the SPARSE I/O memory.  */
+extern int _hae_shift __P ((void)) __attribute__ ((const));
+extern int hae_shift __P ((void)) __attribute__ ((const));
+
+__END_DECLS
+
+#endif /* _SYS_IO_H */
diff --git a/sysdeps/unix/sysv/linux/i386/Dist b/sysdeps/unix/sysv/linux/i386/Dist
index 4e4f467392..780edfca50 100644
--- a/sysdeps/unix/sysv/linux/i386/Dist
+++ b/sysdeps/unix/sysv/linux/i386/Dist
@@ -1,3 +1,3 @@
 sys/perm.h sys/vm86.h
 init-first.h
-close.S
+clone.S
diff --git a/sysdeps/unix/sysv/linux/i386/init-first.h b/sysdeps/unix/sysv/linux/i386/init-first.h
index f42d7f2533..4c61f1b41e 100644
--- a/sysdeps/unix/sysv/linux/i386/init-first.h
+++ b/sysdeps/unix/sysv/linux/i386/init-first.h
@@ -1,13 +1,27 @@
-/* This fragment is invoked in the stack context of program start.
-   Its job is to set up a pointer to argc as an argument, pass
-   control to `INIT', and, if necessary, clean up after the call
-   to leave the stack in the same condition it was found in.  */
+/* The job of this fragment it to find argc and friends for INIT.
+   This is done in one of two ways: either in the stack context
+   of program start, or having dlopen pass them in.  */
 
-#define SYSDEP_CALL_INIT(NAME, INIT)	\
-    asm(".globl " #NAME "\n\t"		\
-	#NAME ":\n\t"			\
-	"lea 4(%esp), %eax\n\t"		\
-	"pushl %eax\n\t"		\
-	"call " #INIT "\n\t"		\
-	"popl %eax\n\t"			\
-	"ret");
+#define SYSDEP_CALL_INIT(NAME, INIT)					      \
+void NAME (void *arg)							      \
+{									      \
+  int argc;								      \
+  char **argv, **envp;							      \
+									      \
+  __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;		      \
+									      \
+  if (!__libc_multiple_libcs)						      \
+    {									      \
+      argc = (int) arg;							      \
+      argv = (char **) &arg + 1;					      \
+      envp = &argv[argc+1];						      \
+    }									      \
+  else									      \
+    {									      \
+      argc = (int) arg;							      \
+      argv = ((char ***) &arg)[1];					      \
+      envp = ((char ***) &arg)[2];					      \
+    }									      \
+									      \
+  INIT (argc, argv, envp);						      \
+}
diff --git a/sysdeps/unix/sysv/linux/i386/mmap.S b/sysdeps/unix/sysv/linux/i386/mmap.S
index 90ac88c46f..638d548e00 100644
--- a/sysdeps/unix/sysv/linux/i386/mmap.S
+++ b/sysdeps/unix/sysv/linux/i386/mmap.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 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
@@ -36,9 +36,9 @@ ENTRY (__mmap)
 	/* Restore registers.  */
 	movl %edx, %ebx
 
-	/* %eax is < 0 if there was an error.  */
-	testl %eax, %eax
-	jl syscall_error
+	/* If 0 > %eax > -4096 there was an error.  */
+	cmpl $-4096, %eax
+	ja syscall_error
 
 	/* Successful; return the syscall's value.  */
 	ret
diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c
index ae163bcd49..9f0a3c0f51 100644
--- a/sysdeps/unix/sysv/linux/init-first.c
+++ b/sysdeps/unix/sysv/linux/init-first.c
@@ -27,7 +27,7 @@ extern void __libc_init (int, char **, char **);
 extern void __libc_global_ctors (void);
 
 /* The function is called from assembly stubs the compiler can't see.  */
-static void init (void *) __attribute__ ((unused));
+static void init (int, char **, char **) __attribute__ ((unused));
 
 extern int _dl_starting_up;
 weak_extern (_dl_starting_up)
@@ -40,26 +40,16 @@ int __libc_multiple_libcs = 1;
    later calls of initializers for dynamic libraries.  */
 int __libc_argc;
 char **__libc_argv;
-char **__libc_envp;
 
 
 static void
-init (void *data)
+init (int argc, char **argv, char **envp)
 {
   extern int __personality (int);
 
-  __libc_multiple_libcs = &_dl_starting_up && ! _dl_starting_up;
-
-
   /* We must not call `personality' twice.  */
   if (!__libc_multiple_libcs)
     {
-      /* The argument we got points to the values describing the
-	 command line argument etc.  */
-      __libc_argc = *(int *)data;
-      __libc_argv = (char **)data + 1;
-      __libc_envp = &__libc_argv[__libc_argc + 1];
-
       /* The `personality' system call takes one argument that chooses
 	 the "personality", i.e. the set of system calls and such.  We
 	 must make this call first thing to disable emulation of some
@@ -70,17 +60,13 @@ init (void *data)
       /* Set the FPU control word to the proper default value.  */
       __setfpucw (__fpu_control);
     }
-  else
-    {
-      /* The argument we got points to the values describing the
-	 command line argument etc.  */
-      __libc_argc = *((int *)data)++;
-      __libc_argv = *((char ***)data)++;
-      __libc_envp = *(char ***)data;
-    }
 
-  __environ = __libc_envp;
-  __libc_init (__libc_argc, __libc_argv, __libc_envp);
+  /* Save the command-line arguments.  */
+  __libc_argc = argc;
+  __libc_argv = argv;
+  __environ = envp;
+
+  __libc_init (argc, argv, envp);
 
 #ifdef PIC
   __libc_global_ctors ();