]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Conversions between 128-bit integer and floating point values.
authorCarl Love <cel@us.ibm.com>
Wed, 21 Apr 2021 22:07:39 +0000 (18:07 -0400)
committerCarl Love <cel@us.ibm.com>
Mon, 21 Jun 2021 22:33:31 +0000 (17:33 -0500)
The files fixkfti-sw.c and fixunskfti-sw.c are renamed versions of
fixkfti.c and fixunskfti.c respectively to do the conversions in software.
The function names in the files were updated with the rename as well as
some white spaces fixes. The file float128-p10.c contains the functions
for using the ISA 3.1 hardware instructions to perform the conversions.

2021-06-15  Carl Love  <cel@us.ibm.com>

gcc/ChangeLog

* config/rs6000/rs6000.c (__fixkfti, __fixunskfti, __floattikf,
__floatuntikf): Names changed to __fixkfti_sw, __fixunskfti_sw,
__floattikf_sw, __floatuntikf_sw respectively.
* config/rs6000/rs6000.md (floatti<mode>2, floatunsti<mode>2,
fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add
define_insn for mode IEEE 128.

gcc/testsuite/ChangeLog

* gcc.target/powerpc/fp128_conversions.c: New file.
* gcc.target/powerpc/int_128bit-runnable.c(vextsd2q,
vcmpuq, vcmpsq, vcmpequq, vcmpequq., vcmpgtsq, vcmpgtsq.
vcmpgtuq, vcmpgtuq.): Update scan-assembler-times.
(ppc_native_128bit): Remove dg-require-effective-target.

libgcc/ChangeLog

* config.host: Add if test and set for
libgcc_cv_powerpc_3_1_float128_hw.
* config/rs6000/fixkfti.c: Renamed to fixkfti-sw.c.
Change calls of __fixkfti to __fixkfti_sw.
* config/rs6000/fixunskfti.c: Renamed to fixunskfti-sw.c.
Change calls of __fixunskfti to __fixunskfti_sw.
* config/rs6000/float128-p10.c (__floattikf_hw,
__floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw): New file.
* config/rs6000/float128-ifunc.c (SW_OR_HW_ISA3_1): New macro.
(__floattikf_resolve, __floatuntikf_resolve, __fixkfti_resolve,
__fixunskfti_resolve): Add resolve functions.
(__floattikf, __floatuntikf, __fixkfti, __fixunskfti): New functions.
* config/rs6000/float128-sed (floattitf, __floatuntitf,
__fixtfti, __fixunstfti): Add editor commands to change names.
* config/rs6000/float128-sed-hw (__floattitf,
__floatuntitf, __fixtfti, __fixunstfti): Add editor commands to
change names.
* config/rs6000/floattikf.c: Renamed to floattikf-sw.c.
* config/rs6000/floatuntikf.c: Renamed to floatuntikf-sw.c.
* config/rs6000/quad-float128.h (__floattikf_sw,
__floatuntikf_sw, __fixkfti_sw, __fixunskfti_sw, __floattikf_hw,
__floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw, __floattikf,
__floatuntikf, __fixkfti, __fixunskfti): New extern declarations.
* config/rs6000/t-float128 (floattikf, floatuntikf,
fixkfti, fixunskfti): Remove file names from fp128_ppc_funcs.
(floattikf-sw, floatuntikf-sw, fixkfti-sw, fixunskfti-sw): Add
file names to fp128_ppc_funcs.
* config/rs6000/t-float128-hw(fp128_3_1_hw_funcs,
fp128_3_1_hw_src, fp128_3_1_hw_static_obj, fp128_3_1_hw_shared_obj,
fp128_3_1_hw_obj): Add variables for ISA 3.1 support.
* config/rs6000/t-float128-p10-hw: New file.
* configure: Update script for isa 3.1 128-bit float support.
* configure.ac: Add check for 128-bit float hardware support.

19 files changed:
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/testsuite/gcc.target/powerpc/fp128_conversions.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
libgcc/config.host
libgcc/config/rs6000/fixkfti-sw.c [moved from libgcc/config/rs6000/fixkfti.c with 96% similarity]
libgcc/config/rs6000/fixunskfti-sw.c [moved from libgcc/config/rs6000/fixunskfti.c with 96% similarity]
libgcc/config/rs6000/float128-ifunc.c
libgcc/config/rs6000/float128-p10.c [new file with mode: 0644]
libgcc/config/rs6000/float128-sed
libgcc/config/rs6000/float128-sed-hw
libgcc/config/rs6000/floattikf-sw.c [moved from libgcc/config/rs6000/floattikf.c with 96% similarity]
libgcc/config/rs6000/floatuntikf-sw.c [moved from libgcc/config/rs6000/floatuntikf.c with 96% similarity]
libgcc/config/rs6000/quad-float128.h
libgcc/config/rs6000/t-float128
libgcc/config/rs6000/t-float128-hw
libgcc/config/rs6000/t-float128-p10-hw [new file with mode: 0644]
libgcc/configure
libgcc/configure.ac

index 7efce4efeb12b8e2451706f71a49945fdfe32a5c..efdf384f20bec01a072cf25e072a0fbeb42a2f24 100644 (file)
@@ -11041,10 +11041,10 @@ init_float128_ieee (machine_mode mode)
 
       if (TARGET_POWERPC64)
        {
-         set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti");
-         set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti");
-         set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf");
-         set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf");
+         set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti_sw");
+         set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti_sw");
+         set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf_sw");
+         set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf_sw");
        }
     }
 
