about summary refs log tree commit diff
path: root/sysdeps/mips
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-07-12 23:35:19 +0000
committerUlrich Drepper <drepper@redhat.com>1997-07-12 23:35:19 +0000
commitf21acc89c06c14160eab88246e9dbe0b17eb5f89 (patch)
tree096a11e16faed78c69e77fd79b7c8bb4dc0bd051 /sysdeps/mips
parent2d7da676f38bc00f40d2b604036c0295c156529e (diff)
downloadglibc-f21acc89c06c14160eab88246e9dbe0b17eb5f89.tar.gz
glibc-f21acc89c06c14160eab88246e9dbe0b17eb5f89.tar.xz
glibc-f21acc89c06c14160eab88246e9dbe0b17eb5f89.zip
1997-07-13 01:18  Ulrich Drepper  <drepper@cygnus.com>

	* setjmp/setjmp.h: Define _setjmp and _longjmp also if __USE_XOPEN.

	* sysdeps/unix/sysv/linux/bits/ipc.h: Fix comment.
	* sysdeps/unix/sysv/linux/bits/msq.h: Likewise.
	* sysdeps/unix/sysv/linux/bits/sem.h: Likewise.
	* sysdeps/unix/sysv/linux/bits/shm.h: Likewise.

	* time/Makefile (routines): Add getdate.
	* time/time.h: Add prototype for getdate and getdate_r.
	* time/getdate.c: New file.
	Provided by Mark Kettenis <kettenis@phys.uva.nl>.

1997-06-30 14:49  H.J. Lu  <hjl@gnu.ai.mit.edu>

	From Ralf Baechle <ralf@informatik.uni-koblenz.de> on
	Sat Jun 21 18:11:21 1997:

	* sysdeps/unix/sysv/linux/syscalls.list (swapon): Add __swapon alias.
	(swapoff): New.

	* elf/Makefile: Add linker script support.
	(headers): Add bits/dlfcn.h.

	* elf/dl-load.c (MAP_BASE_ADDR): New.

	* elf/dlfcn.h: Include <bits/dlfcn.h>.

	* elf/elf.h: Add MIPS support.

	* sysdeps/generic/Dist: Add entry.h.
	* sysdeps/generic/entry.h: New, define the entry symbol.

	* elf/rtld.c (_start): Include <entry.h>.  Change to ENTRY_POINT.
	* sysdeps/generic/dl-sysdep.c (_start): Likewise.
	* mips/elf/start.S (_start): Likewise.

	* sysdeps/mips/bsd-_setjmp.S: Fix PIC.
	* sysdeps/mips/bsd-setjmp.S: Likewise.
	* sysdeps/mips/setjmp.S: Likewise.
	* mips/elf/start.S: Likewise.
	* sysdeps/unix/mips/brk.S: Likewise.
	* sysdeps/unix/mips/sysdep.S: Likewise.
	* sysdeps/unix/mips/sysdep.h: Likewise.
	* sysdeps/unix/mips/wait.S: Likewise.

	* sysdeps/mips/dl-machine.h: Update for Linux/MIPS.
	* sysdeps/mips/fpu_control.h: Likewise.

	* sysdeps/generic/bits/dlfcn.h: New file.

	* sysdeps/mips/rtld-ldscript.in: New for Linux/MIPS.
	* sysdeps/mips/rtld-parms: Likewise.
	* sysdeps/mips/bits/dlfcn.h: Likewise.
	* sysdeps/mips/mips64/rtld-parms: Likewise.
	* sysdeps/mips/mipsel/rtld-parms: Likewise.
	* sysdeps/unix/sysv/linux/mips/Dist: Likewise.
	* sysdeps/unix/sysv/linux/mips/Makefile: Likewise.
	* sysdeps/unix/sysv/linux/mips/clone.S: Likewise.
	* sysdeps/unix/sysv/linux/mips/entry.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/fpregdef.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/fxstat.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/kernel_stat.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/kernel_termios.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/lxstat.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/regdef.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sgidefs.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/syscalls.list: Likewise.
	* sysdeps/unix/sysv/linux/mips/ustat.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/xmknod.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/xstat.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/endian.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/fcntl.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/ioctl-types.h:
	* sysdeps/unix/sysv/linux/mips/bits/ipc.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/shm.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/signum.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/socket.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/stat.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/statfs.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/termios.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/time.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sys/acct.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sys/asm.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sys/cachectl.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sys/fpregdef.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sys/procfs.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sys/regdef.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sys/syscall.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sys/sysmips.h: Likewise.

1997-04-09 19:05  H.J. Lu (hjl@gnu.ai.mit.edu)

	* isomac.c (xstrndup): New, use it instead of strndup ().

1997-07-02 08:55  H.J. Lu  <hjl@gnu.ai.mit.edu>

	* sysdeps/i386/dl-machine.h (elf_machine_rel): Print
	the program name for different sizes.

1997-07-10 15:47  Fila Kolodny  <fila@ibi.com>

	* nis/ypclnt.c: Change references to MAXHOSTNAMELEN to NIS_MAXNAMELEN.
	Add include of rpcsvc/nis.h.
	* inet/getnameinfo.c: Delete references to MAXHOSTNAMELEN.
	* sysdeps/posix/getaddrinfo.c: Likewise.
	Change size of variable buffer to be big enough to hold an IPv6
	address in printable format.

1997-07-12 18:47  Ulrich Drepper  <drepper@cygnus.com>

	* assert/assert.h [!NDEBUG] (assert, assert_perror): Don't use ||
	and && in tests to allow use in C++ code which overloads these
	operators.  Reported by Istvan Marko <istvan@cmdmail.amd.com>.

	* configure.in: Move mips64* recognition before mips*.
	Patch by Zack Weinberg <zack@rabi.phys.columbia.edu>.

1997-07-03 20:44  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* Makerules (lib%.so, $(common-objpfx)libc.so): Don't use
	automatic variables in dependency lists.
	(build-shlib): Always filter out the version script file.
	* extra-lib.mk ($(objpfx)$(lib).so): Depend on version script.

