* Makefile.in (D32PBIT_FUNCS): New.
authorbje <bje@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 18 Jan 2006 00:39:23 +0000 (00:39 +0000)
committerbje <bje@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 18 Jan 2006 00:39:23 +0000 (00:39 +0000)
(D64PBIT_FUNCS, D128PBIT_FUNCS): Likewise.
(libgcc.mk): Set D32PBIT, D64PBIT, D128PBIT, D32PBIT_FUNCS,
D64PBIT_FUNCS and D128PBIT_FUNCS.
(LIBGCC_DEPS): Include $(D32PBIT), $(D64PBIT), $(D128PBIT).
* mklibgcc.in Bring in the DFP support code if D32PBIT, D64PBIT or
D128PBIT are set.
(decnumber_dep): Define.
* doc/libgcc.texi (Decimal float library routines): New node.
* config/dfp-bit.h, config/dfp-bit.c: New files.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109856 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/config/dfp-bit.c [new file with mode: 0644]
gcc/config/dfp-bit.h [new file with mode: 0644]
gcc/doc/libgcc.texi
gcc/mklibgcc.in

index 2ac7d8b..a096147 100644 (file)
@@ -1,5 +1,18 @@
 2006-01-18  Ben Elliston  <bje@au.ibm.com>     
 
+       * Makefile.in (D32PBIT_FUNCS): New.
+       (D64PBIT_FUNCS, D128PBIT_FUNCS): Likewise.
+       (libgcc.mk): Set D32PBIT, D64PBIT, D128PBIT, D32PBIT_FUNCS,
+       D64PBIT_FUNCS and D128PBIT_FUNCS.
+       (LIBGCC_DEPS): Include $(D32PBIT), $(D64PBIT), $(D128PBIT).
+       * mklibgcc.in Bring in the DFP support code if D32PBIT, D64PBIT or
+       D128PBIT are set.
+       (decnumber_dep): Define.
+       * doc/libgcc.texi (Decimal float library routines): New node.
+       * config/dfp-bit.h, config/dfp-bit.c: New files.
+
+2006-01-18  Ben Elliston  <bje@au.ibm.com>     
+
        * expr.c (emit_move_change_mode): Always adjust addresses, not
        just during reload.  Copy replacements only during reload.
        (emit_move_insn_1): Move MODE_DECIMAL_FLOAT modes by invoking
index e791858..a993f97 100644 (file)
@@ -1055,6 +1055,29 @@ TPBIT_FUNCS = _pack_tf _unpack_tf _addsub_tf _mul_tf _div_tf \
     _lt_tf _le_tf _unord_tf _si_to_tf _tf_to_si _negate_tf _make_tf \
     _tf_to_df _tf_to_sf _thenan_tf _tf_to_usi _usi_to_tf
 
+D32PBIT_FUNCS = _addsub_sd _div_sd _mul_sd _plus_sd _minus_sd \
+       _eq_sd _ne_sd _lt_sd _gt_sd _le_sd _ge_sd \
+       _sd_to_si _sd_to_di _sd_to_usi _sd_to_udi \
+       _si_to_sd _di_to_sd _usi_to_sd _udi_to_sd \
+       _sd_to_sf _sd_to_df _sd_to_xf _sf_to_sd _df_to_sd _xf_to_sd \
+       _sd_to_dd _sd_to_td _unord_sd _conv_sd
+
+D64PBIT_FUNCS = _addsub_dd _div_dd _mul_dd _plus_dd _minus_dd \
+       _eq_dd _ne_dd _lt_dd _gt_dd _le_dd _ge_dd \
+       _dd_to_si _dd_to_di _dd_to_usi _dd_to_udi \
+       _si_to_dd _di_to_dd _usi_to_dd _udi_to_dd \
+       _dd_to_sf _dd_to_df _dd_to_xf \
+       _sf_to_dd _df_to_dd _xf_to_dd \
+       _dd_to_sd _dd_to_td _unord_dd _conv_dd
+
+D128PBIT_FUNCS = _addsub_td _div_td _mul_td _plus_td _minus_td \
+       _eq_td _ne_td _lt_td _gt_td _le_td _ge_td \
+       _td_to_si _td_to_di _td_to_usi _td_to_udi \
+       _si_to_td _di_to_td _usi_to_td _udi_to_td \
+       _td_to_sf _td_to_df _td_to_xf \
+       _sf_to_td _df_to_td _xf_to_td \
+       _td_to_sd _td_to_dd _unord_td _conv_td
+
 # These might cause a divide overflow trap and so are compiled with
 # unwinder info.
 LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4
@@ -1393,6 +1416,12 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) specs \
        DPBIT_FUNCS='$(DPBIT_FUNCS)' \
        TPBIT='$(TPBIT)' \
        TPBIT_FUNCS='$(TPBIT_FUNCS)' \
+       D32PBIT='$(D32PBIT)' \
+       D32PBIT_FUNCS='$(D32PBIT_FUNCS)' \
+       D64PBIT='$(D64PBIT)' \
+       D64PBIT_FUNCS='$(D64PBIT_FUNCS)' \
+       D128PBIT='$(D128PBIT)' \
+       D128PBIT_FUNCS='$(D128PBIT_FUNCS)' \
        MULTILIBS=`$(GCC_FOR_TARGET) --print-multi-lib` \
        EXTRA_MULTILIB_PARTS='$(EXTRA_MULTILIB_PARTS)' \
        SHLIB_LINK='$(SHLIB_LINK)' \
@@ -1415,6 +1444,7 @@ LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
        libgcc.mk $(srcdir)/libgcc2.c $(srcdir)/libgcov.c $(TCONFIG_H) \
        $(MACHMODE_H) longlong.h gbl-ctors.h config.status $(srcdir)/libgcc2.h \
        tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