index 3f59b544f6ac624f63699b997989292ef9790298..89c70f4a64e4b37c0d8b862922b069ab5b6dfd3e 100644 (file)
    xscvsxddp %x0,%x1"
   [(set_attr "type" "fp")])
 
+(define_insn "floatti<mode>2"
+  [(set (match_operand:IEEE128 0 "vsx_register_operand" "=v")
+       (float:IEEE128 (match_operand:TI 1 "vsx_register_operand" "v")))]
+  "TARGET_POWER10"
+{
+  return  "xscvsqqp %0,%1";
+}
+  [(set_attr "type" "fp")])
+
+(define_insn "floatunsti<mode>2"
+  [(set (match_operand:IEEE128 0 "vsx_register_operand" "=v")
+       (unsigned_float:IEEE128 (match_operand:TI 1 "vsx_register_operand" "v")))]
+  "TARGET_POWER10"
+{
+  return  "xscvuqqp %0,%1";
+}
+  [(set_attr "type" "fp")])
+
+(define_insn "fix_trunc<mode>ti2"
+  [(set (match_operand:TI 0 "vsx_register_operand" "=v")
+       (fix:TI (match_operand:IEEE128 1 "vsx_register_operand" "v")))]
+  "TARGET_POWER10"
+{
+  return  "xscvqpsqz %0,%1";
+}
+  [(set_attr "type" "fp")])
+
+(define_insn "fixuns_trunc<mode>ti2"
+  [(set (match_operand:TI 0 "vsx_register_operand" "=v")
+       (unsigned_fix:TI (match_operand:IEEE128 1 "vsx_register_operand" "v")))]
+  "TARGET_POWER10"
+{
+  return  "xscvqpuqz %0,%1";
+}
+  [(set_attr "type" "fp")])
+
 ; Allow the combiner to merge source memory operands to the conversion so that
 ; the optimizer/register allocator doesn't try to load the value too early in a
 ; GPR and then use store/load to move it to a FPR and suffer from a store-load
