diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cf4cd24f51d9eb8a86aa73e2f060ee3d860aa3ff..80e90935bbd697eb4c547306fa43557b55758f94 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2007-01-16  Janis Johnson  <janis187@us.ibm.com>
+
+	* config/dfp-bit.c (dfp_compare_op): Return separate value for NaN.
+	(DFP_NE, DFP_LE, DFP_GE): Return false for NaN.
+
 2007-01-16  David Edelsohn  <edelsohn@gnu.org>
 
 	* config/rs6000/darwin-ldouble.c: Build file for SOFT_FLOAT.
diff --git a/gcc/config/dfp-bit.c b/gcc/config/dfp-bit.c
index 0ee2083e835b7f0bf43392f08fab5edb016ecd2b..47575ccc8b77d0f14dffa99f4246fc540ede1d71 100644
--- a/gcc/config/dfp-bit.c
+++ b/gcc/config/dfp-bit.c
@@ -146,6 +146,8 @@ dfp_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
     result = -1;
   else if (decNumberIsZero (&res))
     result = 0;
+  else if (decNumberIsNaN (&res))
+    result = -2;
   else
     result = 1;
 
@@ -302,7 +304,9 @@ DFP_NE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
 {
   int stat;
   stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
-  /* For NE return nonzero for true, zero for false.  */
+  /* For NE return zero for true, nonzero for false.  */
+  if (__builtin_expect (stat == -2, 0))  /* An operand is NaN.  */
+    return 1;
   return stat != 0;
 }
 #endif /* L_ne */
@@ -336,6 +340,8 @@ DFP_LE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
   int stat;
   stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
   /* For LE return 0 (<= 0) for true, 1 for false.  */
+  if (__builtin_expect (stat == -2, 0))  /* An operand is NaN.  */
+    return 1;
   return stat == 1;
 }
 #endif /* L_le */
@@ -347,6 +353,8 @@ DFP_GE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
   int stat;
   stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
   /* For GE return 1 (>=0) for true, -1 for false.  */
+  if (__builtin_expect (stat == -2, 0))  /* An operand is NaN.  */
+    return -1;
   return (stat != -1) ? 1 : -1;
 }
 #endif /* L_ge */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5d3374783bbb8ad75d5f3b60e9fa2481ab29584f..b098046ddbcef9f6ac8455aacb10e793767b216e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2007-01-16  Janis Johnson  <janis187@us.ibm.com>
+
+	* gcc.dg/dfp/compare-special.h: New file.
+	* gcc.dg/dfp/compare-special-32.c: New test.
+	* gcc.dg/dfp/compare-special-64.c: New test.
+	* gcc.dg/dfp/compare-special-128.c: New test.
+
 2007-01-16  Roger Sayle  <roger@eyesopen.com>
 	    Paul Thomas  <pault@gcc.gnu.org>
 	    Steven G. Kargl  <kargl@gcc.gnu.org>
