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.