1997-07-12 17:56  Ulrich Drepper  <drepper@cygnus.com>

	* login/login.c (tty_name): Test return value of ttyname_r for !=
	0, not < 0.
	* misc/ttyslot.c (ttyslot): Test return value of ttyname_r for ==
	0, not >= 0.
	* sysdeps/unix/getlogin.c (getlogin): Test return value of
	ttyname_r for != 0.
	* sysdeps/unix/getlogin_r.c (getlogin_r): Likewise.

1997-07-10  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* login/utmp_file.c (getutline_r_file): Fix type: compare with
	*result.

1997-07-11 00:21  Mark Kettenis  <kettenis@phys.uva.nl>

	* login/Makefile (headers): Add utmpx.h and bits/utmpx.h.

1997-07-09 19:21  Mark Kettenis  <kettenis@phys.uva.nl>

	* login/programs/utmpd.c, login/programs/database.c,
	login/programs/request.c: Prepare messages for
	internationalization.

	* login/programs/utmpd.c:
	(main): Change handling of errors in opening the database.
	* login/programs/database.c:
	(open_database, synchronize_dtatabase, initialize_database):
	Properly handle errors.
	(get_mtime): Use fstat instead of stat.  All callers changed.

	* login/getutent_r.c: Make setutxent a weak alias for __setutxent.
	* login/getutent.c: Rename getutent to __getutent and make
	getutent a weak alias.
	Make getutxent a weak alias for	__getutent.
	* login/utmpx.h: New file.
	* sysdeps/gnu/bits/utmp.h: Cleanup.  Added comments.
	* sysdeps/gnu/bits/utmpx.h: New file.

	* stdio-common/strops.c: Partialy undo last change.  Will need
	more investigation.
Diffstat (limited to 'sysdeps/mips')
-rw-r--r--sysdeps/mips/bits/dlfcn.h42
-rw-r--r--sysdeps/mips/bsd-_setjmp.S13
-rw-r--r--sysdeps/mips/bsd-setjmp.S13
-rw-r--r--sysdeps/mips/dl-machine.h496
-rw-r--r--sysdeps/mips/elf/start.S55
-rw-r--r--sysdeps/mips/fpu_control.h90
-rw-r--r--sysdeps/mips/mips64/rtld-parms3
-rw-r--r--sysdeps/mips/mipsel/rtld-parms3
-rw-r--r--sysdeps/mips/rtld-ldscript.in106
-rw-r--r--sysdeps/mips/setjmp.S22
10 files changed, 545 insertions, 298 deletions
diff --git a/sysdeps/mips/bits/dlfcn.h b/sysdeps/mips/bits/dlfcn.h
new file mode 100644
index 0000000000..636da5662d
--- /dev/null
+++ b/sysdeps/mips/bits/dlfcn.h
@@ -0,0 +1,42 @@
+/* System dependand definitions for run-time dynamic loading.
+   Copyright (C) 1996, 1997 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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef	_BITS_DLFCN_H
+#define	_BITS_DLFCN_H 1
+
+/* The MODE argument to `dlopen' contains one of the following: */
+#define RTLD_LAZY	0x001	/* Lazy function call binding.  */
+#define RTLD_NOW	0x002	/* Immediate function call binding.  */
+#define	RTLD_BINDING_MASK 0x3	/* Mask of binding time value.  */
+
+/* If the following bit is set in the MODE argument to `dlopen',
+   the symbols of the loaded object and its dependencies are made
+   visible as if the object were linked directly into the program.  */
+#define RTLD_GLOBAL	0x004
+
+__BEGIN_DECLS
+
+/* Some SGI specific calls that aren't implemented yet.  */
+extern void *sgidladd __P ((const char *, int));
+extern void *sgidlopen_version __P ((const char *, int, const char *, int));
+extern char *sgigetdsoversion __P ((const char *));
+
+__END_DECLS
+
+#endif	/* bits/dlfcn.h */
diff --git a/sysdeps/mips/bsd-_setjmp.S b/sysdeps/mips/bsd-_setjmp.S
index f519f19359..819a7018c4 100644
--- a/sysdeps/mips/bsd-_setjmp.S
+++ b/sysdeps/mips/bsd-_setjmp.S
@@ -23,14 +23,19 @@
 
 #include <sysdep.h>
 
+/* XXX Must this be __PIC__ ? --drepper */
 #ifdef PIC
 	.option pic2
 #endif
 ENTRY (_setjmp)
+	.set noreorder
 #ifdef PIC
 	.cpload t9
+	la	t9, C_SYMBOL_NAME (__sigsetjmp)
+	jr	t9
+#else
+	j	C_SYMBOL_NAME (__sigsetjmp)
 #endif
-	la t9, C_SYMBOL_NAME (__sigsetjmp)
-	nop
-	jr t9
-	li a1, 0		/* Pass a second argument of zero.  */
+	move	a1,zero		/* Pass a second argument of zero.  */
+	.set	reorder
+	.end	_setjmp
diff --git a/sysdeps/mips/bsd-setjmp.S b/sysdeps/mips/bsd-setjmp.S
index 9a22700718..f220404c2c 100644
--- a/sysdeps/mips/bsd-setjmp.S
+++ b/sysdeps/mips/bsd-setjmp.S
@@ -23,14 +23,19 @@
 
 #include <sysdep.h>
 
+/* XXX Must this be __PIC__ ? --drepper */
 #ifdef PIC
 	.option pic2
 #endif
 ENTRY (setjmp)
+	.set	noreorder
 #ifdef PIC
 	.cpload t9
+	la	t9, C_SYMBOL_NAME (__sigsetjmp)
+	jr	t9
+#else
+	j	C_SYMBOL_NAME (__sigsetjmp)
 #endif
-	la t9, C_SYMBOL_NAME (__sigsetjmp)
-	nop
-	jr t9
-	li a1, 1		/* Pass a second argument of one.  */
+	li	a1, 1		/* Pass a second argument of one.  */
+	.set	reorder
+	.end	setjmp
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index ff7d371025..cc7198b60e 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -24,6 +24,34 @@
 #define ELF_MACHINE_NAME "MIPS"
 
 #include <assert.h>