diff --git a/gcc/testsuite/gcc.dg/dfp/compare-special-d128.c b/gcc/testsuite/gcc.dg/dfp/compare-special-d128.c
new file mode 100644
index 0000000000000000000000000000000000000000..cef4670b766464e22c01d48e3940e9c1042bb522
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/compare-special-d128.c
@@ -0,0 +1,15 @@
+/* { dg-options "-std=gnu99 -O0" } */
+
+/* C99 6.5.8 Relational operators.
+   C99 6.5.9 Equality operators.
+   Compare decimal float special values at runtime.  */
+
+#define WIDTH 128
+#include "compare-special.h"
+
+int
+main ()
+{
+  test_compares ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/compare-special-d32.c b/gcc/testsuite/gcc.dg/dfp/compare-special-d32.c
new file mode 100644
index 0000000000000000000000000000000000000000..fa91d7edd33f2bcaa63447440e684c5371c63dcb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/compare-special-d32.c
@@ -0,0 +1,15 @@
+/* { dg-options "-std=gnu99 -O0" } */
+
+/* C99 6.5.8 Relational operators.
+   C99 6.5.9 Equality operators.
+   Compare decimal float special values at runtime.  */
+
+#define WIDTH 32
+#include "compare-special.h"
+
+int
+main ()
+{
+  test_compares ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/compare-special-d64.c b/gcc/testsuite/gcc.dg/dfp/compare-special-d64.c
new file mode 100644
index 0000000000000000000000000000000000000000..2238e0190e3b5f34dfc5f6f3599c97bf564e09ab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/compare-special-d64.c
@@ -0,0 +1,15 @@
+/* { dg-options "-std=gnu99 -O0" } */
+
+/* C99 6.5.8 Relational operators.
+   C99 6.5.9 Equality operators.
+   Compare decimal float special values at runtime.  */
+
+#define WIDTH 64
+#include "compare-special.h"
+
+int
+main ()
+{
+  test_compares ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/compare-special.h b/gcc/testsuite/gcc.dg/dfp/compare-special.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bd77e521563127ad34fa2dc238d969539650e1f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/compare-special.h
@@ -0,0 +1,287 @@
+/* Basic test of runtime relational comparisons using NaNs and infinities.  */
+
+#include <stdlib.h>
+
+static int failcnt;
+
+#define PASTE2(A,B) A ## B
+#define PASTE(A,B) PASTE2(A,B)
+
+#ifdef DBG
+#include <stdio.h>
+#define FAILURE(OP,KIND) \
+  { printf ("failed at line %d: %s for %s values\n", __LINE__, OP, KIND); \
+    failcnt++; }
+#else
+#define FAILURE(OP,KIND) abort ();
+#endif
+
+#ifndef WIDTH
+#error define WIDTH as decimal float size in bytes
+#endif
+
+#if WIDTH == 32
+#define DTYPE _Decimal32
+#define SUFFIX DF
+#define SUFFIX2 d32
+#elif WIDTH == 64
+#define DTYPE _Decimal64
+#define SUFFIX DD
+#define SUFFIX2 d64
+#elif WIDTH == 128
+#define DTYPE _Decimal128
+#define SUFFIX DL
+#define SUFFIX2 d128
+#elif WIDTH == 0
+/* This is for testing the test using a type known to work.  */
+#define DTYPE double
+#define SUFFIX
+#define SUFFIX2
+#else
+#error invalid width for decimal float type
+#endif
+
+DTYPE m_two = PASTE(-2.0, SUFFIX);
+DTYPE m_one = PASTE(-1.0, SUFFIX);
+DTYPE zero  = PASTE(0.0, SUFFIX);
+DTYPE one   = PASTE(1.0, SUFFIX);
+DTYPE two   = PASTE(2.0, SUFFIX);
+
+volatile DTYPE x, y, z, nan, inf, m_inf;
+
+void
+test_compares (void)
+{
+  nan = PASTE(__builtin_nan, SUFFIX2) ("");
+  inf = PASTE(__builtin_inf, SUFFIX2) ();
+  m_inf = - PASTE(__builtin_inf, SUFFIX2) ();
+
+  x = PASTE(__builtin_nan, SUFFIX2) ("");
+  y = PASTE(__builtin_inf, SUFFIX2) ();
+  z = - PASTE(__builtin_inf, SUFFIX2) ();
+
+  /* Less than or equal to with NaN.  */
+
+  if (x <= two)   FAILURE ("<=", "NaN")
+  if (x <= zero)  FAILURE ("<=", "NaN")
+  if (x <= m_one) FAILURE ("<=", "NaN")
+  if (x <= nan)   FAILURE ("<=", "NaN")
+  if (x <= inf)   FAILURE ("<=", "NaN")
+  if (x <= m_inf) FAILURE ("<=", "NaN")
+
+  if (two <= x)   FAILURE ("<=", "NaN")
+  if (zero <= x)  FAILURE ("<=", "NaN")
+  if (m_one <= x) FAILURE ("<=", "NaN")
+  if (nan <= x)   FAILURE ("<=", "NaN")
+  if (inf <= x)   FAILURE ("<=", "NaN")
+  if (m_inf <= x) FAILURE ("<=", "NaN")
+
+  /* Less than or equal to with infinities, no NaNs.  */
+
+  if (y <= two)      FAILURE ("<=", "inf")
+  if (y <= zero)     FAILURE ("<=", "inf")
+  if (y <= m_one)    FAILURE ("<=", "inf")
+  if (!(two <= y))   FAILURE ("<=", "inf")
+  if (!(zero <= y))  FAILURE ("<=", "inf")
+  if (!(m_one <= y)) FAILURE ("<=", "inf")
+
+  if (!(z <= two))   FAILURE ("<=", "-inf")
+  if (!(z <= zero))  FAILURE ("<=", "-inf")
+  if (!(z <= m_one)) FAILURE ("<=", "-inf")
+  if (two <= z)      FAILURE ("<=", "-inf")
+  if (zero <= z)     FAILURE ("<=", "-inf")
+  if (m_one <= z)    FAILURE ("<=", "-inf")
+
+  if (!(y <= inf))   FAILURE ("<=", "inf")
+  if (y <= m_inf)    FAILURE ("<=", "inf")
+  if (!(z <= inf))   FAILURE ("<=", "inf")
+  if (!(z <= m_inf)) FAILURE ("<=", "inf")
+
+  /* Less than with NaN.  */
+
+  if (x < two)       FAILURE ("<", "NaN")
+  if (x < zero)      FAILURE ("<", "NaN")
+  if (x < m_one)     FAILURE ("<", "NaN")
+  if (x < nan)       FAILURE ("<", "NaN")
+  if (x < inf)       FAILURE ("<", "NaN")
+  if (x < m_inf)     FAILURE ("<", "NaN")
+
+  if (two < x)       FAILURE ("<", "NaN")
+  if (zero < x)      FAILURE ("<", "NaN")
+  if (m_one < x)     FAILURE ("<", "NaN")
+  if (nan < x)       FAILURE ("<", "NaN")
+  if (inf < x)       FAILURE ("<", "NaN")
+  if (m_inf < x)     FAILURE ("<", "NaN")
+
+  /* Less than with infinities, no NaNs.  */
+
+  if (y < two)       FAILURE ("<", "inf")
+  if (y < zero)      FAILURE ("<", "inf")
+  if (y < m_one)     FAILURE ("<", "inf")
+  if (!(two < y))    FAILURE ("<", "inf")
+  if (!(zero < y))   FAILURE ("<", "inf")
+  if (!(m_one < y))  FAILURE ("<", "inf")
+
+  if (!(z < two))    FAILURE ("<", "-inf")
+  if (!(z < zero))   FAILURE ("<", "-inf")
+  if (!(z < m_one))  FAILURE ("<", "-inf")
+  if (two < z)       FAILURE ("<", "-inf")
+  if (zero < z)      FAILURE ("<", "-inf")
+  if (m_one < z)     FAILURE ("<", "-inf")
+
+  if (y < inf)       FAILURE ("<=", "inf")
+  if (y < m_inf)     FAILURE ("<=", "inf")
+  if (!(z < inf))    FAILURE ("<=", "inf")
+  if (z < m_inf)     FAILURE ("<=", "inf")
+
+  /* Greater than or equal to with NaN.  */
+
+  if (x >= two)      FAILURE (">=", "NaN")
+  if (x >= zero)     FAILURE (">=", "NaN")
+  if (x >= m_one)    FAILURE (">=", "NaN")
+  if (x >= nan)      FAILURE (">=", "NaN")
+  if (x >= inf)      FAILURE (">=", "NaN")
+  if (x >= m_inf)    FAILURE (">=", "NaN")
+
+  if (two >= x)      FAILURE (">=", "NaN")
+  if (zero >= x)     FAILURE (">=", "NaN")
+  if (m_one >= x)    FAILURE (">=", "NaN")
+  if (nan >= x)      FAILURE (">=", "NaN")
+  if (inf >= x)      FAILURE (">=", "NaN")
+  if (m_inf >= x)    FAILURE (">=", "NaN")
+
+  /* Greater than or equal to with infinities, no NaNs.  */
+
+  if (!(y >= two))   FAILURE (">=", "inf")
+  if (!(y >= zero))  FAILURE (">=", "inf")
+  if (!(y >= m_one)) FAILURE (">=", "inf")
+  if (two >= y)      FAILURE (">=", "inf")
+  if (zero >= y)     FAILURE (">=", "inf")
+  if (m_one >= y)    FAILURE (">=", "inf")
+
+  if (z >= two)      FAILURE (">=", "-inf")
+  if (z >= zero)     FAILURE (">=", "-inf")
+  if (z >= m_one)    FAILURE (">=", "-inf")
+  if (!(two >= z))   FAILURE (">=", "-inf")
+  if (!(zero >= z))  FAILURE (">=", "-inf")
+  if (!(m_one >= z)) FAILURE (">=", "-inf")
+
+  if (!(y >= inf))   FAILURE ("<=", "inf")
+  if (!(y >= m_inf)) FAILURE ("<=", "inf")
+  if (z >= inf)      FAILURE ("<=", "inf")
+  if (!(z >= m_inf)) FAILURE ("<=", "inf")
+
+  /* Greater than with NaN.  */
+
+  if (x > two)       FAILURE (">", "NaN")
+  if (x > zero)      FAILURE (">", "NaN")
+  if (x > m_one)     FAILURE (">", "NaN")
+  if (x > nan)       FAILURE (">", "NaN")
+  if (x > inf)       FAILURE (">", "NaN")
+  if (x > m_inf)     FAILURE (">", "NaN")
+
+  if (two > x)       FAILURE (">", "NaN")
+  if (zero > x)      FAILURE (">", "NaN")
+  if (m_one > x)     FAILURE (">", "NaN")
+  if (nan > x)       FAILURE (">", "NaN")
+  if (inf > x)       FAILURE (">", "NaN")
+  if (m_inf > x)     FAILURE (">", "NaN")
+
+  /* Greater than with infinities, no NaNs.  */
+
+  if (!(y > two))    FAILURE (">", "inf")
+  if (!(y > zero))   FAILURE (">", "inf")
+  if (!(y > m_one))  FAILURE (">", "inf")
+  if (two > y)       FAILURE (">", "inf")
+  if (zero > y)      FAILURE (">", "inf")
+  if (m_one > y)     FAILURE (">", "inf")
+
+  if (z > two)       FAILURE (">", "-inf")
+  if (z > zero)      FAILURE (">", "-inf")
+  if (z > m_one)     FAILURE (">", "-inf")
+  if (!(two > z))    FAILURE (">", "-inf")
+  if (!(zero > z))   FAILURE (">", "-inf")
+  if (!(m_one > z))  FAILURE (">", "-inf")
+
+  if (y > inf)       FAILURE (">", "inf")
+  if (!(y > m_inf))  FAILURE (">", "inf")
+  if (z > inf)       FAILURE (">", "inf")
+  if (z > m_inf)     FAILURE (">", "inf")
+
+  /* Equal with NaN.  */
+
+  if (x == two)      FAILURE ("==", "NaN")
+  if (x == zero)     FAILURE ("==", "NaN")
+  if (x == m_one)    FAILURE ("==", "NaN")
+  if (x == nan)      FAILURE ("==", "NaN")
+  if (x == inf)      FAILURE ("==", "NaN")
+  if (x == m_inf)    FAILURE ("==", "NaN")
+
+  if (two == x)      FAILURE ("==", "NaN")
+  if (zero == x)     FAILURE ("==", "NaN")
+  if (m_one == x)    FAILURE ("==", "NaN")
+  if (nan == x)      FAILURE ("==", "NaN")
+  if (inf == x)      FAILURE ("==", "NaN")
+  if (m_inf == x)    FAILURE ("==", "NaN")
+
+  /* Equal with infinities, no NaNs.  */
+
+  if (y == two)      FAILURE ("==", "inf")
+  if (y == zero)     FAILURE ("==", "inf")
+  if (y == m_one)    FAILURE ("==", "inf")
+  if (two == y)      FAILURE ("==", "inf")
+  if (zero == y)     FAILURE ("==", "inf")
+  if (m_one == y)    FAILURE ("==", "inf")
+
+  if (z == two)      FAILURE ("==", "-inf")
+  if (z == zero)     FAILURE ("==", "-inf")
+  if (z == m_one)    FAILURE ("==", "-inf")
+  if (two == z)      FAILURE ("==", "-inf")
+  if (zero == z)     FAILURE ("==", "-inf")
+  if (m_one == z)    FAILURE ("==", "-inf")
+
+  if (!(y == inf))   FAILURE ("==", "inf")
+  if (y == m_inf)    FAILURE ("==", "inf")
+  if (z == inf)      FAILURE ("==", "inf")
+  if (!(z == m_inf)) FAILURE ("==", "inf")
+
+  /* Not equal with NaN.  */
+
+  if (!(x != two))   FAILURE ("!=", "NaN")
+  if (!(x != zero))  FAILURE ("!=", "NaN")
+  if (!(x != m_one)) FAILURE ("!=", "NaN")
+  if (!(x != nan))   FAILURE ("!=", "NaN")
+  if (!(x != inf))   FAILURE ("!=", "NaN")
+  if (!(x != m_inf)) FAILURE ("!=", "NaN")
+
+  if (!(two != x))   FAILURE ("!=", "NaN")
+  if (!(zero != x))  FAILURE ("!=", "NaN")
+  if (!(m_one != x)) FAILURE ("!=", "NaN")
+  if (!(nan != x))   FAILURE ("!=", "NaN")
+  if (!(inf != x))   FAILURE ("!=", "NaN")
+  if (!(m_inf != x)) FAILURE ("!=", "NaN")
+
+  /* Not equal with infinities, no NaNs.  */
+
+  if (!(y != two))   FAILURE ("!=", "inf")
+  if (!(y != zero))  FAILURE ("!=", "inf")
+  if (!(y != m_one)) FAILURE ("!=", "inf")
+  if (!(two != y))   FAILURE ("!=", "inf")
+  if (!(zero != y))  FAILURE ("!=", "inf")
+  if (!(m_one != y)) FAILURE ("!=", "inf")
+
+  if (!(z != two))   FAILURE ("!=", "-inf")
+  if (!(z != zero))  FAILURE ("!=", "-inf")
+  if (!(z != m_one)) FAILURE ("!=", "-inf")
+  if (!(two != z))   FAILURE ("!=", "-inf")
+  if (!(zero != z))  FAILURE ("!=", "-inf")
+  if (!(m_one != z)) FAILURE ("!=", "-inf")
+
+  if (y != inf)      FAILURE ("!=", "inf")
+  if (!(y != m_inf)) FAILURE ("!=", "inf")
+  if (!(z != inf))   FAILURE ("!=", "inf")
+  if (z != m_inf)    FAILURE ("!=", "inf")
+
+  if (failcnt)
+    abort ();
+}