Add conversions between _Float128 and Decimal.
authorMichael Meissner <meissner@linux.ibm.com>
Mon, 22 Feb 2021 20:33:29 +0000 (15:33 -0500)
committerMichael Meissner <meissner@linux.ibm.com>
Mon, 22 Feb 2021 20:33:29 +0000 (15:33 -0500)
This patch implements conversions between _Float128 and the 3 Decimal floating
types.  It does this by extendending the dfp-bit conversions to add a new
binary floating point type (KF), and doing the conversions in the same manner
as the other binary/decimal conversions.

For conversions from _Float128 to Decimal, this patch uses a function
(__sprintfkf) instead of the sprintf function to convert long double values to
strings.  The __sprintfkf function determines if GLIBC 2.32 or newer is used
and calls the IEEE 128-bit version of sprintf (__sprintfieee128).  If the GLIBC
is earlier than 2.32, the code will convert _Float128 to __ibm128 and then use
the normal sprintf to convert this value.

For conversions from Decimal to _Float128, this patch uses a function
(__strtokf) instead of strtold to convert the strings from the Decimal
conversion to long double.  The __strtokf function determines if GLIBC 2.32 or
newer is used, and if it is, calls the IEEE 128-bit version (__strtoieee128).
If the GLIBC is earlier than 2.32, the code will call strtold and convert the
__ibm128 value to _Float128.

These functions will primarily be used if/when the default PowerPC long double
type is changed to IEEE 128-bit, but they could also be used if the user
explicitly converts _Float128 to/from a Decimal type.

libgcc/
2021-02-22  Michael Meissner  <meissner@linux.ibm.com>

* config/rs6000/_dd_to_kf.c: New file.
* config/rs6000/_kf_to_dd.c: New file.
* config/rs6000/_kf_to_sd.c: New file.
* config/rs6000/_kf_to_td.c: New file.
* config/rs6000/_sd_to_kf.c: New file.
* config/rs6000/_sprintfkf.c: New file.
* config/rs6000/_sprintfkf.h: New file.
* config/rs6000/_strtokf.h: New file.
* config/rs6000/_strtokf.c: New file.
* config/rs6000/_td_to_kf.c: New file.
* config/rs6000/quad-float128.h: Add new declarations.
* config/rs6000/t-float128 (fp128_dec_funcs): New macro.
(fp128_decstr_funcs): New macro.
(ibm128_dec_funcs): New macro.
(fp128_ppc_funcs): Add the new conversions.
(fp128_dec_objs): Force Decimal <-> __float128 conversions to be
compiled with -mabi=ieeelongdouble.
(fp128_decstr_objs): Force __float128 <-> string conversions to be
compiled with -mabi=ibmlongdouble.
(ibm128_dec_objs): Force Decimal <-> __float128 conversions to be
compiled with -mabi=ieeelongdouble.
(FP128_CFLAGS_DECIMAL): New macro.
(IBM128_CFLAGS_DECIMAL): New macro.
* dfp-bit.c (DFP_TO_BFP): Add PowerPC _Float128 support.
(BFP_TO_DFP): Add PowerPC _Float128 support.
* dfp-bit.h (BFP_KIND): Add new binary floating point kind for
IEEE 128-bit floating point.
(DFP_TO_BFP): Add PowerPC _Float128 support.
(BFP_TO_DFP): Add PowerPC _Float128 support.
(BFP_SPRINTF): New macro.