+#include <entry.h>
+
+#ifndef ENTRY_POINT
+#error ENTRY_POINT needs to be defined for MIPS.
+#endif
+
+#ifndef _RTLD_PROLOGUE
+#ifdef __STDC__
+#define _RTLD_PROLOGUE(entry) "\n\t.globl " #entry \
+			      "\n\t.ent " #entry \
+			      "\n\t" #entry ":\n\t"
+#else
+#define _RTLD_PROLOGUE(entry) "\n\t.globl entry\n\t.ent entry\n\t entry:\n\t"
+#endif
+#endif
+
+#ifndef _RTLD_EPILOGUE
+#ifdef __STDC__
+#define _RTLD_EPILOGUE(entry) "\t.end " #entry "\n"
+#else
+#define _RTLD_EPILOGUE(entry) "\t.end entry\n"
+#endif
+#endif
+
+/* I have no idea what I am doing. */
+#define ELF_MACHINE_RELOC_NOPLT			-1
+#define elf_machine_lookup_noplt_p(type)	(1)
+#define elf_machine_lookup_noexec_p(type)	(0)
 
 /* Translate a processor specific dynamic tag to the index
    in l_info array.  */
@@ -34,6 +62,18 @@
 #define ELF_MACHINE_ALIGN_MASK 0xffff
 #endif
 
+/*
+ * MIPS libraries are usually linked to a non-zero base address.  We
+ * subtrace the base address from the address where we map the object
+ * to.  This results in more efficient address space usage.
+ */
+#if 0
+#define MAP_BASE_ADDR(l) ((l)->l_info[DT_MIPS(BASE_ADDRESS)] ? \
+			  (l)->l_info[DT_MIPS(BASE_ADDRESS)]->d_un.d_ptr : 0)
+#else
+#define MAP_BASE_ADDR(l) 0x5ffe0000
+#endif
+
 /* If there is a DT_MIPS_RLD_MAP entry in the dynamic section, fill it in
    with the run-time address of the r_debug structure  */
 #define ELF_MACHINE_DEBUG_SETUP(l,r) \
@@ -43,7 +83,7 @@ do { if ((l)->l_info[DT_MIPS (RLD_MAP)]) \
    } while (0)
 
 /* Return nonzero iff E_MACHINE is compatible with the running host.  */
-static inline int
+static inline int __attribute__ ((unused))
 elf_machine_matches_host (ElfW(Half) e_machine)
 {
   switch (e_machine)
@@ -56,6 +96,16 @@ elf_machine_matches_host (ElfW(Half) e_machine)
     }
 }
 
+/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
++   first element of the GOT.  This must be inlined in a function which
++   uses global data.  */
++static inline ElfW(Addr)
++elf_machine_dynamic (void)
++{
++  register ElfW(Addr) gp asm ("$28");
++  return * (ElfW(Addr) *) (gp - 0x7ff0);
++}
++
 static inline ElfW(Addr) *
 elf_mips_got_from_gpreg (ElfW(Addr) gpreg)
 {
@@ -75,6 +125,16 @@ elf_machine_got (void)
 }
 
 
+/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
+   first element of the GOT.  This must be inlined in a function which
+   uses global data.  */
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+  register ElfW(Addr) gp asm ("$28");
+  return * (ElfW(Addr) *) (gp - 0x7ff0);
+}
+
 /* Return the run-time load address of the shared object.  */
 static inline ElfW(Addr)
 elf_machine_load_address (void)
@@ -87,7 +147,9 @@ elf_machine_load_address (void)
        "	nop\n"
        "here:	dsubu %0, $31, %0\n"
        "	.set reorder\n"
-       : "=r" (addr));
+       :	"=r" (addr)
+       :	/* No inputs */
+       :	"$31");
 #else
   asm ("	.set noreorder\n"
        "	la %0, here\n"
@@ -95,7 +157,9 @@ elf_machine_load_address (void)
        "	nop\n"
        "here:	subu %0, $31, %0\n"
        "	.set reorder\n"
-       : "=r" (addr));
+       :	"=r" (addr)
+       :	/* No inputs */
+       :	"$31");
 #endif
   return addr;
 }
@@ -105,7 +169,7 @@ elf_machine_load_address (void)
 
 /* Relocate GOT. */
 static inline void
-elf_machine_got_rel (struct link_map *map)
+elf_machine_got_rel (struct link_map *map, int lazy)
 {
   ElfW(Addr) *got;
   ElfW(Sym) *sym;
@@ -119,7 +183,7 @@ elf_machine_got_rel (struct link_map *map)
       const ElfW(Sym) *ref = sym; \
       ElfW(Addr) sym_loadaddr; \
       sym_loadaddr = _dl_lookup_symbol (strtab + sym->st_name, &ref, scope, \
-					map->l_name, DL_LOOKUP_NOPLT); \
+					map->l_name, ELF_MACHINE_RELOC_NOPLT);\
       (ref)? sym_loadaddr + ref->st_value: 0; \
     })
 
@@ -151,7 +215,7 @@ elf_machine_got_rel (struct link_map *map)
 	{
 	  if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC)
 	    {
-	      if (sym->st_value /* && maybe_stub (sym->st_value) */)
+	      if (sym->st_value && lazy)
 		*got = sym->st_value + map->l_addr;
 	      else
 		*got = RESOLVE_GOTSYM (sym);
@@ -163,7 +227,7 @@ elf_machine_got_rel (struct link_map *map)
 	*got = RESOLVE_GOTSYM (sym);
       else if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
 	       && *got != sym->st_value
-	       /* && maybe_stub (*got) */)
+	       && lazy)
 	*got += map->l_addr;
       else if (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION)
 	{
@@ -193,6 +257,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy)
   extern void _dl_runtime_resolve (ElfW(Word));
   extern int _dl_mips_gnu_objects;
 
+#ifdef RTLD_BOOTSTRAP
+    {
+      return lazy;
+    }
+#endif
   if (lazy)
     {
       /* The GOT entries for functions have not yet been filled in.
@@ -216,7 +285,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy)
     }
 
   /* Relocate global offset table.  */
-  elf_machine_got_rel (l);
+  elf_machine_got_rel (l, lazy);
 
   return lazy;
 }
@@ -282,6 +351,7 @@ elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
     }
 
   _dl_signal_error (0, NULL, "cannot find runtime link map");
+  return NULL;
 }
 
 /* Mips has no PLT but define elf_machine_relplt to be elf_machine_rel. */
