# DP: Proposed patch for PR libstdc++/39491.

2009-04-16  Benjamin Kosnik  <bkoz@redhat.com>

	* src/math_stubs_long_double.cc (__signbitl): Add for hppa linux only.

Index: a/src/libstdc++-v3/src/math_stubs_long_double.cc
===================================================================
--- a/src/libstdc++-v3/src/math_stubs_long_double.cc	(revision 146216)
+++ b/src/libstdc++-v3/src/math_stubs_long_double.cc	(working copy)
@@ -213,4 +221,111 @@
     return tanh((double) x);
   }
 #endif
+
+  // From libmath/signbitl.c
+  // XXX ABI mistakenly exported
+#if defined (__hppa__) && defined (__linux__)
+# include <endian.h>
+# include <float.h>
+
+typedef unsigned int U_int32_t __attribute ((mode (SI)));
+typedef int Int32_t __attribute ((mode (SI)));
+typedef unsigned int U_int64_t __attribute ((mode (DI)));
+typedef int Int64_t __attribute ((mode (DI)));
+
+#if BYTE_ORDER == BIG_ENDIAN
+typedef union
+{
+  long double value;
+  struct
+  {
+    unsigned int sign_exponent:16;
+    unsigned int empty:16;
+    U_int32_t msw;
+    U_int32_t lsw;
+  } parts;
+} ieee_long_double_shape_type;
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+typedef union
+{
+  long double value;
+  struct
+  {
+    U_int32_t lsw;
+    U_int32_t msw;
+    unsigned int sign_exponent:16;
+    unsigned int empty:16;
+  } parts;
+} ieee_long_double_shape_type;
+#endif
+
+/* Get int from the exponent of a long double.  */
+#define GET_LDOUBLE_EXP(exp,d)                                  \
+do {                                                            \
+  ieee_long_double_shape_type ge_u;                             \
+  ge_u.value = (d);                                             \
+  (exp) = ge_u.parts.sign_exponent;                             \
+} while (0)
+
+#if BYTE_ORDER == BIG_ENDIAN
+typedef union
+{
+  long double value;
+  struct
+  {
+    U_int64_t msw;
+    U_int64_t lsw;
+  } parts64;
+  struct
+  {
+    U_int32_t w0, w1, w2, w3;
+  } parts32;
+} ieee_quad_double_shape_type;
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+typedef union
+{
+  long double value;
+  struct
+  {
+    U_int64_t lsw;
+    U_int64_t msw;
+  } parts64;
+  struct
+  {
+    U_int32_t w3, w2, w1, w0;
+  } parts32;
+} ieee_quad_double_shape_type;
+#endif
+
+/* Get most significant 64 bit int from a quad long double.  */
+#define GET_LDOUBLE_MSW64(msw,d)				\
+do {								\
+  ieee_quad_double_shape_type qw_u;				\
+  qw_u.value = (d);						\
+  (msw) = qw_u.parts64.msw;					\
+} while (0)
+
+int
+__signbitl (long double x)
+{
+#if LDBL_MANT_DIG == 113
+  Int64_t msw;
+
+  GET_LDOUBLE_MSW64 (msw, x);
+  return msw < 0;
+#else
+  Int32_t e;
+
+  GET_LDOUBLE_EXP (e, x);
+  return e & 0x8000;
+#endif
+}
+#endif
+
+#ifndef _GLIBCXX_HAVE___SIGNBITL
+
+#endif
 } // extern "C"
--- a/src/libstdc++-v3/config/abi/pre/gnu.ver~	2009-04-10 01:23:07.000000000 +0200
+++ b/src/libstdc++-v3/config/abi/pre/gnu.ver	2009-04-21 16:24:24.000000000 +0200
@@ -635,6 +635,7 @@
     sqrtf;
     sqrtl;
     copysignf;
+    __signbitl;
 
    # GLIBCXX_ABI compatibility only.
     # std::string
