diff mbox series

[5/5] Conversions between 128-bit integer and floating point values.

Message ID 467724e7f9f9d7a34626cb630622500aaf3391ae.camel@us.ibm.com
State New
Headers show
Series rs6000, 128-bit Binary Integer Operations | expand

Commit Message

Carl Love Sept. 21, 2020, 11:57 p.m. UTC
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.

Add ifunc resolves for __fixkfti, __floatuntikf_sw, __fixkfti_swn,
__fixunskfti_sw.

The following changes were made to the previous version of the patch: 

Fixed typos in ChangeLog noted by Will.

Turned off debug in test case.

Removed extra blank lines, fixed spacing of #else in the test case.

Added comment to fixunskfti-sw.c about changes made from the original
file fixunskfti.c.

The patch has been tested on

  powerpc64le-unknown-linux-gnu (Power 9 LE)

with no regression errors.

The P10 tests were run by hand on Mambo.

                    Carl Love
---------------------------------------------------------

gcc/ChangeLog

2020-09-21  Carl Love  <cel@us.ibm.com>
	config/rs6000/rs6000.md (floatti<mode>2, floatunsti<mode>2,
	fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add
	define_insn for mode IEEE 128.
	libgcc/config/rs6000/fixkfi-sw.c: New file.
	libgcc/config/rs6000/fixkfi.c: Remove file.
	libgcc/config/rs6000/fixunskfti-sw.c: New file.
	libgcc/config/rs6000/fixunskfti.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.
	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-09-21  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    | 286 ++++++++++++++++++
 .../config/rs6000/{fixkfti.c => fixkfti-sw.c} |   4 +-
 .../rs6000/{fixunskfti.c => fixunskfti-sw.c}  |   7 +-
 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, 417 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} (90%)
 rename libgcc/config/rs6000/{floattikf.c => floattikf-sw.c} (96%)
 rename libgcc/config/rs6000/{floatuntikf.c => floatuntikf-sw.c} (96%)

Comments

will schmidt Sept. 24, 2020, 6:22 p.m. UTC | #1
On Mon, 2020-09-21 at 16:57 -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.
> 
> Add ifunc resolves for __fixkfti, __floatuntikf_sw, __fixkfti_swn,
> __fixunskfti_sw.
> 
> The following changes were made to the previous version of the
> patch: 
> 
> Fixed typos in ChangeLog noted by Will.
> 
> Turned off debug in test case.
> 
> Removed extra blank lines, fixed spacing of #else in the test case.
> 
> Added comment to fixunskfti-sw.c about changes made from the original
> file fixunskfti.c.
> 
> The patch has been tested on
> 
>   powerpc64le-unknown-linux-gnu (Power 9 LE)
> 
> with no regression errors.
> 
> The P10 tests were run by hand on Mambo.
> 
>                     Carl Love
> ---------------------------------------------------------
> 
> gcc/ChangeLog
> 
> 2020-09-21  Carl Love  <cel@us.ibm.com>
> 	config/rs6000/rs6000.md (floatti<mode>2, floatunsti<mode>2,
> 	fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add
> 	define_insn for mode IEEE 128.
ok

> 	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/fixunskfti-sw.c: New file.
> 	libgcc/config/rs6000/fixunskfti.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.
> 	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-09-21  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    | 286
> ++++++++++++++++++
>  .../config/rs6000/{fixkfti.c => fixkfti-sw.c} |   4 +-
>  .../rs6000/{fixunskfti.c => fixunskfti-sw.c}  |   7 +-
>  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, 417 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} (90%)
>  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 694ff70635e..5db5d0b4505 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..dff24e1e2b4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
> @@ -0,0 +1,286 @@
> +/* { 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 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
> +	}
> +
> +  /* 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 90%
> rename from libgcc/config/rs6000/fixunskfti.c
> rename to libgcc/config/rs6000/fixunskfti-sw.c
> index ab232d92d24..5c8b94b8862 100644
> --- a/libgcc/config/rs6000/fixunskfti.c
> +++ b/libgcc/config/rs6000/fixunskfti-sw.c
> @@ -5,7 +5,10 @@
>     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 fixunskfti.c file renamed fixunskfti-sw.c.  Updated the
> +   source file names and made whitespace fixes
> 


^ That should be in the patch description or embedded into the
changelog.



Nothing else jumps out at me below,

Thanks
-Will


>     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 +38,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.  */

