diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 531a9c87243..c7a28044f68 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -11022,10 +11022,10 @@ init_float128_ieee (machine_mode mode)
 
       if (TARGET_POWERPC64)
 	{
-	  set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti");
-	  set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti");
-	  set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf");
-	  set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf");
+	  set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti_sw");
+	  set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti_sw");
+	  set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf_sw");
+	  set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf_sw");
 	}
     }
 
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index c8cdc42533c..674c4432661 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -6421,6 +6421,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..c20282fa0e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
@@ -0,0 +1,294 @@
+/* { dg-do run } */
+/* { dg-require-effective-target power10_hw } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
+
+/* Check that the expected 128-bit instructions are generated if the processor
+   supports the 128-bit integer instructions. */
+/* { dg-final { scan-assembler-times {\mxscvsqqp\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvuqqp\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvqpsqz\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvqpuqz\M} 1 } } */
+
+#include <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/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c b/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
index 9f7dbc6cc75..94dbd2b6230 100644
--- a/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
@@ -4,21 +4,16 @@
 
 /* Check that the expected 128-bit instructions are generated if the processor
    supports the 128-bit integer instructions. */
+/* { dg-final { scan-assembler-times {\mvextsd2q\M} 4 } } */
 /* { dg-final { scan-assembler-times {\mvslq\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvsrq\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvsraq\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvrlq\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvrlqnm\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mvrlqmi\M} 2 } } */
-/* { dg-final { scan-assembler-times {\mvcmpuq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpsq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpequq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpequq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtsq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtuq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvmuleud\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvcmpequq\M} 16 } } */
+/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 16 } } */
+/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 16 } } */
 /* { dg-final { scan-assembler-times {\mvmuloud\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mvmulesd\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mvmulosd\M} 1 } } */
diff --git a/libgcc/config.host b/libgcc/config.host
index f808b61be70..50f00062232 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -1224,6 +1224,10 @@ powerpc*-*-linux*)
 		tmake_file="${tmake_file} rs6000/t-float128-hw"
 	fi
 
+	if test $libgcc_cv_powerpc_3_1_float128_hw = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128-p10-hw"
+	fi
+
 	extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
 	md_unwind_header=rs6000/linux-unwind.h
 	;;
diff --git a/libgcc/config/rs6000/fixkfti.c b/libgcc/config/rs6000/fixkfti-sw.c
similarity index 96%
rename from libgcc/config/rs6000/fixkfti.c
rename to libgcc/config/rs6000/fixkfti-sw.c
index 0d965bc6253..cc000fca0f8 100644
--- a/libgcc/config/rs6000/fixkfti.c
+++ b/libgcc/config/rs6000/fixkfti-sw.c
@@ -5,7 +5,7 @@
    This file is part of the GNU C Library.
    Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
    Code is based on the main soft-fp library written by:
-   	   Uros Bizjak (ubizjak@gmail.com).
+	   Uros Bizjak (ubizjak@gmail.com).
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 #include "quad-float128.h"
 
 TItype