@@ -295,211 +365,220 @@ elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
    to usual c arguments.  */
 
 #ifdef __mips64
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-/* The flag _dl_mips_gnu_objects is set if all dynamic objects are \
-   generated by the gnu linker. */\
-int _dl_mips_gnu_objects = 1;\
-\
+#define ELF_MACHINE_RUNTIME_TRAMPOLINE					      \
+/* The flag _dl_mips_gnu_objects is set if all dynamic objects are	      \
+   generated by the gnu linker. */					      \
+int _dl_mips_gnu_objects = 1;						      \
+									      \
 /* This is called from assembly stubs below which the compiler can't see.  */ \
-static ElfW(Addr) \
-__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr)) \
-                  __attribute__ ((unused)); \
-\
-static ElfW(Addr) \
-__dl_runtime_resolve (ElfW(Word) sym_index,\
-		      ElfW(Word) return_address,\
-		      ElfW(Addr) old_gpreg,\
-		      ElfW(Addr) stub_pc)\
-{\
-  struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);\
-  const ElfW(Sym) *const symtab\
-    = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);\
-  const char *strtab\
-    = (void *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);\
-  const ElfW(Addr) *got\
-    = (const ElfW(Addr) *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);\
-  const ElfW(Word) local_gotno\
-    = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;\
-  const ElfW(Word) gotsym\
-    = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;\
-  const ElfW(Sym) *definer;\
-  ElfW(Addr) loadbase;\
-  ElfW(Addr) funcaddr;\
-  struct link_map **scope;\
-\
-  /* Look up the symbol's run-time value.  */\
-  scope = _dl_object_relocation_scope (l);\
-  definer = &symtab[sym_index];\
-\
-  loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,\
-				scope, l->l_name, DL_LOOKUP_NOPLT);\
-\
-  *_dl_global_scope_end = NULL;\
-\
-  /* Apply the relocation with that value.  */\
-  funcaddr = loadbase + definer->st_value;\
-  *(got + local_gotno + sym_index - gotsym) = funcaddr;\
-\
-  return funcaddr;\
-}\
-\
-asm ("\n\
-	.text\n\
-	.align	3\n\
-	.globl	_dl_runtime_resolve\n\
-	.type	_dl_runtime_resolve,@function\n\
-	.ent	_dl_runtime_resolve\n\
-_dl_runtime_resolve:\n\
-	.set noreorder\n\
-	# Save old GP to $3.\n\
-	move	$3,$28\n\
-	# Modify t9 ($25) so as to point .cpload instruction.\n\
-	daddu	$25,2*8\n\
-	# Compute GP.\n\
-	.cpload $25\n\
-	.set reorder\n\
-	# Save slot call pc.\n\
-        move	$2, $31\n\
-	# Save arguments and sp value in stack.\n\
-	dsubu	$29, 10*8\n\
-	.cprestore 8*8\n\
-	sd	$15, 9*8($29)\n\
-	sd	$4, 3*8($29)\n\
-	sd	$5, 4*8($29)\n\
-	sd	$6, 5*8($29)\n\
-	sd	$7, 6*8($29)\n\
-	sd	$16, 7*8($29)\n\
-	move	$16, $29\n\
-	move	$4, $24\n\
-	move	$5, $15\n\
-	move	$6, $3\n\
-	move	$7, $2\n\
-	jal	__dl_runtime_resolve\n\
-	move	$29, $16\n\
-	ld	$31, 9*8($29)\n\
-	ld	$4, 3*8($29)\n\
-	ld	$5, 4*8($29)\n\
-	ld	$6, 5*8($29)\n\
-	ld	$7, 6*8($29)\n\
-	ld	$16, 7*8($29)\n\
-	daddu	$29, 10*8\n\
-	move	$25, $2\n\
-	jr	$25\n\
-	.end	_dl_runtime_resolve\n\
+static ElfW(Addr)							      \
+__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr))	      \
+                  __attribute__ ((unused));				      \
+									      \
+static ElfW(Addr)							      \
+__dl_runtime_resolve (ElfW(Word) sym_index,				      \
+		      ElfW(Word) return_address,			      \
+		      ElfW(Addr) old_gpreg,				      \
+		      ElfW(Addr) stub_pc)				      \
+{									      \
+  struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);     \
+  const ElfW(Sym) *const symtab						      \
+    = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);     \
+  const char *strtab							      \
+    = (void *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);		      \
+  const ElfW(Addr) *got							      \
+    = (const ElfW(Addr) *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);    \
+  const ElfW(Word) local_gotno						      \
+    = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;	      \
+  const ElfW(Word) gotsym						      \
+    = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;	      \
+  const ElfW(Sym) *definer;						      \
+  ElfW(Addr) loadbase;							      \
+  ElfW(Addr) funcaddr;							      \
+  struct link_map **scope;						      \
+									      \
+  /* Look up the symbol's run-time value.  */				      \
+  scope = _dl_object_relocation_scope (l);				      \
+  definer = &symtab[sym_index];						      \
+									      \
+  loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,	      \
+				scope, l->l_name, ELF_MACHINE_RELOC_NOPLT);   \
+									      \
+  *_dl_global_scope_end = NULL;						      \
+									      \
+  /* Apply the relocation with that value.  */				      \
+  funcaddr = loadbase + definer->st_value;				      \
+  *(got + local_gotno + sym_index - gotsym) = funcaddr;			      \
+									      \
+  return funcaddr;							      \
+}									      \
+									      \
+asm ("\n								      \
+	.text\n								      \
+	.align	3\n							      \
+	.globl	_dl_runtime_resolve\n					      \
+	.type	_dl_runtime_resolve,@function\n				      \
+	.ent	_dl_runtime_resolve\n					      \
+_dl_runtime_resolve:\n							      \
+	.set noreorder\n						      \
+	# Save old GP to $3.\n						      \
+	move	$3,$28\n						      \
+	# Modify t9 ($25) so as to point .cpload instruction.\n		      \
+	daddu	$25,2*8\n						      \
+	# Compute GP.\n							      \
+	.cpload $25\n							      \
+	.set reorder\n							      \
+	# Save slot call pc.\n						      \
+        move	$2, $31\n						      \
+	# Save arguments and sp value in stack.\n			      \
+	dsubu	$29, 10*8\n						      \
+	.cprestore 8*8\n						      \
+	sd	$15, 9*8($29)\n						      \
+	sd	$4, 3*8($29)\n						      \
+	sd	$5, 4*8($29)\n						      \
+	sd	$6, 5*8($29)\n						      \
+	sd	$7, 6*8($29)\n						      \
+	sd	$16, 7*8($29)\n						      \
+	move	$16, $29\n						      \
+	move	$4, $24\n						      \
+	move	$5, $15\n						      \
+	move	$6, $3\n						      \
+	move	$7, $2\n						      \
+	jal	__dl_runtime_resolve\n					      \
+	move	$29, $16\n						      \
+	ld	$31, 9*8($29)\n						      \
+	ld	$4, 3*8($29)\n						      \
+	ld	$5, 4*8($29)\n						      \
+	ld	$6, 5*8($29)\n						      \
+	ld	$7, 6*8($29)\n						      \
+	ld	$16, 7*8($29)\n						      \
+	daddu	$29, 10*8\n						      \
+	move	$25, $2\n						      \
+	jr	$25\n							      \
+	.end	_dl_runtime_resolve\n					      \
 ");
 #else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-/* The flag _dl_mips_gnu_objects is set if all dynamic objects are \
-   generated by the gnu linker. */\
-int _dl_mips_gnu_objects = 1;\
-\
+#define ELF_MACHINE_RUNTIME_TRAMPOLINE					      \
+/* The flag _dl_mips_gnu_objects is set if all dynamic objects are	      \
+   generated by the gnu linker. */					      \
+int _dl_mips_gnu_objects = 1;						      \
+									      \
 /* This is called from assembly stubs below which the compiler can't see.  */ \
-static ElfW(Addr) \
-__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr)) \
-                  __attribute__ ((unused)); \
-\
-static ElfW(Addr) \
-__dl_runtime_resolve (ElfW(Word) sym_index,\
-		      ElfW(Word) return_address,\
-		      ElfW(Addr) old_gpreg,\
-		      ElfW(Addr) stub_pc)\
-{\
-  struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);\
-  const ElfW(Sym) *const symtab\
-    = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);\
-  const char *strtab\
-    = (void *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);\
-  const ElfW(Addr) *got\
-    = (const ElfW(Addr) *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);\
-  const ElfW(Word) local_gotno\
-    = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;\
-  const ElfW(Word) gotsym\
-    = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;\
-  const ElfW(Sym) *definer;\
-  ElfW(Addr) loadbase;\
-  ElfW(Addr) funcaddr;\
-  struct link_map **scope;\
-\
-  /* Look up the symbol's run-time value.  */\
-  scope = _dl_object_relocation_scope (l);\
-  definer = &symtab[sym_index];\
-\
-  loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,\
-				scope, l->l_name, DL_LOOKUP_NOPLT);\
-\
-  *_dl_global_scope_end = NULL;\
-\
-  /* Apply the relocation with that value.  */\
-  funcaddr = loadbase + definer->st_value;\
-  *(got + local_gotno + sym_index - gotsym) = funcaddr;\
-\
-  return funcaddr;\
-}\
-\
-asm ("\n\
-	.text\n\
-	.align	2\n\
-	.globl	_dl_runtime_resolve\n\
-	.type	_dl_runtime_resolve,@function\n\
-	.ent	_dl_runtime_resolve\n\
-_dl_runtime_resolve:\n\
-	.set noreorder\n\
-	# Save old GP to $3.\n\
-	move	$3,$28\n\
-	# Modify t9 ($25) so as to point .cpload instruction.\n\
-	addu	$25,8\n\
-	# Compute GP.\n\
-	.cpload $25\n\
-	.set reorder\n\
-	# Save slot call pc.\n\
-        move	$2, $31\n\
-	# Save arguments and sp value in stack.\n\
-	subu	$29, 40\n\
-	.cprestore 32\n\
-	sw	$15, 36($29)\n\
-	sw	$4, 12($29)\n\
-	sw	$5, 16($29)\n\
-	sw	$6, 20($29)\n\
-	sw	$7, 24($29)\n\
-	sw	$16, 28($29)\n\
-	move	$16, $29\n\
-	move	$4, $24\n\
-	move	$5, $15\n\
-	move	$6, $3\n\
-	move	$7, $2\n\
-	jal	__dl_runtime_resolve\n\
-	move	$29, $16\n\
-	lw	$31, 36($29)\n\
-	lw	$4, 12($29)\n\
-	lw	$5, 16($29)\n\
-	lw	$6, 20($29)\n\
-	lw	$7, 24($29)\n\
-	lw	$16, 28($29)\n\
-	addu	$29, 40\n\
-	move	$25, $2\n\
-	jr	$25\n\
-	.end	_dl_runtime_resolve\n\
+static ElfW(Addr)							      \
+__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr))	      \
+                  __attribute__ ((unused));				      \
+									      \
+static ElfW(Addr)							      \
+__dl_runtime_resolve (ElfW(Word) sym_index,				      \
+		      ElfW(Word) return_address,			      \
+		      ElfW(Addr) old_gpreg,				      \
+		      ElfW(Addr) stub_pc)				      \
+{									      \
+  struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);     \
+  const ElfW(Sym) *const symtab						      \
+    = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);     \
+  const char *strtab							      \
+    = (void *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);		      \
+  const ElfW(Addr) *got							      \
+    = (const ElfW(Addr) *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);    \
+  const ElfW(Word) local_gotno						      \
+    = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;	      \
+  const ElfW(Word) gotsym						      \
+    = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;	      \
+  const ElfW(Sym) *definer;						      \
+  ElfW(Addr) loadbase;							      \
+  ElfW(Addr) funcaddr;							      \
+  struct link_map **scope;						      \
+									      \
+  /* Look up the symbol's run-time value.  */				      \
+  scope = _dl_object_relocation_scope (l);				      \
+  definer = &symtab[sym_index];						      \
+									      \
+  loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,	      \
+				scope, l->l_name, ELF_MACHINE_RELOC_NOPLT);   \
+									      \
+  *_dl_global_scope_end = NULL;						      \
+									      \
+  /* Apply the relocation with that value.  */				      \
+  funcaddr = loadbase + definer->st_value;				      \
+  *(got + local_gotno + sym_index - gotsym) = funcaddr;			      \
+									      \
+  return funcaddr;							      \
+}									      \
+									      \
+asm ("\n								      \
+	.text\n								      \
+	.align	2\n							      \
+	.globl	_dl_runtime_resolve\n					      \
+	.type	_dl_runtime_resolve,@function\n				      \
+	.ent	_dl_runtime_resolve\n					      \
+_dl_runtime_resolve:\n							      \
+	.set noreorder\n						      \
+	# Save slot call pc.\n						      \
+	move	$3, $31\n						      \
+	# Modify t9 ($25) so as to point .cpload instruction.\n		      \
+	addu	$25,8\n							      \
+	# Compute GP.\n							      \
+	.cpload $25\n							      \
+	.set reorder\n							      \
+	# Save slot call pc.\n						      \
+        move	$2, $31\n						      \
+	# Save arguments and sp value in stack.\n			      \
+	subu	$29, 40\n						      \
+	.cprestore 32\n							      \
+	sw	$15, 36($29)\n						      \
+	sw	$4, 12($29)\n						      \
+	sw	$5, 16($29)\n						      \
+	sw	$6, 20($29)\n						      \
+	sw	$7, 24($29)\n						      \
+	sw	$16, 28($29)\n						      \
+	move	$16, $29\n						      \
+	move	$4, $24\n						      \
+	move	$5, $15\n						      \
+	move	$6, $3\n						      \
+	move	$7, $2\n						      \
+	jal	__dl_runtime_resolve\n					      \
+	move	$29, $16\n						      \
+	lw	$31, 36($29)\n						      \
+	lw	$4, 12($29)\n						      \
+	lw	$5, 16($29)\n						      \
+	lw	$6, 20($29)\n						      \
+	lw	$7, 24($29)\n						      \
+	lw	$16, 28($29)\n						      \
+	addu	$29, 40\n						      \
+	move	$25, $2\n						      \
+	jr	$25\n							      \
+	.end	_dl_runtime_resolve\n					      \
 ");
 #endif
 
 /* Mask identifying addresses reserved for the user program,
    where the dynamic linker should not map anything.  */
-#define ELF_MACHINE_USER_ADDRESS_MASK	0x00000000UL
+#define ELF_MACHINE_USER_ADDRESS_MASK	0x80000000UL
 
 
 
 /* Initial entry point code for the dynamic linker.
    The C function `_dl_start' is the real entry point;
-   its return value is the user program's entry point.  */
+   its return value is the user program's entry point.
+   Note how we have to be careful about two things:
+
+   1) That we allocate a minimal stack of 24 bytes for
+      every function call, the MIPS ABI states that even
+      if all arguments are passed in registers the procedure
+      called can use the 16 byte area pointed to by $sp
+      when it is called to store away the arguments passed
+      to it.
+
+   2) That under Linux the entry is named __start
+      and not just plain _start.  */
 
 #ifdef __mips64
 #define RTLD_START asm ("\
 	.text\n\
