about summary refs log tree commit diff
path: root/sysdeps/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/sparc')
-rw-r--r--sysdeps/sparc/Dist1
-rw-r--r--sysdeps/sparc/Makefile3
-rw-r--r--sysdeps/sparc/bits/link.h100
-rw-r--r--sysdeps/sparc/bits/mathdef.h (renamed from sysdeps/sparc/fpu/bits/mathdef.h)14
-rw-r--r--sysdeps/sparc/dl-procinfo.c62
-rw-r--r--sysdeps/sparc/dl-procinfo.h79
-rw-r--r--sysdeps/sparc/dl-sysdep.h21
-rw-r--r--sysdeps/sparc/fpu/bits/mathinline.h81
-rw-r--r--sysdeps/sparc/fpu/feholdexcpt.c3
-rw-r--r--sysdeps/sparc/fpu/fesetround.c3
-rw-r--r--sysdeps/sparc/fpu/fraiseexcpt.c34
-rw-r--r--sysdeps/sparc/sparc32/Dist9
-rw-r--r--sysdeps/sparc/sparc32/Implies3
-rw-r--r--sysdeps/sparc/sparc32/__longjmp.S24
-rw-r--r--sysdeps/sparc/sparc32/bits/atomic.h260
-rw-r--r--sysdeps/sparc/sparc32/bits/setjmp.h13
-rw-r--r--sysdeps/sparc/sparc32/dl-machine.h343
-rw-r--r--sysdeps/sparc/sparc32/dl-trampoline.S184
-rw-r--r--sysdeps/sparc/sparc32/elf/start.S10
-rw-r--r--sysdeps/sparc/sparc32/fpu/e_sqrtl.c1
-rw-r--r--sysdeps/sparc/sparc32/fpu/libm-test-ulps433
-rw-r--r--sysdeps/sparc/sparc32/fpu/s_fabs.c11
-rw-r--r--sysdeps/sparc/sparc32/fpu/s_fabsf.S29
-rw-r--r--sysdeps/sparc/sparc32/fpu/s_fabsl.c8
-rw-r--r--sysdeps/sparc/sparc32/jmpbuf-offsets.h22
-rw-r--r--sysdeps/sparc/sparc32/jmpbuf-unwind.h48
-rw-r--r--sysdeps/sparc/sparc32/memchr.S21
-rw-r--r--sysdeps/sparc/sparc32/memcpy.S40
-rw-r--r--sysdeps/sparc/sparc32/memset.S2
-rw-r--r--sysdeps/sparc/sparc32/setjmp.S16
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/Dist28
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/Makefile20
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/Versions8
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_add.c8
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_div.c4
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_dtoq.c10
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_itoq.c6
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_lltoq.c (renamed from sysdeps/sparc/sparc32/soft-fp/q_xtoq.c)8
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_qtod.c10
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_qtoi.c6
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_qtoll.c (renamed from sysdeps/sparc/sparc32/soft-fp/q_qtox.c)10
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_qtos.c10
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_qtou.c (renamed from sysdeps/sparc/sparc32/soft-fp/q_qtoui.c)6
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_qtoull.c (renamed from sysdeps/sparc/sparc32/soft-fp/q_qtoux.c)8
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_sqrt.c3
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_stoq.c10
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_sub.c8
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_ulltoq.c (renamed from sysdeps/sparc/sparc32/soft-fp/q_uxtoq.c)8
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/q_utoq.c (renamed from sysdeps/sparc/sparc32/soft-fp/q_uitoq.c)8
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/sfp-machine.h14
-rw-r--r--sysdeps/sparc/sparc32/sparcv8/Dist6
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/Dist7
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/bits/atomic.h12
-rw-r--r--sysdeps/sparc/sparc32/sparcv9b/Implies1
-rw-r--r--sysdeps/sparc/sparc32/sparcv9v/memcpy.S2
-rw-r--r--sysdeps/sparc/sparc32/sparcv9v/memset.S2
-rw-r--r--sysdeps/sparc/sparc32/stpcpy.S16
-rw-r--r--sysdeps/sparc/sparc32/strcat.S78
-rw-r--r--sysdeps/sparc/sparc32/strchr.S37
-rw-r--r--sysdeps/sparc/sparc32/strcmp.S14
-rw-r--r--sysdeps/sparc/sparc32/strcpy.S16
-rw-r--r--sysdeps/sparc/sparc32/strlen.S28
-rw-r--r--sysdeps/sparc/sparc64/Dist1
-rw-r--r--sysdeps/sparc/sparc64/Makefile3
-rw-r--r--sysdeps/sparc/sparc64/Versions7
-rw-r--r--sysdeps/sparc/sparc64/bits/atomic.h14
-rw-r--r--sysdeps/sparc/sparc64/dl-machine.h683
-rw-r--r--sysdeps/sparc/sparc64/dl-trampoline.S327
-rw-r--r--sysdeps/sparc/sparc64/elf/start.S10
-rw-r--r--sysdeps/sparc/sparc64/fpu/libm-test-ulps13
-rw-r--r--sysdeps/sparc/sparc64/jmpbuf-unwind.h37
-rw-r--r--sysdeps/sparc/sparc64/memcmp.S2
-rw-r--r--sysdeps/sparc/sparc64/memcpy.S8
-rw-r--r--sysdeps/sparc/sparc64/memset.S2
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/Dist32
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_add.c8
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_dtoq.c10
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_itoq.c6
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_qtod.c10
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_qtoi.c6
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_qtos.c10
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_qtoui.c4
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_qtoux.c4
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_qtox.c6
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_stoq.c10
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_sub.c8
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_uitoq.c6
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_uxtoq.c6
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/qp_xtoq.c6
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/sfp-machine.h3
-rw-r--r--sysdeps/sparc/sparc64/sparcv9b/memcpy.S10
-rw-r--r--sysdeps/sparc/sparc64/sparcv9v/memcpy.S593
-rw-r--r--sysdeps/sparc/sparc64/sparcv9v/memset.S127
93 files changed, 3285 insertions, 977 deletions
diff --git a/sysdeps/sparc/Dist b/sysdeps/sparc/Dist
deleted file mode 100644
index 7832507772..0000000000
--- a/sysdeps/sparc/Dist
+++ /dev/null
@@ -1 +0,0 @@
-sys/trap.h
diff --git a/sysdeps/sparc/Makefile b/sysdeps/sparc/Makefile
index e55e461423..40323a0643 100644
--- a/sysdeps/sparc/Makefile
+++ b/sysdeps/sparc/Makefile
@@ -1,3 +1,6 @@
+# The Sparc `long double' is a distinct type we support.
+long-double-fcts = yes
+
 ifeq ($(subdir),db2)
 CPPFLAGS += -DHAVE_SPINLOCKS=1 -DHAVE_ASSEM_SPARC_GCC=1
 endif
diff --git a/sysdeps/sparc/bits/link.h b/sysdeps/sparc/bits/link.h
new file mode 100644
index 0000000000..9b8434f56f
--- /dev/null
+++ b/sysdeps/sparc/bits/link.h
@@ -0,0 +1,100 @@
+/* Machine-specific audit interfaces for dynamic linker.  SPARC version.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+#if __WORDSIZE == 32
+
+typedef struct La_sparc32_regs
+{
+  uint32_t lr_lreg[8];  /* %l0 through %l7 */
+  uint32_t lr_reg[6];   /* %o0 through %o5 */
+  uint32_t lr_sp;       /* %o6 */
+  uint32_t lr_ra;       /* %o7 */
+  uint32_t lr_struct;   /* Pass-by-reference struct pointer */
+} La_sparc32_regs;
+
+typedef struct La_sparc32_retval
+{
+  uint32_t lrv_reg[2]; /* %o0 and %o1 */
+  double lrv_fpreg[2]; /* %f0 and %f2 */
+} La_sparc32_retval;
+
+#else
+
+typedef struct La_sparc64_regs
+{
+  uint64_t lr_lreg[8];  /* %l0 through %l7 */
+  uint64_t lr_reg[6];	/* %o0 through %o5 */
+  uint64_t lr_sp;	/* %o6 */
+  uint64_t lr_ra;	/* %o7 */
+  double lr_fpreg[16];	/* %f0 through %f30 */
+} La_sparc64_regs;
+
+typedef struct La_sparc64_retval
+{
+  uint64_t lrv_reg[4]; /* %o0 through %o3 */
+  double lrv_fprev[4]; /* %f0 through %f8 */
+} La_sparc64_retval;
+
+#endif
+
+__BEGIN_DECLS
+
+#if __WORDSIZE == 32
+
+extern Elf32_Addr la_sparc32_gnu_pltenter (Elf32_Sym *__sym,
+					   unsigned int __ndx,
+					   uintptr_t *__refcook,
+					   uintptr_t *__defcook,
+					   La_sparc32_regs *__regs,
+					   unsigned int *__flags,
+					   const char *__symname,
+					   long int *__framesizep);
+extern unsigned int la_sparc32_gnu_pltexit (Elf32_Sym *__sym,
+					    unsigned int __ndx,
+					    uintptr_t *__refcook,
+					    uintptr_t *__defcook,
+					     const La_sparc32_regs *__inregs,
+					    La_sparc32_retval *__outregs,
+					    const char *symname);
+
+#else
+
+extern Elf64_Addr la_sparc64_gnu_pltenter (Elf64_Sym *__sym,
+					   unsigned int __ndx,
+					   uintptr_t *__refcook,
+					   uintptr_t *__defcook,
+					   La_sparc64_regs *__regs,
+					   unsigned int *__flags,
+					   const char *__symname,
+					   long int *__framesizep);
+extern unsigned int la_sparc64_gnu_pltexit (Elf64_Sym *__sym,
+					    unsigned int __ndx,
+					    uintptr_t *__refcook,
+					    uintptr_t *__defcook,
+					    const La_sparc64_regs *__inregs,
+					    La_sparc64_retval *__outregs,
+					    const char *symname);
+
+#endif
+
+__END_DECLS
diff --git a/sysdeps/sparc/fpu/bits/mathdef.h b/sysdeps/sparc/bits/mathdef.h
index e76735b55b..c8dcc9c93f 100644
--- a/sysdeps/sparc/fpu/bits/mathdef.h
+++ b/sysdeps/sparc/bits/mathdef.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000, 2004, 2006
+   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
@@ -55,14 +56,3 @@ typedef double double_t;
 # define FP_ILOGBNAN     (2147483647)
 
 #endif	/* ISO C99 */
-
-#ifndef __NO_LONG_DOUBLE_MATH
-
-# if __WORDSIZE == 32
-/* Signal that in 32bit ABI we do not really have a `long double'.
-   The disables the declaration of all the `long double' function
-   variants.  */
-#  define __NO_LONG_DOUBLE_MATH	1
-# endif
-
-#endif
diff --git a/sysdeps/sparc/dl-procinfo.c b/sysdeps/sparc/dl-procinfo.c
new file mode 100644
index 0000000000..875820fab3
--- /dev/null
+++ b/sysdeps/sparc/dl-procinfo.c
@@ -0,0 +1,62 @@
+/* Data for Linux/sparc version of processor capability information.
+   Copyright (C) 2002,2003,2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This information must be kept in sync with the _DL_HWCAP_COUNT
+   definition in procinfo.h.
+
+   If anything should be added here check whether the size of each string
+   is still ok with the given array size.
+
+   All the #ifdefs in the definitions ar equite irritating but
+   necessary if we want to avoid duplicating the information.  There
+   are three different modes:
+
+   - PROCINFO_DECL is defined.  This means we are only interested in
+     declarations.
+
+   - PROCINFO_DECL is not defined:
+
+     + if SHARED is defined the file is included in an array
+       initializer.  The .element = { ... } syntax is needed.
+
+     + if SHARED is not defined a normal array initialization is
+       needed.
+  */
+
+#ifndef PROCINFO_CLASS
+#define PROCINFO_CLASS
+#endif
+
+#if !defined PROCINFO_DECL && defined SHARED
+  ._dl_sparc_cap_flags
+#else
+PROCINFO_CLASS const char _dl_sparc_cap_flags[7][7]
+#endif
+#ifndef PROCINFO_DECL
+  = { "flush", "stbar", "swap", "muldiv", "v9", "ultra3", "v9v" }
+#endif
+#if !defined SHARED || defined PROCINFO_DECL
+;
+#else
+,
+#endif
+
+#undef PROCINFO_DECL
+#undef PROCINFO_CLASS
diff --git a/sysdeps/sparc/dl-procinfo.h b/sysdeps/sparc/dl-procinfo.h
new file mode 100644
index 0000000000..dde02b556c
--- /dev/null
+++ b/sysdeps/sparc/dl-procinfo.h
@@ -0,0 +1,79 @@
+/* Linux/sparc version of processor capability information handling macros.
+   Copyright (C) 1999,2000,2001,2002,2003,2004,2006
+	Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jj@ultra.linux.cz>, 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _DL_PROCINFO_H
+#define _DL_PROCINFO_H	1
+
+#include <ldsodefs.h>
+
+#define _DL_HWCAP_COUNT 7
+
+static inline int
+__attribute__ ((unused))
+_dl_procinfo (int word)
+{
+  int i;
+
+  _dl_printf ("AT_HWCAP:   ");
+
+  for (i = 0; i < _DL_HWCAP_COUNT; ++i)
+    if (word & (1 << i))
+      _dl_printf (" %s", GLRO(dl_sparc_cap_flags)[i]);
+
+  _dl_printf ("\n");
+
+  return 0;
+}
+
+static inline const char *
+__attribute__ ((unused))
+_dl_hwcap_string (int idx)
+{
+  return GLRO(dl_sparc_cap_flags)[idx];
+};
+
+static inline int
+__attribute__ ((unused, always_inline))
+_dl_string_hwcap (const char *str)
+{
+  int i;
+  for (i = 0; i < _DL_HWCAP_COUNT; i++)
+    {
+      if (strcmp (str, GLRO(dl_sparc_cap_flags) [i]) == 0)
+	return i;
+    }
+  return -1;
+};
+
+#include <bits/wordsize.h>
+#define HWCAP_IMPORTANT_V9	(__WORDSIZE == 64 ? 0 : HWCAP_SPARC_V9)
+#define HWCAP_IMPORTANT		(HWCAP_IMPORTANT_V9 | HWCAP_SPARC_ULTRA3 \
+				 | HWCAP_SPARC_BLKINIT)
+
+/* There are no different platforms defined.  */
+#define _dl_platform_string(idx) ""
+
+/* There're no platforms to filter out.  */
+#define _DL_HWCAP_PLATFORM 0
+
+#define _dl_string_platform(str) (-1)
+
+#endif /* dl-procinfo.h */
diff --git a/sysdeps/sparc/dl-sysdep.h b/sysdeps/sparc/dl-sysdep.h
index eb6a788a89..2dee6b1f50 100644
--- a/sysdeps/sparc/dl-sysdep.h
+++ b/sysdeps/sparc/dl-sysdep.h
@@ -1,5 +1,5 @@
 /* System-specific settings for dynamic linker code.  SPARC version.
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 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,25 +17,8 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#ifndef _DL_SYSDEP_H
-#define _DL_SYSDEP_H   1
-
-/* This macro must be defined to either 0 or 1.
-
-   If 1, then an errno global variable hidden in ld.so will work right with
-   all the errno-using libc code compiled for ld.so, and there is never a
-   need to share the errno location with libc.  This is appropriate only if
-   all the libc functions that ld.so uses are called without PLT and always
-   get the versions linked into ld.so rather than the libc ones.  */
-
-#ifdef IS_IN_rtld
-# define RTLD_PRIVATE_ERRNO 1
-#else
-# define RTLD_PRIVATE_ERRNO 0
-#endif
+#include_next <dl-sysdep.h>
 
 /* _dl_argv cannot be attribute_relro, because _dl_start_user
    might write into it after _dl_start returns.  */
 #define DL_ARGV_NOT_RELRO 1
-
-#endif /* dl-sysdep.h */
diff --git a/sysdeps/sparc/fpu/bits/mathinline.h b/sysdeps/sparc/fpu/bits/mathinline.h
index 7add493660..9dd784d122 100644
--- a/sysdeps/sparc/fpu/bits/mathinline.h
+++ b/sysdeps/sparc/fpu/bits/mathinline.h
@@ -1,5 +1,6 @@
 /* Inline math functions for SPARC.
-   Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
@@ -36,23 +37,52 @@
 
 # if __WORDSIZE == 32
 
-#  define __unordered_cmp(x, y) \
+#  ifndef __NO_LONG_DOUBLE_MATH
+
+#   define __unordered_cmp(x, y) \
   (__extension__							      \
    ({ unsigned __r;							      \
-      if (sizeof(x) == 4 && sizeof(y) == 4)				      \
+      if (sizeof (x) == 4 && sizeof (y) == 4)				      \
 	{								      \
 	  float __x = (x); float __y = (y);				      \
-	  __asm__("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x),	      \
-		  "f" (__y) : "cc");					      \
+	  __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x),      \
+		   "f" (__y) : "cc");					      \
+	}								      \
+      else if (sizeof (x) <= 8 && sizeof (y) <= 8)			      \
+	{								      \
+	  double __x = (x); double __y = (y);				      \
+	  __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),   \
+		   "f" (__y) : "cc");					      \
+	}								      \
+      else								      \
+	{								      \
+	  long double __x = (x); long double __y = (y);			      \
+	  extern int _Q_cmp (const long double a, const long double b);	      \
+	  __r = _Q_cmp (__x, __y) << 10;				      \
+	}								      \
+      __r; }))
+
+#  else
+
+#   define __unordered_cmp(x, y) \
+  (__extension__							      \
+   ({ unsigned __r;							      \
+      if (sizeof (x) == 4 && sizeof (y) == 4)				      \
+	{								      \
+	  float __x = (x); float __y = (y);				      \
+	  __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x),      \
+		   "f" (__y) : "cc");					      \
 	}								      \
       else								      \
 	{								      \
 	  double __x = (x); double __y = (y);				      \
-	  __asm__("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),    \
-		  "f" (__y) : "cc");					      \
+	  __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),   \
+		   "f" (__y) : "cc");					      \
 	}								      \
       __r; }))
 
+#  endif
+
 #  define isgreater(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (2 << 10))
 #  define isgreaterequal(x, y) ((__unordered_cmp (x, y) & (1 << 10)) == 0)
 #  define isless(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (1 << 10))
@@ -65,22 +95,22 @@
 #  define __unordered_v9cmp(x, y, op, qop) \
   (__extension__							      \
    ({ unsigned __r;						      	      \
-      if (sizeof(x) == 4 && sizeof(y) == 4)				      \
+      if (sizeof (x) == 4 && sizeof (y) == 4)				      \
 	{								      \
 	  float __x = (x); float __y = (y);				      \
-	  __asm__("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"	      \
-		  : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");	      \
+	  __asm__ ("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"	      \
+		   : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");      \
 	}								      \
-      else if (sizeof(x) <= 8 && sizeof(y) <= 8)			      \
+      else if (sizeof (x) <= 8 && sizeof (y) <= 8)			      \
 	{								      \
 	  double __x = (x); double __y = (y);				      \
-	  __asm__("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"	      \
-		  : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");	      \
+	  __asm__ ("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"	      \
+		   : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");      \
 	}								      \
       else								      \
 	{								      \
 	  long double __x = (x); long double __y = (y);			      \
-	  extern int _Qp_cmp(const long double *a, const long double *b);     \
+	  extern int _Qp_cmp (const long double *a, const long double *b);    \
 	  __r = qop;						      	      \
 	}								      \
       __r; }))
@@ -127,11 +157,20 @@ __NTH (__signbit (double __x))
   return __u.__i[0] < 0;
 }
 
+#    ifndef __NO_LONG_DOUBLE_MATH
+__MATH_INLINE int
+__NTH (__signbitl (long double __x))
+{
+  __extension__ union { long double __l; int __i[4]; } __u = { __l: __x };
+  return __u.__i[0] < 0;
+}
+#    else
 __MATH_INLINE int
 __NTH (__signbitl (long double __x))
 {
   return __signbit ((double)__x);
 }
+#    endif
 
 #   else /* sparc64 */
 
@@ -180,6 +219,13 @@ __NTH (sqrtl (long double __x))
   _Qp_sqrt (&__r, &__x);
   return __r;
 }
+#   elif !defined __NO_LONG_DOUBLE_MATH
+__MATH_INLINE long double
+sqrtl (long double __x) __THROW
+{
+  extern long double _Q_sqrt (__const__ long double);
+  return _Q_sqrt (__x);
+}
 #   endif /* sparc64 */
 
 #  endif /* !__NO_MATH_INLINES && !GCC 3.2+ */
@@ -211,6 +257,13 @@ __ieee754_sqrtl (long double __x)
   _Qp_sqrt(&__r, &__x);
   return __r;
 }
+#   elif !defined __NO_LONG_DOUBLE_MATH
+__MATH_INLINE long double
+__ieee754_sqrtl (long double __x)
+{
+  extern long double _Q_sqrt (__const__ long double);
+  return _Q_sqrt (__x);
+}
 #   endif /* sparc64 */
 #  endif /* __LIBC_INTERNAL_MATH_INLINES */
 # endif /* gcc 2.8+ */
diff --git a/sysdeps/sparc/fpu/feholdexcpt.c b/sysdeps/sparc/fpu/feholdexcpt.c
index 3bd2b16cf1..729637ad1b 100644
--- a/sysdeps/sparc/fpu/feholdexcpt.c
+++ b/sysdeps/sparc/fpu/feholdexcpt.c
@@ -1,5 +1,5 @@
 /* Store current floating-point environment and clear exceptions.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2005 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
@@ -33,3 +33,4 @@ feholdexcept (fenv_t *envp)
 
   return 0;
 }
+libm_hidden_def (feholdexcept)
diff --git a/sysdeps/sparc/fpu/fesetround.c b/sysdeps/sparc/fpu/fesetround.c
index b18b344516..e3b441cd53 100644
--- a/sysdeps/sparc/fpu/fesetround.c
+++ b/sysdeps/sparc/fpu/fesetround.c
@@ -1,5 +1,5 @@
 /* Set current rounding direction.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2005 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
@@ -35,3 +35,4 @@ fesetround (int round)
 
   return 0;
 }
+libm_hidden_def (fesetround)
diff --git a/sysdeps/sparc/fpu/fraiseexcpt.c b/sysdeps/sparc/fpu/fraiseexcpt.c
index 0d45ec82d2..cbb8be80ec 100644
--- a/sysdeps/sparc/fpu/fraiseexcpt.c
+++ b/sysdeps/sparc/fpu/fraiseexcpt.c
@@ -25,12 +25,12 @@
 int
 __feraiseexcept (int excepts)
 {
-  static volatile double sink;
   static const struct {
     double zero, one, max, min, sixteen, pi;
   } c = {
     0.0, 1.0, DBL_MAX, DBL_MIN, 16.0, M_PI
   };
+  double d;
 
   /* Raise exceptions represented by EXPECTS.  But we must raise only
      one signal at a time.  It is important the if the overflow/underflow
@@ -39,24 +39,44 @@ __feraiseexcept (int excepts)
 
   /* First: invalid exception.  */
   if ((FE_INVALID & excepts) != 0)
-    /* One example of a invalid operation is 0/0.  */
-    sink = c.zero / c.zero;
+    {
+      /* One example of a invalid operation is 0/0.  */
+      __asm ("" : "=e" (d) : "0" (c.zero));
+      d /= c.zero;
+      __asm __volatile ("" : : "e" (d));
+    }
 
   /* Next: division by zero.  */
   if ((FE_DIVBYZERO & excepts) != 0)
-    sink = c.one / c.zero;
+    {
+      __asm ("" : "=e" (d) : "0" (c.one));
+      d /= c.zero;
+      __asm __volatile ("" : : "e" (d));
+    }
 
   /* Next: overflow.  */
   if ((FE_OVERFLOW & excepts) != 0)
-    sink = c.max * c.max;
+    {
+      __asm ("" : "=e" (d) : "0" (c.max));
+      d *= d;
+      __asm __volatile ("" : : "e" (d));
+    }
 
   /* Next: underflow.  */
   if ((FE_UNDERFLOW & excepts) != 0)
-    sink = c.min / c.sixteen;
+    {
+      __asm ("" : "=e" (d) : "0" (c.min));
+      d /= c.sixteen;
+      __asm __volatile ("" : : "e" (d));
+    }
 
   /* Last: inexact.  */
   if ((FE_INEXACT & excepts) != 0)
-    sink = c.one / c.pi;
+    {
+      __asm ("" : "=e" (d) : "0" (c.one));
+      d /= c.pi;
+      __asm __volatile ("" : : "e" (d));
+    }
 
   /* Success.  */
   return 0;
diff --git a/sysdeps/sparc/sparc32/Dist b/sysdeps/sparc/sparc32/Dist
deleted file mode 100644
index c3bf9746bc..0000000000
--- a/sysdeps/sparc/sparc32/Dist
+++ /dev/null
@@ -1,9 +0,0 @@
-dotmul.S
-umul.S
-divrem.m4
-sdiv.S
-udiv.S
-rem.S
-urem.S
-alloca.S
-ieee754.h
diff --git a/sysdeps/sparc/sparc32/Implies b/sysdeps/sparc/sparc32/Implies
index 5312721497..436436a651 100644
--- a/sysdeps/sparc/sparc32/Implies
+++ b/sysdeps/sparc/sparc32/Implies
@@ -1,5 +1,6 @@
 wordsize-32
 # SPARC uses IEEE 754 floating point.
-ieee754/flt-32
+ieee754/ldbl-128
 ieee754/dbl-64
+ieee754/flt-32
 sparc/sparc32/soft-fp
diff --git a/sysdeps/sparc/sparc32/__longjmp.S b/sysdeps/sparc/sparc32/__longjmp.S
index 1c81c92692..a5453b4294 100644
--- a/sysdeps/sparc/sparc32/__longjmp.S
+++ b/sysdeps/sparc/sparc32/__longjmp.S
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991, 93, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2006
+   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
@@ -18,9 +19,7 @@
 
 #include <sysdep.h>
 