14 files changed:
libgcc/config/rs6000/_dd_to_kf.c [new file with mode: 0644]
libgcc/config/rs6000/_kf_to_dd.c [new file with mode: 0644]
libgcc/config/rs6000/_kf_to_sd.c [new file with mode: 0644]
libgcc/config/rs6000/_kf_to_td.c [new file with mode: 0644]
libgcc/config/rs6000/_sd_to_kf.c [new file with mode: 0644]
libgcc/config/rs6000/_sprintfkf.c [new file with mode: 0644]
libgcc/config/rs6000/_sprintfkf.h [new file with mode: 0644]
libgcc/config/rs6000/_strtokf.c [new file with mode: 0644]
libgcc/config/rs6000/_strtokf.h [new file with mode: 0644]
libgcc/config/rs6000/_td_to_kf.c [new file with mode: 0644]
libgcc/config/rs6000/quad-float128.h
libgcc/config/rs6000/t-float128
libgcc/dfp-bit.c
libgcc/dfp-bit.h

diff --git a/libgcc/config/rs6000/_dd_to_kf.c b/libgcc/config/rs6000/_dd_to_kf.c
new file mode 100644 (file)
index 0000000..6613c44
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright (C) 2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Decimal64 -> _Float128 conversion.  */
+
+/* FINE_GRAINED_LIBRARIES is used so we can isolate just to dd_to_tf conversion
+   function from dp-bits.c.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_dd_to_kf             1
+#define WIDTH                  64
+
+#if !defined(__LONG_DOUBLE_128__) || !defined(__LONG_DOUBLE_IEEE128__)
+#error "Long double is not IEEE 128-bit"
+#endif
+
+/* Use dfp-bit.c to do the real work.  */
+#include "dfp-bit.c"
diff --git a/libgcc/config/rs6000/_kf_to_dd.c b/libgcc/config/rs6000/_kf_to_dd.c
new file mode 100644 (file)
index 0000000..93a1043
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright (C) 2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* _Float128 -> Decimal64 conversion.  */
+
+/* FINE_GRAINED_LIBRARIES is used so we can isolate just to tf_to_dd conversion
+   function from dp-bits.c.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_kf_to_dd             1
+#define WIDTH                  64
+
+#if !defined(__LONG_DOUBLE_128__) || !defined(__LONG_DOUBLE_IEEE128__)
+#error "Long double is not IEEE 128-bit"
+#endif
+
+/* Use dfp-bit.c to do the real work.  */
+#include "dfp-bit.c"
diff --git a/libgcc/config/rs6000/_kf_to_sd.c b/libgcc/config/rs6000/_kf_to_sd.c
new file mode 100644 (file)
index 0000000..01396da
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright (C) 2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* _Float128 -> Decimal32 conversion.  */
+
+/* FINE_GRAINED_LIBRARIES is used so we can isolate just to tf_to_sd conversion
+   function from dp-bits.c.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_kf_to_sd             1
+#define WIDTH                  32
+
+#if !defined(__LONG_DOUBLE_128__) || !defined(__LONG_DOUBLE_IEEE128__)
+#error "Long double is not IEEE 128-bit"
+#endif
+
+/* Use dfp-bit.c to do the real work.  */
+#include "dfp-bit.c"
diff --git a/libgcc/config/rs6000/_kf_to_td.c b/libgcc/config/rs6000/_kf_to_td.c
new file mode 100644 (file)
index 0000000..45bba92
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright (C) 2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* _Float128 -> Decimal128 conversion.  */
+
+/* FINE_GRAINED_LIBRARIES is used so we can isolate just to tf_to_td conversion
+   function from dp-bits.c.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_kf_to_td             1
+#define WIDTH                  128
+
+#if !defined(__LONG_DOUBLE_128__) || !defined(__LONG_DOUBLE_IEEE128__)
+#error "Long double is not IEEE 128-bit"
+#endif
+
+/* Use dfp-bit.c to do the real work.  */
+#include "dfp-bit.c"
diff --git a/libgcc/config/rs6000/_sd_to_kf.c b/libgcc/config/rs6000/_sd_to_kf.c
new file mode 100644 (file)
index 0000000..9224444
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright (C) 2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Decimal32 -> _Float128 conversion.  */
+
+/* FINE_GRAINED_LIBRARIES is used so we can isolate just to sd_to_tf conversion
+   function from dp-bits.c.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_sd_to_kf             1
+#define WIDTH                  32
+
+#if !defined(__LONG_DOUBLE_128__) || !defined(__LONG_DOUBLE_IEEE128__)
+#error "Long double is not IEEE 128-bit"
+#endif
+
+/* Use dfp-bit.c to do the real work.  */
+#include "dfp-bit.c"
diff --git a/libgcc/config/rs6000/_sprintfkf.c b/libgcc/config/rs6000/_sprintfkf.c
new file mode 100644 (file)
index 0000000..a7fdfb4
--- /dev/null
@@ -0,0 +1,57 @@
+/* Copyright (C) 1989-2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Conversion to IEEE 128-bit floating point from string using snprintf.  */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <soft-fp.h>
+#include <quad-float128.h>
+#include <stdio.h>
+
+/* This function must be built with IBM 128-bit as long double, so that we can
+   access the strfroml function if do not have an IEEE 128-bit version, and if
+   that is not available, use sprintf.  */
+#if !defined(__LONG_DOUBLE_128__) || !defined(__LONG_DOUBLE_IBM128__)
+#error "Long double is not IBM 128-bit"
+#endif
+
+/* If the user is using GLIBC 2.32, we can use the __snprintfieee128 function.
+
+   If we are linked against an earlier library, we will have fake it by
+   converting the value to long double, and using sprintf to do the conversion.
+   This isn't ideal, as IEEE 128-bit has more exponent range than IBM
+   128-bit.  */
+
+extern int __sprintfieee128 (char *restrict, const char *restrict, ...)
+  __attribute__ ((__weak__));
+
+int __sprintfkf (char *restrict string,
+                const char *restrict format,
+                _Float128 number)
+{
+  if (__sprintfieee128)
+    return __sprintfieee128 (string, format, number);
+
+  return sprintf (string, format, (long double) number);
+}
diff --git a/libgcc/config/rs6000/_sprintfkf.h b/libgcc/config/rs6000/_sprintfkf.h
new file mode 100644 (file)
index 0000000..637d104
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (C) 1989-2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Declaration of the conversion function to IEEE 128-bit floating point from
+   string using snprintf.  */
+
+extern int __sprintfkf (char *restrict, const char *restrict, ...);
+
diff --git a/libgcc/config/rs6000/_strtokf.c b/libgcc/config/rs6000/_strtokf.c
new file mode 100644 (file)
index 0000000..dc13534
--- /dev/null
@@ -0,0 +1,53 @@
+/* Copyright (C) 1989-2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Conversion to IEEE 128-bit floating point from string.  */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <soft-fp.h>
+#include <quad-float128.h>
+
+/* This function must be built with IBM 128-bit as long double, so that we can
+   access the strtold function if do not have an IEEE 128-bit version.  */
+#if !defined(__LONG_DOUBLE_128__) || !defined(__LONG_DOUBLE_IBM128__)
+#error "Long double is not IBM 128-bit"
+#endif
+
+/* If the user is using GLIBC 2.32, we can use the __strtoieee128 function.
+
+   If we are linked against an earlier library, we will have fake it by
+   converting the string to IBM 128-bit long double, and then converting that to
+   __float128.  This isn't ideal, as IEEE 128-bit has more exponent range than
+   IBM 128-bit.  */
+
+extern _Float128 __strtoieee128 (const char *, char **) __attribute__ ((__weak__));
+
+_Float128
+__strtokf (const char *string, char **endptr)
+{
+  if (__strtoieee128)
+    return __strtoieee128 (string, endptr);
+
+  return strtold (string, endptr);
+}
diff --git a/libgcc/config/rs6000/_strtokf.h b/libgcc/config/rs6000/_strtokf.h
new file mode 100644 (file)
index 0000000..a7ca8e0
--- /dev/null
@@ -0,0 +1,27 @@
+/* Copyright (C) 1989-2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Declaration of the conversion function to IEEE 128-bit floating point from
+   string.  */
+
+extern _Float128 __strtokf (const char *, char **);
diff --git a/libgcc/config/rs6000/_td_to_kf.c b/libgcc/config/rs6000/_td_to_kf.c
new file mode 100644 (file)
index 0000000..0134581
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright (C) 2021 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 3, or (at your option) any later
+version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Decimal128 -> _Float128 conversion.  */
+
+/* FINE_GRAINED_LIBRARIES is used so we can isolate just to td_to_tf conversion
+   function from dp-bits.c.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_td_to_kf             1
+#define WIDTH                  128
+
+#if !defined(__LONG_DOUBLE_128__) || !defined(__LONG_DOUBLE_IEEE128__)
+#error "Long double is not IEEE 128-bit"
+#endif
+
+/* Use dfp-bit.c to do the real work.  */
+#include "dfp-bit.c"
index 0eb1d34..5beb153 100644 (file)
@@ -49,6 +49,7 @@ typedef __complex float TCtype __attribute__ ((mode (TC)));
 #pragma GCC target ("vsx,float128")
 #endif
 