-	.align	3\n\
-	.globl _start\n\
-	.globl _dl_start_user\n\
-	.ent _start\n\
-_start:\n\
+	.align	3\n"\
+_RTLD_PROLOGUE (ENTRY_POINT)\
+"	.globl _dl_start_user\n\
 	.set noreorder\n\
 	bltzal $0, 0f\n\
 	nop\n\
@@ -561,16 +640,15 @@ _dl_start_user:\n\
 	ld $5, 1*8($29)\n\
 	ld $6, 2*8$29)\n\
 	ld $7, 3*8($29)\n\
-	jr $25\n\
-	.end _start\n\
-");
+	jr $25\n"\
+_RTLD_EPILOGUE(ENTRY_POINT) \
+);
+
 #else
 #define RTLD_START asm ("\
-	.text\n\
-	.globl _start\n\
-	.globl _dl_start_user\n\
-	.ent _start\n\
-_start:\n\
+	.text\n"\
+_RTLD_PROLOGUE(ENTRY_POINT)\
+"	.globl _dl_start_user\n\
 	.set noreorder\n\
 	bltzal $0, 0f\n\
 	nop\n\
@@ -582,7 +660,9 @@ _start:\n\
 	la $4, _DYNAMIC\n\
 	sw $4, -0x7ff0($28)\n\
 	move $4, $29\n\