-#define _ASM 1
-#define _SETJMP_H
-#include <bits/setjmp.h>
+#include <jmpbuf-offsets.h>
 #define ENV(base,reg) [%base + (reg * 4)]
 #define ST_FLUSH_WINDOWS 3
 #define RW_FP [%fp + 0x48]
@@ -30,6 +29,9 @@ ENTRY(__longjmp)
 	   use them while unwinding frames and their register windows.  */
 
 	ld ENV(o0,JB_FP), %g3	/* Cache target FP in register %g3.  */
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE (%g3, %g3, %g4)
+#endif
 	mov %o0, %g1		/* ENV in %g1 */
      	orcc %o1, %g0, %g2	/* VAL in %g2 */
      	be,a 0f			/* Branch if zero; else skip delay slot.  */
@@ -62,8 +64,15 @@ LOC(thread):
 	 * windows.
 	 */
 	ta	ST_FLUSH_WINDOWS
+#ifdef PTR_DEMANGLE
+	ld	ENV(g1,JB_PC), %g5 /* Set return PC. */
+	ld	ENV(g1,JB_SP), %g1 /* Set saved SP on restore below. */
+	PTR_DEMANGLE2 (%o7, %g5, %g4)
+	PTR_DEMANGLE2 (%fp, %g1, %g4)
+#else
 	ld	ENV(g1,JB_PC), %o7 /* Set return PC. */
 	ld	ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */
+#endif
 	sub	%fp, 64, %sp	/* Allocate a register frame. */
 	st	%g3, RW_FP	/* Set saved FP on restore below. */
 	retl
@@ -71,10 +80,17 @@ LOC(thread):
 
 LOC(found):
 	/* We have unwound register windows so %fp matches the target.  */
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE2 (%sp, %o0, %g4)
+#else
 	mov %o0, %sp		/* OK, install new SP.  */
+#endif
 
 LOC(sp_ok):
 	ld ENV(g1,JB_PC), %o0	/* Extract target return PC.  */
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE2 (%o0, %o0, %g4)
+#endif
 	jmp %o0 + 8		/* Return there.  */
 	 mov %g2, %o0		/* Delay slot: set return value.  */
 
diff --git a/sysdeps/sparc/sparc32/bits/atomic.h b/sysdeps/sparc/sparc32/bits/atomic.h
index 736372a3d4..ef553f7270 100644
--- a/sysdeps/sparc/sparc32/bits/atomic.h
+++ b/sysdeps/sparc/sparc32/bits/atomic.h
@@ -1,5 +1,5 @@
 /* Atomic operations.  sparc32 version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -21,6 +21,34 @@
 #ifndef _BITS_ATOMIC_H
 #define _BITS_ATOMIC_H	1
 
+#include <stdint.h>
+
+typedef int8_t atomic8_t;
+typedef uint8_t uatomic8_t;
+typedef int_fast8_t atomic_fast8_t;
+typedef uint_fast8_t uatomic_fast8_t;
+
+typedef int16_t atomic16_t;
+typedef uint16_t uatomic16_t;
+typedef int_fast16_t atomic_fast16_t;
+typedef uint_fast16_t uatomic_fast16_t;
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+
 /* We have no compare and swap, just test and set.
    The following implementation contends on 64 global locks
    per library and assumes no variable will be accessed using atomic.h
@@ -41,22 +69,65 @@ volatile unsigned char __sparc32_atomic_locks[64]
       unsigned int __idx = (((long) addr >> 2) ^ ((long) addr >> 12)) \
 			   & 63;				      \
       do							      \
-	__asm ("ldstub %1, %0"					      \
-	       : "=r" (__old_lock),				      \
-		 "=m" (__sparc32_atomic_locks[__idx])		      \
-	       : "m" (__sparc32_atomic_locks[__idx]));		      \
+	__asm __volatile ("ldstub %1, %0"			      \
+			  : "=r" (__old_lock),			      \
+			    "=m" (__sparc32_atomic_locks[__idx])      \
+			  : "m" (__sparc32_atomic_locks[__idx])	      \
+			  : "memory");				      \
       while (__old_lock);					      \
     }								      \
   while (0)
 
 #define __sparc32_atomic_do_unlock(addr) \
   do								      \
-    __sparc32_atomic_locks[(((long) addr >> 2)			      \
-			    ^ ((long) addr >> 12)) & 63] = 0;	      \
+    {								      \
+      __sparc32_atomic_locks[(((long) addr >> 2)		      \
+			      ^ ((long) addr >> 12)) & 63] = 0;	      \
+      __asm __volatile ("" ::: "memory");			      \
+    }								      \
+  while (0)
+
+#define __sparc32_atomic_do_lock24(addr) \
+  do								      \
+    {								      \
+      unsigned int __old_lock;					      \
+      do							      \
+	__asm __volatile ("ldstub %1, %0"			      \
+			  : "=r" (__old_lock), "=m" (*(addr))	      \
+			  : "m" (*(addr))			      \
+			  : "memory");				      \
+      while (__old_lock);					      \
+    }								      \
   while (0)
 
+#define __sparc32_atomic_do_unlock24(addr) \
+  do								      \
+    {								      \
+      *(char *) (addr) = 0;					      \
+      __asm __volatile ("" ::: "memory");			      \
+    }								      \
+  while (0)
+
+
+#ifndef SHARED
+# define __v9_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+({									      \
+  register __typeof (*(mem)) __acev_tmp __asm ("%g6");			      \
+  register __typeof (mem) __acev_mem __asm ("%g1") = (mem);		      \
+  register __typeof (*(mem)) __acev_oldval __asm ("%g5");		      \
+  __acev_tmp = (newval);						      \
+  __acev_oldval = (oldval);						      \
+  /* .word 0xcde05005 is cas [%g1], %g5, %g6.  Can't use cas here though,     \
+     because as will then mark the object file as V8+ arch.  */		      \
+  __asm __volatile (".word 0xcde05005"					      \
+		    : "+r" (__acev_tmp), "=m" (*__acev_mem)		      \
+		    : "r" (__acev_oldval), "m" (*__acev_mem),		      \
+		      "r" (__acev_mem) : "memory");			      \
+  __acev_tmp; })
+#endif
+
 /* The only basic operation needed is compare and exchange.  */
-#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
+#define __v7_compare_and_exchange_val_acq(mem, newval, oldval) \
   ({ __typeof (mem) __acev_memp = (mem);			      \
      __typeof (*mem) __acev_ret;				      \
      __typeof (*mem) __acev_newval = (newval);			      \
@@ -68,7 +139,7 @@ volatile unsigned char __sparc32_atomic_locks[64]
      __sparc32_atomic_do_unlock (__acev_memp);			      \
      __acev_ret; })
 
-#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
+#define __v7_compare_and_exchange_bool_acq(mem, newval, oldval) \
   ({ __typeof (mem) __aceb_memp = (mem);			      \
      int __aceb_ret;						      \
      __typeof (*mem) __aceb_newval = (newval);			      \
@@ -82,4 +153,175 @@ volatile unsigned char __sparc32_atomic_locks[64]
      __sparc32_atomic_do_unlock (__aceb_memp);			      \
      __aceb_ret; })
 
+#define __v7_exchange_acq(mem, newval) \
+  ({ __typeof (mem) __acev_memp = (mem);			      \
+     __typeof (*mem) __acev_ret;				      \
+     __typeof (*mem) __acev_newval = (newval);			      \
+								      \
+     __sparc32_atomic_do_lock (__acev_memp);			      \
+     __acev_ret = *__acev_memp;					      \
+     *__acev_memp = __acev_newval;				      \
+     __sparc32_atomic_do_unlock (__acev_memp);			      \
+     __acev_ret; })
+
+#define __v7_exchange_and_add(mem, value) \
+  ({ __typeof (mem) __acev_memp = (mem);			      \
+     __typeof (*mem) __acev_ret;				      \
+								      \
+     __sparc32_atomic_do_lock (__acev_memp);			      \
+     __acev_ret = *__acev_memp;					      \
+     *__acev_memp = __acev_ret + (value);			      \
+     __sparc32_atomic_do_unlock (__acev_memp);			      \
+     __acev_ret; })
+
+/* Special versions, which guarantee that top 8 bits of all values
+   are cleared and use those bits as the ldstub lock.  */
+#define __v7_compare_and_exchange_val_24_acq(mem, newval, oldval) \
+  ({ __typeof (mem) __acev_memp = (mem);			      \
+     __typeof (*mem) __acev_ret;				      \
+     __typeof (*mem) __acev_newval = (newval);			      \
+								      \
+     __sparc32_atomic_do_lock24 (__acev_memp);			      \
+     __acev_ret = *__acev_memp & 0xffffff;			      \
+     if (__acev_ret == (oldval))				      \
+       *__acev_memp = __acev_newval;				      \
+     else							      \
+       __sparc32_atomic_do_unlock24 (__acev_memp);		      \
+     __asm __volatile ("" ::: "memory");			      \
+     __acev_ret; })
+
+#define __v7_exchange_24_rel(mem, newval) \
+  ({ __typeof (mem) __acev_memp = (mem);			      \
+     __typeof (*mem) __acev_ret;				      \
+     __typeof (*mem) __acev_newval = (newval);			      \
+								      \
+     __sparc32_atomic_do_lock24 (__acev_memp);			      \
+     __acev_ret = *__acev_memp & 0xffffff;			      \
+     *__acev_memp = __acev_newval;				      \
+     __asm __volatile ("" ::: "memory");			      \
+     __acev_ret; })
+
+#ifdef SHARED
+
+/* When dynamically linked, we assume pre-v9 libraries are only ever
+   used on pre-v9 CPU.  */
+# define __atomic_is_v9 0
+
+# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
+  __v7_compare_and_exchange_val_acq (mem, newval, oldval)
+
+# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
+  __v7_compare_and_exchange_bool_acq (mem, newval, oldval)
+
+# define atomic_exchange_acq(mem, newval) \
+  __v7_exchange_acq (mem, newval)
+
+# define atomic_exchange_and_add(mem, value) \
+  __v7_exchange_and_add (mem, value)
+
+# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
+  ({								      \
+     if (sizeof (*mem) != 4)					      \
+       abort ();						      \
+     __v7_compare_and_exchange_val_24_acq (mem, newval, oldval); })
+
+# define atomic_exchange_24_rel(mem, newval) \
+  ({								      \
+     if (sizeof (*mem) != 4)					      \
+       abort ();						      \
+     __v7_exchange_24_rel (mem, newval); })
+
+#else
+
+/* In libc.a/libpthread.a etc. we don't know if we'll be run on
+   pre-v9 or v9 CPU.  To be interoperable with dynamically linked
+   apps on v9 CPUs e.g. with process shared primitives, use cas insn
+   on v9 CPUs and ldstub on pre-v9.  */
+
+/* Avoid <ldsodefs.h> include here.  */
+extern uint64_t _dl_hwcap __attribute__((weak));
+# define __ATOMIC_HWCAP_SPARC_V9	16
+# define __atomic_is_v9 \
+  (__builtin_expect (&_dl_hwcap != 0, 1) \
+   && __builtin_expect (_dl_hwcap & __ATOMIC_HWCAP_SPARC_V9, \
+			__ATOMIC_HWCAP_SPARC_V9))
+
+# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
+  ({								      \
+     __typeof (*mem) __acev_wret;				      \
+     if (sizeof (*mem) != 4)					      \
+       abort ();						      \
+     if (__atomic_is_v9)					      \
+       __acev_wret						      \
+	 = __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\
+     else							      \
+       __acev_wret						      \
+	 = __v7_compare_and_exchange_val_acq (mem, newval, oldval);   \
+     __acev_wret; })
+
+# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
+  ({								      \
+     int __acev_wret;						      \
+     if (sizeof (*mem) != 4)					      \
+       abort ();						      \
+     if (__atomic_is_v9)					      \
+       {							      \
+	 __typeof (oldval) __acev_woldval = (oldval);		      \
+	 __acev_wret						      \
+	   = __v9_compare_and_exchange_val_32_acq (mem, newval,	      \
+						   __acev_woldval)    \
+	     != __acev_woldval;					      \
+       }							      \
+     else							      \
+       __acev_wret						      \
+	 = __v7_compare_and_exchange_bool_acq (mem, newval, oldval);  \
+     __acev_wret; })
+
+# define atomic_exchange_rel(mem, newval) \
+  ({								      \
+     __typeof (*mem) __acev_wret;				      \
+     if (sizeof (*mem) != 4)					      \
+       abort ();						      \
+     if (__atomic_is_v9)					      \
+       {							      \
+	 __typeof (mem) __acev_wmemp = (mem);			      \
+	 __typeof (*(mem)) __acev_wval = (newval);		      \
+	 do							      \
+	   __acev_wret = *__acev_wmemp;				      \
+	 while (__builtin_expect				      \
+		  (__v9_compare_and_exchange_val_32_acq (__acev_wmemp,\
+							 __acev_wval, \
+							 __acev_wret) \
+		   != __acev_wret, 0));				      \
+       }							      \
+     else							      \
+       __acev_wret = __v7_exchange_acq (mem, newval);		      \
+     __acev_wret; })
+
+# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
+  ({								      \
+     __typeof (*mem) __acev_wret;				      \
+     if (sizeof (*mem) != 4)					      \
+       abort ();						      \
+     if (__atomic_is_v9)					      \
+       __acev_wret						      \
+	 = __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\
+     else							      \
+       __acev_wret						      \
+	 = __v7_compare_and_exchange_val_24_acq (mem, newval, oldval);\
+     __acev_wret; })
+
+# define atomic_exchange_24_rel(mem, newval) \
+  ({								      \
+     __typeof (*mem) __acev_w24ret;				      \
+     if (sizeof (*mem) != 4)					      \
+       abort ();						      \
+     if (__atomic_is_v9)					      \
+       __acev_w24ret = atomic_exchange_rel (mem, newval);	      \
+     else							      \
+       __acev_w24ret = __v7_exchange_24_rel (mem, newval);	      \
+     __acev_w24ret; })
+
+#endif
+
 #endif	/* bits/atomic.h */
diff --git a/sysdeps/sparc/sparc32/bits/setjmp.h b/sysdeps/sparc/sparc32/bits/setjmp.h
index 76d7af02c7..86ccc20d20 100644
--- a/sysdeps/sparc/sparc32/bits/setjmp.h
+++ b/sysdeps/sparc/sparc32/bits/setjmp.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 2005, 2006 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
@@ -22,17 +22,6 @@
 # error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
 #endif
 
-#if defined __USE_MISC || defined _ASM
-# define JB_SP	0
-# define JB_FP	1
-# define JB_PC	2
-#endif
-
 #ifndef	_ASM
 typedef int __jmp_buf[3];
 #endif
-
-/* Test if longjmp to JMPBUF would unwind the frame
-   containing a local variable at ADDRESS.  */
-#define _JMPBUF_UNWINDS(jmpbuf, address) \
-  ((int) (address) < (jmpbuf)[JB_SP])
diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h
index 52fc6329dd..02dabaabb4 100644
--- a/sysdeps/sparc/sparc32/dl-machine.h
+++ b/sysdeps/sparc/sparc32/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  SPARC version.
-   Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1996-2003, 2004, 2005, 2006 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
@@ -40,13 +40,6 @@
 #define OPCODE_SAVE_SP	0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
 #define OPCODE_BA	0x30800000 /* b,a ?; add PC-rel word address */
 
-/* Use a different preload file when running in 32-bit emulation mode
-   on a 64-bit host.  */
-#define LD_SO_PRELOAD ((GLRO(dl_hwcap) & HWCAP_SPARC_V9) \
-		       ? "/etc/ld.so.preload32" \
-		       : "/etc/ld.so.preload")
-
-
 /* Return nonzero iff ELF header is compatible with the running host.  */
 static inline int
 elf_machine_matches_host (const Elf32_Ehdr *ehdr)
@@ -131,30 +124,31 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	 bits of %g1 with an offset into the .rela.plt section and jump to
 	 the beginning of the PLT.  */
       plt = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
-      if (! profile)
-	rfunc = (Elf32_Addr) &_dl_runtime_resolve;
-      else
+      if (__builtin_expect(profile, 0))
 	{
 	  rfunc = (Elf32_Addr) &_dl_runtime_profile;
 
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    GL(dl_profile_map) = l;
 	}
+      else
+	{
+	  rfunc = (Elf32_Addr) &_dl_runtime_resolve;
+	}
 
       /* The beginning of the PLT does:
 
-		save %sp, -64, %sp
-	 pltpc:	call _dl_runtime_resolve
-		nop
+		sethi %hi(_dl_runtime_{resolve,profile}), %g2
+	 pltpc:	jmpl %g2 + %lo(_dl_runtime_{resolve,profile}), %g2
+		 nop
 		.word MAP
 
-         This saves the register window containing the arguments, and the
-	 PC value (pltpc) implicitly saved in %o7 by the call points near the
+         The PC value (pltpc) saved in %g2 by the jmpl points near the
 	 location where we store the link_map pointer for this object.  */
 
-      plt[0] = OPCODE_SAVE_SP;
-      /* Construct PC-relative word address.  */
-      plt[1] = OPCODE_CALL | ((rfunc - (Elf32_Addr) &plt[1]) >> 2);
+      plt[0] = 0x05000000 | ((rfunc >> 10) & 0x003fffff);
+      plt[1] = 0x85c0a000 | (rfunc & 0x3ff);
       plt[2] = OPCODE_NOP;	/* Fill call delay slot.  */
       plt[3] = (Elf32_Addr) l;
       if (__builtin_expect (l->l_info[VALIDX(DT_GNU_PRELINKED)] != NULL, 0)
@@ -190,39 +184,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name)	\
-  asm ( "\
-	.text\n\
-	.globl	" #tramp_name "\n\
-	.type	" #tramp_name ", @function\n\
-	.align	32\n\
-" #tramp_name ":\n\
-	/* Set up the arguments to fixup --\n\
-	   %o0 = link_map out of plt0\n\
-	   %o1 = offset of reloc entry\n\
-	   %o2 = return address  */\n\
-	ld	[%o7 + 8], %o0\n\
-	srl	%g1, 10, %o1\n\
-	mov	%i7, %o2\n\
-	call	" #fixup_name "\n\
-	 sub	%o1, 4*12, %o1\n\
-	jmp	%o0\n\
-	 restore\n\
-	.size	" #tramp_name ", . - " #tramp_name "\n\
-	.previous")
-
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE			\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);	\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE			\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);	\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, fixup);
-#endif
-
 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
    PLT entries should not be allowed to define the value.
    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
@@ -406,18 +367,25 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
 
 #endif /* dl_machine_h */
 
-#ifdef RESOLVE
+#define ARCH_LA_PLTENTER	sparc32_gnu_pltenter
+#define ARCH_LA_PLTEXIT		sparc32_gnu_pltexit
+
+#ifdef RESOLVE_MAP
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 		  const Elf32_Sym *sym, const struct r_found_version *version,
 		  void *const reloc_addr_arg)
 {
   Elf32_Addr *const reloc_addr = reloc_addr_arg;
+  const Elf32_Sym *const refsym = sym;
+  Elf32_Addr value;
   const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+  struct link_map *sym_map = NULL;
 
 #if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
   /* This is defined in rtld.c, but nowhere in the static libc.a; make the
@@ -428,6 +396,9 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
   weak_extern (_dl_rtld_map);
 #endif
 
+  if (__builtin_expect (r_type == R_SPARC_NONE, 0))
+    return;
+
 #if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
   if (__builtin_expect (r_type == R_SPARC_RELATIVE, 0))
     {
@@ -435,165 +406,148 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
       if (map != &_dl_rtld_map) /* Already done in rtld itself. */
 # endif
 	*reloc_addr += map->l_addr + reloc->r_addend;
+      return;
     }
-  else
-#endif
-    {
-#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
-      const Elf32_Sym *const refsym = sym;
-# ifdef USE_TLS
-      struct link_map *sym_map;
-# endif
 #endif
-      Elf32_Addr value;
+
 #ifndef RESOLVE_CONFLICT_FIND_MAP
-      if (sym->st_shndx != SHN_UNDEF &&
-	  ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
-	{
-	  value = map->l_addr;
-# if defined USE_TLS && !defined RTLD_BOOTSTRAP
-	  sym_map = map;
-# endif
-	}
-      else
-	{
-# if defined USE_TLS && !defined RTLD_BOOTSTRAP
-	  sym_map = RESOLVE_MAP (&sym, version, r_type);
-	  value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-# else
-	  value = RESOLVE (&sym, version, r_type);
-	  if (sym)
-	    value += sym->st_value;
-# endif
-	}
+  if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0)
+      && sym->st_shndx != SHN_UNDEF)
+    {
+      value = map->l_addr;
+    }
+  else
+    {
+      sym_map = RESOLVE_MAP (&sym, version, r_type);
+      value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
+    }
 #else
-      value = 0;
+  value = 0;
 #endif
-      value += reloc->r_addend;	/* Assume copy relocs have zero addend.  */
 