+       $(D32PBIT) $(D64PBIT) $(D128PBIT) \
        $(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
        $(srcdir)/config/$(LIB1ASMSRC) \
        $(srcdir)/gcov-io.h $(srcdir)/gcov-io.c gcov-iov.h
diff --git a/gcc/config/dfp-bit.c b/gcc/config/dfp-bit.c
new file mode 100644 (file)
index 0000000..835586b
--- /dev/null
@@ -0,0 +1,541 @@
+/* This is a software decimal floating point library.
+   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+/* This implements IEEE 754R decimal floating point arithmetic, but
+   does not provide a mechanism for setting the rounding mode, or for
+   generating or handling exceptions.  Conversions between decimal
+   floating point types and other types depend on C library functions.
+
+   Contributed by Ben Elliston  <bje@au.ibm.com>.  */
+
+/* The intended way to use this file is to make two copies, add `#define '
+   to one copy, then compile both copies and add them to libgcc.a.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "config/dfp-bit.h"
+
+/* Forward declarations.  */
+#if WIDTH == 32 || WIDTH_TO == 32
+void __host_to_ieee_32 (_Decimal32 in, decimal32 *out);
+void __ieee_to_host_32 (decimal32 in, _Decimal32 *out);
+#endif
+#if WIDTH == 64 || WIDTH_TO == 64
+void __host_to_ieee_64 (_Decimal64 in, decimal64 *out);
+void __ieee_to_host_64 (decimal64 in, _Decimal64 *out);
+#endif
+#if WIDTH == 128 || WIDTH_TO == 128
+void __host_to_ieee_128 (_Decimal128 in, decimal128 *out);
+void __ieee_to_host_128 (decimal128 in, _Decimal128 *out);
+#endif
+
+/* A pointer to a unary decNumber operation.  */
+typedef decNumber* (*dfp_unary_func)
+     (decNumber *, decNumber *, decContext *);
+
+/* A pointer to a binary decNumber operation.  */
+typedef decNumber* (*dfp_binary_func)
+     (decNumber *, decNumber *, decNumber *, decContext *);
+
+extern unsigned long __dec_byte_swap (unsigned long);
+\f
+/* Unary operations.  */
+
+static inline DFP_C_TYPE
+dfp_unary_op (dfp_unary_func op, DFP_C_TYPE arg)
+{
+  DFP_C_TYPE result;
+  decContext context;
+  decNumber arg1, res;
+  IEEE_TYPE a, encoded_result;
+
+  HOST_TO_IEEE (arg, &a);
+
+  decContextDefault (&context, CONTEXT_INIT);
+  context.round = CONTEXT_ROUND;
+
+  TO_INTERNAL (&a, &arg1);
+
+  /* Perform the operation.  */
+  op (&res, &arg1, &context);
+
+  if (CONTEXT_TRAPS && CONTEXT_ERRORS (context))
+    DFP_RAISE (0);
+
+  TO_ENCODED (&encoded_result, &res, &context);
+  IEEE_TO_HOST (encoded_result, &result);
+  return result;
+}
+
+/* Binary operations.  */
+
+static inline DFP_C_TYPE
+dfp_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  DFP_C_TYPE result;
+  decContext context;
+  decNumber arg1, arg2, res;
+  IEEE_TYPE a, b, encoded_result;
+
+  HOST_TO_IEEE (arg_a, &a);
+  HOST_TO_IEEE (arg_b, &b);
+
+  decContextDefault (&context, CONTEXT_INIT);
+  context.round = CONTEXT_ROUND;
+
+  TO_INTERNAL (&a, &arg1);
+  TO_INTERNAL (&b, &arg2);
+
+  /* Perform the operation.  */
+  op (&res, &arg1, &arg2, &context);
+
+  if (CONTEXT_TRAPS && CONTEXT_ERRORS (context))
+    DFP_RAISE (0);
+
+  TO_ENCODED (&encoded_result, &res, &context);
+  IEEE_TO_HOST (encoded_result, &result);
+  return result;
+}
+
+/* Comparison operations.  */
+
+static inline int
+dfp_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  IEEE_TYPE a, b;
+  decContext context;
+  decNumber arg1, arg2, res;
+  int result;
+
+  HOST_TO_IEEE (arg_a, &a);
+  HOST_TO_IEEE (arg_b, &b);
+
+  decContextDefault (&context, CONTEXT_INIT);
+  context.round = CONTEXT_ROUND;
+
+  TO_INTERNAL (&a, &arg1);
+  TO_INTERNAL (&b, &arg2);
+
+  /* Perform the comparison.  */
+  op (&res, &arg1, &arg2, &context);
+
+  if (CONTEXT_TRAPS && CONTEXT_ERRORS (context))
+    DFP_RAISE (0);
+
+  if (decNumberIsNegative (&res))
+    result = -1;
+  else if (decNumberIsZero (&res))
+    result = 0;
+  else
+    result = 1;
+
+  return result;
+}
+
+\f
+#if defined(L_conv_sd)
+void
+__host_to_ieee_32 (_Decimal32 in, decimal32 *out)
+{
+  uint32_t t;
+
+  if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
+    {
+      memcpy (&t, &in, 4);
+      t = __dec_byte_swap (t);
+      memcpy (out, &t, 4);
+    }
+  else
+    memcpy (out, &in, 4);
+}
+
+void
+__ieee_to_host_32 (decimal32 in, _Decimal32 *out)
+{
+  uint32_t t;
+
+  if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
+    {
+      memcpy (&t, &in, 4);
+      t = __dec_byte_swap (t);
+      memcpy (out, &t, 4);
+    }
+  else
+    memcpy (out, &in, 4);
+}
+#endif /* L_conv_sd */
+
+#if defined(L_conv_dd)
+static void
+__swap64 (char *src, char *dst)
+{
+  uint32_t t1, t2;
+
+  if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN) 
+    {
+      memcpy (&t1, src, 4);
+      memcpy (&t2, src + 4, 4);
+      t1 = __dec_byte_swap (t1);
+      t2 = __dec_byte_swap (t2);
+      memcpy (dst, &t2, 4);
+      memcpy (dst + 4, &t1, 4);
+    }
+  else
+    memcpy (dst, src, 8);
+}
+
+void
+__host_to_ieee_64 (_Decimal64 in, decimal64 *out)
+{
+  __swap64 ((char *) &in, (char *) out);
+}
+
+void
+__ieee_to_host_64 (decimal64 in, _Decimal64 *out)
+{
+  __swap64 ((char *) &in, (char *) out);
+}
+#endif /* L_conv_dd */
+
+#if defined(L_conv_td)
+static void
+__swap128 (char *src, char *dst)
+{
+  uint32_t t1, t2, t3, t4;
+
+  if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
+    {
+      memcpy (&t1, src, 4);
+      memcpy (&t2, src + 4, 4);
+      memcpy (&t3, src + 8, 4);
+      memcpy (&t4, src + 12, 4);
+      t1 = __dec_byte_swap (t1);
+      t2 = __dec_byte_swap (t2);
+      t3 = __dec_byte_swap (t3);
+      t4 = __dec_byte_swap (t4);
+      memcpy (dst, &t4, 4);
+      memcpy (dst + 4, &t3, 4);
+      memcpy (dst + 8, &t2, 4);
+      memcpy (dst + 12, &t1, 4);
+    }
+  else
+    memcpy (dst, src, 16);
+}
+
+void
+__host_to_ieee_128 (_Decimal128 in, decimal128 *out)
+{
+  __swap128 ((char *) &in, (char *) out);
+}
+
+void
+__ieee_to_host_128 (decimal128 in, _Decimal128 *out)
+{
+  __swap128 ((char *) &in, (char *) out);
+}
+#endif /* L_conv_td */
+
+#if defined(L_addsub_sd) || defined(L_addsub_dd) || defined(L_addsub_td)
+DFP_C_TYPE
+DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  return dfp_binary_op (decNumberAdd, arg_a, arg_b);
+}
+
+DFP_C_TYPE
+DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  return dfp_binary_op (decNumberSubtract, arg_a, arg_b);
+}
+#endif /* L_addsub */
+
+#if defined(L_mul_sd) || defined(L_mul_dd) || defined(L_mul_td)
+DFP_C_TYPE
+DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  return dfp_binary_op (decNumberMultiply, arg_a, arg_b);
+}
+#endif /* L_mul */
+
+#if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
+DFP_C_TYPE
+DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  return dfp_binary_op (decNumberDivide, arg_a, arg_b);
+}
+#endif /* L_div */
+
+#if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
+CMPtype
+DFP_EQ (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  int stat;
+  stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+  /* For EQ return zero for true, nonzero for false.  */
+  return stat != 0;
+}
+#endif /* L_eq */
+
+#if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
+CMPtype
+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.  */
+  return stat != 0;
+}
+#endif /* L_ne */
+
+#if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
+CMPtype
+DFP_LT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  int stat;
+  stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+  /* For LT return -1 (<0) for true, 1 for false.  */
+  return (stat == -1) ? -1 : 1;
+}
+#endif /* L_lt */
+
+#if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
+CMPtype
+DFP_GT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  int stat;
+  stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+  /* For GT return 1 (>0) for true, -1 for false.  */
+  return (stat == 1) ? 1 : -1;
+}
+#endif
+
+#if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
+CMPtype
+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.  */
+  return stat == 1;
+}
+#endif /* L_le */
+
+#if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
+CMPtype
+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.  */
+  return (stat != -1) ? 1 : -1;
+}
+#endif /* L_ge */
+
+#define BUFMAX 128
+
+#if defined (L_sd_to_dd) || defined (L_sd_to_td) || defined (L_dd_to_sd) \
+ || defined (L_dd_to_td) || defined (L_td_to_sd) || defined (L_td_to_dd)
+DFP_C_TYPE_TO
+DFP_TO_DFP (DFP_C_TYPE f_from)
+{
+  DFP_C_TYPE_TO f_to;
+  IEEE_TYPE s_from;
+  IEEE_TYPE_TO s_to;
+  decNumber d;
+  decContext context;
+
+  decContextDefault (&context, CONTEXT_INIT);
+  context.round = CONTEXT_ROUND;
+
+  HOST_TO_IEEE (f_from, &s_from);
+  TO_INTERNAL (&s_from, &d);
+  TO_ENCODED_TO (&s_to, &d, &context);
+  if (CONTEXT_TRAPS && (context.status & DEC_Inexact) != 0)
+    DFP_RAISE (DEC_Inexact);
+
+  IEEE_TO_HOST_TO (s_to, &f_to);
+  return f_to;
+}
+#endif
+
+#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si) \
+  || defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
+  || defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi) \
+  || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
+INT_TYPE
+DFP_TO_INT (DFP_C_TYPE x)
+{
+  /* decNumber's decimal* types have the same format as C's _Decimal*
+     types, but they have different calling conventions.  */
+
+  IEEE_TYPE s;
+  char buf[BUFMAX];
+  char *pos;
+  decNumber qval, n1, n2;
+  decContext context;
+
+  decContextDefault (&context, CONTEXT_INIT);
+  /* Need non-default rounding mode here.  */
+  context.round = DEC_ROUND_DOWN;
+
+  HOST_TO_IEEE (x, &s);
+  TO_INTERNAL (&s, &n1);
+  /* Rescale if the exponent is less than zero.  */
+  decNumberToIntegralValue (&n2, &n1, &context);
+  /* Get a value to use for the quanitize call.  */
+  decNumberFromString (&qval, (char *) "1.0", &context);
+  /* Force the exponent to zero.  */
+  decNumberQuantize (&n1, &n2, &qval, &context);
+  /* This is based on text in N1107 secton 5.1; it might turn out to be
+     undefined behavior instead.  */
+  if (context.status & DEC_Invalid_operation)
+    {
+#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si)
+      if (decNumberIsNegative(&n2))
+        return INT_MIN;
+      else
+        return INT_MAX;
+#elif defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di)
+      if (decNumberIsNegative(&n2))
+        /* Find a defined constant that will work here.  */
+        return (-9223372036854775807LL - 1LL);
+      else
+        /* Find a defined constant that will work here.  */
+        return 9223372036854775807LL;
+#elif defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi)
+      return UINT_MAX;
+#elif defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
+        /* Find a defined constant that will work here.  */
+      return 18446744073709551615ULL;
+#endif
+    }
+  /* Get a string, which at this point will not include an exponent.  */
+  decNumberToString (&n1, buf);
+  /* Ignore the fractional part.  */
+  pos = strchr (buf, '.');
+  if (pos)
+    *pos = 0;
+  /* Use a C library function to convert to the integral type.  */
+  return STR_TO_INT (buf, NULL, 10);
+}
+#endif
+
+#if defined (L_si_to_sd) || defined (L_si_to_dd) || defined (L_si_to_td) \
+  || defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
+  || defined (L_usi_to_sd) || defined (L_usi_to_dd) || defined (L_usi_to_td) \
+  || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
+DFP_C_TYPE
+INT_TO_DFP (INT_TYPE i)
+{
+  DFP_C_TYPE f;
+  IEEE_TYPE s;
+  char buf[BUFMAX];
+  decContext context;
+
+  decContextDefault (&context, CONTEXT_INIT);
+  context.round = CONTEXT_ROUND;
+
+  /* Use a C library function to get a floating point string.  */
+  sprintf (buf, INT_FMT ".0", CAST_FOR_FMT(i));
+  /* Convert from the floating point string to a decimal* type.  */
+  FROM_STRING (&s, buf, &context);
+  IEEE_TO_HOST (s, &f);
+  if (CONTEXT_TRAPS && (context.status & DEC_Inexact) != 0)
+    DFP_RAISE (DEC_Inexact);
+  return f;
+}
+#endif
+
+#if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
+ || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
+ || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
+     && LIBGCC2_HAS_XF_MODE)
+BFP_TYPE
+DFP_TO_BFP (DFP_C_TYPE f)
+{
+  IEEE_TYPE s;
+  char buf[BUFMAX];
+
+  HOST_TO_IEEE (f, &s);
+  /* Write the value to a string.  */
+  TO_STRING (&s, buf);
+  /* Read it as the binary floating point type and return that.  */
+  return STR_TO_BFP (buf, NULL);
+}
+#endif
+                                                                                
+#if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
+ || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
+ || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
+     && LIBGCC2_HAS_XF_MODE)
+DFP_C_TYPE
+BFP_TO_DFP (BFP_TYPE x)
+{
+  DFP_C_TYPE f;
+  IEEE_TYPE s;
+  char buf[BUFMAX];
+  decContext context;
+
+  decContextDefault (&context, CONTEXT_INIT);
+  context.round = CONTEXT_ROUND;
+
+  /* Use a C library function to write the floating point value to a string.  */
+#ifdef BFP_VIA_TYPE
+  /* FIXME: Is threre a better way to output an XFmode variable in C?  */
+  sprintf (buf, BFP_FMT, (BFP_VIA_TYPE) x);
+#else
+  sprintf (buf, BFP_FMT, x);
+#endif
+
+  /* Convert from the floating point string to a decimal* type.  */
+  FROM_STRING (&s, buf, &context);
+  IEEE_TO_HOST (s, &f);
+  if (CONTEXT_TRAPS && (context.status & DEC_Inexact) != 0)
+    DFP_RAISE (DEC_Inexact);
+  return f;
+}
+#endif
+
+#if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
+CMPtype
+DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+  decNumber arg1, arg2;
+  IEEE_TYPE a, b;
+
+  HOST_TO_IEEE (arg_a, &a);
+  HOST_TO_IEEE (arg_b, &b);
+  TO_INTERNAL (&a, &arg1);
+  TO_INTERNAL (&b, &arg2);
+  return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
+}
+#endif /* L_unord_sd || L_unord_dd || L_unord_td */
diff --git a/gcc/config/dfp-bit.h b/gcc/config/dfp-bit.h
new file mode 100644 (file)
index 0000000..5f3a04e
--- /dev/null
@@ -0,0 +1,511 @@
+/* Header file for dfp-bit.c.
+   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#ifndef _DFPBIT_H
+#define _DFPBIT_H
+
+#include "tconfig.h"
+#include "coretypes.h"
+#include "tm.h"
+
+#ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
+#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN
+#endif
+
+#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
+#endif
+
+#ifndef LIBGCC2_HAS_XF_MODE
+#define LIBGCC2_HAS_XF_MODE \
+  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
+#endif
+
+/* Depending on WIDTH, define a number of macros:
+
+   DFP_C_TYPE: type of the arguments to the libgcc functions;
+       (eg _Decimal32)
+
+   IEEE_TYPE: the corresponding (encoded) IEEE754R type;
+       (eg decimal32)
+   
+   TO_INTERNAL: the name of the decNumber function to convert an
+   encoded value into the decNumber internal representation;
+
+   TO_ENCODED: the name of the decNumber function to convert an
+   internally represented decNumber into the encoded
+   representation.
+
+   FROM_STRING: the name of the decNumber function to read an
+   encoded value from a string.
+
+   TO_STRING: the name of the decNumber function to write an
+   encoded value to a string.  */
+
+#if WIDTH == 32
+#define DFP_C_TYPE     _Decimal32
+#define IEEE_TYPE      decimal32
+#define HOST_TO_IEEE   __host_to_ieee_32
+#define IEEE_TO_HOST   __ieee_to_host_32
+#define TO_INTERNAL    __decimal32ToNumber
+#define TO_ENCODED     __decimal32FromNumber
+#define FROM_STRING    __decimal32FromString
+#define TO_STRING      __decimal32ToString
+#elif WIDTH == 64
+#define DFP_C_TYPE     _Decimal64
+#define IEEE_TYPE      decimal64
+#define HOST_TO_IEEE   __host_to_ieee_64
+#define IEEE_TO_HOST   __ieee_to_host_64
+#define TO_INTERNAL    __decimal64ToNumber
+#define TO_ENCODED     __decimal64FromNumber
+#define FROM_STRING    __decimal64FromString
+#define TO_STRING      __decimal64ToString
+#elif WIDTH == 128
+#define DFP_C_TYPE     _Decimal128
+#define IEEE_TYPE      decimal128
+#define HOST_TO_IEEE   __host_to_ieee_128
+#define IEEE_TO_HOST   __ieee_to_host_128
+#define TO_INTERNAL    __decimal128ToNumber
+#define TO_ENCODED     __decimal128FromNumber
+#define FROM_STRING    __decimal128FromString
+#define TO_STRING      __decimal128ToString
+#else
+#error invalid decimal float word width
+#endif
+
+/* We define __DEC_EVAL_METHOD__ to 2, saying that we evaluate all
+   operations and constants to the range and precision of the _Decimal128
+   type.  Make it so.  */
+#if WIDTH == 32
+#define CONTEXT_INIT DEC_INIT_DECIMAL32
+#elif WIDTH == 64
+#define CONTEXT_INIT DEC_INIT_DECIMAL64
+#elif WIDTH == 128
+#define CONTEXT_INIT DEC_INIT_DECIMAL128
+#endif
+
+/* Define CONTEXT_ROUND to obtain the current decNumber rounding mode.  */
+extern enum rounding   __decGetRound (void);
+#define CONTEXT_ROUND  __decGetRound ()
+
+extern int __dfp_traps;
+#define CONTEXT_TRAPS  __dfp_traps
+#define CONTEXT_ERRORS(context)        context.status & DEC_Errors
+extern void __dfp_raise (int);
+#define DFP_RAISE(A)   __dfp_raise(A)
+
+/* Conversions between different decimal float types use WIDTH_TO to
+   determine additional macros to define.  */
+
+#if defined (L_dd_to_sd) || defined (L_td_to_sd)
+#define WIDTH_TO 32
+#elif defined (L_sd_to_dd) || defined (L_td_to_dd)
+#define WIDTH_TO 64
+#elif defined (L_sd_to_td) || defined (L_dd_to_td)
+#define WIDTH_TO 128
+#endif
+
+/* If WIDTH_TO is defined, define additional macros:
+
+   DFP_C_TYPE_TO: type of the result of dfp to dfp conversion.
+
+   IEEE_TYPE_TO: the corresponding (encoded) IEEE754R type.
+
+   TO_ENCODED_TO: the name of the decNumber function to convert an
+   internally represented decNumber into the encoded representation
+   for the destination.  */
+
+#if WIDTH_TO == 32
+#define DFP_C_TYPE_TO  _Decimal32
+#define IEEE_TYPE_TO   decimal32
+#define TO_ENCODED_TO  __decimal32FromNumber
+#define IEEE_TO_HOST_TO __ieee_to_host_32
+#elif WIDTH_TO == 64
+#define DFP_C_TYPE_TO  _Decimal64
+#define IEEE_TYPE_TO   decimal64
+#define TO_ENCODED_TO  __decimal64FromNumber
+#define IEEE_TO_HOST_TO __ieee_to_host_64
+#elif WIDTH_TO == 128
+#define DFP_C_TYPE_TO  _Decimal128
+#define IEEE_TYPE_TO   decimal128
+#define TO_ENCODED_TO  __decimal128FromNumber
+#define IEEE_TO_HOST_TO __ieee_to_host_128
+#endif
+
+/* Conversions between decimal float types and integral types use INT_KIND
+   to determine the data type and C functions to use.  */
+
+#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si)  \
+   || defined (L_si_to_sd) || defined (L_si_to_dd) || defined (L_si_to_td)
+#define INT_KIND 1
+#elif defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
+   || defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td)
+#define INT_KIND 2
+#elif defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi) \
+   || defined (L_usi_to_sd) || defined (L_usi_to_dd) || defined (L_usi_to_td)
+#define INT_KIND 3
+#elif defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi) \
+   || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
+#define INT_KIND 4
+#endif
+
+/*  If INT_KIND is defined, define additional macros:
+
+    INT_TYPE: The integer data type.
+
+    INT_FMT: The format string for writing the integer to a string.
+
+    CAST_FOR_FMT: Cast variable of INT_KIND to C type for sprintf.
+    This works for ILP32 and LP64, won't for other type size systems.
+
+    STR_TO_INT: The function to read the integer from a string.  */
+
+#if INT_KIND == 1
+#define INT_TYPE SItype
+#define INT_FMT "%d"
+#define CAST_FOR_FMT(A) (int)A
+#define STR_TO_INT strtol
+#elif INT_KIND == 2
+#define INT_TYPE DItype
+#define INT_FMT "%lld"
+#define CAST_FOR_FMT(A) (long long)A
+#define STR_TO_INT strtoll
+#elif INT_KIND == 3
+#define INT_TYPE USItype
+#define INT_FMT "%u"
+#define CAST_FOR_FMT(A) (unsigned int)A
+#define STR_TO_INT strtoul
+#elif INT_KIND == 4
+#define INT_TYPE UDItype
+#define INT_FMT "%llu"
+#define CAST_FOR_FMT(A) (unsigned long long)A
+#define STR_TO_INT strtoull
+#endif
+
+/* Conversions between decimal float types and binary float types use
+   BFP_KIND to determine the data type and C functions to use.  */
+
+#if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
+ || defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td)
+#define BFP_KIND 1
+#elif defined (L_sd_to_df) || defined (L_dd_to_df ) || defined (L_td_to_df) \
+ ||   defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td)
+#define BFP_KIND 2
+#elif defined (L_sd_to_xf) || defined (L_dd_to_xf ) || defined (L_td_to_xf) \
+ ||   defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)
+#define BFP_KIND 3
+#endif
+
+/*  If BFP_KIND is defined, define additional macros:
+
+    BFP_TYPE: The binary floating point data type.
+
+    BFP_FMT: The format string for writing the value to a string.
+
+    STR_TO_BFP: The function to read the value from a string.  */
+
+#if BFP_KIND == 1
+/* strtof is declared in <stdlib.h> only for C99.  */
+extern float strtof (const char *, char **);
+#define BFP_TYPE SFtype
+#define BFP_FMT "%e"
+#define STR_TO_BFP strtof
+
+#elif BFP_KIND == 2
+#define BFP_TYPE DFtype
+#define BFP_FMT "%e"
+#define STR_TO_BFP strtod
+
+#elif BFP_KIND == 3
+#if LIBGCC2_HAS_XF_MODE
+/* These aren't used if XF mode is not supported.  */
+#define BFP_TYPE XFtype
+#define BFP_FMT "%e"
+#define BFP_VIA_TYPE double
+#define STR_TO_BFP strtod
+#endif
+
+#endif /* BFP_KIND */
+
+#if WIDTH == 128 || WIDTH_TO == 128
+#include "decimal128.h"
+#endif
+#if WIDTH == 64 || WIDTH_TO == 64
+#include "decimal64.h"
+#endif
+#if WIDTH == 32 || WIDTH_TO == 32
+#include "decimal32.h"
+#endif
+#include "decNumber.h"
+
+/* Names of arithmetic functions.  */
+
+#if WIDTH == 32
+#define DFP_ADD                __addsd3
+#define DFP_SUB                __subsd3
+#define DFP_MULTIPLY   __mulsd3
+#define DFP_DIVIDE     __divsd3
+#define DFP_EQ         __eqsd2
+#define DFP_NE         __nesd2
+#define DFP_LT         __ltsd2
+#define DFP_GT         __gtsd2
+#define DFP_LE         __lesd2
+#define DFP_GE         __gesd2
+#define DFP_UNORD      __unordsd2
+#elif WIDTH == 64
+#define DFP_ADD                __adddd3
+#define DFP_SUB                __subdd3
+#define DFP_MULTIPLY   __muldd3
+#define DFP_DIVIDE     __divdd3
+#define DFP_EQ         __eqdd2
+#define DFP_NE         __nedd2
+#define DFP_LT         __ltdd2
+#define DFP_GT         __gtdd2
+#define DFP_LE         __ledd2
+#define DFP_GE         __gedd2
+#define DFP_UNORD      __unorddd2
+#elif WIDTH == 128
+#define DFP_ADD                __addtd3
+#define DFP_SUB                __subtd3
+#define DFP_MULTIPLY   __multd3
+#define DFP_DIVIDE     __divtd3
+#define DFP_EQ         __eqtd2
+#define DFP_NE         __netd2
+#define DFP_LT         __lttd2
+#define DFP_GT         __gttd2
+#define DFP_LE         __letd2
+#define DFP_GE         __getd2
+#define DFP_UNORD      __unordtd2
+#endif
+
+/* Names of functions to convert between different decimal float types.  */
+
+#if WIDTH == 32
+#if WIDTH_TO == 64
+#define DFP_TO_DFP     __extendsddd2
+#elif WIDTH_TO == 128
+#define DFP_TO_DFP     __extendsdtd2
+#endif
+#elif WIDTH == 64      
+#if WIDTH_TO == 32
+#define DFP_TO_DFP     __truncddsd2
+#elif WIDTH_TO == 128
+#define DFP_TO_DFP     __extendddtd2
+#endif
+#elif WIDTH == 128
+#if WIDTH_TO == 32
+#define DFP_TO_DFP     __trunctdsd2
+#elif WIDTH_TO == 64
+#define DFP_TO_DFP     __trunctddd2
+#endif
+#endif
+
+/* Names of functions to convert between decimal float and integers.  */
+
+#if WIDTH == 32
+#if INT_KIND == 1
+#define INT_TO_DFP     __floatsisd
+#define DFP_TO_INT     __fixsdsi
+#elif INT_KIND == 2
+#define INT_TO_DFP     __floatdisd
+#define DFP_TO_INT     __fixsddi
+#elif INT_KIND == 3
+#define INT_TO_DFP     __floatunssisd
+#define DFP_TO_INT     __fixunssdsi
+#elif INT_KIND == 4
+#define INT_TO_DFP     __floatunsdisd
+#define DFP_TO_INT     __fixunssddi
+#endif
+#elif WIDTH == 64
+#if INT_KIND == 1
+#define INT_TO_DFP     __floatsidd
+#define DFP_TO_INT     __fixddsi
+#elif INT_KIND == 2
+#define INT_TO_DFP     __floatdidd
+#define DFP_TO_INT     __fixdddi
+#elif INT_KIND == 3
+#define INT_TO_DFP     __floatunssidd
+#define DFP_TO_INT     __fixunsddsi
+#elif INT_KIND == 4
+#define INT_TO_DFP     __floatunsdidd
+#define DFP_TO_INT     __fixunsdddi
+#endif
+#elif WIDTH == 128
+#if INT_KIND == 1
+#define INT_TO_DFP     __floatsitd
+#define DFP_TO_INT     __fixtdsi
+#elif INT_KIND == 2
+#define INT_TO_DFP     __floatditd
+#define DFP_TO_INT     __fixtddi
+#elif INT_KIND == 3
+#define INT_TO_DFP     __floatunssitd
+#define DFP_TO_INT     __fixunstdsi
+#elif INT_KIND == 4
+#define INT_TO_DFP     __floatunsditd
+#define DFP_TO_INT     __fixunstddi
+#endif
+#endif
+
+/* Names of functions to convert between decimal float and binary float.  */
+
+#if WIDTH == 32
+#if BFP_KIND == 1
+#define BFP_TO_DFP     __extendsfsd
+#define DFP_TO_BFP     __truncsdsf
+#elif BFP_KIND == 2
+#define BFP_TO_DFP     __truncdfsd
+#define DFP_TO_BFP     __extendsddf
+#elif BFP_KIND == 3
+#define BFP_TO_DFP     __truncxfsd
+#define DFP_TO_BFP     __extendsdxf
+#endif /* BFP_KIND */
+
+#elif WIDTH == 64
+#if BFP_KIND == 1
+#define BFP_TO_DFP     __extendsfdd
+#define DFP_TO_BFP     __truncddsf
+#elif BFP_KIND == 2
+#define BFP_TO_DFP     __extenddfdd
+#define DFP_TO_BFP     __truncdddf
+#elif BFP_KIND == 3
+#define BFP_TO_DFP     __truncxfdd
+#define DFP_TO_BFP     __extendddxf
+#endif /* BFP_KIND */
+
+#elif WIDTH == 128
+#if BFP_KIND == 1
+#define BFP_TO_DFP     __extendsftd
+#define DFP_TO_BFP     __trunctdsf
+#elif BFP_KIND == 2
+#define BFP_TO_DFP     __extenddftd
+#define DFP_TO_BFP     __trunctddf
+#elif BFP_KIND == 3
+#define BFP_TO_DFP     __extendxftd
+#define DFP_TO_BFP     __trunctdxf
+#endif /* BFP_KIND */
+
+#endif /* WIDTH */
+
+/* Some handy typedefs.  */
+
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef float DFtype __attribute__ ((mode (DF)));
+#if LIBGCC2_HAS_XF_MODE
+typedef float XFtype __attribute__ ((mode (XF)));
+#endif /* LIBGCC2_HAS_XF_MODE */
+
+typedef int SItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+
+/* The type of the result of a decimal float comparison.  This must
+   match `word_mode' in GCC for the target.  Default to SItype.  */
+
+#ifndef CMPtype
+#define CMPtype SItype
+#endif
+
+/* Prototypes.  */
+
+#if defined (L_mul_sd) || defined (L_mul_dd) || defined (L_mul_td)
+extern DFP_C_TYPE DFP_MULTIPLY (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_div_sd) || defined (L_div_dd) || defined (L_div_td)
+extern DFP_C_TYPE DFP_DIVIDE (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_addsub_sd) || defined (L_addsub_dd) || defined (L_addsub_td)
+extern DFP_C_TYPE DFP_ADD (DFP_C_TYPE, DFP_C_TYPE);
+extern DFP_C_TYPE DFP_SUB (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
+extern CMPtype DFP_EQ (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
+extern CMPtype DFP_NE (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
+extern CMPtype DFP_LT (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
+extern CMPtype DFP_GT (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
+extern CMPtype DFP_LE (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
+extern CMPtype DFP_GE (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
+extern CMPtype DFP_UNORD (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_sd_to_dd) || defined (L_sd_to_td) || defined (L_dd_to_sd) \
+ || defined (L_dd_to_td) || defined (L_td_to_sd) || defined (L_td_to_dd)
+extern DFP_C_TYPE_TO DFP_TO_DFP (DFP_C_TYPE);
+#endif
+
+#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si) \
+ || defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
+ || defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi) \
+ || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
+extern INT_TYPE DFP_TO_INT (DFP_C_TYPE);
+#endif
+
+#if defined (L_si_to_sd) || defined (L_si_to_dd) || defined (L_si_to_td) \
+ || defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
+ || defined (L_usi_to_sd) || defined (L_usi_to_dd) || defined (L_usi_to_td) \
+ || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
+extern DFP_C_TYPE INT_TO_DFP (INT_TYPE);
+#endif
+
+#if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
+ || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
+ || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
+     && LIBGCC2_HAS_XF_MODE)
+extern BFP_TYPE DFP_TO_BFP (DFP_C_TYPE);
+#endif
+
+#if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
+ || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
+ || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
+     && LIBGCC2_HAS_XF_MODE)
+extern DFP_C_TYPE BFP_TO_DFP (BFP_TYPE);
+#endif
+
+#endif /* _DFPBIT_H */
index c97bd8b..f67b117 100644 (file)
@@ -39,6 +39,7 @@ and @code{@w{unsigned int}} correspond to @code{SImode}; @code{long} and
 @menu
 * Integer library routines::
 * Soft float library routines::
+* Decimal float library routines::
 * Exception handling routines::
 * Miscellaneous routines::
 @end menu
@@ -485,6 +486,205 @@ These functions return the quotient of @math{@var{a} + i@var{b}} and
 + i@var{d})}), following the rules of C99 Annex G@.
 @end deftypefn
 
+@node Decimal float library routines
+@section Routines for decimal floating point emulation
+@cindex decimal float library
+@cindex IEEE-754R
+
+The software decimal floating point library implements IEEE 754R
+decimal floating point arithmetic and is only activated on selected
+targets.
+
+@subsection Arithmetic functions
+
+@deftypefn {Runtime Function} _Decimal32 __addsd3 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} _Decimal64 __adddd3 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} _Decimal128 __addtd3 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return the sum of @var{a} and @var{b}.
+@end deftypefn
+
+@deftypefn {Runtime Function} _Decimal32 __subsd3 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} _Decimal64 __subdd3 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} _Decimal128 __subtd3 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return the difference between @var{b} and @var{a};
+that is, @w{@math{@var{a} - @var{b}}}.
+@end deftypefn
+
+@deftypefn {Runtime Function} _Decimal32 __mulsd3 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} _Decimal64 __muldd3 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} _Decimal128 __multd3 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return the product of @var{a} and @var{b}.
+@end deftypefn
+
+@deftypefn {Runtime Function} _Decimal32 __divsd3 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} _Decimal64 __divdd3 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} _Decimal128 __divtd3 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return the quotient of @var{a} and @var{b}; that is,
+@w{@math{@var{a} / @var{b}}}.
+@end deftypefn
+
+@deftypefn {Runtime Function} _Decimal32 __negsd2 (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} _Decimal64 __negdd2 (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} _Decimal128 __negtd2 (_Decimal128 @var{a})
+These functions return the negation of @var{a}.  They simply flip the
+sign bit, so they can produce negative zero and negative NaN@.
+@end deftypefn
+
+@subsection Conversion functions
+
+@c DFP/DFP conversions
+@deftypefn {Runtime Function} _Decimal64 __extendsddd2 (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} _Decimal128 __extendsdtd2 (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} _Decimal128 __extendddtd2 (_Decimal64 @var{a})
+@c DFP/binary FP conversions
+@deftypefnx {Runtime Function} _Decimal32 __extendsfsd (float @var{a})
+@deftypefnx {Runtime Function} double __extendsddf (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} {long double} __extendsdxf (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} _Decimal64 __extendsfdd (float @var{a})
+@deftypefnx {Runtime Function} _Decimal64 __extenddfdd (double @var{a})
+@deftypefnx {Runtime Function} {long double} __extendddxf (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} _Decimal128 __extendsftd (float @var{a})
+@deftypefnx {Runtime Function} _Decimal128 __extenddftd (double @var{a})
+@deftypefnx {Runtime Function} _Decimal128 __extendxftd ({long double} @var{a})
+These functions extend @var{a} to the wider mode of their return type.
+@end deftypefn
+
+@c DFP/DFP conversions
+@deftypefn {Runtime Function} _Decimal32 __truncddsd2 (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} _Decimal32 __trunctdsd2 (_Decimal128 @var{a})
+@deftypefnx {Runtime Function} _Decimal64 __trunctddd2 (_Decimal128 @var{a})
+@c DFP/binary FP conversions
+@deftypefnx {Runtime Function} float __truncsdsf (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} _Decimal32 __truncdfsd (double @var{a})
+@deftypefnx {Runtime Function} _Decimal32 __truncxfsd ({long double} @var{a})
+@deftypefnx {Runtime Function} float __truncddsf (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} double __truncdddf (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} _Decimal64 __truncxfdd ({long double} @var{a})
+@deftypefnx {Runtime Function} float __trunctdsf (_Decimal128 @var{a})
+@deftypefnx {Runtime Function} double __trunctddf (_Decimal128 @var{a})
+@deftypefnx {Runtime Function} {long double} __trunctdxf (_Decimal128 @var{a})
+These functions truncate @var{a} to the narrower mode of their return
+type.
+@end deftypefn
+
+@deftypefn {Runtime Function} int __fixsdsi (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} int __fixddsi (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} int __fixtdsi (_Decimal128 @var{a})
+These functions convert @var{a} to a signed integer.
+@end deftypefn
+
+@deftypefn {Runtime Function} long __fixsddi (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} long __fixdddi (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} long __fixtddi (_Decimal128 @var{a})
+These functions convert @var{a} to a signed long.
+@end deftypefn
+
+@deftypefn {Runtime Function} {unsigned int} __fixunssdsi (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} {unsigned int} __fixunsddsi (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} {unsigned int} __fixunstdsi (_Decimal128 @var{a})
+These functions convert @var{a} to an unsigned integer.  Negative values all become zero.
+@end deftypefn
+
+@deftypefn {Runtime Function} {unsigned long} __fixunssddi (_Decimal32 @var{a})
+@deftypefnx {Runtime Function} {unsigned long} __fixunsdddi (_Decimal64 @var{a})
+@deftypefnx {Runtime Function} {unsigned long} __fixunstddi (_Decimal128 @var{a})
+These functions convert @var{a} to an unsigned long.  Negative values
+all become zero.
+@end deftypefn
+
+@deftypefn {Runtime Function} _Decimal32 __floatsisd (int @var{i})
+@deftypefnx {Runtime Function} _Decimal64 __floatsidd (int @var{i})
+@deftypefnx {Runtime Function} _Decimal128 __floatsitd (int @var{i})
+These functions convert @var{i}, a signed integer, to decimal floating point.
+@end deftypefn
+
+@deftypefn {Runtime Function} _Decimal32 __floatdisd (long @var{i})
+@deftypefnx {Runtime Function} _Decimal64 __floatdidd (long @var{i})
+@deftypefnx {Runtime Function} _Decimal128 __floatditd (long @var{i})
+These functions convert @var{i}, a signed long, to decimal floating point.
+@end deftypefn
+
+@deftypefn {Runtime Function} _Decimal32 __floatunssisd (unsigned int @var{i})
+@deftypefnx {Runtime Function} _Decimal64 __floatunssidd (unsigned int @var{i})
+@deftypefnx {Runtime Function} _Decimal128 __floatunssitd (unsigned int @var{i})
+These functions convert @var{i}, an unsigned integer, to decimal floating point.
+@end deftypefn
+
+@deftypefn {Runtime Function} _Decimal32 __floatunsdisd (unsigned long @var{i})
+@deftypefnx {Runtime Function} _Decimal64 __floatunsdidd (unsigned long @var{i})
+@deftypefnx {Runtime Function} _Decimal128 __floatunsditd (unsigned long @var{i})
+These functions convert @var{i}, an unsigned long, to decimal floating point.
+@end deftypefn
+
+@subsection Comparison functions
+
+@deftypefn {Runtime Function} int __unordsd2 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} int __unorddd2 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} int __unordtd2 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return a nonzero value if either argument is NaN, otherwise 0.
+@end deftypefn
+
+There is also a complete group of higher level functions which
+correspond directly to comparison operators.  They implement the ISO C
+semantics for floating-point comparisons, taking NaN into account.
+Pay careful attention to the return values defined for each set.
+Under the hood, all of these routines are implemented as
+
+@smallexample
+  if (__unord@var{X}d2 (a, b))
+    return @var{E};
+  return __cmp@var{X}d2 (a, b);
+@end smallexample
+
+@noindent
+where @var{E} is a constant chosen to give the proper behavior for
+NaN@.  Thus, the meaning of the return value is different for each set.
+Do not rely on this implementation; only the semantics documented
+below are guaranteed.
+
+@deftypefn {Runtime Function} int __eqsd2 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} int __eqdd2 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} int __eqtd2 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return zero if neither argument is NaN, and @var{a} and
+@var{b} are equal.
+@end deftypefn
+
+@deftypefn {Runtime Function} int __nesd2 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} int __nedd2 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} int __netd2 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return a nonzero value if either argument is NaN, or
+if @var{a} and @var{b} are unequal.
+@end deftypefn
+
+@deftypefn {Runtime Function} int __gesd2 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} int __gedd2 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} int __getd2 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return a value greater than or equal to zero if
+neither argument is NaN, and @var{a} is greater than or equal to
+@var{b}.
+@end deftypefn
+
+@deftypefn {Runtime Function} int __ltsd2 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} int __ltdd2 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} int __lttd2 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return a value less than zero if neither argument is
+NaN, and @var{a} is strictly less than @var{b}.
+@end deftypefn
+
+@deftypefn {Runtime Function} int __lesd2 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} int __ledd2 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} int __letd2 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return a value less than or equal to zero if neither
+argument is NaN, and @var{a} is less than or equal to @var{b}.
+@end deftypefn
+
+@deftypefn {Runtime Function} int __gtsd2 (_Decimal32 @var{a}, _Decimal32 @var{b})
+@deftypefnx {Runtime Function} int __gtdd2 (_Decimal64 @var{a}, _Decimal64 @var{b})
+@deftypefnx {Runtime Function} int __gttd2 (_Decimal128 @var{a}, _Decimal128 @var{b})
+These functions return a value greater than zero if neither argument
+is NaN, and @var{a} is strictly greater than @var{b}.
+@end deftypefn
+
 @node Exception handling routines
 @section Language-independent routines for exception handling
 
