PowerPC: Add __float128 conversions to/from Decimal.

I have split all of these patches into separate patches to hopefully get them
into the tree.

This patch adds the various decimal to/from IEEE 128-bit conversions.  I
had to make some changes to the infrastructure, since that infrastructure
assumed that there is a sprintf/scanf format modifier to convert floating
point.  Instead, I used to str* conversion functions.

I have tested this patch with bootstrap builds on a little endian power9 system
running Linux.  With the other patches, I have built two full bootstrap builds
using this patch and the patches after this patch.  One build used the current
default for long double (IBM extended double) and the other build switched the
default to IEEE 128-bit.  I used the Advance Toolchain AT 14.0 compiler as the
library used by this compiler.  There are no regressions between the tests.
There are 3 fortran benchmarks (ieee/large_2.f90, default_format_2.f90, and
default_format_denormal_2.f90) that now pass.

Can I install this into the trunk?

We have gotten some requests to back port these changes to GCC 10.x.  At the
moment, I am not planning to do the back port, but I may need to in the future.

libgcc/
2020-10-22  Michael Meissner  <meiss...@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/_td_to_kf.c: New file.
        * config/rs6000/t-float128: Build __float128 conversions to and
        from Decimal support functions.
        * dfp-bit.c: Add support for building the PowerPC _Float128
        to/from Decimal conversion functions.
        * dfp-bit.h: Likewise.
---
 libgcc/config/rs6000/_dd_to_kf.c | 30 ++++++++++++++++++++++++++
 libgcc/config/rs6000/_kf_to_dd.c | 30 ++++++++++++++++++++++++++
 libgcc/config/rs6000/_kf_to_sd.c | 30 ++++++++++++++++++++++++++
 libgcc/config/rs6000/_kf_to_td.c | 30 ++++++++++++++++++++++++++
 libgcc/config/rs6000/_sd_to_kf.c | 30 ++++++++++++++++++++++++++
 libgcc/config/rs6000/_td_to_kf.c | 30 ++++++++++++++++++++++++++
 libgcc/config/rs6000/t-float128  | 20 ++++++++++++++++-
 libgcc/dfp-bit.c                 | 10 +++++++--
 libgcc/dfp-bit.h                 | 37 +++++++++++++++++++++++++++++---
 9 files changed, 241 insertions(+), 6 deletions(-)
 create mode 100644 libgcc/config/rs6000/_dd_to_kf.c
 create mode 100644 libgcc/config/rs6000/_kf_to_dd.c
 create mode 100644 libgcc/config/rs6000/_kf_to_sd.c
 create mode 100644 libgcc/config/rs6000/_kf_to_td.c
 create mode 100644 libgcc/config/rs6000/_sd_to_kf.c
 create mode 100644 libgcc/config/rs6000/_td_to_kf.c

diff --git a/libgcc/config/rs6000/_dd_to_kf.c b/libgcc/config/rs6000/_dd_to_kf.c
new file mode 100644
index 00000000000..081415fd393
--- /dev/null
+++ b/libgcc/config/rs6000/_dd_to_kf.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989-2020 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.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_dd_to_kf             1
+#define WIDTH                  64
+
+/* 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
index 00000000000..09a62cbe629
--- /dev/null
+++ b/libgcc/config/rs6000/_kf_to_dd.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989-2020 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.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_kf_to_dd             1
+#define WIDTH                  64
+
+/* 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
index 00000000000..f35b68eb4d9
--- /dev/null
+++ b/libgcc/config/rs6000/_kf_to_sd.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989-2020 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.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_kf_to_sd             1
+#define WIDTH                  32
+
+/* 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
index 00000000000..d35d09ed848
--- /dev/null
+++ b/libgcc/config/rs6000/_kf_to_td.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989-2020 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.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_kf_to_td             1
+#define WIDTH                  128
+
+/* 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
index 00000000000..9396b71f162
--- /dev/null
+++ b/libgcc/config/rs6000/_sd_to_kf.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989-2020 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.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_sd_to_kf             1
+#define WIDTH                  32
+
+/* Use dfp-bit.c to do the real work.  */
+#include "dfp-bit.c"
diff --git a/libgcc/config/rs6000/_td_to_kf.c b/libgcc/config/rs6000/_td_to_kf.c
new file mode 100644
index 00000000000..fade2a28859
--- /dev/null
+++ b/libgcc/config/rs6000/_td_to_kf.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989-2020 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.  */
+#define FINE_GRAINED_LIBRARIES 1
+#define L_td_to_kf             1
+#define WIDTH                  128
+
+/* Use dfp-bit.c to do the real work.  */
+#include "dfp-bit.c"
diff --git a/libgcc/config/rs6000/t-float128 b/libgcc/config/rs6000/t-float128
index c2cb3e2b705..14a4df1bbf3 100644
--- a/libgcc/config/rs6000/t-float128
+++ b/libgcc/config/rs6000/t-float128
@@ -22,10 +22,15 @@ 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
+
 # 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_ppc_src          = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix \
                                .c,$(fp128_ppc_funcs)))
