Message ID | 084b020dba585c8b7a22dc3a3624239cc17bdfe2.camel@us.ibm.com |
---|---|
State | New |
Headers | show |
Series | rs6000, 128-bit Binary Integer Operations | expand |
On Tue, 2020-08-11 at 12:23 -0700, Carl Love wrote: > Segher, Will: > > Patch 5 adds the 128-bit integer to/from 128-floating point > conversions. This patch has to invoke the routines to use the 128-bit > hardware instructions if on Power 10 or use software routines if > running on a pre Power 10 system via the resolve function. > > Carl > > ----------------------------------------------------------- > Conversions between 128-bit integer and floating point values. > > gcc/ChangeLog > > 2020-08-10 Carl Love <cel@us.ibm.com> > config/rs6000/rs6000.md (floatunsti<mode>2, > fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add > define_insn for mode IEEE 128. s/Add/Update/ missing floatti<mode>2 > libgcc/config/rs6000/fixkfi-sw.c: New file. > libgcc/config/rs6000/fixkfi.c: Remove file. > libgcc/config/rs6000/fixunskfi-sw.c: New file. > libgcc/config/rs6000/fixunskfi.c: Remove file. ... rename to ... ? > libgcc/config/rs6000/float128-hw.c (__floattikf_hw, > __floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw): > New functions. > libgcc/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. > libgcc/config/rs6000/float128-sed (floattitf, __floatuntitf, > __fixtfti, __fixunstfti): Add editor commands to change > names. > libgcc/config/rs6000/float128-sed-hw (__floattitf, > __floatuntitf, __fixtfti, __fixunstfti): Add editor commands > to change names. > libgcc/config/rs6000/floattikf-sw.c: New file. > libgcc/config/rs6000/floattikf.c: Remove file. > libgcc/config/rs6000/floatuntikf-sw.c: New file. > libgcc/config/rs6000/floatuntikf.c: Remove file. > libgcc/config/rs6000/floatuntikf-sw.c: New file. floatuntikf-sw was so good, it was added twice. ... rename to ... ? > libgcc/config/rs6000/quaad-float128.h (__floattikf_sw, One 'a' in quad. > __floatuntikf_sw, __fixkfti_sw, __fixunskfti_sw, __floattikf_hw, > __floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw, __floattikf, > __floatuntikf, __fixkfti, __fixunskfti): New extern declarations. Tab in there that should not be. > libgcc/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. Perhaps libgcc/config/rs6000/t-float128 (floattikf, floatuntikf, fixkfti, fixunskfti): Rename to (floattikf-sw, floatuntikf-sw, fixkfti-sw, fixunskfti-sw) > > gcc/testsuite/ChangeLog > > 2020-08-10 Carl Love <cel@us.ibm.com> > gcc.target/powerpc/fl128_conversions.c: New file. New test. or just New. > --- > gcc/config/rs6000/rs6000.md | 36 +++ > .../gcc.target/powerpc/fp128_conversions.c | 287 ++++++++++++++++++ > .../config/rs6000/{fixkfti.c => fixkfti-sw.c} | 4 +- > .../rs6000/{fixunskfti.c => fixunskfti-sw.c} | 4 +- > libgcc/config/rs6000/float128-hw.c | 24 ++ > libgcc/config/rs6000/float128-ifunc.c | 44 ++- > 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 | 3 +- > 12 files changed, 415 insertions(+), 20 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%) > rename libgcc/config/rs6000/{floattikf.c => floattikf-sw.c} (96%) > rename libgcc/config/rs6000/{floatuntikf.c => floatuntikf-sw.c} (96%) > > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > index 43b620ae1c0..3853ebd4195 100644 > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -6390,6 +6390,42 @@ > 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 ok. > 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..f0336e6f1fc > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c > @@ -0,0 +1,287 @@ > +/* { dg-do run } */ > +/* { dg-require-effective-target power10_hw } */ > +/* { dg-options "-mdejagnu-cpu=power10" } */ > + > +/* 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 { target { ppc_native_128bit } } } } */ > +/* { dg-final { scan-assembler-times {\mxscvuqqp\M} 1 { target { ppc_native_128bit } } } } */ > +/* { dg-final { scan-assembler-times {\mxscvqpsqz\M} 1 { target { ppc_native_128bit } } } } */ > +/* { dg-final { scan-assembler-times {\mxscvqpuqz\M} 1 { target { ppc_native_128bit } } } } */ > + > +#include <stdio.h> > +#include <math.h> > +#include <fenv.h> > +#include <stdlib.h> > +#include <wchar.h> > + > +#define DEBUG 1 Turn off Debug. > + > +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; So.. Should this test be duplicated and updated to test both of those -mabi=<foo> options? And the default? > +} > + > +__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, messages about uses IBM long double, no binary output What does that mean? What messages? Clarify. > + 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 > + } > + > + /* Currently printing 128-bit float does not work correctly */ What does that mean? (Limitations in printing the type? Perhaps just a comment at the printf that clarifies you are printing the values in hex for reasons..) Here and elsewhere. > + 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 > + } > + > + /* Currently printing 128-bit float does not work correctly */ > + 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 > + } > + > + /* Currently printing 128-bit float does not work correctly */ > + 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; > +} ok > 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 a22286228aa..d6bbbf889b7 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); ok > 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 ab232d92d24..d803936e48a 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); ok > diff --git a/libgcc/config/rs6000/float128-hw.c b/libgcc/config/rs6000/float128-hw.c > index 8705b53e22a..be8bd07e853 100644 > --- a/libgcc/config/rs6000/float128-hw.c > +++ b/libgcc/config/rs6000/float128-hw.c > @@ -86,6 +86,30 @@ __floatdikf_hw (DItype_ppc a) > return (TFtype) a; > } > > +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; > +} > + > TFtype > __floatundikf_hw (UDItype_ppc a) > { ok. > diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c > index c2f65912a74..c221be2c864 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"))); > ok > 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 ok > 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 4e8c40cfbe4..110706352bb 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 8bfba4267d4..5e712a67e26 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 32ef328a8ea..24712b9277f 100644 > --- a/libgcc/config/rs6000/quad-float128.h > +++ b/libgcc/config/rs6000/quad-float128.h > @@ -87,19 +87,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); > @@ -130,8 +129,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); > @@ -162,8 +165,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); ok > diff --git a/libgcc/config/rs6000/t-float128 b/libgcc/config/rs6000/t-float128 > index d5413445189..325b22fd49e 100644 > --- a/libgcc/config/rs6000/t-float128 > +++ b/libgcc/config/rs6000/t-float128 > @@ -23,7 +23,8 @@ fp128_softfp_shared_obj = $(addsuffix -sw_s$(objext),$(fp128_softfp_funcs)) > fp128_softfp_obj = $(fp128_softfp_static_obj) $(fp128_softfp_shared_obj) > > # 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 ok.
Hi! On Tue, Aug 11, 2020 at 12:23:13PM -0700, Carl Love wrote: [ Perfect stuff, or I don't see anything anyway! ] Okay for trunk. Thank you! Segher
On Tue, 2020-08-11 at 12:23 -0700, Carl Love wrote: > Segher, Will: > > Patch 5 adds the 128-bit integer to/from 128-floating point > conversions. This patch has to invoke the routines to use the 128-bit > hardware instructions if on Power 10 or use software routines if > running on a pre Power 10 system via the resolve function. > > Carl Some mostly cosmetic bits below. Thanks -Will > > ----------------------------------------------------------- > Conversions between 128-bit integer and floating point values. > > gcc/ChangeLog > > 2020-08-10 Carl Love <cel@us.ibm.com> > config/rs6000/rs6000.md (floatunsti<mode>2, > fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add > define_insn for mode IEEE 128. also floatti<mode>2 > libgcc/config/rs6000/fixkfi-sw.c: New file. > libgcc/config/rs6000/fixkfi.c: Remove file. Should that be fixkfti-sw.c (missing t)? Adjust to indicate this is a rename libgcc/config/rs6000/fixkfti.c: Rename to libgcc/config/rs6000/fixkfti-sw.c > libgcc/config/rs6000/fixunskfi-sw.c: New file. > libgcc/config/rs6000/fixunskfi.c: Remove file. > libgcc/config/rs6000/float128-hw.c (__floattikf_hw, > __floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw): > New functions. > libgcc/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. > libgcc/config/rs6000/float128-sed (floattitf, __floatuntitf, > __fixtfti, __fixunstfti): Add editor commands to change > names. > libgcc/config/rs6000/float128-sed-hw (__floattitf, > __floatuntitf, __fixtfti, __fixunstfti): Add editor commands > to change names. > libgcc/config/rs6000/floattikf-sw.c: New file. > libgcc/config/rs6000/floattikf.c: Remove file. > libgcc/config/rs6000/floatuntikf-sw.c: New file. > libgcc/config/rs6000/floatuntikf.c: Remove file. > libgcc/config/rs6000/floatuntikf-sw.c: New file. > libgcc/config/rs6000/quaad-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. no tab. > libgcc/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. > > gcc/testsuite/ChangeLog > > 2020-08-10 Carl Love <cel@us.ibm.com> > gcc.target/powerpc/fl128_conversions.c: New file. > --- > gcc/config/rs6000/rs6000.md | 36 +++ > .../gcc.target/powerpc/fp128_conversions.c | 287 ++++++++++++++++++ > .../config/rs6000/{fixkfti.c => fixkfti-sw.c} | 4 +- > .../rs6000/{fixunskfti.c => fixunskfti-sw.c} | 4 +- > libgcc/config/rs6000/float128-hw.c | 24 ++ > libgcc/config/rs6000/float128-ifunc.c | 44 ++- > 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 | 3 +- > 12 files changed, 415 insertions(+), 20 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%) > rename libgcc/config/rs6000/{floattikf.c => floattikf-sw.c} (96%) > rename libgcc/config/rs6000/{floatuntikf.c => floatuntikf-sw.c} (96%) > > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > index 43b620ae1c0..3853ebd4195 100644 > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -6390,6 +6390,42 @@ > 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 > index 00000000000..f0336e6f1fc > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c > @@ -0,0 +1,287 @@ > +/* { dg-do run } */ > +/* { dg-require-effective-target power10_hw } */ > +/* { dg-options "-mdejagnu-cpu=power10" } */ > + > +/* 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 { target { ppc_native_128bit } } } } */ > +/* { dg-final { scan-assembler-times {\mxscvuqqp\M} 1 { target { ppc_native_128bit } } } } */ > +/* { dg-final { scan-assembler-times {\mxscvqpsqz\M} 1 { target { ppc_native_128bit } } } } */ > +/* { dg-final { scan-assembler-times {\mxscvqpuqz\M} 1 { target { ppc_native_128bit } } } } */ > + > +#include <stdio.h> > +#include <math.h> > +#include <fenv.h> > +#include <stdlib.h> > +#include <wchar.h> > + > +#define DEBUG 1 > + Probably turn off the DEBUG. > +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, messages about uses IBM long double, no binary output Could use a few more words.. What messages? > + 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; Extra blank line +space above the "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 The indent for #else should match the #if and #endif. Same elsewhere. > + 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 > + } > + > + /* Currently printing 128-bit float does not work correctly */ > + 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 > + } > + > + /* Currently printing 128-bit float does not work correctly */ > + 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 > + } > + > + /* Currently printing 128-bit float does not work correctly */ > + 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/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 a22286228aa..d6bbbf889b7 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 ab232d92d24..d803936e48a 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). Probably OK. I'd recommend adding a line in the summary paragraph to clarify that you are renaming some of the fix* source files and doing whitespace touch-ups to the same. > > 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-hw.c b/libgcc/config/rs6000/float128-hw.c > index 8705b53e22a..be8bd07e853 100644 > --- a/libgcc/config/rs6000/float128-hw.c > +++ b/libgcc/config/rs6000/float128-hw.c > @@ -86,6 +86,30 @@ __floatdikf_hw (DItype_ppc a) > return (TFtype) a; > } > > +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; > +} > + > TFtype > __floatundikf_hw (UDItype_ppc a) > { > diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c > index c2f65912a74..c221be2c864 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. */ Could add a line in the patch description " Add ifunc resolves for __fixkfti,... " same as appropriate below. > - > 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); > } > > + extra blank line. > +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-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 ok > 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 4e8c40cfbe4..110706352bb 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 8bfba4267d4..5e712a67e26 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 32ef328a8ea..24712b9277f 100644 > --- a/libgcc/config/rs6000/quad-float128.h > +++ b/libgcc/config/rs6000/quad-float128.h > @@ -87,19 +87,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); > @@ -130,8 +129,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); > @@ -162,8 +165,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 d5413445189..325b22fd49e 100644 > --- a/libgcc/config/rs6000/t-float128 > +++ b/libgcc/config/rs6000/t-float128 > @@ -23,7 +23,8 @@ fp128_softfp_shared_obj = $(addsuffix -sw_s$(objext),$(fp128_softfp_funcs)) > fp128_softfp_obj = $(fp128_softfp_static_obj) $(fp128_softfp_shared_obj) > > # 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 ok >
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 43b620ae1c0..3853ebd4195 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -6390,6 +6390,42 @@ 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 index 00000000000..f0336e6f1fc --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c @@ -0,0 +1,287 @@ +/* { dg-do run } */ +/* { dg-require-effective-target power10_hw } */ +/* { dg-options "-mdejagnu-cpu=power10" } */ + +/* 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 { target { ppc_native_128bit } } } } */ +/* { dg-final { scan-assembler-times {\mxscvuqqp\M} 1 { target { ppc_native_128bit } } } } */ +/* { dg-final { scan-assembler-times {\mxscvqpsqz\M} 1 { target { ppc_native_128bit } } } } */ +/* { dg-final { scan-assembler-times {\mxscvqpuqz\M} 1 { target { ppc_native_128bit } } } } */ + +#include <stdio.h> +#include <math.h> +#include <fenv.h> +#include <stdlib.h> +#include <wchar.h> + +#define DEBUG 1 + +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, messages about 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 + } + + /* Currently printing 128-bit float does not work correctly */ + 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 + } + + /* Currently printing 128-bit float does not work correctly */ + 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 + } + + /* Currently printing 128-bit float does not work correctly */ + 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/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 a22286228aa..d6bbbf889b7 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 ab232d92d24..d803936e48a 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-hw.c b/libgcc/config/rs6000/float128-hw.c index 8705b53e22a..be8bd07e853 100644 --- a/libgcc/config/rs6000/float128-hw.c +++ b/libgcc/config/rs6000/float128-hw.c @@ -86,6 +86,30 @@ __floatdikf_hw (DItype_ppc a) return (TFtype) a; } +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; +} + TFtype __floatundikf_hw (UDItype_ppc a) { diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c index c2f65912a74..c221be2c864 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-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 4e8c40cfbe4..110706352bb 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 8bfba4267d4..5e712a67e26 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 32ef328a8ea..24712b9277f 100644 --- a/libgcc/config/rs6000/quad-float128.h +++ b/libgcc/config/rs6000/quad-float128.h @@ -87,19 +87,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); @@ -130,8 +129,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); @@ -162,8 +165,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 d5413445189..325b22fd49e 100644 --- a/libgcc/config/rs6000/t-float128 +++ b/libgcc/config/rs6000/t-float128 @@ -23,7 +23,8 @@ fp128_softfp_shared_obj = $(addsuffix -sw_s$(objext),$(fp128_softfp_funcs)) fp128_softfp_obj = $(fp128_softfp_static_obj) $(fp128_softfp_shared_obj) # 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