-      switch (r_type)
-	{
+  value += reloc->r_addend;	/* Assume copy relocs have zero addend.  */
+
+  switch (r_type)
+    {
 #if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
-	case R_SPARC_COPY:
-	  if (sym == NULL)
-	    /* This can happen in trace mode if an object could not be
-	       found.  */
-	    break;
-	  if (sym->st_size > refsym->st_size
-	      || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
-	    {
-	      const char *strtab;
+    case R_SPARC_COPY:
+      if (sym == NULL)
+	/* This can happen in trace mode if an object could not be
+	   found.  */
+	break;
+      if (sym->st_size > refsym->st_size
+	  || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
+	{
+	  const char *strtab;
 
-	      strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
-	      _dl_error_printf ("\
+	  strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+	  _dl_error_printf ("\
 %s: Symbol `%s' has different size in shared object, consider re-linking\n",
-				rtld_progname ?: "<program name unknown>",
-				strtab + refsym->st_name);
-	    }
-	  memcpy (reloc_addr_arg, (void *) value,
-		  MIN (sym->st_size, refsym->st_size));
-	  break;
+			    rtld_progname ?: "<program name unknown>",
+			    strtab + refsym->st_name);
+	}
+      memcpy (reloc_addr_arg, (void *) value,
+	      MIN (sym->st_size, refsym->st_size));
+      break;
 #endif
-	case R_SPARC_GLOB_DAT:
-	case R_SPARC_32:
-	  *reloc_addr = value;
-	  break;
-	case R_SPARC_JMP_SLOT:
-	  /* At this point we don't need to bother with thread safety,
-	     so we can optimize the first instruction of .plt out.  */
-	  sparc_fixup_plt (reloc, reloc_addr, value, 0);
-	  break;
+    case R_SPARC_GLOB_DAT:
+    case R_SPARC_32:
+      *reloc_addr = value;
+      break;
+    case R_SPARC_JMP_SLOT:
+      /* At this point we don't need to bother with thread safety,
+	 so we can optimize the first instruction of .plt out.  */
+      sparc_fixup_plt (reloc, reloc_addr, value, 0);
+      break;
 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) \
     && !defined RESOLVE_CONFLICT_FIND_MAP
-	case R_SPARC_TLS_DTPMOD32:
-	  /* Get the information from the link map returned by the
-	     resolv function.  */
-	  if (sym_map != NULL)
-	    *reloc_addr = sym_map->l_tls_modid;
-	  break;
-	case R_SPARC_TLS_DTPOFF32:
-	  /* During relocation all TLS symbols are defined and used.
-	     Therefore the offset is already correct.  */
-	  *reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
-	  break;
-	case R_SPARC_TLS_TPOFF32:
-	  /* The offset is negative, forward from the thread pointer.  */
-	  /* We know the offset of object the symbol is contained in.
-	     It is a negative value which will be added to the
-	     thread pointer.  */
-	  if (sym != NULL)
-	    {
-	      CHECK_STATIC_TLS (map, sym_map);
-	      *reloc_addr = sym->st_value - sym_map->l_tls_offset
-			    + reloc->r_addend;
-	    }
-	  break;
+    case R_SPARC_TLS_DTPMOD32:
+      /* Get the information from the link map returned by the
+	 resolv function.  */
+      if (sym_map != NULL)
+	*reloc_addr = sym_map->l_tls_modid;
+      break;
+    case R_SPARC_TLS_DTPOFF32:
+      /* During relocation all TLS symbols are defined and used.
+	 Therefore the offset is already correct.  */
+      *reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
+      break;
+    case R_SPARC_TLS_TPOFF32:
+      /* The offset is negative, forward from the thread pointer.  */
+      /* We know the offset of object the symbol is contained in.
+	 It is a negative value which will be added to the
+	 thread pointer.  */
+      if (sym != NULL)
+	{
+	  CHECK_STATIC_TLS (map, sym_map);
+	  *reloc_addr = sym->st_value - sym_map->l_tls_offset
+	    + reloc->r_addend;
+	}
+      break;
 # ifndef RTLD_BOOTSTRAP
-	case R_SPARC_TLS_LE_HIX22:
-	case R_SPARC_TLS_LE_LOX10:
-	  if (sym != NULL)
-	    {
-	      CHECK_STATIC_TLS (map, sym_map);
-	      value = sym->st_value - sym_map->l_tls_offset
-		      + reloc->r_addend;
-	      if (r_type == R_SPARC_TLS_LE_HIX22)
-		*reloc_addr = (*reloc_addr & 0xffc00000) | ((~value) >> 10);
-	      else
-		*reloc_addr = (*reloc_addr & 0xffffe000) | (value & 0x3ff)
-			      | 0x1c00;
-	    }
-	  break;
+    case R_SPARC_TLS_LE_HIX22:
+    case R_SPARC_TLS_LE_LOX10:
+      if (sym != NULL)
+	{
+	  CHECK_STATIC_TLS (map, sym_map);
+	  value = sym->st_value - sym_map->l_tls_offset
+	    + reloc->r_addend;
+	  if (r_type == R_SPARC_TLS_LE_HIX22)
+	    *reloc_addr = (*reloc_addr & 0xffc00000) | ((~value) >> 10);
+	  else
+	    *reloc_addr = (*reloc_addr & 0xffffe000) | (value & 0x3ff)
+	      | 0x1c00;
+	}
+      break;
 # endif
 #endif
 #ifndef RTLD_BOOTSTRAP
-	case R_SPARC_8:
-	  *(char *) reloc_addr = value;
-	  break;
-	case R_SPARC_16:
-	  *(short *) reloc_addr = value;
-	  break;
-	case R_SPARC_DISP8:
-	  *(char *) reloc_addr = (value - (Elf32_Addr) reloc_addr);
-	  break;
-	case R_SPARC_DISP16:
-	  *(short *) reloc_addr = (value - (Elf32_Addr) reloc_addr);
-	  break;
-	case R_SPARC_DISP32:
-	  *reloc_addr = (value - (Elf32_Addr) reloc_addr);
-	  break;
-	case R_SPARC_LO10:
-	  *reloc_addr = (*reloc_addr & ~0x3ff) | (value & 0x3ff);
-	  break;
-	case R_SPARC_WDISP30:
-	  *reloc_addr = ((*reloc_addr & 0xc0000000)
-			 | ((value - (unsigned int) reloc_addr) >> 2));
-	  break;
-	case R_SPARC_HI22:
-	  *reloc_addr = (*reloc_addr & 0xffc00000) | (value >> 10);
-	  break;
-	case R_SPARC_UA16:
-	  ((unsigned char *) reloc_addr_arg) [0] = value >> 8;
-	  ((unsigned char *) reloc_addr_arg) [1] = value;
-	  break;
-	case R_SPARC_UA32:
-	  ((unsigned char *) reloc_addr_arg) [0] = value >> 24;
-	  ((unsigned char *) reloc_addr_arg) [1] = value >> 16;
-	  ((unsigned char *) reloc_addr_arg) [2] = value >> 8;
-	  ((unsigned char *) reloc_addr_arg) [3] = value;
-	  break;
+    case R_SPARC_8:
+      *(char *) reloc_addr = value;
+      break;
+    case R_SPARC_16:
+      *(short *) reloc_addr = value;
+      break;
+    case R_SPARC_DISP8:
+      *(char *) reloc_addr = (value - (Elf32_Addr) reloc_addr);
+      break;
+    case R_SPARC_DISP16:
+      *(short *) reloc_addr = (value - (Elf32_Addr) reloc_addr);
+      break;
+    case R_SPARC_DISP32:
+      *reloc_addr = (value - (Elf32_Addr) reloc_addr);
+      break;
+    case R_SPARC_LO10:
+      *reloc_addr = (*reloc_addr & ~0x3ff) | (value & 0x3ff);
+      break;
+    case R_SPARC_WDISP30:
+      *reloc_addr = ((*reloc_addr & 0xc0000000)
+		     | ((value - (unsigned int) reloc_addr) >> 2));
+      break;
+    case R_SPARC_HI22:
+      *reloc_addr = (*reloc_addr & 0xffc00000) | (value >> 10);
+      break;
+    case R_SPARC_UA16:
+      ((unsigned char *) reloc_addr_arg) [0] = value >> 8;
+      ((unsigned char *) reloc_addr_arg) [1] = value;
+      break;
+    case R_SPARC_UA32:
+      ((unsigned char *) reloc_addr_arg) [0] = value >> 24;
+      ((unsigned char *) reloc_addr_arg) [1] = value >> 16;
+      ((unsigned char *) reloc_addr_arg) [2] = value >> 8;
+      ((unsigned char *) reloc_addr_arg) [3] = value;
+      break;
 #endif
-	case R_SPARC_NONE:		/* Alright, Wilbur.  */
-	  break;
 #if !defined RTLD_BOOTSTRAP || defined _NDEBUG
-	default:
-	  _dl_reloc_bad_type (map, r_type, 0);
-	  break;
+    default:
+      _dl_reloc_bad_type (map, r_type, 0);
+      break;
 #endif
-	}
     }
 }
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
 			   void *const reloc_addr_arg)
 {
@@ -601,7 +555,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
   *reloc_addr += l_addr + reloc->r_addend;
 }
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_lazy_rel (struct link_map *map,
 		      Elf32_Addr l_addr, const Elf32_Rela *reloc)
 {
@@ -617,4 +572,4 @@ elf_machine_lazy_rel (struct link_map *map,
     }
 }
 
-#endif	/* RESOLVE */
+#endif	/* RESOLVE_MAP */
diff --git a/sysdeps/sparc/sparc32/dl-trampoline.S b/sysdeps/sparc/sparc32/dl-trampoline.S
new file mode 100644
index 0000000000..b0f86dda4e
--- /dev/null
+++ b/sysdeps/sparc/sparc32/dl-trampoline.S
@@ -0,0 +1,184 @@
+/* PLT trampolines.  Sparc 32-bit version.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+	.text
+	.align	32
+
+	/* %g1:	PLT offset loaded by PLT entry
+	 * %g2: callers PC, which is PLT0 + 4, and we store the
+	 *      link map at PLT0 + 12, therefore we add 8 to get
+	 *      the address of the link map
+	 */
+	.globl	_dl_runtime_resolve
+	.type	_dl_runtime_resolve, @function
+_dl_runtime_resolve:
+	cfi_startproc
+
+	save	%sp, -104, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+	cfi_register (%o7, %i7)
+
+	ld	[%g2 + 8], %o0
+	srl	%g1, 10, %o1
+	call	_dl_fixup
+	 sub	%o1, 4*12, %o1
+	jmp	%o0
+	 restore
+
+	cfi_endproc
+
+	.size	_dl_runtime_resolve, .-_dl_runtime_resolve
+
+	/* For the profiling cases we pass in our stack frame
+	 * as the base of the La_sparc64_regs, so it looks
+	 * like:
+	 *	%l0			%sp
+	 *	...
+	 *	%l7			%sp + (7 * 8)
+	 *	%i0			%sp + (8 * 8)
+	 *	...
+	 *	%i7			%sp + (15 * 8)
+	 *	%f0			%sp + (16 * 8)
+	 *	%f16			%sp + (31 * 8)
+	 *	framesize		%sp + (32 * 8)
+	 */
+
+	.globl	_dl_profile_save_regs
+	.type	_dl_profile_save_regs, @function
+_dl_profile_save_regs:
+	cfi_startproc
+
+	std	%l0, [%sp + ( 0 * 8)]
+	std	%l2, [%sp + ( 1 * 8)]
+	std	%l4, [%sp + ( 2 * 8)]
+	std	%l6, [%sp + ( 3 * 8)]
+	std	%i0, [%sp + ( 4 * 8)]
+	std	%i2, [%sp + ( 5 * 8)]
+	std	%i4, [%sp + ( 6 * 8)]
+	std	%i6, [%sp + ( 7 * 8)]
+	ld	[%sp + (8 * 8)], %l4
+	retl
+	 st	%l4, [%sp + (8 * 8)]
+
+	cfi_endproc
+
+	.size	_dl_profile_save_regs, .-_dl_profile_save_regs
+
+	/* If we are going to call pltexit, then we must replicate
+	 * the caller's stack frame.
+	 * %o0: PLT resolved function address
+	 */
+	.globl	_dl_profile_invoke
+	.type	_dl_profile_invoke, @function
+_dl_profile_invoke:
+	cfi_startproc
+
+	sub	%sp, %l0, %sp
+1:
+	srl	%l0, 3, %l7
+	mov	%o0, %l1
+	mov	%i0, %o0
+	mov	%i1, %o1
+	mov	%i2, %o2
+	mov	%i3, %o3
+	mov	%i4, %o4
+	mov	%i5, %o5
+	mov	%fp, %l2
+	mov	%sp, %l3
+1:	ldd	[%l2], %g2
+	add	%l2, 0x8, %l2
+	subcc	%l7, 1, %l7
+	std	%g2, [%l3]
+	bne	1b
+	 add	%l3, 0x8, %l3
+
+	jmpl	%l1, %o7
+	 nop
+
+	std	%o0, [%sp + ( 9 * 8)]
+	std	%f0, [%sp + (10 * 8)]
+
+	mov	%l5, %o0
+	mov	%l6, %o1
+	add	%sp, %l0, %o2
+	call	_dl_call_pltexit
+	 add	%sp, (16 * 8), %o3
+
+	ldd	[%sp + (9 * 8)], %i0
+
+	jmpl	%i7 + 8, %g0
+	 restore
+
+	cfi_endproc
+
+	.size	_dl_profile_invoke, .-_dl_profile_invoke
+
+	/* %g1:	PLT offset loaded by PLT entry
+	 * %g2: callers PC, which is PLT0 + 4, and we store the
+	 *      link map at PLT0 + 12, therefore we add 8 to get
+	 *      the address of the link map
+	 */
+	.align	32
+	.globl	_dl_runtime_profile
+	.type	_dl_runtime_profile, @function
+_dl_runtime_profile:
+	cfi_startproc
+
+	cmp	%fp, 0
+	be,a	1f
+	 mov	104, %g3
+	sub	%fp, %sp, %g3
+1:	save	%sp, -104, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+	cfi_register(%o7, %i7)
+
+	ld	[%g2 + 8], %o0
+	srl	%g1, 10, %o1
+	mov	%i7, %o2
+	sub	%o1, 4*12, %o1
+
+	mov	%g3, %l0
+	mov	%o0, %l5
+	mov	%o1, %l6
+
+	call _dl_profile_save_regs
+	 nop
+
+	mov	%sp, %o3
+	call	_dl_profile_fixup
+	 add	%sp, (9 * 8), %o4
+
+	ld	[%sp + (9 * 8)], %o1
+	cmp	%o1, 0
+	bgeu	1f
+	 nop
+	
+	call	_dl_profile_invoke
+	 nop
+
+1:	jmp	%o0
+	 restore
+
+	cfi_endproc
+
+	.size	_dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/sparc/sparc32/elf/start.S b/sysdeps/sparc/sparc32/elf/start.S
index 2787fd27f8..702dd755e6 100644
--- a/sysdeps/sparc/sparc32/elf/start.S
+++ b/sysdeps/sparc/sparc32/elf/start.S
@@ -48,6 +48,7 @@
 	.global _start
 	.type _start,#function
 _start:
+	cfi_startproc
 
 #ifdef SHARED
 	sethi	%hi(_GLOBAL_OFFSET_TABLE_-4), %l7
@@ -59,6 +60,7 @@ _start:
      drop their arguments.  */
 	mov	%g0, %fp
 	sub	%sp, 6*4, %sp
+	cfi_adjust_cfa_offset(6*4)
 
   /* Extract the arguments and environment as encoded on the stack.  The
      argument info starts after one register window (16 words) past the SP.  */
@@ -91,4 +93,12 @@ _start:
   /* Die very horribly if exit returns.  */
 	unimp
 
+	cfi_endproc
+
 	.size _start, .-_start
+
+/* Define a symbol for the first piece of initialized data.  */
+	.data
+	.globl	__data_start
+__data_start:
+weak_alias (__data_start, data_start)
diff --git a/sysdeps/sparc/sparc32/fpu/e_sqrtl.c b/sysdeps/sparc/sparc32/fpu/e_sqrtl.c
new file mode 100644
index 0000000000..3c3acfee02
--- /dev/null
+++ b/sysdeps/sparc/sparc32/fpu/e_sqrtl.c
@@ -0,0 +1 @@
+/* __ieee754_sqrtl is defined in q_sqrt.c.  */
diff --git a/sysdeps/sparc/sparc32/fpu/libm-test-ulps b/sysdeps/sparc/sparc32/fpu/libm-test-ulps
index 979e0e2c91..ccf53788a6 100644
--- a/sysdeps/sparc/sparc32/fpu/libm-test-ulps
+++ b/sysdeps/sparc/sparc32/fpu/libm-test-ulps
@@ -4,32 +4,49 @@
 Test "atan2 (-0.75, -1.0) == -2.49809154479650885165983415456218025":
 float: 3
 ifloat: 3
+ildouble: 1
+ldouble: 1
 Test "atan2 (0.75, -1.0) == 2.49809154479650885165983415456218025":
 float: 3
 ifloat: 3
+ildouble: 1
+ldouble: 1
 Test "atan2 (1.390625, 0.9296875) == 0.981498387184244311516296577615519772":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "atan2 (-0.00756827042671106339, -.001792735857538728036) == -1.80338464113663849327153994379639112":
 float: 6
 ifloat: 6
+ildouble: 1
+ldouble: 1
 
 # atanh
 Test "atanh (0.75) == 0.972955074527656652552676371721589865":
 float: 1
 ifloat: 1
 
+# cacos
+Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i":
+ildouble: 1
+ldouble: 1
+
 # cacosh
-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
 double: 1
 float: 7
 idouble: 1
 ifloat: 7
-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
+ildouble: 5
+ldouble: 5
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
 double: 1
 float: 3
 idouble: 1
 ifloat: 3
+ildouble: 1
+ldouble: 1
 
 # casin
 Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
@@ -37,6 +54,9 @@ double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "Imaginary part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+ildouble: 1
+ldouble: 1
 
 # casinh
 Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
@@ -44,19 +64,27 @@ double: 5
 float: 1
 idouble: 5
 ifloat: 1
+ildouble: 4
+ldouble: 4
 Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
 double: 3
 float: 6
 idouble: 3
 ifloat: 6
+ildouble: 2
+ldouble: 2
 Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 # catan
 Test "Real part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
@@ -70,6 +98,9 @@ ifloat: 1
 Test "Real part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
 float: 4
 ifloat: 4
+Test "Imaginary part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+ildouble: 1
+ldouble: 1
 
 # catanh
 Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
@@ -81,11 +112,18 @@ ifloat: 4
 Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
 double: 1
 idouble: 1
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
 float: 6
 ifloat: 6
+ildouble: 1
+ldouble: 1
 
 # cbrt
+Test "cbrt (-0.001) == -0.1":
+ildouble: 1
+ldouble: 1
 Test "cbrt (-27.0) == -3.0":
 double: 1
 idouble: 1
@@ -97,9 +135,14 @@ double: 1
 idouble: 1
 
 # ccos
+Test "Real part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
 double: 1
 float: 1
@@ -113,9 +156,13 @@ ifloat: 1
 Test "Real part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
 double: 1
 float: 1
@@ -126,12 +173,20 @@ float: 1
 ifloat: 1
 
 # cexp
+Test "Real part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
 float: 1
 ifloat: 1
+Test "Imaginary part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+ildouble: 1
+ldouble: 1
 
 # clog
 Test "Imaginary part of: clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i":
@@ -140,57 +195,98 @@ ifloat: 3
 Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 # clog10
 Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
+Test "Real part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
 double: 1
 float: 5
 idouble: 1
 ifloat: 5
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
+Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i":
+double: 1
+idouble: 1
 Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
 float: 1
 ifloat: 1
+Test "Imaginary part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
 
 # cos
@@ -199,16 +295,22 @@ double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "cos (M_PI_6l * 4.0) == -0.5":
 double: 2
 float: 1
 idouble: 2
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "cos (pi/2) == 0":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 # cpow
 Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
@@ -222,16 +324,31 @@ double: 1
 float: 4
 idouble: 1
 ifloat: 4
+ildouble: 4
+ldouble: 4
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 1
+ldouble: 1
 Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
 double: 2
 float: 3
 idouble: 2
 ifloat: 3
+ildouble: 10
+ldouble: 10
+Test "Real part of: cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i":
+ildouble: 2
+ldouble: 2
 Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
 double: 1
 float: 4
 idouble: 1
 ifloat: 4
+ildouble: 3
+ldouble: 3
 Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
 float: 2
 ifloat: 2
@@ -240,8 +357,21 @@ double: 2
 float: 2
 idouble: 2
 ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# csin
+Test "Imaginary part of: csin (-2 - 3 i) == -9.15449914691142957346729954460983256 + 4.16890695996656435075481305885375484 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+ildouble: 1
+ldouble: 1
 
 # csinh
+Test "Real part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
 double: 1
 idouble: 1
@@ -256,17 +386,31 @@ ifloat: 1
 Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csqrt (0.75 + 1.25 i) == 1.05065169626078392338656675760808326 + 0.594868882070379067881984030639932657 i":
+ildouble: 1
+ldouble: 1
 
 # ctan
 Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
 double: 1
 idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
 double: 1
 idouble: 1
+ildouble: 2
+ldouble: 2
 
 # ctanh
 Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
@@ -274,6 +418,11 @@ double: 1
 float: 2
 idouble: 1
 ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+ildouble: 1
+ldouble: 1
 Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
 float: 1
 ifloat: 1
@@ -290,6 +439,9 @@ idouble: 1
 Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
 double: 1
 idouble: 1
+Test "erfc (27.0) == 0.523704892378925568501606768284954709e-318":
+ildouble: 1
+ldouble: 1
 Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
 double: 1
 idouble: 1
@@ -310,14 +462,30 @@ double: 6
 float: 2
 idouble: 6
 ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# exp2
+Test "exp2 (10) == 1024":
+ildouble: 2
+ldouble: 2
 
 # expm1
 Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
 double: 1
 idouble: 1
 Test "expm1 (1) == M_El - 1.0":
+double: 1
 float: 1
+idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# gamma
+Test "gamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
 
 # hypot
 Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
@@ -359,9 +527,13 @@ double: 2
 float: 1
 idouble: 2
 ifloat: 1
+ildouble: 2
+ldouble: 2
 Test "j0 (2.0) == 0.223890779141235668051827454649948626":
 float: 2
 ifloat: 2
+ildouble: 2
+ldouble: 2
 Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
 double: 1
 float: 1
@@ -370,17 +542,32 @@ ifloat: 1
 Test "j0 (8.0) == 0.171650807137553906090869407851972001":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 # j1
+Test "j1 (-1.0) == -0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "j1 (0.75) == 0.349243602174862192523281016426251335":
+ildouble: 1
+ldouble: 1
+Test "j1 (1.0) == 0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
 Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
 float: 2
 ifloat: 2
+ildouble: 2
+ldouble: 2
 Test "j1 (2.0) == 0.576724807756873387202448242269137087":
 double: 1
 idouble: 1
 Test "j1 (8.0) == 0.234636346853914624381276651590454612":
 double: 1
 idouble: 1
+ildouble: 4
+ldouble: 4
 
 # jn
 Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
@@ -396,9 +583,13 @@ double: 2
 float: 1
 idouble: 2
 ifloat: 1
+ildouble: 2
+ldouble: 2
 Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
 float: 2
 ifloat: 2
+ildouble: 2
+ldouble: 2
 Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
 double: 1
 float: 1
@@ -407,30 +598,57 @@ ifloat: 1
 Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (1, -1.0) == -0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 0.75) == 0.349243602174862192523281016426251335":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 1.0) == 0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
 Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
 float: 2
 ifloat: 2
+ildouble: 2
+ldouble: 2
 Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
 double: 1
 idouble: 1
 Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
 double: 1
 idouble: 1
+ildouble: 4
+ldouble: 4
+Test "jn (10, -1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
 Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
 Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
 double: 4
 float: 3
 idouble: 4
 ifloat: 3
+ildouble: 2
+ldouble: 2
 Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
 float: 4
 ifloat: 4
@@ -449,6 +667,8 @@ double: 3
 float: 1
 idouble: 3
 ifloat: 1
+ildouble: 2
+ldouble: 2
 Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
 double: 1
 float: 2
@@ -456,16 +676,23 @@ idouble: 1
 ifloat: 2
 
 # lgamma
+Test "lgamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
 Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
 double: 1
 float: 2
 idouble: 1
 ifloat: 2
+ildouble: 1
+ldouble: 1
 
 # log10
 Test "log10 (0.75) == -0.124938736608299953132449886193870744":
@@ -476,11 +703,21 @@ ifloat: 2
 Test "log10 (e) == log10(e)":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 # log1p
 Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
 float: 1
 ifloat: 1
+Test "log1p (M_El - 1.0) == 1":
+ildouble: 1
+ldouble: 1
+
+# log2
+Test "log2 (0.75) == -.415037499278843818546261056052183492":
+ildouble: 1
+ldouble: 1
 
 # sincos
 Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
@@ -488,31 +725,58 @@ double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res":
 float: 1
 ifloat: 1
 
+# sqrt
+Test "sqrt (2) == M_SQRT2l":
+ildouble: 1
+ldouble: 1
+
 # tan
 Test "tan (pi/4) == 1":
 double: 1
 idouble: 1
 
+# tanh
+Test "tanh (-0.75) == -0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (-1.0) == -0.7615941559557648881194582826047935904":
+ildouble: 1
+ldouble: 1
+Test "tanh (0.75) == 0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (1.0) == 0.7615941559557648881194582826047935904":
+ildouble: 1
+ldouble: 1
+
 # tgamma
 Test "tgamma (-0.5) == -2 sqrt (pi)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "tgamma (0.5) == sqrt (pi)":
 float: 1
 ifloat: 1
@@ -521,6 +785,9 @@ double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "tgamma (4) == 6":
+ildouble: 1
+ldouble: 1
 
 # y0
 Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
@@ -536,19 +803,28 @@ ifloat: 1
 Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
 float: 1
 ifloat: 1
+ildouble: 3
+ldouble: 3
 Test "y0 (8.0) == 0.223521489387566220527323400498620359":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 3
+ldouble: 3
 
 # y1
 Test "y1 (0.125) == -5.19993611253477499595928744876579921":
 double: 1
 idouble: 1
+Test "y1 (0.75) == -1.03759455076928541973767132140642198":
+ildouble: 1
+ldouble: 1
 Test "y1 (1.5) == -0.412308626973911295952829820633445323":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "y1 (10.0) == 0.249015424206953883923283474663222803":
 double: 3
 float: 1
@@ -559,11 +835,15 @@ double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "y1 (8.0) == -0.158060461731247494255555266187483550":
 double: 1
 float: 2
 idouble: 1
 ifloat: 2
+ildouble: 1
+ldouble: 1
 
 # yn
 Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
@@ -579,17 +859,26 @@ ifloat: 1
 Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
 float: 1
 ifloat: 1
+ildouble: 3
+ldouble: 3
 Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 3
+ldouble: 3
 Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
 double: 1
 idouble: 1
+Test "yn (1, 0.75) == -1.03759455076928541973767132140642198":
+ildouble: 1
+ldouble: 1
 Test "yn (1, 1.5) == -0.412308626973911295952829820633445323":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
 double: 3
 float: 1
@@ -600,30 +889,44 @@ double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
 double: 1
 float: 2
 idouble: 1
 ifloat: 2
+ildouble: 1
+ldouble: 1
 Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
 double: 1
 idouble: 1
+ildouble: 2
+ldouble: 2
 Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 5
+ldouble: 5
 Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
 double: 1
 idouble: 1
+ildouble: 1
+ldouble: 1
 Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 2
+ldouble: 2
 Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
 double: 2
 idouble: 2
+ildouble: 2
+ldouble: 2
 Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
 double: 1
 idouble: 1
@@ -632,11 +935,15 @@ double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 2
+ldouble: 2
 Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
 double: 1
 idouble: 1
@@ -645,22 +952,32 @@ idouble: 1
 Function: "atan2":
 float: 6
 ifloat: 6
+ildouble: 1
+ldouble: 1
 
 Function: "atanh":
 float: 1
 ifloat: 1
 
+Function: Imaginary part of "cacos":
+ildouble: 1
+ldouble: 1
+
 Function: Real part of "cacosh":
 double: 1
 float: 7
 idouble: 1
 ifloat: 7
+ildouble: 5
+ldouble: 5
 
 Function: Imaginary part of "cacosh":
 double: 1
 float: 3
 idouble: 1
 ifloat: 3
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "casin":
 double: 1
@@ -668,17 +985,25 @@ float: 1
 idouble: 1
 ifloat: 1
 
+Function: Imaginary part of "casin":
+ildouble: 1
+ldouble: 1
+
 Function: Real part of "casinh":
 double: 5
 float: 1
 idouble: 5
 ifloat: 1
+ildouble: 4
+ldouble: 4
 
 Function: Imaginary part of "casinh":
 double: 3
 float: 6
 idouble: 3
 ifloat: 6
+ildouble: 2
+ldouble: 2
 
 Function: Real part of "catan":
 float: 4
@@ -689,50 +1014,72 @@ double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "catanh":
 double: 4
 idouble: 4
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "catanh":
 float: 6
 ifloat: 6
+ildouble: 1
+ldouble: 1
 
 Function: "cbrt":
 double: 1
 idouble: 1
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "ccos":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "ccos":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "ccosh":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "ccosh":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "cexp":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "cexp":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "clog":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "clog":
 float: 3
@@ -741,34 +1088,54 @@ ifloat: 3
 Function: Real part of "clog10":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "clog10":
 double: 1
 float: 5
 idouble: 1
 ifloat: 5
+ildouble: 1
+ldouble: 1
 
 Function: "cos":
 double: 2
 float: 1
 idouble: 2
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "cpow":
 double: 2
 float: 4
 idouble: 2
 ifloat: 4
+ildouble: 10
+ldouble: 10
 
 Function: Imaginary part of "cpow":
 double: 2
 float: 2
 idouble: 2
 ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csin":
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "csinh":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "csinh":
 double: 1
@@ -779,24 +1146,38 @@ ifloat: 1
 Function: Real part of "csqrt":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csqrt":
+ildouble: 1
+ldouble: 1
 
 Function: Real part of "ctan":
 double: 1
 idouble: 1
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "ctan":
 double: 1
 idouble: 1
+ildouble: 2
+ldouble: 2
 
 Function: Real part of "ctanh":
 double: 1
 float: 2
 idouble: 1
 ifloat: 2
+ildouble: 1
+ldouble: 1
 
 Function: Imaginary part of "ctanh":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: "erf":
 double: 1
@@ -805,18 +1186,32 @@ idouble: 1
 Function: "erfc":
 double: 1
 idouble: 1
+ildouble: 1
+ldouble: 1
 
 Function: "exp10":
 double: 6
 float: 2
 idouble: 6
 ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "exp2":
+ildouble: 2
+ldouble: 2
 
 Function: "expm1":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "gamma":
+ildouble: 1
+ldouble: 1
 
 Function: "hypot":
 float: 1
@@ -827,67 +1222,101 @@ double: 2
 float: 2
 idouble: 2
 ifloat: 2
+ildouble: 2
+ldouble: 2
 
 Function: "j1":
 double: 1
 float: 2
 idouble: 1
 ifloat: 2
+ildouble: 4
+ldouble: 4
 
 Function: "jn":
 double: 4
 float: 4
 idouble: 4
 ifloat: 4
+ildouble: 4
+ldouble: 4
 
 Function: "lgamma":
 double: 1
 float: 2
 idouble: 1
 ifloat: 2
+ildouble: 1
+ldouble: 1
 
 Function: "log10":
 double: 1
 float: 2
 idouble: 1
 ifloat: 2
+ildouble: 1
+ldouble: 1
 
 Function: "log1p":
 float: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log2":
+ildouble: 1
+ldouble: 1
 
 Function: "sincos":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sqrt":
+ildouble: 1
+ldouble: 1
 
 Function: "tan":
 double: 1
 idouble: 1
 
+Function: "tanh":
+ildouble: 1
+ldouble: 1
+
 Function: "tgamma":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+ildouble: 1
+ldouble: 1
 
 Function: "y0":
 double: 2
 float: 1
 idouble: 2
 ifloat: 1
+ildouble: 3
+ldouble: 3
 
 Function: "y1":
 double: 3
 float: 2
 idouble: 3
 ifloat: 2
+ildouble: 1
+ldouble: 1
 
 Function: "yn":
 double: 3
 float: 2
 idouble: 3
 ifloat: 2
+ildouble: 5
+ldouble: 5
 
 # end of automatic generation
diff --git a/sysdeps/sparc/sparc32/fpu/s_fabs.c b/sysdeps/sparc/sparc32/fpu/s_fabs.c
new file mode 100644
index 0000000000..b883e6e862
--- /dev/null
+++ b/sysdeps/sparc/sparc32/fpu/s_fabs.c
@@ -0,0 +1,11 @@
+#include <math.h>
+#include <math_ldbl_opt.h>
+
+double __fabs (double x)
+{
+  return __builtin_fabs (x);
+}
+weak_alias (__fabs, fabs)
+#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0)
+compat_symbol (libm, __fabs, fabsl, GLIBC_2_0);
+#endif
diff --git a/sysdeps/sparc/sparc32/fpu/s_fabsf.S b/sysdeps/sparc/sparc32/fpu/s_fabsf.S
new file mode 100644
index 0000000000..e1487247d1
--- /dev/null
+++ b/sysdeps/sparc/sparc32/fpu/s_fabsf.S
@@ -0,0 +1,29 @@
+/* Float absolute value, sparc32 version.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+ENTRY (__fabsf)
+	st	%o0, [%sp+64]
+	ld	[%sp+64], %f0
+	retl
+	 fabss	%f0, %f0
+END (__fabsf)
+weak_alias (__fabsf, fabsf)
diff --git a/sysdeps/sparc/sparc32/fpu/s_fabsl.c b/sysdeps/sparc/sparc32/fpu/s_fabsl.c
new file mode 100644
index 0000000000..3c03b92828
--- /dev/null
+++ b/sysdeps/sparc/sparc32/fpu/s_fabsl.c
@@ -0,0 +1,8 @@
+#include <math.h>
+#include <math_ldbl_opt.h>
+
+long double __fabsl (long double x)
+{
+  return __builtin_fabsl (x);
+}
+long_double_symbol (libm, __fabsl, fabsl);
diff --git a/sysdeps/sparc/sparc32/jmpbuf-offsets.h b/sysdeps/sparc/sparc32/jmpbuf-offsets.h
new file mode 100644
index 0000000000..1c6f7a9d17
--- /dev/null
+++ b/sysdeps/sparc/sparc32/jmpbuf-offsets.h
@@ -0,0 +1,22 @@
+/* Private macros for accessing __jmp_buf contents.  SPARC version.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define JB_SP	0
+#define JB_FP	1
+#define JB_PC	2
diff --git a/sysdeps/sparc/sparc32/jmpbuf-unwind.h b/sysdeps/sparc/sparc32/jmpbuf-unwind.h
new file mode 100644
index 0000000000..0f317b99d0
--- /dev/null
+++ b/sysdeps/sparc/sparc32/jmpbuf-unwind.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <setjmp.h>
+#include <jmpbuf-offsets.h>
+#include <stdint.h>
+#include <unwind.h>
+#include <sysdep.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+   containing a local variable at ADDRESS.  */
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
+  ((int) (address) < demangle ((jmpbuf)[JB_SP]))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+static inline uintptr_t __attribute__ ((unused))
+_jmpbuf_sp (__jmp_buf regs)
+{
+  uintptr_t sp = regs[JB_SP];
+#ifdef PTR_DEMANGLE
+  PTR_DEMANGLE (sp);
+#endif
+  return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
+/* We use the normal lobngjmp for unwinding.  */
+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
diff --git a/sysdeps/sparc/sparc32/memchr.S b/sysdeps/sparc/sparc32/memchr.S
index 0ca56ccdd9..fcd98315db 100644
--- a/sysdeps/sparc/sparc32/memchr.S
+++ b/sysdeps/sparc/sparc32/memchr.S
@@ -32,7 +32,15 @@
 
 	.text
 	.align		4
-0:	cmp		%o2, 0
+ENTRY(__memchr)
+	andcc		%o1, 0xff, %o1
+	sll		%o1, 8, %g6
+	andcc		%o0, 3, %g0
+	or		%o1, %g6, %g6
+	sll		%g6, 16, %o3
+	be		10f
+	 or		%o3, %g6, %g2
+	cmp		%o2, 0
 	be		9f
 	 sethi		%hi(0x80808080), %o4
 	ldub		[%o0], %g4
@@ -64,16 +72,7 @@
 	 clr		%o0
 1:	retl
 	 sub		%o0, 1, %o0
-
-ENTRY(__memchr)
-	andcc		%o1, 0xff, %o1
-	sll		%o1, 8, %g6
-	andcc		%o0, 3, %g0
-	or		%o1, %g6, %g6
-	sll		%g6, 16, %o3
-	bne		0b
-	 or		%o3, %g6, %g2
-	sethi		%hi(0x80808080), %o4
+10:	sethi		%hi(0x80808080), %o4
 	or		%o4, %lo(0x80808080), %o3
 4:	sethi		%hi(0x01010101), %o5
 5:	and		%o2, 3, %g1
diff --git a/sysdeps/sparc/sparc32/memcpy.S b/sysdeps/sparc/sparc32/memcpy.S
index 35bcef4963..6bd55c06a1 100644
--- a/sysdeps/sparc/sparc32/memcpy.S
+++ b/sysdeps/sparc/sparc32/memcpy.S
@@ -146,28 +146,12 @@
 	.text
 	.align	4
 
-70:	andcc		%o1, 1, %g0
-	be		4f
-	 andcc		%o1, 2, %g0
-
-	ldub		[%o1 - 1], %g2
-	sub		%o1, 1, %o1
-	stb		%g2, [%o0 - 1]
-	sub		%o2, 1, %o2
-	be		3f
-	 sub		%o0, 1, %o0
-4:	lduh		[%o1 - 2], %g2
-	sub		%o1, 2, %o1
-	sth		%g2, [%o0 - 2]
-	sub		%o2, 2, %o2
-	b		3f
-	 sub		%o0, 2, %o0
-
 ENTRY(bcopy)
 	mov		%o0, %o3
 	mov		%o1, %o0
 	mov		%o3, %o1
 END(bcopy)
+
 ENTRY(memmove)
 	cmp		%o0, %o1
 	st		%o0, [%sp + 64]
@@ -185,8 +169,26 @@ ENTRY(memmove)
 	 cmp		%o2, 15
 	bleu		91f
 	 andcc		%o1, 3, %g0
-	bne		70b
-3:	 andcc		%o1, 4, %g0
+	be		3f
+	 nop
+
+	andcc		%o1, 1, %g0
+	be		4f
+	 andcc		%o1, 2, %g0
+
+	ldub		[%o1 - 1], %g2
+	sub		%o1, 1, %o1
+	stb		%g2, [%o0 - 1]
+	sub		%o2, 1, %o2
+	be		3f
+	 sub		%o0, 1, %o0
+4:	lduh		[%o1 - 2], %g2
+	sub		%o1, 2, %o1
+	sth		%g2, [%o0 - 2]
+	sub		%o2, 2, %o2
+	sub		%o0, 2, %o0
+
+3:	andcc		%o1, 4, %g0
 
 	be		2f
 	 mov		%o2, %g1
diff --git a/sysdeps/sparc/sparc32/memset.S b/sysdeps/sparc/sparc32/memset.S
index 8e91e998bf..e6204e8ac9 100644
--- a/sysdeps/sparc/sparc32/memset.S
+++ b/sysdeps/sparc/sparc32/memset.S
@@ -152,4 +152,4 @@ ENTRY(memset)
 END(memset)
 libc_hidden_builtin_def (memset)
 
-weak_alias(__bzero, bzero)
+weak_alias (__bzero, bzero)
diff --git a/sysdeps/sparc/sparc32/setjmp.S b/sysdeps/sparc/sparc32/setjmp.S
index 883ea06297..0a5d3cece8 100644
--- a/sysdeps/sparc/sparc32/setjmp.S
+++ b/sysdeps/sparc/sparc32/setjmp.S
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991, 93, 94, 96, 97, 98, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1993, 1994, 1996, 1997, 1998, 2002, 2006
+   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
@@ -19,9 +20,7 @@
 #include <sysdep.h>
 #include <sys/trap.h>
 
-#define _ASM 1
-#define _SETJMP_H
-#include <bits/setjmp.h>
+#include <jmpbuf-offsets.h>
 
 ENTRY(_setjmp)
 	b	1f
@@ -39,9 +38,18 @@ ENTRY (__sigsetjmp)
 	   a tail-call for simplicity; it always returns zero.  */
 	ta	ST_FLUSH_WINDOWS
 
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%g1, %o7, %g4)
+	PTR_MANGLE2 (%g2, %sp, %g4)
+	PTR_MANGLE2 (%g3, %fp, %g4)
+	st	%g1, [%o0 + (JB_PC * 4)]
+	st	%g2, [%o0 + (JB_SP * 4)]
+	st	%g3, [%o0 + (JB_FP * 4)]
+#else
 	st	%o7, [%o0 + (JB_PC * 4)]
 	st	%sp, [%o0 + (JB_SP * 4)]
 	st	%fp, [%o0 + (JB_FP * 4)]
+#endif
 
 	mov	%o7, %g1
 	call	__sigjmp_save
diff --git a/sysdeps/sparc/sparc32/soft-fp/Dist b/sysdeps/sparc/sparc32/soft-fp/Dist
deleted file mode 100644
index b3c7344889..0000000000
--- a/sysdeps/sparc/sparc32/soft-fp/Dist
+++ /dev/null
@@ -1,28 +0,0 @@
-q_add.c
-q_cmp.c
-q_cmpe.c
-q_div.c
-q_dtoq.c
-q_feq.c
-q_fge.c
-q_fgt.c
-q_fle.c
-q_flt.c
-q_fne.c
-q_itoq.c
-q_mul.c
-q_neg.c
-q_qtod.c
-q_qtoi.c
-q_qtos.c
-q_qtoui.c
-q_qtoux.c
-q_qtox.c
-q_sqrt.c
-q_stoq.c
-q_sub.c
-q_uitoq.c
-q_util.c
-q_uxtoq.c
-q_xtoq.c
-sfp-machine.h
diff --git a/sysdeps/sparc/sparc32/soft-fp/Makefile b/sysdeps/sparc/sparc32/soft-fp/Makefile
index bba9bf7f86..d447b48285 100644
--- a/sysdeps/sparc/sparc32/soft-fp/Makefile
+++ b/sysdeps/sparc/sparc32/soft-fp/Makefile
@@ -1,6 +1,6 @@
 #  Software floating-point emulation.
 #  Makefile for SPARC v8 long double utility functions (_Q_*).
-#  Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+#  Copyright (C) 1999, 2000, 2006 Free Software Foundation, Inc.
 #  This file is part of the GNU C Library.
 #  Contributed by Jakub Jelinek (jj@ultra.linux.cz).
 #
@@ -20,13 +20,11 @@
 # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 # 02111-1307 USA.
 
-#  Currently gcc does not support TFmode long double on sparc32
-#  so these routines are not used.
-#ifeq ($(subdir),soft-fp)
-#sparc32-quad-routines := q_add q_cmp q_cmpe q_div q_dtoq q_feq q_fge	\
-#	q_fgt q_fle q_flt q_fne q_itoq q_mul q_neg q_qtod q_qtoi	\
-#	q_qtos q_qtoui q_qtoux q_qtox q_sqrt q_stoq q_sub q_uitoq	\
-#	q_uxtoq q_xtoq q_util
-#sysdep_routines += $(sparc32-quad-routines)
-#
-#endif
+ifeq ($(subdir),soft-fp)
+sparc32-quad-routines := q_add q_cmp q_cmpe q_div q_dtoq q_feq q_fge	\
+	q_fgt q_fle q_flt q_fne q_itoq q_mul q_neg q_qtod q_qtoi	\
+	q_qtos q_qtou q_qtoull q_qtoll q_sqrt q_stoq q_sub q_utoq	\
+	q_ulltoq q_lltoq q_util
+sysdep_routines += $(sparc32-quad-routines)
+
+endif
diff --git a/sysdeps/sparc/sparc32/soft-fp/Versions b/sysdeps/sparc/sparc32/soft-fp/Versions
new file mode 100644
index 0000000000..6a09249c46
--- /dev/null
+++ b/sysdeps/sparc/sparc32/soft-fp/Versions
@@ -0,0 +1,8 @@
+libc {
+  GLIBC_2.4 {
+    _Q_add; _Q_cmp; _Q_cmpe; _Q_div; _Q_dtoq; _Q_feq; _Q_fge; _Q_fgt;
+    _Q_fle; _Q_flt; _Q_fne; _Q_itoq; _Q_mul; _Q_neg; _Q_qtod; _Q_qtoi;
+    _Q_qtos; _Q_qtou; _Q_qtoull; _Q_qtoll; _Q_sqrt; _Q_stoq; _Q_sub;
+    _Q_utoq; _Q_ulltoq; _Q_lltoq;
+  }
+}
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_add.c b/sysdeps/sparc/sparc32/soft-fp/q_add.c
index fb93461593..987c725582 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_add.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_add.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return a + b
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -30,10 +30,10 @@ long double _Q_add(const long double a, const long double b)
   long double c;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_Q(A, a);
-  FP_UNPACK_Q(B, b);
+  FP_UNPACK_SEMIRAW_Q(A, a);
+  FP_UNPACK_SEMIRAW_Q(B, b);
   FP_ADD_Q(C, A, B);
-  FP_PACK_Q(c, C);
+  FP_PACK_SEMIRAW_Q(c, C);
   FP_HANDLE_EXCEPTIONS;
   return c;
 }
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_div.c b/sysdeps/sparc/sparc32/soft-fp/q_div.c
index bb4e697236..86db5ed9e9 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_div.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_div.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return a / b
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -35,5 +35,5 @@ long double _Q_div(const long double a, const long double b)
   FP_DIV_Q(C, A, B);
   FP_PACK_Q(c, C);
   FP_HANDLE_EXCEPTIONS;
-  return long double;
+  return c;
 }
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_dtoq.c b/sysdeps/sparc/sparc32/soft-fp/q_dtoq.c
index 5cac5c0840..6b119f4501 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_dtoq.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_dtoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ long double _Q_dtoq(const double a)
   long double c;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_D(A, a);
+  FP_UNPACK_RAW_D(A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
-  FP_CONV(Q,D,4,2,C,A);
+  FP_EXTEND(Q,D,4,2,C,A);
 #else
-  FP_CONV(Q,D,2,1,C,A);
+  FP_EXTEND(Q,D,2,1,C,A);
 #endif
-  FP_PACK_Q(c, C);
+  FP_PACK_RAW_Q(c, C);
   FP_HANDLE_EXCEPTIONS;
   return c;
 }
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_itoq.c b/sysdeps/sparc/sparc32/soft-fp/q_itoq.c
index 0010b3bcbf..b50942f75f 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_itoq.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_itoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -30,8 +30,8 @@ long double _Q_itoq(const int a)
   int b = a;
   long double c;
 
-  FP_FROM_INT_Q(C, b, 32, int);
-  FP_PACK_Q(c, C);
+  FP_FROM_INT_Q(C, b, 32, unsigned int);
+  FP_PACK_RAW_Q(c, C);
   FP_CLEAR_EXCEPTIONS;
   FP_HANDLE_EXCEPTIONS;
   return c;
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_xtoq.c b/sysdeps/sparc/sparc32/soft-fp/q_lltoq.c
index 867ef27131..f977585e42 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_xtoq.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_lltoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (long double)a
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -23,15 +23,15 @@
 #include "soft-fp.h"
 #include "quad.h"
 
-long double _Q_xtoq(const long long a)
+long double _Q_lltoq(const long long a)
 {
   FP_DECL_EX;
   FP_DECL_Q(C);
   long double c;
   long long b = a;
 
-  FP_FROM_INT_Q(C, b, 64, long long);
-  FP_PACK_Q(c, C);
+  FP_FROM_INT_Q(C, b, 64, unsigned long long);
+  FP_PACK_RAW_Q(c, C);
   FP_CLEAR_EXCEPTIONS;
   FP_HANDLE_EXCEPTIONS;
   return c;
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_qtod.c b/sysdeps/sparc/sparc32/soft-fp/q_qtod.c
index b0778476b8..82b01ec8a1 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_qtod.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_qtod.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (double)a
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ double _Q_qtod(const long double a)
   double r;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_Q(A, a);
+  FP_UNPACK_SEMIRAW_Q(A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
-  FP_CONV(D,Q,2,4,R,A);
+  FP_TRUNC(D,Q,2,4,R,A);
 #else
-  FP_CONV(D,Q,1,2,R,A);
+  FP_TRUNC(D,Q,1,2,R,A);
 #endif
-  FP_PACK_D(r, R);
+  FP_PACK_SEMIRAW_D(r, R);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_qtoi.c b/sysdeps/sparc/sparc32/soft-fp/q_qtoi.c
index 0440e9abba..270ba9f677 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_qtoi.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_qtoi.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (int)a
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -28,9 +28,9 @@ int _Q_qtoi(const long double a)
 {
   FP_DECL_EX;
   FP_DECL_Q(A);
-  int r;
+  unsigned int r;
 
-  FP_UNPACK_Q(A, a);
+  FP_UNPACK_RAW_Q(A, a);
   FP_TO_INT_Q(r, A, 32, 1);
   FP_HANDLE_EXCEPTIONS;
 
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_qtox.c b/sysdeps/sparc/sparc32/soft-fp/q_qtoll.c
index 108373328e..e0d29019b3 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_qtox.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_qtoll.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
-   Return (long)a
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Return (long long)a
+   Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -24,13 +24,13 @@
 #include "soft-fp.h"
 #include "quad.h"
 
-long long _Q_qtox(const long double a)
+long long _Q_qtoll(const long double a)
 {
   FP_DECL_EX;
   FP_DECL_Q(A);
-  long long r;
+  unsigned long long r;
 
-  FP_UNPACK_Q(A, a);
+  FP_UNPACK_RAW_Q(A, a);
   FP_TO_INT_Q(r, A, 64, 1);
   FP_HANDLE_EXCEPTIONS;
 
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_qtos.c b/sysdeps/sparc/sparc32/soft-fp/q_qtos.c
index 31c8d6ac82..93daa23cac 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_qtos.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_qtos.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (float)a
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ float _Q_qtos(const long double a)
   float r;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_Q(A, a);
+  FP_UNPACK_SEMIRAW_Q(A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
-  FP_CONV(S,Q,1,4,R,A);
+  FP_TRUNC(S,Q,1,4,R,A);
 #else
-  FP_CONV(S,Q,1,2,R,A);
+  FP_TRUNC(S,Q,1,2,R,A);
 #endif
-  FP_PACK_S(r, R);
+  FP_PACK_SEMIRAW_S(r, R);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_qtoui.c b/sysdeps/sparc/sparc32/soft-fp/q_qtou.c
index bdbf052e09..812b4e06ea 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_qtoui.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_qtou.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (unsigned int)a
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -24,13 +24,13 @@
 #include "soft-fp.h"
 #include "quad.h"
 
-unsigned int _Q_qtoui(const long double a)
+unsigned int _Q_qtou(const long double a)
 {
   FP_DECL_EX;
   FP_DECL_Q(A);
   unsigned int r;
 
-  FP_UNPACK_Q(A, a);
+  FP_UNPACK_RAW_Q(A, a);
   FP_TO_INT_Q(r, A, 32, -1);
   FP_HANDLE_EXCEPTIONS;
 
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_qtoux.c b/sysdeps/sparc/sparc32/soft-fp/q_qtoull.c
index 3e6d40f220..7a88c9f382 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_qtoux.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_qtoull.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
-   Return (unsigned long)a
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Return (unsigned long long)a
+   Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -24,13 +24,13 @@
 #include "soft-fp.h"
 #include "quad.h"
 
-unsigned long long _Q_qtoux(const long double a)
+unsigned long long _Q_qtoull(const long double a)
 {
   FP_DECL_EX;
   FP_DECL_Q(A);
   unsigned long long r;
 
-  FP_UNPACK_Q(A, a);
+  FP_UNPACK_RAW_Q(A, a);
   FP_TO_INT_Q(r, A, 64, -1);
   FP_HANDLE_EXCEPTIONS;
 
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_sqrt.c b/sysdeps/sparc/sparc32/soft-fp/q_sqrt.c
index 7516ed7c5c..373d02a639 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_sqrt.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_sqrt.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return sqrtl(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -36,3 +36,4 @@ long double _Q_sqrt(const long double a)
   FP_HANDLE_EXCEPTIONS;
   return c;
 }
+strong_alias (_Q_sqrt, __ieee754_sqrtl);
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_stoq.c b/sysdeps/sparc/sparc32/soft-fp/q_stoq.c
index 98609faf20..714d880dd7 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_stoq.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_stoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    c = (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,13 +31,13 @@ long double _Q_stoq(const float a)
   FP_DECL_Q(C);
   long double c;
 
-  FP_UNPACK_S(A, a);
+  FP_UNPACK_RAW_S(A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
-  FP_CONV(Q,S,4,1,C,A);
+  FP_EXTEND(Q,S,4,1,C,A);
 #else
-  FP_CONV(Q,S,2,1,C,A);
+  FP_EXTEND(Q,S,2,1,C,A);
 #endif
-  FP_PACK_Q(c, C);
+  FP_PACK_RAW_Q(c, C);
   FP_HANDLE_EXCEPTIONS;
   return c;
 }
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_sub.c b/sysdeps/sparc/sparc32/soft-fp/q_sub.c
index 1987aea480..8616727bb1 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_sub.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_sub.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    c = a - b
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -30,10 +30,10 @@ long double _Q_sub(const long double a, const long double b)
   long double c;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_Q(A, a);
-  FP_UNPACK_Q(B, b);
+  FP_UNPACK_SEMIRAW_Q(A, a);
+  FP_UNPACK_SEMIRAW_Q(B, b);
   FP_SUB_Q(C, A, B);
-  FP_PACK_Q(c, C);
+  FP_PACK_SEMIRAW_Q(c, C);
   FP_HANDLE_EXCEPTIONS;
   return c;
 }
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_uxtoq.c b/sysdeps/sparc/sparc32/soft-fp/q_ulltoq.c
index 8944e9614d..53c0add2d8 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_uxtoq.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_ulltoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -23,15 +23,15 @@
 #include "soft-fp.h"
 #include "quad.h"
 
-long double _Q_uxtoq(const unsigned long long a)
+long double _Q_ulltoq(const unsigned long long a)
 {
   FP_DECL_EX;
   FP_DECL_Q(C);
   long double c;
   unsigned long long b = a;
 
-  FP_FROM_INT_Q(C, b, 64, long long);
-  FP_PACK_Q(c, C);
+  FP_FROM_INT_Q(C, b, 64, unsigned long long);
+  FP_PACK_RAW_Q(c, C);
   FP_CLEAR_EXCEPTIONS;
   FP_HANDLE_EXCEPTIONS;
   return c;
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_uitoq.c b/sysdeps/sparc/sparc32/soft-fp/q_utoq.c
index b716fabde2..f902bf8397 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_uitoq.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_utoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    c = (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -23,15 +23,15 @@
 #include "soft-fp.h"
 #include "quad.h"
 
-long double _Q_uitoq(const unsigned int a)
+long double _Q_utoq(const unsigned int a)
 {
   FP_DECL_EX;
   FP_DECL_Q(C);
   long double c;
   unsigned int b = a;
 
-  FP_FROM_INT_Q(C, b, 32, int);
-  FP_PACK_Q(c, C);
+  FP_FROM_INT_Q(C, b, 32, unsigned int);
+  FP_PACK_RAW_Q(c, C);
   FP_CLEAR_EXCEPTIONS;
   FP_HANDLE_EXCEPTIONS;
   return c;
diff --git a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
index 40bcbb4762..f1211705ef 100644
--- a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
@@ -1,6 +1,6 @@
 /* Machine-dependent software floating-point definitions.
    Sparc userland (_Q_*) version.
-   Copyright (C) 1997,1998,1999, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1997,1998,1999, 2002, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com),
 		  Jakub Jelinek (jj@ultra.linux.cz) and
@@ -22,6 +22,7 @@
    02111-1307 USA.  */
 
 #include <fpu_control.h>
+#include <stdlib.h>
 
 #define _FP_W_TYPE_SIZE		32
 #define _FP_W_TYPE		unsigned long
@@ -208,14 +209,5 @@ do {								\
       	" : : "r" (___Q_numbers) : "f30");			\
     }								\
   else								\
-    {								\
-      __asm__ __volatile__("\
-        mov %0, %%o0\n\
-        mov %%o7, %%g1\n\
-        call ___Q_simulate_exceptions\n\
-         mov %%g1, %%o7\
-        " : : "r" (_fex) :					\
-        "g1", "g2", "g3", "g4", "g5", "o0", 			\
-        "o1", "o2", "o3", "o4", "o5", "cc");			\
-    }								\
+    ___Q_simulate_exceptions (_fex);			        \
 } while (0)
diff --git a/sysdeps/sparc/sparc32/sparcv8/Dist b/sysdeps/sparc/sparc32/sparcv8/Dist
deleted file mode 100644
index 6318172684..0000000000
--- a/sysdeps/sparc/sparc32/sparcv8/Dist
+++ /dev/null
@@ -1,6 +0,0 @@
-urem.S
-umul.S
-udiv.S
-sdiv.S
-rem.S
-dotmul.S
diff --git a/sysdeps/sparc/sparc32/sparcv9/Dist b/sysdeps/sparc/sparc32/sparcv9/Dist
deleted file mode 100644
index 2de64957fb..0000000000
--- a/sysdeps/sparc/sparc32/sparcv9/Dist
+++ /dev/null
@@ -1,7 +0,0 @@
-dotmul.S
-hp-timing.c
-rem.S
-sdiv.S
-udiv.S
-umul.S
-urem.S
diff --git a/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h b/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h
index 6d316f37d5..7b9d61d468 100644
--- a/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h
+++ b/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h
@@ -1,5 +1,5 @@
 /* Atomic operations.  sparcv9 version.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -59,7 +59,7 @@ typedef uintmax_t uatomic_max_t;
   __asm __volatile ("cas [%4], %2, %0"					      \
 		    : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
 		    : "r" (oldval), "m" (*__acev_mem), "r" (__acev_mem),      \
-		      "0" (newval));					      \
+		      "0" (newval) : "memory");				      \
   __acev_tmp; })
 
 /* This can be implemented if needed.  */
@@ -74,11 +74,17 @@ typedef uintmax_t uatomic_max_t;
      if (sizeof (*(mem)) == 4)						      \
        __asm ("swap %0, %1"						      \
 	      : "=m" (*__memp), "=r" (__oldval)				      \
-	      : "m" (*__memp), "1" (__value));				      \
+	      : "m" (*__memp), "1" (__value) : "memory");		      \
      else								      \
        abort ();							      \
      __oldval; })
 
+#define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
+  atomic_compare_and_exchange_val_acq (mem, newval, oldval)
+
+#define atomic_exchange_24_rel(mem, newval) \
+  atomic_exchange_rel (mem, newval)
+
 #define atomic_full_barrier() \
   __asm __volatile ("membar #LoadLoad | #LoadStore"			      \
 			  " | #StoreLoad | #StoreStore" : : : "memory")
diff --git a/sysdeps/sparc/sparc32/sparcv9b/Implies b/sysdeps/sparc/sparc32/sparcv9b/Implies
deleted file mode 100644
index 78a424460b..0000000000
--- a/sysdeps/sparc/sparc32/sparcv9b/Implies
+++ /dev/null
@@ -1 +0,0 @@
-sparc/sparc32/sparcv9
diff --git a/sysdeps/sparc/sparc32/sparcv9v/memcpy.S b/sysdeps/sparc/sparc32/sparcv9v/memcpy.S
new file mode 100644
index 0000000000..4c05f57bc2
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9v/memcpy.S
@@ -0,0 +1,2 @@
+#define XCC icc
+#include <sparc64/sparcv9v/memcpy.S>
diff --git a/sysdeps/sparc/sparc32/sparcv9v/memset.S b/sysdeps/sparc/sparc32/sparcv9v/memset.S
new file mode 100644
index 0000000000..5e46c7489f
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9v/memset.S
@@ -0,0 +1,2 @@
+#define XCC icc
+#include <sparc64/sparcv9v/memset.S>
diff --git a/sysdeps/sparc/sparc32/stpcpy.S b/sysdeps/sparc/sparc32/stpcpy.S
index 937fed35f8..222bc2a445 100644
--- a/sysdeps/sparc/sparc32/stpcpy.S
+++ b/sysdeps/sparc/sparc32/stpcpy.S
@@ -38,7 +38,13 @@
 
 	.text
 	.align		4
-10:	ldub		[%o1], %o5
+
+ENTRY(__stpcpy)
+	andcc		%o1, 3, %g0
+	be		20f
+	 sethi		%hi(0x80808080), %o4
+
+	ldub		[%o1], %o5
 	stb		%o5, [%o0]
 	cmp		%o5, 0
 	add		%o0, 1, %o0
@@ -67,11 +73,7 @@
 1:	retl
 	 add		%o0, -1, %o0
 
-ENTRY(__stpcpy)
-	andcc		%o1, 3, %g0
-	bne		10b
-	 sethi		%hi(0x80808080), %o4
-	or		%o4, %lo(0x80808080), %o3
+20:	or		%o4, %lo(0x80808080), %o3
 4:	sethi		%hi(0x01010101), %o4
 5:	or		%o4, %lo(0x01010101), %o2
 6:	andcc		%o0, 3, %g0
@@ -160,6 +162,6 @@ ENTRY(__stpcpy)
 	 nop
 END(__stpcpy)
 
-weak_alias(__stpcpy, stpcpy)
+weak_alias (__stpcpy, stpcpy)
 libc_hidden_def (__stpcpy)
 libc_hidden_builtin_def (stpcpy)
diff --git a/sysdeps/sparc/sparc32/strcat.S b/sysdeps/sparc/sparc32/strcat.S
index 3709c8a692..4ce0771908 100644
--- a/sysdeps/sparc/sparc32/strcat.S
+++ b/sysdeps/sparc/sparc32/strcat.S
@@ -38,36 +38,14 @@
 
 	.text
 	.align		4
-10:	cmp		%o4, 2
-	be		1f
-	 cmp		%o4, 3
-	ldub		[%o1], %o5
-	add		%o1, 1, %o1
-	stb		%o5, [%o0]
-	be		3f
-	 cmp		%o5, 0
-	be		0f
-	 add		%o0, 1, %o0
-1:	lduh		[%o1], %o5
-	add		%o1, 2, %o1
-	srl		%o5, 8, %o4
-	cmp		%o4, 0
-	stb		%o4, [%o0]
-	bne,a		2f
-	 stb		%o5, [%o0 + 1]
-	retl
-	 mov		%g2, %o0
-2:	andcc		%o5, 0xff, %o5
-	bne		4f
-	 add		%o0, 2, %o0
-	retl
-	 mov 		%g2, %o0
-3:	bne		4f
-	 add		%o0, 1, %o0
-	retl
-	 mov		%g2, %o0
 
-11:	ldub		[%o0], %o5
+ENTRY(strcat)
+	mov		%o0, %g2
+	andcc		%o0, 3, %g0
+	be		30f
+	 sethi		%hi(0x80808080), %o4
+
+	ldub		[%o0], %o5
 	cmp		%o5, 0
 	be		1f
 	 add		%o0, 1, %o0
@@ -93,12 +71,7 @@
 	b		3f
 	 sub		%o0, 1, %o0
 
-ENTRY(strcat)
-	mov		%o0, %g2
-	andcc		%o0, 3, %g0
-	bne		11b
-	 sethi		%hi(0x80808080), %o4
-	or		%o4, %lo(0x80808080), %o3
+30:	or		%o4, %lo(0x80808080), %o3
 7:	sethi		%hi(0x01010101), %o4
 8:	or		%o4, %lo(0x01010101), %o2
 9:	ld		[%o0], %o5
@@ -128,8 +101,39 @@ ENTRY(strcat)
 	 ld		[%o0], %o5
 	sub		%o0, 1, %o0
 3:	andcc		%o1, 3, %o4
-	bne		10b
-4:	 andcc		%o0, 3, %g3
+	be		4f
+	 nop
+
+	cmp		%o4, 2
+	be		11f
+	 cmp		%o4, 3
+	ldub		[%o1], %o5
+	add		%o1, 1, %o1
+	stb		%o5, [%o0]
+	be		13f
+	 cmp		%o5, 0
+	be		0f
+	 add		%o0, 1, %o0
+11:	lduh		[%o1], %o5
+	add		%o1, 2, %o1
+	srl		%o5, 8, %o4
+	cmp		%o4, 0
+	stb		%o4, [%o0]
+	bne,a		12f
+	 stb		%o5, [%o0 + 1]
+	retl
+	 mov		%g2, %o0
+12:	andcc		%o5, 0xff, %o5
+	bne		4f
+	 add		%o0, 2, %o0
+	retl
+	 mov 		%g2, %o0
+13:	bne		4f
+	 add		%o0, 1, %o0
+	retl
+	 mov		%g2, %o0
+
+4:	andcc		%o0, 3, %g3
 	bne		12f
 1:	ld		[%o1], %o5
 	add		%o1, 4, %o1
diff --git a/sysdeps/sparc/sparc32/strchr.S b/sysdeps/sparc/sparc32/strchr.S
index b5be3adf60..7c397171f5 100644
--- a/sysdeps/sparc/sparc32/strchr.S
+++ b/sysdeps/sparc/sparc32/strchr.S
@@ -39,9 +39,20 @@
 
 	.text
 	.align		4
-10:	ldub		[%o0], %g4
+ENTRY(strchr)
+	andcc		%o1, 0xff, %o1
+	be		12f
+	 sll		%o1, 8, %o2
+	andcc		%o0, 3, %g0
+	or		%o1, %o2, %o2
+	sethi		%hi(0x80808080), %o4
+	sll		%o2, 16, %o3
+	be		13f
+	 or		%o3, %o2, %g2
+
+	ldub		[%o0], %g4
 	cmp		%g4, %o1
-	be		1f
+	be		11f
 	 add		%o0, 1, %o0
 	cmp		%g4, 0
 	be		9f
@@ -50,7 +61,7 @@
 	 or		%o4, %lo(0x80808080), %o3
 	ldub		[%o0], %g4
 	cmp		%g4, %o1
-	be		1f
+	be		11f
 	 add		%o0, 1, %o0
 	cmp		%g4, 0
 	be		9f
@@ -59,27 +70,17 @@
 	 sethi		%hi(0x01010101), %o5
 	ldub		[%o0], %g4
 	cmp		%g4, %o1
-	be		1f
+	be		11f
 	 add		%o0, 1, %o0
 	cmp		%g4, 0
 	be		9f
 	 or		%o5, %lo(0x01010101), %o2
 	b		6f
 	 ld		[%o0], %g4
-1:	retl
+11:	retl
 	 sub		%o0, 1, %o0
 
-ENTRY(strchr)
-	andcc		%o1, 0xff, %o1
-	be		12f
-	 sll		%o1, 8, %o2
-	andcc		%o0, 3, %g0
-	or		%o1, %o2, %o2
-	sethi		%hi(0x80808080), %o4
-	sll		%o2, 16, %o3
-	bne		10b
-	 or		%o3, %o2, %g2
-	or		%o4, %lo(0x80808080), %o3
+13:	or		%o4, %lo(0x80808080), %o3
 4:	sethi		%hi(0x01010101), %o5
 5:	or		%o5, %lo(0x01010101), %o2
 7:	ld		[%o0], %g4
@@ -278,7 +279,7 @@ ENTRY(strrchr)
 	 mov		%o5, %o0
 END(strrchr)
 
-weak_alias(strchr, index)
-weak_alias(strrchr, rindex)
+weak_alias (strchr, index)
+weak_alias (strrchr, rindex)
 libc_hidden_builtin_def (strchr)
 libc_hidden_builtin_def (strrchr)
diff --git a/sysdeps/sparc/sparc32/strcmp.S b/sysdeps/sparc/sparc32/strcmp.S
index 6723593eed..cf369dd839 100644
--- a/sysdeps/sparc/sparc32/strcmp.S
+++ b/sysdeps/sparc/sparc32/strcmp.S
@@ -38,7 +38,13 @@
 
 	.text
 	.align		4
-10:	ldub		[%o0], %o4
+
+ENTRY(strcmp)
+	andcc		%o0, 3, %g0
+	be		13f
+	 sethi		%hi(0x80808080), %g1
+
+	ldub		[%o0], %o4
 	add		%o0, 1, %o0
 	ldub		[%o1], %o5
 	cmp		%o4, 0
@@ -76,11 +82,7 @@
 2:	retl
 	 mov		%o4, %o0
 
-ENTRY(strcmp)
-	andcc		%o0, 3, %g0
-	bne		10b
-	 sethi		%hi(0x80808080), %g1
-	or		%g1, %lo(0x80808080), %o3
+13:	or		%g1, %lo(0x80808080), %o3
 4:	sethi		%hi(0x01010101), %g1
 5:	andcc		%o1, 3, %g2
 	bne		12f
diff --git a/sysdeps/sparc/sparc32/strcpy.S b/sysdeps/sparc/sparc32/strcpy.S
index 787ac9f7c8..f3f337e3f7 100644
--- a/sysdeps/sparc/sparc32/strcpy.S
+++ b/sysdeps/sparc/sparc32/strcpy.S
@@ -38,7 +38,14 @@
 
 	.text
 	.align		4
-1:	ldub		[%o1], %o5
+
+ENTRY(strcpy)
+	mov		%o0, %g2
+	andcc		%o1, 3, %g0
+	be		10f
+	 sethi		%hi(0x80808080), %o4
+
+	ldub		[%o1], %o5
 	stb		%o5, [%o0]
 	cmp		%o5, 0
 	add		%o0, 1, %o0
@@ -65,12 +72,7 @@
 	b		6f
 	 andcc		%o0, 3, %g3
 
-ENTRY(strcpy)
-	mov		%o0, %g2
-	andcc		%o1, 3, %g0
-	bne		1b
-	 sethi		%hi(0x80808080), %o4
-	or		%o4, %lo(0x80808080), %o3
+10:	or		%o4, %lo(0x80808080), %o3
 4:	sethi		%hi(0x01010101), %o4
 5:	andcc		%o0, 3, %g3
 6:	bne		10f
diff --git a/sysdeps/sparc/sparc32/strlen.S b/sysdeps/sparc/sparc32/strlen.S
index 76466ec9dd..ed92f20e28 100644
--- a/sysdeps/sparc/sparc32/strlen.S
+++ b/sysdeps/sparc/sparc32/strlen.S
@@ -38,39 +38,41 @@
 
 	.text
 	.align		4
-10:	ldub		[%o0], %o5
+
+ENTRY(strlen)
+	mov		%o0, %o1
+	andcc		%o0, 3, %g0
+	be		20f
+	 sethi		%hi(0x80808080), %o4
+
+	ldub		[%o0], %o5
 	cmp		%o5, 0
-	be		1f
+	be		21f
 	 add		%o0, 1, %o0
 	andcc		%o0, 3, %g0
 	be		4f
 	 or		%o4, %lo(0x80808080), %o3
 	ldub		[%o0], %o5
 	cmp		%o5, 0
-	be		2f
+	be		22f
 	 add		%o0, 1, %o0
 	andcc		%o0, 3, %g0
 	be		5f
 	 sethi		%hi(0x01010101), %o4
 	ldub		[%o0], %o5
 	cmp		%o5, 0
-	be		3f
+	be		23f
 	 add		%o0, 1, %o0
 	b		11f
 	 or		%o4, %lo(0x01010101), %o2
-1:	retl
+21:	retl
 	 mov		0, %o0
-2:	retl
+22:	retl
 	 mov		1, %o0
-3:	retl
+23:	retl
 	 mov		2, %o0
 
-ENTRY(strlen)
-	mov		%o0, %o1
-	andcc		%o0, 3, %g0
-	bne		10b
-	 sethi		%hi(0x80808080), %o4
-	or		%o4, %lo(0x80808080), %o3
+20:	or		%o4, %lo(0x80808080), %o3
 4:	sethi		%hi(0x01010101), %o4
 5:	or		%o4, %lo(0x01010101), %o2
 11:	ld		[%o0], %o5
diff --git a/sysdeps/sparc/sparc64/Dist b/sysdeps/sparc/sparc64/Dist
deleted file mode 100644
index dbf11d5009..0000000000
--- a/sysdeps/sparc/sparc64/Dist
+++ /dev/null
@@ -1 +0,0 @@
-hp-timing.c
diff --git a/sysdeps/sparc/sparc64/Makefile b/sysdeps/sparc/sparc64/Makefile
index 6335984c7d..c1df31727c 100644
--- a/sysdeps/sparc/sparc64/Makefile
+++ b/sysdeps/sparc/sparc64/Makefile
@@ -1,6 +1,3 @@
-# The Sparc `long double' is a distinct type we support.
-long-double-fcts = yes
-
 ifeq ($(subdir),csu)
 sysdep_routines += hp-timing
 elide-routines.os += hp-timing
diff --git a/sysdeps/sparc/sparc64/Versions b/sysdeps/sparc/sparc64/Versions
index 99fe741a12..4cef7bcc71 100644
--- a/sysdeps/sparc/sparc64/Versions
+++ b/sysdeps/sparc/sparc64/Versions
@@ -5,3 +5,10 @@ libc {
     __align_cpy_8; __align_cpy_16;
   }
 }
+libm {
+  GLIBC_2.1 {
+    # A generic bug got this omitted from other configurations' version
+    # sets, but we always had it.
+    exp2l;
+  }
+}
diff --git a/sysdeps/sparc/sparc64/bits/atomic.h b/sysdeps/sparc/sparc64/bits/atomic.h
index 8f97753140..d0a64afce8 100644
--- a/sysdeps/sparc/sparc64/bits/atomic.h
+++ b/sysdeps/sparc/sparc64/bits/atomic.h
@@ -1,5 +1,5 @@
 /* Atomic operations.  sparc64 version.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -59,7 +59,7 @@ typedef uintmax_t uatomic_max_t;
   __asm __volatile ("cas [%4], %2, %0"					      \
 		    : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
 		    : "r" (oldval), "m" (*__acev_mem), "r" (__acev_mem),      \
-		      "0" (newval));					      \
+		      "0" (newval) : "memory");				      \
   __acev_tmp; })
 
 #define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
@@ -69,7 +69,7 @@ typedef uintmax_t uatomic_max_t;
   __asm __volatile ("casx [%4], %2, %0"					      \
 		    : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
 		    : "r" ((long) (oldval)), "m" (*__acev_mem),		      \
-		      "r" (__acev_mem), "0" ((long) (newval)));		      \
+		      "r" (__acev_mem), "0" ((long) (newval)) : "memory");    \
   __acev_tmp; })
 
 #define atomic_exchange_acq(mem, newvalue) \
@@ -80,7 +80,7 @@ typedef uintmax_t uatomic_max_t;
      if (sizeof (*(mem)) == 4)						      \
        __asm ("swap %0, %1"						      \
 	      : "=m" (*__memp), "=r" (__oldval)				      \
-	      : "m" (*__memp), "1" (__value));				      \
+	      : "m" (*__memp), "1" (__value) : "memory");		      \
      else								      \
        {								      \
 	 __val = *__memp;						      \
@@ -94,6 +94,12 @@ typedef uintmax_t uatomic_max_t;
        }								      \
      __oldval; })
 
+#define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
+  atomic_compare_and_exchange_val_acq (mem, newval, oldval)
+
+#define atomic_exchange_24_rel(mem, newval) \
+  atomic_exchange_rel (mem, newval)
+
 #define atomic_full_barrier() \
   __asm __volatile ("membar #LoadLoad | #LoadStore"			      \
 			  " | #StoreLoad | #StoreStore" : : : "memory")
diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h
index 474aa0e6e6..314a784dbc 100644
--- a/sysdeps/sparc/sparc64/dl-machine.h
+++ b/sysdeps/sparc/sparc64/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  Sparc64 version.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
 	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,6 +18,9 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#ifndef dl_machine_h
+#define dl_machine_h
+
 #define ELF_MACHINE_NAME "sparc64"
 
 #include <string.h>
@@ -88,7 +91,7 @@ elf_machine_load_address (void)
 
 /* We have 4 cases to handle.  And we code different code sequences
    for each one.  I love V9 code models...  */
-static inline void
+static inline void __attribute__ ((always_inline))
 sparc64_fixup_plt (struct link_map *map, const Elf64_Rela *reloc,
 		   Elf64_Addr *reloc_addr, Elf64_Addr value,
 		   Elf64_Addr high, int t)
@@ -212,7 +215,7 @@ sparc64_fixup_plt (struct link_map *map, const Elf64_Rela *reloc,
     }
 }
 
-static inline Elf64_Addr
+static inline Elf64_Addr __attribute__ ((always_inline))
 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
 		       const Elf64_Rela *reloc,
 		       Elf64_Addr *reloc_addr, Elf64_Addr value)
@@ -233,236 +236,21 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
   return value;
 }
 
-#ifdef RESOLVE
-
-/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
-   MAP is the object containing the reloc.  */
-
-static inline void
-elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
-		  const Elf64_Sym *sym, const struct r_found_version *version,
-		  void *const reloc_addr_arg)
-{
-  Elf64_Addr *const reloc_addr = reloc_addr_arg;
-  const unsigned long int r_type = ELF64_R_TYPE_ID (reloc->r_info);
-
-#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
-  if (__builtin_expect (r_type == R_SPARC_RELATIVE, 0))
-    *reloc_addr = map->l_addr + reloc->r_addend;
-# ifndef RTLD_BOOTSTRAP
-  else if (r_type == R_SPARC_NONE) /* Who is Wilbur? */
-    return;
-# endif
-  else
-#endif
-    {
-#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
-      const Elf64_Sym *const refsym = sym;
-#endif
-      Elf64_Addr value;
-#ifndef RESOLVE_CONFLICT_FIND_MAP
-      if (sym->st_shndx != SHN_UNDEF &&
-	  ELF64_ST_BIND (sym->st_info) == STB_LOCAL)
-	value = map->l_addr;
-      else
-	{
-	  value = RESOLVE (&sym, version, r_type);
-	  if (sym)
-	    value += sym->st_value;
-	}
-#else
-      value = 0;
-#endif
-      value += reloc->r_addend;	/* Assume copy relocs have zero addend.  */
-
-      switch (r_type)
-	{
-#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
-	case R_SPARC_COPY:
-	  if (sym == NULL)
-	    /* This can happen in trace mode if an object could not be
-	       found.  */
-	    break;
-	  if (sym->st_size > refsym->st_size
-	      || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
-	    {
-	      const char *strtab;
-
-	      strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
-	      _dl_error_printf ("\
-%s: Symbol `%s' has different size in shared object, consider re-linking\n",
-				rtld_progname ?: "<program name unknown>",
-				strtab + refsym->st_name);
-	    }
-	  memcpy (reloc_addr_arg, (void *) value,
-		  MIN (sym->st_size, refsym->st_size));
-	  break;
-#endif
-	case R_SPARC_64:
-	case R_SPARC_GLOB_DAT:
-	  *reloc_addr = value;
-	  break;
-#ifndef RTLD_BOOTSTRAP
-	case R_SPARC_8:
-	  *(char *) reloc_addr = value;
-	  break;
-	case R_SPARC_16:
-	  *(short *) reloc_addr = value;
-	  break;
-	case R_SPARC_32:
-	  *(unsigned int *) reloc_addr = value;
-	  break;
-	case R_SPARC_DISP8:
-	  *(char *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
-	  break;
-	case R_SPARC_DISP16:
-	  *(short *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
-	  break;
-	case R_SPARC_DISP32:
-	  *(unsigned int *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
-	  break;
-	case R_SPARC_WDISP30:
-	  *(unsigned int *) reloc_addr =
-	    ((*(unsigned int *)reloc_addr & 0xc0000000) |
-	     ((value - (Elf64_Addr) reloc_addr) >> 2));
-	  break;
-
-	/* MEDLOW code model relocs */
-	case R_SPARC_LO10:
-	  *(unsigned int *) reloc_addr =
-	    ((*(unsigned int *)reloc_addr & ~0x3ff) |
-	     (value & 0x3ff));
-	  break;
-	case R_SPARC_HI22:
-	  *(unsigned int *) reloc_addr =
-	    ((*(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:
-	  *(unsigned int *) reloc_addr =
-	    ((*(unsigned int *)reloc_addr & 0xffc00000) |
-	     (value >> 22));
-	  break;
-	case R_SPARC_M44:
-	  *(unsigned int *) reloc_addr =
-	    ((*(unsigned int *)reloc_addr & ~0x3ff) |
-	     ((value >> 12) & 0x3ff));
-	  break;
-	case R_SPARC_L44:
-	  *(unsigned int *) reloc_addr =
-	    ((*(unsigned int *)reloc_addr & ~0xfff) |
-	     (value & 0xfff));
-	  break;
-
-	/* MEDANY code model relocs */
-	case R_SPARC_HH22:
-	  *(unsigned int *) reloc_addr =
-	    ((*(unsigned int *)reloc_addr & 0xffc00000) |
-	     (value >> 42));
-	  break;
-	case R_SPARC_HM10:
-	  *(unsigned int *) reloc_addr =
-	    ((*(unsigned int *)reloc_addr & ~0x3ff) |
-	     ((value >> 32) & 0x3ff));
-	  break;
-	case R_SPARC_LM22:
-	  *(unsigned int *) reloc_addr =
-	    ((*(unsigned int *)reloc_addr & 0xffc00000) |
-	     ((value >> 10) & 0x003fffff));
-	  break;
-#endif
-	case R_SPARC_JMP_SLOT:
-#ifdef RESOLVE_CONFLICT_FIND_MAP
-	  /* R_SPARC_JMP_SLOT conflicts against .plt[32768+]
-	     relocs should be turned into R_SPARC_64 relocs
-	     in .gnu.conflict section.
-	     r_addend non-zero does not mean it is a .plt[32768+]
-	     reloc, instead it is the actual address of the function
-	     to call.  */
-	  sparc64_fixup_plt (NULL, reloc, reloc_addr, value, 0, 0);
-#else
-	  sparc64_fixup_plt (map, reloc, reloc_addr, value,
-			     reloc->r_addend, 0);
-#endif
-	  break;
-#ifndef RTLD_BOOTSTRAP
-	case R_SPARC_UA16:
-	  ((unsigned char *) reloc_addr_arg) [0] = value >> 8;
-	  ((unsigned char *) reloc_addr_arg) [1] = value;
-	  break;
-	case R_SPARC_UA32:
-	  ((unsigned char *) reloc_addr_arg) [0] = value >> 24;
-	  ((unsigned char *) reloc_addr_arg) [1] = value >> 16;
-	  ((unsigned char *) reloc_addr_arg) [2] = value >> 8;
-	  ((unsigned char *) reloc_addr_arg) [3] = value;
-	  break;
-	case R_SPARC_UA64:
-	  if (! ((long) reloc_addr_arg & 3))
-	    {
-	      /* Common in .eh_frame */
-	      ((unsigned int *) reloc_addr_arg) [0] = value >> 32;
-	      ((unsigned int *) reloc_addr_arg) [1] = value;
-	      break;
-	    }
-	  ((unsigned char *) reloc_addr_arg) [0] = value >> 56;
-	  ((unsigned char *) reloc_addr_arg) [1] = value >> 48;
-	  ((unsigned char *) reloc_addr_arg) [2] = value >> 40;
-	  ((unsigned char *) reloc_addr_arg) [3] = value >> 32;
-	  ((unsigned char *) reloc_addr_arg) [4] = value >> 24;
-	  ((unsigned char *) reloc_addr_arg) [5] = value >> 16;
-	  ((unsigned char *) reloc_addr_arg) [6] = value >> 8;
-	  ((unsigned char *) reloc_addr_arg) [7] = value;
-	  break;
-#endif
-#if !defined RTLD_BOOTSTRAP || defined _NDEBUG
-	default:
-	  _dl_reloc_bad_type (map, r_type, 0);
-	  break;
-#endif
-	}
-    }
-}
-
-static inline void
-elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
-			   void *const reloc_addr_arg)
-{
-  Elf64_Addr *const reloc_addr = reloc_addr_arg;
-  *reloc_addr = l_addr + reloc->r_addend;
-}
-
-static inline void
-elf_machine_lazy_rel (struct link_map *map,
-		      Elf64_Addr l_addr, const Elf64_Rela *reloc)
-{
-  switch (ELF64_R_TYPE (reloc->r_info))
-    {
-    case R_SPARC_NONE:
-      break;
-    case R_SPARC_JMP_SLOT:
-      break;
-    default:
-      _dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 1);
-      break;
-    }
-}
-
-#endif	/* RESOLVE */
-
 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
    PLT entries should not be allowed to define the value.
    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
    of the main executable's symbols, as for a COPY reloc.  */
-#define elf_machine_type_class(type) \
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+# define elf_machine_type_class(type) \
+  ((((type) == R_SPARC_JMP_SLOT						      \
+     || ((type) >= R_SPARC_TLS_GD_HI22 && (type) <= R_SPARC_TLS_TPOFF64))     \
+    * ELF_RTYPE_CLASS_PLT)						      \
+   | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
+# define elf_machine_type_class(type) \
   ((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)	\
    | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT	R_SPARC_JMP_SLOT
@@ -487,74 +275,67 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
       extern void _dl_runtime_profile_1 (void);
       Elf64_Addr res0_addr, res1_addr;
       unsigned int *plt = (void *) D_PTR (l, l_info[DT_PLTGOT]);
-      int i = 0;
 
-      if (! profile)
-	{
-	  res0_addr = (Elf64_Addr) &_dl_runtime_resolve_0;
-	  res1_addr = (Elf64_Addr) &_dl_runtime_resolve_1;
-	}
-      else
+      if (__builtin_expect(profile, 0))
 	{
 	  res0_addr = (Elf64_Addr) &_dl_runtime_profile_0;
 	  res1_addr = (Elf64_Addr) &_dl_runtime_profile_1;
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    GL(dl_profile_map) = l;
 	}
+      else
+	{
+	  res0_addr = (Elf64_Addr) &_dl_runtime_resolve_0;
+	  res1_addr = (Elf64_Addr) &_dl_runtime_resolve_1;
+	}
 
       /* PLT0 looks like:
 
-	 save	%sp, -192, %sp
-	 sethi	%hh(_dl_runtime_{resolve,profile}_0), %l0
-	 sethi	%lm(_dl_runtime_{resolve,profile}_0), %l1
-	 or	%l0, %hm(_dl_runtime_{resolve,profile}_0), %l0
-	 or	%l1, %lo(_dl_runtime_{resolve,profile}_0), %l1
-	 sllx	%l0, 32, %l0
-	 jmpl	%l0 + %l1, %l6
-	  sethi	%hi(0xffc00), %l2
+         sethi	%uhi(_dl_runtime_{resolve,profile}_0), %g4
+	 sethi	%hi(_dl_runtime_{resolve,profile}_0), %g5
+	 or	%g4, %ulo(_dl_runtime_{resolve,profile}_0), %g4
+	 or	%g5, %lo(_dl_runtime_{resolve,profile}_0), %g5
+	 sllx	%g4, 32, %g4
+	 add	%g4, %g5, %g5
+	 jmpl	%g5, %g4
+	  nop
        */
 
-      plt[0] = 0x9de3bf40;
-      plt[1] = 0x21000000 | (res0_addr >> (64 - 22));
-      plt[2] = 0x23000000 | ((res0_addr >> 10) & 0x003fffff);
-      plt[3] = 0xa0142000 | ((res0_addr >> 32) & 0x3ff);
-      plt[4] = 0xa2146000 | (res0_addr & 0x3ff);
-      plt[5] = 0xa12c3020;
-      plt[6] = 0xadc40011;
-      plt[7] = 0x250003ff;
+      plt[0] = 0x09000000 | (res0_addr >> (64 - 22));
+      plt[1] = 0x0b000000 | ((res0_addr >> 10) & 0x003fffff);
+      plt[2] = 0x88112000 | ((res0_addr >> 32) & 0x3ff);
+      plt[3] = 0x8a116000 | (res0_addr & 0x3ff);
+      plt[4] = 0x89293020;
+      plt[5] = 0x8a010005;
+      plt[6] = 0x89c14000;
+      plt[7] = 0x01000000;
 
       /* PLT1 looks like:
 
-	 save	%sp, -192, %sp
-	 sethi	%hh(_dl_runtime_{resolve,profile}_1), %l0
-	 sethi	%lm(_dl_runtime_{resolve,profile}_1), %l1
-	 or	%l0, %hm(_dl_runtime_{resolve,profile}_1), %l0
-	 or	%l1, %lo(_dl_runtime_{resolve,profile}_1), %l1
-	 sllx	%l0, 32, %l0
-	 jmpl	%l0 + %l1, %l6
-	  srlx	%g1, 12, %o1
+         sethi	%uhi(_dl_runtime_{resolve,profile}_1), %g4
+	 sethi	%hi(_dl_runtime_{resolve,profile}_1), %g5
+	 or	%g4, %ulo(_dl_runtime_{resolve,profile}_1), %g4
+	 or	%g5, %lo(_dl_runtime_{resolve,profile}_1), %g5
+	 sllx	%g4, 32, %g4
+	 add	%g4, %g5, %g5
+	 jmpl	%g5, %g4
+	  nop
        */
 
-      plt[8 + 0] = 0x9de3bf40;
-      if (__builtin_expect (((res1_addr + 4) >> 32) & 0x3ff, 0))
-	i = 1;
-      else
-	res1_addr += 4;
-      plt[8 + 1] = 0x21000000 | (res1_addr >> (64 - 22));
-      plt[8 + 2] = 0x23000000 | ((res1_addr >> 10) & 0x003fffff);
-      if (__builtin_expect (i, 0))
-	plt[8 + 3] = 0xa0142000 | ((res1_addr >> 32) & 0x3ff);
-      else
-	plt[8 + 3] = 0xa12c3020;
-      plt[8 + 4] = 0xa2146000 | (res1_addr & 0x3ff);
-      if (__builtin_expect (i, 0))
-	plt[8 + 5] = 0xa12c3020;
-      plt[8 + 5 + i] = 0xadc40011;
-      plt[8 + 6 + i] = 0x9330700c;
+      plt[8] = 0x09000000 | (res1_addr >> (64 - 22));
+      plt[9] = 0x0b000000 | ((res1_addr >> 10) & 0x003fffff);
+      plt[10] = 0x88112000 | ((res1_addr >> 32) & 0x3ff);
+      plt[11] = 0x8a116000 | (res1_addr & 0x3ff);
+      plt[12] = 0x89293020;
+      plt[13] = 0x8a010005;
+      plt[14] = 0x89c14000;
+      plt[15] = 0x01000000;
 
       /* Now put the magic cookie at the beginning of .PLT2
 	 Entry .PLT3 is unused by this implementation.  */
-      *((struct link_map **)(&plt[16 + 0])) = l;
+      *((struct link_map **)(&plt[16])) = l;
 
       if (__builtin_expect (l->l_info[VALIDX(DT_GNU_PRELINKED)] != NULL, 0)
 	  || __builtin_expect (l->l_info [VALIDX (DT_GNU_LIBLISTSZ)] != NULL, 0))
@@ -601,68 +382,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name)	\
-  asm ("\n"						\
-"	.text\n"					\
-"	.globl	" #tramp_name "_0\n"			\
-"	.type	" #tramp_name "_0, @function\n"		\
-"	.align	32\n"					\
-"\t" #tramp_name "_0:\n"				\
-"	! sethi   %hi(1047552), %l2 - Done in .PLT0\n"	\
-"	ldx	[%l6 + 32 + 8], %o0\n"			\
-"	sub     %g1, %l6, %l0\n"			\
-"	xor     %l2, -1016, %l2\n"			\
-"	sethi   %hi(5120), %l3	! 160 * 32\n"		\
-"	add     %l0, %l2, %l0\n"			\
-"	sethi   %hi(32768), %l4\n"			\
-"	udivx   %l0, %l3, %l3\n"			\
-"	sllx    %l3, 2, %l1\n"				\
-"	add     %l1, %l3, %l1\n"			\
-"	sllx    %l1, 10, %l2\n"				\
-"	sub	%l4, 4, %l4	! No thanks to Sun for not obeying their own ABI\n" \
-"	sllx    %l1, 5, %l1\n"				\
-"	sub     %l0, %l2, %l0\n"			\
-"	udivx   %l0, 24, %l0\n"				\
-"	add     %l0, %l4, %l0\n"			\
-"	add     %l1, %l0, %l1\n"			\
-"	add     %l1, %l1, %l0\n"			\
-"	add     %l0, %l1, %l0\n"			\
-"	mov	%i7, %o2\n"				\
-"	call	" #fixup_name "\n"			\
-"	 sllx    %l0, 3, %o1\n"				\
-"	jmp	%o0\n"					\
-"	 restore\n"					\
-"	.size	" #tramp_name "_0, . - " #tramp_name "_0\n" \
-"\n"							\
-"	.globl	" #tramp_name "_1\n"			\
-"	.type	" #tramp_name "_1, @function\n"		\
-"	! tramp_name_1 + 4 needs to be .align 32\n"	\
-"\t" #tramp_name "_1:\n"				\
-"	sub	%l6, 4, %l6\n"				\
-"	! srlx	%g1, 12, %o1 - Done in .PLT1\n"		\
-"	ldx	[%l6 + 12], %o0\n"			\
-"	add	%o1, %o1, %o3\n"			\
-"	sub	%o1, 96, %o1	! No thanks to Sun for not obeying their own ABI\n" \
-"	mov	%i7, %o2\n"				\
-"	call	" #fixup_name "\n"			\
-"	 add	%o1, %o3, %o1\n"			\
-"	jmp	%o0\n"					\
-"	 restore\n"					\
-"	.size	" #tramp_name "_1, . - " #tramp_name "_1\n" \
-"	.previous\n");
-
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE			\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);	\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE			\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);	\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, fixup);
-#endif
-
 /* The PLT uses Elf64_Rela relocs.  */
 #define elf_machine_relplt elf_machine_rela
 
@@ -763,3 +482,291 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 "	 add	%sp, 6*8, %sp\n"					\
 "	.size	_dl_start_user, . - _dl_start_user\n"			\
 "	.previous\n");
+
+#endif /* dl_machine_h */
+
+#define ARCH_LA_PLTENTER	sparc64_gnu_pltenter
+#define ARCH_LA_PLTEXIT		sparc64_gnu_pltexit
+
+#ifdef RESOLVE_MAP
+
+/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
+   MAP is the object containing the reloc.  */
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
+		  const Elf64_Sym *sym, const struct r_found_version *version,
+		  void *const reloc_addr_arg)
+{
+  Elf64_Addr *const reloc_addr = reloc_addr_arg;
+#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
+  const Elf64_Sym *const refsym = sym;
+#endif
+  Elf64_Addr value;
+  const unsigned long int r_type = ELF64_R_TYPE_ID (reloc->r_info);
+#if !defined RESOLVE_CONFLICT_FIND_MAP
+  struct link_map *sym_map = NULL;
+#endif
+
+#if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+  /* This is defined in rtld.c, but nowhere in the static libc.a; make the
+     reference weak so static programs can still link.  This declaration
+     cannot be done when compiling rtld.c (i.e.  #ifdef RTLD_BOOTSTRAP)
+     because rtld.c contains the common defn for _dl_rtld_map, which is
+     incompatible with a weak decl in the same file.  */
+  weak_extern (_dl_rtld_map);
+#endif
+
+  if (__builtin_expect (r_type == R_SPARC_NONE, 0))
+    return;
+
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
+  if (__builtin_expect (r_type == R_SPARC_RELATIVE, 0))
+    {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+      if (map != &_dl_rtld_map) /* Already done in rtld itself. */
+# endif
+	*reloc_addr += map->l_addr + reloc->r_addend;
+      return;
+    }
+#endif
+
+#ifndef RESOLVE_CONFLICT_FIND_MAP
+  if (__builtin_expect (ELF64_ST_BIND (sym->st_info) == STB_LOCAL, 0)
+      && sym->st_shndx != SHN_UNDEF)
+    {
+      value = map->l_addr;
+    }
+  else
+    {
+      sym_map = RESOLVE_MAP (&sym, version, r_type);
+      value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
+    }
+#else
+  value = 0;
+#endif
+
+  value += reloc->r_addend;	/* Assume copy relocs have zero addend.  */
+
+  switch (r_type)
+    {
+#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
+    case R_SPARC_COPY:
+      if (sym == NULL)
+	/* This can happen in trace mode if an object could not be
+	   found.  */
+	break;
+      if (sym->st_size > refsym->st_size
+	  || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
+	{
+	  const char *strtab;
+
+	  strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+	  _dl_error_printf ("\
+%s: Symbol `%s' has different size in shared object, consider re-linking\n",
+			    rtld_progname ?: "<program name unknown>",
+			    strtab + refsym->st_name);
+	}
+      memcpy (reloc_addr_arg, (void *) value,
+	      MIN (sym->st_size, refsym->st_size));
+      break;
+#endif
+    case R_SPARC_64:
+    case R_SPARC_GLOB_DAT:
+      *reloc_addr = value;
+      break;
+    case R_SPARC_JMP_SLOT:
+#ifdef RESOLVE_CONFLICT_FIND_MAP
+      /* R_SPARC_JMP_SLOT conflicts against .plt[32768+]
+	 relocs should be turned into R_SPARC_64 relocs
+	 in .gnu.conflict section.
+	 r_addend non-zero does not mean it is a .plt[32768+]
+	 reloc, instead it is the actual address of the function
+	 to call.  */
+      sparc64_fixup_plt (NULL, reloc, reloc_addr, value, 0, 0);
+#else
+      sparc64_fixup_plt (map, reloc, reloc_addr, value, reloc->r_addend, 0);
+#endif
+      break;
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) \
+    && !defined RESOLVE_CONFLICT_FIND_MAP
+    case R_SPARC_TLS_DTPMOD64:
+      /* Get the information from the link map returned by the
+	 resolv function.  */
+      if (sym_map != NULL)
+	*reloc_addr = sym_map->l_tls_modid;
+      break;
+    case R_SPARC_TLS_DTPOFF64:
+      /* During relocation all TLS symbols are defined and used.
+	 Therefore the offset is already correct.  */
+      *reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
+      break;
+    case R_SPARC_TLS_TPOFF64:
+      /* The offset is negative, forward from the thread pointer.  */
+      /* We know the offset of object the symbol is contained in.
+	 It is a negative value which will be added to the
+	 thread pointer.  */
+      if (sym != NULL)
+	{
+	  CHECK_STATIC_TLS (map, sym_map);
+	  *reloc_addr = sym->st_value - sym_map->l_tls_offset
+	    + reloc->r_addend;
+	}
+      break;
+# ifndef RTLD_BOOTSTRAP
+    case R_SPARC_TLS_LE_HIX22:
+    case R_SPARC_TLS_LE_LOX10:
+      if (sym != NULL)
+	{
+	  CHECK_STATIC_TLS (map, sym_map);
+	  value = sym->st_value - sym_map->l_tls_offset
+	    + reloc->r_addend;
+	  if (r_type == R_SPARC_TLS_LE_HIX22)
+	    *reloc_addr = (*reloc_addr & 0xffc00000)
+	      | (((~value) >> 10) & 0x3fffff);
+	  else
+	    *reloc_addr = (*reloc_addr & 0xffffe000) | (value & 0x3ff)
+	      | 0x1c00;
+	}
+      break;
+# endif
+#endif
+#ifndef RTLD_BOOTSTRAP
+    case R_SPARC_8:
+      *(char *) reloc_addr = value;
+      break;
+    case R_SPARC_16:
+      *(short *) reloc_addr = value;
+      break;
+    case R_SPARC_32:
+      *(unsigned int *) reloc_addr = value;
+      break;
+    case R_SPARC_DISP8:
+      *(char *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
+      break;
+    case R_SPARC_DISP16:
+      *(short *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
+      break;
+    case R_SPARC_DISP32:
+      *(unsigned int *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
+      break;
+    case R_SPARC_WDISP30:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & 0xc0000000) |
+	 (((value - (Elf64_Addr) reloc_addr) >> 2) & 0x3fffffff));
+      break;
+
+      /* MEDLOW code model relocs */
+    case R_SPARC_LO10:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & ~0x3ff) |
+	 (value & 0x3ff));
+      break;
+    case R_SPARC_HI22:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & 0xffc00000) |
+	 ((value >> 10) & 0x3fffff));
+      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:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & 0xffc00000) |
+	 ((value >> 22) & 0x3fffff));
+      break;
+    case R_SPARC_M44:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & ~0x3ff) |
+	 ((value >> 12) & 0x3ff));
+      break;
+    case R_SPARC_L44:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & ~0xfff) |
+	 (value & 0xfff));
+      break;
+
+      /* MEDANY code model relocs */
+    case R_SPARC_HH22:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & 0xffc00000) |
+	 (value >> 42));
+      break;
+    case R_SPARC_HM10:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & ~0x3ff) |
+	 ((value >> 32) & 0x3ff));
+      break;
+    case R_SPARC_LM22:
+      *(unsigned int *) reloc_addr =
+	((*(unsigned int *)reloc_addr & 0xffc00000) |
+	 ((value >> 10) & 0x003fffff));
+      break;
+    case R_SPARC_UA16:
+      ((unsigned char *) reloc_addr_arg) [0] = value >> 8;
+      ((unsigned char *) reloc_addr_arg) [1] = value;
+      break;
+    case R_SPARC_UA32:
+      ((unsigned char *) reloc_addr_arg) [0] = value >> 24;
+      ((unsigned char *) reloc_addr_arg) [1] = value >> 16;
+      ((unsigned char *) reloc_addr_arg) [2] = value >> 8;
+      ((unsigned char *) reloc_addr_arg) [3] = value;
+      break;
+    case R_SPARC_UA64:
+      if (! ((long) reloc_addr_arg & 3))
+	{
+	  /* Common in .eh_frame */
+	  ((unsigned int *) reloc_addr_arg) [0] = value >> 32;
+	  ((unsigned int *) reloc_addr_arg) [1] = value;
+	  break;
+	}
+      ((unsigned char *) reloc_addr_arg) [0] = value >> 56;
+      ((unsigned char *) reloc_addr_arg) [1] = value >> 48;
+      ((unsigned char *) reloc_addr_arg) [2] = value >> 40;
+      ((unsigned char *) reloc_addr_arg) [3] = value >> 32;
+      ((unsigned char *) reloc_addr_arg) [4] = value >> 24;
+      ((unsigned char *) reloc_addr_arg) [5] = value >> 16;
+      ((unsigned char *) reloc_addr_arg) [6] = value >> 8;
+      ((unsigned char *) reloc_addr_arg) [7] = value;
+      break;
+#endif
+#if !defined RTLD_BOOTSTRAP || defined _NDEBUG
+    default:
+      _dl_reloc_bad_type (map, r_type, 0);
+      break;
+#endif
+    }
+}
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
+			   void *const reloc_addr_arg)
+{
+  Elf64_Addr *const reloc_addr = reloc_addr_arg;
+  *reloc_addr = l_addr + reloc->r_addend;
+}
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_lazy_rel (struct link_map *map,
+		      Elf64_Addr l_addr, const Elf64_Rela *reloc)
+{
+  switch (ELF64_R_TYPE (reloc->r_info))
+    {
+    case R_SPARC_NONE:
+      break;
+    case R_SPARC_JMP_SLOT:
+      break;
+    default:
+      _dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 1);
+      break;
+    }
+}
+
+#endif	/* RESOLVE_MAP */
diff --git a/sysdeps/sparc/sparc64/dl-trampoline.S b/sysdeps/sparc/sparc64/dl-trampoline.S
new file mode 100644
index 0000000000..81e5c556c3
--- /dev/null
+++ b/sysdeps/sparc/sparc64/dl-trampoline.S
@@ -0,0 +1,327 @@
+/* PLT trampolines.  Sparc 64-bit version.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+	.text
+	.align	32
+
+	/* %g1:	PLT offset loaded by PLT entry
+	 * %g4: callers PC, which is PLT0 + 24, therefore we
+	 *      add (32 + 8) to get the address of PLT2 which
+	 *      is where the magic cookie is stored
+	 */
+	.globl	_dl_runtime_resolve_0
+	.type	_dl_runtime_resolve_0, @function
+_dl_runtime_resolve_0:
+	cfi_startproc
+
+	save	%sp, -192, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+	cfi_register(%o7, %i7)
+
+	sethi   %hi(1047552), %l2
+	ldx	[%g4 + 32 + 8], %o0
+	sub     %g1, %g4, %l0
+	xor     %l2, -1016, %l2
+	sethi   %hi(5120), %l3	/* 160 * 32 */
+	add     %l0, %l2, %l0
+	sethi   %hi(32768), %l4
+	udivx   %l0, %l3, %l3
+	sllx    %l3, 2, %l1
+	add     %l1, %l3, %l1
+	sllx    %l1, 10, %l2
+	sub	%l4, 4, %l4
+	sllx    %l1, 5, %l1
+	sub     %l0, %l2, %l0
+	udivx   %l0, 24, %l0
+	add     %l0, %l4, %l0
+	add     %l1, %l0, %l1
+	add     %l1, %l1, %l0
+	add     %l0, %l1, %l0
+	call	_dl_fixup
+	 sllx    %l0, 3, %o1
+	jmp	%o0
+	 restore
+
+	cfi_endproc
+
+	.size	_dl_runtime_resolve_0, .-_dl_runtime_resolve_0
+
+	/* %g1:	PLT offset loaded by PLT entry
+	 * %g4: callers PC, which is PLT1 + 24, therefore we
+	 *      add 8 to get the address of PLT2 which
+	 *      is where the magic cookie is stored
+	 */
+	.globl	_dl_runtime_resolve_1
+	.type	_dl_runtime_resolve_1, @function
+_dl_runtime_resolve_1:
+	cfi_startproc
+
+	save	%sp, -192, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+	cfi_register(%o7, %i7)
+
+	srlx	%g1, 12, %o1
+	ldx	[%g4 + 8], %o0
+	add	%o1, %o1, %o3
+	sub	%o1, 96, %o1
+	call	_dl_fixup
+	 add	%o1, %o3, %o1
+	jmp	%o0
+	 restore
+
+	cfi_endproc
+
+	.size	_dl_runtime_resolve_1, .-_dl_runtime_resolve_1
+
+	/* For the profiling cases we pass in our stack frame
+	 * as the base of the La_sparc64_regs, so it looks
+	 * like:
+	 *	%l0			%sp
+	 *	...
+	 *	%l7			%sp + (7 * 8)
+	 *	%i0			%sp + (8 * 8)
+	 *	...
+	 *	%i7			%sp + (15 * 8)
+	 *	%f0			%sp + (16 * 8)
+	 *	%f16			%sp + (31 * 8)
+	 *	framesize		%sp + (32 * 8)
+	 */
+
+	.globl	_dl_profile_save_regs
+	.type	_dl_profile_save_regs, @function
+_dl_profile_save_regs:
+	cfi_startproc
+
+	stx	%l0, [%sp + STACK_BIAS + ( 0 * 8)]
+	stx	%l1, [%sp + STACK_BIAS + ( 1 * 8)]
+	stx	%l2, [%sp + STACK_BIAS + ( 2 * 8)]
+	stx	%l3, [%sp + STACK_BIAS + ( 3 * 8)]
+	stx	%l4, [%sp + STACK_BIAS + ( 4 * 8)]
+	stx	%l5, [%sp + STACK_BIAS + ( 5 * 8)]
+	stx	%l6, [%sp + STACK_BIAS + ( 6 * 8)]
+	stx	%l7, [%sp + STACK_BIAS + ( 7 * 8)]
+	stx	%i0, [%sp + STACK_BIAS + ( 8 * 8)]
+	stx	%i1, [%sp + STACK_BIAS + ( 9 * 8)]
+	stx	%i2, [%sp + STACK_BIAS + (10 * 8)]
+	stx	%i3, [%sp + STACK_BIAS + (11 * 8)]
+	stx	%i4, [%sp + STACK_BIAS + (12 * 8)]
+	stx	%i5, [%sp + STACK_BIAS + (13 * 8)]
+	stx	%i6, [%sp + STACK_BIAS + (14 * 8)]
+	stx	%i7, [%sp + STACK_BIAS + (15 * 8)]
+	std	%f0, [%sp + STACK_BIAS + (16 * 8)]
+	std	%f2, [%sp + STACK_BIAS + (17 * 8)]
+	std	%f4, [%sp + STACK_BIAS + (18 * 8)]
+	std	%f6, [%sp + STACK_BIAS + (19 * 8)]
+	std	%f8, [%sp + STACK_BIAS + (20 * 8)]
+	std	%f10, [%sp + STACK_BIAS + (21 * 8)]
+	std	%f12, [%sp + STACK_BIAS + (22 * 8)]
+	std	%f14, [%sp + STACK_BIAS + (23 * 8)]
+	std	%f16, [%sp + STACK_BIAS + (24 * 8)]
+	std	%f18, [%sp + STACK_BIAS + (25 * 8)]
+	std	%f20, [%sp + STACK_BIAS + (26 * 8)]
+	std	%f22, [%sp + STACK_BIAS + (27 * 8)]
+	std	%f24, [%sp + STACK_BIAS + (28 * 8)]
+	std	%f26, [%sp + STACK_BIAS + (29 * 8)]
+	std	%f28, [%sp + STACK_BIAS + (30 * 8)]
+	retl
+	 std	%f30, [%sp + STACK_BIAS + (31 * 8)]
+
+	cfi_endproc
+
+	.size	_dl_profile_save_regs, .-_dl_profile_save_regs
+
+	/* If we are going to call pltexit, then we must replicate
+	 * the caller's stack frame.
+	 * %o0: PLT resolved function address
+	 */
+	.globl	_dl_profile_invoke
+	.type	_dl_profile_invoke, @function
+_dl_profile_invoke:
+	cfi_startproc
+
+	sub	%sp, %l0, %sp
+1:
+	srlx	%l0, 3, %l7
+	mov	%o0, %l1
+	mov	%i0, %o0
+	mov	%i1, %o1
+	mov	%i2, %o2
+	mov	%i3, %o3
+	mov	%i4, %o4
+	mov	%i5, %o5
+	add	%fp, STACK_BIAS, %l2
+	add	%sp, STACK_BIAS, %l3
+1:	ldx	[%l2], %l4
+	add	%l2, 0x8, %l2
+	subcc	%l7, 1, %l7
+	stx	%l4, [%l3]
+	bne,pt	%xcc, 1b
+	 add	%l3, 0x8, %l3
+
+	jmpl	%l1, %o7
+	 nop
+
+	stx	%o0, [%sp + STACK_BIAS + (16 * 8)]
+	stx	%o1, [%sp + STACK_BIAS + (17 * 8)]
+	stx	%o2, [%sp + STACK_BIAS + (18 * 8)]
+	stx	%o3, [%sp + STACK_BIAS + (19 * 8)]
+	std	%f0, [%sp + STACK_BIAS + (20 * 8)]
+	std	%f2, [%sp + STACK_BIAS + (21 * 8)]
+	std	%f4, [%sp + STACK_BIAS + (22 * 8)]
+	std	%f8, [%sp + STACK_BIAS + (23 * 8)]
+
+	mov	%l5, %o0
+	mov	%l6, %o1
+	add	%sp, %l0, %o2
+	add	%sp, STACK_BIAS + (16 * 8), %o3
+	call	_dl_call_pltexit
+	 add	%o2, STACK_BIAS, %o2
+
+	ldx	[%sp + STACK_BIAS + (16 * 8)], %i0
+	ldx	[%sp + STACK_BIAS + (17 * 8)], %i1
+	ldx	[%sp + STACK_BIAS + (18 * 8)], %i2
+	ldx	[%sp + STACK_BIAS + (19 * 8)], %i3
+
+	jmpl	%i7 + 8, %g0
+	 restore
+
+	cfi_endproc
+
+	.size	_dl_profile_invoke, .-_dl_profile_invoke
+
+	/* %g1:	PLT offset loaded by PLT entry
+	 * %g4: callers PC, which is PLT0 + 24, therefore we
+	 *      add (32 + 8) to get the address of PLT2 which
+	 *      is where the magic cookie is stored
+	 */
+	.align	32
+	.globl	_dl_runtime_profile_0
+	.type	_dl_runtime_profile_0, @function
+_dl_runtime_profile_0:
+	cfi_startproc
+
+	brz,a,pn %fp, 1f
+	 mov	192, %g5
+	sub	%fp, %sp, %g5
+1:	save	%sp, -336, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+	cfi_register(%o7, %i7)
+
+	sethi   %hi(1047552), %l2
+	ldx	[%g4 + 32 + 8], %o0
+	sub     %g1, %g4, %l0
+	xor     %l2, -1016, %l2
+	sethi   %hi(5120), %l3	/* 160 * 32 */
+	add     %l0, %l2, %l0
+	sethi   %hi(32768), %l4
+	udivx   %l0, %l3, %l3
+	sllx    %l3, 2, %l1
+	add     %l1, %l3, %l1
+	sllx    %l1, 10, %l2
+	sub	%l4, 4, %l4
+	sllx    %l1, 5, %l1
+	sub     %l0, %l2, %l0
+	udivx   %l0, 24, %l0
+	add     %l0, %l4, %l0
+	add     %l1, %l0, %l1
+	add     %l1, %l1, %l0
+	add     %l0, %l1, %l0
+
+	mov	%i7, %o2
+	sllx    %l0, 3, %o1
+
+	mov	%g5, %l0
+	mov	%o0, %l5
+	mov	%o1, %l6
+
+	call	_dl_profile_save_regs
+	 nop
+
+	add	%sp, STACK_BIAS, %o3
+	call	_dl_profile_fixup
+	 add	%sp, (STACK_BIAS + (32 * 8)), %o4
+
+	ldx	[%sp + STACK_BIAS + (32 * 8)], %o1
+	brgez,pt %o1, 1f
+	 nop
+
+	call	_dl_profile_invoke
+	 nop
+
+1:	jmp	%o0
+	 restore
+
+	cfi_endproc
+
+	.size	_dl_runtime_profile_0, .-_dl_runtime_profile_0
+
+	/* %g1:	PLT offset loaded by PLT entry
+	 * %g4: callers PC, which is PLT1 + 24, therefore we
+	 *      add 8 to get the address of PLT2 which
+	 *      is where the magic cookie is stored
+	 */
+	.globl	_dl_runtime_profile_1
+	.type	_dl_runtime_profile_1, @function
+_dl_runtime_profile_1:
+	cfi_startproc
+
+	brz,a,pn %fp, 1f
+	 mov	192, %g5
+	sub	%fp, %sp, %g5
+1:	save	%sp, -336, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+	cfi_register(%o7, %i7)
+
+	srlx	%g1, 12, %o1
+	ldx	[%g4 + 8], %o0
+	add	%o1, %o1, %o3
+	sub	%o1, 96, %o1
+	mov	%i7, %o2
+	add	%o1, %o3, %o1
+
+	mov	%g5, %l0
+	mov	%o0, %l5
+	mov	%o1, %l6
+
+	call	_dl_profile_save_regs
+	 nop
+
+	add	%sp, STACK_BIAS, %o3
+	call	_dl_profile_fixup
+	 add	%sp, (STACK_BIAS + (32 * 8)), %o4
+
+	ldx	[%sp + STACK_BIAS + (32 * 8)], %o1
+	brgez,pt %o1, 1f
+	 nop
+
+	call	_dl_profile_invoke
+	 nop
+
+1:	jmp	%o0
+	 restore
+
+	cfi_endproc
+
+	.size	_dl_runtime_resolve_1, .-_dl_runtime_resolve_1
diff --git a/sysdeps/sparc/sparc64/elf/start.S b/sysdeps/sparc/sparc64/elf/start.S
index b0ef9d355d..df44cae068 100644
--- a/sysdeps/sparc/sparc64/elf/start.S
+++ b/sysdeps/sparc/sparc64/elf/start.S
@@ -48,6 +48,7 @@
 	.global _start
 	.type _start,#function
 _start:
+	cfi_startproc
 
 #ifdef SHARED
 	sethi	%hi(_GLOBAL_OFFSET_TABLE_-4), %l7
@@ -59,6 +60,7 @@ _start:
      drop their arguments.  */
 	mov	%g0, %fp
 	sub	%sp, 6*8, %sp
+	cfi_adjust_cfa_offset(6*8)
 
   /* Extract the arguments and environment as encoded on the stack.  The
      argument info starts after one register window (16 words) past the SP,
@@ -92,4 +94,12 @@ _start:
   /* Die very horribly if exit returns.  */
 	illtrap	0
 
+	cfi_endproc
+
 	.size _start, .-_start
+
+/* Define a symbol for the first piece of initialized data.  */
+	.data
+	.globl	__data_start
+__data_start:
+weak_alias (__data_start, data_start)
diff --git a/sysdeps/sparc/sparc64/fpu/libm-test-ulps b/sysdeps/sparc/sparc64/fpu/libm-test-ulps
index 4888dd2149..db5543e9eb 100644
--- a/sysdeps/sparc/sparc64/fpu/libm-test-ulps
+++ b/sysdeps/sparc/sparc64/fpu/libm-test-ulps
@@ -33,14 +33,14 @@ ildouble: 1
 ldouble: 1
 
 # cacosh
