aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/Makefile.in30
-rw-r--r--gcc/config/dfp-bit.c541
-rw-r--r--gcc/config/dfp-bit.h511
-rw-r--r--gcc/doc/libgcc.texi200
-rw-r--r--gcc/mklibgcc.in55
6 files changed, 1350 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2ac7d8b..a096147 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index e791858..a993f97 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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
index 0000000..835586b
--- /dev/null
+++ b/gcc/config/dfp-bit.c
@@ -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);
+
+/* 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;
+}
+
+
+#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
index 0000000..5f3a04e
--- /dev/null
+++ b/gcc/config/dfp-bit.h
@@ -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 */
diff --git a/gcc/doc/libgcc.texi b/gcc/doc/libgcc.texi
index c97bd8b..f67b117 100644
--- a/gcc/doc/libgcc.texi
+++ b/gcc/doc/libgcc.texi
@@ -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
diff --git a/gcc/mklibgcc.in b/gcc/mklibgcc.in
index ba85363..2162c05 100644
--- a/gcc/mklibgcc.in
+++ b/gcc/mklibgcc.in
@@ -28,6 +28,12 @@
# 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,.*/,,'`