This would be good to turn into part of the changelog.

"Provide ifunc resolvers for 128-bit floating point 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
>
Carl Love Oct. 5, 2020, 6:52 p.m. UTC | #2
Will, Segher:

This patch adds support for converting to/from 128-bit integers and
128-bit decimal floating point formats using the new P10 instructions
dcffixqq and dctfixqq.  The new instructions are only used on P10 HW,
otherwise the conversions continue to use the existing SW routines.

The changes from the previous version include:

Fixed up the change log entry issues noted by Will.

Regression tests reran on Power 9 LE with no regression errors.

Please let me know if it looks OK to commit to mainline.

                  Carl 
---------------------------------------------

gcc/ChangeLog

2020-10-05  Carl Love  <cel@us.ibm.com>
	* config/rs6000/rs6000.md (floatti<mode>2, floatunsti<mode>2,
	fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add
	define_insn for mode IEEE 128.
	* libgcc/config/rs6000/fixkfti.c: Renamed to fixkfti-sw.c.
	Update source function name.  White space fixes.
	* libgcc/config/rs6000/fixunskfti.c: Renamed to fixunskfti-sw.c.
	Update source function name.  White space fixes.
	* 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.c: Renamed to floattikf-sw.c.
	* libgcc/config/rs6000/floatuntikf.c: Renamed to floatuntikf-sw.c.
	* 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.
	* 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-10-05  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    | 286 ++++++++++++++++++
 .../config/rs6000/{fixkfti.c => fixkfti-sw.c} |   4 +-
 .../rs6000/{fixunskfti.c => fixunskfti-sw.c}  |   7 +-
 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, 417 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} (90%)
 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 694ff70635e..5db5d0b4505 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..dff24e1e2b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
@@ -0,0 +1,286 @@
+/* { 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 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
+	}
+
+  /* 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 90%
rename from libgcc/config/rs6000/fixunskfti.c
rename to libgcc/config/rs6000/fixunskfti-sw.c
index ab232d92d24..5c8b94b8862 100644
--- a/libgcc/config/rs6000/fixunskfti.c
+++ b/libgcc/config/rs6000/fixunskfti-sw.c
@@ -5,7 +5,10 @@
    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 fixunskfti.c file renamed fixunskfti-sw.c.  Updated the
+   source file names and made whitespace fixes
 
    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 +38,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
will schmidt Oct. 8, 2020, 3:35 p.m. UTC | #3
On Mon, 2020-10-05 at 11:52 -0700, Carl Love wrote:
> Will, Segher:
> 
> This patch adds support for converting to/from 128-bit integers and
> 128-bit decimal floating point formats using the new P10 instructions
> dcffixqq and dctfixqq.  The new instructions are only used on P10 HW,
> otherwise the conversions continue to use the existing SW routines.
> 
> The changes from the previous version include:
> 
> Fixed up the change log entry issues noted by Will.
> 
> Regression tests reran on Power 9 LE with no regression errors.
> 
> Please let me know if it looks OK to commit to mainline.
> 
>                   Carl 
> ---------------------------------------------
> 
> gcc/ChangeLog
> 
> 2020-10-05  Carl Love  <cel@us.ibm.com>
> 	* config/rs6000/rs6000.md (floatti<mode>2, floatunsti<mode>2,
> 	fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add
> 	define_insn for mode IEEE 128.
> 	* libgcc/config/rs6000/fixkfti.c: Renamed to fixkfti-sw.c.
> 	Update source function name.  White space fixes.

I'd move the generic 'Update source ... White space...' bits to the
patch description.  In addition to the 'Rename' statement, some form of
'Change calls of __fixkfti to __fixkfti_sw` would be more useful here.

> 	* libgcc/config/rs6000/fixunskfti.c: Renamed to fixunskfti-sw.c.
> 	Update source function name.  White space fixes.
> 	* libgcc/config/rs6000/float128-hw.c (__floattikf_hw,
> 	__floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw):
> 	New functions.
ok
> 	* 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.
ok
> 	* 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.
ok

> 	* libgcc/config/rs6000/floattikf.c: Renamed to floattikf-sw.c.
> 	* libgcc/config/rs6000/floatuntikf.c: Renamed to floatuntikf-sw.c.
> 	* 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.
> 	* 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-10-05  Carl Love  <cel@us.ibm.com>
> 	* gcc.target/powerpc/fl128_conversions.c: New file.

fp128_conversions.c



> ---
>  gcc/config/rs6000/rs6000.md                   |  36 +++
>  .../gcc.target/powerpc/fp128_conversions.c    | 286 ++++++++++++++++++
>  .../config/rs6000/{fixkfti.c => fixkfti-sw.c} |   4 +-
>  .../rs6000/{fixunskfti.c => fixunskfti-sw.c}  |   7 +-
>  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, 417 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} (90%)
>  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 694ff70635e..5db5d0b4505 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..dff24e1e2b4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
> @@ -0,0 +1,286 @@
> +/* { 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 } } } } */