-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
 double: 1
 float: 7
 idouble: 1
 ifloat: 7
 ildouble: 5
 ldouble: 5
-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
 double: 1
 float: 3
 idouble: 1
@@ -465,6 +465,11 @@ ifloat: 2
 ildouble: 1
 ldouble: 1
 
+# exp2
+Test "exp2 (10) == 1024":
+ildouble: 2
+ldouble: 2
+
 # expm1
 Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
 double: 1
@@ -1192,6 +1197,10 @@ ifloat: 2
 ildouble: 1
 ldouble: 1
 
+Function: "exp2":
+ildouble: 2
+ldouble: 2
+
 Function: "expm1":
 double: 1
 float: 1
diff --git a/sysdeps/sparc/sparc64/jmpbuf-unwind.h b/sysdeps/sparc/sparc64/jmpbuf-unwind.h
new file mode 100644
index 0000000000..f7eed15ea1
--- /dev/null
+++ b/sysdeps/sparc/sparc64/jmpbuf-unwind.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by David S. Miller <davem@davemloft.net>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <setjmp.h>
+#include <stdint.h>
+#include <unwind.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+   containing a local variable at ADDRESS.  */
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle)			\
+  ((unsigned long int) (address) < (jmpbuf)->uc_mcontext.mc_fp + 2047)
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+  ((uintptr_t) (_address) - (_adj) \
+   < (uintptr_t) (_jmpbuf)[0].uc_mcontext.mc_fp + 2047 - (_adj))
+
+/* We use the normal lobngjmp for unwinding.  */
+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
diff --git a/sysdeps/sparc/sparc64/memcmp.S b/sysdeps/sparc/sparc64/memcmp.S
index 074767b983..f9502d63f5 100644
--- a/sysdeps/sparc/sparc64/memcmp.S
+++ b/sysdeps/sparc/sparc64/memcmp.S
@@ -139,5 +139,5 @@ ENTRY(memcmp)
 END(memcmp)
 
 #undef bcmp