+	subu $29, 16\n\
 	jal _dl_start\n\
+	addiu $29, 16\n\
 	# Get the value of label '_dl_start_user' in t9 ($25).\n\
 	la $25, _dl_start_user\n\
 _dl_start_user:\n\
@@ -610,7 +690,9 @@ _dl_start_user:\n\
 	lw $4, 8($2)\n\
 	# Call _dl_init_next to return the address of an initializer\n\
 	# function to run.\n\
+	subu $29, 16\n\
 	jal _dl_init_next\n\
+	addiu $29, 16\n\
 	move $28, $16\n\
 	# Check for zero return,  when out of initializers.\n\
 	beq $2, $0, 2f\n\
@@ -624,16 +706,18 @@ _dl_start_user:\n\
 	move $28, $16\n\
 	# Loop to call _dl_init_next for the next initializer.\n\
 	b 1b\n\
+2:	# Clear the startup flag.  Assumes 32 bit ints.\n\
+	sw $0, _dl_starting_up\n\
 	# Pass our finalizer function to the user in ra.\n\
-2:	la $31, _dl_fini\n\
+	la $31, _dl_fini\n\
 	# Jump to the user entry point.\n\
 	move $25, $17\n\
 	lw $4, 0($29)\n\
 	lw $5, 4($29)\n\
 	lw $6, 8($29)\n\
 	lw $7, 12($29)\n\
-	jr $25\n\
-	.end _start\n\
+	jr $25\n"\
+_RTLD_EPILOGUE(ENTRY_POINT)\
 ");
 #endif
 