+#include <stddef.h>
 #include <quad.h>
 
 #define IBM128_TYPE    __ibm128
@@ -171,6 +172,13 @@ extern TFtype __trunctfkf2 (IBM128_TYPE);
 extern TCtype __mulkc3 (TFtype, TFtype, TFtype, TFtype);
 extern TCtype __divkc3 (TFtype, TFtype, TFtype, TFtype);
 
+/* Convert IEEE 128-bit floating point to/from string.  We explicitly use
+   _Float128 instead of TFmode because _strtokf and _strfromkf must be compiled
+   with long double being IBM 128.  */
+extern _Float128 __strtokf (const char *, char **);
+extern int __strfromkf (char *restrict, size_t, const char *restrict,
+                       _Float128);
+
 /* Implementation of conversions between __ibm128 and __float128, to allow the
    same code to be used on systems with IEEE 128-bit emulation and with IEEE
    128-bit hardware support.  */
index d541344..6fb1a3d 100644 (file)
@@ -22,10 +22,23 @@ fp128_softfp_static_obj     = $(addsuffix -sw$(objext),$(fp128_softfp_funcs))
 fp128_softfp_shared_obj        = $(addsuffix -sw_s$(objext),$(fp128_softfp_funcs))
 fp128_softfp_obj       = $(fp128_softfp_static_obj) $(fp128_softfp_shared_obj)
 
