commit 4e784e457bf57bf2d5f3a7c5072ad30e768c0ac3
Author: Justin Waters <justin.waters@timesys.com>
Date:   Wed Jul 17 22:07:18 2013 -0400

    glibc-2.17: e500 Patch
    
    Pulled from eglibc 2.17 svn23539

diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/Makefile b/ports/sysdeps/powerpc/powerpc32/e500/fpu/Makefile
new file mode 100644
index 0000000..3e7c9e9
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/Makefile
@@ -0,0 +1,11 @@
+ifeq ($(subdir),stdlib)
+spepim_routines = atosfix16 atosfix32 atosfix64 atoufix16 atoufix32 atoufix64 \
+  strtosfix16 strtosfix32 strtosfix64 strtoufix16 strtoufix32 strtoufix64
+sysdep_routines += $(spepim_routines)
+tests += tst-spepim
+ifeq ($(build-shared),yes)
+$(objpfx)tst-spepim: $(common-objpfx)math/libm.so$(libm.so-version)
+else
+$(objpfx)tst-spepim: $(common-objpfx)math/libm.a
+endif
+endif
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/Versions b/ports/sysdeps/powerpc/powerpc32/e500/fpu/Versions
new file mode 100644
index 0000000..bd45e1d
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/Versions
@@ -0,0 +1,8 @@
+libc {
+  GLIBC_2.3.3 {
+    atosfix16; atosfix32; atosfix64;
+    atoufix16; atoufix32; atoufix64;
+    strtosfix16; strtosfix32; strtosfix64;
+    strtoufix16; strtoufix32; strtoufix64;
+  }
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/__longjmp-common.S b/ports/sysdeps/powerpc/powerpc32/e500/fpu/__longjmp-common.S
new file mode 100644
index 0000000..765701d
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/__longjmp-common.S
@@ -0,0 +1,112 @@
+/* longjmp for PowerPC E500.
+   Copyright (C) 2004, 2006, 2009 Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>.
+
+   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 _ASM
+#define _SETJMP_H
+#ifdef __NO_VMX__
+# include <novmxsetjmp.h>
+#else
+# include <jmpbuf-offsets.h>
+#endif
+#include <bp-sym.h>
+#include <bp-asm.h>
+
+ENTRY (BP_SYM (__longjmp))
+	CHECK_BOUNDS_BOTH_WIDE_LIT (r3, r8, r9, JB_SIZE)
+
+#if defined PTR_DEMANGLE || defined CHECK_SP
+	lwz r24,(JB_GPR1*4)(r3)
+# ifdef CHECK_SP
+#  ifdef PTR_DEMANGLE
+	PTR_DEMANGLE3 (r24, r24, r25)
+#  endif
+	CHECK_SP (r24)
+	mr r1,r24
+# endif
+#else
+	lwz r1,(JB_GPR1*4)(r3)
+#endif
+	lwz r0,(JB_LR*4)(r3)
+	/*lfd fp14,((JB_FPRS+0*2)*4)(r3)*/
+	evldd r14,((JB_FPRS+0*2)*4)(r3)
+	lwz r14,((JB_GPRS+0)*4)(r3)
+	/*lfd fp15,((JB_FPRS+1*2)*4)(r3)*/
+	evldd r15,((JB_FPRS+1*2)*4)(r3)
+	lwz r15,((JB_GPRS+1)*4)(r3)
+	/*lfd fp16,((JB_FPRS+2*2)*4)(r3)*/
+	evldd r16,((JB_FPRS+2*2)*4)(r3)
+	lwz r16,((JB_GPRS+2)*4)(r3)
+	/*lfd fp17,((JB_FPRS+3*2)*4)(r3)*/
+	evldd r17,((JB_FPRS+3*2)*4)(r3)
+	lwz r17,((JB_GPRS+3)*4)(r3)
+	/*lfd fp18,((JB_FPRS+4*2)*4)(r3)*/
+	evldd r18,((JB_FPRS+4*2)*4)(r3)
+	lwz r18,((JB_GPRS+4)*4)(r3)
+	/*lfd fp19,((JB_FPRS+5*2)*4)(r3)*/
+	evldd r19,((JB_FPRS+5*2)*4)(r3)
+	lwz r19,((JB_GPRS+5)*4)(r3)
+	/*lfd fp20,((JB_FPRS+6*2)*4)(r3)*/
+	evldd r20,((JB_FPRS+6*2)*4)(r3)
+	lwz r20,((JB_GPRS+6)*4)(r3)
+#ifdef PTR_DEMANGLE
+# ifndef CHECK_SP
+	PTR_DEMANGLE3 (r1, r24, r25)
+# endif
+	PTR_DEMANGLE2 (r0, r25)
+#endif
+	mtlr r0
+	/*lfd fp21,((JB_FPRS+7*2)*4)(r3)*/
+	evldd r21,((JB_FPRS+7*2)*4)(r3)
+	lwz r21,((JB_GPRS+7)*4)(r3)
+	/*lfd fp22,((JB_FPRS+8*2)*4)(r3)*/
+	evldd r22,((JB_FPRS+8*2)*4)(r3)
+	lwz r22,((JB_GPRS+8)*4)(r3)
+	lwz r0,(JB_CR*4)(r3)
+	/*lfd fp23,((JB_FPRS+9*2)*4)(r3)*/
+	evldd r23,((JB_FPRS+9*2)*4)(r3)
+	lwz r23,((JB_GPRS+9)*4)(r3)
+	/*lfd fp24,((JB_FPRS+10*2)*4)(r3)*/
+	evldd r24,((JB_FPRS+10*2)*4)(r3)
+	lwz r24,((JB_GPRS+10)*4)(r3)
+	/*lfd fp25,((JB_FPRS+11*2)*4)(r3)*/
+	evldd r25,((JB_FPRS+11*2)*4)(r3)
+	lwz r25,((JB_GPRS+11)*4)(r3)
+	mtcrf 0xFF,r0
+	/*lfd fp26,((JB_FPRS+12*2)*4)(r3)*/
+	evldd r26,((JB_FPRS+12*2)*4)(r3)
+	lwz r26,((JB_GPRS+12)*4)(r3)
+	/*lfd fp27,((JB_FPRS+13*2)*4)(r3)*/
+	evldd r27,((JB_FPRS+13*2)*4)(r3)
+	lwz r27,((JB_GPRS+13)*4)(r3)
+	/*lfd fp28,((JB_FPRS+14*2)*4)(r3)*/
+	evldd r28,((JB_FPRS+14*2)*4)(r3)
+	lwz r28,((JB_GPRS+14)*4)(r3)
+	/*lfd fp29,((JB_FPRS+15*2)*4)(r3)*/
+	evldd r29,((JB_FPRS+15*2)*4)(r3)
+	lwz r29,((JB_GPRS+15)*4)(r3)
+	/*lfd fp30,((JB_FPRS+16*2)*4)(r3)*/
+	evldd r30,((JB_FPRS+16*2)*4)(r3)
+	lwz r30,((JB_GPRS+16)*4)(r3)
+	/*lfd fp31,((JB_FPRS+17*2)*4)(r3)*/
+	evldd r31,((JB_FPRS+17*2)*4)(r3)
+	lwz r31,((JB_GPRS+17)*4)(r3)
+	mr r3,r4
+	blr
+END (BP_SYM (__longjmp))
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/__longjmp.S b/ports/sysdeps/powerpc/powerpc32/e500/fpu/__longjmp.S
new file mode 100644
index 0000000..5a050f1
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/__longjmp.S
@@ -0,0 +1,39 @@
+/* AltiVec/VMX (new) version of __longjmp for PowerPC.
+   Copyright (C)  1995-1997,1999,2000,2003,2004 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 <libc-symbols.h>
+#include <shlib-compat.h>
+
+#if defined NOT_IN_libc
+/* Build a non-versioned object for rtld-*.  */
+# include "__longjmp-common.S"
+
+#else /* !NOT_IN_libc */
+strong_alias (__vmx__longjmp, __longjmp);
+# define __longjmp  __vmx__longjmp
+# include "__longjmp-common.S"
+
+# if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+#  define __NO_VMX__
+#  undef JB_SIZE
+#  undef __longjmp
+#  define __longjmp  __novmx__longjmp
+#  include "__longjmp-common.S"
+# endif
+#endif /* !NOT_IN_libc */
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix16.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix16.c
new file mode 100644
index 0000000..41af5a3
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix16.c
@@ -0,0 +1,28 @@
+/* Convert string to 16-bit signed fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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 <stddef.h>
+#include <spe.h>
+
+int16_t
+atosfix16 (const char *str)
+{
+  return strtosfix16 (str, NULL);
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix32.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix32.c
new file mode 100644
index 0000000..ec8fc93
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix32.c
@@ -0,0 +1,28 @@
+/* Convert string to 32-bit signed fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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 <stddef.h>
+#include <spe.h>
+
+int32_t
+atosfix32 (const char *str)
+{
+  return strtosfix32 (str, NULL);
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix64.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix64.c
new file mode 100644
index 0000000..1942001
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atosfix64.c
@@ -0,0 +1,28 @@
+/* Convert string to 64-bit signed fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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 <stddef.h>
+#include <spe.h>
+
+int64_t
+atosfix64 (const char *str)
+{
+  return strtosfix64 (str, NULL);
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix16.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix16.c
new file mode 100644
index 0000000..1770d48
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix16.c
@@ -0,0 +1,28 @@
+/* Convert string to 16-bit unsigned fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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 <stddef.h>
+#include <spe.h>
+
+uint16_t
+atoufix16 (const char *str)
+{
+  return strtoufix16 (str, NULL);
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix32.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix32.c
new file mode 100644
index 0000000..9054187
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix32.c
@@ -0,0 +1,28 @@
+/* Convert string to 32-bit unsigned fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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 <stddef.h>
+#include <spe.h>
+
+uint32_t
+atoufix32 (const char *str)
+{
+  return strtoufix32 (str, NULL);
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix64.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix64.c
new file mode 100644
index 0000000..24c83a6
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/atoufix64.c
@@ -0,0 +1,28 @@
+/* Convert string to 64-bit unsigned fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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 <stddef.h>
+#include <spe.h>
+
+uint64_t
+atoufix64 (const char *str)
+{
+  return strtoufix64 (str, NULL);
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/e_sqrt.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/e_sqrt.c
new file mode 100644
index 0000000..bdbeff4
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/e_sqrt.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/e_sqrt.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/e_sqrtf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/e_sqrtf.c
new file mode 100644
index 0000000..8b2f552
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/e_sqrtf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/e_sqrtf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fclrexcpt.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fclrexcpt.c
new file mode 100644
index 0000000..d937ec0
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fclrexcpt.c
@@ -0,0 +1,48 @@
+/* Clear given exceptions in current floating-point environment.
+   Copyright (C) 2004 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 <fenv_libc.h>
+
+#undef feclearexcept
+int
+__feclearexcept (int excepts)
+{
+  unsigned int fpescr;
+
+  /* Get the current state.  */
+  fpescr = fegetenv_register ();
+
+  /* Clear the relevant bits.  */
+  fpescr &= ~(excepts & FE_ALL_EXCEPT);
+
+  /* Put the new state in effect.  */
+  fesetenv_register (fpescr);
+
+  /* Success.  */
+  return 0;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__feclearexcept, __old_feclearexcept)
+compat_symbol (libm, __old_feclearexcept, feclearexcept, GLIBC_2_1);
+#endif
+
+libm_hidden_ver (__feclearexcept, feclearexcept)
+versioned_symbol (libm, __feclearexcept, feclearexcept, GLIBC_2_2);
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fe_nomask.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fe_nomask.c
new file mode 100644
index 0000000..ba45d85
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fe_nomask.c
@@ -0,0 +1,32 @@
+/* Procedure definition for FE_NOMASK_ENV.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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 <fenv.h>
+#include <errno.h>
+
+/* This is presently a stub, until it's decided how the kernels should
+   support this.  */
+
+const fenv_t *
+__fe_nomask_env(void)
+{
+  __set_errno (ENOSYS);
+  return FE_ENABLED_ENV;
+}
+stub_warning (__fe_nomask_env)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fedisblxcpt.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fedisblxcpt.c
new file mode 100644
index 0000000..072a39d
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fedisblxcpt.c
@@ -0,0 +1,60 @@
+/* Disable floating-point exceptions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+
+int
+fedisableexcept (int excepts)
+{
+  unsigned int result = 0, pflags, r;
+  INTERNAL_SYSCALL_DECL (err);
+
+  INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags);
+
+  /* Save old enable bits.  */
+  if (pflags & PR_FP_EXC_OVF) 
+    result |= FE_OVERFLOW;
+  if (pflags & PR_FP_EXC_UND) 
+    result |= FE_UNDERFLOW;
+  if (pflags & PR_FP_EXC_INV) 
+    result |= FE_INVALID;
+  if (pflags & PR_FP_EXC_DIV) 
+    result |= FE_DIVBYZERO;
+  if (pflags & PR_FP_EXC_RES) 
+    result |= FE_INEXACT;
+
+  if (excepts & FE_INEXACT)
+    pflags &=  ~PR_FP_EXC_RES;
+  if (excepts & FE_DIVBYZERO)
+    pflags &= ~PR_FP_EXC_DIV;
+  if (excepts & FE_UNDERFLOW)
+    pflags &= ~PR_FP_EXC_UND;
+  if (excepts & FE_OVERFLOW)
+    pflags &= ~PR_FP_EXC_OVF;
+  if (excepts & FE_INVALID)
+    pflags &= ~PR_FP_EXC_INV;
+  r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags);
+  if (INTERNAL_SYSCALL_ERROR_P (r, err))
+    return -1;
+
+  return result;
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/feenablxcpt.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/feenablxcpt.c
new file mode 100644
index 0000000..4a36a27
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/feenablxcpt.c
@@ -0,0 +1,60 @@
+/* Enable floating-point exceptions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+
+int
+feenableexcept (int excepts)
+{
+  unsigned int result = 0, pflags, r;
+  INTERNAL_SYSCALL_DECL (err);
+
+  INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags);
+
+  /* Save old enable bits.  */
+  if (pflags & PR_FP_EXC_OVF) 
+    result |= FE_OVERFLOW;
+  if (pflags & PR_FP_EXC_UND) 
+    result |= FE_UNDERFLOW;
+  if (pflags & PR_FP_EXC_INV) 
+    result |= FE_INVALID;
+  if (pflags & PR_FP_EXC_DIV) 
+    result |= FE_DIVBYZERO;
+  if (pflags & PR_FP_EXC_RES) 
+    result |= FE_INEXACT;
+
+  if (excepts & FE_INEXACT)
+    pflags |= PR_FP_EXC_RES;
+  if (excepts & FE_DIVBYZERO)
+    pflags |= PR_FP_EXC_DIV;
+  if (excepts & FE_UNDERFLOW)
+    pflags |= PR_FP_EXC_UND;
+  if (excepts & FE_OVERFLOW)
+    pflags |= PR_FP_EXC_OVF;
+  if (excepts & FE_INVALID)
+    pflags |= PR_FP_EXC_INV;
+  r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags);
+  if (INTERNAL_SYSCALL_ERROR_P (r, err))
+    return -1;
+
+  return result;
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetenv.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetenv.c
new file mode 100644
index 0000000..2ab9f51
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetenv.c
@@ -0,0 +1,46 @@
+/* Store current floating-point environment.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004
+   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 <fenv_libc.h>
+#include <bp-sym.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+
+int
+__fegetenv (fenv_t *envp)
+{
+  fenv_union_t u;
+  INTERNAL_SYSCALL_DECL (err);
+
+  INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]);
+  u.l[1] = fegetenv_register ();
+  *envp = u.fenv;
+
+  /* Success.  */
+  return 0;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__fegetenv, __old_fegetenv)
+compat_symbol (libm, BP_SYM (__old_fegetenv), BP_SYM (fegetenv), GLIBC_2_1);
+#endif
+
+versioned_symbol (libm, BP_SYM (__fegetenv), BP_SYM (fegetenv), GLIBC_2_2);
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetexcept.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetexcept.c
new file mode 100644
index 0000000..bfd4481
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetexcept.c
@@ -0,0 +1,31 @@
+/* Get floating-point exceptions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+
+int
+fegetexcept (void)
+{
+  unsigned long fpescr;
+
+  fpescr = fegetenv_register ();
+
+  return fpescr & FE_ALL_EXCEPT;
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetround.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetround.c
new file mode 100644
index 0000000..4bb18ce
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fegetround.c
@@ -0,0 +1,31 @@
+/* Return current rounding direction.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+
+#undef fegetround
+int
+fegetround (void)
+{
+  unsigned long fpescr;
+
+  fpescr = fegetenv_register ();
+  return fpescr & 3;
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/feholdexcpt.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/feholdexcpt.c
new file mode 100644
index 0000000..04cc030
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/feholdexcpt.c
@@ -0,0 +1,45 @@
+/* Store current floating-point environment and clear exceptions.
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+
+int
+feholdexcept (fenv_t *envp)
+{
+  fenv_union_t u;
+  INTERNAL_SYSCALL_DECL (err);
+
+
+  /* Get the current state.  */
+  INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]);
+  u.l[1] = fegetenv_register ();
+  *envp = u.fenv;
+
+  /* Clear everything except for the rounding mode.  */
+  u.l[1] &= 3;
+
+  /* Put the new state in effect.  */
+  fesetenv_register (u.l[1]);
+
+  return 0;
+}
+libm_hidden_def (feholdexcept)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fenv_const.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fenv_const.c
new file mode 100644
index 0000000..073fc92
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fenv_const.c
@@ -0,0 +1,27 @@
+/* Constants for fenv_bits.h.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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.  */
+
+/* If the default argument is used we use this value.  */
+const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) =
+0x0ULL;
+
+/* Floating-point environment where none of the exceptions are masked.  */
+const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) =
+0xF00000000ULL;
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fenv_libc.h b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fenv_libc.h
new file mode 100644
index 0000000..cd003ea
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fenv_libc.h
@@ -0,0 +1,77 @@
+/* Internal libc stuff for floating point environment routines.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004
+   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 _FENV_LIBC_H
+#define _FENV_LIBC_H	1
+
+#include <fenv.h>
+
+extern int __feraiseexcept_internal (int __excepts);
+
+/* Equivalent to fegetenv, but returns a fenv_t instead of taking a
+   pointer.  */
+#define fegetenv_register() \
+        ({ unsigned fscr; asm volatile ("mfspefscr %0" : "=r" (fscr)); fscr; })
+
+/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer.  */
+#define fesetenv_register(fscr) \
+	({ asm volatile ("mtspefscr %0" : : "r" (fscr)); })
+
+typedef union
+{
+  fenv_t fenv;
+  unsigned int l[2];
+} fenv_union_t;
+
+/* Definitions of all the SPEFSCR bit numbers.  */
+enum {
+  SPEFSCR_SOVH          = 0x80000000,
+  SPEFSCR_OVH           = 0x40000000,
+  SPEFSCR_FGH           = 0x20000000,
+  SPEFSCR_FXH           = 0x10000000,
+  SPEFSCR_FINVH         = 0x08000000,
+  SPEFSCR_FDBZH         = 0x04000000,
+  SPEFSCR_FUNFH         = 0x02000000,
+  SPEFSCR_FOVFH         = 0x01000000,
+  /* 2 unused bits.  */
+  SPEFSCR_FINXS         = 0x00200000,
+  SPEFSCR_FINVS         = 0x00100000,
+  SPEFSCR_FDBZS         = 0x00080000,
+  SPEFSCR_FUNFS         = 0x00040000,
+  SPEFSCR_FOVFS         = 0x00020000,
+  SPEFSCR_MODE          = 0x00010000,
+  SPEFSCR_SOV           = 0x00008000,
+  SPEFSCR_OV            = 0x00004000,
+  SPEFSCR_FG            = 0x00002000,
+  SPEFSCR_FX            = 0x00001000,
+  SPEFSCR_FINV          = 0x00000800,
+  SPEFSCR_FDBZ          = 0x00000400,
+  SPEFSCR_FUNF          = 0x00000200,
+  SPEFSCR_FOVF          = 0x00000100,
+  /* 1 unused bit.  */
+  SPEFSCR_FINXE         = 0x00000040,
+  SPEFSCR_FINVE         = 0x00000020,
+  SPEFSCR_FDBZE         = 0x00000010,
+  SPEFSCR_FUNFE         = 0x00000008,
+  SPEFSCR_FOVFE         = 0x00000004,
+  SPEFSCR_FRMC          = 0x00000003
+};
+
+#endif /* fenv_libc.h */
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fesetenv.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fesetenv.c
new file mode 100644
index 0000000..5ecf4c4
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fesetenv.c
@@ -0,0 +1,46 @@
+/* Install given floating-point environment.
+   Copyright (C) 1997,99,2000,01,02 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 <fenv_libc.h>
+#include <bp-sym.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+
+int
+__fesetenv (const fenv_t *envp)
+{
+  fenv_union_t u;
+  INTERNAL_SYSCALL_DECL (err);
+
+  u.fenv = *envp;
+  INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, &u.l[0]);
+  fesetenv_register (u.l[1]);
+
+  /* Success.  */
+  return 0;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__fesetenv, __old_fesetenv)
+compat_symbol (libm, BP_SYM (__old_fesetenv), BP_SYM (fesetenv), GLIBC_2_1);
+#endif
+
+libm_hidden_ver (__fesetenv, fesetenv)
+versioned_symbol (libm, BP_SYM (__fesetenv), BP_SYM (fesetenv), GLIBC_2_2);
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fesetround.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fesetround.c
new file mode 100644
index 0000000..b25d8b3
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fesetround.c
@@ -0,0 +1,37 @@
+/* Set current rounding direction.
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+
+int
+fesetround (int round)
+{
+  unsigned long fpescr;
+
+  if ((unsigned int) round > 3)
+    return 1;
+
+  fpescr = fegetenv_register ();
+  fpescr = (fpescr & ~SPEFSCR_FRMC) | (round & 3);
+  fesetenv_register (fpescr);
+
+  return 0;
+}
+libm_hidden_def (fesetround)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/feupdateenv.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/feupdateenv.c
new file mode 100644
index 0000000..effe9d5
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/feupdateenv.c
@@ -0,0 +1,58 @@
+/* Install given floating-point environment and raise exceptions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+#include <bp-sym.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+
+int
+__feupdateenv (const fenv_t *envp)
+{
+  unsigned long fpescr, old, new, pflags;
+  fenv_union_t u;
+  INTERNAL_SYSCALL_DECL (err);
+
+  /* Save the currently set exceptions.  */
+  u.fenv = *envp;
+  new = u.l[1];
+  old = fegetenv_register ();
+  new |= (old & FE_ALL_EXCEPT);
+
+  INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags);
+  pflags |= u.l[0];
+  INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags);
+
+  /* Enable and raise (if appropriate) exceptions set in `new'. */
+  fesetenv_register (new);
+  feraiseexcept (new & FE_ALL_EXCEPT);
+
+  /* Success.  */
+  return 0;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__feupdateenv, __old_feupdateenv)
+compat_symbol (libm, BP_SYM (__old_feupdateenv), BP_SYM (feupdateenv), GLIBC_2_1);
+#endif
+
+libm_hidden_ver (__feupdateenv, feupdateenv)
+versioned_symbol (libm, BP_SYM (__feupdateenv), BP_SYM (feupdateenv), GLIBC_2_2);
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fgetexcptflg.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fgetexcptflg.c
new file mode 100644
index 0000000..93459f8
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fgetexcptflg.c
@@ -0,0 +1,47 @@
+/* Store current representation for exceptions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+#include <bp-sym.h>
+
+int
+__fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+  unsigned long fpescr;
+
+  /* Get the current state.  */
+  fpescr = fegetenv_register ();
+
+  /* ?? Classic PPC doesn't do anything with `excepts', so we'll do
+     the same here.  (We should really be ignoring exceptions in
+     excepts) ??  */
+  *flagp = fpescr & FE_ALL_EXCEPT;
+
+  /* Success.  */
+  return 0;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__fegetexceptflag, __old_fegetexceptflag)
+compat_symbol (libm, BP_SYM (__old_fegetexceptflag), BP_SYM (fegetexceptflag), GLIBC_2_1);
+#endif
+
+versioned_symbol (libm, BP_SYM (__fegetexceptflag), BP_SYM (fegetexceptflag), GLIBC_2_2);
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fprrest.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fprrest.c
new file mode 100644
index 0000000..1cc8931
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fprrest.c
@@ -0,0 +1 @@
+/* Not needed.  */
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fprsave.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fprsave.c
new file mode 100644
index 0000000..1cc8931
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fprsave.c
@@ -0,0 +1 @@
+/* Not needed.  */
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fraiseexcpt.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fraiseexcpt.c
new file mode 100644
index 0000000..0b55808
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fraiseexcpt.c
@@ -0,0 +1,30 @@
+/* Raise given exceptions.
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+#include <bp-sym.h>
+
+#undef feraiseexcept
+
+#define __FERAISEEXCEPT_INTERNAL feraiseexcept
+#include "../spe-raise.c"
+
+strong_alias (feraiseexcept, __feraiseexcept)
+libm_hidden_def (feraiseexcept)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/fsetexcptflg.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fsetexcptflg.c
new file mode 100644
index 0000000..4794839
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/fsetexcptflg.c
@@ -0,0 +1,51 @@
+/* Set floating-point environment exception handling.
+   Copyright (C) 1997,99,2000,01,04 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 <fenv_libc.h>
+#include <bp-sym.h>
+
+int
+__fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+  unsigned long spefscr;
+  fexcept_t flag;
+
+  /* Get the current state.  */
+  spefscr = fegetenv_register ();
+
+  /* Ignore exceptions not listed in 'excepts'.  */
+  flag = *flagp & excepts;
+
+  /* Replace the exception status */
+  spefscr = (spefscr & ~(FE_ALL_EXCEPT & excepts)) | flag;
+
+  /* Store the new status word (along with the rest of the environment).  */
+  fesetenv_register (spefscr);
+
+  /* Success.  */
+  return 0;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__fesetexceptflag, __old_fesetexceptflag)
+compat_symbol (libm, BP_SYM (__old_fesetexceptflag), BP_SYM (fesetexceptflag), GLIBC_2_1);
+#endif
+
+versioned_symbol (libm, BP_SYM (__fesetexceptflag), BP_SYM (fesetexceptflag), GLIBC_2_2);
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/ftestexcept.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/ftestexcept.c
new file mode 100644
index 0000000..459af7b
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/ftestexcept.c
@@ -0,0 +1,33 @@
+/* Test exception in current environment.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+
+int
+fetestexcept (int excepts)
+{
+  unsigned long f;
+
+  /* Get the current state.  */
+  f = fegetenv_register ();
+
+  return f & excepts;
+}
+libm_hidden_def (fetestexcept)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/math_ldbl.h b/ports/sysdeps/powerpc/powerpc32/e500/fpu/math_ldbl.h
new file mode 100644
index 0000000..e99166b
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/math_ldbl.h
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/ldbl-128ibm/math_ldbl.h>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/math_private.h b/ports/sysdeps/powerpc/powerpc32/e500/fpu/math_private.h
new file mode 100644
index 0000000..4909535
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/math_private.h
@@ -0,0 +1,2 @@
+/* Bypass sysdeps/powerpc/fpu/math_private.h and use generic header.  */
+#include <../sysdeps/generic/math_private.h>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_ceil.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_ceil.c
new file mode 100644
index 0000000..f3f3421
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_ceil.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_ceil.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_ceilf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_ceilf.c
new file mode 100644
index 0000000..2a71fcd
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_ceilf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_ceilf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysign.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysign.c
new file mode 100644
index 0000000..8616ca0
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysign.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_copysign.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysignf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysignf.c
new file mode 100644
index 0000000..34bcb6c
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysignf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_copysignf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysignl.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysignl.c
new file mode 100644
index 0000000..29a0286
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_copysignl.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/ldbl-128ibm/s_copysignl.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabs.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabs.c
new file mode 100644
index 0000000..2ef531d
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabs.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_fabs.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabsf.S b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabsf.S
new file mode 100644
index 0000000..85b1f39
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabsf.S
@@ -0,0 +1,29 @@
+/* Floating-point absolute value.  PowerPC E500 version.
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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)
+/* float [r3] fabsf (float [r3] x) ;  */
+	efsabs r3,r3
+	blr
+END(__fabsf)
+
+weak_alias(__fabsf,fabsf)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabsl.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabsl.c
new file mode 100644
index 0000000..33ebe78
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fabsl.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/ldbl-128ibm/s_fabsl.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fdim.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fdim.c
new file mode 100644
index 0000000..5fb35ed
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fdim.c
@@ -0,0 +1 @@
+#include <math/s_fdim.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fdimf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fdimf.c
new file mode 100644
index 0000000..42df130
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fdimf.c
@@ -0,0 +1 @@
+#include <math/s_fdimf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_floor.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_floor.c
new file mode 100644
index 0000000..2a43c81
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_floor.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_floor.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_floorf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_floorf.c
new file mode 100644
index 0000000..d129d37
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_floorf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_floorf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fma.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fma.c
new file mode 100644
index 0000000..40efd24
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fma.c
@@ -0,0 +1 @@
+#include <math/s_fma.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmaf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmaf.c
new file mode 100644
index 0000000..5b7663f
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmaf.c
@@ -0,0 +1 @@
+#include <math/s_fmaf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmax.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmax.c
new file mode 100644
index 0000000..95edd5f
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmax.c
@@ -0,0 +1 @@
+#include <math/s_fmax.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmaxf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmaxf.c
new file mode 100644
index 0000000..084fe72
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmaxf.c
@@ -0,0 +1 @@
+#include <math/s_fmaxf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmin.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmin.c
new file mode 100644
index 0000000..e072a91
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fmin.c
@@ -0,0 +1 @@
+#include <math/s_fmin.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fminf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fminf.c
new file mode 100644
index 0000000..e37e4ac
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_fminf.c
@@ -0,0 +1 @@
+#include <math/s_fminf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_isnan.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_isnan.c
new file mode 100644
index 0000000..dec5dd0
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_isnan.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_isnan.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_isnanf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_isnanf.c
new file mode 100644
index 0000000..3be64a2
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_isnanf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_isnanf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llrint.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llrint.c
new file mode 100644
index 0000000..c8215aa
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llrint.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_llrint.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llrintf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llrintf.c
new file mode 100644
index 0000000..b74275e
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llrintf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_llrintf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llround.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llround.c
new file mode 100644
index 0000000..69658f3
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llround.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_llround.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llroundf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llroundf.c
new file mode 100644
index 0000000..386777e
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_llroundf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_llroundf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lrint.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lrint.c
new file mode 100644
index 0000000..909e699
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lrint.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_lrint.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lrintf.S b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lrintf.S
new file mode 100644
index 0000000..e94ec25
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lrintf.S
@@ -0,0 +1,29 @@
+/* Round float to long int.  PowerPC E500 version.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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(__lrintf)
+/* long int [r3] lrintf (float [r3] x) ;  */
+	efsctsi r3,r3
+	blr
+END(__lrintf)
+
+weak_alias(__lrintf,lrintf)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lround.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lround.c
new file mode 100644
index 0000000..83a8783
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lround.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_lround.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lroundf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lroundf.c
new file mode 100644
index 0000000..930abb5
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_lroundf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_lroundf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_rint.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_rint.c
new file mode 100644
index 0000000..b610359
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_rint.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_rint.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_rintf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_rintf.c
new file mode 100644
index 0000000..6593140
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_rintf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_rintf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_round.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_round.c
new file mode 100644
index 0000000..4c006d4
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_round.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_round.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_roundf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_roundf.c
new file mode 100644
index 0000000..e82d90a
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_roundf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_roundf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_trunc.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_trunc.c
new file mode 100644
index 0000000..bc5ec54
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_trunc.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/dbl-64/s_trunc.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_truncf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_truncf.c
new file mode 100644
index 0000000..b8cc5f6
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/s_truncf.c
@@ -0,0 +1 @@
+#include <sysdeps/ieee754/flt-32/s_truncf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/setjmp-common.S b/ports/sysdeps/powerpc/powerpc32/e500/fpu/setjmp-common.S
new file mode 100644
index 0000000..311f158
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/setjmp-common.S
@@ -0,0 +1,108 @@
+/* setjmp for PowerPC E500.
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>.
+
+   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 _ASM
+#ifdef __NO_VMX__
+# include <novmxsetjmp.h>
+#else
+# include <jmpbuf-offsets.h>
+#endif
+#include <bp-sym.h>
+#include <bp-asm.h>
+
+ENTRY (BP_SYM (__sigsetjmp))
+	CHECK_BOUNDS_BOTH_WIDE_LIT (r3, r8, r9, JB_SIZE)
+
+#ifdef PTR_MANGLE
+	mr   r5,r1
+	PTR_MANGLE(r5, r10)
+	stw  r5,(JB_GPR1*4)(3)
+#else
+	stw  r1,(JB_GPR1*4)(3)
+#endif
+	mflr r0
+	stw  r14,((JB_GPRS+0)*4)(3)
+#ifdef PTR_MANGLE
+	PTR_MANGLE2 (r0, r10)
+	li   r10,0
+#endif
+	/*stfd fp14,((JB_FPRS+0*2)*4)(3)*/
+	evstdd r14,((JB_FPRS+0*2)*4)(3)
+	stw  r0,(JB_LR*4)(3)
+	stw  r15,((JB_GPRS+1)*4)(3)
+	/*stfd fp15,((JB_FPRS+1*2)*4)(3)*/
+	evstdd r15,((JB_FPRS+1*2)*4)(3)
+	mfcr r0
+	stw  r16,((JB_GPRS+2)*4)(3)
+	/*stfd fp16,((JB_FPRS+2*2)*4)(3)*/
+	evstdd r16,((JB_FPRS+2*2)*4)(3)
+	stw  r0,(JB_CR*4)(3)
+	stw  r17,((JB_GPRS+3)*4)(3)
+	/*stfd fp17,((JB_FPRS+3*2)*4)(3)*/
+	evstdd r17,((JB_FPRS+3*2)*4)(3)
+	stw  r18,((JB_GPRS+4)*4)(3)
+	/*stfd fp18,((JB_FPRS+4*2)*4)(3)*/
+	evstdd r18,((JB_FPRS+4*2)*4)(3)
+	stw  r19,((JB_GPRS+5)*4)(3)
+	/*stfd fp19,((JB_FPRS+5*2)*4)(3)*/
+	evstdd r19,((JB_FPRS+5*2)*4)(3)
+	stw  r20,((JB_GPRS+6)*4)(3)
+	/*stfd fp20,((JB_FPRS+6*2)*4)(3)*/
+	evstdd r20,((JB_FPRS+6*2)*4)(3)
+	stw  r21,((JB_GPRS+7)*4)(3)
+	/*stfd fp21,((JB_FPRS+7*2)*4)(3)*/
+	evstdd r21,((JB_FPRS+7*2)*4)(3)
+	stw  r22,((JB_GPRS+8)*4)(3)
+	/*stfd fp22,((JB_FPRS+8*2)*4)(3)*/
+	evstdd r22,((JB_FPRS+8*2)*4)(3)
+	stw  r23,((JB_GPRS+9)*4)(3)
+	/*stfd fp23,((JB_FPRS+9*2)*4)(3)*/
+	evstdd r23,((JB_FPRS+9*2)*4)(3)
+	stw  r24,((JB_GPRS+10)*4)(3)
+	/*stfd fp24,((JB_FPRS+10*2)*4)(3)*/
+	evstdd r24,((JB_FPRS+10*2)*4)(3)
+	stw  r25,((JB_GPRS+11)*4)(3)
+	/*stfd fp25,((JB_FPRS+11*2)*4)(3)*/
+	evstdd r25,((JB_FPRS+11*2)*4)(3)
+	stw  r26,((JB_GPRS+12)*4)(3)
+	/*stfd fp26,((JB_FPRS+12*2)*4)(3)*/
+	evstdd r26,((JB_FPRS+12*2)*4)(3)
+	stw  r27,((JB_GPRS+13)*4)(3)
+	/*stfd fp27,((JB_FPRS+13*2)*4)(3)*/
+	evstdd r27,((JB_FPRS+13*2)*4)(3)
+	stw  r28,((JB_GPRS+14)*4)(3)
+	/*stfd fp28,((JB_FPRS+14*2)*4)(3)*/
+	evstdd r28,((JB_FPRS+14*2)*4)(3)
+	stw  r29,((JB_GPRS+15)*4)(3)
+	/*stfd fp29,((JB_FPRS+15*2)*4)(3)*/
+	evstdd r29,((JB_FPRS+15*2)*4)(3)
+	stw  r30,((JB_GPRS+16)*4)(3)
+	/*stfd fp30,((JB_FPRS+16*2)*4)(3)*/
+	evstdd r30,((JB_FPRS+16*2)*4)(3)
+	stw  r31,((JB_GPRS+17)*4)(3)
+	/*stfd fp31,((JB_FPRS+17*2)*4)(3)*/
+	evstdd r31,((JB_FPRS+17*2)*4)(3)
+#if defined NOT_IN_libc && defined IS_IN_rtld
+	li   r3,0
+	blr
+#else
+	b BP_SYM (__sigjmp_save@local)
+#endif
+END (BP_SYM (__sigsetjmp))
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/setjmp.S b/ports/sysdeps/powerpc/powerpc32/e500/fpu/setjmp.S
new file mode 100644
index 0000000..ef3514a
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/setjmp.S
@@ -0,0 +1,44 @@
+/* non alitivec (old) version of setjmp for PowerPC.
+   Copyright (C) 1995-1997,1999-2001,2004 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 <shlib-compat.h>
+#include <libc-symbols.h>
+
+#if defined NOT_IN_libc
+/* Build a non-versioned object for rtld-*.  */
+# include "setjmp-common.S"
+
+#else /* !NOT_IN_libc */
+/* Build a versioned object for libc.  */
+default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4)
+# define __sigsetjmp __vmx__sigsetjmp
+# define __sigjmp_save __vmx__sigjmp_save
+# include "setjmp-common.S"
+
+# if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+#  define __NO_VMX__
+#  undef __sigsetjmp
+#  undef __sigjmp_save
+#  undef JB_SIZE
+symbol_version (__novmx__sigsetjmp,__sigsetjmp,GLIBC_2.0)
+#  define __sigsetjmp __novmx__sigsetjmp
+#  define __sigjmp_save __novmx__sigjmp_save
+#  include "setjmp-common.S"
+# endif
+#endif /* !NOT_IN_libc */
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/spe.h b/ports/sysdeps/powerpc/powerpc32/e500/fpu/spe.h
new file mode 100644
index 0000000..91bca27
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/spe.h
@@ -0,0 +1,12 @@
+#ifndef _SPE_H
+
+#include_next <spe.h>
+
+libc_hidden_proto (strtosfix16)
+libc_hidden_proto (strtosfix32)
+libc_hidden_proto (strtosfix64)
+libc_hidden_proto (strtoufix16)
+libc_hidden_proto (strtoufix32)
+libc_hidden_proto (strtoufix64)
+
+#endif
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtofix.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtofix.c
new file mode 100644
index 0000000..63628f6
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtofix.c
@@ -0,0 +1,702 @@
+/* Convert string representing a number to float value, using given locale.
+   Copyright (C) 1997,1998,2002,2004,2005,2006,2008
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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.  */
+
+/* Cut down from strtod_l.c for converting to fixed-point, no locale
+   choice, no grouping, narrow strings only.  */
+
+
+#include <ctype.h>
+#include <errno.h>
+#include <fenv_libc.h>
+#include <locale/localeinfo.h>
+#include <locale.h>
+#include <math.h>
+#include <spe.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* The gmp headers need some configuration frobs.  */
+#define HAVE_ALLOCA 1
+
+/* Include gmp-mparam.h first, such that definitions of _SHORT_LIMB
+   and _LONG_LONG_LIMB in it can take effect into gmp.h.  */
+#include <gmp-mparam.h>
+#include <gmp.h>
+#include <stdlib/gmp-impl.h>
+#include <stdlib/longlong.h>
+#include <stdlib/fpioconst.h>
+
+/*#define NDEBUG 1*/
+#include <assert.h>
+
+#if UNSIGNED
+#define RETURN_FRAC_BITS RETURN_TYPE_BITS
+#else
+#define RETURN_FRAC_BITS (RETURN_TYPE_BITS - 1)
+#endif
+
+#define RETURN(val,end)					\
+    do { if (endptr != NULL) *endptr = (char *) (end);	\
+	 return val; } while (0)
+
+/* Definitions according to limb size used.  */
+#if	BITS_PER_MP_LIMB == 32
+# define MAX_DIG_PER_LIMB	9
+# define MAX_FAC_PER_LIMB	1000000000UL
+#elif	BITS_PER_MP_LIMB == 64
+# define MAX_DIG_PER_LIMB	19
+# define MAX_FAC_PER_LIMB	10000000000000000000ULL
+#else
+# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+
+/* Local data structure.  */
+static const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
+{    0,                   10,                   100,
+     1000,                10000,                100000L,
+     1000000L,            10000000L,            100000000L,
+     1000000000L
+#if BITS_PER_MP_LIMB > 32
+	        ,	  10000000000ULL,       100000000000ULL,
+     1000000000000ULL,    10000000000000ULL,    100000000000000ULL,
+     1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL,
+     1000000000000000000ULL, 10000000000000000000ULL
+#endif
+#if BITS_PER_MP_LIMB > 64
+  #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB
+#endif
+};
+
+/* Define pow5 to be 5^(RETURN_FRAC_BITS + 1), shifted left so the
+   most significant bit is set (as required by mpn_divrem), pow5size
+   to be the size in limbs and pow5shift to be the shift.  */
+#if RETURN_FRAC_BITS + 1 == 16
+# if BITS_PER_MP_LIMB == 32
+static const mp_limb_t pow5[] = { 0x04000000, 0x8e1bc9bf };
+#  define pow5shift 26
+#  define pow5size 2
+# else
+static const mp_limb_t pow5[] = { 0x8e1bc9bf04000000ull };
+#  define pow5shift 26
+#  define pow5size 1
+# endif
+#elif RETURN_FRAC_BITS + 1 == 17
+# if BITS_PER_MP_LIMB == 32
+static const mp_limb_t pow5[] = { 0xc5000000, 0xb1a2bc2e };
+#  define pow5shift 24
+#  define pow5size 2
+# else
+static const mp_limb_t pow5[] = { 0xb1a2bc2ec5000000ull };
+#  define pow5shift 24
+#  define pow5size 1
+# endif
+#elif RETURN_FRAC_BITS + 1 == 32
+# if BITS_PER_MP_LIMB == 32
+static const mp_limb_t pow5[] = { 0xf0200000, 0x2b70b59d, 0x9dc5ada8 };
+#  define pow5shift 21
+#  define pow5size 3
+# else
+static const mp_limb_t pow5[] = { 0xf020000000000000ull, 0x9dc5ada82b70b59dull };
+#  define pow5shift 53
+#  define pow5size 2
+# endif
+#elif RETURN_FRAC_BITS + 1 == 33
+# if BITS_PER_MP_LIMB == 32
+static const mp_limb_t pow5[] = { 0x6c280000, 0x364ce305, 0xc5371912 };
+#  define pow5shift 19
+#  define pow5size 3
+# else
+static const mp_limb_t pow5[] = { 0x6c28000000000000ull, 0xc5371912364ce305ull };
+#  define pow5shift 51
+#  define pow5size 2
+# endif
+#elif RETURN_FRAC_BITS + 1 == 64
+# if BITS_PER_MP_LIMB == 32
+static const mp_limb_t pow5[] = { 0x50f80800, 0xc76b25fb, 0x3cbf6b71, 0xffcfa6d5, 0xc2781f49 };
+#  define pow5shift 11
+#  define pow5size 5
+# else
+static const mp_limb_t pow5[] = { 0x50f8080000000000ull, 0x3cbf6b71c76b25fbull, 0xc2781f49ffcfa6d5ull };
+#  define pow5shift 43
+#  define pow5size 3
+# endif
+#elif RETURN_FRAC_BITS + 1 == 65
+# if BITS_PER_MP_LIMB == 32
+static const mp_limb_t pow5[] = { 0x25360a00, 0x3945ef7a, 0x8bef464e, 0x7fc3908a, 0xf316271c };
+#  define pow5shift 9
+#  define pow5size 5
+# else
+static const mp_limb_t pow5[] = { 0x25360a0000000000ull, 8bef464e3945ef7aull, 0xf316271c7fc3908aull };
+#  define pow5shift 41
+#  define pow5size 3
+# endif
+#else
+# error "Unknown RETURN_FRAC_BITS value."
+#endif
+
+/* Read a multi-precision integer starting at STR with exactly DIGCNT digits
+   into N.  Return the size of the number limbs in NSIZE.  */
+static void
+str_to_mpn (const char *str, int digcnt, mp_limb_t *n, mp_size_t *nsize)
+{
+  /* Number of digits for actual limb.  */
+  int cnt = 0;
+  mp_limb_t low = 0;
+  mp_limb_t start;
+
+  *nsize = 0;
+  assert (digcnt > 0);
+  do
+    {
+      if (cnt == MAX_DIG_PER_LIMB)
+	{
+	  if (*nsize == 0)
+	    {
+	      n[0] = low;
+	      *nsize = 1;
+	    }
+	  else
+	    {
+	      mp_limb_t cy;
+	      cy = __mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB);
+	      cy += __mpn_add_1 (n, n, *nsize, low);
+	      if (cy != 0)
+		{
+		  n[*nsize] = cy;
+		  ++(*nsize);
+		}
+	    }
+	  cnt = 0;
+	  low = 0;
+	}
+
+      low = low * 10 + *str++ - '0';
+      ++cnt;
+    }
+  while (--digcnt > 0);
+
+  start = _tens_in_limb[cnt];
+
+  if (*nsize == 0)
+    {
+      n[0] = low;
+      *nsize = 1;
+    }
+  else
+    {
+      mp_limb_t cy;
+      cy = __mpn_mul_1 (n, n, *nsize, start);
+      cy += __mpn_add_1 (n, n, *nsize, low);
+      if (cy != 0)
+	n[(*nsize)++] = cy;
+    }
+}
+
+/* Round a fixed point number according to the current rounding mode
+   and set its sign.  VAL is the initial part of the number
+   (RETURN_TYPE_BITS for unsigned, one fewer for signed; values equal
+   to -1.0 do not come here).  SIGN is 1 for negative, 0 for positive;
+   this function will not be called for negative numbers in the
+   unsigned case.  HALF is 1 if the next bit is 1; REST is 1 if any of
+   the subsequent bits are 1.  */
+static RETURN_TYPE
+round_and_set_sign (RETURN_TYPE val, int sign, int half, int rest)
+{
+  int incr = 0;
+  unsigned int mode = fegetenv_register ();
+  mode &= 3;
+  switch (mode)
+    {
+    case FE_TONEAREST:
+      incr = (half && (rest || (val & 1)));
+      break;
+    case FE_TOWARDZERO:
+      break;
+    case FE_UPWARD:
+      incr = (!sign && (half || rest));
+      break;
+    case FE_DOWNWARD:
+      incr = (sign && (half || rest));
+      break;
+    }
+  if (incr)
+    {
+      if (val == SAT_MAX)
+	{
+	  if (sign)
+	    val = SAT_MIN;
+	  else
+	    {
+	      __set_errno (ERANGE);
+	      return SAT_MAX;
+	    }
+	}
+      else
+	{
+	  val++;
+	  if (sign)
+	    val = -val;
+	}
+    }
+  else if (sign)
+    val = -val;
+  return val;
+}
+
+/* Return a fixed point number with the value of the given string
+   NPTR, handling out-of-range numbers as described in the SPE PIM.
+   Set *ENDPTR to the character after the last used one.  */
+RETURN_TYPE
+STRTOFIX (const char *nptr, char **endptr)
+{
+  int negative;			/* The sign of the number.  */
+  int exponent;			/* Exponent of the number.  */
+
+  /* Numbers starting `0X' or `0x' have to be processed with base 16.  */
+  int base = 10;
+
+  /* Running pointer after the last character processed in the string.  */
+  const char *cp;
+  /* Start of significant part of the number.  */
+  const char *startp, *start_of_digits;
+  /* Points at the character following the integer and fractional digits.  */
+  const char *expp;
+  /* Total number of digit and number of digits in integer part.  */
+  int dig_no, int_no, lead_zero;
+  /* Contains the last character read.  */
+  char c;
+
+  /* The radix character of the current locale.  */
+  const char *decimal;
+  size_t decimal_len;
+  /* Used in several places.  */
+  int cnt;
+
+  decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
+  decimal_len = strlen (decimal);
+  assert (decimal_len > 0);
+
+  /* Prepare number representation.  */
+  exponent = 0;
+  negative = 0;
+
+  /* Parse string to get maximal legal prefix.  We need the number of
+     characters of the integer part, the fractional part and the exponent.  */
+  cp = nptr - 1;
+  /* Ignore leading white space.  */
+  do
+    c = *++cp;
+  while (isspace (c));
+
+  /* Get sign of the result.  */
+  if (c == '-')
+    {
+      negative = 1;
+      c = *++cp;
+    }
+  else if (c == '+')
+    c = *++cp;
+
+  /* Return 0.0 if no legal string is found.
+     No character is used even if a sign was found.  */
+  for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+    if (cp[cnt] != decimal[cnt])
+      break;
+  if (decimal[cnt] == '\0' && cp[cnt] >= '0' && cp[cnt] <= '9')
+    {
+      /* We accept it.  This funny construct is here only to indent
+	 the code directly.  */
+    }
+  else if (c < '0' || c > '9')
+    {
+      /* The SPE PIM says NaN and Inf are not supported.  */
+      /* It is really a text we do not recognize.  */
+      RETURN (0, nptr);
+    }
+
+  /* First look whether we are faced with a hexadecimal number.  */
+  if (c == '0' && tolower (cp[1]) == 'x')
+    {
+      /* Okay, it is a hexa-decimal number.  Remember this and skip
+	 the characters.  BTW: hexadecimal numbers must not be
+	 grouped.  */
+      base = 16;
+      cp += 2;
+      c = *cp;
+    }
+
+  /* Record the start of the digits, in case we will check their grouping.  */
+  start_of_digits = startp = cp;
+
+  /* Ignore leading zeroes.  This helps us to avoid useless computations.  */
+  while (c == '0')
+    c = *++cp;
+
+  /* If no other digit but a '0' is found the result is 0.0.
+     Return current read pointer.  */
+  if ((c < '0' || c > '9')
+      && (base != 16 || (c < (char) tolower ('a')
+			 || c > (char) tolower ('f')))
+      && ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+	      if (decimal[cnt] != cp[cnt])
+		break;
+	    decimal[cnt] != '\0'; })
+      && (base != 16 || (cp == start_of_digits
+			 || (char) tolower (c) != 'p'))
+      && (base == 16 || (char) tolower (c) != 'e'))
+    {
+      /* If CP is at the start of the digits, there was no correctly
+	 grouped prefix of the string; so no number found.  */
+      RETURN (0, cp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : cp);
+    }
+
+  /* Remember first significant digit and read following characters until the
+     decimal point, exponent character or any non-FP number character.  */
+  startp = cp;
+  dig_no = 0;
+  while (1)
+    {
+      if ((c >= '0' && c <= '9')
+	  || (base == 16 && tolower (c) >= 'a'
+	      && tolower (c) <= 'f'))
+	++dig_no;
+      else
+	{
+	  break;
+	}
+      c = *++cp;
+    }
+
+  /* We have the number digits in the integer part.  Whether these are all or
+     any is really a fractional digit will be decided later.  */
+  int_no = dig_no;
+  lead_zero = int_no == 0 ? -1 : 0;
+
+  /* Read the fractional digits.  A special case are the 'american style'
+     numbers like `16.' i.e. with decimal but without trailing digits.  */
+  if (
+      ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+	   if (decimal[cnt] != cp[cnt])
+	     break;
+	 decimal[cnt] == '\0'; })
+      )
+    {
+      cp += decimal_len;
+      c = *cp;
+      while ((c >= '0' && c <= '9') ||
+	     (base == 16 && tolower (c) >= 'a' && tolower (c) <= 'f'))
+	{
+	  if (c != '0' && lead_zero == -1)
+	    lead_zero = dig_no - int_no;
+	  ++dig_no;
+	  c = *++cp;
+	}
+    }
+
+  /* For numbers like "0x." with no hex digits, only the "0" is valid.  */
+  if (base == 16
+      && startp == start_of_digits
+      && dig_no == 0)
+    RETURN (0, start_of_digits - 1);
+
+  /* Remember start of exponent (if any).  */
+  expp = cp;
+
+  /* Read exponent.  */
+  if ((base == 16 && tolower (c) == 'p')
+      || (base != 16 && tolower (c) == 'e'))
+    {
+      int exp_negative = 0;
+
+      c = *++cp;
+      if (c == '-')
+	{
+	  exp_negative = 1;
+	  c = *++cp;
+	}
+      else if (c == '+')
+	c = *++cp;
+
+      if (c >= '0' && c <= '9')
+	{
+	  int exp_limit;
+
+	  /* Get the exponent limit. */
+	  if (base == 16)
+	    exp_limit = (exp_negative ?
+			 RETURN_TYPE_BITS + 4 * int_no :
+			 4 - 4 * int_no + 4 * lead_zero);
+	  else
+	    exp_limit = (exp_negative ?
+			 (RETURN_TYPE_BITS + 2) / 3 + int_no :
+			 1 - int_no + lead_zero);
+
+	  do
+	    {
+	      exponent *= 10;
+
+	      if (exponent > exp_limit)
+		/* The exponent is too large/small to represent a valid
+		   number.  */
+		{
+		  RETURN_TYPE result;
+
+		  /* Accept all following digits as part of the exponent.  */
+		  do
+		    ++cp;
+		  while (*cp >= '0' && *cp <= '9');
+
+		  /* We have to take care for special situation: a joker
+		     might have written "0.0e100000" which is in fact
+		     zero.  */
+		  if (lead_zero == -1)
+		    result = 0;
+#if UNSIGNED
+		  else if (negative)
+		    {
+		      /* Saturate to 0.  */
+		      __set_errno (ERANGE);
+		      result = SAT_MIN;
+		    }
+#endif
+		  else if (exp_negative)
+		    {
+		      /* Round to either 0 or smallest value.  */
+		      result = round_and_set_sign (0, negative, 0, 1);
+		    }
+		  else
+		    {
+		      /* Overflow.  */
+		      __set_errno (ERANGE);
+		      result = (negative ? SAT_MIN : SAT_MAX);
+		    }
+
+		  RETURN (result, cp);
+		  /* NOTREACHED */
+		}
+
+	      exponent += c - '0';
+	      c = *++cp;
+	    }
+	  while (c >= '0' && c <= '9');
+
+	  if (exp_negative)
+	    exponent = -exponent;
+	}
+      else
+	cp = expp;
+    }
+
+  /* We don't want to have to work with trailing zeroes after the radix.  */
+  if (dig_no > int_no)
+    {
+      while (expp[-1] == '0')
+	{
+	  --expp;
+	  --dig_no;
+	}
+      assert (dig_no >= int_no);
+    }
+
+  if (dig_no == int_no && dig_no > 0)
+    do
+      {
+	while (! (base == 16 ? isxdigit (expp[-1]) : isdigit (expp[-1])))
+	  --expp;
+
+	if (expp[-1] != '0')
+	  break;
+
+	--expp;
+	--dig_no;
+	--int_no;
+	exponent += (base == 16 ? 4 : 1);
+      }
+    while (dig_no > 0);
+
+  /* The whole string is parsed.  Store the address of the next character.  */
+  if (endptr)
+    *endptr = (char *) cp;
+
+  if (dig_no == 0)
+    return 0;
+
+#if UNSIGNED
+  if (negative)
+    {
+      /* Saturate to 0.  */
+      __set_errno (ERANGE);
+      return SAT_MIN;
+    }
+#endif
+
+  if (lead_zero)
+    {
+      /* Find the decimal point */
+      while (1)
+	{
+	  if (*startp == decimal[0])
+	    {
+	      for (cnt = 1; decimal[cnt] != '\0'; ++cnt)
+		if (decimal[cnt] != startp[cnt])
+		  break;
+	      if (decimal[cnt] == '\0')
+		break;
+	    }
+	  ++startp;
+	}
+      startp += lead_zero + decimal_len;
+      exponent -= base == 16 ? 4 * lead_zero : lead_zero;
+      dig_no -= lead_zero;
+    }
+
+  /* Normalize the exponent so that all digits can be considered to
+     start just after the point.  */
+  exponent += base == 16 ? 4 * int_no : int_no;
+
+  if (exponent > (base == 16 ? 4 : 1))
+    {
+      /* Overflow.  */
+      __set_errno (ERANGE);
+      return (negative ? SAT_MIN : SAT_MAX);
+    }
+
+  /* Copy just the digits needed to a separate buffer.  */
+  int digits_needed = (base == 16 ? RETURN_TYPE_BITS / 4 + 2 : RETURN_FRAC_BITS + 1);
+  char buf[RETURN_TYPE_BITS + 1];
+  int digits_copied = 0;
+  int extra = 0;
+  int rdigno = dig_no;
+  while (exponent < 0)
+    {
+      buf[digits_copied++] = '0';
+      exponent += (base == 16 ? 4 : 1);
+      if (digits_copied == digits_needed)
+	return round_and_set_sign (0, negative, 0, 1);
+    }
+  while (digits_copied < digits_needed && rdigno > 0)
+    {
+      if (!(base == 16 ? isxdigit (*startp) : isdigit (*startp)))
+	startp += decimal_len;
+      buf[digits_copied++] = *startp++;
+      rdigno--;
+    }
+  if (rdigno)
+    extra = 1;
+  else
+    while (digits_copied < digits_needed)
+      buf[digits_copied++] = '0';
+
+  if (base == 10 && exponent == 1)
+    {
+      assert (buf[0] != '0');
+      /* At least 1.0; see if there is overflow.  */
+      if (UNSIGNED
+	  || !negative
+	  || buf[0] > '1'
+	  || dig_no > 1)
+	__set_errno (ERANGE);
+      return (negative ? SAT_MIN : SAT_MAX);
+    }
+
+  if (base == 16 && exponent > 0)
+    {
+      int max_dig = (16 >> exponent) + '0';
+      assert (buf[0] != '0');
+      if (buf[0] >= max_dig)
+	{
+	  /* At least 1.0; see if there is overflow.  */
+	  if (UNSIGNED
+	      || !negative
+	      || buf[0] > max_dig
+	      || dig_no > 1)
+	    __set_errno (ERANGE);
+	  return (negative ? SAT_MIN : SAT_MAX);
+	}
+    }
+
+  /* Now strictly in the range (0, 1) (though rounding may yet
+     saturate to 1.0).  */
+  if (base == 10)
+    assert (exponent == 0);
+  else
+    assert (exponent >= 0 && exponent <= 3);
+
+  if (base == 16)
+    {
+      RETURN_TYPE r = 0;
+      int half = 0;
+      for (int i = 0; i < digits_needed; i++)
+	{
+	  RETURN_TYPE val;
+	  int shift;
+	  if (isdigit (buf[i]))
+	    val = buf[i] - '0';
+	  else
+	    val = 10 + tolower (buf[i]) - 'a';
+	  shift = RETURN_FRAC_BITS - 4 + exponent - 4 * i;
+	  if (shift >= 0)
+	    r |= val << shift;
+	  else if (shift < -4)
+	    extra |= (val != 0);
+	  else
+	    {
+	      r |= val >> -shift;
+	      half = (val & (1 << (-shift - 1))) != 0;
+	      extra |= (val & ((1 << (-shift - 1)) - 1)) != 0;
+	    }
+	}
+      return round_and_set_sign (r, negative, half, extra);
+    }
+
+  /* Now we have RETURN_FRAC_BITS + 1 digits after the decimal point.
+     Interpret these as an integer and divide by 5^(RETURN_FRAC_BITS +
+     1).  If there is a remainder, set extra.  If the result of the
+     division is odd, set half.  Divide by 2 again, and round the
+     result.  */
+  mp_limb_t frac[8];
+  mp_size_t fracsize;
+  str_to_mpn (buf, digits_needed, frac, &fracsize);
+  if (fracsize < pow5size)
+    return round_and_set_sign (0, negative, 0, 1);
+  frac[fracsize] = __mpn_lshift (frac, frac, fracsize, pow5shift);
+  if (frac[fracsize])
+    fracsize++;
+  mp_limb_t quot[8];
+  quot[fracsize - pow5size] = mpn_divmod (quot, frac, fracsize, pow5, pow5size);
+  for (int i = 0; i < pow5size; i++)
+    if (frac[i])
+      extra = 1;
+  int half = quot[0] & 1;
+  RETURN_TYPE val = quot[0] >> 1;
+#if RETURN_FRAC_BITS > BITS_PER_MP_LIMB - 1
+  val |= ((RETURN_TYPE) quot[1]) << (BITS_PER_MP_LIMB - 1);
+# if RETURN_FRAC_BITS > 2 * BITS_PER_MP_LIMB - 1
+  val |= ((RETURN_TYPE) quot[2]) << (2 * BITS_PER_MP_LIMB - 1);
+#  if RETURN_FRAC_BITS > 3 * BITS_PER_MP_LIMB - 1
+#   error "Too many bits."
+#  endif
+# endif
+#endif
+  return round_and_set_sign (val, negative, half, extra);
+}
+
+libc_hidden_def (STRTOFIX)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix16.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix16.c
new file mode 100644
index 0000000..febd661
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix16.c
@@ -0,0 +1,28 @@
+/* Convert string to 16-bit signed fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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.  */
+
+#define RETURN_TYPE int16_t
+#define UNSIGNED 0
+#define RETURN_TYPE_BITS 16
+#define SAT_MIN -0x8000
+#define SAT_MAX 0x7fff
+#define STRTOFIX strtosfix16
+
+#include "strtofix.c"
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix32.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix32.c
new file mode 100644
index 0000000..39a563c
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix32.c
@@ -0,0 +1,28 @@
+/* Convert string to 32-bit signed fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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.  */
+
+#define RETURN_TYPE int32_t
+#define UNSIGNED 0
+#define RETURN_TYPE_BITS 32
+#define SAT_MIN 0x80000000
+#define SAT_MAX 0x7fffffff
+#define STRTOFIX strtosfix32
+
+#include "strtofix.c"
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix64.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix64.c
new file mode 100644
index 0000000..ec186a4
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtosfix64.c
@@ -0,0 +1,28 @@
+/* Convert string to 64-bit signed fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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.  */
+
+#define RETURN_TYPE int64_t
+#define UNSIGNED 0
+#define RETURN_TYPE_BITS 64
+#define SAT_MIN 0x8000000000000000LL
+#define SAT_MAX 0x7fffffffffffffffLL
+#define STRTOFIX strtosfix64
+
+#include "strtofix.c"
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix16.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix16.c
new file mode 100644
index 0000000..771b436
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix16.c
@@ -0,0 +1,28 @@
+/* Convert string to 16-bit unsigned fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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.  */
+
+#define RETURN_TYPE uint16_t
+#define UNSIGNED 1
+#define RETURN_TYPE_BITS 16
+#define SAT_MIN 0
+#define SAT_MAX 0xffff
+#define STRTOFIX strtoufix16
+
+#include "strtofix.c"
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix32.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix32.c
new file mode 100644
index 0000000..b47435b
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix32.c
@@ -0,0 +1,28 @@
+/* Convert string to 32-bit unsigned fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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.  */
+
+#define RETURN_TYPE uint32_t
+#define UNSIGNED 1
+#define RETURN_TYPE_BITS 32
+#define SAT_MIN 0
+#define SAT_MAX 0xffffffff
+#define STRTOFIX strtoufix32
+
+#include "strtofix.c"
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix64.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix64.c
new file mode 100644
index 0000000..e6b9cfe
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/strtoufix64.c
@@ -0,0 +1,28 @@
+/* Convert string to 64-bit unsigned fixed point.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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.  */
+
+#define RETURN_TYPE uint64_t
+#define UNSIGNED 1
+#define RETURN_TYPE_BITS 64
+#define SAT_MIN 0
+#define SAT_MAX 0xffffffffffffffffLL
+#define STRTOFIX strtoufix64
+
+#include "strtofix.c"
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/t_sqrt.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/t_sqrt.c
new file mode 100644
index 0000000..1cc8931
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/t_sqrt.c
@@ -0,0 +1 @@
+/* Not needed.  */
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/tst-spepim.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/tst-spepim.c
new file mode 100644
index 0000000..acac00e
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/tst-spepim.c
@@ -0,0 +1,494 @@
+/* Test SPE PIM functions.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.com>, 2007.
+
+   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 <errno.h>
+#include <fenv.h>
+#include <spe.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef int16_t sint16_t;
+typedef int32_t sint32_t;
+typedef int64_t sint64_t;
+
+#define SAT_MAX_U16	0xffff
+#define SAT_MAX_U32	0xffffffffu
+#define SAT_MAX_U64	0xffffffffffffffffull
+#define SAT_MAX_S16	0x7fff
+#define SAT_MAX_S32	0x7fffffff
+#define SAT_MAX_S64	0x7fffffffffffffffll
+#define SAT_MIN_S16	(-SAT_MAX_S16 - 1)
+#define SAT_MIN_S32	(-SAT_MAX_S32 - 1)
+#define SAT_MIN_S64	(-SAT_MAX_S64 - 1)
+
+/* Test results for a single rounding mode.  For each type of result,
+   store the expected result and the expected errno.  */
+struct res {
+  sint16_t s16;
+  int es16;
+  sint32_t s32;
+  int es32;
+  sint64_t s64;
+  int es64;
+  uint16_t u16;
+  int eu16;
+  uint32_t u32;
+  int eu32;
+  uint64_t u64;
+  int eu64;
+};
+
+struct testcase {
+  /* String to test.  */
+  const char *s;
+  /* Number of junk characters at end.  */
+  size_t njunk;
+  /* Expected results for rounding to nearest, zero, upward and
+     downward.  */
+  struct res res[4];
+};
+
+/* Saturating value.  */
+#define SAT(VAL)	VAL, ERANGE
+/* Unsaturating value.  */
+#define UNSAT(VAL)	VAL, 0
+/* Values saturating for both signed and unsigned.  */
+#define SAT6(VAL0, VAL1, VAL2, VAL3, VAL4, VAL5)	\
+  {							\
+    SAT (VAL0), SAT (VAL1), SAT (VAL2),			\
+    SAT (VAL3), SAT (VAL4), SAT (VAL5)			\
+  }
+#define SAT6_MAX				\
+  SAT6 (SAT_MAX_S16, SAT_MAX_S32, SAT_MAX_S64,	\
+	SAT_MAX_U16, SAT_MAX_U32, SAT_MAX_U64)
+#define SAT6_MIN					\
+  SAT6 (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64, 0, 0, 0)
+/* Values saturating for unsigned but not signed.  */
+#define SATNEG(VAL0, VAL1, VAL2)		\
+  {						\
+    UNSAT (VAL0), UNSAT (VAL1), UNSAT (VAL2),	\
+    SAT (0), SAT (0), SAT (0)			\
+  }
+/* Values not saturating.  */
+#define UNSAT6(VAL0, VAL1, VAL2, VAL3, VAL4, VAL5)	\
+  {							\
+    UNSAT (VAL0), UNSAT (VAL1), UNSAT (VAL2),		\
+    UNSAT (VAL3), UNSAT (VAL4), UNSAT (VAL5)		\
+  }
+/* Results not depending on rounding mode.  */
+#define EXACT_SAT6_MAX				\
+  {						\
+    SAT6_MAX,					\
+    SAT6_MAX,					\
+    SAT6_MAX,					\
+    SAT6_MAX					\
+  }
+#define EXACT_SAT6_MIN				\
+  {						\
+    SAT6_MIN,					\
+    SAT6_MIN,					\
+    SAT6_MIN,					\
+    SAT6_MIN					\
+  }
+#define EXACT_SATNEG(VAL0, VAL1, VAL2)		\
+  {						\
+    SATNEG (VAL0, VAL1, VAL2),			\
+    SATNEG (VAL0, VAL1, VAL2),			\
+    SATNEG (VAL0, VAL1, VAL2),			\
+    SATNEG (VAL0, VAL1, VAL2)			\
+  }
+#define EXACT_UNSAT6(VAL0, VAL1, VAL2, VAL3, VAL4, VAL5)	\
+  {								\
+    UNSAT6 (VAL0, VAL1, VAL2, VAL3, VAL4, VAL5),		\
+    UNSAT6 (VAL0, VAL1, VAL2, VAL3, VAL4, VAL5),		\
+    UNSAT6 (VAL0, VAL1, VAL2, VAL3, VAL4, VAL5),		\
+    UNSAT6 (VAL0, VAL1, VAL2, VAL3, VAL4, VAL5)			\
+  }
+
+static const struct testcase tests[] = {
+  /* Strings evaluating to 0, including INF and NaN (not supported by
+     SPE PIM functions).  */
+  { "", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "00", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "+0", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "-0", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0.0", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { ".0", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0.", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { " \n-0.", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0e100000000000000000", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { " \t 0e-100000000000000000", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x0", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x0.", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x.0", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x0.p100000000000000000", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "-0x0.p002000000000000000", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x.0p-100000000000000000", 0, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x", 1, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x.", 2, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { ".", 1, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { " .", 2, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "+.", 2, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { " +.", 3, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { " -.", 3, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0xp", 2, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x.p", 3, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "+0x.p", 3, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "-0x.p0", 4, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "0x0q", 1, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "INF", 3, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  { "nan", 3, EXACT_UNSAT6 (0, 0, 0, 0, 0, 0) },
+  /* Strings evaluating to 1.0 or greater, saturating unconditionally.  */
+  { "1", 0, EXACT_SAT6_MAX },
+  { "1.0", 0, EXACT_SAT6_MAX },
+  { "1e0", 0, EXACT_SAT6_MAX },
+  { "10e-1", 0, EXACT_SAT6_MAX },
+  { "0.1e1", 0, EXACT_SAT6_MAX },
+  { "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-100", 0, EXACT_SAT6_MAX },
+  { "2", 0, EXACT_SAT6_MAX },
+  { "0x1", 0, EXACT_SAT6_MAX },
+  { "0x2p-1", 0, EXACT_SAT6_MAX },
+  { "0x.8p1", 0, EXACT_SAT6_MAX },
+  { "0x.40p2", 0, EXACT_SAT6_MAX },
+  /* Strings evaluating to less than -1.0, saturating unconditionally.  */
+  { "-1.1", 0, EXACT_SAT6_MIN },
+  { "-.11e1", 0, EXACT_SAT6_MIN },
+  { "-11e-1", 0, EXACT_SAT6_MIN },
+  { "-100", 0, EXACT_SAT6_MIN },
+  { "-2", 0, EXACT_SAT6_MIN },
+  { "-0x1.00000000000000000000000001", 0, EXACT_SAT6_MIN },
+  { "-0x2.00000000000000000000000001p-1", 0, EXACT_SAT6_MIN },
+  { "-0x0.80000000000000000000000001p1", 0, EXACT_SAT6_MIN },
+  { "-1.000000000000000000000000000000000000000000000000000000000000000000000000000000001", 0, EXACT_SAT6_MIN },
+  /* Strings evaluating to -1.0 exactly, saturating for unsigned but
+     exactly representable for signed.  */
+  { "-1", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-1e", 1, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-1.0", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-10e-1", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-.1e+1", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-.0000000001e+10", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-10000000000e-10", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x1", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x1p+", 2, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x2p-1", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x4.0p-2", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x8.p-3", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x10p-4", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x.8p1", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x.4p+2", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x.2p+3", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x.1p+4", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  { "-0x.08p5", 0, EXACT_SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64) },
+  /* Strings evaluating to exactly representable values between -1.0
+     and 0.0, saturating for unsigned.  */
+  { "-0.5", 0, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-0.5e-", 2, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-05e-1", 0, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-05000000000e-10", 0, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-0.5e0", 0, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-0.00000000005e10", 0, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-0x.8", 0, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-0x1p-1", 0, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-0x.4p1", 0, EXACT_SATNEG (-0x4000, -0x40000000, -0x4000000000000000ll) },
+  { "-0.25", 0, EXACT_SATNEG (-0x2000, -0x20000000, -0x2000000000000000ll) },
+  { "-2.5e-1", 0, EXACT_SATNEG (-0x2000, -0x20000000, -0x2000000000000000ll) },
+  { "-0.75", 0, EXACT_SATNEG (-0x6000, -0x60000000, -0x6000000000000000ll) },
+  { "-0.000030517578125", 0, EXACT_SATNEG (-0x0001, -0x00010000, -0x0001000000000000ll) },
+  { "-0.376739501953125", 0, EXACT_SATNEG (-12345, -12345*0x10000, -12345*0x1000000000000ll) },
+  { "-0x.dcba", 0, EXACT_SATNEG (-0x6e5d, -0x6e5d0000, -0x6e5d000000000000ll) },
+  { "-0xd.cbap-4", 0, EXACT_SATNEG (-0x6e5d, -0x6e5d0000, -0x6e5d000000000000ll) },
+  /* Strings evaluating to exactly representable values between 0.0
+     and 1.0.  */
+  { "0.5", 0, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "0.5e-", 2, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "05e-1", 0, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "05000000000e-10", 0, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "0.5e0", 0, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "0.00000000005e10", 0, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "0x.8", 0, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "0x1p-1", 0, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "0x.4p1", 0, EXACT_UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000000ull) },
+  { "0.25", 0, EXACT_UNSAT6 (0x2000, 0x20000000, 0x2000000000000000ll, 0x4000, 0x40000000u, 0x4000000000000000ull) },
+  { "2.5e-1", 0, EXACT_UNSAT6 (0x2000, 0x20000000, 0x2000000000000000ll, 0x4000, 0x40000000u, 0x4000000000000000ull) },
+  { "0.75", 0, EXACT_UNSAT6 (0x6000, 0x60000000, 0x6000000000000000ll, 0xc000, 0xc0000000u, 0xc000000000000000ull) },
+  { "0.000030517578125", 0, EXACT_UNSAT6 (0x0001, 0x00010000, 0x0001000000000000ll, 0x0002, 0x00020000u, 0x0002000000000000ull) },
+  { "0.376739501953125", 0, EXACT_UNSAT6 (12345, 12345*0x10000, 12345*0x1000000000000ll, 12345*0x2, 12345*0x20000u, 12345*0x2000000000000ull) },
+  { "0x.dcba", 0, EXACT_UNSAT6 (0x6e5d, 0x6e5d0000, 0x6e5d000000000000ll, 0xdcba, 0xdcba0000u, 0xdcba000000000000ull) },
+  { "0xd.cbap-4", 0, EXACT_UNSAT6 (0x6e5d, 0x6e5d0000, 0x6e5d000000000000ll, 0xdcba, 0xdcba0000u, 0xdcba000000000000ull) },
+  /* Strings evaluating to values between 0.0 and 1.0, depending on
+     rounding mode.  */
+  { "0.1", 0,
+    {
+      UNSAT6 (0xccd, 0xccccccd, 0xccccccccccccccdll, 0x199a, 0x1999999au, 0x199999999999999aull),
+      UNSAT6 (0xccc, 0xccccccc, 0xcccccccccccccccll, 0x1999, 0x19999999u, 0x1999999999999999ull),
+      UNSAT6 (0xccd, 0xccccccd, 0xccccccccccccccdll, 0x199a, 0x1999999au, 0x199999999999999aull),
+      UNSAT6 (0xccc, 0xccccccc, 0xcccccccccccccccll, 0x1999, 0x19999999u, 0x1999999999999999ull)
+    }
+  },
+  { "0.5000152587890625", 0,
+    {
+      UNSAT6 (0x4000, 0x40008000, 0x4000800000000000ll, 0x8001, 0x80010000u, 0x8001000000000000ull),
+      UNSAT6 (0x4000, 0x40008000, 0x4000800000000000ll, 0x8001, 0x80010000u, 0x8001000000000000ull),
+      UNSAT6 (0x4001, 0x40008000, 0x4000800000000000ll, 0x8001, 0x80010000u, 0x8001000000000000ull),
+      UNSAT6 (0x4000, 0x40008000, 0x4000800000000000ll, 0x8001, 0x80010000u, 0x8001000000000000ull)
+    }
+  },
+  { "0.50001525878906250000000000000000000000000000000000000000000000000000000000001", 0,
+    {
+      UNSAT6 (0x4001, 0x40008000, 0x4000800000000000ll, 0x8001, 0x80010000u, 0x8001000000000000ull),
+      UNSAT6 (0x4000, 0x40008000, 0x4000800000000000ll, 0x8001, 0x80010000u, 0x8001000000000000ull),
+      UNSAT6 (0x4001, 0x40008001, 0x4000800000000001ll, 0x8002, 0x80010001u, 0x8001000000000001ull),
+      UNSAT6 (0x4000, 0x40008000, 0x4000800000000000ll, 0x8001, 0x80010000u, 0x8001000000000000ull)
+    }
+  },
+  { "0.50000000000000000008131516293641283255055896006524562835693359375", 0,
+    {
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000001ll, 0x8000, 0x80000000u, 0x8000000000000002ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull),
+      UNSAT6 (0x4001, 0x40000001, 0x4000000000000001ll, 0x8001, 0x80000001u, 0x8000000000000002ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull)
+    }
+  },
+  { "0.50000000000000000008131516293641283255055896006524562835693359376", 0,
+    {
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000001ll, 0x8000, 0x80000000u, 0x8000000000000002ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull),
+      UNSAT6 (0x4001, 0x40000001, 0x4000000000000001ll, 0x8001, 0x80000001u, 0x8000000000000002ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull)
+    }
+  },
+  { "0.50000000000000000008131516293641283255055896006524562835693359374", 0,
+    {
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000001ll, 0x8000, 0x80000000u, 0x8000000000000001ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull),
+      UNSAT6 (0x4001, 0x40000001, 0x4000000000000001ll, 0x8001, 0x80000001u, 0x8000000000000002ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull)
+    }
+  },
+  { "0x0.80000000000000018", 0,
+    {
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000001ll, 0x8000, 0x80000000u, 0x8000000000000002ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull),
+      UNSAT6 (0x4001, 0x40000001, 0x4000000000000001ll, 0x8001, 0x80000001u, 0x8000000000000002ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull)
+    }
+  },
+  { "0x0.80000000000000017", 0,
+    {
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000001ll, 0x8000, 0x80000000u, 0x8000000000000001ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull),
+      UNSAT6 (0x4001, 0x40000001, 0x4000000000000001ll, 0x8001, 0x80000001u, 0x8000000000000002ull),
+      UNSAT6 (0x4000, 0x40000000, 0x4000000000000000ll, 0x8000, 0x80000000u, 0x8000000000000001ull)
+    }
+  },
+  /* Strings evaluating to values between -1.0 and 0.0, depending on
+     rounding mode.  */
+  { "-0.1", 0,
+    {
+      SATNEG (-0xccd, -0xccccccd, -0xccccccccccccccdll),
+      SATNEG (-0xccc, -0xccccccc, -0xcccccccccccccccll),
+      SATNEG (-0xccc, -0xccccccc, -0xcccccccccccccccll),
+      SATNEG (-0xccd, -0xccccccd, -0xccccccccccccccdll)
+    }
+  },
+  { "-0.5000000000000000001626303258728256651011179201304912567138671875", 0,
+    {
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000002ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4001, -0x40000001, -0x4000000000000002ll)
+    }
+  },
+  { "-0.5000000000000000001626303258728256651011179201304912567138671874", 0,
+    {
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4001, -0x40000001, -0x4000000000000002ll)
+    }
+  },
+  { "-0.5000000000000000001626303258728256651011179201304912567138671876", 0,
+    {
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000002ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4001, -0x40000001, -0x4000000000000002ll)
+    }
+  },
+  { "-0x.8000000000000003", 0,
+    {
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000002ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4001, -0x40000001, -0x4000000000000002ll)
+    }
+  },
+  { "-0x.8000000000000002f", 0,
+    {
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4000, -0x40000000, -0x4000000000000001ll),
+      SATNEG (-0x4001, -0x40000001, -0x4000000000000002ll)
+    }
+  },
+  /* Strings evaluating very close to 1.0, saturation depending on
+     rounding mode.  */
+  { "0x.fffe1", 0,
+    {
+      { UNSAT (0x7fff), UNSAT (0x7fff0800), UNSAT (0x7fff080000000000ll), UNSAT (0xfffe), UNSAT (0xfffe1000u), UNSAT (0xfffe100000000000ull) },
+      { UNSAT (0x7fff), UNSAT (0x7fff0800), UNSAT (0x7fff080000000000ll), UNSAT (0xfffe), UNSAT (0xfffe1000u), UNSAT (0xfffe100000000000ull) },
+      { SAT (0x7fff), UNSAT (0x7fff0800), UNSAT (0x7fff080000000000ll), UNSAT (0xffff), UNSAT (0xfffe1000u), UNSAT (0xfffe100000000000ull) },
+      { UNSAT (0x7fff), UNSAT (0x7fff0800), UNSAT (0x7fff080000000000ll), UNSAT (0xfffe), UNSAT (0xfffe1000u), UNSAT (0xfffe100000000000ull) }
+    }
+  },
+  { "0x.ffff8", 0,
+    {
+      { SAT (0x7fff), UNSAT (0x7fffc000), UNSAT (0x7fffc00000000000ll), SAT (0xffff), UNSAT (0xffff8000u), UNSAT (0xffff800000000000ull) },
+      { UNSAT (0x7fff), UNSAT (0x7fffc000), UNSAT (0x7fffc00000000000ll), UNSAT (0xffff), UNSAT (0xffff8000u), UNSAT (0xffff800000000000ull) },
+      { SAT (0x7fff), UNSAT (0x7fffc000), UNSAT (0x7fffc00000000000ll), SAT (0xffff), UNSAT (0xffff8000u), UNSAT (0xffff800000000000ull) },
+      { UNSAT (0x7fff), UNSAT (0x7fffc000), UNSAT (0x7fffc00000000000ll), UNSAT (0xffff), UNSAT (0xffff8000u), UNSAT (0xffff800000000000ull) }
+    }
+  },
+  { "0x.fffffffffffffffff", 0,
+    {
+      { SAT (0x7fff), SAT (0x7fffffff), SAT (0x7fffffffffffffffll), SAT (0xffff), SAT (0xffffffffu), SAT (0xffffffffffffffffull) },
+      { UNSAT (0x7fff), UNSAT (0x7fffffff), UNSAT (0x7fffffffffffffffll), UNSAT (0xffff), UNSAT (0xffffffffu), UNSAT (0xffffffffffffffffull) },
+      { SAT (0x7fff), SAT (0x7fffffff), SAT (0x7fffffffffffffffll), SAT (0xffff), SAT (0xffffffffu), SAT (0xffffffffffffffffull) },
+      { UNSAT (0x7fff), UNSAT (0x7fffffff), UNSAT (0x7fffffffffffffffll), UNSAT (0xffff), UNSAT (0xffffffffu), UNSAT (0xffffffffffffffffull) }
+    }
+  },
+  /* Strings evaluating very close to -1.0, may round to -1 but only
+     saturate for unsigned.  */
+  { "-0x.fffe1", 0,
+    {
+      SATNEG (-0x7fff, -0x7fff0800, -0x7fff080000000000ll),
+      SATNEG (-0x7fff, -0x7fff0800, -0x7fff080000000000ll),
+      SATNEG (-0x7fff, -0x7fff0800, -0x7fff080000000000ll),
+      SATNEG (SAT_MIN_S16, -0x7fff0800, -0x7fff080000000000ll)
+    }
+  },
+  { "-0x.ffffffffffffffff", 0,
+    {
+      SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64),
+      SATNEG (-0x7fff, -0x7fffffff, -0x7fffffffffffffffll),
+      SATNEG (-0x7fff, -0x7fffffff, -0x7fffffffffffffffll),
+      SATNEG (SAT_MIN_S16, SAT_MIN_S32, SAT_MIN_S64)
+    }
+  }
+};
+
+static const int rounding_modes[4] = {
+  FE_TONEAREST,
+  FE_TOWARDZERO,
+  FE_UPWARD,
+  FE_DOWNWARD
+};
+
+static const char *const mode_names[4] = {
+  "FE_TONEAREST",
+  "FE_TOWARDZERO",
+  "FE_UPWARD",
+  "FE_DOWNWARD"
+};
+
+int
+main (void)
+{
+  int passes = 0;
+  int fails = 0;
+  size_t i;
+  for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i++)
+    {
+      size_t j;
+      for (j = 0; j < 4; j++)
+	{
+	  if (fesetround (rounding_modes[j]) != 0)
+	    {
+	      printf ("fesetround (%s) failed.\n", mode_names[j]);
+	      abort ();
+	    }
+#define DO_TEST(SU, SZ, PR)						\
+	  do {								\
+	    SU##int##SZ##_t expret = tests[i].res[j].SU##SZ;		\
+	    int experr = tests[i].res[j].e##SU##SZ;			\
+	    size_t explen = strlen (tests[i].s) - tests[i].njunk;	\
+	    SU##int##SZ##_t ret0, ret1;					\
+	    int reterr;							\
+	    size_t retlen;						\
+	    char *ep;							\
+	    errno = 0;							\
+	    ret0 = strto##SU##fix##SZ (tests[i].s, &ep);		\
+	    reterr = errno;						\
+	    retlen = ep - tests[i].s;					\
+	    if (ret0 == expret)						\
+	      passes++;							\
+	    else							\
+	      {								\
+		fails++;						\
+		printf ("strto"#SU"fix"#SZ" (\"%s\") in mode %s "	\
+			"returned %0"PR"x, expected %0"PR"x.\n",	\
+			tests[i].s, mode_names[j], ret0, expret);	\
+	      }								\
+	    if (reterr == experr)					\
+	      passes++;							\
+	    else							\
+	      {								\
+		fails++;						\
+		printf ("strto"#SU"fix"#SZ" (\"%s\") in mode %s "	\
+			"left errno as %d, expected %d.\n",		\
+			tests[i].s, mode_names[j], reterr, experr);	\
+	      }								\
+	    if (retlen == explen)					\
+	      passes++;							\
+	    else							\
+	      {								\
+		fails++;						\
+		printf ("strto"#SU"fix"#SZ" (\"%s\") in mode %s "	\
+			"consumed %zu characters, expected %zu.\n",	\
+			tests[i].s, mode_names[j], retlen, explen);	\
+	      }								\
+	    if (experr == 0)						\
+	      {								\
+		ret1 = ato##SU##fix##SZ (tests[i].s);			\
+		if (ret1 == expret)					\
+		  passes++;						\
+		else							\
+		  {							\
+		    fails++;						\
+		    printf ("ato"#SU"fix"#SZ" (\"%s\") in mode %s "	\
+			    "returned %0"PR"x, expected %0"PR"x.\n",	\
+			    tests[i].s, mode_names[j], ret1, expret);	\
+		  }							\
+	      }								\
+	  } while (0)
+	  DO_TEST (s, 16, "4h");
+	  DO_TEST (s, 32, "8");
+	  DO_TEST (s, 64, "16ll");
+	  DO_TEST (u, 16, "4h");
+	  DO_TEST (u, 32, "8");
+	  DO_TEST (u, 64, "16ll");
+	}
+    }
+  printf ("Number of passes: %d\nNumber of failures: %d\n", passes, fails);
+  return fails != 0;
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/w_sqrt.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/w_sqrt.c
new file mode 100644
index 0000000..3721f24
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/w_sqrt.c
@@ -0,0 +1 @@
+#include <math/w_sqrt.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/fpu/w_sqrtf.c b/ports/sysdeps/powerpc/powerpc32/e500/fpu/w_sqrtf.c
new file mode 100644
index 0000000..7c6ca90
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/fpu/w_sqrtf.c
@@ -0,0 +1 @@
+#include <math/w_sqrtf.c>
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Makefile b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Makefile
new file mode 100644
index 0000000..2d7d092
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Makefile
@@ -0,0 +1,4 @@
+# Double precision floating point gets emulated.
+ifeq ($(subdir),soft-fp)
+sysdep_routines += $(gcc-double-routines) fraiseexcept-soft
+endif
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Subdirs b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Subdirs
new file mode 100644
index 0000000..87eadf3
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Subdirs
@@ -0,0 +1 @@
+soft-fp
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Versions b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Versions
new file mode 100644
index 0000000..f126c9a
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/Versions
@@ -0,0 +1,19 @@
+libc {
+  GLIBC_2.3.3 {
+    __feraiseexcept_soft;
+    __adddf3; __truncdfsf2;
+    __divdf3; __eqdf2;
+    __extendsfdf2; __fixdfdi; __fixdfsi; __fixsfdi;
+    __fixtfdi;
+    __fixunsdfdi; __fixunsdfsi;
+    __floatdidf; __floatsidf;
+    __gedf2; __ledf2; __muldf3;
+    __negdf2; __sqrtdf2; __subdf3;
+    __truncdfsf2;
+  }
+  GLIBC_2.5 {
+    __floatundidf; __floatunsidf;
+    __unorddf2; __nedf2;
+    __gtdf2; __ltdf2;
+  }
+}
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/fraiseexcept-soft.c b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/fraiseexcept-soft.c
new file mode 100644
index 0000000..3462d41
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/fraiseexcept-soft.c
@@ -0,0 +1,30 @@
+/* Raise given exceptions.
+   Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>, 2004.
+
+   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 <fenv_libc.h>
+#include <bp-sym.h>
+#include <libc-symbols.h>
+
+int __feraiseexcept_soft (int);
+libc_hidden_proto (__feraiseexcept_soft)
+
+#define __FERAISEEXCEPT_INTERNAL __feraiseexcept_soft
+#include "../spe-raise.c"
+libc_hidden_def (__feraiseexcept_soft)
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/sfp-machine.h b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/sfp-machine.h
new file mode 100644
index 0000000..752eb62
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/soft-fp/sfp-machine.h
@@ -0,0 +1,64 @@
+#ifndef _SFP_MACHINE_H_
+#define _SFP_MACHINE_H_
+#include <fenv_libc.h>
+#include <libc-symbols.h>
+
+int __feraiseexcept_soft (int);
+libc_hidden_proto (__feraiseexcept_soft)
+
+#define _FP_W_TYPE_SIZE		32
+#define _FP_W_TYPE		unsigned long
+#define _FP_WS_TYPE		signed long
+#define _FP_I_TYPE		long
+
+#define _FP_MUL_MEAT_S(R,X,Y)				\
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)				\
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)				\
+  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_loop(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S		0
+#define _FP_NANSIGN_D		0
+#define _FP_NANSIGN_Q		0
+
+#define _FP_KEEPNANFRACP 1
+
+/* Someone please check this.  */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
+  do {								\
+    if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)		\
+	&& !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs))	\
+      {								\
+	R##_s = Y##_s;						\
+	_FP_FRAC_COPY_##wc(R,Y);				\
+      }								\
+    else							\
+      {								\
+	R##_s = X##_s;						\
+	_FP_FRAC_COPY_##wc(R,X);				\
+      }								\
+    R##_c = FP_CLS_NAN;						\
+  } while (0)
+
+/* Exception flags.  We use the bit positions of the appropriate bits
+   in the FPEFSCR, which also correspond to the FE_* bits.  This makes
+   everything easier ;-).  */
+#define FP_EX_INEXACT         (1 << (63 - 42))
+#define FP_EX_INVALID         (1 << (63 - 43))
+#define FP_EX_DIVZERO         (1 << (63 - 44))
+#define FP_EX_UNDERFLOW       (1 << (63 - 45))
+#define FP_EX_OVERFLOW        (1 << (63 - 46))
+
+/* This will work inasmuch as FP_EX_* are the same as FE_*.  */
+#define FP_HANDLE_EXCEPTIONS  __feraiseexcept_soft (_fex)
+
+#define FP_ROUNDMODE          (fegetenv_register() & 0x3)
+#endif /* _SFP_MACHINE_H_ */
diff --git a/ports/sysdeps/powerpc/powerpc32/e500/spe-raise.c b/ports/sysdeps/powerpc/powerpc32/e500/spe-raise.c
new file mode 100644
index 0000000..6ff880c
--- /dev/null
+++ b/ports/sysdeps/powerpc/powerpc32/e500/spe-raise.c
@@ -0,0 +1,68 @@
+/* Raise given exceptions.
+   Copyright (C) 1997,99,2000,01,02,04 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 <fenv_libc.h>
+#include <bp-sym.h>
+
+int
+__FERAISEEXCEPT_INTERNAL (int excepts)
+{
+  unsigned long f;
+
+  f = fegetenv_register ();
+  f |= (excepts & FE_ALL_EXCEPT);
+  fesetenv_register (f);
+
+  /* Force the operations that cause the exceptions.  */
+  if ((FE_INVALID & excepts) != 0)
+    {
+      /* ?? Does not set sticky bit ?? */
+      /* 0 / 0 */
+      asm volatile ("efsdiv %0,%0,%1" : : "r" (0), "r" (0));
+    }
+
+  if ((FE_DIVBYZERO & excepts) != 0)
+    {
+      /* 1.0 / 0.0 */
+      asm volatile ("efsdiv %0,%0,%1" : : "r" (1.0F), "r" (0));
+    }
+
+  if ((FE_OVERFLOW & excepts) != 0)
+    {
+      /* ?? Does not set sticky bit ?? */
+      /* Largest normalized number plus itself.  */
+      asm volatile ("efsadd %0,%0,%1" : : "r" (0x7f7fffff), "r" (0x7f7fffff));
+    }
+
+  if ((FE_UNDERFLOW & excepts) != 0)
+    {
+      /* ?? Does not set sticky bit ?? */
+      /* Smallest normalized number times itself.  */
+      asm volatile ("efsmul %0,%0,%1" : : "r" (0x800000), "r" (0x800000));
+    }
+
+  if ((FE_INEXACT & excepts) != 0)
+    {
+      /* Smallest normalized minus 1.0 raises the inexact flag.  */
+      asm volatile ("efssub %0,%0,%1" : : "r" (0x00800000), "r" (1.0F));
+    }
+
+  /* Success.  */
+  return 0;
+}
diff --git a/ports/sysdeps/powerpc/preconfigure b/ports/sysdeps/powerpc/preconfigure
new file mode 100644
index 0000000..57f24a0
--- /dev/null
+++ b/ports/sysdeps/powerpc/preconfigure
@@ -0,0 +1,20 @@
+# Check for E500.
+
+case "$machine" in
+powerpc)
+	if test "$with_fp" = "yes"; then
+	  variant=`(echo "#ifdef __NO_FPRS__"
+	      echo "#ifdef _SOFT_DOUBLE"
+	      echo "e500/single"
+	      echo "#else"
+	      echo "e500"
+	      echo "#endif"
+	      echo "#endif") |
+	     $CC $CFLAGS $CPPFLAGS -E - |
+	     grep '^[a-z]'`
+	  if test -n "$variant"; then
+	    base_machine=powerpc machine=powerpc/powerpc32/$variant
+	  fi
+	fi
+	;;
+esac
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/Implies b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/Implies
new file mode 100644
index 0000000..be4188a
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/Implies
@@ -0,0 +1 @@
+powerpc/powerpc32/e500/fpu
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/getcontext-extra.S b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/getcontext-extra.S
new file mode 100644
index 0000000..d1ac7ee
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/getcontext-extra.S
@@ -0,0 +1,61 @@
+/* Save current context.  Support for saving high parts of registers.
+   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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.  */
+
+/* We follow the kernel's layout, which saves the high parts of the
+   SPE registers in the vregs area, immediately followed by the
+   SPEFSCR value.  */
+.macro getcontext_extra
+	la	r10,(_UC_VREGS)(r3)
+	evstwwe	r0,(0*4)(r10)
+	evstwwe	r1,(1*4)(r10)
+	evstwwe	r2,(2*4)(r10)
+	evstwwe	r3,(3*4)(r10)
+	evstwwe	r4,(4*4)(r10)
+	evstwwe	r5,(5*4)(r10)
+	evstwwe	r6,(6*4)(r10)
+	evstwwe	r7,(7*4)(r10)
+	evstwwe	r8,(8*4)(r10)
+	evstwwe	r9,(9*4)(r10)
+	evstwwe	r10,(10*4)(r10)
+	evstwwe	r11,(11*4)(r10)
+	evstwwe	r12,(12*4)(r10)
+	evstwwe	r13,(13*4)(r10)
+	evstwwe	r14,(14*4)(r10)
+	evstwwe	r15,(15*4)(r10)
+	evstwwe	r16,(16*4)(r10)
+	evstwwe	r17,(17*4)(r10)
+	evstwwe	r18,(18*4)(r10)
+	evstwwe	r19,(19*4)(r10)
+	evstwwe	r20,(20*4)(r10)
+	evstwwe	r21,(21*4)(r10)
+	evstwwe	r22,(22*4)(r10)
+	evstwwe	r23,(23*4)(r10)
+	evstwwe	r24,(24*4)(r10)
+	evstwwe	r25,(25*4)(r10)
+	evstwwe	r26,(26*4)(r10)
+	evstwwe	r27,(27*4)(r10)
+	evstwwe	r28,(28*4)(r10)
+	evstwwe	r29,(29*4)(r10)
+	evstwwe	r30,(30*4)(r10)
+	evstwwe	r31,(31*4)(r10)
+	mfspefscr	r9
+	stw	r9,(32*4)(r10)
+.endm
+#define __GETCONTEXT_EXTRA getcontext_extra
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/getcontext.S b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/getcontext.S
new file mode 100644
index 0000000..8ac9c97
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/getcontext.S
@@ -0,0 +1,60 @@
+/* Save current context.
+   Copyright (C) 2002, 2004, 2005, 2006, 2007 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>
+#include <rtld-global-offsets.h>
+#include <shlib-compat.h>
+
+#define __ASSEMBLY__
+#include <asm/ptrace.h>
+#include "ucontext_i.h"
+
+#define __CONTEXT_FUNC_NAME __getcontext
+#undef __CONTEXT_ENABLE_FPRS
+#undef __CONTEXT_ENABLE_VRS
+#include "getcontext-extra.S"
+
+#include "getcontext-common.S"
+
+versioned_symbol (libc, __getcontext, getcontext, GLIBC_2_3_4)
+
+#if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
+
+/* For the nofpu case the old/new versions are the same function.  */  
+strong_alias (__getcontext, __novec_getcontext)
+
+compat_symbol (libc, __novec_getcontext, getcontext, GLIBC_2_3_3)
+
+#endif
+
+#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
+
+#define _ERRNO_H	1
+#include <bits/errno.h>
+
+	compat_text_section
+ENTRY (__getcontext_stub)
+	li	r3,ENOSYS
+	b	__syscall_error@local
+END (__getcontext_stub)
+	.previous
+
+compat_symbol (libc, __getcontext_stub, getcontext, GLIBC_2_1)
+
+#endif
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/setcontext-extra.S b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/setcontext-extra.S
new file mode 100644
index 0000000..78af483
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/setcontext-extra.S
@@ -0,0 +1,93 @@
+/* Jump to a new context.  Support for restoring high parts of registers.
+   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Joseph Myers <joseph@codesourcery.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.  */
+
+.macro setcontext_extra
+	lwz	r3,_UC_VREGS+(0*4)(r31)
+	evmergelo	r0,r3,r0
+	lwz	r3,_UC_VREGS+(1*4)(r31)
+	evmergelo	r1,r3,r1
+	lwz	r3,_UC_VREGS+(2*4)(r31)
+	evmergelo	r2,r3,r2
+	lwz	r3,_UC_VREGS+(1*4)(r31)
+	evmergelo	r1,r3,r1
+	lwz	r3,_UC_VREGS+(2*4)(r31)
+	evmergelo	r2,r3,r2
+	lwz	r3,_UC_VREGS+(3*4)(r31)
+	evmergelo	r3,r3,r3
+	lwz	r3,_UC_VREGS+(4*4)(r31)
+	evmergelo	r4,r3,r4
+	lwz	r3,_UC_VREGS+(5*4)(r31)
+	evmergelo	r5,r3,r5
+	lwz	r3,_UC_VREGS+(6*4)(r31)
+	evmergelo	r6,r3,r6
+	lwz	r3,_UC_VREGS+(7*4)(r31)
+	evmergelo	r7,r3,r7
+	lwz	r3,_UC_VREGS+(8*4)(r31)
+	evmergelo	r8,r3,r8
+	lwz	r3,_UC_VREGS+(9*4)(r31)
+	evmergelo	r9,r3,r9
+	lwz	r3,_UC_VREGS+(10*4)(r31)
+	evmergelo	r10,r3,r10
+	lwz	r3,_UC_VREGS+(11*4)(r31)
+	evmergelo	r11,r3,r11
+	lwz	r3,_UC_VREGS+(12*4)(r31)
+	evmergelo	r12,r3,r12
+	lwz	r3,_UC_VREGS+(13*4)(r31)
+	evmergelo	r13,r3,r13
+	lwz	r3,_UC_VREGS+(14*4)(r31)
+	evmergelo	r14,r3,r14
+	lwz	r3,_UC_VREGS+(15*4)(r31)
+	evmergelo	r15,r3,r15
+	lwz	r3,_UC_VREGS+(16*4)(r31)
+	evmergelo	r16,r3,r16
+	lwz	r3,_UC_VREGS+(17*4)(r31)
+	evmergelo	r17,r3,r17
+	lwz	r3,_UC_VREGS+(18*4)(r31)
+	evmergelo	r18,r3,r18
+	lwz	r3,_UC_VREGS+(19*4)(r31)
+	evmergelo	r19,r3,r19
+	lwz	r3,_UC_VREGS+(20*4)(r31)
+	evmergelo	r20,r3,r20
+	lwz	r3,_UC_VREGS+(21*4)(r31)
+	evmergelo	r21,r3,r21
+	lwz	r3,_UC_VREGS+(22*4)(r31)
+	evmergelo	r22,r3,r22
+	lwz	r3,_UC_VREGS+(23*4)(r31)
+	evmergelo	r23,r3,r23
+	lwz	r3,_UC_VREGS+(24*4)(r31)
+	evmergelo	r24,r3,r24
+	lwz	r3,_UC_VREGS+(25*4)(r31)
+	evmergelo	r25,r3,r25
+	lwz	r3,_UC_VREGS+(26*4)(r31)
+	evmergelo	r26,r3,r26
+	lwz	r3,_UC_VREGS+(27*4)(r31)
+	evmergelo	r27,r3,r27
+	lwz	r3,_UC_VREGS+(28*4)(r31)
+	evmergelo	r28,r3,r28
+	lwz	r3,_UC_VREGS+(29*4)(r31)
+	evmergelo	r29,r3,r29
+	lwz	r3,_UC_VREGS+(30*4)(r31)
+	evmergelo	r30,r3,r30
+	lwz	r3,_UC_VREGS+(31*4)(r31)
+	evmergelo	r31,r3,r31
+	lwz	r3,_UC_VREGS+(32*4)(r31)
+	mtspefscr	r3
+.endm
+#define __SETCONTEXT_EXTRA setcontext_extra
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/setcontext.S b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/setcontext.S
new file mode 100644
index 0000000..7759033
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/setcontext.S
@@ -0,0 +1,60 @@
+/* Jump to a new context.
+   Copyright (C) 2002, 2004, 2005, 2006, 2007 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>
+#include <rtld-global-offsets.h>
+#include <shlib-compat.h>
+
+#define __ASSEMBLY__
+#include <asm/ptrace.h>
+#include "ucontext_i.h"
+
+#define __CONTEXT_FUNC_NAME __setcontext
+#undef __CONTEXT_ENABLE_FPRS
+#undef __CONTEXT_ENABLE_VRS
+#include "setcontext-extra.S"
+
+#include "setcontext-common.S"
+
+versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4)
+
+#if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
+
+/* For the nofpu case the old/new versions are the same function.  */  
+strong_alias (__setcontext, __novec_setcontext)
+
+compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3_3)
+
+#endif
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_3)
+
+#define _ERRNO_H	1
+#include <bits/errno.h>
+
+	compat_text_section
+ENTRY (__setcontext_stub)
+	li	r3,ENOSYS
+	b	__syscall_error@local
+END (__setcontext_stub)
+	.previous
+
+compat_symbol (libc, __setcontext_stub, setcontext, GLIBC_2_0)
+
+#endif
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/swapcontext.S b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/swapcontext.S
new file mode 100644
index 0000000..caa36c6
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/fpu/swapcontext.S
@@ -0,0 +1,61 @@
+/* Save current context and jump to a new context.
+   Copyright (C) 2002, 2004, 2005, 2006, 2007 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>
+#include <rtld-global-offsets.h>
+#include <shlib-compat.h>
+
+#define __ASSEMBLY__
+#include <asm/ptrace.h>
+#include "ucontext_i.h"
+
+#define __CONTEXT_FUNC_NAME __swapcontext
+#undef __CONTEXT_ENABLE_FPRS
+#undef __CONTEXT_ENABLE_VRS
+#include "getcontext-extra.S"
+#include "setcontext-extra.S"
+
+# include "swapcontext-common.S"
+
+versioned_symbol (libc, __swapcontext, swapcontext, GLIBC_2_3_4)
+
+#if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
+
+/* For the nofpu case the old/new versions are the same function.  */  
+strong_alias (__swapcontext, __novec_swapcontext)
+
+compat_symbol (libc, __novec_swapcontext, swapcontext, GLIBC_2_3_3)
+
+#endif
+
+#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
+
+#define _ERRNO_H	1
+#include <bits/errno.h>
+
+	compat_text_section
+ENTRY (__swapcontext_stub)
+	li	r3,ENOSYS
+	b	__syscall_error@local
+END (__swapcontext_stub)
+	.previous
+
+compat_symbol (libc, __swapcontext_stub, swapcontext, GLIBC_2_1)
+
+#endif
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/nptl/c++-types.data b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/nptl/c++-types.data
new file mode 100644
index 0000000..fde53bf
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/nptl/c++-types.data
@@ -0,0 +1,67 @@
+blkcnt64_t:x
+blkcnt_t:l
+blksize_t:l
+caddr_t:Pc
+clockid_t:i
+clock_t:l
+daddr_t:i
+dev_t:y
+fd_mask:l
+fsblkcnt64_t:y
+fsblkcnt_t:m
+fsfilcnt64_t:y
+fsfilcnt_t:m
+fsid_t:8__fsid_t
+gid_t:j
+id_t:j
+ino64_t:y
+ino_t:m
+int16_t:s
+int32_t:i
+int64_t:x
+int8_t:a
+intptr_t:i
+key_t:i
+loff_t:x
+mode_t:j
+nlink_t:j
+off64_t:x
+off_t:l
+pid_t:i
+pthread_attr_t:14pthread_attr_t
+pthread_barrier_t:17pthread_barrier_t
+pthread_barrierattr_t:21pthread_barrierattr_t
+pthread_cond_t:14pthread_cond_t
+pthread_condattr_t:18pthread_condattr_t
+pthread_key_t:j
+pthread_mutex_t:15pthread_mutex_t
+pthread_mutexattr_t:19pthread_mutexattr_t
+pthread_once_t:i
+pthread_rwlock_t:16pthread_rwlock_t
+pthread_rwlockattr_t:20pthread_rwlockattr_t
+pthread_spinlock_t:i
+pthread_t:m
+quad_t:x
+register_t:i
+rlim64_t:y
+rlim_t:m
+sigset_t:10__sigset_t
+size_t:j
+socklen_t:j
+ssize_t:i
+suseconds_t:l
+time_t:l
+u_char:h
+uid_t:j
+uint:j
+u_int:j
+u_int16_t:t
+u_int32_t:j
+u_int64_t:y
+u_int8_t:h
+ulong:m
+u_long:m
+u_quad_t:y
+useconds_t:j
+ushort:t
+u_short:t
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/nptl/localplt.data b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/nptl/localplt.data
new file mode 100644
index 0000000..3c64ec9
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/nptl/localplt.data
@@ -0,0 +1,13 @@
+libc.so: __signbit
+libc.so: __signbitl
+libc.so: abort
+libc.so: calloc
+libc.so: free
+libc.so: malloc
+libc.so: memalign
+libc.so: realloc
+libm.so: __signbit
+libm.so: __signbitf
+libm.so: __signbitl
+libm.so: fegetround
+libm.so: matherr
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/shlib-versions b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/shlib-versions
new file mode 100644
index 0000000..2ea2298
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/shlib-versions
@@ -0,0 +1 @@
+powerpc.*-.*-.*		ABI			powerpce500v2-linux-gnu
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/Implies b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/Implies
new file mode 100644
index 0000000..ec38796
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/Implies
@@ -0,0 +1 @@
+powerpc/powerpc32/e500/soft-fp
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/nptl/c++-types.data b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/nptl/c++-types.data
new file mode 100644
index 0000000..fde53bf
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/nptl/c++-types.data
@@ -0,0 +1,67 @@
+blkcnt64_t:x
+blkcnt_t:l
+blksize_t:l
+caddr_t:Pc
+clockid_t:i
+clock_t:l
+daddr_t:i
+dev_t:y
+fd_mask:l
+fsblkcnt64_t:y
+fsblkcnt_t:m
+fsfilcnt64_t:y
+fsfilcnt_t:m
+fsid_t:8__fsid_t
+gid_t:j
+id_t:j
+ino64_t:y
+ino_t:m
+int16_t:s
+int32_t:i
+int64_t:x
+int8_t:a
+intptr_t:i
+key_t:i
+loff_t:x
+mode_t:j
+nlink_t:j
+off64_t:x
+off_t:l
+pid_t:i
+pthread_attr_t:14pthread_attr_t
+pthread_barrier_t:17pthread_barrier_t
+pthread_barrierattr_t:21pthread_barrierattr_t
+pthread_cond_t:14pthread_cond_t
+pthread_condattr_t:18pthread_condattr_t
+pthread_key_t:j
+pthread_mutex_t:15pthread_mutex_t
+pthread_mutexattr_t:19pthread_mutexattr_t
+pthread_once_t:i
+pthread_rwlock_t:16pthread_rwlock_t
+pthread_rwlockattr_t:20pthread_rwlockattr_t
+pthread_spinlock_t:i
+pthread_t:m
+quad_t:x
+register_t:i
+rlim64_t:y
+rlim_t:m
+sigset_t:10__sigset_t
+size_t:j
+socklen_t:j
+ssize_t:i
+suseconds_t:l
+time_t:l
+u_char:h
+uid_t:j
+uint:j
+u_int:j
+u_int16_t:t
+u_int32_t:j
+u_int64_t:y
+u_int8_t:h
+ulong:m
+u_long:m
+u_quad_t:y
+useconds_t:j
+ushort:t
+u_short:t
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/nptl/localplt.data b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/nptl/localplt.data
new file mode 100644
index 0000000..f385223
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/nptl/localplt.data
@@ -0,0 +1,31 @@
+libc.so: __adddf3
+libc.so: __divdf3
+libc.so: __eqdf2
+libc.so: __extendsfdf2
+libc.so: __fixdfsi
+libc.so: __fixunsdfsi
+libc.so: __floatsidf
+libc.so: __floatunsidf
+libc.so: __gedf2
+libc.so: __gtdf2
+libc.so: __ledf2
+libc.so: __ltdf2
+libc.so: __muldf3
+libc.so: __nedf2
+libc.so: __signbit
+libc.so: __signbitl
+libc.so: __subdf3
+libc.so: __truncdfsf2
+libc.so: __unorddf2
+libc.so: abort
+libc.so: calloc
+libc.so: free
+libc.so: malloc
+libc.so: memalign
+libc.so: realloc
+libm.so: __signbit
+libm.so: __signbitf
+libm.so: __signbitl
+libm.so: copysignl
+libm.so: fegetround
+libm.so: matherr
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/shlib-versions b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/shlib-versions
new file mode 100644
index 0000000..a746f46
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500/single/shlib-versions
@@ -0,0 +1 @@
+powerpc.*-.*-.*		ABI			powerpce500v1-linux-gnu
diff --git a/sysdeps/powerpc/fpu/bits/fenvinline.h b/sysdeps/powerpc/fpu/bits/fenvinline.h
index 46c5013..3a440ab 100644
--- a/sysdeps/powerpc/fpu/bits/fenvinline.h
+++ b/sysdeps/powerpc/fpu/bits/fenvinline.h
@@ -17,7 +17,8 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_MATH_INLINES
+#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__ \
+  && !defined __NO_MATH_INLINES
 
 /* Inline definition for fegetround.  */
 # define fegetround() \