diff --git a/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
new file mode 100644 (file)
index 0000000..c20282f
--- /dev/null
@@ -0,0 +1,294 @@
+/* { dg-do run } */
+/* { dg-require-effective-target power10_hw } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
+
+/* Check that the expected 128-bit instructions are generated if the processor
+   supports the 128-bit integer instructions. */
+/* { dg-final { scan-assembler-times {\mxscvsqqp\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvuqqp\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvqpsqz\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvqpuqz\M} 1 } } */
+
+#include <stdio.h>
+#include <math.h>
+#include <fenv.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#define DEBUG 0
+
+void
+abort (void);
+
+float
+conv_i_2_fp( long long int a)
+{
+  return (float) a;
+}
+
+double
+conv_i_2_fpd( long long int a)
+{
+  return (double) a;
+}
+
+double
+conv_ui_2_fpd( unsigned long long int a)
+{
+  return (double) a;
+}
+
+__float128
+conv_i128_2_fp128 (__int128_t a)
+{
+  // default, gen inst KF mode
+  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (__float128) a;
+}
+
+__float128
+conv_ui128_2_fp128 (__uint128_t a)
+{
+  // default, gen inst KF mode
+  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (__float128) a;
+}
+
+__int128_t
+conv_fp128_2_i128 (__float128 a)
+{
+  // default, gen inst KF mode
+  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (__int128_t) a;
+}
+
+__uint128_t
+conv_fp128_2_ui128 (__float128 a)
+{
+  // default, gen inst KF mode
+  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (__uint128_t) a;
+}
+
+long double
+conv_i128_2_ld (__int128_t a)
+{
+  // default, gen call __floattitf
+  // -mabi=ibmlongdouble, gen call __floattitf
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (long double) a;
+}
+
+__ibm128
+conv_i128_2_ibm128 (__int128_t a)
+{
+  // default, gen call __floattitf
+  // -mabi=ibmlongdouble, gen call __floattitf
+  // -mabi=ieeelongdouble, message uses IBM long double, no binary output
+  return (__ibm128) a;
+}
+
+int
+main()
+{
+       float a, expected_result_float;
+       double b, expected_result_double;
+       long long int c, expected_result_llint;
+       unsigned long long int u;
+       __int128_t d;
+       __uint128_t u128;
+       unsigned long long expected_result_uint128[2] ;
+       __float128 e;
+       long double ld;     // another 128-bit float version
+
+       union conv_t {
+               float a;
+               double b;
+               long long int c;
+               long long int128[2] ;
+               unsigned long long uint128[2] ;
+               unsigned long long int u;
+               __int128_t d;
+               __uint128_t u128;
+               __float128 e;
+               long double ld;     // another 128-bit float version
+       } conv, conv_result;
+
+       c = 20;
+       expected_result_llint = 20.00000;
+       a = conv_i_2_fp (c);
+
+       if (a != expected_result_llint) {
+#if DEBUG
+               printf("ERROR: conv_i_2_fp(%lld) = %10.5f\n", c, a);
+               printf("\n does not match expected_result = %10.5f\n\n",
+                                expected_result_llint);
+#else
+               abort();
+#endif
+       }
+
+       c = 20;
+       expected_result_double = 20.00000;
+       b = conv_i_2_fpd (c);
+
+       if (b != expected_result_double) {
+#if DEBUG
+               printf("ERROR: conv_i_2_fpd(%lld) = %10.5f\n", d, b);
+               printf("\n does not match expected_result = %10.5f\n\n",
+                                expected_result_double);
+ #else
+               abort();
+#endif
+       }
+
+       u = 20;
+       expected_result_double = 20.00000;
+       b = conv_ui_2_fpd (u);
+
+       if (b != expected_result_double) {
+#if DEBUG
+               printf("ERROR: conv_ui_2_fpd(%llu) = %10.5f\n", u, b);
+               printf("\n does not match expected_result = %10.5f\n\n",
+                                expected_result_double);
+ #else
+               abort();
+#endif
+       }
+
+  d = -3210;
+  d = (d * 10000000000) + 9876543210;
+  conv_result.e = conv_i128_2_fp128 (d);
+  expected_result_uint128[1] = 0xc02bd2f9068d1160;
+  expected_result_uint128[0] = 0x0;
+  
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+               && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+         printf("ERROR: conv_i128_2_fp128(-32109876543210) = (result in hex) 0x%llx %llx\n",
+                               conv.uint128[1], conv.uint128[0]);
+         printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+                               expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+         abort();
+#endif
+       }
+
+  d = 123;
+  d = (d * 10000000000) + 1234567890;
+  conv_result.ld = conv_i128_2_fp128 (d);
+  expected_result_uint128[1] = 0x0;
+  expected_result_uint128[0] = 0x4271eab4c8ed2000;
+
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+               && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+         printf("ERROR: conv_i128_2_fp128(1231234567890) = (result in hex) 0x%llx %llx\n",
+                               conv.uint128[1], conv.uint128[0]);
+         printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+                               expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+         abort();
+#endif
+       }
+
+  u128 = 8760;
+  u128 = (u128 * 10000000000) + 1234567890;
+  conv_result.e = conv_ui128_2_fp128 (u128);
+  expected_result_uint128[1] = 0x402d3eb101df8b48;
+  expected_result_uint128[0] = 0x0;
+
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+               && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+         printf("ERROR: conv_ui128_2_fp128(87601234567890) = (result in hex) 0x%llx %llx\n",
+                               conv.uint128[1], conv.uint128[0]);
+         printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+                               expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+         abort();
+#endif
+       }
+
+  u128 = 3210;
+  u128 = (u128 * 10000000000) + 9876543210;
+  expected_result_uint128[1] = 0x402bd3429c8feea0;
+  expected_result_uint128[0] = 0x0;
+  conv_result.e = conv_ui128_2_fp128 (u128);
+
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+               && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+         printf("ERROR: conv_ui128_2_fp128(32109876543210) = (result in hex) 0x%llx %llx\n",
+                               conv.uint128[1], conv.uint128[0]);
+         printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+                               expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+         abort();
+#endif
+       }
+
+  conv.e = 12345.6789;
+  expected_result_uint128[1] = 0x1407374883526960;
+  expected_result_uint128[0] = 0x3039;
+
+  conv_result.d = conv_fp128_2_i128 (conv.e);
+
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+               && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+         printf("ERROR: conv_fp128_2_i128(0x%llx %llx) =  ",
+                               conv.uint128[1], conv.uint128[0]);
+         printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+
+         printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+                               expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+         abort();
+#endif
+       }
+
+  conv.e = -6789.12345;
+  expected_result_uint128[1] = 0x0;
+  expected_result_uint128[0] = 0xffffffffffffe57b;
+  conv_result.d = conv_fp128_2_i128 (conv.e);
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+               && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+         printf("ERROR: conv_fp128_2_i128(0x%llx %llx) = ",
+                               conv.uint128[1], conv.uint128[0]);
+         printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+
+         printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+                               expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+         abort();
+#endif
+       }
+
+  conv.e = 6789.12345;
+  expected_result_uint128[1] = 0x0;
+  expected_result_uint128[0] = 0x1a85;
+  conv_result.d = conv_fp128_2_ui128 (conv.e);
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+               && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+         printf("ERROR: conv_fp128_2_ui128(0x%llx %llx) = ",
+                               conv.uint128[1], conv.uint128[0]);
+         printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+         
+         printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+                               expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+         abort();
+#endif
+       }
+
+  return 0;
+}
index 9f7dbc6cc755e8c6f0857a2abdbfec3c58bd4fee..94dbd2b623072f39c3291a175745b09ecdf13d90 100644 (file)
@@ -4,21 +4,16 @@
 
 /* Check that the expected 128-bit instructions are generated if the processor
    supports the 128-bit integer instructions. */