-weak_alias(memcmp, bcmp)
+weak_alias (memcmp, bcmp)
 libc_hidden_builtin_def (memcmp)
diff --git a/sysdeps/sparc/sparc64/memcpy.S b/sysdeps/sparc/sparc64/memcpy.S
index 3742573248..5993358017 100644
--- a/sysdeps/sparc/sparc64/memcpy.S
+++ b/sysdeps/sparc/sparc64/memcpy.S
@@ -209,6 +209,7 @@ ENTRY(bcopy)
 END(bcopy)
 
 	.align		32
+ENTRY(__memcpy_large)
 200:	be,pt		%xcc, 201f			/* CTI				*/
 	 andcc		%o0, 0x38, %g5			/* IEU1		Group		*/
 	mov		8, %g1				/* IEU0				*/
@@ -443,6 +444,7 @@ END(bcopy)
 	 stb		%o5, [%o0 - 1]			/* Store			*/
 209:	retl
 	 mov		%g4, %o0
+END(__memcpy_large)
 
 #ifdef USE_BPR
 
@@ -698,6 +700,7 @@ ENTRY(memcpy)
 END(memcpy)
 
 	.align		32
+ENTRY(__memmove_slowpath)
 228:	andcc		%o2, 1, %g0			/* IEU1		Group		*/
 	be,pt		%icc, 2f+4			/* CTI				*/
 1:	 ldub		[%o1 - 1], %o5			/* LOAD		Group		*/