@@ -57,4 +58,4 @@
       : 0)								      \
    : (feclearexcept) (__excepts))
 
-#endif /* __GNUC__ && !_SOFT_FLOAT */
+#endif /* __GNUC__ && !__NO_FPRS__ */
diff --git a/sysdeps/powerpc/fpu/bits/mathinline.h b/sysdeps/powerpc/fpu/bits/mathinline.h
index 51eca15..3e44640 100644
--- a/sysdeps/powerpc/fpu/bits/mathinline.h
+++ b/sysdeps/powerpc/fpu/bits/mathinline.h
@@ -27,7 +27,7 @@
 # define __MATH_INLINE __extern_inline
 #endif  /* __cplusplus */
 
-#if defined __GNUC__ && !defined _SOFT_FLOAT
+#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__
 
 #ifdef __USE_ISOC99
 # if !__GNUC_PREREQ (2,97)
@@ -128,4 +128,4 @@ __NTH (fdimf (float __x, float __y))
 
 #endif /* __USE_ISOC99 */
 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
-#endif /* __GNUC__ && !_SOFT_FLOAT */
+#endif /* __GNUC__ && !__NO_FPRS__ */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
index 3693e41..68c715f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
@@ -261,6 +261,11 @@ ENTRY(__CONTEXT_FUNC_NAME)
 2: /* L(no_vec): */
 # endif
 #endif