+/* { dg-final { scan-assembler-times {\mvextsd2q\M} 4 } } */
 /* { dg-final { scan-assembler-times {\mvslq\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvsrq\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvsraq\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvrlq\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvrlqnm\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvrlqmi\M} 2 } } */
-/* { dg-final { scan-assembler-times {\mvcmpuq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpsq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpequq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpequq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtsq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtuq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvmuleud\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvcmpequq\M} 16 } } */
+/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 16 } } */
+/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 16 } } */
 /* { dg-final { scan-assembler-times {\mvmuloud\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mvmulesd\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mvmulosd\M} 1 } } */
index f808b61be704cf32c2c234eb4792493cde1958de..50f00062232b0279ac45420cc9a2a5683ace2262 100644 (file)
@@ -1224,6 +1224,10 @@ powerpc*-*-linux*)
                tmake_file="${tmake_file} rs6000/t-float128-hw"
        fi
 
+       if test $libgcc_cv_powerpc_3_1_float128_hw = yes; then
+               tmake_file="${tmake_file} rs6000/t-float128-p10-hw"
+       fi
+
        extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
        md_unwind_header=rs6000/linux-unwind.h
        ;;
similarity index 96%
rename from libgcc/config/rs6000/fixkfti.c
rename to libgcc/config/rs6000/fixkfti-sw.c
index 0d965bc62533a6de0bb5bf0cb6e17c14c41edaf3..cc000fca0f8a37197e3b16973a1d06cfbc535dbf 100644 (file)
@@ -5,7 +5,7 @@
    This file is part of the GNU C Library.
    Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
    Code is based on the main soft-fp library written by:
-          Uros Bizjak (ubizjak@gmail.com).
+          Uros Bizjak (ubizjak@gmail.com).
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 #include "quad-float128.h"
 
 TItype