index ba85363..2162c05 100644 (file)
 # DPBIT_FUNCS
 # TPBIT
 # TPBIT_FUNCS
+# D32PBIT
+# D32PBIT_FUNCS
+# D64PBIT
+# D64PBIT_FUNCS
+# D128PBIT
+# D128PBIT_FUNCS
 # LIBGCC
 # MULTILIBS
 # EXTRA_MULTILIB_PARTS
@@ -96,6 +102,12 @@ libgcov_c_dep='stmp-dirs $(srcdir)/libgcov.c $(srcdir)/gcov-io.h $(srcdir)/gcov-
 # Dependencies for fp-bit.c
 fpbit_c_dep='stmp-dirs config.status tsystem.h'
 
+# Dependencies for decnumber and friends.  This is an overzealous set,
+# but at least we can be sure to recompile if anything gets modified.
+decnumber_dep='stmp-dirs $(srcdir)/../libdecnumber/decContext.h $(srcdir)/../libdecnumber/decNumber.h
+       $(srcdir)/../libdecnumber/decNumberLocal.h $(srcdir)/../libdecnumber/decimal32.h $(srcdir)/../libdecnumber/decimal64.h
+       $(srcdir)/../libdecnumber/decimal128.h $(srcdir)/../libdecnumber/decDPD.h $(srcdir)/../libdecnumber/decUtility.h'
+
 # Flag whether we need eh_dummy.c
 need_eh_dummy=
 