@@ -74,6 +79,19 @@ $(fp128_obj)          : 
$(srcdir)/config/rs6000/quad-float128.h
 # __ibm128 if long double uses the IEEE 128-bit representation.
 ibm-ldouble$(objext)   : INTERNAL_CFLAGS += -mno-gnu-attribute
 
+# 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.
+TF_DECIMAL_OBJS                = _dd_to_tf$(objext) _sd_to_tf$(objext) \
+                         _td_to_tf$(objext) _tf_to_dd$(objext) \
+                         _tf_to_sd$(objext) _tf_to_td$(objext)
+
+CFLAGS_TF_DECIMAL      = -mno-gnu-attribute -Wno-psabi -mabi=ibmlongdouble
+CFLAGS_KF_DECIMAL      = -mno-gnu-attribute -Wno-psabi -mabi=ieeelongdouble
+CFLAGS_KF_DECIMAL_SW   = $(CFLAGS_KF_DECIMAL) -mno-float128-hardware
+
+$(TF_DECIMAL_OBJS) : INTERNAL_CFLAGS += $(CFLAGS_TF_DECIMAL)
+
 $(fp128_softfp_src) : $(srcdir)/soft-fp/$(subst -sw,,$(subst kf,tf,$@)) 
$(fp128_dep)
        @src="$(srcdir)/soft-fp/$(subst -sw,,$(subst kf,tf,$@))"; \
        echo "Create $@"; \
diff --git a/libgcc/dfp-bit.c b/libgcc/dfp-bit.c
index 935a1e340db..67212daa0bd 100644
--- a/libgcc/dfp-bit.c
+++ b/libgcc/dfp-bit.c
@@ -609,7 +609,8 @@ INT_TO_DFP (INT_TYPE i)
  || ((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)) \
-     && LONG_DOUBLE_HAS_TF_MODE)
+     && LONG_DOUBLE_HAS_TF_MODE) \
+  || defined (L_sd_to_kf) || defined (L_dd_to_kf) || defined (L_td_to_kf)
 BFP_TYPE
 DFP_TO_BFP (DFP_C_TYPE f)
 {
@@ -629,7 +630,8 @@ DFP_TO_BFP (DFP_C_TYPE f)
  || ((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)) \
-     && LONG_DOUBLE_HAS_TF_MODE)
+     && LONG_DOUBLE_HAS_TF_MODE) \
+ || defined (L_kf_to_sd) || defined (L_kf_to_dd) || defined (L_kf_to_td)
 DFP_C_TYPE
 BFP_TO_DFP (BFP_TYPE x)
 {
@@ -642,7 +644,11 @@ BFP_TO_DFP (BFP_TYPE x)
   DFP_INIT_ROUNDMODE (context.round);
 
   /* Use a C library function to write the floating point value to a string.  
*/
+#if HAVE_KF_MODE
+  strfromf128 (buf, BUFMAX, BFP_FMT, (BFP_VIA_TYPE) x);
+#else
   sprintf (buf, BFP_FMT, (BFP_VIA_TYPE) x);
+#endif
 
   /* Convert from the floating point string to a decimal* type.  */
   FROM_STRING (&s, buf, &context);
diff --git a/libgcc/dfp-bit.h b/libgcc/dfp-bit.h
index 4215241da18..91fcdcdc7eb 100644
--- a/libgcc/dfp-bit.h
+++ b/libgcc/dfp-bit.h
@@ -226,6 +226,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
 #define STR_TO_INT strtoull
 #endif
 
+/* Support PowerPC KF mode, which is __float128 when long double is
+   IBM extended double.  */
+#if 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 HAVE_KF_MODE 1
+#endif
+
 /* Conversions between decimal float types and binary float types use
    BFP_KIND to determine the data type and C functions to use.  */
 
@@ -239,7 +246,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
  ||   defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)
 #define BFP_KIND 3
 #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)