diff --git a/sysdeps/mips/elf/start.S b/sysdeps/mips/elf/start.S
index 355a4a905c..ce9ad9c7ec 100644
--- a/sysdeps/mips/elf/start.S
+++ b/sysdeps/mips/elf/start.S
@@ -17,6 +17,12 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <entry.h>
+
+#ifndef ENTRY_POINT
+#error ENTRY_POINT needs to be defined for start.S on MIPS/ELF.
+#endif
+
 /* This is the canonical entry point, usually the first thing in the text
    segment.  The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry
    point runs, most registers' values are unspecified, except for:
@@ -53,8 +59,8 @@
 #endif
 
 	.text
-	.globl _start
-_start:
+	.globl ENTRY_POINT
+ENTRY_POINT:
 #ifdef PIC
 	SET_GP
 #endif
@@ -81,20 +87,9 @@ nofini:
 	   the prologue of __libc_init_first, we preload them to
 	   prevent clobbering the stack tops. In Hurd case, stack pointer
 	   ($29) may be VM_MAX_ADDRESS here. If so, we must modify it.  */
-#if (__mips64)
-	dli $4, 0x10000000000
-	bne $29, $4, 1f
-	dsubu $29, 32
-	sd $0, 0($29)
-	sd $0, 8($29)
-	sd $0, 16($29)
-	sd $0, 24($29)
-1:
-	ld $4, 0($29)
-	ld $5, 8($29)
-	ld $6, 16($29)
-	ld $7, 24($29)
-#else  /* __mips64 */
+#if 0
+	jal mach_host_self
+#endif
 	li $4, 0x80000000
 	bne $29, $4, 1f
 	subu $29, 16
@@ -107,23 +102,14 @@ nofini:
 	lw $5, 4($29)
 	lw $6, 8($29)
 	lw $7, 12($29)
-#endif  /* __mips64 */
-
 	jal __libc_init_first
 #ifdef PIC
 	SET_GP
 #endif
-#if (__mips64)
-	ld $4, 0($29)
-	ld $5, 8($29)
-	ld $6, 16($29)
-	ld $7, 24($29)
-#else  /* __mips64 */
 	lw $4, 0($29)
 	lw $5, 4($29)
 	lw $6, 8($29)
 	lw $7, 12($29)
-#endif  /* __mips64 */
 
 	/* Call `_init', which is the entry point to our own `.init'
 	   section; and register with `atexit' to have `exit' call
@@ -145,19 +131,11 @@ nofini:
 
 	/* Extract the arguments and environment as encoded on the stack
 	   and set up the arguments for `main': argc, argv, envp.  */
-#if (__mips64)
-	ld $4, 0($29)		/* argc */
-	daddu $5, $29, 8	/* argv */
-	dsll $6, $4, 3
-	daddu $6, $6, 8
-	daddu $6, $5, $6	/* envp = &argv[argc + 1] */
-#else  /* __mips64 */
 	lw $4, 0($29)		/* argc */
 	addu $5, $29, 4		/* argv */
 	sll $6, $4, 2
 	addu $6, $6, 4
 	addu $6, $5, $6		/* envp = &argv[argc + 1] */
-#endif  /* __mips64 */
 
 	/* Call the user's main function, and exit with its value.  */
 	jal main
@@ -172,10 +150,11 @@ hlt:	b hlt			/* Crash if somehow it does return.  */
 	.data
 	.globl __data_start
 __data_start:
-#if (__mips64)
-	.dword 0
-#else  /* __mips64 */
-	.word 0
-#endif  /* __mips64 */
+	.long 0
 	.weak data_start
 	data_start = __data_start
+
+	.comm errno, 4, 4
+#ifdef __ELF__
+	.type errno, @object
+#endif
diff --git a/sysdeps/mips/fpu_control.h b/sysdeps/mips/fpu_control.h
index 36e05a4f6e..e271ae1fcc 100644
--- a/sysdeps/mips/fpu_control.h
+++ b/sysdeps/mips/fpu_control.h
@@ -1,7 +1,7 @@
 /* FPU control word bits.  Mips version.
    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Olaf Flebbe.
+   Contributed by Olaf Flebbe and Ralf Baechle.
 
    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
@@ -21,74 +21,84 @@
 #ifndef _FPU_CONTROL_H
 #define _FPU_CONTROL_H
 
-/* FP control/status register bit assignments.
+/* MIPS FPU floating point control register bits.
  *
- *     31-25    24  23     22-18       17-12          11-7       6-2     1-0
- *                                    (cause)      (enables)   (flags)
- * | reserved | FS | C | reserved | E V Z O U I | V Z O U I | V Z O U I | RM
+ * 31-25  -> floating point conditions code bits 7-1.  These bits are only
+ *           available in MIPS IV.
+ * 24     -> flush denormalized results to zero instead of
+ *           causing unimplemented operation exception.  This bit is only
+ *           available for MIPS III and newer.
+ * 23     -> Condition bit
+ * 22-18  -> reserved (read as 0, write with 0)
+ * 17     -> cause bit for unimplemented operation
+ * 16     -> cause bit for invalid exception
+ * 15     -> cause bit for division by zero exception
+ * 14     -> cause bit for overflow exception
+ * 13     -> cause bit for underflow exception
+ * 12     -> cause bit for inexact exception
+ * 11     -> enable exception for invalid exception
+ * 10     -> enable exception for division by zero exception
+ *  9     -> enable exception for overflow exception
+ *  8     -> enable exception for underflow exception
+ *  7     -> enable exception for inexact exception
+ *  6     -> flag invalid exception
+ *  5     -> flag division by zero exception
+ *  4     -> flag overflow exception
+ *  3     -> flag underflow exception
+ *  2     -> flag inexact exception
+ *  1-0   -> rounding control
  *
- * FS: When set, denormalized results are flushed to zero instead of
- *     causing an unimplemented operation exception.
- * C:  Condition bit.
- * E:  Unimplemented Operation.
- * V:  Invalid Operation.
- * Z:  Division by zero.
- * O:  Overflow.
- * U:  Underflow.
- * I:  Inexact Operation
- * RM: Rounding mode bits
- * 00 (RN) - rounding to nearest
- * 01 (RZ) - rounding toward zero
- * 10 (RP) - rounding down (toward - infinity)
- * 11 (RM) - rounding up (toward + infinity)
  *
+ * Rounding Control:
+ * 00 - rounding to nearest (RN)
+ * 01 - rounding toward zero (RZ)
+ * 01 - rounding (up) toward plus infinity (RP)
+ * 11 - rounding (down)toward minus infinity (RM)
  */
 
 #include <features.h>
 
 /* masking of interrupts */