+
+#ifdef __GETCONTEXT_EXTRA
+	__GETCONTEXT_EXTRA
+#endif
+
 /* We need to set up parms and call sigprocmask which will clobber
    volatile registers. So before the call we need to retrieve the
    original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
index 2942573..74359e8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
@@ -243,6 +243,10 @@ ENTRY(__CONTEXT_FUNC_NAME)
 	lfd	fp31,_UC_FREGS+(31*8)(r31)
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __SETCONTEXT_EXTRA
+	__SETCONTEXT_EXTRA
+#endif
+
 	/* Restore LR and CCR, and set CTR to the NIP value */
 	lwz	r3,_UC_GREGS+(PT_LNK*4)(r31)
 	lwz	r4,_UC_GREGS+(PT_NIP*4)(r31)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
index 90270b3..7724303 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
@@ -265,6 +265,10 @@ ENTRY(__CONTEXT_FUNC_NAME)
 # endif /* __CONTEXT_ENABLE_VRS */
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __GETCONTEXT_EXTRA
+	__GETCONTEXT_EXTRA
+#endif
+
 /* Restore ucontext (parm1) from stack.  */
 	lwz	r12,_FRAME_PARM_SAVE1(r1)
 	li	r4,0
@@ -468,6 +472,10 @@ ENTRY(__CONTEXT_FUNC_NAME)
 	lfd	fp31,_UC_FREGS+(31*8)(r31)
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __SETCONTEXT_EXTRA
+	__SETCONTEXT_EXTRA
+#endif
+
 	/* Restore LR and CCR, and set CTR to the NIP value */
 	lwz	r3,_UC_GREGS+(PT_LNK*4)(r31)
 	lwz	r4,_UC_GREGS+(PT_NIP*4)(r31)