@@ -718,6 +721,7 @@ END(memcpy)
 	 mov		%g4, %o0
 219:	retl
 	 nop
+END(__memmove_slowpath)
 
 	.align		32
 ENTRY(memmove)
@@ -914,8 +918,8 @@ ENTRY(memmove)
 END(memmove)
 
 #ifdef USE_BPR
-weak_alias(memcpy, __align_cpy_1)
-weak_alias(memcpy, __align_cpy_2)
+weak_alias (memcpy, __align_cpy_1)
+weak_alias (memcpy, __align_cpy_2)
 #endif
 libc_hidden_builtin_def (memcpy)
 libc_hidden_builtin_def (memmove)
diff --git a/sysdeps/sparc/sparc64/memset.S b/sysdeps/sparc/sparc64/memset.S
index b34ccc8869..99624ba9d7 100644
--- a/sysdeps/sparc/sparc64/memset.S
+++ b/sysdeps/sparc/sparc64/memset.S
@@ -312,4 +312,4 @@ ENTRY(__bzero)
 	 mov		%o5, %o0
 END(__bzero)
 
-weak_alias(__bzero, bzero)
+weak_alias (__bzero, bzero)
diff --git a/sysdeps/sparc/sparc64/soft-fp/Dist b/sysdeps/sparc/sparc64/soft-fp/Dist
deleted file mode 100644
index f98d85f7c2..0000000000
--- a/sysdeps/sparc/sparc64/soft-fp/Dist
+++ /dev/null
@@ -1,32 +0,0 @@
-qp_add.c
-qp_cmp.c
-qp_cmpe.c
-qp_div.c
-qp_dtoq.c
-qp_feq.c
-qp_fge.c
-qp_fgt.c
-qp_fle.c
-qp_flt.c
-qp_fne.c
-qp_itoq.c
-qp_mul.c
-qp_neg.S
-qp_qtod.c
-qp_qtoi.c
-qp_qtos.c
-qp_qtoui.c
-qp_qtoux.c
-qp_qtox.c
-qp_sqrt.c
-qp_stoq.c
-qp_sub.c
-qp_uitoq.c
-qp_util.c
-qp_uxtoq.c
-qp_xtoq.c
-s_frexpl.c
-s_ilogbl.c
-s_scalblnl.c
-s_scalbnl.c
-sfp-machine.h
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_add.c b/sysdeps/sparc/sparc64/soft-fp/qp_add.c
index bcfd0ff281..eced23fad8 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_add.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_add.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    (*c) = (*a) + (*b)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,10 +29,10 @@ void _Qp_add(long double *c, const long double *a, const long double *b)
   FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(C);
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_QP(A, a);
-  FP_UNPACK_QP(B, b);
+  FP_UNPACK_SEMIRAW_QP(A, a);
+  FP_UNPACK_SEMIRAW_QP(B, b);
   FP_ADD_Q(C, A, B);