@@ -349,6 +361,49 @@ for ml in $MULTILIBS; do
       fi
   done
 
+  if [ "@enable_decimal_float@" = "yes" -a -z "$libgcc_so" ]; then
+    # Bring in the DFP support code if D32PBIT, D64PBIT or D128PBIT are set.
+    if [ -n "$D32PBIT" -o -n "$D64PBIT" -o -n "$D128PBIT" ] ; then
+      dec_filenames="decContext decNumber decRound decLibrary decUtility"
+    fi
+
+    # Only bring in decimal*.c files for types we support.
+    if [ -n "$D32PBIT" ] ; then
+      dec_filenames="$dec_filenames decimal32"
+    fi
+    if [ -n "$D64PBIT" ] ; then
+      dec_filenames="$dec_filenames decimal64"
+    fi
+    if [ -n "$D128PBIT" ] ; then
+      dec_filenames="$dec_filenames decimal128"
+    fi
+
+    for name in $dec_filenames ; do
+      out="libgcc/${dir}/${name}${objext}"
+      echo $out: "\$(srcdir)/../libdecnumber/${name}.c" $decnumber_dep
+      echo "   $gcc_compile" $flags -c "\$(srcdir)/../libdecnumber/${name}.c" -o $out
+      echo $libgcc_a: $out
+    done
+
+    # For individual functions, loop over each variable by name.
+    for dpbit_var in D32PBIT D64PBIT D128PBIT ; do
+      dpfuncs_var="${dpbit_var}_FUNCS"
+      eval dpbit=\$$dpbit_var
+      eval dpfuncs=\$$dpfuncs_var
+
+      if [ "$dpbit" ]; then
+        for name in $dpfuncs; do
+          out="libgcc/${dir}/${name}${objext}"
+         echo $out: $dpbit $fpbit_c_dep
+         echo "        $gcc_compile" -DFINE_GRAINED_LIBRARIES $flags -DL$name \
+           -c $dpbit -o $out
+
+         echo $libgcc_a: $out
+        done
+      fi
+    done
+  fi
+
   for file in $LIB2ADD; do
     name=`echo $file | sed -e 's/[.][cS]$//' -e 's/[.]asm$//'`
     oname=`echo $name | sed -e 's,.*/,,'`