+# Decimal <-> _Float128 conversions
+fp128_dec_funcs                = _kf_to_sd _kf_to_dd _kf_to_td \
+                         _sd_to_kf _dd_to_kf _td_to_kf
+
+# _Float128 to/from string conversions that must be compiled with IBM 128-bit
+# long double.
+fp128_decstr_funcs     = _strtokf _sprintfkf
+
+# Decimal <-> __ibm128 conversions
+ibm128_dec_funcs       = _tf_to_sd _tf_to_dd _tf_to_td \
+                         _sd_to_tf _dd_to_tf _td_to_tf
+
 # New functions for software emulation
 fp128_ppc_funcs                = floattikf floatuntikf fixkfti fixunskfti \
                          extendkftf2-sw trunctfkf2-sw \
-                         sfp-exceptions _mulkc3 _divkc3 _powikf2
+                         sfp-exceptions _mulkc3 _divkc3 _powikf2 \
+                         $(fp128_dec_funcs) $(fp128_decstr_funcs)
 
 fp128_ppc_src          = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix \
                                .c,$(fp128_ppc_funcs)))
@@ -69,6 +82,28 @@ $(fp128_ppc_obj)      : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW)
 $(fp128_obj)            : $(fp128_includes)
 $(fp128_obj)            : $(srcdir)/config/rs6000/quad-float128.h
 