-  FP_PACK_QP(c, C);
+  FP_PACK_SEMIRAW_QP(c, C);
   QP_HANDLE_EXCEPTIONS(__asm (
 "	ldd [%1], %%f52\n"
 "	ldd [%1+8], %%f54\n"
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_dtoq.c b/sysdeps/sparc/sparc64/soft-fp/qp_dtoq.c
index 9ba2fac9ce..63f3d742aa 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_dtoq.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_dtoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    (*c) = (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,13 +31,13 @@ void _Qp_dtoq(long double *c, const double a)
   FP_DECL_Q(C);
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_D(A, a);
+  FP_UNPACK_RAW_D(A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
-  FP_CONV(Q,D,4,2,C,A);
+  FP_EXTEND(Q,D,4,2,C,A);
 #else
-  FP_CONV(Q,D,2,1,C,A);
+  FP_EXTEND(Q,D,2,1,C,A);
 #endif
-  FP_PACK_QP(c, C);
+  FP_PACK_RAW_QP(c, C);
   QP_HANDLE_EXCEPTIONS(__asm (
 "	fdtoq %1, %%f60\n"
 "	std %%f60, [%0]\n"
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_itoq.c b/sysdeps/sparc/sparc64/soft-fp/qp_itoq.c
index dd28b6a56e..310d70c77a 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_itoq.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_itoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    (*c) = (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,7 +29,7 @@ void _Qp_itoq(long double *c, const int a)
   FP_DECL_Q(C);
   int b = a;
 
-  FP_FROM_INT_Q(C, b, 32, int);
-  FP_PACK_QP(c, C);
+  FP_FROM_INT_Q(C, b, 32, unsigned int);
+  FP_PACK_RAW_QP(c, C);
   QP_NO_EXCEPTIONS;
 }
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_qtod.c b/sysdeps/sparc/sparc64/soft-fp/qp_qtod.c
index c86967a5d4..2e5edadcb7 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_qtod.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_qtod.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (double)(*a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ double _Qp_qtod(const long double *a)
   double r;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_QP(A, a);
+  FP_UNPACK_SEMIRAW_QP(A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
-  FP_CONV(D,Q,2,4,R,A);
+  FP_TRUNC(D,Q,2,4,R,A);
 #else
-  FP_CONV(D,Q,1,2,R,A);
+  FP_TRUNC(D,Q,1,2,R,A);
 #endif
-  FP_PACK_D(r, R);
+  FP_PACK_SEMIRAW_D(r, R);
   QP_HANDLE_EXCEPTIONS(__asm (
 "	ldd [%1], %%f52\n"
 "	ldd [%1+8], %%f54\n"
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_qtoi.c b/sysdeps/sparc/sparc64/soft-fp/qp_qtoi.c
index cf8aba73c6..a40253654a 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_qtoi.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_qtoi.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (int)(*a)
-   Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -28,10 +28,10 @@ int _Qp_qtoi(const long double *a)
 {
   FP_DECL_EX;
   FP_DECL_Q(A);
-  int r;
+  unsigned int r;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_QP(A, a);
+  FP_UNPACK_RAW_QP(A, a);
   FP_TO_INT_Q(r, A, 32, 1);
   QP_HANDLE_EXCEPTIONS(
   	int rx;
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_qtos.c b/sysdeps/sparc/sparc64/soft-fp/qp_qtos.c
index 52d52d6830..f5f9cdb190 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_qtos.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_qtos.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (float)(*a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ float _Qp_qtos(const long double *a)
   float r;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_QP(A, a);
+  FP_UNPACK_SEMIRAW_QP(A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
-  FP_CONV(S,Q,1,4,R,A);
+  FP_TRUNC(S,Q,1,4,R,A);
 #else
-  FP_CONV(S,Q,1,2,R,A);
+  FP_TRUNC(S,Q,1,2,R,A);
 #endif
-  FP_PACK_S(r, R);
+  FP_PACK_SEMIRAW_S(r, R);
 
   QP_HANDLE_EXCEPTIONS(__asm (
 "	ldd [%1], %%f52\n"
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_qtoui.c b/sysdeps/sparc/sparc64/soft-fp/qp_qtoui.c
index abee50b06a..884d23e527 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_qtoui.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_qtoui.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (unsigned int)(*a)
-   Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,7 +31,7 @@ unsigned int _Qp_qtoui(const long double *a)
   unsigned int r;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_QP(A, a);
+  FP_UNPACK_RAW_QP(A, a);
   FP_TO_INT_Q(r, A, 32, -1);
   QP_HANDLE_EXCEPTIONS(
   	int rx;
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_qtoux.c b/sysdeps/sparc/sparc64/soft-fp/qp_qtoux.c
index 87c8478880..4b6f265a47 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_qtoux.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_qtoux.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (unsigned long)(*a)
-   Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,7 +31,7 @@ unsigned long _Qp_qtoux(const long double *a)
   unsigned long r;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_QP(A, a);
+  FP_UNPACK_RAW_QP(A, a);
   FP_TO_INT_Q(r, A, 64, -1);
   QP_HANDLE_EXCEPTIONS(
 	unsigned long rx;
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_qtox.c b/sysdeps/sparc/sparc64/soft-fp/qp_qtox.c
index 35481196ee..fac6166c2c 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_qtox.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_qtox.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    Return (long)(*a)
-   Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -28,10 +28,10 @@ long _Qp_qtox(const long double *a)
 {
   FP_DECL_EX;
   FP_DECL_Q(A);
-  long r;
+  unsigned long r;
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_QP(A, a);
+  FP_UNPACK_RAW_QP(A, a);
   FP_TO_INT_Q(r, A, 64, 1);
   QP_HANDLE_EXCEPTIONS(
 	long rx;
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_stoq.c b/sysdeps/sparc/sparc64/soft-fp/qp_stoq.c
index 655813186e..1a4a03df88 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_stoq.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_stoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    (*c) = (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,13 +31,13 @@ void _Qp_stoq(long double *c, const float a)
   FP_DECL_Q(C);
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_S(A, a);
+  FP_UNPACK_RAW_S(A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
-  FP_CONV(Q,S,4,1,C,A);
+  FP_EXTEND(Q,S,4,1,C,A);
 #else
-  FP_CONV(Q,S,2,1,C,A);
+  FP_EXTEND(Q,S,2,1,C,A);
 #endif
-  FP_PACK_QP(c, C);
+  FP_PACK_RAW_QP(c, C);
   QP_HANDLE_EXCEPTIONS(__asm (
 "	fstoq %1, %%f60\n"
 "	std %%f60, [%0]\n"
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_sub.c b/sysdeps/sparc/sparc64/soft-fp/qp_sub.c
index b1ed15a588..056224fb46 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_sub.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_sub.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    (*c) = (*a) - (*b)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,10 +29,10 @@ void _Qp_sub(long double *c, const long double *a, const long double *b)
   FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(C);
 
   FP_INIT_ROUNDMODE;
-  FP_UNPACK_QP(A, a);
-  FP_UNPACK_QP(B, b);
+  FP_UNPACK_SEMIRAW_QP(A, a);
+  FP_UNPACK_SEMIRAW_QP(B, b);
   FP_SUB_Q(C, A, B);
-  FP_PACK_QP(c, C);
+  FP_PACK_SEMIRAW_QP(c, C);
   QP_HANDLE_EXCEPTIONS(__asm (
 "	ldd [%1], %%f52\n"
 "	ldd [%1+8], %%f54\n"
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_uitoq.c b/sysdeps/sparc/sparc64/soft-fp/qp_uitoq.c
index d143ba28d3..a3bfaedfc9 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_uitoq.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_uitoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    (*c) = (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,7 +29,7 @@ void _Qp_uitoq(long double *c, const unsigned int a)
   FP_DECL_Q(C);
   unsigned int b = a;
 
-  FP_FROM_INT_Q(C, b, 32, int);
-  FP_PACK_QP(c, C);
+  FP_FROM_INT_Q(C, b, 32, unsigned int);
+  FP_PACK_RAW_QP(c, C);
   QP_NO_EXCEPTIONS;
 }
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_uxtoq.c b/sysdeps/sparc/sparc64/soft-fp/qp_uxtoq.c
index 302147711c..f691e4d36f 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_uxtoq.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_uxtoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    (*c) = (long double)(a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,7 +29,7 @@ void _Qp_uxtoq(long double *c, const unsigned long a)
   FP_DECL_Q(C);
   unsigned long b = a;
 
-  FP_FROM_INT_Q(C, b, 64, long);
-  FP_PACK_QP(c, C);
+  FP_FROM_INT_Q(C, b, 64, unsigned long);
+  FP_PACK_RAW_QP(c, C);
   QP_NO_EXCEPTIONS;
 }
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_xtoq.c b/sysdeps/sparc/sparc64/soft-fp/qp_xtoq.c
index 9b4d16969e..b7a6102693 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_xtoq.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_xtoq.c
@@ -1,6 +1,6 @@
 /* Software floating-point emulation.
    (*c) = (long double)(*a)
-   Copyright (C) 1997,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com) and
 		  Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,7 +29,7 @@ void _Qp_xtoq(long double *c, const long a)
   FP_DECL_Q(C);
   long b = a;
 
-  FP_FROM_INT_Q(C, b, 64, long);
-  FP_PACK_QP(c, C);
+  FP_FROM_INT_Q(C, b, 64, unsigned long);
+  FP_PACK_RAW_QP(c, C);
   QP_NO_EXCEPTIONS;
 }
diff --git a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
index 42e6aa8506..449e955c16 100644
--- a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
@@ -1,6 +1,6 @@
 /* Machine-dependent software floating-point definitions.
    Sparc64 userland (_Q_* and _Qp_*) version.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth@cygnus.com),
 		  Jakub Jelinek (jj@ultra.linux.cz) and
@@ -23,6 +23,7 @@
    
 #include <fpu_control.h>
 #include <fenv.h>
+#include <stdlib.h>
 
 #define _FP_W_TYPE_SIZE		64
 #define _FP_W_TYPE		unsigned long
diff --git a/sysdeps/sparc/sparc64/sparcv9b/memcpy.S b/sysdeps/sparc/sparc64/sparcv9b/memcpy.S
index 8b70b0a932..760d526630 100644
--- a/sysdeps/sparc/sparc64/sparcv9b/memcpy.S
+++ b/sysdeps/sparc/sparc64/sparcv9b/memcpy.S
@@ -600,11 +600,11 @@ ENTRY(memmove)
 END(memmove)
 
 #ifdef USE_BPR
-weak_alias(memcpy, __align_cpy_1)
-weak_alias(memcpy, __align_cpy_2)
-weak_alias(memcpy, __align_cpy_4)
-weak_alias(memcpy, __align_cpy_8)
-weak_alias(memcpy, __align_cpy_16)
+weak_alias (memcpy, __align_cpy_1)
+weak_alias (memcpy, __align_cpy_2)
+weak_alias (memcpy, __align_cpy_4)
+weak_alias (memcpy, __align_cpy_8)
+weak_alias (memcpy, __align_cpy_16)
 #endif
 libc_hidden_builtin_def (memcpy)
 libc_hidden_builtin_def (memmove)
diff --git a/sysdeps/sparc/sparc64/sparcv9v/memcpy.S b/sysdeps/sparc/sparc64/sparcv9v/memcpy.S
new file mode 100644
index 0000000000..05c837fa25
--- /dev/null
+++ b/sysdeps/sparc/sparc64/sparcv9v/memcpy.S
@@ -0,0 +1,593 @@
+/* Copy SIZE bytes from SRC to DEST.  For SUN4V Niagara.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by David S. Miller (davem@davemloft.net)
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+#define ASI_BLK_INIT_QUAD_LDD_P	0xe2
+#define ASI_P			0x80
+#define ASI_PNF			0x82
+
+#define LOAD(type,addr,dest)	type##a [addr] ASI_P, dest
+#define LOAD_TWIN(addr_reg,dest0,dest1)	\
+	ldda [addr_reg] ASI_BLK_INIT_QUAD_LDD_P, dest0
+
+#define STORE(type,src,addr)	type src, [addr]
+#define STORE_INIT(src,addr)	stxa src, [addr] %asi
+
+#ifndef XCC
+#define USE_BPR
+#define XCC xcc
+#endif
+
+	.register	%g2,#scratch
+	.register	%g3,#scratch
+	.register	%g6,#scratch
+
+	.text
+	.align		32
+
+ENTRY(bcopy)
+	sub		%o1, %o0, %o4
+	mov		%o0, %g4
+	cmp		%o4, %o2
+	mov		%o1, %o0
+	bgeu,pt		%XCC, 100f
+	 mov		%g4, %o1
+#ifndef USE_BPR
+	srl		%o2, 0, %o2
+#endif
+	brnz,pn		%o2, 220f
+	 add		%o0, %o2, %o0
+	retl
+	 nop
+END(bcopy)
+
+	.align		32
+ENTRY(memcpy)
+100:	/* %o0=dst, %o1=src, %o2=len */
+	mov		%o0, %g5
+	cmp		%o2, 0
+	be,pn		%XCC, 85f
+218:	 or		%o0, %o1, %o3
+	cmp		%o2, 16
+	blu,a,pn	%XCC, 80f
+	 or		%o3, %o2, %o3
+
+	/* 2 blocks (128 bytes) is the minimum we can do the block
+	 * copy with.  We need to ensure that we'll iterate at least
+	 * once in the block copy loop.  At worst we'll need to align
+	 * the destination to a 64-byte boundary which can chew up
+	 * to (64 - 1) bytes from the length before we perform the
+	 * block copy loop.
+	 */
+	cmp		%o2, (2 * 64)
+	blu,pt		%XCC, 70f
+	 andcc		%o3, 0x7, %g0
+
+	/* %o0:	dst
+	 * %o1:	src
+	 * %o2:	len  (known to be >= 128)
+	 *
+	 * The block copy loops will use %o4/%o5,%g2/%g3 as
+	 * temporaries while copying the data.
+	 */
+
+	LOAD(prefetch, %o1, #one_read)
+	wr		%g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
+
+	/* Align destination on 64-byte boundary.  */
+	andcc		%o0, (64 - 1), %o4
+	be,pt		%XCC, 2f
+	 sub		%o4, 64, %o4
+	sub		%g0, %o4, %o4	! bytes to align dst
+	sub		%o2, %o4, %o2
+1:	subcc		%o4, 1, %o4
+	LOAD(ldub, %o1, %g1)
+	STORE(stb, %g1, %o0)
+	add		%o1, 1, %o1
+	bne,pt		%XCC, 1b
+	add		%o0, 1, %o0
+
+	/* If the source is on a 16-byte boundary we can do
+	 * the direct block copy loop.  If it is 8-byte aligned
+	 * we can do the 16-byte loads offset by -8 bytes and the
+	 * init stores offset by one register.
+	 *
+	 * If the source is not even 8-byte aligned, we need to do
+	 * shifting and masking (basically integer faligndata).
+	 *
+	 * The careful bit with init stores is that if we store
+	 * to any part of the cache line we have to store the whole
+	 * cacheline else we can end up with corrupt L2 cache line
+	 * contents.  Since the loop works on 64-bytes of 64-byte
+	 * aligned store data at a time, this is easy to ensure.
+	 */
+2:
+	andcc		%o1, (16 - 1), %o4
+	andn		%o2, (64 - 1), %g1	! block copy loop iterator
+	sub		%o2, %g1, %o2		! final sub-block copy bytes
+	be,pt		%XCC, 50f
+	 cmp		%o4, 8
+	be,a,pt		%XCC, 10f
+	 sub		%o1, 0x8, %o1
+
+	/* Neither 8-byte nor 16-byte aligned, shift and mask.  */
+	mov		%g1, %o4
+	and		%o1, 0x7, %g1
+	sll		%g1, 3, %g1
+	mov		64, %o3
+	andn		%o1, 0x7, %o1
+	LOAD(ldx, %o1, %g2)
+	sub		%o3, %g1, %o3
+	sllx		%g2, %g1, %g2
+
+#define SWIVEL_ONE_DWORD(SRC, TMP1, TMP2, PRE_VAL, PRE_SHIFT, POST_SHIFT, DST)\
+	LOAD(ldx, SRC, TMP1); \
+	srlx		TMP1, PRE_SHIFT, TMP2; \
+	or		TMP2, PRE_VAL, TMP2; \
+	STORE_INIT(TMP2, DST); \
+	sllx		TMP1, POST_SHIFT, PRE_VAL;
+
+1:	add		%o1, 0x8, %o1
+	SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x00)
+	add		%o1, 0x8, %o1
+	SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x08)
+	add		%o1, 0x8, %o1
+	SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x10)
+	add		%o1, 0x8, %o1
+	SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x18)
+	add		%o1, 32, %o1
+	LOAD(prefetch, %o1, #one_read)
+	sub		%o1, 32 - 8, %o1
+	SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x20)
+	add		%o1, 8, %o1
+	SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x28)
+	add		%o1, 8, %o1
+	SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x30)
+	add		%o1, 8, %o1
+	SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x38)
+	subcc		%o4, 64, %o4
+	bne,pt		%XCC, 1b
+	 add		%o0, 64, %o0
+
+#undef SWIVEL_ONE_DWORD
+
+	srl		%g1, 3, %g1
+	ba,pt		%XCC, 60f
+	 add		%o1, %g1, %o1
+
+10:	/* Destination is 64-byte aligned, source was only 8-byte
+	 * aligned but it has been subtracted by 8 and we perform
+	 * one twin load ahead, then add 8 back into source when
+	 * we finish the loop.
+	 */
+	LOAD_TWIN(%o1, %o4, %o5)
+1:	add		%o1, 16, %o1
+	LOAD_TWIN(%o1, %g2, %g3)
+	add		%o1, 16 + 32, %o1
+	LOAD(prefetch, %o1, #one_read)
+	sub		%o1, 32, %o1
+	STORE_INIT(%o5, %o0 + 0x00)		! initializes cache line
+	STORE_INIT(%g2, %o0 + 0x08)
+	LOAD_TWIN(%o1, %o4, %o5)
+	add		%o1, 16, %o1
+	STORE_INIT(%g3, %o0 + 0x10)
+	STORE_INIT(%o4, %o0 + 0x18)
+	LOAD_TWIN(%o1, %g2, %g3)
+	add		%o1, 16, %o1
+	STORE_INIT(%o5, %o0 + 0x20)
+	STORE_INIT(%g2, %o0 + 0x28)
+	LOAD_TWIN(%o1, %o4, %o5)
+	STORE_INIT(%g3, %o0 + 0x30)
+	STORE_INIT(%o4, %o0 + 0x38)
+	subcc		%g1, 64, %g1
+	bne,pt		%XCC, 1b
+	 add		%o0, 64, %o0
+
+	ba,pt		%XCC, 60f
+	 add		%o1, 0x8, %o1
+
+50:	/* Destination is 64-byte aligned, and source is 16-byte
+	 * aligned.
+	 */
+1:	LOAD_TWIN(%o1, %o4, %o5)
+	add	%o1, 16, %o1
+	LOAD_TWIN(%o1, %g2, %g3)
+	add	%o1, 16 + 32, %o1
+	LOAD(prefetch, %o1, #one_read)
+	sub	%o1, 32, %o1
+	STORE_INIT(%o4, %o0 + 0x00)		! initializes cache line
+	STORE_INIT(%o5, %o0 + 0x08)
+	LOAD_TWIN(%o1, %o4, %o5)
+	add	%o1, 16, %o1
+	STORE_INIT(%g2, %o0 + 0x10)
+	STORE_INIT(%g3, %o0 + 0x18)
+	LOAD_TWIN(%o1, %g2, %g3)
+	add	%o1, 16, %o1
+	STORE_INIT(%o4, %o0 + 0x20)
+	STORE_INIT(%o5, %o0 + 0x28)
+	STORE_INIT(%g2, %o0 + 0x30)
+	STORE_INIT(%g3, %o0 + 0x38)
+	subcc	%g1, 64, %g1
+	bne,pt	%XCC, 1b
+	 add	%o0, 64, %o0
+	/* fall through */
+
+60:
+	/* %o2 contains any final bytes still needed to be copied
+	 * over. If anything is left, we copy it one byte at a time.
+	 */
+	wr		%g0, ASI_PNF, %asi
+	brz,pt		%o2, 85f
+	 sub		%o0, %o1, %o3
+	ba,a,pt		%XCC, 90f
+
+	.align		64
+70: /* 16 < len <= 64 */
+	bne,pn		%XCC, 75f
+	 sub		%o0, %o1, %o3
+
+72:
+	andn		%o2, 0xf, %o4
+	and		%o2, 0xf, %o2
+1:	subcc		%o4, 0x10, %o4
+	LOAD(ldx, %o1, %o5)
+	add		%o1, 0x08, %o1
+	LOAD(ldx, %o1, %g1)
+	sub		%o1, 0x08, %o1
+	STORE(stx, %o5, %o1 + %o3)
+	add		%o1, 0x8, %o1
+	STORE(stx, %g1, %o1 + %o3)
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x8, %o1
+73:	andcc		%o2, 0x8, %g0
+	be,pt		%XCC, 1f
+	 nop
+	sub		%o2, 0x8, %o2
+	LOAD(ldx, %o1, %o5)
+	STORE(stx, %o5, %o1 + %o3)
+	add		%o1, 0x8, %o1
+1:	andcc		%o2, 0x4, %g0
+	be,pt		%XCC, 1f
+	 nop
+	sub		%o2, 0x4, %o2
+	LOAD(lduw, %o1, %o5)
+	STORE(stw, %o5, %o1 + %o3)
+	add		%o1, 0x4, %o1
+1:	cmp		%o2, 0
+	be,pt		%XCC, 85f
+	 nop
+	ba,pt		%XCC, 90f
+	 nop
+
+75:
+	andcc		%o0, 0x7, %g1
+	sub		%g1, 0x8, %g1
+	be,pn		%icc, 2f
+	 sub		%g0, %g1, %g1
+	sub		%o2, %g1, %o2
+
+1:	subcc		%g1, 1, %g1
+	LOAD(ldub, %o1, %o5)
+	STORE(stb, %o5, %o1 + %o3)
+	bgu,pt		%icc, 1b
+	 add		%o1, 1, %o1
+
+2:	add		%o1, %o3, %o0
+	andcc		%o1, 0x7, %g1
+	bne,pt		%icc, 8f
+	 sll		%g1, 3, %g1
+
+	cmp		%o2, 16
+	bgeu,pt		%icc, 72b
+	 nop
+	ba,a,pt		%XCC, 73b
+
+8:	mov		64, %o3
+	andn		%o1, 0x7, %o1
+	LOAD(ldx, %o1, %g2)
+	sub		%o3, %g1, %o3
+	andn		%o2, 0x7, %o4
+	sllx		%g2, %g1, %g2
+1:	add		%o1, 0x8, %o1
+	LOAD(ldx, %o1, %g3)
+	subcc		%o4, 0x8, %o4
+	srlx		%g3, %o3, %o5
+	or		%o5, %g2, %o5
+	STORE(stx, %o5, %o0)
+	add		%o0, 0x8, %o0
+	bgu,pt		%icc, 1b
+	 sllx		%g3, %g1, %g2
+
+	srl		%g1, 3, %g1
+	andcc		%o2, 0x7, %o2
+	be,pn		%icc, 85f
+	 add		%o1, %g1, %o1
+	ba,pt		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+	.align		64
+80: /* 0 < len <= 16 */
+	andcc		%o3, 0x3, %g0
+	bne,pn		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+1:
+	subcc		%o2, 4, %o2
+	LOAD(lduw, %o1, %g1)
+	STORE(stw, %g1, %o1 + %o3)
+	bgu,pt		%XCC, 1b
+	 add		%o1, 4, %o1
+
+85:	retl
+	 mov		%g5, %o0
+
+	.align		32
+90:
+	subcc		%o2, 1, %o2
+	LOAD(ldub, %o1, %g1)
+	STORE(stb, %g1, %o1 + %o3)
+	bgu,pt		%XCC, 90b
+	 add		%o1, 1, %o1
+	retl
+	 mov		%g5, %o0
+
+END(memcpy)
+
+#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3)	\
+	ldx		[%src - offset - 0x20], %t0; 		\
+	ldx		[%src - offset - 0x18], %t1; 		\
+	ldx		[%src - offset - 0x10], %t2; 		\
+	ldx		[%src - offset - 0x08], %t3; 		\
+	stw		%t0, [%dst - offset - 0x1c]; 		\
+	srlx		%t0, 32, %t0;				\
+	stw		%t0, [%dst - offset - 0x20]; 		\
+	stw		%t1, [%dst - offset - 0x14]; 		\
+	srlx		%t1, 32, %t1;				\
+	stw		%t1, [%dst - offset - 0x18]; 		\
+	stw		%t2, [%dst - offset - 0x0c]; 		\
+	srlx		%t2, 32, %t2;				\
+	stw		%t2, [%dst - offset - 0x10]; 		\
+	stw		%t3, [%dst - offset - 0x04];		\
+	srlx		%t3, 32, %t3;				\
+	stw		%t3, [%dst - offset - 0x08];
+
+#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3)	\
+	ldx		[%src - offset - 0x20], %t0; 		\
+	ldx		[%src - offset - 0x18], %t1; 		\
+	ldx		[%src - offset - 0x10], %t2; 		\
+	ldx		[%src - offset - 0x08], %t3; 		\
+	stx		%t0, [%dst - offset - 0x20]; 		\
+	stx		%t1, [%dst - offset - 0x18]; 		\
+	stx		%t2, [%dst - offset - 0x10]; 		\
+	stx		%t3, [%dst - offset - 0x08];		\
+	ldx		[%src - offset - 0x40], %t0; 		\
+	ldx		[%src - offset - 0x38], %t1; 		\
+	ldx		[%src - offset - 0x30], %t2; 		\
+	ldx		[%src - offset - 0x28], %t3; 		\
+	stx		%t0, [%dst - offset - 0x40]; 		\
+	stx		%t1, [%dst - offset - 0x38]; 		\
+	stx		%t2, [%dst - offset - 0x30]; 		\
+	stx		%t3, [%dst - offset - 0x28];
+
+#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)	\
+	ldx		[%src + offset + 0x00], %t0;		\
+	ldx		[%src + offset + 0x08], %t1; 		\
+	stw		%t0, [%dst + offset + 0x04]; 		\
+	srlx		%t0, 32, %t2;				\
+	stw		%t2, [%dst + offset + 0x00]; 		\
+	stw		%t1, [%dst + offset + 0x0c]; 		\
+	srlx		%t1, 32, %t3;				\
+	stw		%t3, [%dst + offset + 0x08];
+
+#define RMOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1)		\
+	ldx		[%src + offset + 0x00], %t0; 		\
+	ldx		[%src + offset + 0x08], %t1; 		\
+	stx		%t0, [%dst + offset + 0x00]; 		\
+	stx		%t1, [%dst + offset + 0x08];
+
+	.align		32
+228:	andcc		%o2, 1, %g0
+	be,pt		%icc, 2f+4
+1:	 ldub		[%o1 - 1], %o5
+	sub		%o1, 1, %o1
+	sub		%o0, 1, %o0
+	subcc		%o2, 1, %o2
+	be,pn		%xcc, 229f
+	 stb		%o5, [%o0]
+2:	ldub		[%o1 - 1], %o5
+	sub		%o0, 2, %o0
+	ldub		[%o1 - 2], %g5
+	sub		%o1, 2, %o1
+	subcc		%o2, 2, %o2
+	stb		%o5, [%o0 + 1]
+	bne,pt		%xcc, 2b
+	 stb		%g5, [%o0]
+229:	retl
+	 mov		%g4, %o0
+out:	retl
+	 mov		%g5, %o0
+
+	.align		32
+ENTRY(memmove)
+	mov		%o0, %g5
+#ifndef USE_BPR
+	srl		%o2, 0, %o2
+#endif
+	brz,pn		%o2, out
+	 sub		%o0, %o1, %o4
+	cmp		%o4, %o2
+	bgeu,pt		%XCC, 218b
+	 mov		%o0, %g4
+	add		%o0, %o2, %o0
+220:	add		%o1, %o2, %o1
+	cmp		%o2, 15
+	bleu,pn		%xcc, 228b
+	 andcc		%o0, 7, %g2
+	sub		%o0, %o1, %g5
+	andcc		%g5, 3, %o5
+	bne,pn		%xcc, 232f
+	 andcc		%o1, 3, %g0
+	be,a,pt		%xcc, 236f
+	 andcc		%o1, 4, %g0
+	andcc		%o1, 1, %g0
+	be,pn		%xcc, 4f
+	 andcc		%o1, 2, %g0
+	ldub		[%o1 - 1], %g2
+	sub		%o1, 1, %o1
+	sub		%o0, 1, %o0
+	sub		%o2, 1, %o2
+	be,pn		%xcc, 5f
+	 stb		%g2, [%o0]
+4:	lduh		[%o1 - 2], %g2
+	sub		%o1, 2, %o1
+	sub		%o0, 2, %o0
+	sub		%o2, 2, %o2
+	sth		%g2, [%o0]
+5:	andcc		%o1, 4, %g0
+236:	be,a,pn		%xcc, 2f
+	 andcc		%o2, -128, %g6
+	lduw		[%o1 - 4], %g5
+	sub		%o1, 4, %o1
+	sub		%o0, 4, %o0
+	sub		%o2, 4, %o2
+	stw		%g5, [%o0]
+	andcc		%o2, -128, %g6
+2:	be,pn		%xcc, 235f
+	 andcc		%o0, 4, %g0
+	be,pn		%xcc, 282f + 4
+5:	RMOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
+	RMOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5)
+	RMOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
+	RMOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5)
+	subcc		%g6, 128, %g6
+	sub		%o1, 128, %o1
+	bne,pt		%xcc, 5b
+	 sub		%o0, 128, %o0
+235:	andcc		%o2, 0x70, %g6
+41:	be,pn		%xcc, 280f
+	 andcc		%o2, 8, %g0
+
+279:	rd		%pc, %o5
+	sll		%g6, 1, %g5
+	sub		%o1, %g6, %o1
+	sub		%o5, %g5, %o5
+	jmpl		%o5 + %lo(280f - 279b), %g0
+	 sub		%o0, %g6, %o0
+	RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5)
+	RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5)
+	RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5)
+	RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5)
+	RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5)
+	RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5)
+	RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5)
+280:	be,pt		%xcc, 281f
+	 andcc		%o2, 4, %g0
+	ldx		[%o1 - 8], %g2
+	sub		%o0, 8, %o0
+	stw		%g2, [%o0 + 4]
+	sub		%o1, 8, %o1
+	srlx		%g2, 32, %g2
+	stw		%g2, [%o0]
+281:	be,pt		%xcc, 1f
+	 andcc		%o2, 2, %g0
+	lduw		[%o1 - 4], %g2
+	sub		%o1, 4, %o1
+	stw		%g2, [%o0 - 4]
+	sub		%o0, 4, %o0
+1:	be,pt		%xcc, 1f
+	 andcc		%o2, 1, %g0
+	lduh		[%o1 - 2], %g2
+	sub		%o1, 2, %o1
+	sth		%g2, [%o0 - 2]
+	sub		%o0, 2, %o0
+1:	be,pt		%xcc, 211f
+	 nop
+	ldub		[%o1 - 1], %g2
+	stb		%g2, [%o0 - 1]
+211:	retl
+	 mov		%g4, %o0
+
+282:	RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
+	RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
+	subcc		%g6, 128, %g6
+	sub		%o1, 128, %o1
+	bne,pt		%xcc, 282b
+	 sub		%o0, 128, %o0
+	andcc		%o2, 0x70, %g6
+	be,pn		%xcc, 284f
+	 andcc		%o2, 8, %g0
+
+283:	rd		%pc, %o5
+	sub		%o1, %g6, %o1
+	sub		%o5, %g6, %o5
+	jmpl		%o5 + %lo(284f - 283b), %g0
+	 sub		%o0, %g6, %o0
+	RMOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3)
+	RMOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3)
+	RMOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3)
+	RMOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3)
+	RMOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3)
+	RMOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3)
+	RMOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3)
+284:	be,pt		%xcc, 285f
+	 andcc		%o2, 4, %g0
+	ldx		[%o1 - 8], %g2
+	sub		%o0, 8, %o0
+	sub		%o1, 8, %o1
+	stx		%g2, [%o0]
+285:	be,pt		%xcc, 1f
+	 andcc		%o2, 2, %g0
+	lduw		[%o1 - 4], %g2
+	sub		%o0, 4, %o0
+	sub		%o1, 4, %o1
+	stw		%g2, [%o0]
+1:	be,pt		%xcc, 1f
+	 andcc		%o2, 1, %g0
+	lduh		[%o1 - 2], %g2
+	sub		%o0, 2, %o0
+	sub		%o1, 2, %o1
+	sth		%g2, [%o0]
+1:	be,pt		%xcc, 1f
+	 nop
+	ldub		[%o1 - 1], %g2
+	stb		%g2, [%o0 - 1]
+1:	retl
+	 mov		%g4, %o0
+
+232:	ldub		[%o1 - 1], %g5
+	sub		%o1, 1, %o1
+	sub		%o0, 1, %o0
+	subcc		%o2, 1, %o2
+	bne,pt		%xcc, 232b
+	 stb		%g5, [%o0]
+234:	retl
+	 mov		%g4, %o0
+END(memmove)
+
+#ifdef USE_BPR
+weak_alias (memcpy, __align_cpy_1)
+weak_alias (memcpy, __align_cpy_2)
+weak_alias (memcpy, __align_cpy_4)
+weak_alias (memcpy, __align_cpy_8)
+weak_alias (memcpy, __align_cpy_16)
+#endif
+libc_hidden_builtin_def (memcpy)
+libc_hidden_builtin_def (memmove)
diff --git a/sysdeps/sparc/sparc64/sparcv9v/memset.S b/sysdeps/sparc/sparc64/sparcv9v/memset.S
new file mode 100644
index 0000000000..ac0a50cf8e
--- /dev/null
+++ b/sysdeps/sparc/sparc64/sparcv9v/memset.S
@@ -0,0 +1,127 @@
+/* Set a block of memory to some byte value.  For SUN4V Niagara.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by David S. Miller (davem@davemloft.net)
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+#define ASI_BLK_INIT_QUAD_LDD_P	0xe2
+#define ASI_P			0x80
+#define ASI_PNF			0x82
+
+#ifndef XCC
+#define USE_BPR
+#define XCC xcc
+#endif
+
+	.register	%g2,#scratch
+
+	.text
+	.align		32
+
+ENTRY(memset)
+	/* %o0=buf, %o1=pat, %o2=len */
+	and		%o1, 0xff, %o3
+	mov		%o2, %o1
+	sllx		%o3, 8, %g1
+	or		%g1, %o3, %o2
+	sllx		%o2, 16, %g1
+	or		%g1, %o2, %o2
+	sllx		%o2, 32, %g1
+	ba,pt		%XCC, 1f
+	 or		%g1, %o2, %o2
+END(memset)
+
+ENTRY(__bzero)
+	clr		%o2
+1:	brz,pn		%o1, 90f
+	 mov		%o0, %o3
+
+	wr		%g0, ASI_P, %asi
+
+	cmp		%o1, 15
+	bl,pn		%icc, 70f
+	 andcc		%o0, 0x7, %g1
+	be,pt		%XCC, 2f
+	 mov		8, %g2
+	sub		%g2, %g1, %g1
+	sub		%o1, %g1, %o1
+1:	stba		%o2, [%o0 + 0x00] %asi
+	subcc		%g1, 1, %g1
+	bne,pt		%XCC, 1b
+	 add		%o0, 1, %o0
+2:	cmp		%o1, 128
+	bl,pn		%icc, 60f
+	 andcc		%o0, (64 - 1), %g1
+	be,pt		%XCC, 40f
+	 mov		64, %g2
+	sub		%g2, %g1, %g1
+	sub		%o1, %g1, %o1
+1:	stxa		%o2, [%o0 + 0x00] %asi
+	subcc		%g1, 8, %g1
+	bne,pt		%XCC, 1b
+	 add		%o0, 8, %o0
+
+40:
+	wr		%g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
+	andn		%o1, (64 - 1), %g1
+	sub		%o1, %g1, %o1
+50:
+	stxa		%o2, [%o0 + 0x00] %asi
+	stxa		%o2, [%o0 + 0x08] %asi
+	stxa		%o2, [%o0 + 0x10] %asi
+	stxa		%o2, [%o0 + 0x18] %asi
+	stxa		%o2, [%o0 + 0x20] %asi
+	stxa		%o2, [%o0 + 0x28] %asi
+	stxa		%o2, [%o0 + 0x30] %asi
+	stxa		%o2, [%o0 + 0x38] %asi
+	subcc		%g1, 64, %g1
+	bne,pt		%XCC, 50b
+	 add		%o0, 64, %o0
+
+	wr		%g0, ASI_P, %asi
+	brz,pn		%o1, 80f
+60:
+	 andncc		%o1, 0x7, %g1
+	be,pn		%XCC, 2f
+	 sub		%o1, %g1, %o1
+1:	stxa		%o2, [%o0 + 0x00] %asi
+	subcc		%g1, 8, %g1
+	bne,pt		%XCC, 1b
+	 add		%o0, 8, %o0
+2:	brz,pt		%o1, 80f
+	 nop
+
+70:
+1:	stba		%o2, [%o0 + 0x00] %asi
+	subcc		%o1, 1, %o1
+	bne,pt		%icc, 1b
+	 add		%o0, 1, %o0
+
+	/* fallthrough */
+
+80:
+	wr		%g0, ASI_PNF, %asi
+
+90:
+	retl
+	 mov		%o3, %o0
+END(__bzero)
+
+libc_hidden_builtin_def (memset)
+weak_alias (__bzero, bzero)