summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-07-06 16:26:03 +0000
committerUlrich Drepper <drepper@redhat.com>1999-07-06 16:26:03 +0000
commit2e65ca2b226a55e7d25ef687ce33185c0a71bd99 (patch)
tree0b76ef817b2b4977374fe025016e80fcd2e4f3ff
parent4708015f24a69bd0a436483c4d1244d1fb1f2e87 (diff)
downloadglibc-2e65ca2b226a55e7d25ef687ce33185c0a71bd99.tar.gz
glibc-2e65ca2b226a55e7d25ef687ce33185c0a71bd99.tar.xz
glibc-2e65ca2b226a55e7d25ef687ce33185c0a71bd99.zip
Update.
1999-07-06  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/unix/sysv/linux/alpha/ioperm.c: Update for some more
	motherboards.
	Patch by Jay Estabrook.

	* sysdeps/unix/sysv/linux/configure.in: Don't test for libc4 in
	ldd for SPARC.
	* /sysdeps/unix/sysv/linux/sparc/ldd-rewrite.sed: New file.
	Patch by Cristian Gafton.

1999-07-02  Cristian Gafton  <gafton@redhat.com>

	* sysdeps/unix/sysv/linux/bits/socket.h (__cmsg_nxthdr): "return 0"
	instead of "return NULL" to make C++ happy.

1999-07-04  Mark Kettenis  <kettenis@gnu.org>

	* libio/iofdopen.c (_IO_new_fdopen): Set EINVAL if MODE is not
	allowed by the file access mode of the open file.

1999-07-06  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/generic/setfpucw.c: Include math.h to get all needed
	macros defined.

1999-07-03  Jakub Jelinek   <jj@ultra.linux.cz>

	* sysdeps/sparc/sparc64/submul_1.S: Fix carry handling. Optimize.
	* sysdeps/sparc/sparc64/lshift.S: Make a leaf subroutine. Optimize.
	* sysdeps/sparc/sparc64/rshift.S: Likewise.
	* sysdeps/sparc/sparc64/mul_1.S: Optimize.

1999-07-04  Wolfram Gloger  <wmglo@dent.med.uni-muenchen.de>

	* malloc/malloc.c (request2size): Check for overflow and return
	NULL whenever it is encountered.

1999-07-04  Zack Weinberg  <zack@rabi.columbia.edu>

	* sysdeps/posix/tempname.c (__gen_tempname):   Add
	ability to create directories.  Replace OPENIT and LARGEFILE
	args with a single flags parameter.
	* sysdeps/generic/tempname.c: Likewise.
	* include/stdio.h: Adjust prototype of __gen_tempname to
	match.  Define symbolic constants for second argument.

	* misc/mkdtemp.c: New file, provides new function mkdtemp().
	* stdlib/stdlib.h: Prototype it.
	* misc/Versions: Export it.
	* misc/Makefile (routines): Add mktemp.
	* manual/filesys.texi: Document it.

	* misc/mktemp.c: Adjust call of __gen_tempname to match new
	convention.
	* misc/mkstemp.c: Likewise.
	* stdio-common/tempnam.c: Likewise.
	* stdio-common/tmpfile.c: Likewise.
	* stdio-common/tmpfile64.c: Likewise.
	* stdio-common/tmpnam.c: Likewise.
	* stdio-common/tmpnam_r.c: Likewise.

1999-07-05  Jakub Jelinek   <jj@ultra.linux.cz>

	* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_rela): Support
	R_SPARC_OLO10 relocations.
	* elf/elf.h (R_SPARC_OLO10): Fix comment.
-rw-r--r--BUGS10
-rw-r--r--ChangeLog68
-rw-r--r--elf/elf.h2
-rw-r--r--include/stdio.h7
-rw-r--r--libio/iofdopen.c11
-rw-r--r--malloc/malloc.c51
-rw-r--r--manual/filesys.texi27
-rw-r--r--misc/Makefile2
-rw-r--r--misc/Versions4
-rw-r--r--misc/mkdtemp.c35
-rw-r--r--misc/mkstemp.c4
-rw-r--r--misc/mktemp.c4
-rw-r--r--stdio-common/tempnam.c4
-rw-r--r--stdio-common/tmpfile.c4
-rw-r--r--stdio-common/tmpfile64.c4
-rw-r--r--stdio-common/tmpnam.c4
-rw-r--r--stdio-common/tmpnam_r.c4
-rw-r--r--stdlib/stdlib.h9
-rw-r--r--sysdeps/generic/setfpucw.c3
-rw-r--r--sysdeps/generic/tempname.c16
-rw-r--r--sysdeps/posix/tempname.c65
-rw-r--r--sysdeps/sparc/sparc64/dl-machine.h16
-rw-r--r--sysdeps/sparc/sparc64/lshift.S127
-rw-r--r--sysdeps/sparc/sparc64/mul_1.S7
-rw-r--r--sysdeps/sparc/sparc64/rshift.S121
-rw-r--r--sysdeps/sparc/sparc64/submul_1.S38
-rw-r--r--sysdeps/unix/sysv/linux/alpha/ioperm.c383
-rw-r--r--sysdeps/unix/sysv/linux/bits/socket.h4
-rw-r--r--sysdeps/unix/sysv/linux/configure.in5
-rw-r--r--sysdeps/unix/sysv/linux/sparc/ldd-rewrite.sed2
30 files changed, 656 insertions, 385 deletions
diff --git a/BUGS b/BUGS
index 9a6dd62ab8..9b546c60dd 100644
--- a/BUGS
+++ b/BUGS
@@ -1,7 +1,7 @@
 	    List of known bugs (certainly very incomplete)
 	    ----------------------------------------------
 
-Time-stamp: <1999-04-19T17:58:10-0700 drepper>
+Time-stamp: <1999-07-06T15:37:11-0700 drepper>
 
 This following list contains those bugs which I'm aware of.  Please
 make sure that bugs you report are not listed here.  If you can fix one