I don't see any other uses or references to ppc_native_128bit.  
Nothing in testsuite/lib/target-supports.exp looks close.  ? 

> +
> +#include <stdio.h>
> +#include <math.h>
> +#include <fenv.h>
> +#include <stdlib.h>
> +#include <wchar.h>
> +
> +#define DEBUG 0
> +
> +void abort (void);
> +
> +float conv_i_2_fp( long long int a)
> +{
> +  return (float) a;
> +}
> +
> +double conv_i_2_fpd( long long int a)
> +{
> +  return (double) a;
> +}
> +
> +double conv_ui_2_fpd( unsigned long long int a)
> +{
> +  return (double) a;
> +}
> +
> +__float128 conv_i128_2_fp128 (__int128_t a)
> +{
> +  // default, gen inst KF mode
> +  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
> +  // -mabi=ieeelongdouble gen inst floattiieee TF mode
> +  return (__float128) a;
> +}
> +
> +__float128 conv_ui128_2_fp128 (__uint128_t a)
> +{
> +  // default, gen inst KF mode
> +  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
> +  // -mabi=ieeelongdouble gen inst floattiieee TF mode
> +  return (__float128) a;
> +}
> +
> +__int128_t conv_fp128_2_i128 (__float128 a)
> +{
> +  // default, gen inst KF mode
> +  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
> +  // -mabi=ieeelongdouble gen inst floattiieee TF mode
> +  return (__int128_t) a;
> +}
> +
> +__uint128_t conv_fp128_2_ui128 (__float128 a)
> +{
> +  // default, gen inst KF mode
> +  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
> +  // -mabi=ieeelongdouble gen inst floattiieee TF mode
> +  return (__uint128_t) a;
> +}
> +
> +long double conv_i128_2_ld (__int128_t a)
> +{
> +  // default, gen call __floattitf
> +  // -mabi=ibmlongdouble, gen call __floattitf
> +  // -mabi=ieeelongdouble gen inst floattiieee TF mode
> +  return (long double) a;
> +}
> +
> +__ibm128 conv_i128_2_ibm128 (__int128_t a)
> +{
> +  // default, gen call __floattitf
> +  // -mabi=ibmlongdouble, gen call __floattitf
> +  // -mabi=ieeelongdouble, message uses IBM long double, no binary output
> +  return (__ibm128) a;
> +}
> +
> +int main()
> +{
> +	float a, expected_result_float;
> +	double b, expected_result_double;
> +	long long int c, expected_result_llint;
> +	unsigned long long int u;
> +	__int128_t d;
> +	__uint128_t u128;
> +	unsigned long long expected_result_uint128[2] ;
> +	__float128 e;
> +	long double ld;     // another 128-bit float version
> +
> +	union conv_t {
> +		float a;
> +		double b;
> +		long long int c;
> +		long long int128[2] ;
> +		unsigned long long uint128[2] ;
> +		unsigned long long int u;
> +		__int128_t d;
> +		__uint128_t u128;
> +		__float128 e;
> +		long double ld;     // another 128-bit float version
> +	} conv, conv_result;
> +
> +	c = 20;
> +	expected_result_llint = 20.00000;
> +	a = conv_i_2_fp (c);
> +
> +	if (a != expected_result_llint) {
> +#if DEBUG
> +		printf("ERROR: conv_i_2_fp(%lld) = %10.5f\n", c, a);
> +		printf("\n does not match expected_result = %10.5f\n\n",
> +				 expected_result_llint);
> +#else
> +		abort();
> +#endif
> +	}
> +
> +	c = 20;
> +	expected_result_double = 20.00000;
> +	b = conv_i_2_fpd (c);
> +
> +	if (b != expected_result_double) {
> +#if DEBUG
> +		printf("ERROR: conv_i_2_fpd(%lld) = %10.5f\n", d, b);
> +		printf("\n does not match expected_result = %10.5f\n\n",
> +				 expected_result_double);
> + #else
> +		abort();
> +#endif
> +	}
> +
> +	u = 20;
> +	expected_result_double = 20.00000;
> +	b = conv_ui_2_fpd (u);
> +
> +	if (b != expected_result_double) {
> +#if DEBUG
> +		printf("ERROR: conv_ui_2_fpd(%llu) = %10.5f\n", u, b);
> +		printf("\n does not match expected_result = %10.5f\n\n",
> +				 expected_result_double);
> + #else
> +		abort();
> +#endif
> +	}
> +
> +  /* Currently printing 128-bit float does not work correctly  */

limitation or pr ? 

> +  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 90%
> rename from libgcc/config/rs6000/fixunskfti.c
> rename to libgcc/config/rs6000/fixunskfti-sw.c
> index ab232d92d24..5c8b94b8862 100644
> --- a/libgcc/config/rs6000/fixunskfti.c
> +++ b/libgcc/config/rs6000/fixunskfti-sw.c
> @@ -5,7 +5,10 @@
>     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 fixunskfti.c file renamed fixunskfti-sw.c.  Updated the
> +   source file names and made whitespace fixes

This would be better in patch description.  Not sure it is useful here.


> 
>     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 +38,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.  */
> -

good.  :-)

