diff mbox series

[4/9] PowerPC: Add IEEE 128-bit <-> Decimal conversions.

Message ID 20200924203545.GD31597@ibm-toto.the-meissners.org
State New
Headers show
Series PowerPC: Patches to enable changing the long double default to IEEE 128-bit on little endian PowerPC 64-bit Linux systems | expand

Commit Message

Michael Meissner Sept. 24, 2020, 8:35 p.m. UTC
PowerPC: Add IEEE 128-bit <-> Decimal conversions.

This patch adds the basic support for converting between IEEE 128-bit floating
point and Decimal types.

libgcc/
2020-09-23  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/_td_to_kf.c: New file.
	* config/rs6000/t-float128: Build __floating conversions to/from
	Decimal support functions.  By default compile with long double
	being IBM extended double.
	* 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  | 30 +++++++++++++++++++++++++-
 libgcc/dfp-bit.c                 | 10 +++++++--
 libgcc/dfp-bit.h                 | 37 +++++++++++++++++++++++++++++---
 9 files changed, 251 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 mbox series

Patch

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 d5413445189..3d6054c6a54 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)))
@@ -69,6 +74,29 @@  $(fp128_ppc_obj)	 : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW)
 $(fp128_obj)		 : $(fp128_includes)
 $(fp128_obj)		 : $(srcdir)/config/rs6000/quad-float128.h
 
+
+# If we are switching the default long double type, we need to use
+# -mno-gnu-attribute so that the __ibm128 support functions don't signal a
+# linker error since the default long double is now IEEE 128-bit instead of IBM
+# 128-bit.
+ibm-ldouble$(objext)	: INTERNAL_CFLAGS += -mno-gnu-attribute
+
+# Similarly for the decimal routines, compile with long double == IBM 128-bit,
+# but set the flags so that it can be linked with either long double format.
+#DECNUMINC	+= -Wno-psabi -mabi=ibmlongdouble -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
+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