+# Force the TF mode to/from decimal functions to be compiled with IBM long
+# double.  Add building the KF mode to/from decimal conversions with explict
+# IEEE long double.
+fp128_dec_objs         = $(addsuffix $(objext),$(fp128_dec_funcs)) \
+                         $(addsuffix _s$(objext),$(fp128_dec_funcs))
+
+fp128_decstr_objs      = $(addsuffix $(objext),$(fp128_decstr_funcs)) \
+                         $(addsuffix _s$(objext),$(fp128_decstr_funcs))
+
+ibm128_dec_objs                = $(addsuffix $(objext),$(ibm128_dec_funcs)) \
+                         $(addsuffix _s$(objext),$(ibm128_dec_funcs))
+
+FP128_CFLAGS_DECIMAL   = -mno-gnu-attribute -Wno-psabi -mabi=ieeelongdouble
+IBM128_CFLAGS_DECIMAL  = -mno-gnu-attribute -Wno-psabi -mabi=ibmlongdouble
+
+$(fp128_dec_objs)      : INTERNAL_CFLAGS += $(FP128_CFLAGS_DECIMAL)
+$(fp128_decstr_objs)   : INTERNAL_CFLAGS += $(IBM128_CFLAGS_DECIMAL)
+$(ibm128_dec_objs)     : INTERNAL_CFLAGS += $(IBM128_CFLAGS_DECIMAL)
+
+$(fp128_decstr_objs)   : $(srcdir)/config/rs6000/_strtokf.h \
+                         $(srcdir)/config/rs6000/_sprintfkf.h \
+
 $(fp128_softfp_src) : $(srcdir)/soft-fp/$(subst -sw,,$(subst kf,tf,$@)) $(fp128_dep)
        @src="$(srcdir)/soft-fp/$(subst -sw,,$(subst kf,tf,$@))"; \
        echo "Create $@"; \
index 17bca9c..0b0f9ac 100644 (file)
@@ -606,6 +606,7 @@ INT_TO_DFP (INT_TYPE i)
 
 #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_kf) || defined (L_dd_to_kf) || defined (L_td_to_kf) \
  || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
      && LONG_DOUBLE_HAS_XF_MODE) \
  || ((defined (L_sd_to_tf) || defined (L_dd_to_tf) || defined (L_td_to_tf)) \
@@ -626,6 +627,7 @@ DFP_TO_BFP (DFP_C_TYPE f)
                                                                                 
 #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_kf_to_sd) || defined (L_kf_to_dd) || defined (L_kf_to_td) \
  || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
      && LONG_DOUBLE_HAS_XF_MODE) \
  || ((defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)) \
@@ -641,8 +643,14 @@ BFP_TO_DFP (BFP_TYPE x)
   decContextDefault (&context, CONTEXT_INIT);
   DFP_INIT_ROUNDMODE (context.round);
 
-  /* Use a C library function to write the floating point value to a string.  */
-  sprintf (buf, BFP_FMT, (BFP_VIA_TYPE) x);
+  /* Use the sprintf library function to write the floating point value to a string.
+
+     If we are handling the IEEE 128-bit floating point on PowerPC, use the
+     special function __sprintfkf instead of sprintf.  This function allows us
+     to use __sprintfieee128 if we have a new enough GLIBC, and it can fall back
+     to using the traditional sprintf via conversion to IBM 128-bit if the glibc
+     is older.  */
+  BFP_SPRINTF (buf, BFP_FMT, (BFP_VIA_TYPE) x);
 
   /* Convert from the floating point string to a decimal* type.  */
   FROM_STRING (&s, buf, &context);
index 1fa42ee..5e3bfa6 100644 (file)
@@ -241,6 +241,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #elif defined (L_sd_to_tf) || defined (L_dd_to_tf) || defined (L_td_to_tf) \
  ||   defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)
 #define BFP_KIND 4