-__fixkfti (TFtype a)
+__fixkfti_sw (TFtype a)
 {
   FP_DECL_EX;
   FP_DECL_Q (A);
diff --git a/libgcc/config/rs6000/fixunskfti.c b/libgcc/config/rs6000/fixunskfti-sw.c
similarity index 96%
rename from libgcc/config/rs6000/fixunskfti.c
rename to libgcc/config/rs6000/fixunskfti-sw.c
index f285b4e3fbd..7a04d1a489a 100644
--- a/libgcc/config/rs6000/fixunskfti.c
+++ b/libgcc/config/rs6000/fixunskfti-sw.c
@@ -5,7 +5,7 @@
    This file is part of the GNU C Library.
    Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
    Code is based on the main soft-fp library written by:
-   	   Uros Bizjak (ubizjak@gmail.com).
+	   Uros Bizjak (ubizjak@gmail.com).
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 #include "quad-float128.h"
 
 UTItype
-__fixunskfti (TFtype a)
+__fixunskfti_sw (TFtype a)
 {
   FP_DECL_EX;
   FP_DECL_Q (A);
diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c
index 85380471c5e..57545dd7edb 100644
--- a/libgcc/config/rs6000/float128-ifunc.c
+++ b/libgcc/config/rs6000/float128-ifunc.c
@@ -46,14 +46,9 @@
 #endif
 
 #define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW)
+#define SW_OR_HW_ISA3_1(SW, HW) (__builtin_cpu_supports ("arch_3_1") ? HW : SW)
 
 /* Resolvers.  */
-
-/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
-   and __floatuntikf.  There is no ISA 3.0 instruction that converts between
-   128-bit integer types and 128-bit IEEE floating point, or vice versa.  So
-   use the emulator functions for these conversions.  */
-
 static __typeof__ (__addkf3_sw) *
 __addkf3_resolve (void)
 {
@@ -102,6 +97,18 @@ __floatdikf_resolve (void)
   return SW_OR_HW (__floatdikf_sw, __floatdikf_hw);
 }
 
+static __typeof__ (__floattikf_sw) *
+__floattikf_resolve (void)
+{
+  return SW_OR_HW_ISA3_1 (__floattikf_sw, __floattikf_hw);
+}
+
+static __typeof__ (__floatuntikf_sw) *
+__floatuntikf_resolve (void)
+{
+  return SW_OR_HW_ISA3_1 (__floatuntikf_sw, __floatuntikf_hw);
+}
+
 static __typeof__ (__floatunsikf_sw) *
 __floatunsikf_resolve (void)
 {
@@ -114,6 +121,19 @@ __floatundikf_resolve (void)
   return SW_OR_HW (__floatundikf_sw, __floatundikf_hw);
 }
 
+
+static __typeof__ (__fixkfti_sw) *
+__fixkfti_resolve (void)
+{
+  return SW_OR_HW_ISA3_1 (__fixkfti_sw, __fixkfti_hw);
+}
+
+static __typeof__ (__fixunskfti_sw) *
+__fixunskfti_resolve (void)
+{
+  return SW_OR_HW_ISA3_1 (__fixunskfti_sw, __fixunskfti_hw);
+}
+
 static __typeof__ (__fixkfsi_sw) *
 __fixkfsi_resolve (void)
 {
@@ -303,6 +323,18 @@ TFtype __floatsikf (SItype_ppc)
 TFtype __floatdikf (DItype_ppc)
   __attribute__ ((__ifunc__ ("__floatdikf_resolve")));
 
+TFtype __floattikf (TItype_ppc)
+  __attribute__ ((__ifunc__ ("__floattikf_resolve")));
+
+TFtype __floatuntikf (UTItype_ppc)
+  __attribute__ ((__ifunc__ ("__floatuntikf_resolve")));
+
+TItype_ppc __fixkfti (TFtype)
+  __attribute__ ((__ifunc__ ("__fixkfti_resolve")));
+
+UTItype_ppc __fixunskfti (TFtype)
+  __attribute__ ((__ifunc__ ("__fixunskfti_resolve")));
+
 TFtype __floatunsikf (USItype_ppc)
   __attribute__ ((__ifunc__ ("__floatunsikf_resolve")));
 
diff --git a/libgcc/config/rs6000/float128-p10.c b/libgcc/config/rs6000/float128-p10.c
new file mode 100644
index 00000000000..7f5d317631a
--- /dev/null
+++ b/libgcc/config/rs6000/float128-p10.c
@@ -0,0 +1,71 @@
+/* Automatic switching between software and hardware IEEE 128-bit
+   ISA 3.1 floating-point emulation for PowerPC.
+
+   Copyright (C) 2016-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Carl Love (cel@us.ibm.com)
+   Code is based on the main soft-fp library written by:
+	Richard Henderson (rth@cygnus.com) and
+	Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Note, the hardware conversion instructions for 128-bit integers are
+   supported for ISA 3.1 and later.  Only compile this file with -mcpu=power10
+   or newer support.  */
+
+#include <soft-fp.h>
+#include <quad-float128.h>
+
+#ifndef __FLOAT128_HARDWARE__
+#error "This module must be compiled with IEEE 128-bit hardware support"
+#endif
+
+#ifndef _ARCH_PWR10
+#error "This module must be compiled for Power 10 support"
+#endif
+
+TFtype
+__floattikf_hw (TItype_ppc a)
+{
+  return (TFtype) a;
+}
+
+TFtype
+__floatuntikf_hw (UTItype_ppc a)
+{
+  return (TFtype) a;
+}
+
+TItype_ppc
+__fixkfti_hw (TFtype a)
+{
+  return (TItype_ppc) a;
+}
+
+UTItype_ppc
+__fixunskfti_hw (TFtype a)
+{
+  return (UTItype_ppc) a;
+}
diff --git a/libgcc/config/rs6000/float128-sed b/libgcc/config/rs6000/float128-sed
index d9a089ff9ba..c0fcddb1959 100644
--- a/libgcc/config/rs6000/float128-sed
+++ b/libgcc/config/rs6000/float128-sed
@@ -8,6 +8,10 @@ s/__fixtfsi/__fixkfsi/g
 s/__fixunstfdi/__fixunskfdi/g
 s/__fixunstfsi/__fixunskfsi/g
 s/__floatditf/__floatdikf/g
+s/__floattitf/__floattikf/g
+s/__floatuntitf/__floatuntikf/g
+s/__fixtfti/__fixkfti/g
+s/__fixunstfti/__fixunskfti/g
 s/__floatsitf/__floatsikf/g
 s/__floatunditf/__floatundikf/g
 s/__floatunsitf/__floatunsikf/g
diff --git a/libgcc/config/rs6000/float128-sed-hw b/libgcc/config/rs6000/float128-sed-hw
index acf36b0c17d..3d2bf556da1 100644
--- a/libgcc/config/rs6000/float128-sed-hw
+++ b/libgcc/config/rs6000/float128-sed-hw
@@ -8,6 +8,10 @@ s/__fixtfsi/__fixkfsi_sw/g
 s/__fixunstfdi/__fixunskfdi_sw/g
 s/__fixunstfsi/__fixunskfsi_sw/g
 s/__floatditf/__floatdikf_sw/g
+s/__floattitf/__floattikf_sw/g
+s/__floatuntitf/__floatuntikf_sw/g
+s/__fixtfti/__fixkfti_sw/g
+s/__fixunstfti/__fixunskfti_sw/g
 s/__floatsitf/__floatsikf_sw/g
 s/__floatunditf/__floatundikf_sw/g
 s/__floatunsitf/__floatunsikf_sw/g
diff --git a/libgcc/config/rs6000/floattikf.c b/libgcc/config/rs6000/floattikf-sw.c
similarity index 96%
rename from libgcc/config/rs6000/floattikf.c
rename to libgcc/config/rs6000/floattikf-sw.c
index cc5c7ca0fd0..4e1786cd229 100644
--- a/libgcc/config/rs6000/floattikf.c
+++ b/libgcc/config/rs6000/floattikf-sw.c
@@ -5,7 +5,7 @@
    This file is part of the GNU C Library.
    Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
    Code is based on the main soft-fp library written by:
-   	   Uros Bizjak (ubizjak@gmail.com).
+	   Uros Bizjak (ubizjak@gmail.com).
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 #include "quad-float128.h"
 
 TFtype
-__floattikf (TItype i)
+__floattikf_sw (TItype i)
 {
   FP_DECL_EX;
   FP_DECL_Q (A);
diff --git a/libgcc/config/rs6000/floatuntikf.c b/libgcc/config/rs6000/floatuntikf-sw.c
similarity index 96%
rename from libgcc/config/rs6000/floatuntikf.c
rename to libgcc/config/rs6000/floatuntikf-sw.c
index 96f2d3bdcb8..c4b814ddd68 100644
--- a/libgcc/config/rs6000/floatuntikf.c
+++ b/libgcc/config/rs6000/floatuntikf-sw.c
@@ -5,7 +5,7 @@
    This file is part of the GNU C Library.
    Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
    Code is based on the main soft-fp library written by:
-   	   Uros Bizjak (ubizjak@gmail.com).
+	   Uros Bizjak (ubizjak@gmail.com).
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 #include "quad-float128.h"
 
 TFtype
-__floatuntikf (UTItype i)
+__floatuntikf_sw (UTItype i)
 {
   FP_DECL_EX;
   FP_DECL_Q (A);
diff --git a/libgcc/config/rs6000/quad-float128.h b/libgcc/config/rs6000/quad-float128.h
index 5beb1531d2b..c4d775b4ad3 100644
--- a/libgcc/config/rs6000/quad-float128.h
+++ b/libgcc/config/rs6000/quad-float128.h
@@ -88,19 +88,18 @@ extern USItype_ppc __fixunskfsi_sw (TFtype);
 extern UDItype_ppc __fixunskfdi_sw (TFtype);
 extern TFtype __floatsikf_sw (SItype_ppc);
 extern TFtype __floatdikf_sw (DItype_ppc);
+extern TFtype __floattikf_sw (TItype_ppc);
 extern TFtype __floatunsikf_sw (USItype_ppc);
 extern TFtype __floatundikf_sw (UDItype_ppc);
+extern TFtype __floatuntikf_sw (UTItype_ppc);
+extern TItype_ppc __fixkfti_sw (TFtype);
+extern UTItype_ppc __fixunskfti_sw (TFtype);
 extern IBM128_TYPE __extendkftf2_sw (TFtype);
 extern TFtype __trunctfkf2_sw (IBM128_TYPE);
 extern TCtype __mulkc3_sw (TFtype, TFtype, TFtype, TFtype);
 extern TCtype __divkc3_sw (TFtype, TFtype, TFtype, TFtype);
 
 #ifdef _ARCH_PPC64
-/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
-   and __floatuntikf.  There is no ISA 3.0 instruction that converts between
-   128-bit integer types and 128-bit IEEE floating point, or vice versa.  So
-   use the emulator functions for these conversions.  */
-
 extern TItype_ppc __fixkfti (TFtype);
 extern UTItype_ppc __fixunskfti (TFtype);
 extern TFtype __floattikf (TItype_ppc);
@@ -131,8 +130,12 @@ extern USItype_ppc __fixunskfsi_hw (TFtype);
 extern UDItype_ppc __fixunskfdi_hw (TFtype);
 extern TFtype __floatsikf_hw (SItype_ppc);
 extern TFtype __floatdikf_hw (DItype_ppc);
+extern TFtype __floattikf_hw (TItype_ppc);
 extern TFtype __floatunsikf_hw (USItype_ppc);
 extern TFtype __floatundikf_hw (UDItype_ppc);
+extern TFtype __floatuntikf_hw (UTItype_ppc);
+extern TItype_ppc __fixkfti_hw (TFtype);
+extern UTItype_ppc __fixunskfti_hw (TFtype);
 extern IBM128_TYPE __extendkftf2_hw (TFtype);
 extern TFtype __trunctfkf2_hw (IBM128_TYPE);
 extern TCtype __mulkc3_hw (TFtype, TFtype, TFtype, TFtype);
@@ -163,8 +166,12 @@ extern USItype_ppc __fixunskfsi (TFtype);
 extern UDItype_ppc __fixunskfdi (TFtype);
 extern TFtype __floatsikf (SItype_ppc);
 extern TFtype __floatdikf (DItype_ppc);
+extern TFtype __floattikf (TItype_ppc);
 extern TFtype __floatunsikf (USItype_ppc);
 extern TFtype __floatundikf (UDItype_ppc);
+extern TFtype __floatuntikf (UTItype_ppc);
+extern TItype_ppc __fixkfti (TFtype);
+extern UTItype_ppc __fixunskfti (TFtype);
 extern IBM128_TYPE __extendkftf2 (TFtype);
 extern TFtype __trunctfkf2 (IBM128_TYPE);
 
diff --git a/libgcc/config/rs6000/t-float128 b/libgcc/config/rs6000/t-float128
index d745f0d82e1..b09b5664af0 100644
--- a/libgcc/config/rs6000/t-float128
+++ b/libgcc/config/rs6000/t-float128
@@ -31,7 +31,8 @@ ibm128_dec_funcs	= _tf_to_sd _tf_to_dd _tf_to_td \
 			  _sd_to_tf _dd_to_tf _td_to_tf
 
 # New functions for software emulation
-fp128_ppc_funcs		= floattikf floatuntikf fixkfti fixunskfti \
+fp128_ppc_funcs		= floattikf-sw floatuntikf-sw \
+			  fixkfti-sw fixunskfti-sw \
 			  extendkftf2-sw trunctfkf2-sw \
 			  sfp-exceptions _mulkc3 _divkc3 _powikf2
 
@@ -47,13 +48,16 @@ fp128_ppc_obj		= $(fp128_ppc_static_obj) $(fp128_ppc_shared_obj)
 
 # All functions
 fp128_funcs		= $(fp128_softfp_funcs) $(fp128_ppc_funcs) \
-			  $(fp128_hw_funcs) $(fp128_ifunc_funcs)
+			  $(fp128_hw_funcs) $(fp128_ifunc_funcs) \
+			  $(fp128_3_1_hw_funcs)
 
 fp128_src		= $(fp128_softfp_src) $(fp128_ppc_src) \
-			  $(fp128_hw_src) $(fp128_ifunc_src)
+			  $(fp128_hw_src) $(fp128_ifunc_src) \
+			  $(fp128_3_1_hw_src)
 
 fp128_obj		= $(fp128_softfp_obj) $(fp128_ppc_obj) \
-			  $(fp128_hw_obj) $(fp128_ifunc_obj)
+			  $(fp128_hw_obj) $(fp128_ifunc_obj) \
+			  $(fp128_3_1_hw_obj)
 
 fp128_sed		= $(srcdir)/config/rs6000/float128-sed$(fp128_sed_hw)
 fp128_dep		= $(fp128_sed) $(srcdir)/config/rs6000/t-float128
diff --git a/libgcc/config/rs6000/t-float128-hw b/libgcc/config/rs6000/t-float128-hw
index d64ca4dd694..c0827366cc4 100644
--- a/libgcc/config/rs6000/t-float128-hw
+++ b/libgcc/config/rs6000/t-float128-hw
@@ -13,6 +13,13 @@ fp128_hw_static_obj	= $(addsuffix $(objext),$(fp128_hw_funcs))
 fp128_hw_shared_obj	= $(addsuffix _s$(objext),$(fp128_hw_funcs))
 fp128_hw_obj		= $(fp128_hw_static_obj) $(fp128_hw_shared_obj)
 
+# New functions for ISA 3.1 hardware support
+fp128_3_1_hw_funcs	= float128-p10
+fp128_3_1_hw_src	= $(srcdir)/config/rs6000/float128-p10.c
+fp128_3_1_hw_static_obj	= $(addsuffix $(objext),$(fp128_3_1_hw_funcs))
+fp128_3_1_hw_shared_obj	= $(addsuffix _s$(objext),$(fp128_3_1_hw_funcs))
+fp128_3_1_hw_obj	= $(fp128_3_1_hw_static_obj) $(fp128_3_1_hw_shared_obj)
+
 fp128_ifunc_funcs	= float128-ifunc
 fp128_ifunc_src		= $(srcdir)/config/rs6000/float128-ifunc.c
 fp128_ifunc_static_obj	= float128-ifunc$(objext)
@@ -30,9 +37,18 @@ FP128_CFLAGS_HW		 = -Wno-type-limits -mvsx -mfloat128 \
 			   -I$(srcdir)/config/rs6000 \
 			   $(FLOAT128_HW_INSNS)
 
+FP128_3_1_CFLAGS_HW	 = -Wno-type-limits -mvsx -mcpu=power10 \
+			   -mfloat128-hardware -mno-gnu-attribute \
+			   -I$(srcdir)/soft-fp \
+			   -I$(srcdir)/config/rs6000 \
+			   $(FLOAT128_HW_INSNS)
+
 $(fp128_hw_obj)		 : INTERNAL_CFLAGS += $(FP128_CFLAGS_HW)
 $(fp128_hw_obj)		 : $(srcdir)/config/rs6000/t-float128-hw
 
+$(fp128_3_1_hw_obj)	 : INTERNAL_CFLAGS += $(FP128_3_1_CFLAGS_HW)
+$(fp128_3_1_hw_obj)	 : $(srcdir)/config/rs6000/t-float128-p10-hw
+
 $(fp128_ifunc_obj)	 : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW)
 $(fp128_ifunc_obj)	 : $(srcdir)/config/rs6000/t-float128-hw
 
diff --git a/libgcc/config/rs6000/t-float128-p10-hw b/libgcc/config/rs6000/t-float128-p10-hw
new file mode 100644
index 00000000000..de36227c3d1
--- /dev/null
+++ b/libgcc/config/rs6000/t-float128-p10-hw
@@ -0,0 +1,24 @@
+# Support for adding __float128 hardware support to the powerpc.
+# Tell the float128 functions that the ISA 3.1 hardware support can
+# be compiled it to be selected via IFUNC functions.
+
+FLOAT128_HW_INSNS	= -DFLOAT128_HW_INSNS
+
+# New functions for hardware support
+
+fp128_3_1_hw_funcs	= float128-p10
+fp128_3_1_hw_src	= $(srcdir)/config/rs6000/float128-p10.c
+fp128_3_1_hw_static_obj	= $(addsuffix $(objext),$(fp128_3_1_hw_funcs))
+fp128_3_1_hw_shared_obj	= $(addsuffix _s$(objext),$(fp128_3_1_hw_funcs))
+fp128_3_1_hw_obj	= $(fp128_3_1_hw_static_obj) $(fp128_3_1_hw_shared_obj)
+
+# Build the hardware support functions with appropriate hardware support
+FP128_3_1_CFLAGS_HW	 = -Wno-type-limits -mvsx -mfloat128 \
+			   -mpower10 \
+			   -mfloat128-hardware -mno-gnu-attribute \
+			   -I$(srcdir)/soft-fp \
+			   -I$(srcdir)/config/rs6000 \
+			   $(FLOAT128_HW_INSNS)
+
+$(fp128_3_1_hw_obj)		 : INTERNAL_CFLAGS += $(FP128_3_1_CFLAGS_HW)
+$(fp128_3_1_hw_obj)		 : $(srcdir)/config/rs6000/t-float128-p10-hw
diff --git a/libgcc/configure b/libgcc/configure
index dd3afb2c957..ce05e0dd48b 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -5263,6 +5263,43 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128_hw" >&5
 $as_echo "$libgcc_cv_powerpc_float128_hw" >&6; }
   CFLAGS="$saved_CFLAGS"
+
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -mpower10 -mfloat128-hardware"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PowerPC ISA 3.1 to build hardware __float128 libraries" >&5
+$as_echo_n "checking for PowerPC ISA 3.1 to build hardware __float128 libraries... " >&6; }
+if ${libgcc_cv_powerpc_float128_hw+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/auxv.h>
+     #ifndef AT_PLATFORM
+     #error "AT_PLATFORM is not defined"
+     #endif
+     #ifndef __BUILTIN_CPU_SUPPORTS__
+     #error "__builtin_cpu_supports is not available"
+     #endif
+     vector unsigned char add (vector unsigned char a, vector unsigned char b)
+     {
+       vector unsigned char ret;
+       __asm__ ("xscvsqqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
+       return ret;
+     }
+     void *add_resolver (void) { return (void *) add; }
+     __float128 add_ifunc (__float128, __float128)
+	__attribute__ ((__ifunc__ ("add_resolver")));
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgcc_cv_powerpc_3_1_float128_hw=yes
+else
+  libgcc_cv_powerpc_3_1_float128_hw=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128_hw" >&5
+  $as_echo "$libgcc_cv_powerpc_float128_hw" >&6; }
+  CFLAGS="$saved_CFLAGS"
 esac
 
 # Collect host-machine-specific information.
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 10ffb046415..bc315dec7e4 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -458,6 +458,31 @@ powerpc*-*-linux*)
     [libgcc_cv_powerpc_float128_hw=yes],
     [libgcc_cv_powerpc_float128_hw=no])])
   CFLAGS="$saved_CFLAGS"
+
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -mpower10 -mfloat128-hardware"
+  AC_CACHE_CHECK([for PowerPC ISA 3.1 to build hardware __float128 libraries],
+		 [libgcc_cv_powerpc_float128_hw],
+		 [AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE([#include <sys/auxv.h>
+     #ifndef AT_PLATFORM
+     #error "AT_PLATFORM is not defined"
+     #endif
+     #ifndef __BUILTIN_CPU_SUPPORTS__
+     #error "__builtin_cpu_supports is not available"
+     #endif
+     vector unsigned char add (vector unsigned char a, vector unsigned char b)
+     {
+       vector unsigned char ret;
+       __asm__ ("xscvsqqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
+       return ret;
+     }
+     void *add_resolver (void) { return (void *) add; }
+     __float128 add_ifunc (__float128, __float128)
+	__attribute__ ((__ifunc__ ("add_resolver")));])],
+    [libgcc_cv_powerpc_3_1_float128_hw=yes],
+    [libgcc_cv_powerpc_3_1_float128_hw=no])])
+  CFLAGS="$saved_CFLAGS"
 esac
 
 # Collect host-machine-specific information.