@@ -56,13 +56,13 @@ Severity: [  *] to [***]
 [  *]  The libm-ieee `scalb' function gives wrong results for
        non-integral second parameters.
 
-[  *]  The *scanf() functions currently do not handle %l[ and %ls parameters
-       correctly since the parsing of the multi-byte characters does not
-       yet use mbsrtowcs().
-
 [  *]  The strftime() implementation cannot handle multibyte locales really
        good since the TOLOWER and TOUPPER are not prepared.
 
+[  *]  The putenv() function copies it's argument which means that the
+       string (and possible later changes to it) are not automatically
+       reflected in the environment.
+
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Ulrich Drepper
 drepper@cygnus.com
diff --git a/ChangeLog b/ChangeLog
index 5950790ad1..c931262070 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,71 @@
+1999-07-06  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/sysv/linux/alpha/ioperm.c: Update for some more
+	motherboards.
+	Patch by Jay Estabrook.
+
+	* sysdeps/unix/sysv/linux/configure.in: Don't test for libc4 in
+	ldd for SPARC.
+	* /sysdeps/unix/sysv/linux/sparc/ldd-rewrite.sed: New file.
+	Patch by Cristian Gafton.
+
+1999-07-02  Cristian Gafton  <gafton@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/socket.h (__cmsg_nxthdr): "return 0"
+	instead of "return NULL" to make C++ happy.
+
+1999-07-04  Mark Kettenis  <kettenis@gnu.org>
+
+	* libio/iofdopen.c (_IO_new_fdopen): Set EINVAL if MODE is not
+	allowed by the file access mode of the open file.
+
+1999-07-06  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/generic/setfpucw.c: Include math.h to get all needed
+	macros defined.
+
+1999-07-03  Jakub Jelinek   <jj@ultra.linux.cz>
+
+	* sysdeps/sparc/sparc64/submul_1.S: Fix carry handling. Optimize.
+	* sysdeps/sparc/sparc64/lshift.S: Make a leaf subroutine. Optimize.
+	* sysdeps/sparc/sparc64/rshift.S: Likewise.
+	* sysdeps/sparc/sparc64/mul_1.S: Optimize.
+
+1999-07-04  Wolfram Gloger  <wmglo@dent.med.uni-muenchen.de>
+
+	* malloc/malloc.c (request2size): Check for overflow and return
+	NULL whenever it is encountered.
+
+1999-07-04  Zack Weinberg  <zack@rabi.columbia.edu>
+
+	* sysdeps/posix/tempname.c (__gen_tempname):   Add
+	ability to create directories.  Replace OPENIT and LARGEFILE
+	args with a single flags parameter.
+	* sysdeps/generic/tempname.c: Likewise.
+	* include/stdio.h: Adjust prototype of __gen_tempname to
+	match.  Define symbolic constants for second argument.
+
+	* misc/mkdtemp.c: New file, provides new function mkdtemp().
+	* stdlib/stdlib.h: Prototype it.
+	* misc/Versions: Export it.
+	* misc/Makefile (routines): Add mktemp.
+	* manual/filesys.texi: Document it.
+
+	* misc/mktemp.c: Adjust call of __gen_tempname to match new
+	convention.
+	* misc/mkstemp.c: Likewise.
+	* stdio-common/tempnam.c: Likewise.
+	* stdio-common/tmpfile.c: Likewise.
+	* stdio-common/tmpfile64.c: Likewise.
+	* stdio-common/tmpnam.c: Likewise.
+	* stdio-common/tmpnam_r.c: Likewise.
+
+1999-07-05  Jakub Jelinek   <jj@ultra.linux.cz>
+
+	* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_rela): Support
+	R_SPARC_OLO10 relocations.
+	* elf/elf.h (R_SPARC_OLO10): Fix comment.
+
 1999-07-02  Tim Waugh  <tim@cyberelk.demon.co.uk>
 
 	* posix/wordexp-test.c: Revert bogus 'unset IFS' change.  It
diff --git a/elf/elf.h b/elf/elf.h
index 9b368bb44d..7c98051396 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -929,7 +929,7 @@ typedef struct
 #define R_SPARC_10	30		/* Direct 10 bit */
 #define R_SPARC_11	31		/* Direct 11 bit */
 #define R_SPARC_64	32		/* Direct 64 bit */
-#define R_SPARC_OLO10	33		/* ?? */
+#define R_SPARC_OLO10	33		/* 10bit with secondary 13bit addend */
 #define R_SPARC_HH22	34		/* Top 22 bits of direct 64 bit */
 #define R_SPARC_HM10	35		/* High middle 10 bits of ... */
 #define R_SPARC_LM22	36		/* Low middle 22 bits of ... */
diff --git a/include/stdio.h b/include/stdio.h
index dcc9c15ec7..eff125f476 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -36,7 +36,12 @@ extern int __path_search __P ((char *__tmpl, size_t __tmpl_len,
 			       __const char *__dir, __const char *__pfx,
 			       int __try_tempdir));
 
-extern int __gen_tempname __P ((char *__tmpl, int __openit, int __large_file));
+extern int __gen_tempname __P ((char *__tmpl, int __kind));
+/* The __kind argument to __gen_tempname may be one of: */
+#define __GT_FILE	0	/* create a file */
+#define __GT_BIGFILE	1	/* create a file, using open64 */
+#define __GT_DIR	2	/* create a directory */
+#define __GT_NOCREATE	3	/* just find a name not currently in use */
 
 /* Print out MESSAGE on the error output and abort.  */
 extern void __libc_fatal __P ((__const char *__message))
diff --git a/libio/iofdopen.c b/libio/iofdopen.c
index 3bfa40c7c6..e8e32e03dc 100644
--- a/libio/iofdopen.c
+++ b/libio/iofdopen.c
@@ -77,10 +77,15 @@ _IO_new_fdopen (fd, mode)
 #ifndef O_ACCMODE
 #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
 #endif
-  if (fd_flags == -1
-      || ((fd_flags & O_ACCMODE) == O_RDONLY && !(read_write & _IO_NO_WRITES))
-      || ((fd_flags & O_ACCMODE) == O_WRONLY && !(read_write & _IO_NO_READS)))
+  if (fd_flags == -1)
     return NULL;
+  
+  if (((fd_flags & O_ACCMODE) == O_RDONLY && !(read_write & _IO_NO_WRITES))
+      || ((fd_flags & O_ACCMODE) == O_WRONLY && !(read_write & _IO_NO_READS)))
+    {
+      MAYBE_SET_EINVAL;
+      return NULL;
+    }
 
   /* The May 93 draft of P1003.4/D14.1 (redesignated as 1003.1b)
      [System Application Program Interface (API) Amendment 1:
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 01ff7aa304..e096f00eeb 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1259,12 +1259,12 @@ static void      free_atfork();
 #define chunk2mem(p)   ((Void_t*)((char*)(p) + 2*SIZE_SZ))
 #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
 
-/* pad request bytes into a usable size */
+/* pad request bytes into a usable size, return non-zero on overflow */
 
-#define request2size(req) \
- (((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \
-  (long)(MINSIZE + MALLOC_ALIGN_MASK)) ? MINSIZE : \
-   (((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK)))
+#define request2size(req, nb) \
+ ((nb = (req) + (SIZE_SZ + MALLOC_ALIGN_MASK)),\
+  ((long)nb <= 0 ? 1 : ((nb < (MINSIZE + MALLOC_ALIGN_MASK) ? (nb = MINSIZE) :\
+                         (nb &= ~MALLOC_ALIGN_MASK)), 0)))
 
 /* Check if m has acceptable alignment */
 
@@ -2622,7 +2622,8 @@ Void_t* mALLOc(bytes) size_t bytes;
   }
 #endif
 
-  nb = request2size(bytes);
+  if(request2size(bytes, nb))
+    return 0;
   arena_get(ar_ptr, nb);
   if(!ar_ptr)
     return 0;
@@ -3133,7 +3134,8 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
   oldp    = mem2chunk(oldmem);
   oldsize = chunksize(oldp);
 
-  nb = request2size(bytes);
+  if(request2size(bytes, nb))
+    return 0;
 
 #if HAVE_MMAP
   if (chunk_is_mmapped(oldp))
@@ -3399,7 +3401,8 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
 
   if (alignment <  MINSIZE) alignment = MINSIZE;
 
-  nb = request2size(bytes);
+  if(request2size(bytes, nb))
+    return 0;
   arena_get(ar_ptr, nb + alignment + MINSIZE);
   if(!ar_ptr)
     return 0;
@@ -3574,7 +3577,8 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size;
   }
 #endif
 
-  sz = request2size(n * elem_size);
+  if(request2size(n * elem_size, sz))
+    return 0;
   arena_get(ar_ptr, sz);
   if(!ar_ptr)
     return 0;
@@ -4364,8 +4368,10 @@ malloc_check(sz, caller) size_t sz; const Void_t *caller;
 #endif
 {
   mchunkptr victim;
-  INTERNAL_SIZE_T nb = request2size(sz + 1);
+  INTERNAL_SIZE_T nb;
 
+  if(request2size(sz+1, nb))
+    return 0;
   (void)mutex_lock(&main_arena.mutex);
   victim = (top_check() >= 0) ? chunk_alloc(&main_arena, nb) : NULL;
   (void)mutex_unlock(&main_arena.mutex);
@@ -4434,7 +4440,10 @@ realloc_check(oldmem, bytes, caller)
   }
   oldsize = chunksize(oldp);
 
-  nb = request2size(bytes+1);
+  if(request2size(bytes+1, nb)) {
+    (void)mutex_unlock(&main_arena.mutex);
+    return 0;
+  }
 
 #if HAVE_MMAP
   if (chunk_is_mmapped(oldp)) {
@@ -4491,7 +4500,8 @@ memalign_check(alignment, bytes, caller)
   if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL);
   if (alignment <  MINSIZE) alignment = MINSIZE;
 
-  nb = request2size(bytes+1);
+  if(request2size(bytes+1, nb))
+    return 0;
   (void)mutex_lock(&main_arena.mutex);
   p = (top_check() >= 0) ? chunk_align(&main_arena, nb, alignment) : NULL;
   (void)mutex_unlock(&main_arena.mutex);
@@ -4511,7 +4521,12 @@ malloc_starter(size_t sz, const Void_t *caller)
 malloc_starter(sz, caller) size_t sz; const Void_t *caller;
 #endif
 {
-  mchunkptr victim = chunk_alloc(&main_arena, request2size(sz));
+  INTERNAL_SIZE_T nb;
+  mchunkptr victim;
+
+  if(request2size(sz, nb))
+    return 0;
+  victim = chunk_alloc(&main_arena, nb);
 
   return victim ? chunk2mem(victim) : 0;
 }
@@ -4547,16 +4562,20 @@ malloc_atfork(sz, caller) size_t sz; const Void_t *caller;
 #endif
 {
   Void_t *vptr = NULL;
+  INTERNAL_SIZE_T nb;
   mchunkptr victim;
 
   tsd_getspecific(arena_key, vptr);
   if(!vptr) {
     if(save_malloc_hook != malloc_check) {
-      victim = chunk_alloc(&main_arena, request2size(sz));
+      if(request2size(sz, nb))
+        return 0;
+      victim = chunk_alloc(&main_arena, nb);
       return victim ? chunk2mem(victim) : 0;
     } else {
-      if(top_check() < 0) return 0;
-      victim = chunk_alloc(&main_arena, request2size(sz+1));
+      if(top_check()<0 || request2size(sz+1, nb))
+        return 0;
+      victim = chunk_alloc(&main_arena, nb);
       return victim ? chunk2mem_check(victim, sz) : 0;
     }
   } else {
diff --git a/manual/filesys.texi b/manual/filesys.texi
index 51af84633d..29f20758e8 100644
--- a/manual/filesys.texi
+++ b/manual/filesys.texi
@@ -2935,7 +2935,7 @@ end with @samp{XXXXXX}, @code{mkstemp} returns @code{-1} and does not
 modify @var{template}.
 
 The file is opened using mode @code{0600}.  If the file is meant to be
-used by other users the mode must explicitly changed.
+used by other users the mode must be changed explicitly.
 @end deftypefun
 
 Unlike @code{mktemp}, @code{mkstemp} is actually guaranteed to create a
@@ -2943,3 +2943,28 @@ unique file that cannot possibly clash with any other program trying to
 create a temporary file.  This is because it works by calling
 @code{open} with the @code{O_EXCL} flag bit, which says you want to
 always create a new file, and get an error if the file already exists.
+
+@comment stdlib.h
+@comment BSD
+@deftypefun {char *} mkdtemp (char *@var{template})
+The @code{mkdtemp} function creates a directory with a unique name.  If
+it succeeds, it overwrites @var{template} with the name of the
+directory, and returns @var{template}.  As with @code{mktemp} and
+@code{mkstemp}, @var{template} should be a string ending with
+@samp{XXXXXX}.
+
+If @code{mkdtemp} cannot create an uniquely named directory, it returns
+@code{NULL} and sets @var{errno} appropriately.  If @var{template} does
+not end with @samp{XXXXXX}, @code{mkdtemp} returns @code{NULL} and does
+not modify @var{template}.  @var{errno} will be set to @code{EINVAL} in
+this case.
+
+The directory is created using mode @code{0700}.
+@end deftypefun
+
+The directory created by @code{mkdtemp} cannot clash with temporary
+files or directories created by other users.  This is because directory
+creation always works like @code{open} with @code{O_EXCL}.
+@xref{Creating Directories}.
+
+The @code{mkdtemp} function comes from OpenBSD.
diff --git a/misc/Makefile b/misc/Makefile
index 948c087edf..a1aeaa6c32 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -42,7 +42,7 @@ routines := brk sbrk sstk ioctl \
 	    acct chroot fsync sync fdatasync reboot \
 	    gethostid sethostid \
 	    revoke vhangup \
-	    swapon swapoff mktemp mkstemp \
+	    swapon swapoff mktemp mkstemp mkdtemp \
 	    ualarm usleep \
 	    gtty stty \
 	    ptrace \
diff --git a/misc/Versions b/misc/Versions
index 110606330e..d9eee7a746 100644
--- a/misc/Versions
+++ b/misc/Versions
@@ -102,4 +102,8 @@ libc {
     # t*
     tdestroy; truncate64;
   }
+  GLIBC_2.2 {
+    # m*
+    mkdtemp;
+  }
 }
diff --git a/misc/mkdtemp.c b/misc/mkdtemp.c
new file mode 100644
index 0000000000..3961c7a097
--- /dev/null
+++ b/misc/mkdtemp.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1999 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.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Generate a unique temporary directory from TEMPLATE.
+   The last six characters of TEMPLATE must be "XXXXXX";
+   they are replaced with a string that makes the filename unique.
+   The directory is created, mode 700, and its name is returned.
+   (This function comes from OpenBSD.) */
+char *
+mkdtemp (template)
+     char *template;
+{
+  if (__gen_tempname (template, __GT_DIR))
+    return NULL;
+  else
+    return template;
+}
diff --git a/misc/mkstemp.c b/misc/mkstemp.c
index fc911da9a1..8441c8ee2a 100644
--- a/misc/mkstemp.c
+++ b/misc/mkstemp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999 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
@@ -27,5 +27,5 @@ int
 mkstemp (template)
      char *template;
 {
-  return __gen_tempname (template, 1, 0);
+  return __gen_tempname (template, __GT_FILE);
 }
diff --git a/misc/mktemp.c b/misc/mktemp.c
index 36b50031b9..4130f9e2f0 100644
--- a/misc/mktemp.c
+++ b/misc/mktemp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999 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
@@ -26,7 +26,7 @@ char *
 mktemp (template)
      char *template;
 {
-  if (__gen_tempname (template, 0, 0) < 0)
+  if (__gen_tempname (template, __GT_NOCREATE) < 0)
     /* We return the null string if we can't find a unique file name.  */
     template[0] = '\0';
 
diff --git a/stdio-common/tempnam.c b/stdio-common/tempnam.c
index 47ecf6d56d..61af145605 100644
--- a/stdio-common/tempnam.c
+++ b/stdio-common/tempnam.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1993,1996,1997,1998,1999 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
@@ -34,7 +34,7 @@ tempnam (const char *dir, const char *pfx)
   if (__path_search (buf, FILENAME_MAX, dir, pfx, 1))
     return NULL;
 
-  if (__gen_tempname (buf, 0, 0))
+  if (__gen_tempname (buf, __GT_NOCREATE))
     return NULL;
 
   return __strdup (buf);
diff --git a/stdio-common/tmpfile.c b/stdio-common/tmpfile.c
index cfd3606bec..ccf0630fa1 100644
--- a/stdio-common/tmpfile.c
+++ b/stdio-common/tmpfile.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1993,1996,1997,1998,1999 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
@@ -38,7 +38,7 @@ tmpfile (void)
 
   if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0))
     return NULL;
-  fd = __gen_tempname (buf, 1, 0);
+  fd = __gen_tempname (buf, __GT_FILE);
   if (fd < 0)
     return NULL;
 
diff --git a/stdio-common/tmpfile64.c b/stdio-common/tmpfile64.c
index 2ea6bfc3a8..f8670cbf9b 100644
--- a/stdio-common/tmpfile64.c
+++ b/stdio-common/tmpfile64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1993,1996,1997,1998,1999 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
@@ -37,7 +37,7 @@ tmpfile64 ()
 
   if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0))
     return NULL;
-  fd = __gen_tempname (buf, 1, 1);
+  fd = __gen_tempname (buf, __GT_BIGFILE);
   if (fd < 0)
     return NULL;
 
diff --git a/stdio-common/tmpnam.c b/stdio-common/tmpnam.c
index beba12d130..f78f0f0bbf 100644
--- a/stdio-common/tmpnam.c
+++ b/stdio-common/tmpnam.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1993,1996,1997,1998,1999 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
@@ -37,7 +37,7 @@ tmpnam (char *s)
   if (__path_search (s ? : tmpbuf, L_tmpnam, NULL, NULL, 0))
     return NULL;
 
-  if (__gen_tempname (s ? : tmpbuf, 0, 0))
+  if (__gen_tempname (s ? : tmpbuf, __GT_NOCREATE))
     return NULL;
 
   if (s == NULL)
diff --git a/stdio-common/tmpnam_r.c b/stdio-common/tmpnam_r.c
index 26214ecf2b..409d031dec 100644
--- a/stdio-common/tmpnam_r.c
+++ b/stdio-common/tmpnam_r.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1993,1996,1997,1998,1999 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
@@ -28,7 +28,7 @@ tmpnam_r (char *s)
 
   if (__path_search (s, L_tmpnam, NULL, NULL, 0))
     return NULL;
-  if (__gen_tempname (s, 0, 0))
+  if (__gen_tempname (s, __GT_NOCREATE))
     return NULL;
 
   return s;
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 8a47b81ed9..97fa000ea0 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -573,6 +573,15 @@ extern char *mktemp __P ((char *__template));
 extern int mkstemp __P ((char *__template));
 #endif
 
+#ifdef __USE_BSD
+/* Create a unique temporary directory from TEMPLATE.
+   The last six characters of TEMPLATE must be "XXXXXX";
+   they are replaced with a string that makes the directory name unique.
+   Returns TEMPLATE, or a null pointer if it cannot get a unique name.
+   The directory is created mode 700.  */
+extern char *mkdtemp __P ((char *__template));
+#endif
+
 
 /* Execute the given line as a shell command.  */
 extern int system __P ((__const char *__command));
diff --git a/sysdeps/generic/setfpucw.c b/sysdeps/generic/setfpucw.c
index ba91a76715..59d5de3737 100644
--- a/sysdeps/generic/setfpucw.c
+++ b/sysdeps/generic/setfpucw.c
@@ -1,5 +1,5 @@
 /* Set the FPU control word.
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1999 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
@@ -17,6 +17,7 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <math.h>
 #include <fpu_control.h>
 
 void
diff --git a/sysdeps/generic/tempname.c b/sysdeps/generic/tempname.c
index fb366fcb2b..253375c292 100644
--- a/sysdeps/generic/tempname.c
+++ b/sysdeps/generic/tempname.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 93, 95, 96, 97, 98 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 95-98, 99 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
@@ -38,13 +38,17 @@ stub_warning (__path_search)
 
 /* Generate a (hopefully) unique temporary filename
    in DIR (if applicable), using template TMPL.
-   If OPENIT is 1, open the file and return a fd.  If LARGEFILE is 1,
-   use open64() to do that. */
+   KIND determines what to do with that name.  It may be one of:
+     __GT_FILE:		create a file and return a read-write fd.
+     __GT_BIGFILE:	same, but use open64() (or equivalent).
+     __GT_DIR:		create a directory.
+     __GT_NOCREATE:	just find a name not currently in use.
+ */
+
 int
-__gen_tempname (tmpl, openit, largefile)
+__gen_tempname (tmpl, kind)
      char *tmpl;
-     int openit;
-     int largefile;
+     int kind;
 {
   __set_errno (ENOSYS);
   return -1;
diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c
index 7689bb01e3..536225e957 100644
--- a/sysdeps/posix/tempname.c
+++ b/sysdeps/posix/tempname.c
@@ -27,6 +27,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/time.h>
+#include <assert.h>
 
 /* Return nonzero if DIR is an existent directory.  */
 static int
@@ -106,20 +107,27 @@ static const char letters[] =
 /* Generate a temporary file name based on TMPL.  TMPL must match the
    rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
    does not exist at the time of the call to __gen_tempname.  TMPL is
-   overwritten with the result.  If OPENIT is nonzero, creates the
-   file and returns a read-write fd; the file is mode 0600 modulo
-   umask.  If LARGEFILE is nonzero, uses open64() instead of open().
+   overwritten with the result.
+
+   KIND may be one of:
+   __GT_NOCREATE:	simply verify that the name does not exist
+			at the time of the call.
+   __GT_FILE:		create the file using open(O_CREAT|O_EXCL)
+			and return a read-write fd.  The file is mode 0600.
+   __GT_BIGFILE:	same as __GT_FILE but use open64().
+   __GT_DIR:		create a directory, which will be mode 0700.
 
    We use a clever algorithm to get hard-to-predict names. */
 int
-__gen_tempname (char *tmpl, int openit, int largefile)
+__gen_tempname (char *tmpl, int kind)
 {
   int len;
   char *XXXXXX;
   static uint64_t value;
   struct timeval tv;
-  int count, fd;
+  int count, fd = -1;
   int save_errno = errno;
+  struct stat st;
 
   len = strlen (tmpl);
   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
@@ -152,24 +160,25 @@ __gen_tempname (char *tmpl, int openit, int largefile)
       v /= 62;
       XXXXXX[5] = letters[v % 62];
 
-      if (openit)
-	{
-	  fd = (largefile
-		? __open (tmpl, O_RDWR | O_CREAT | O_EXCL, 0600)
-		: __open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, 0600));
-	  if (fd >= 0)
-	    {
-	      __set_errno (save_errno);
-	      return fd;
-	    }
-	  else if (errno != EEXIST)
-	    /* Any other error will apply also to other names we might
-	       try, and there are 2^32 or so of them, so give up now. */
-	    return -1;
-	}
-      else
+      switch (kind)
 	{
-	  struct stat st;
+	case __GT_FILE:
+	  fd = __open (tmpl, O_RDWR | O_CREAT | O_EXCL, 0600);
+	  break;
+
+	case __GT_BIGFILE:
+	  fd = __open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, 0600);
+	  break;
+
+	case __GT_DIR:
+	  fd = __mkdir (tmpl, 0700);
+	  break;
+
+	case __GT_NOCREATE:
+	  /* This case is backward from the other three.  __gen_tempname
+	     succeeds if __xstat fails because the name does not exist.
+	     Note the continue to bypass the common logic at the bottom
+	     of the loop.  */
 	  if (__xstat (_STAT_VER, tmpl, &st) < 0)
 	    {
 	      if (errno == ENOENT)
@@ -181,7 +190,19 @@ __gen_tempname (char *tmpl, int openit, int largefile)
 		/* Give up now. */
 		return -1;
 	    }
+	  continue;
+
+	default:
+	  assert (! "invalid KIND in __gen_tempname");
+	}
+
+      if (fd >= 0)
+	{
+	  __set_errno (save_errno);
+	  return fd;
 	}
+      else if (errno != EEXIST)
+	return -1;
     }
 
   /* We got out of the loop because we ran out of combinations to try.  */
diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h
index b042989881..5a86ec57d8 100644
--- a/sysdeps/sparc/sparc64/dl-machine.h
+++ b/sysdeps/sparc/sparc64/dl-machine.h
@@ -25,6 +25,9 @@
 #include <elf/ldsodefs.h>
 #include <sysdep.h>
 
+#define ELF64_R_TYPE_ID(info)	((info) & 0xff)
+#define ELF64_R_TYPE_DATA(info) ((info) >> 8)
+
 /* Return nonzero iff E_MACHINE is compatible with the running host.  */
 static inline int
 elf_machine_matches_host (Elf64_Half e_machine)
@@ -178,14 +181,14 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
   weak_extern (_dl_rtld_map);
 #endif
 
-  if (ELF64_R_TYPE (reloc->r_info) == R_SPARC_RELATIVE)
+  if (ELF64_R_TYPE_ID (reloc->r_info) == R_SPARC_RELATIVE)
     {
 #ifndef RTLD_BOOTSTRAP
       if (map != &_dl_rtld_map) /* Already done in rtld itself. */
 #endif
 	*reloc_addr = map->l_addr + reloc->r_addend;
     }
-  else if (ELF64_R_TYPE (reloc->r_info) != R_SPARC_NONE) /* Who is Wilbur? */
+  else if (ELF64_R_TYPE_ID (reloc->r_info) != R_SPARC_NONE) /* Who is Wilbur? */
     {
       const Elf64_Sym *const refsym = sym;
       Elf64_Addr value;
@@ -194,13 +197,13 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
 	value = map->l_addr;
       else
 	{
-	  value = RESOLVE (&sym, version, ELF64_R_TYPE (reloc->r_info));
+	  value = RESOLVE (&sym, version, ELF64_R_TYPE_ID (reloc->r_info));
 	  if (sym)
 	    value += sym->st_value;
 	}
       value += reloc->r_addend;	/* Assume copy relocs have zero addend.  */
 
-      switch (ELF64_R_TYPE (reloc->r_info))
+      switch (ELF64_R_TYPE_ID (reloc->r_info))
 	{
 	case R_SPARC_COPY:
 	  if (sym == NULL)
@@ -262,6 +265,11 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
 	    ((*(unsigned int *)reloc_addr & 0xffc00000) |
 	     (value >> 10));
 	  break;
+	case R_SPARC_OLO10:
+	  *(unsigned int *) reloc_addr =
+	    ((*(unsigned int *)reloc_addr & ~0x1fff) |
+	     (((value & 0x3ff) + ELF64_R_TYPE_DATA (reloc->r_info)) & 0x1fff));
+	  break;
 
 	/* MEDMID code model relocs */
 	case R_SPARC_H44:
diff --git a/sysdeps/sparc/sparc64/lshift.S b/sysdeps/sparc/sparc64/lshift.S
index f211924ddb..4f265ad96b 100644
--- a/sysdeps/sparc/sparc64/lshift.S
+++ b/sysdeps/sparc/sparc64/lshift.S
@@ -1,6 +1,6 @@
 /* SPARC v9 __mpn_lshift --
 
-   Copyright (C) 1996 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1999 Free Software Foundation, Inc.
 
    This file is part of the GNU MP Library.
 
@@ -22,75 +22,72 @@
 #include <sysdep.h>
 
 /* INPUT PARAMETERS
-   res_ptr	%i0
-   src_ptr	%i1
-   size		%i2
-   cnt		%i3  */
+   res_ptr	%o0
+   src_ptr	%o1
+   size		%o2
+   cnt		%o3  */
 
 ENTRY(__mpn_lshift)
-	save	%sp, -192, %sp
-
-	sllx	%i2,3,%g1
-	add	%i1,%g1,%i1	! make %i1 point at end of src
-	ldx	[%i1-8],%g2	! load first limb
-	sub	%g0,%i3,%i5	! negate shift count
-	add	%i0,%g1,%i0	! make %i0 point at end of res
-	add	%i2,-1,%i2
-	and	%i2,4-1,%l4	! number of limbs in first loop
-	srlx	%g2,%i5,%g1	! compute function result
-	brz,pn	%l4,.L0		! if multiple of 4 limbs, skip first loop
-	mov	%g1,%l1
-
-	sub	%i2,%l4,%i2	! adjust count for main loop
-
-.Loop0:	ldx	[%i1-16],%g3
-	add	%i0,-8,%i0
-	add	%i1,-8,%i1
-	add	%l4,-1,%l4
-	sllx	%g2,%i3,%i4
-	srlx	%g3,%i5,%g1
+	sllx	%o2,3,%g1
+	add	%o1,%g1,%o1	! make %o1 point at end of src
+	ldx	[%o1-8],%g2	! load first limb
+	sub	%g0,%o3,%o5	! negate shift count
+	add	%o0,%g1,%o0	! make %o0 point at end of res
+	add	%o2,-1,%o2
+	andcc	%o2,4-1,%g4	! number of limbs in first loop
+	srlx	%g2,%o5,%g1	! compute function result
+	be,pn	%xcc,.L0	! if multiple of 4 limbs, skip first loop
+	 mov	%g1,%g5
+
+	sub	%o2,%g4,%o2	! adjust count for main loop
+
+.Loop0:	ldx	[%o1-16],%g3
+	add	%o0,-8,%o0
+	add	%o1,-8,%o1
+	sllx	%g2,%o3,%o4
+	addcc	%g4,-1,%g4
+	srlx	%g3,%o5,%g1
 	mov	%g3,%g2
-	or	%i4,%g1,%i4
-	brnz,pt	%l4,.Loop0
-	 stx	%i4,[%i0+0]
+	or	%o4,%g1,%o4
+	bne,pt	%xcc,.Loop0
+	 stx	%o4,[%o0+0]
 
-.L0:	brz,pn	%i2,.Lend
+.L0:	brz,pn	%o2,.Lend
 	 nop
 
-.Loop:	ldx	[%i1-16],%g3
-	add	%i0,-32,%i0
-	add	%i2,-4,%i2
-	sllx	%g2,%i3,%i4
-	srlx	%g3,%i5,%g1
-
-	ldx	[%i1-24],%g2
-	sllx	%g3,%i3,%l4
-	or	%i4,%g1,%i4
-	stx	%i4,[%i0+24]
-	srlx	%g2,%i5,%g1
-
-	ldx	[%i1-32],%g3
-	sllx	%g2,%i3,%i4
-	or	%l4,%g1,%l4
-	stx	%l4,[%i0+16]
-	srlx	%g3,%i5,%g1
-
-	ldx	[%i1-40],%g2
-	sllx	%g3,%i3,%l4
-	or	%i4,%g1,%i4
-	stx	%i4,[%i0+8]
-	srlx	%g2,%i5,%g1
-
-	add	%i1,-32,%i1
-	or	%l4,%g1,%l4
-	brnz,pt	%i2,.Loop
-	 stx	%l4,[%i0+0]
-
-.Lend:	sllx	%g2,%i3,%g2
-	stx	%g2,[%i0-8]
-
-	mov	%l1,%i0
-	jmpl	%i7+8, %g0
-	 restore
+.Loop:	ldx	[%o1-16],%g3
+	add	%o0,-32,%o0
+	sllx	%g2,%o3,%o4
+	addcc	%o2,-4,%o2
+	srlx	%g3,%o5,%g1
+
+	ldx	[%o1-24],%g2
+	sllx	%g3,%o3,%g4
+	or	%o4,%g1,%o4
+	stx	%o4,[%o0+24]
+	srlx	%g2,%o5,%g1
+
+	ldx	[%o1-32],%g3
+	sllx	%g2,%o3,%o4
+	or	%g4,%g1,%g4
+	stx	%g4,[%o0+16]
+	srlx	%g3,%o5,%g1
+
+	ldx	[%o1-40],%g2
+	sllx	%g3,%o3,%g4
+	or	%o4,%g1,%o4
+	stx	%o4,[%o0+8]
+	srlx	%g2,%o5,%g1
+
+	add	%o1,-32,%o1
+	or	%g4,%g1,%g4
+	bne,pt	%xcc,.Loop
+	 stx	%g4,[%o0+0]
+
+.Lend:	sllx	%g2,%o3,%g2
+	stx	%g2,[%o0-8]
+
+	jmpl	%o7+8, %g0
+	 mov	%g5,%o0
 
 END(__mpn_lshift)
diff --git a/sysdeps/sparc/sparc64/mul_1.S b/sysdeps/sparc/sparc64/mul_1.S
index 757856b4cd..67b9696682 100644
--- a/sysdeps/sparc/sparc64/mul_1.S
+++ b/sysdeps/sparc/sparc64/mul_1.S
@@ -72,13 +72,12 @@ ENTRY(__mpn_mul_1)
 	addcc	%i0,%o0,%i0		! add cy_limb to low 64 bits of result
 	mov	0,%g5
 	movcs	%xcc,1,%g5
-	add	%o7,1,%o7
+	addcc	%o7,1,%o7
 	stx	%i0,[%o4+%g1]
-	brnz	%o7,.Loop
+	bne,pt	%xcc,.Loop
 	 add	%i1,%g5,%o0		! compute new cy_limb
 
-	mov	%o0,%i0
 	jmpl	%i7+8,%g0
-	 restore
+	 restore %o0,%g0,%o0
 
 END(__mpn_mul_1)
diff --git a/sysdeps/sparc/sparc64/rshift.S b/sysdeps/sparc/sparc64/rshift.S
index 51eb4af3ab..f43d25efe8 100644
--- a/sysdeps/sparc/sparc64/rshift.S
+++ b/sysdeps/sparc/sparc64/rshift.S
@@ -1,6 +1,6 @@
 /* SPARC v9 __mpn_rshift --
 
-   Copyright (C) 1996 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1999 Free Software Foundation, Inc.
 
    This file is part of the GNU MP Library.
 
@@ -22,72 +22,69 @@
 #include <sysdep.h>
 
 /* INPUT PARAMETERS
-   res_ptr	%i0
-   src_ptr	%i1
-   size		%i2
-   cnt		%i3  */
+   res_ptr	%o0
+   src_ptr	%o1
+   size		%o2
+   cnt		%o3  */
 
 ENTRY(__mpn_rshift)
-	save	%sp, -192, %sp
-
-	ldx	[%i1],%g2	! load first limb
-	sub	%g0,%i3,%i5	! negate shift count
-	add	%i2,-1,%i2
-	and	%i2,4-1,%l4	! number of limbs in first loop
-	sllx	%g2,%i5,%g1	! compute function result
-	brz,pn	%l4,.L0		! if multiple of 4 limbs, skip first loop
-	mov	%g1,%l1
-
-	sub	%i2,%l4,%i2	! adjust count for main loop
-
-.Loop0:	ldx	[%i1+8],%g3
-	add	%i0,8,%i0
-	add	%i1,8,%i1
-	add	%l4,-1,%l4
-	srlx	%g2,%i3,%i4
-	sllx	%g3,%i5,%g1
+	ldx	[%o1],%g2	! load first limb
+	sub	%g0,%o3,%o5	! negate shift count
+	add	%o2,-1,%o2
+	andcc	%o2,4-1,%g4	! number of limbs in first loop
+	sllx	%g2,%o5,%g1	! compute function result
+	be,pn	%xcc,.L0	! if multiple of 4 limbs, skip first loop
+	 mov	%g1,%g5
+
+	sub	%o2,%g4,%o2	! adjust count for main loop
+
+.Loop0:	ldx	[%o1+8],%g3
+	add	%o0,8,%o0
+	add	%o1,8,%o1
+	srlx	%g2,%o3,%o4
+	addcc	%g4,-1,%g4
+	sllx	%g3,%o5,%g1
 	mov	%g3,%g2
-	or	%i4,%g1,%i4
-	brnz,pt	%l4,.Loop0
-	 stx	%i4,[%i0-8]
+	or	%o4,%g1,%o4
+	bne,pt	%xcc,.Loop0
+	 stx	%o4,[%o0-8]
 
-.L0:	brz,pn	%i2,.Lend
+.L0:	brz,pn	%o2,.Lend
 	 nop
 
-.Loop:	ldx	[%i1+8],%g3
-	add	%i0,32,%i0
-	add	%i2,-4,%i2
-	srlx	%g2,%i3,%i4
-	sllx	%g3,%i5,%g1
-
-	ldx	[%i1+16],%g2
-	srlx	%g3,%i3,%l4
-	or	%i4,%g1,%i4
-	stx	%i4,[%i0-32]
-	sllx	%g2,%i5,%g1
-
-	ldx	[%i1+24],%g3
-	srlx	%g2,%i3,%i4
-	or	%l4,%g1,%l4
-	stx	%l4,[%i0-24]
-	sllx	%g3,%i5,%g1
-
-	ldx	[%i1+32],%g2
-	srlx	%g3,%i3,%l4
-	or	%i4,%g1,%i4
-	stx	%i4,[%i0-16]
-	sllx	%g2,%i5,%g1
-
-	add	%i1,32,%i1
-	or	%l4,%g1,%l4
-	brnz	%i2,.Loop
-	 stx	%l4,[%i0-8]
-
-.Lend:	srlx	%g2,%i3,%g2
-	stx	%g2,[%i0-0]
-
-	mov	%l1,%i0
-	jmpl	%i7+8,%g0
-	 restore
+.Loop:	ldx	[%o1+8],%g3
+	add	%o0,32,%o0
+	srlx	%g2,%o3,%o4
+	addcc	%o2,-4,%o2
+	sllx	%g3,%o5,%g1
+
+	ldx	[%o1+16],%g2
+	srlx	%g3,%o3,%g4
+	or	%o4,%g1,%o4
+	stx	%o4,[%o0-32]
+	sllx	%g2,%o5,%g1
+
+	ldx	[%o1+24],%g3
+	srlx	%g2,%o3,%o4
+	or	%g4,%g1,%g4
+	stx	%g4,[%o0-24]
+	sllx	%g3,%o5,%g1
+
+	ldx	[%o1+32],%g2
+	srlx	%g3,%o3,%g4
+	or	%o4,%g1,%o4
+	stx	%o4,[%o0-16]
+	sllx	%g2,%o5,%g1
+
+	add	%o1,32,%o1
+	or	%g4,%g1,%g4
+	bne,pt	%xcc,.Loop
+	 stx	%g4,[%o0-8]
+
+.Lend:	srlx	%g2,%o3,%g2
+	stx	%g2,[%o0-0]
+
+	jmpl	%o7+8,%g0
+	 mov	%g5,%o0
 
 END(__mpn_rshift)
diff --git a/sysdeps/sparc/sparc64/submul_1.S b/sysdeps/sparc/sparc64/submul_1.S
index ce9a80464f..8f86916133 100644
--- a/sysdeps/sparc/sparc64/submul_1.S
+++ b/sysdeps/sparc/sparc64/submul_1.S
@@ -30,29 +30,26 @@
    s2_limb	o3  */
 
 ENTRY(__mpn_submul_1)
-	!#PROLOGUE#	0
 	save	%sp,-192,%sp
-	!#PROLOGUE#	1
 
 	sub	%g0,%i2,%o7
-	sllx	%o7,3,%g5
-	sub	%i1,%g5,%o3
-	sub	%i0,%g5,%o4
 	mov	0,%o0			! zero cy_limb
-
+	sllx	%o7,3,%o7
+	sethi	%hi(0x80000000),%o2
 	srl	%i3,0,%o1		! extract low 32 bits of s2_limb
+	sub	%i1,%o7,%o3
 	srlx	%i3,32,%i3		! extract high 32 bits of s2_limb
-	mov	1,%o2
-	sllx	%o2,32,%o2		! o2 = 0x100000000
+	sub	%i0,%o7,%o4
+	add	%o2,%o2,%o2		! o2 = 0x100000000
 
 	!   hi   !
              !  mid-1 !
              !  mid-2 !
 		 !   lo   !
-.Loop:
-	sllx	%o7,3,%g1
-	ldx	[%o3+%g1],%g5
+1:
+	ldx	[%o3+%o7],%g5
 	srl	%g5,0,%i0		! zero hi bits
+	ldx	[%o4+%o7],%l1
 	srlx	%g5,32,%g5
 	mulx	%o1,%i0,%i4		! lo product
 	mulx	%i3,%i0,%i1		! mid-1 product
@@ -63,25 +60,24 @@ ENTRY(__mpn_submul_1)
 	addcc	%i1,%l2,%i1		! add mid products
 	mov	0,%l0			! we need the carry from that add...
 	movcs	%xcc,%o2,%l0		! ...compute it and...
+	sllx	%i1,32,%i0		!  align low bits of mid product
 	add	%i5,%l0,%i5		! ...add to bit 32 of the hi product
-	sllx	%i1,32,%i0		! align low bits of mid product
 	srl	%i4,0,%g5		! zero high 32 bits of lo product
 	add	%i0,%g5,%i0		! combine into low 64 bits of result
 	srlx	%i1,32,%i1		! extract high bits of mid product...
+	addcc	%i0,%o0,%i0		!  add cy_limb to low 64 bits of result
 	add	%i5,%i1,%i1		! ...and add them to the high result
-	addcc	%i0,%o0,%i0		! add cy_limb to low 64 bits of result
 	mov	0,%g5
 	movcs	%xcc,1,%g5
-	add	%o7,1,%o7
-	ldx	[%o4+%g1],%l1
 	subcc	%l1,%i0,%i0
-	movcs	%xcc,1,%g5
-	stx	%i0,[%o4+%g1]
-	brnz	%o7,.Loop
+	stx	%i0,[%o4+%o7]
+	add	%g5,1,%l1
+	movcs	%xcc,%l1,%g5
+	addcc	%o7,8,%o7
+	bne,pt	%xcc,1b
 	 add	%i1,%g5,%o0		! compute new cy_limb
 
-	mov	%o0,%i0
-	jmpl	%i7+8,%g0
-	 restore
+	jmpl	%i7+8, %g0
+	 restore %o0,%g0,%o0
 
 END(__mpn_submul_1)
diff --git a/sysdeps/unix/sysv/linux/alpha/ioperm.c b/sysdeps/unix/sysv/linux/alpha/ioperm.c
index bd642e33c8..5b2edd0482 100644
--- a/sysdeps/unix/sysv/linux/alpha/ioperm.c
+++ b/sysdeps/unix/sysv/linux/alpha/ioperm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by David Mosberger.
 
@@ -86,11 +86,21 @@
 #define TSUNAMI_IO_BASE		(0x00000801fc000000UL + 0xfffffc0000000000UL)
 #define TSUNAMI_DENSE_MEM	(0x0000080000000000UL + 0xfffffc0000000000UL)
 
+/* Polaris has SPARSE space, but we prefer to use only DENSE */
+/* because of some idiosyncracies in actually using SPARSE */
+#define POLARIS_IO_BASE		(0xfffffcf9fc000000UL)
+#define POLARIS_DENSE_MEM	(0xfffffcf900000000UL)
+
 typedef enum {
   IOSYS_UNKNOWN, IOSYS_JENSEN, IOSYS_APECS, IOSYS_CIA, IOSYS_T2,
-  IOSYS_TSUNAMI, IOSYS_MCPCIA, IOSYS_GAMMA, IOSYS_CPUDEP
+  IOSYS_TSUNAMI, IOSYS_MCPCIA, IOSYS_GAMMA, IOSYS_POLARIS,
+  IOSYS_CPUDEP, IOSYS_PCIDEP
 } iosys_t;
 
+typedef enum {
+  IOSWIZZLE_JENSEN, IOSWIZZLE_SPARSE, IOSWIZZLE_DENSE
+} ioswizzle_t;
+
 static struct io_system {
   int		    hae_shift;
   unsigned long	int bus_memory_base;
@@ -105,7 +115,9 @@ static struct io_system {
 /* TSUNAMI */	{0, TSUNAMI_DENSE_MEM, 0, TSUNAMI_IO_BASE},
 /* MCPCIA */	{5, MCPCIA_DENSE_MEM, MCPCIA_SPARSE_MEM, MCPCIA_IO_BASE},
 /* GAMMA */	{5, GAMMA_DENSE_MEM, GAMMA_SPARSE_MEM, GAMMA_IO_BASE},
-/* CPUDEP */	{0, 0, 0, 0},
+/* POLARIS */	{0, POLARIS_DENSE_MEM, 0, POLARIS_IO_BASE},
+/* CPUDEP */	{0, 0, 0, 0}, /* for platforms dependent on CPU type */
+/* PCIDEP */	{0, 0, 0, 0}, /* for platforms dependent on core logic */
 };
 
 static struct platform {
@@ -116,7 +128,7 @@ static struct platform {
   {"Avanti",	IOSYS_APECS},
   {"XL",	IOSYS_APECS},
   {"Cabriolet",	IOSYS_APECS},
-  {"EB164",	IOSYS_CIA},
+  {"EB164",	IOSYS_PCIDEP},
   {"EB64+",	IOSYS_APECS},
   {"EB66",	IOSYS_APECS},
   {"EB66P",	IOSYS_APECS},
@@ -153,38 +165,27 @@ static struct {
   unsigned long int	sparse_bus_memory_base;
   unsigned long int	io_base;
   iosys_t		sys;
+  ioswizzle_t		swiz;
   int			hae_shift;
 } io;
 
 extern void __sethae (unsigned long int);	/* we can't use asm/io.h */
 
-
 static inline unsigned long int
-port_to_cpu_addr (unsigned long int port, iosys_t iosys, int size)
+port_to_cpu_addr (unsigned long int port, ioswizzle_t ioswiz, int size)
 {
-  if (iosys == IOSYS_JENSEN)
-    return (port << 7) + ((size - 1) << 5) + io.base;
-  else if (iosys == IOSYS_TSUNAMI)
+  if (ioswiz == IOSWIZZLE_SPARSE)
+    return (port << 5) + ((size - 1) << 3) + io.base;
+  else if (ioswiz == IOSWIZZLE_DENSE)
     return port + io.base;
   else
-    return (port << 5) + ((size - 1) << 3) + io.base;
+    return (port << 7) + ((size - 1) << 5) + io.base;
 }
 
-
 static inline void
-inline_sethae (unsigned long int addr, iosys_t iosys)
+inline_sethae (unsigned long int addr, ioswizzle_t ioswiz)
 {
-  if (iosys == IOSYS_JENSEN)
-    {
-      /* hae on the Jensen is bits 31:25 shifted right */
-      addr >>= 25;
-      if (addr != io.hae.cache)
-	{
-	  __sethae (addr);
-	  io.hae.cache = addr;
-	}
-    }
-  else
+  if (ioswiz == IOSWIZZLE_SPARSE)
     {
       unsigned long int msb;
 
@@ -196,16 +197,25 @@ inline_sethae (unsigned long int addr, iosys_t iosys)
 	  io.hae.cache = msb;
 	}
     }
+  else
+    {
+      /* hae on the Jensen is bits 31:25 shifted right */
+      addr >>= 25;
+      if (addr != io.hae.cache)
+	{
+	  __sethae (addr);
+	  io.hae.cache = addr;
+	}
+    }
 }
 
-
 static inline void
-inline_outb (unsigned char b, unsigned long int port, iosys_t iosys)
+inline_outb (unsigned char b, unsigned long int port, ioswizzle_t ioswiz)
 {
   unsigned int w;
-  unsigned long int addr = port_to_cpu_addr (port, iosys, 1);
+  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 1);
 
-  inline_sethae (0, iosys);
+  inline_sethae (0, ioswiz);
   asm ("insbl %2,%1,%0" : "=r" (w) : "ri" (port & 0x3), "r" (b));
   *(vuip)addr = w;
   mb ();
@@ -213,12 +223,12 @@ inline_outb (unsigned char b, unsigned long int port, iosys_t iosys)
 
 
 static inline void
-inline_outw (unsigned short int b, unsigned long int port, iosys_t iosys)
+inline_outw (unsigned short int b, unsigned long int port, ioswizzle_t ioswiz)
 {
   unsigned int w;
-  unsigned long int addr = port_to_cpu_addr (port, iosys, 2);
+  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 2);
 
-  inline_sethae (0, iosys);
+  inline_sethae (0, ioswiz);
   asm ("inswl %2,%1,%0" : "=r" (w) : "ri" (port & 0x3), "r" (b));
   *(vuip)addr = w;
   mb ();
@@ -226,22 +236,22 @@ inline_outw (unsigned short int b, unsigned long int port, iosys_t iosys)
 
 
 static inline void
-inline_outl (unsigned int b, unsigned long int port, iosys_t iosys)
+inline_outl (unsigned int b, unsigned long int port, ioswizzle_t ioswiz)
 {
-  unsigned long int addr = port_to_cpu_addr (port, iosys, 4);
+  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 4);
 
-  inline_sethae (0, iosys);
+  inline_sethae (0, ioswiz);
   *(vuip)addr = b;
   mb ();
 }
 
 
 static inline unsigned int
-inline_inb (unsigned long int port, iosys_t iosys)
+inline_inb (unsigned long int port, ioswizzle_t ioswiz)
 {
-  unsigned long int result, addr = port_to_cpu_addr (port, iosys, 1);
+  unsigned long int result, addr = port_to_cpu_addr (port, ioswiz, 1);
 
-  inline_sethae (0, iosys);
+  inline_sethae (0, ioswiz);
   result = *(vuip) addr;
   result >>= (port & 3) * 8;
   return 0xffUL & result;
@@ -249,11 +259,11 @@ inline_inb (unsigned long int port, iosys_t iosys)
 
 
 static inline unsigned int
-inline_inw (unsigned long int port, iosys_t iosys)
+inline_inw (unsigned long int port, ioswizzle_t ioswiz)
 {
-  unsigned long int result, addr = port_to_cpu_addr (port, iosys, 2);
+  unsigned long int result, addr = port_to_cpu_addr (port, ioswiz, 2);
 
-  inline_sethae (0, iosys);
+  inline_sethae (0, ioswiz);
   result = *(vuip) addr;
   result >>= (port & 3) * 8;
   return 0xffffUL & result;
@@ -261,11 +271,11 @@ inline_inw (unsigned long int port, iosys_t iosys)
 
 
 static inline unsigned int
-inline_inl (unsigned long int port, iosys_t iosys)
+inline_inl (unsigned long int port, ioswizzle_t ioswiz)
 {
-  unsigned long int addr = port_to_cpu_addr (port, iosys, 4);
+  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 4);
 
-  inline_sethae (0, iosys);
+  inline_sethae (0, ioswiz);
   return *(vuip) addr;
 }
 
@@ -274,115 +284,115 @@ inline_inl (unsigned long int port, iosys_t iosys)
  * and whose core logic supports I/O space accesses utilizing them.
  *
  * These routines could be used by MIATA, for example, because it has
- * and EV56 plus PYXIS, but it currently uses SPARSE anyway.
+ * and EV56 plus PYXIS, but it currently uses SPARSE anyway. This is
+ * also true of RX164 which used POLARIS, but we will choose to use
+ * these routines in that case instead of SPARSE.
  *
  * These routines are necessary for TSUNAMI/TYPHOON based platforms,
  * which will have (at least) EV6.
  */
 
+static inline unsigned long int
+dense_port_to_cpu_addr (unsigned long int port)
+{
+  return port + io.base;
+}
+
 static inline void
-inline_bwx_outb (unsigned char b, unsigned long int port, iosys_t iosys)
+inline_bwx_outb (unsigned char b, unsigned long int port)
 {
-  unsigned long int addr = port_to_cpu_addr (port, iosys, 4);
+  unsigned long int addr = dense_port_to_cpu_addr (port);
 
   __asm__ __volatile__ ("stb %1,%0" : : "m"(*(unsigned char *)addr), "r"(b));
   mb ();
 }
 
-
 static inline void
-inline_bwx_outw (unsigned short int b, unsigned long int port, iosys_t iosys)
+inline_bwx_outw (unsigned short int b, unsigned long int port)
 {
-  unsigned long int addr = port_to_cpu_addr (port, iosys, 4);
+  unsigned long int addr = dense_port_to_cpu_addr (port);
 
   __asm__ __volatile__ ("stw %1,%0" : : "m"(*(unsigned short *)addr), "r"(b));
   mb ();
 }
 
-
 static inline void
-inline_bwx_outl (unsigned int b, unsigned long int port, iosys_t iosys)
+inline_bwx_outl (unsigned int b, unsigned long int port)
 {
-  unsigned long int addr = port_to_cpu_addr (port, iosys, 4);
+  unsigned long int addr = dense_port_to_cpu_addr (port);
 
   *(vuip)addr = b;
   mb ();
 }
 
-
 static inline unsigned int
-inline_bwx_inb (unsigned long int port, iosys_t iosys)
+inline_bwx_inb (unsigned long int port)
 {
-  unsigned long int r, addr = port_to_cpu_addr (port, iosys, 1);
+  unsigned long int r, addr = dense_port_to_cpu_addr (port);
 
   __asm__ __volatile__ ("ldbu %0,%1" : "=r"(r) : "m"(*(unsigned char *)addr));
   return 0xffUL & r;
 }
 
-
 static inline unsigned int
-inline_bwx_inw (unsigned long int port, iosys_t iosys)
+inline_bwx_inw (unsigned long int port)
 {
-  unsigned long int r, addr = port_to_cpu_addr (port, iosys, 1);
+  unsigned long int r, addr = dense_port_to_cpu_addr (port);
 
   __asm__ __volatile__ ("ldwu %0,%1" : "=r"(r) : "m"(*(unsigned short *)addr));
   return 0xffffUL & r;
 }
 
-
 static inline unsigned int
-inline_bwx_inl (unsigned long int port, iosys_t iosys)
+inline_bwx_inl (unsigned long int port)
 {
-  unsigned long int addr = port_to_cpu_addr (port, iosys, 4);
+  unsigned long int addr = dense_port_to_cpu_addr (port);
 
   return *(vuip) addr;
 }
 
+/* macros to define routines with appropriate names and functions */
 
-#define DCL_SETHAE(name, iosys)				\
-static void						\
-name##_sethae (unsigned long int addr)			\
-{							\
-  inline_sethae (addr, IOSYS_##iosys);			\
+/* these do either SPARSE or JENSEN swizzle */
+
+#define DCL_SETHAE(name, ioswiz)                        \
+static void                                             \
+name##_sethae (unsigned long int addr)                  \
+{                                                       \
+  inline_sethae (addr, IOSWIZZLE_##ioswiz);             \
 }
 
-#define DCL_OUT(name, func, type, iosys)		\
+#define DCL_OUT(name, func, type, ioswiz)		\
 static void						\
 name##_##func (unsigned type b, unsigned long int addr)	\
 {							\
-  inline_##func (b, addr, IOSYS_##iosys);		\
+  inline_##func (b, addr, IOSWIZZLE_##ioswiz);		\
 }
 
-
-#define DCL_IN(name, func, iosys)			\
+#define DCL_IN(name, func, ioswiz)			\
 static unsigned int					\
 name##_##func (unsigned long int addr)			\
 {							\
-  return inline_##func (addr, IOSYS_##iosys);		\
+  return inline_##func (addr, IOSWIZZLE_##ioswiz);	\
 }
 
-#define DCL_SETHAE_IGNORE(name, iosys)			\
-static void						\
-name##_sethae (unsigned long int addr)			\
-{							\
-/* do nothing */					\
-}
+/* these do DENSE, so no swizzle is needed */
 
-#define DCL_OUT_BWX(name, func, type, iosys)		\
+#define DCL_OUT_BWX(name, func, type)			\
 static void						\
 name##_##func (unsigned type b, unsigned long int addr)	\
 {							\
-  inline_bwx_##func (b, addr, IOSYS_##iosys);		\
+  inline_bwx_##func (b, addr);				\
 }
 
-
-#define DCL_IN_BWX(name, func, iosys)			\
+#define DCL_IN_BWX(name, func)				\
 static unsigned int					\
 name##_##func (unsigned long int addr)			\
 {							\
-  return inline_bwx_##func (addr, IOSYS_##iosys);	\
+  return inline_bwx_##func (addr);			\
 }
 
+/* now declare/define the necessary routines */
 
 DCL_SETHAE(jensen, JENSEN)
 DCL_OUT(jensen, outb, char,  JENSEN)
@@ -392,25 +402,22 @@ DCL_IN(jensen, inb, JENSEN)
 DCL_IN(jensen, inw, JENSEN)
 DCL_IN(jensen, inl, JENSEN)
 
-/* The APECS functions are also used for CIA since they are
-   identical.  */
-
-DCL_SETHAE(apecs, APECS)
-DCL_OUT(apecs, outb, char,  APECS)
-DCL_OUT(apecs, outw, short int, APECS)
-DCL_OUT(apecs, outl, int,   APECS)
-DCL_IN(apecs, inb, APECS)
-DCL_IN(apecs, inw, APECS)
-DCL_IN(apecs, inl, APECS)
-
-DCL_SETHAE_IGNORE(tsunami, TSUNAMI)
-DCL_OUT_BWX(tsunami, outb, char,  TSUNAMI)
-DCL_OUT_BWX(tsunami, outw, short int, TSUNAMI)
-DCL_OUT_BWX(tsunami, outl, int,   TSUNAMI)
-DCL_IN_BWX(tsunami, inb, TSUNAMI)
-DCL_IN_BWX(tsunami, inw, TSUNAMI)
-DCL_IN_BWX(tsunami, inl, TSUNAMI)
-
+DCL_SETHAE(sparse, SPARSE)
+DCL_OUT(sparse, outb, char,  SPARSE)
+DCL_OUT(sparse, outw, short int, SPARSE)
+DCL_OUT(sparse, outl, int,   SPARSE)
+DCL_IN(sparse, inb, SPARSE)
+DCL_IN(sparse, inw, SPARSE)
+DCL_IN(sparse, inl, SPARSE)
+
+DCL_OUT_BWX(dense, outb, char)
+DCL_OUT_BWX(dense, outw, short int)
+DCL_OUT_BWX(dense, outl, int)
+DCL_IN_BWX(dense, inb)
+DCL_IN_BWX(dense, inw)
+DCL_IN_BWX(dense, inl)
+
+/* define the "swizzle" switch */
 static struct ioswtch ioswtch[] = {
   {
     jensen_sethae,
@@ -418,18 +425,63 @@ static struct ioswtch ioswtch[] = {
     jensen_inb, jensen_inw, jensen_inl
   },
   {
-    apecs_sethae,
-    apecs_outb, apecs_outw, apecs_outl,
-    apecs_inb, apecs_inw, apecs_inl
+    sparse_sethae,
+    sparse_outb, sparse_outw, sparse_outl,
+    sparse_inb, sparse_inw, sparse_inl
   },
   {
-    tsunami_sethae,
-    tsunami_outb, tsunami_outw, tsunami_outl,
-    tsunami_inb, tsunami_inw, tsunami_inl
+    NULL,
+    dense_outb, dense_outw, dense_outl,
+    dense_inb, dense_inw, dense_inl
   }
 };
 
+/* routine to process the /proc/cpuinfo information into the fields */
+/* that are required for correctly determining the platform parameters */
+
+char systype[256]; /* system type field */
+char sysvari[256]; /* system variation field */
+char cpumodel[256]; /* cpu model field */
+int got_type, got_vari, got_model;
+
+static int
+process_cpuinfo(void)
+{
+  char dummy[256];
+  FILE * fp;
 
+  fp = fopen (PATH_CPUINFO, "r");
+  if (!fp)
+    return 0;
+
+  got_type = got_vari = got_model = 0;
+  systype[0] = sysvari[0] = cpumodel[0] = 0;
+
+  while (1)
+    {
+      if (fgets (dummy, 256, fp) == NULL) break;
+      /*	  fprintf(stderr, "read: %s", dummy); */
+      if (!got_type &&
+	  sscanf (dummy, "system type : %256[^\n]\n", systype) == 1)
+	got_type = 1;
+      if (!got_vari &&
+	  sscanf (dummy, "system variation : %256[^\n]\n", sysvari) == 1)
+	got_vari = 1;
+      if (!got_model &&
+	  sscanf (dummy, "cpu model : %256[^\n]\n", cpumodel) == 1)
+	got_model = 1;
+    }
+
+  fclose (fp);
+
+#if 1
+  fprintf(stderr, "system type: %s\n", systype);
+  fprintf(stderr, "system vari: %s\n", sysvari);
+  fprintf(stderr, "cpu model: %s\n", cpumodel);
+#endif
+
+  return got_type+got_vari+got_model;
+}
 /*
  * Initialize I/O system.  To determine what I/O system we're dealing
  * with, we first try to read the value of symlink PATH_ALPHA_SYSTYPE,
@@ -443,7 +495,6 @@ static struct ioswtch ioswtch[] = {
 static int
 init_iosys (void)
 {
-  char systype[256];
   int i, n;
 
   n = readlink (PATH_ALPHA_SYSTYPE, systype, sizeof (systype) - 1);
@@ -456,7 +507,8 @@ init_iosys (void)
 		      &io.bus_memory_base, &io.sparse_bus_memory_base) == 4)
 	    {
 	      io.sys = IOSYS_UNKNOWN;
-	      io.swp = &ioswtch[1];
+	      io.swiz = IOSWIZZLE_SPARSE;
+	      io.swp = &ioswtch[IOSWIZZLE_SPARSE];
 	      return 0;
 	    }
 	  /* else we're likely going to fail with the system match below */
@@ -464,22 +516,9 @@ init_iosys (void)
     }
   else
     {
-      FILE * fp;
+      n = process_cpuinfo();
 
-      fp = fopen (PATH_CPUINFO, "r");
-      if (!fp)
-	return -1;
-      while ((n = fscanf (fp, "system type : %256[^\n]\n", systype))
-	     != EOF)
-	{
-	  if (n == 1)
-	    break;
-	  else
-	    fgets (systype, 256, fp);
-	}
-      fclose (fp);
-
-      if (n == EOF)
+      if (!n)
 	{
 	  /* this can happen if the format of /proc/cpuinfo changes...  */
 	  fprintf (stderr,
@@ -497,35 +536,23 @@ init_iosys (void)
 	{
 	  io.sys = platform[i].io_sys;
 	  /* some platforms can have either EV4 or EV5 CPUs */
-	  if (io.sys == IOSYS_CPUDEP)
+	  if (io.sys == IOSYS_CPUDEP) /* SABLE or MIKASA or NORITAKE so far */
 	    {
-	      FILE * fp;
-	      char cputype[256];
-	      fp = fopen (PATH_CPUINFO, "r");
-	      if (fp == NULL)
-		return -1;
-	      while ((n = fscanf (fp, "cpu model : %256[^\n]\n", cputype))
-		     != EOF
-		     && n != 1)
-		fgets (cputype, 256, fp);
-
-	      fclose (fp);
-
 	      if (strcmp (platform[i].name, "Sable") == 0)
 		{
-		  if (strncmp (cputype, "EV4", 3) == 0)
+		  if (strncmp (cpumodel, "EV4", 3) == 0)
 		    io.sys = IOSYS_T2;
-		  else if (strncmp (cputype, "EV5", 3) == 0)
+		  else if (strncmp (cpumodel, "EV5", 3) == 0)
 		    io.sys = IOSYS_GAMMA;
 		}
 	      else
-		{
-		  if (strncmp (cputype, "EV4", 3) == 0)
+		{ /* this covers MIKASA/NORITAKE */
+		  if (strncmp (cpumodel, "EV4", 3) == 0)
 		    io.sys = IOSYS_APECS;
-		  else if (strncmp (cputype, "EV5", 3) == 0)
+		  else if (strncmp (cpumodel, "EV5", 3) == 0)
 		    io.sys = IOSYS_CIA;
 		}
-	      if (n == EOF || io.sys == IOSYS_CPUDEP)
+	      if (io.sys == IOSYS_CPUDEP)
 		{
 		  /* This can happen if the format of /proc/cpuinfo changes.*/
 		  fprintf (stderr, "ioperm.init_iosys(): Unable to determine"
@@ -534,23 +561,46 @@ init_iosys (void)
 		  return -1;
 		}
 	    }
+	  /* some platforms can have different core logic chipsets */
+	  if (io.sys == IOSYS_PCIDEP) /* EB164 so far */
+	    {
+	      if (strcmp (systype, "EB164") == 0)
+		{
+		  if (strncmp (sysvari, "RX164", 5) == 0)
+		    io.sys = IOSYS_POLARIS;
+		  else
+		    io.sys = IOSYS_CIA;
+		}
+	      if (io.sys == IOSYS_PCIDEP)
+		{
+		  /* This can happen if the format of /proc/cpuinfo changes.*/
+		  fprintf (stderr, "ioperm.init_iosys(): Unable to determine"
+			   " core logic chipset.\n");
+		  __set_errno (ENODEV);
+		  return -1;
+		}
+	    }
 	  io.hae_shift = io_system[io.sys].hae_shift;
 	  io.bus_memory_base = io_system[io.sys].bus_memory_base;
 	  io.sparse_bus_memory_base = io_system[io.sys].sparse_bus_mem_base;
 	  io.io_base = io_system[io.sys].bus_io_base;
 
 	  if (io.sys == IOSYS_JENSEN)
-	    io.swp = &ioswtch[0];
-	  else if (io.sys == IOSYS_TSUNAMI)
-	    io.swp = &ioswtch[2];
+	    io.swiz = IOSWIZZLE_JENSEN;
+	  else if (io.sys == IOSYS_TSUNAMI || io.sys == IOSYS_POLARIS)
+	    io.swiz = IOSWIZZLE_DENSE;
 	  else
-	    io.swp = &ioswtch[1];
+	    io.swiz = IOSWIZZLE_SPARSE;
+	  io.swp = &ioswtch[io.swiz];
 	  return 0;
 	}
     }
 
   /* systype is not a know platform name... */
   __set_errno (EINVAL);
+#if 1
+  fprintf(stderr, "init_iosys: platform not recognized\n");
+#endif
   return -1;
 }
 
@@ -559,18 +609,29 @@ int
 _ioperm (unsigned long int from, unsigned long int num, int turn_on)
 {
   unsigned long int addr, len;
-  int prot;
+  int prot, err;
 
-  if (!io.swp && init_iosys () < 0)
+  if (!io.swp && init_iosys() < 0) {
+#if 1
+	    fprintf(stderr, "ioperm: init_iosys() failed\n");
+#endif
     return -1;
+  }
 
   /* this test isn't as silly as it may look like; consider overflows! */
   if (from >= MAX_PORT || from + num > MAX_PORT)
     {
       __set_errno (EINVAL);
+#if 1
+      fprintf(stderr, "ioperm: from/num out of range\n");
+#endif
       return -1;
     }
 
+#if 1
+      fprintf(stderr, "ioperm: turn_on %d io.base %ld\n", turn_on, io.base);
+#endif
+
   if (turn_on)
     {
       if (!io.base)
@@ -579,19 +640,27 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on)
 
 	  io.hae.reg   = 0;		/* not used in user-level */
 	  io.hae.cache = 0;
-	  if (io.sys != IOSYS_TSUNAMI)
+	  if (io.swiz != IOSWIZZLE_DENSE)
 	    __sethae (io.hae.cache);	/* synchronize with hw */
 
 	  fd = open ("/dev/mem", O_RDWR);
-	  if (fd < 0)
+	  if (fd < 0) {
+#if 1
+	    fprintf(stderr, "ioperm: /dev/mem open failed\n");
+#endif
 	    return -1;
+	  }
 
-	  addr = port_to_cpu_addr (0, io.sys, 1);
-	  len = port_to_cpu_addr (MAX_PORT, io.sys, 1) - addr;
+	  addr = port_to_cpu_addr (0, io.swiz, 1);
+	  len = port_to_cpu_addr (MAX_PORT, io.swiz, 1) - addr;
 	  io.base =
 	    (unsigned long int) __mmap (0, len, PROT_NONE, MAP_SHARED,
 					fd, io.io_base);
 	  close (fd);
+#if 1
+	  fprintf(stderr, "ioperm: mmap of len 0x%lx  returned 0x%lx\n",
+		  len, io.base);
+#endif
 	  if ((long) io.base == -1)
 	    return -1;
 	}
@@ -605,10 +674,14 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on)
       /* turnoff access to relevant pages: */
       prot = PROT_NONE;
     }
-  addr  = port_to_cpu_addr (from, io.sys, 1);
+  addr = port_to_cpu_addr (from, io.swiz, 1);
   addr &= PAGE_MASK;
-  len = port_to_cpu_addr (from + num, io.sys, 1) - addr;
-  return mprotect ((void *) addr, len, prot);
+  len = port_to_cpu_addr (from + num, io.swiz, 1) - addr;
+  err = mprotect ((void *) addr, len, prot);
+#if 1
+  fprintf(stderr, "ioperm: mprotect returned %d\n", err);
+#endif
+  return err;
 }
 
 
diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h
index 0a93a42f35..056087b2f7 100644
--- a/sysdeps/unix/sysv/linux/bits/socket.h
+++ b/sysdeps/unix/sysv/linux/bits/socket.h
@@ -255,7 +255,7 @@ __cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg) __THROW
 {
   if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
     /* The kernel header does this so there may be a reason.  */
-    return NULL;
+    return 0;
 
   __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
 			       + CMSG_ALIGN (__cmsg->cmsg_len));
@@ -264,7 +264,7 @@ __cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg) __THROW
       || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
 	  >= ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
     /* No more entries.  */
-    return NULL;
+    return 0;
   return __cmsg;
 }
 #endif	/* Use `extern inline'.  */