>  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
> 
ok.


lgtm,
thanks
-Will
Carl Love Oct. 12, 2020, 8:16 p.m. UTC | #4
Will, Segher:
 
This patch adds support for converting to/from 128-bit integers and
128-bit decimal floating point formats using the new P10 instructions
dcffixqq and dctfixqq.  The new instructions are only used on P10 HW,
otherwise the conversions continue to use the existing SW routines.

The files fixkfti-sw.c and fixunskfti-sw.c are renamed versions of
fixkfti.c and fixunskfti.c respectively.  The function names in the
files were updated with the rename as well as some white spaces fixes.

Fixed a typo in the ChangeLog noted by Will.

Removed the target ppc_native_128bit from the test case as we no longer
have the 128-bit flag.

Re-tested the patch on Power 9 with no regression errors.
                    Carl

--------------------------------------------------------------



gcc/ChangeLog

2020-10-12  Carl Love  <cel@us.ibm.com>
	* config/rs6000/rs6000.md (floatti<mode>2, floatunsti<mode>2,
	fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add
	define_insn for mode IEEE 128.
	* libgcc/config/rs6000/fixkfti.c: Renamed to fixkfti-sw.c.
	Change calls of __fixkfti to __fixkfti_sw.
	* libgcc/config/rs6000/fixunskfti.c: Renamed to fixunskfti-sw.c.
	Change calls of __fixunskfti to __fixunskfti_sw.
	* 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.c: Renamed to floattikf-sw.c.
	* libgcc/config/rs6000/floatuntikf.c: Renamed to floatuntikf-sw.c.
	* 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.
	* 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-10-12  Carl Love  <cel@us.ibm.com>
	* gcc.target/powerpc/fp128_conversions.c: New file.
---
 gcc/config/rs6000/rs6000.md                   |  36 +++
 .../gcc.target/powerpc/fp128_conversions.c    | 283 ++++++++++++++++++
 .../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, 411 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 694ff70635e..5db5d0b4505 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..1269232a6cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
@@ -0,0 +1,283 @@
+/* { 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 } } */
+/* { dg-final { scan-assembler-times {\mxscvuqqp\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvqpsqz\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvqpuqz\M} 1 } } */
+
+#include <stdio.h>
+#include <math.h>
+#include <fenv.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#define DEBUG 0
+
+void abort (void);
+
+float conv_i_2_fp( long long int a)
+{
+  return (float) a;
+}
+
+double conv_i_2_fpd( long long int a)
+{
+  return (double) a;
+}
+
+double conv_ui_2_fpd( unsigned long long int a)
+{
+  return (double) a;
+}
+
+__float128 conv_i128_2_fp128 (__int128_t a)
+{
+  // default, gen inst KF mode
+  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (__float128) a;
+}
+
+__float128 conv_ui128_2_fp128 (__uint128_t a)
+{
+  // default, gen inst KF mode
+  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (__float128) a;
+}
+
+__int128_t conv_fp128_2_i128 (__float128 a)
+{
+  // default, gen inst KF mode
+  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (__int128_t) a;
+}
+
+__uint128_t conv_fp128_2_ui128 (__float128 a)
+{
+  // default, gen inst KF mode
+  // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (__uint128_t) a;
+}
+
+long double conv_i128_2_ld (__int128_t a)
+{
+  // default, gen call __floattitf
+  // -mabi=ibmlongdouble, gen call __floattitf
+  // -mabi=ieeelongdouble gen inst floattiieee TF mode
+  return (long double) a;
+}
+
+__ibm128 conv_i128_2_ibm128 (__int128_t a)
+{
+  // default, gen call __floattitf
+  // -mabi=ibmlongdouble, gen call __floattitf
+  // -mabi=ieeelongdouble, message uses IBM long double, no binary output
+  return (__ibm128) a;
+}
+
+int main()
+{
+	float a, expected_result_float;
+	double b, expected_result_double;
+	long long int c, expected_result_llint;
+	unsigned long long int u;
+	__int128_t d;
+	__uint128_t u128;
+	unsigned long long expected_result_uint128[2] ;
+	__float128 e;
+	long double ld;     // another 128-bit float version
+
+	union conv_t {
+		float a;
+		double b;
+		long long int c;
+		long long int128[2] ;
+		unsigned long long uint128[2] ;
+		unsigned long long int u;
+		__int128_t d;
+		__uint128_t u128;
+		__float128 e;
+		long double ld;     // another 128-bit float version
+	} conv, conv_result;
+
+	c = 20;
+	expected_result_llint = 20.00000;
+	a = conv_i_2_fp (c);
+
+	if (a != expected_result_llint) {
+#if DEBUG
+		printf("ERROR: conv_i_2_fp(%lld) = %10.5f\n", c, a);
+		printf("\n does not match expected_result = %10.5f\n\n",
+				 expected_result_llint);
+#else
+		abort();
+#endif
+	}
+
+	c = 20;
+	expected_result_double = 20.00000;
+	b = conv_i_2_fpd (c);
+
+	if (b != expected_result_double) {
+#if DEBUG
+		printf("ERROR: conv_i_2_fpd(%lld) = %10.5f\n", d, b);
+		printf("\n does not match expected_result = %10.5f\n\n",
+				 expected_result_double);
+ #else
+		abort();
+#endif
+	}
+
+	u = 20;
+	expected_result_double = 20.00000;
+	b = conv_ui_2_fpd (u);
+
+	if (b != expected_result_double) {
+#if DEBUG
+		printf("ERROR: conv_ui_2_fpd(%llu) = %10.5f\n", u, b);
+		printf("\n does not match expected_result = %10.5f\n\n",
+				 expected_result_double);
+ #else
+		abort();
+#endif
+	}
+
+  d = -3210;
+  d = (d * 10000000000) + 9876543210;
+  conv_result.e = conv_i128_2_fp128 (d);
+  expected_result_uint128[1] = 0xc02bd2f9068d1160;
+  expected_result_uint128[0] = 0x0;
+  
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+		&& (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+	  printf("ERROR: conv_i128_2_fp128(-32109876543210) = (result in hex) 0x%llx %llx\n",
+				conv.uint128[1], conv.uint128[0]);
+	  printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+				expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+	  abort();
+#endif
+	}
+
+  d = 123;
+  d = (d * 10000000000) + 1234567890;
+  conv_result.ld = conv_i128_2_fp128 (d);
+  expected_result_uint128[1] = 0x0;
+  expected_result_uint128[0] = 0x4271eab4c8ed2000;
+
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+		&& (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+	  printf("ERROR: conv_i128_2_fp128(1231234567890) = (result in hex) 0x%llx %llx\n",
+				conv.uint128[1], conv.uint128[0]);
+	  printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+				expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+	  abort();
+#endif
+	}
+
+  u128 = 8760;
+  u128 = (u128 * 10000000000) + 1234567890;
+  conv_result.e = conv_ui128_2_fp128 (u128);
+  expected_result_uint128[1] = 0x402d3eb101df8b48;
+  expected_result_uint128[0] = 0x0;
+
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+		&& (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+	  printf("ERROR: conv_ui128_2_fp128(87601234567890) = (result in hex) 0x%llx %llx\n",
+				conv.uint128[1], conv.uint128[0]);
+	  printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+				expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+	  abort();
+#endif
+	}
+
+  u128 = 3210;
+  u128 = (u128 * 10000000000) + 9876543210;
+  expected_result_uint128[1] = 0x402bd3429c8feea0;
+  expected_result_uint128[0] = 0x0;
+  conv_result.e = conv_ui128_2_fp128 (u128);
+
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+		&& (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+	  printf("ERROR: conv_ui128_2_fp128(32109876543210) = (result in hex) 0x%llx %llx\n",
+				conv.uint128[1], conv.uint128[0]);
+	  printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+				expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+	  abort();
+#endif
+	}
+
+  conv.e = 12345.6789;
+  expected_result_uint128[1] = 0x1407374883526960;
+  expected_result_uint128[0] = 0x3039;
+
+  conv_result.d = conv_fp128_2_i128 (conv.e);
+
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+		&& (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+	  printf("ERROR: conv_fp128_2_i128(0x%llx %llx) =  ",
+				conv.uint128[1], conv.uint128[0]);
+	  printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+
+	  printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+				expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+	  abort();
+#endif
+	}
+
+  conv.e = -6789.12345;
+  expected_result_uint128[1] = 0x0;
+  expected_result_uint128[0] = 0xffffffffffffe57b;
+  conv_result.d = conv_fp128_2_i128 (conv.e);
+ 
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+		&& (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+	  printf("ERROR: conv_fp128_2_i128(0x%llx %llx) = ",
+				conv.uint128[1], conv.uint128[0]);
+	  printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+
+	  printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+				expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+	  abort();
+#endif
+	}
+
+  conv.e = 6789.12345;
+  expected_result_uint128[1] = 0x0;
+  expected_result_uint128[0] = 0x1a85;
+  conv_result.d = conv_fp128_2_ui128 (conv.e);
+ 
+  if ((conv_result.uint128[1] != expected_result_uint128[1])
+		&& (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+	  printf("ERROR: conv_fp128_2_ui128(0x%llx %llx) = ",
+				conv.uint128[1], conv.uint128[0]);
+	  printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+	  
+	  printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+				expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+	  abort();
+#endif
+	}
+
+  return 0;
+}
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
diff mbox series

Patch

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 694ff70635e..5db5d0b4505 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..dff24e1e2b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
@@ -0,0 +1,286 @@ 
+/* { 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 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
+	}
+
+  /* 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 90%
rename from libgcc/config/rs6000/fixunskfti.c
rename to libgcc/config/rs6000/fixunskfti-sw.c
index ab232d92d24..5c8b94b8862 100644
--- a/libgcc/config/rs6000/fixunskfti.c
+++ b/libgcc/config/rs6000/fixunskfti-sw.c
@@ -5,7 +5,10 @@ 
    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 fixunskfti.c file renamed fixunskfti-sw.c.  Updated the
+   source file names and made whitespace fixes
 
    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 +38,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