-#define _FPU_MASK_IM  (1 << 11)
-#define _FPU_MASK_DM  (1 << 24)	/* XXX */
-#define _FPU_MASK_ZM  (1 << 10)
-#define _FPU_MASK_OM  (1 << 9)
-#define _FPU_MASK_UM  (1 << 8)
-#define _FPU_MASK_PM  (1 << 7)
-
-/* precision control */
-#define _FPU_EXTENDED 0
-#define _FPU_DOUBLE   0
-#define _FPU_SINGLE   0
+#define _FPU_MASK_V     0x0800  /* Invalid operation */
+#define _FPU_MASK_Z     0x0400  /* Division by zero  */
+#define _FPU_MASK_O     0x0200  /* Overflow          */
+#define _FPU_MASK_U     0x0100  /* Underflow         */
+#define _FPU_MASK_I     0x0080  /* Inexact operation */
+
+/* flush denormalized numbers to zero */
+#define _FPU_FLUSH_TZ   0x1000000
 
 /* rounding control */
-#define _FPU_RC_NEAREST 0x0    /* RECOMMENDED */
-#define _FPU_RC_DOWN    0x2
-#define _FPU_RC_UP      0x3
+#define _FPU_RC_NEAREST 0x0     /* RECOMMENDED */
 #define _FPU_RC_ZERO    0x1
+#define _FPU_RC_UP      0x2
+#define _FPU_RC_DOWN    0x3
 
-#define _FPU_RESERVED 0xfe7c0000  /* Reserved bits */
+#define _FPU_RESERVED 0xfe3c0000  /* Reserved bits in cw */
 
 
 /* The fdlibm code requires strict IEEE double precision arithmetic,
    and no interrupts for exceptions, rounding to nearest.  */
 
-#define _FPU_DEFAULT  0x0
+#define _FPU_DEFAULT  0x00000600
 
 /* IEEE:  same as above, but exceptions */
-#define _FPU_IEEE     (0x1f << 7)
+#define _FPU_IEEE     0x00000F80
 
 /* Type of the control word.  */
-typedef unsigned int fpu_control_t;
+typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
 
 /* Macros for accessing the hardware control word.  */
-#define _FPU_GETCW(cw) __asm__ ("cfc1 %0, $31; nop; nop" : "=r" (cw))
-#define _FPU_SETCW(cw) __asm__ ("ctc1 %0, $31; nop; nop" : : "r" (cw))
+#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw) : )
+#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw))
 
 /* Default control word set at startup.  */
 extern fpu_control_t __fpu_control;
 
 __BEGIN_DECLS
 
-/* Called at startup.  It can be used to manipulate fpu control register.  */
+/* Called at startup.  It can be used to manipulate the fpu control
+   register.  */
 extern void __setfpucw __P ((fpu_control_t));
 
 __END_DECLS
diff --git a/sysdeps/mips/mips64/rtld-parms b/sysdeps/mips/mips64/rtld-parms
new file mode 100644
index 0000000000..77dfc39ef4
--- /dev/null
+++ b/sysdeps/mips/mips64/rtld-parms
@@ -0,0 +1,3 @@
+ifndef rtld-wordsize
+rtld-wordsize = 64
+endif
diff --git a/sysdeps/mips/mipsel/rtld-parms b/sysdeps/mips/mipsel/rtld-parms
new file mode 100644
index 0000000000..07fac51647
--- /dev/null
+++ b/sysdeps/mips/mipsel/rtld-parms
@@ -0,0 +1,3 @@
+ifndef rtld-oformat
+rtld-oformat = elf32-littlemips
+endif
diff --git a/sysdeps/mips/rtld-ldscript.in b/sysdeps/mips/rtld-ldscript.in
new file mode 100644
index 0000000000..7c9f65f3e7
--- /dev/null
+++ b/sysdeps/mips/rtld-ldscript.in
@@ -0,0 +1,106 @@
+OUTPUT_FORMAT("@@rtld-oformat@@")
+OUTPUT_ARCH(@@rtld-arch@@)
+ENTRY(@@rtld-entry@@)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = @@rtld-base@@;
+  .reginfo       : { *(.reginfo) }
+  .dynamic       : { *(.dynamic) }
+  .dynstr        : { *(.dynstr)		}
+  .dynsym        : { *(.dynsym)		}
+  .hash          : { *(.hash)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.init      : { *(.rel.init)	}
+  .rela.init     : { *(.rela.init)	}
+  .rel.fini      : { *(.rel.fini)	}
+  .rela.fini     : { *(.rela.fini)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .rodata    : { *(.rodata)  }
+  .rodata1   : { *(.rodata1) }
+  .init          : { *(.init)	} =0
+  .text      :
+  {
+    *(.text)
+    *(.stub)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  .fini      : { *(.fini)    } =0
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = 0x10000000;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . += 0x10000;
+  .data    :
+  {
+    *(.data)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  _gp = ALIGN(16) + 0x7ff0;
+  .got           :
+  {
+    *(.got.plt) *(.got)
+   }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .sbss      : { *(.sbss) *(.scommon) }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  /* The normal linker scripts created by the binutils doesn't have the
+     symbols end and _end which breaks ld.so's dl-minimal.c.  */
+  _end = . ;
+  PROVIDE (end = .);
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}
diff --git a/sysdeps/mips/setjmp.S b/sysdeps/mips/setjmp.S
index bc42dcb03b..607b5f268d 100644
--- a/sysdeps/mips/setjmp.S
+++ b/sysdeps/mips/setjmp.S
@@ -26,10 +26,20 @@
 #endif
 ENTRY (__sigsetjmp)
 #ifdef PIC
-	.cpload t9
+	.set	noreorder
+	.cpload	t9
+	.set	reorder
 #endif
-	move a2, sp
-	move a3, fp
-	la t9, __sigsetjmp_aux
-	nop
-	jr t9
+	move	a2, sp
+#ifdef fp
+	move	a3, fp
+#else
+	move	a3, $fp
+#endif
+#ifdef PIC
+	la	t9, __sigsetjmp_aux
+	jr	t9
+#else
+	j	__sigsetjmp_aux
+#endif
+	.end __sigsetjmp