diff --git a/sysdeps/unix/sysv/linux/configure.in b/sysdeps/unix/sysv/linux/configure.in
index 3f3d02131a..d7b2bd97c4 100644
--- a/sysdeps/unix/sysv/linux/configure.in
+++ b/sysdeps/unix/sysv/linux/configure.in
@@ -123,9 +123,12 @@ fi
 # We need some extensions to the `ldd' script.
 changequote(,)
 case "$machine" in
-  i[3456]86* | m68* | sparc/sparc32)
+  i[3456]86* | m68*)
     ldd_rewrite_script=../sysdeps/unix/sysv/linux/ldd-rewrite.sed
     ;;
+  sparc/sparc32)
+    ldd_rewrite_script=../sysdeps/unix/sysv/linux/sparc/ldd-rewrite.sed
+    ;;
   *)
     ;;
 esac
diff --git a/sysdeps/unix/sysv/linux/sparc/ldd-rewrite.sed b/sysdeps/unix/sysv/linux/sparc/ldd-rewrite.sed
new file mode 100644
index 0000000000..f0a192c7e0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/ldd-rewrite.sed
@@ -0,0 +1,2 @@
+/LD_TRACE_LOADED_OBJECTS=1/a\
+add_env="$add_env LD_LIBRARY_VERSION=\\$verify_out"