-__fixkfti (TFtype a)
+__fixkfti_sw (TFtype a)
 {
   FP_DECL_EX;
   FP_DECL_Q (A);
similarity index 96%
rename from libgcc/config/rs6000/fixunskfti.c
rename to libgcc/config/rs6000/fixunskfti-sw.c
index f285b4e3fbd21106218064ec2259e7aad5239614..7a04d1a489a66645edf1734a94be9e4c40de914a 100644 (file)
@@ -5,7 +5,7 @@
    This file is part of the GNU C Library.
    Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
    Code is based on the main soft-fp library written by:
-          Uros Bizjak (ubizjak@gmail.com).
+          Uros Bizjak (ubizjak@gmail.com).
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 #include "quad-float128.h"
 
 UTItype
-__fixunskfti (TFtype a)
+__fixunskfti_sw (TFtype a)
 {
   FP_DECL_EX;
   FP_DECL_Q (A);
index 85380471c5ec0fc57bc63134a8f7accd6f525097..57545dd7edbb8cf7e5b78b99e8af53115738acab 100644 (file)
 #endif
 
 #define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW)
+#define SW_OR_HW_ISA3_1(SW, HW) (__builtin_cpu_supports ("arch_3_1") ? HW : SW)
 
 /* Resolvers.  */
-
-/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
-   and __floatuntikf.  There is no ISA 3.0 instruction that converts between
-   128-bit integer types and 128-bit IEEE floating point, or vice versa.  So
-   use the emulator functions for these conversions.  */
-
 static __typeof__ (__addkf3_sw) *
 __addkf3_resolve (void)
 {
@@ -102,6 +97,18 @@ __floatdikf_resolve (void)
   return SW_OR_HW (__floatdikf_sw, __floatdikf_hw);
 }
 
+static __typeof__ (__floattikf_sw) *
+__floattikf_resolve (void)
+{
+  return SW_OR_HW_ISA3_1 (__floattikf_sw, __floattikf_hw);
+}
+
+static __typeof__ (__floatuntikf_sw) *
+__floatuntikf_resolve (void)
+{
+  return SW_OR_HW_ISA3_1 (__floatuntikf_sw, __floatuntikf_hw);
+}
+
 static __typeof__ (__floatunsikf_sw) *
 __floatunsikf_resolve (void)
 {
@@ -114,6 +121,19 @@ __floatundikf_resolve (void)
   return SW_OR_HW (__floatundikf_sw, __floatundikf_hw);
 }
 
+
+static __typeof__ (__fixkfti_sw) *
+__fixkfti_resolve (void)
+{
+  return SW_OR_HW_ISA3_1 (__fixkfti_sw, __fixkfti_hw);
+}
+
+static __typeof__ (__fixunskfti_sw) *
+__fixunskfti_resolve (void)
+{
+  return SW_OR_HW_ISA3_1 (__fixunskfti_sw, __fixunskfti_hw);
+}
+
 static __typeof__ (__fixkfsi_sw) *
 __fixkfsi_resolve (void)
 {
@@ -303,6 +323,18 @@ TFtype __floatsikf (SItype_ppc)
 TFtype __floatdikf (DItype_ppc)
   __attribute__ ((__ifunc__ ("__floatdikf_resolve")));
 
+TFtype __floattikf (TItype_ppc)
+  __attribute__ ((__ifunc__ ("__floattikf_resolve")));
+
+TFtype __floatuntikf (UTItype_ppc)
+  __attribute__ ((__ifunc__ ("__floatuntikf_resolve")));
+
+TItype_ppc __fixkfti (TFtype)
+  __attribute__ ((__ifunc__ ("__fixkfti_resolve")));
+
+UTItype_ppc __fixunskfti (TFtype)
+  __attribute__ ((__ifunc__ ("__fixunskfti_resolve")));
+
 TFtype __floatunsikf (USItype_ppc)
   __attribute__ ((__ifunc__ ("__floatunsikf_resolve")));
 
diff --git a/libgcc/config/rs6000/float128-p10.c b/libgcc/config/rs6000/float128-p10.c
new file mode 100644 (file)
index 0000000..7f5d317
--- /dev/null
@@ -0,0 +1,71 @@
+/* Automatic switching between software and hardware IEEE 128-bit
+   ISA 3.1 floating-point emulation for PowerPC.
+
+   Copyright (C) 2016-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Carl Love (cel@us.ibm.com)
+   Code is based on the main soft-fp library written by:
+       Richard Henderson (rth@cygnus.com) and
+       Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Note, the hardware conversion instructions for 128-bit integers are
+   supported for ISA 3.1 and later.  Only compile this file with -mcpu=power10
+   or newer support.  */
+
+#include <soft-fp.h>
+#include <quad-float128.h>
+
+#ifndef __FLOAT128_HARDWARE__
+#error "This module must be compiled with IEEE 128-bit hardware support"
+#endif
+
+#ifndef _ARCH_PWR10
+#error "This module must be compiled for Power 10 support"
+#endif
+
+TFtype
+__floattikf_hw (TItype_ppc a)
+{
+  return (TFtype) a;
+}
+
+TFtype
+__floatuntikf_hw (UTItype_ppc a)
+{
+  return (TFtype) a;
+}
+
+TItype_ppc
+__fixkfti_hw (TFtype a)
+{
+  return (TItype_ppc) a;
+}
+
+UTItype_ppc
+__fixunskfti_hw (TFtype a)
+{
+  return (UTItype_ppc) a;
+}
index d9a089ff9bacec038081ce258b7d46f3c180a038..c0fcddb1959b328f459c56e0a580eac6137e7e6d 100644 (file)
@@ -8,6 +8,10 @@ s/__fixtfsi/__fixkfsi/g
 s/__fixunstfdi/__fixunskfdi/g
 s/__fixunstfsi/__fixunskfsi/g
 s/__floatditf/__floatdikf/g
+s/__floattitf/__floattikf/g
+s/__floatuntitf/__floatuntikf/g
+s/__fixtfti/__fixkfti/g
+s/__fixunstfti/__fixunskfti/g
 s/__floatsitf/__floatsikf/g
 s/__floatunditf/__floatundikf/g
 s/__floatunsitf/__floatunsikf/g
index acf36b0c17dd9e1cbd6a5899469fc7559a7d02a8..3d2bf556da1a1164bf085d72430e6abc478b13b5 100644 (file)
@@ -8,6 +8,10 @@ s/__fixtfsi/__fixkfsi_sw/g
 s/__fixunstfdi/__fixunskfdi_sw/g
 s/__fixunstfsi/__fixunskfsi_sw/g
 s/__floatditf/__floatdikf_sw/g
+s/__floattitf/__floattikf_sw/g
+s/__floatuntitf/__floatuntikf_sw/g
+s/__fixtfti/__fixkfti_sw/g
+s/__fixunstfti/__fixunskfti_sw/g
 s/__floatsitf/__floatsikf_sw/g
 s/__floatunditf/__floatundikf_sw/g
 s/__floatunsitf/__floatunsikf_sw/g
similarity index 96%
rename from libgcc/config/rs6000/floattikf.c
rename to libgcc/config/rs6000/floattikf-sw.c
index cc5c7ca0fd050a99f44e1767f8bf0638bcb91ab5..4e1786cd229058832f1ed72a6b41af2272663bd6 100644 (file)
@@ -5,7 +5,7 @@
    This file is part of the GNU C Library.
    Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
    Code is based on the main soft-fp library written by:
-          Uros Bizjak (ubizjak@gmail.com).
+          Uros Bizjak (ubizjak@gmail.com).
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 #include "quad-float128.h"
 
 TFtype
-__floattikf (TItype i)
+__floattikf_sw (TItype i)
 {
   FP_DECL_EX;
   FP_DECL_Q (A);
similarity index 96%
rename from libgcc/config/rs6000/floatuntikf.c
rename to libgcc/config/rs6000/floatuntikf-sw.c
index 96f2d3bdcb89b6269de80c6fc37cd1aeb2adf0e4..c4b814ddd682c2691eb2477b1dc5585e5fd5d270 100644 (file)
@@ -5,7 +5,7 @@
    This file is part of the GNU C Library.
    Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
    Code is based on the main soft-fp library written by:
-          Uros Bizjak (ubizjak@gmail.com).
+          Uros Bizjak (ubizjak@gmail.com).
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 #include "quad-float128.h"
 
 TFtype
-__floatuntikf (UTItype i)
+__floatuntikf_sw (UTItype i)
 {
   FP_DECL_EX;
   FP_DECL_Q (A);
index 5beb1531d2b90ce637ea5d7784353d6a9f997456..c7f2b77ed357fd088062320bea04c3fd22d0a8bc 100644 (file)
@@ -88,19 +88,22 @@ extern USItype_ppc __fixunskfsi_sw (TFtype);
 extern UDItype_ppc __fixunskfdi_sw (TFtype);
 extern TFtype __floatsikf_sw (SItype_ppc);
 extern TFtype __floatdikf_sw (DItype_ppc);
+#ifdef _ARCH_PPC64
+extern TFtype __floattikf_sw (TItype_ppc);
+#endif
 extern TFtype __floatunsikf_sw (USItype_ppc);
 extern TFtype __floatundikf_sw (UDItype_ppc);
+#ifdef _ARCH_PPC64
+extern TFtype __floatuntikf_sw (UTItype_ppc);
+extern TItype_ppc __fixkfti_sw (TFtype);
+extern UTItype_ppc __fixunskfti_sw (TFtype);
+#endif
 extern IBM128_TYPE __extendkftf2_sw (TFtype);
 extern TFtype __trunctfkf2_sw (IBM128_TYPE);
 extern TCtype __mulkc3_sw (TFtype, TFtype, TFtype, TFtype);
 extern TCtype __divkc3_sw (TFtype, TFtype, TFtype, TFtype);
 
 #ifdef _ARCH_PPC64
-/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
-   and __floatuntikf.  There is no ISA 3.0 instruction that converts between
-   128-bit integer types and 128-bit IEEE floating point, or vice versa.  So
-   use the emulator functions for these conversions.  */
-
 extern TItype_ppc __fixkfti (TFtype);
 extern UTItype_ppc __fixunskfti (TFtype);
 extern TFtype __floattikf (TItype_ppc);
@@ -131,8 +134,16 @@ extern USItype_ppc __fixunskfsi_hw (TFtype);
 extern UDItype_ppc __fixunskfdi_hw (TFtype);
 extern TFtype __floatsikf_hw (SItype_ppc);
 extern TFtype __floatdikf_hw (DItype_ppc);
+#ifdef _ARCH_PPC64
+extern TFtype __floattikf_hw (TItype_ppc);
+#endif
 extern TFtype __floatunsikf_hw (USItype_ppc);
 extern TFtype __floatundikf_hw (UDItype_ppc);
+#ifdef _ARCH_PPC64
+extern TFtype __floatuntikf_hw (UTItype_ppc);
+extern TItype_ppc __fixkfti_hw (TFtype);
+extern UTItype_ppc __fixunskfti_hw (TFtype);
+#endif
 extern IBM128_TYPE __extendkftf2_hw (TFtype);
 extern TFtype __trunctfkf2_hw (IBM128_TYPE);
 extern TCtype __mulkc3_hw (TFtype, TFtype, TFtype, TFtype);
@@ -163,8 +174,16 @@ extern USItype_ppc __fixunskfsi (TFtype);
 extern UDItype_ppc __fixunskfdi (TFtype);
 extern TFtype __floatsikf (SItype_ppc);
 extern TFtype __floatdikf (DItype_ppc);
+#ifdef _ARCH_PPC64
+extern TFtype __floattikf (TItype_ppc);
+#endif
 extern TFtype __floatunsikf (USItype_ppc);
 extern TFtype __floatundikf (UDItype_ppc);
+#ifdef _ARCH_PPC64
+extern TFtype __floatuntikf (UTItype_ppc);
+extern TItype_ppc __fixkfti (TFtype);
+extern UTItype_ppc __fixunskfti (TFtype);
+#endif
 extern IBM128_TYPE __extendkftf2 (TFtype);
 extern TFtype __trunctfkf2 (IBM128_TYPE);
 
index d745f0d82e189f9a7741ffbf9910c72c1059b9a9..b09b5664af0ec31fc81276dabd2ea4d99ab43f36 100644 (file)
@@ -31,7 +31,8 @@ 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 \
+fp128_ppc_funcs                = floattikf-sw floatuntikf-sw \
+                         fixkfti-sw fixunskfti-sw \
                          extendkftf2-sw trunctfkf2-sw \
                          sfp-exceptions _mulkc3 _divkc3 _powikf2
 
@@ -47,13 +48,16 @@ fp128_ppc_obj               = $(fp128_ppc_static_obj) $(fp128_ppc_shared_obj)
 
 # All functions
 fp128_funcs            = $(fp128_softfp_funcs) $(fp128_ppc_funcs) \
-                         $(fp128_hw_funcs) $(fp128_ifunc_funcs)
+                         $(fp128_hw_funcs) $(fp128_ifunc_funcs) \
+                         $(fp128_3_1_hw_funcs)
 
 fp128_src              = $(fp128_softfp_src) $(fp128_ppc_src) \
-                         $(fp128_hw_src) $(fp128_ifunc_src)
+                         $(fp128_hw_src) $(fp128_ifunc_src) \
+                         $(fp128_3_1_hw_src)
 
 fp128_obj              = $(fp128_softfp_obj) $(fp128_ppc_obj) \
-                         $(fp128_hw_obj) $(fp128_ifunc_obj)
+                         $(fp128_hw_obj) $(fp128_ifunc_obj) \
+                         $(fp128_3_1_hw_obj)
 
 fp128_sed              = $(srcdir)/config/rs6000/float128-sed$(fp128_sed_hw)
 fp128_dep              = $(fp128_sed) $(srcdir)/config/rs6000/t-float128
index d64ca4dd69438bb1a01cef65ee2a8de534c71aba..c0827366cc48ec6b97f43cccc4ef0d15dce4975b 100644 (file)
@@ -13,6 +13,13 @@ fp128_hw_static_obj  = $(addsuffix $(objext),$(fp128_hw_funcs))
 fp128_hw_shared_obj    = $(addsuffix _s$(objext),$(fp128_hw_funcs))
 fp128_hw_obj           = $(fp128_hw_static_obj) $(fp128_hw_shared_obj)
 
+# New functions for ISA 3.1 hardware support
+fp128_3_1_hw_funcs     = float128-p10
+fp128_3_1_hw_src       = $(srcdir)/config/rs6000/float128-p10.c
+fp128_3_1_hw_static_obj        = $(addsuffix $(objext),$(fp128_3_1_hw_funcs))
+fp128_3_1_hw_shared_obj        = $(addsuffix _s$(objext),$(fp128_3_1_hw_funcs))
+fp128_3_1_hw_obj       = $(fp128_3_1_hw_static_obj) $(fp128_3_1_hw_shared_obj)
+
 fp128_ifunc_funcs      = float128-ifunc
 fp128_ifunc_src                = $(srcdir)/config/rs6000/float128-ifunc.c
 fp128_ifunc_static_obj = float128-ifunc$(objext)
@@ -30,9 +37,18 @@ FP128_CFLAGS_HW               = -Wno-type-limits -mvsx -mfloat128 \
                           -I$(srcdir)/config/rs6000 \
                           $(FLOAT128_HW_INSNS)
 
+FP128_3_1_CFLAGS_HW     = -Wno-type-limits -mvsx -mcpu=power10 \
+                          -mfloat128-hardware -mno-gnu-attribute \
+                          -I$(srcdir)/soft-fp \
+                          -I$(srcdir)/config/rs6000 \
+                          $(FLOAT128_HW_INSNS)
+
 $(fp128_hw_obj)                 : INTERNAL_CFLAGS += $(FP128_CFLAGS_HW)
 $(fp128_hw_obj)                 : $(srcdir)/config/rs6000/t-float128-hw
 
+$(fp128_3_1_hw_obj)     : INTERNAL_CFLAGS += $(FP128_3_1_CFLAGS_HW)
+$(fp128_3_1_hw_obj)     : $(srcdir)/config/rs6000/t-float128-p10-hw
+
 $(fp128_ifunc_obj)      : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW)
 $(fp128_ifunc_obj)      : $(srcdir)/config/rs6000/t-float128-hw
 
diff --git a/libgcc/config/rs6000/t-float128-p10-hw b/libgcc/config/rs6000/t-float128-p10-hw
new file mode 100644 (file)
index 0000000..de36227
--- /dev/null
@@ -0,0 +1,24 @@
+# Support for adding __float128 hardware support to the powerpc.
+# Tell the float128 functions that the ISA 3.1 hardware support can
+# be compiled it to be selected via IFUNC functions.
+
+FLOAT128_HW_INSNS      = -DFLOAT128_HW_INSNS
+
+# New functions for hardware support
+
+fp128_3_1_hw_funcs     = float128-p10
+fp128_3_1_hw_src       = $(srcdir)/config/rs6000/float128-p10.c
+fp128_3_1_hw_static_obj        = $(addsuffix $(objext),$(fp128_3_1_hw_funcs))
+fp128_3_1_hw_shared_obj        = $(addsuffix _s$(objext),$(fp128_3_1_hw_funcs))
+fp128_3_1_hw_obj       = $(fp128_3_1_hw_static_obj) $(fp128_3_1_hw_shared_obj)
+
+# Build the hardware support functions with appropriate hardware support
+FP128_3_1_CFLAGS_HW     = -Wno-type-limits -mvsx -mfloat128 \
+                          -mpower10 \
+                          -mfloat128-hardware -mno-gnu-attribute \
+                          -I$(srcdir)/soft-fp \
+                          -I$(srcdir)/config/rs6000 \
+                          $(FLOAT128_HW_INSNS)
+
+$(fp128_3_1_hw_obj)             : INTERNAL_CFLAGS += $(FP128_3_1_CFLAGS_HW)
+$(fp128_3_1_hw_obj)             : $(srcdir)/config/rs6000/t-float128-p10-hw
index dd3afb2c95761f53dfa5bc71434e944369ef8a98..ce05e0dd48b7a419e7aff4a85acd67349c6e38d4 100755 (executable)
@@ -5263,6 +5263,43 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128_hw" >&5
 $as_echo "$libgcc_cv_powerpc_float128_hw" >&6; }
   CFLAGS="$saved_CFLAGS"
+
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -mpower10 -mfloat128-hardware"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PowerPC ISA 3.1 to build hardware __float128 libraries" >&5
+$as_echo_n "checking for PowerPC ISA 3.1 to build hardware __float128 libraries... " >&6; }
+if ${libgcc_cv_powerpc_float128_hw+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/auxv.h>
+     #ifndef AT_PLATFORM
+     #error "AT_PLATFORM is not defined"
+     #endif
+     #ifndef __BUILTIN_CPU_SUPPORTS__
+     #error "__builtin_cpu_supports is not available"
+     #endif
+     vector unsigned char add (vector unsigned char a, vector unsigned char b)
+     {
+       vector unsigned char ret;
+       __asm__ ("xscvsqqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
+       return ret;
+     }
+     void *add_resolver (void) { return (void *) add; }
+     __float128 add_ifunc (__float128, __float128)
+       __attribute__ ((__ifunc__ ("add_resolver")));
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgcc_cv_powerpc_3_1_float128_hw=yes
+else
+  libgcc_cv_powerpc_3_1_float128_hw=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128_hw" >&5
+  $as_echo "$libgcc_cv_powerpc_float128_hw" >&6; }
+  CFLAGS="$saved_CFLAGS"
 esac
 
 # Collect host-machine-specific information.
index 10ffb0464156cded1b2c386ff61d198216e2e399..bc315dec7e403218d668c48b6d97b0333ab018bb 100644 (file)
@@ -458,6 +458,31 @@ powerpc*-*-linux*)
     [libgcc_cv_powerpc_float128_hw=yes],
     [libgcc_cv_powerpc_float128_hw=no])])
   CFLAGS="$saved_CFLAGS"
+
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -mpower10 -mfloat128-hardware"
+  AC_CACHE_CHECK([for PowerPC ISA 3.1 to build hardware __float128 libraries],
+                [libgcc_cv_powerpc_float128_hw],
+                [AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE([#include <sys/auxv.h>
+     #ifndef AT_PLATFORM
+     #error "AT_PLATFORM is not defined"
+     #endif
+     #ifndef __BUILTIN_CPU_SUPPORTS__
+     #error "__builtin_cpu_supports is not available"
+     #endif
+     vector unsigned char add (vector unsigned char a, vector unsigned char b)
+     {
+       vector unsigned char ret;
+       __asm__ ("xscvsqqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
+       return ret;
+     }
+     void *add_resolver (void) { return (void *) add; }
+     __float128 add_ifunc (__float128, __float128)
+       __attribute__ ((__ifunc__ ("add_resolver")));])],
+    [libgcc_cv_powerpc_3_1_float128_hw=yes],
+    [libgcc_cv_powerpc_3_1_float128_hw=no])])
+  CFLAGS="$saved_CFLAGS"
 esac
 
 # Collect host-machine-specific information.