+ ||   defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td) \
+ ||   defined (HAVE_KF_MODE)
 #define BFP_KIND 4
 #endif
 
@@ -277,6 +285,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
 #define STR_TO_BFP strtold
 #endif /* LONG_DOUBLE_HAS_XF_MODE */
 
+#elif BFP_KIND == 4 && HAVE_KF_MODE
+#define BFP_TYPE _Float128
+#define BFP_FMT "%.36e"
+#define STR_TO_BFP strtof128
+#define BFP_VIA_TYPE _Float128
+extern _Float128 strtof128 (const char *__restrict __nptr,
+                           char **__restrict __endptr)
+  __THROW __nonnull ((1));
+extern int strfromf128 (char *__dest, size_t __size, const char * __format,
+                       _Float128 __f)
+  __THROW __nonnull ((3));
+
 #elif BFP_KIND == 4
 #if LONG_DOUBLE_HAS_TF_MODE
 #define BFP_TYPE TFtype
@@ -487,6 +507,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
 #elif BFP_KIND == 3
 #define BFP_TO_DFP     DPD_BID_NAME(__dpd_truncxfsd,__bid_truncxfsd)
 #define DFP_TO_BFP     DPD_BID_NAME(__dpd_extendsdxf,__bid_extendsdxf)
+#elif BFP_KIND == 4 && HAVE_KF_MODE
+#define BFP_TO_DFP     DPD_BID_NAME(__dpd_trunckfsd,__bid_trunckfsd)
+#define DFP_TO_BFP     DPD_BID_NAME(__dpd_extendsdkf,__bid_extendsdkf)
 #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)
@@ -502,6 +525,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
 #elif BFP_KIND == 3
 #define BFP_TO_DFP     DPD_BID_NAME(__dpd_truncxfdd,__bid_truncxfdd)
 #define DFP_TO_BFP     DPD_BID_NAME(__dpd_extendddxf,__bid_extendddxf)
+#elif BFP_KIND == 4 && HAVE_KF_MODE
+#define BFP_TO_DFP     DPD_BID_NAME(__dpd_trunckfdd,__bid_trunckfdd)
+#define DFP_TO_BFP     DPD_BID_NAME(__dpd_extendddkf,__bid_extendddkf)
 #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)
@@ -517,6 +543,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
 #elif BFP_KIND == 3
 #define BFP_TO_DFP     DPD_BID_NAME(__dpd_extendxftd,__bid_extendxftd)
 #define DFP_TO_BFP     DPD_BID_NAME(__dpd_trunctdxf,__bid_trunctdxf)
+#elif BFP_KIND == 4 && HAVE_KF_MODE
+#define BFP_TO_DFP     DPD_BID_NAME(__dpd_extendkftd,__bid_extendkftd)
+#define DFP_TO_BFP     DPD_BID_NAME(__dpd_trunctdkf,__bid_trunctdkf)
 #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)
@@ -612,7 +641,8 @@ extern DFP_C_TYPE INT_TO_DFP (INT_TYPE);
  || ((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)) \
-     && LONG_DOUBLE_HAS_TF_MODE)
+     && LONG_DOUBLE_HAS_TF_MODE) \
+ || defined (L_sd_to_kf) || defined (L_dd_to_kf) || defined (L_td_to_kf)
 extern BFP_TYPE DFP_TO_BFP (DFP_C_TYPE);
 #endif
 
@@ -621,7 +651,8 @@ extern BFP_TYPE DFP_TO_BFP (DFP_C_TYPE);
  || ((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)) \
-     && LONG_DOUBLE_HAS_TF_MODE)
+     && LONG_DOUBLE_HAS_TF_MODE) \
+ || defined (L_kf_to_sd) || defined (L_kf_to_dd) || defined (L_kf_to_td)
 extern DFP_C_TYPE BFP_TO_DFP (BFP_TYPE);
 #endif
 
-- 
2.22.0


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meiss...@linux.ibm.com, phone: +1 (978) 899-4797

Reply via email to