+#elif defined (L_sd_to_kf) || defined (L_dd_to_kf) || defined (L_td_to_kf) \
+ ||   defined (L_kf_to_sd) || defined (L_kf_to_dd) || defined (L_kf_to_td)
+#define BFP_KIND 5
 #endif
 
 /*  If BFP_KIND is defined, define additional macros:
@@ -291,6 +294,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define BFP_VIA_TYPE long double
 #endif /* LONG_DOUBLE_HAS_TF_MODE */
 
+#elif BFP_KIND == 5
+#define BFP_TYPE _Float128
+#define BFP_FMT "%.36Le"
+#define BFP_VIA_TYPE _Float128
+#define STR_TO_BFP __strtokf
+#include <_strtokf.h>
+
 #endif /* BFP_KIND */
 
 #if WIDTH == 128 || WIDTH_TO == 128
@@ -490,6 +500,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #elif BFP_KIND == 4
 #define BFP_TO_DFP     DPD_BID_NAME(__dpd_trunctfsd,__bid_trunctfsd)
 #define DFP_TO_BFP     DPD_BID_NAME(__dpd_extendsdtf,__bid_extendsdtf)
+#elif BFP_KIND == 5
+#define BFP_TO_DFP     DPD_BID_NAME(__dpd_trunckfsd,__bid_trunckfsd)
+#define DFP_TO_BFP     DPD_BID_NAME(__dpd_extendsdkf,__bid_extendsdkf)
 #endif /* BFP_KIND */
 
 #elif WIDTH == 64
@@ -505,6 +518,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #elif BFP_KIND == 4
 #define BFP_TO_DFP     DPD_BID_NAME(__dpd_trunctfdd,__bid_trunctfdd)
 #define DFP_TO_BFP     DPD_BID_NAME(__dpd_extendddtf,__bid_extendddtf)
+#elif BFP_KIND == 5
+#define BFP_TO_DFP     DPD_BID_NAME(__dpd_trunckfdd,__bid_trunckfdd)
+#define DFP_TO_BFP     DPD_BID_NAME(__dpd_extendddkf,__bid_extendddkf)
 #endif /* BFP_KIND */
 
 #elif WIDTH == 128
@@ -520,6 +536,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #elif BFP_KIND == 4
 #define BFP_TO_DFP     DPD_BID_NAME(__dpd_extendtftd,__bid_extendtftd)
 #define DFP_TO_BFP     DPD_BID_NAME(__dpd_trunctdtf,__bid_trunctdtf)
+#elif BFP_KIND == 5
+#define BFP_TO_DFP     DPD_BID_NAME(__dpd_extendkftd,__bid_extendkftd)
+#define DFP_TO_BFP     DPD_BID_NAME(__dpd_trunctdkf,__bid_trunctdkf)
 #endif /* BFP_KIND */
 
 #endif /* WIDTH */
@@ -609,6 +628,7 @@ extern DFP_C_TYPE INT_TO_DFP (INT_TYPE);
 
 #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_kf) || defined (L_dd_to_kf) || defined (L_td_to_kf) \
  || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
      && LONG_DOUBLE_HAS_XF_MODE) \
  || ((defined (L_sd_to_tf) || defined (L_dd_to_tf) || defined (L_td_to_tf)) \
@@ -623,6 +643,12 @@ extern BFP_TYPE DFP_TO_BFP (DFP_C_TYPE);
  || ((defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)) \
      && LONG_DOUBLE_HAS_TF_MODE)
 extern DFP_C_TYPE BFP_TO_DFP (BFP_TYPE);
+#define BFP_SPRINTF sprintf
+
+#elif defined (L_kf_to_sd) || defined (L_kf_to_dd) || defined (L_kf_to_td)
+extern DFP_C_TYPE BFP_TO_DFP (BFP_TYPE);
+#include <_sprintfkf.h>
+#define BFP_SPRINTF __sprintfkf
 #endif
 
 #endif /* _DFPBIT_H */