From 9090f4807161876033f6bf0e1133364b38d91865 Mon Sep 17 00:00:00 2001 From: Carl Love Date: Wed, 21 Apr 2021 18:07:39 -0400 Subject: [PATCH] Conversions between 128-bit integer and floating point values. 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-08 Carl Love 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 (floatti2, floatunsti2, fix_truncti2, fixuns_truncti2): 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. --- gcc/config/rs6000/rs6000.c | 8 +- gcc/config/rs6000/rs6000.md | 36 +++ .../gcc.target/powerpc/fp128_conversions.c | 294 ++++++++++++++++++ .../gcc.target/powerpc/int_128bit-runnable.c | 13 +- libgcc/config.host | 4 + .../config/rs6000/{fixkfti.c => fixkfti-sw.c} | 4 +- .../rs6000/{fixunskfti.c => fixunskfti-sw.c} | 4 +- libgcc/config/rs6000/float128-ifunc.c | 44 ++- libgcc/config/rs6000/float128-p10.c | 71 +++++ libgcc/config/rs6000/float128-sed | 4 + libgcc/config/rs6000/float128-sed-hw | 4 + .../rs6000/{floattikf.c => floattikf-sw.c} | 4 +- .../{floatuntikf.c => floatuntikf-sw.c} | 4 +- libgcc/config/rs6000/quad-float128.h | 17 +- libgcc/config/rs6000/t-float128 | 12 +- libgcc/config/rs6000/t-float128-hw | 16 + libgcc/config/rs6000/t-float128-p10-hw | 24 ++ libgcc/configure | 37 +++ libgcc/configure.ac | 25 ++ 19 files changed, 589 insertions(+), 36 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/fp128_conversions.c rename libgcc/config/rs6000/{fixkfti.c => fixkfti-sw.c} (96%) rename libgcc/config/rs6000/{fixunskfti.c => fixunskfti-sw.c} (96%) create mode 100644 libgcc/config/rs6000/float128-p10.c rename libgcc/config/rs6000/{floattikf.c => floattikf-sw.c} (96%) rename libgcc/config/rs6000/{floatuntikf.c => floatuntikf-sw.c} (96%) create mode 100644 libgcc/config/rs6000/t-float128-p10-hw diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 328dc10a61b..75c2cc4f8b7 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -11014,10 +11014,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"); } } diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 3f59b544f6a..89c70f4a64e 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -6441,6 +6441,42 @@ xscvsxddp %x0,%x1" [(set_attr "type" "fp")]) +(define_insn "floatti2" + [(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 "floatunsti2" + [(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_truncti2" + [(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_truncti2" + [(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 index 00000000000..c20282fa0e0 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c @@ -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 +#include +#include +#include +#include + +#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; +} diff --git a/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c b/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c index 9f7dbc6cc75..94dbd2b6230 100644 --- a/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c +++ b/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c @@ -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 } } */ diff --git a/libgcc/config.host b/libgcc/config.host index f808b61be70..50f00062232 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -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 ;; diff --git a/libgcc/config/rs6000/fixkfti.c b/libgcc/config/rs6000/fixkfti-sw.c similarity index 96% rename from libgcc/config/rs6000/fixkfti.c rename to libgcc/config/rs6000/fixkfti-sw.c index 0d965bc6253..cc000fca0f8 100644 --- a/libgcc/config/rs6000/fixkfti.c +++ b/libgcc/config/rs6000/fixkfti-sw.c @@ -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); diff --git a/libgcc/config/rs6000/fixunskfti.c b/libgcc/config/rs6000/fixunskfti-sw.c similarity index 96% rename from libgcc/config/rs6000/fixunskfti.c rename to libgcc/config/rs6000/fixunskfti-sw.c index f285b4e3fbd..7a04d1a489a 100644 --- a/libgcc/config/rs6000/fixunskfti.c +++ b/libgcc/config/rs6000/fixunskfti-sw.c @@ -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); diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c index 85380471c5e..57545dd7edb 100644 --- a/libgcc/config/rs6000/float128-ifunc.c +++ b/libgcc/config/rs6000/float128-ifunc.c @@ -46,14 +46,9 @@ #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 index 00000000000..7f5d317631a --- /dev/null +++ b/libgcc/config/rs6000/float128-p10.c @@ -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 + . */ + +/* 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 +#include + +#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; +} diff --git a/libgcc/config/rs6000/float128-sed b/libgcc/config/rs6000/float128-sed index d9a089ff9ba..c0fcddb1959 100644 --- a/libgcc/config/rs6000/float128-sed +++ b/libgcc/config/rs6000/float128-sed @@ -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 diff --git a/libgcc/config/rs6000/float128-sed-hw b/libgcc/config/rs6000/float128-sed-hw index acf36b0c17d..3d2bf556da1 100644 --- a/libgcc/config/rs6000/float128-sed-hw +++ b/libgcc/config/rs6000/float128-sed-hw @@ -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 diff --git a/libgcc/config/rs6000/floattikf.c b/libgcc/config/rs6000/floattikf-sw.c similarity index 96% rename from libgcc/config/rs6000/floattikf.c rename to libgcc/config/rs6000/floattikf-sw.c index cc5c7ca0fd0..4e1786cd229 100644 --- a/libgcc/config/rs6000/floattikf.c +++ b/libgcc/config/rs6000/floattikf-sw.c @@ -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); diff --git a/libgcc/config/rs6000/floatuntikf.c b/libgcc/config/rs6000/floatuntikf-sw.c similarity index 96% rename from libgcc/config/rs6000/floatuntikf.c rename to libgcc/config/rs6000/floatuntikf-sw.c index 96f2d3bdcb8..c4b814ddd68 100644 --- a/libgcc/config/rs6000/floatuntikf.c +++ b/libgcc/config/rs6000/floatuntikf-sw.c @@ -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); diff --git a/libgcc/config/rs6000/quad-float128.h b/libgcc/config/rs6000/quad-float128.h index 5beb1531d2b..c4d775b4ad3 100644 --- a/libgcc/config/rs6000/quad-float128.h +++ b/libgcc/config/rs6000/quad-float128.h @@ -88,19 +88,18 @@ extern USItype_ppc __fixunskfsi_sw (TFtype); extern UDItype_ppc __fixunskfdi_sw (TFtype); extern TFtype __floatsikf_sw (SItype_ppc); extern TFtype __floatdikf_sw (DItype_ppc); +extern TFtype __floattikf_sw (TItype_ppc); extern TFtype __floatunsikf_sw (USItype_ppc); extern TFtype __floatundikf_sw (UDItype_ppc); +extern TFtype __floatuntikf_sw (UTItype_ppc); +extern TItype_ppc __fixkfti_sw (TFtype); +extern UTItype_ppc __fixunskfti_sw (TFtype); 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 +130,12 @@ extern USItype_ppc __fixunskfsi_hw (TFtype); extern UDItype_ppc __fixunskfdi_hw (TFtype); extern TFtype __floatsikf_hw (SItype_ppc); extern TFtype __floatdikf_hw (DItype_ppc); +extern TFtype __floattikf_hw (TItype_ppc); extern TFtype __floatunsikf_hw (USItype_ppc); extern TFtype __floatundikf_hw (UDItype_ppc); +extern TFtype __floatuntikf_hw (UTItype_ppc); +extern TItype_ppc __fixkfti_hw (TFtype); +extern UTItype_ppc __fixunskfti_hw (TFtype); extern IBM128_TYPE __extendkftf2_hw (TFtype); extern TFtype __trunctfkf2_hw (IBM128_TYPE); extern TCtype __mulkc3_hw (TFtype, TFtype, TFtype, TFtype); @@ -163,8 +166,12 @@ extern USItype_ppc __fixunskfsi (TFtype); extern UDItype_ppc __fixunskfdi (TFtype); extern TFtype __floatsikf (SItype_ppc); extern TFtype __floatdikf (DItype_ppc); +extern TFtype __floattikf (TItype_ppc); extern TFtype __floatunsikf (USItype_ppc); extern TFtype __floatundikf (UDItype_ppc); +extern TFtype __floatuntikf (UTItype_ppc); +extern TItype_ppc __fixkfti (TFtype); +extern UTItype_ppc __fixunskfti (TFtype); extern IBM128_TYPE __extendkftf2 (TFtype); extern TFtype __trunctfkf2 (IBM128_TYPE); diff --git a/libgcc/config/rs6000/t-float128 b/libgcc/config/rs6000/t-float128 index d745f0d82e1..b09b5664af0 100644 --- a/libgcc/config/rs6000/t-float128 +++ b/libgcc/config/rs6000/t-float128 @@ -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 diff --git a/libgcc/config/rs6000/t-float128-hw b/libgcc/config/rs6000/t-float128-hw index d64ca4dd694..c0827366cc4 100644 --- a/libgcc/config/rs6000/t-float128-hw +++ b/libgcc/config/rs6000/t-float128-hw @@ -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 index 00000000000..de36227c3d1 --- /dev/null +++ b/libgcc/config/rs6000/t-float128-p10-hw @@ -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 diff --git a/libgcc/configure b/libgcc/configure index dd3afb2c957..ce05e0dd48b 100755 --- a/libgcc/configure +++ b/libgcc/configure @@ -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 + #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. diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 10ffb046415..bc315dec7e4 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -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 + #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.