re PR target/78597 (test case gcc.dg/torture/fp-int-convert-float128-ieee.c (and...
authorMichael Meissner <meissner@linux.vnet.ibm.com>
Tue, 31 Jan 2017 13:38:35 +0000 (13:38 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Tue, 31 Jan 2017 13:38:35 +0000 (13:38 +0000)
2017-01-31  Michael Meissner  <meissner@linux.vnet.ibm.com>

PR target/78597
PR target/79038
* config/rs6000/rs6000-protos.h (convert_float128_to_int): Delete,
no longer used.
(convert_int_to_float128): Likewise.
* config/rs6000/rs6000.c (convert_float128_to_int): Likewise.
(convert_int_to_float128): Likewise.
* config/rs6000/rs6000.md (UNSPEC_IEEE128_MOVE): Likewise.
(UNSPEC_IEEE128_CONVERT): Likewise.
(floatsi<mode>2, FLOAT128 iterator): Bypass calling
rs6000_expand_float128_convert if we have IEEE 128-bit hardware.
Use local variables for IBM extended format.
(fix_trunc<mode>si2, FLOAT128 iterator): Likewise.
(fix_trunc<mode>si2_fprs): Likewise.
(fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise.
(floatuns<IEEE128:mode>2, IEEE128 iterator): Likewise.
(fix<uns>_<mode>si2_hw): Rework the IEEE 128-bt hardware support
to know that we can now have integers of all sizes in vector
registers.
(fix<uns>_<mode>di2_hw): Likewise.
(float<uns>_<mode>si2_hw): Likewise.
(fix_<mode>si2_hw): Likewise.
(fixuns_<mode>si2_hw): Likewise.
(float<uns>_<mode>di2_hw): Likewise.
(float_<mode>di2_hw): Likewise.
(float_<mode>si2_hw): Likewise.
(floatuns_<mode>di2_hw): Likewise.
(floatuns_<mode>si2_hw): Likewise.
(xscvqp<su>wz_<mode>): Delete, no longer used.
(xscvqp<su>dz_<mode>): Likewise.
(xscv<su>dqp_<mode>): Likewise.
(ieee128_mfvsrd_64bit): Likewise.
(ieee128_mfvsrd_32bit): Likewise.
(ieee128_mfvsrwz): Likewise.
(ieee128_mtvsrw): Likewise.
(ieee128_mtvsrd_64bit): Likewise.
(ieee128_mtvsrd_32bit): Likewise.

From-SVN: r245059

gcc/ChangeLog
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 8190ad43c299c3565cc6071017a47339ea3932e8..772a2f4bad3eaf43748688b6436cbd4e080f6135 100644 (file)
@@ -1,3 +1,43 @@
+2017-01-31  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/78597
+       PR target/79038
+       * config/rs6000/rs6000-protos.h (convert_float128_to_int): Delete,
+       no longer used.
+       (convert_int_to_float128): Likewise.
+       * config/rs6000/rs6000.c (convert_float128_to_int): Likewise.
+       (convert_int_to_float128): Likewise.
+       * config/rs6000/rs6000.md (UNSPEC_IEEE128_MOVE): Likewise.
+       (UNSPEC_IEEE128_CONVERT): Likewise.
+       (floatsi<mode>2, FLOAT128 iterator): Bypass calling
+       rs6000_expand_float128_convert if we have IEEE 128-bit hardware.
+       Use local variables for IBM extended format.
+       (fix_trunc<mode>si2, FLOAT128 iterator): Likewise.
+       (fix_trunc<mode>si2_fprs): Likewise.
+       (fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise.
+       (floatuns<IEEE128:mode>2, IEEE128 iterator): Likewise.
+       (fix<uns>_<mode>si2_hw): Rework the IEEE 128-bt hardware support
+       to know that we can now have integers of all sizes in vector
+       registers.
+       (fix<uns>_<mode>di2_hw): Likewise.
+       (float<uns>_<mode>si2_hw): Likewise.
+       (fix_<mode>si2_hw): Likewise.
+       (fixuns_<mode>si2_hw): Likewise.
+       (float<uns>_<mode>di2_hw): Likewise.
+       (float_<mode>di2_hw): Likewise.
+       (float_<mode>si2_hw): Likewise.
+       (floatuns_<mode>di2_hw): Likewise.
+       (floatuns_<mode>si2_hw): Likewise.
+       (xscvqp<su>wz_<mode>): Delete, no longer used.
+       (xscvqp<su>dz_<mode>): Likewise.
+       (xscv<su>dqp_<mode>): Likewise.
+       (ieee128_mfvsrd_64bit): Likewise.
+       (ieee128_mfvsrd_32bit): Likewise.
+       (ieee128_mfvsrwz): Likewise.
+       (ieee128_mtvsrw): Likewise.
+       (ieee128_mtvsrd_64bit): Likewise.
+       (ieee128_mtvsrd_32bit): Likewise.
+
 2017-01-31  Martin Liska  <mliska@suse.cz>
 
        PR ipa/79285
index 0b18994df4068da7907f1149fd632a0623ce6821..74ad733d1b905f822c07e73146b39925b5c6444d 100644 (file)
@@ -57,8 +57,6 @@ extern const char *rs6000_output_move_128bit (rtx *);
 extern bool rs6000_move_128bit_ok_p (rtx []);
 extern bool rs6000_split_128bit_ok_p (rtx []);
 extern void rs6000_expand_float128_convert (rtx, rtx, bool);
-extern void convert_float128_to_int (rtx *, enum rtx_code);
-extern void convert_int_to_float128 (rtx *, enum rtx_code);
 extern void rs6000_expand_vector_init (rtx, rtx);
 extern void paired_expand_vector_init (rtx, rtx);
 extern void rs6000_expand_vector_set (rtx, rtx, int);
index 5ea59a439f5c8a6c246f0d5e995c7bba7ca015ff..e44664124466418d730e16d69047cc11dc65cd7f 100644 (file)
@@ -24686,92 +24686,6 @@ rs6000_expand_float128_convert (rtx dest, rtx src, bool unsigned_p)
   return;
 }
 
-/* Split a conversion from __float128 to an integer type into separate insns.
-   OPERANDS points to the destination, source, and V2DI temporary
-   register. CODE is either FIX or UNSIGNED_FIX.  */
-
-void
-convert_float128_to_int (rtx *operands, enum rtx_code code)
-{
-  rtx dest = operands[0];
-  rtx src = operands[1];
-  rtx tmp = operands[2];
-  rtx cvt;
-  rtvec cvt_vec;
-  rtx cvt_unspec;
-  rtvec move_vec;
-  rtx move_unspec;
-
-  if (GET_CODE (tmp) == SCRATCH)
-    tmp = gen_reg_rtx (V2DImode);
-
-  if (MEM_P (dest))
-    dest = rs6000_address_for_fpconvert (dest);
-
-  /* Generate the actual convert insn of the form:
-     (set (tmp) (unspec:V2DI [(fix:SI (reg:KF))] UNSPEC_IEEE128_CONVERT)).  */
-  cvt = gen_rtx_fmt_e (code, GET_MODE (dest), src);
-  cvt_vec = gen_rtvec (1, cvt);
-  cvt_unspec = gen_rtx_UNSPEC (V2DImode, cvt_vec, UNSPEC_IEEE128_CONVERT);
-  emit_insn (gen_rtx_SET (tmp, cvt_unspec));
-
-  /* Generate the move insn of the form:
-     (set (dest:SI) (unspec:SI [(tmp:V2DI))] UNSPEC_IEEE128_MOVE)).  */
-  move_vec = gen_rtvec (1, tmp);
-  move_unspec = gen_rtx_UNSPEC (GET_MODE (dest), move_vec, UNSPEC_IEEE128_MOVE);
-  emit_insn (gen_rtx_SET (dest, move_unspec));
-}
-
-/* Split a conversion from an integer type to __float128 into separate insns.
-   OPERANDS points to the destination, source, and V2DI temporary
-   register. CODE is either FLOAT or UNSIGNED_FLOAT.  */
-
-void
-convert_int_to_float128 (rtx *operands, enum rtx_code code)
-{
-  rtx dest = operands[0];
-  rtx src = operands[1];
-  rtx tmp = operands[2];
-  rtx cvt;
-  rtvec cvt_vec;
-  rtx cvt_unspec;
-  rtvec move_vec;
-  rtx move_unspec;
-  rtx unsigned_flag;
-
-  if (GET_CODE (tmp) == SCRATCH)
-    tmp = gen_reg_rtx (V2DImode);
-
-  if (MEM_P (src))
-    src = rs6000_address_for_fpconvert (src);
-
-  /* Generate the move of the integer into the Altivec register of the form:
-     (set (tmp:V2DI) (unspec:V2DI [(src:SI)
-                                  (const_int 0)] UNSPEC_IEEE128_MOVE)).
-
-     or:
-     (set (tmp:V2DI) (unspec:V2DI [(src:DI)] UNSPEC_IEEE128_MOVE)).  */
-
-  if (GET_MODE (src) == SImode)
-    {
-      unsigned_flag = (code == UNSIGNED_FLOAT) ? const1_rtx : const0_rtx;
-      move_vec = gen_rtvec (2, src, unsigned_flag);
-    }
-  else
-    move_vec = gen_rtvec (1, src);
-
-  move_unspec = gen_rtx_UNSPEC (V2DImode, move_vec, UNSPEC_IEEE128_MOVE);
-  emit_insn (gen_rtx_SET (tmp, move_unspec));
-
-  /* Generate the actual convert insn of the form:
-     (set (dest:KF) (float:KF (unspec:DI [(tmp:V2DI)]
-                                        UNSPEC_IEEE128_CONVERT))).  */
-  cvt_vec = gen_rtvec (1, tmp);
-  cvt_unspec = gen_rtx_UNSPEC (DImode, cvt_vec, UNSPEC_IEEE128_CONVERT);
-  cvt = gen_rtx_fmt_e (code, GET_MODE (dest), cvt_unspec);
-  emit_insn (gen_rtx_SET (dest, cvt));
-}
-
 \f
 /* Emit the RTL for an sISEL pattern.  */
 
index 61759949725ff5d21e91cab4f03cb6f6e8e702e8..7a908acb88ee6c8c48f94704dd33b53924a42d34 100644 (file)
    UNSPEC_FUSION_P9
    UNSPEC_FUSION_ADDIS
    UNSPEC_ROUND_TO_ODD
-   UNSPEC_IEEE128_MOVE
-   UNSPEC_IEEE128_CONVERT
    UNSPEC_SIGNBIT
    UNSPEC_SF_FROM_SI
    UNSPEC_SI_FROM_SF
   "")
 
 (define_expand "floatsi<mode>2"
-  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
-        (float:FLOAT128 (match_operand:SI 1 "gpc_reg_operand" "")))]
+  [(parallel [(set (match_operand:FLOAT128 0 "gpc_reg_operand")
+                  (float:FLOAT128 (match_operand:SI 1 "gpc_reg_operand")))
+             (clobber (match_scratch:DI 2))])]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (FLOAT128_IEEE_P (<MODE>mode))
-    rs6000_expand_float128_convert (operands[0], operands[1], false);
+  rtx op0 = operands[0];
+  rtx op1 = operands[1];
+
+  if (TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode))
+    ;
+  else if (FLOAT128_IEEE_P (<MODE>mode))
+    {
+      rs6000_expand_float128_convert (op0, op1, false);
+      DONE;
+    }
   else
     {
       rtx tmp = gen_reg_rtx (DFmode);
-      expand_float (tmp, operands[1], false);
+      expand_float (tmp, op1, false);
       if (<MODE>mode == TFmode)
-       emit_insn (gen_extenddftf2 (operands[0], tmp));
+       emit_insn (gen_extenddftf2 (op0, tmp));
       else if (<MODE>mode == IFmode)
-       emit_insn (gen_extenddfif2 (operands[0], tmp));
+       emit_insn (gen_extenddfif2 (op0, tmp));
       else
        gcc_unreachable ();
+      DONE;
     }
-  DONE;
 })
 
 ; fadd, but rounding towards zero.
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128"
 {
-  if (FLOAT128_IEEE_P (<MODE>mode))
-    rs6000_expand_float128_convert (operands[0], operands[1], false);
-  else if (TARGET_E500_DOUBLE && <MODE>mode == TFmode)
-    emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1]));
-  else if (<MODE>mode == TFmode)
-    emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1]));
-  else if (<MODE>mode == IFmode)
-    emit_insn (gen_fix_truncifsi2_fprs (operands[0], operands[1]));
+  rtx op0 = operands[0];
+  rtx op1 = operands[1];
+
+  if (TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode))
+    ;
   else
-    gcc_unreachable ();
-  DONE;
+    {
+      if (FLOAT128_IEEE_P (<MODE>mode))
+       rs6000_expand_float128_convert (op0, op1, false);
+      else if (TARGET_E500_DOUBLE && <MODE>mode == TFmode)
+       emit_insn (gen_spe_fix_trunctfsi2 (op0, op1));
+      else if (<MODE>mode == TFmode)
+       emit_insn (gen_fix_trunctfsi2_fprs (op0, op1));
+      else if (<MODE>mode == IFmode)
+       emit_insn (gen_fix_truncifsi2_fprs (op0, op1));
+      else
+       gcc_unreachable ();
+      DONE;
+    }
 })
 
 (define_expand "fix_trunc<mode>si2_fprs"
        (fix:DI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128_TYPE"
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
+  if (!TARGET_FLOAT128_HW)
+    {
+      rs6000_expand_float128_convert (operands[0], operands[1], false);
+      DONE;
+    }
 })
 
 (define_expand "fixuns_trunc<IEEE128:mode><SDI:mode>2"
        (float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128_TYPE"
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
+  if (!TARGET_FLOAT128_HW)
+    {
+      rs6000_expand_float128_convert (operands[0], operands[1], false);
+      DONE;
+    }
 })
 
-(define_expand "floatuns<SDI:mode><IEEE128:mode>2"
+(define_expand "floatunsdi<IEEE128:mode>2"
   [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
-       (unsigned_float:IEEE128 (match_operand:SDI 1 "gpc_reg_operand" "")))]
+       (unsigned_float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128_TYPE"
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], true);
+  if (!TARGET_FLOAT128_HW)
+    {
+      rs6000_expand_float128_convert (operands[0], operands[1], true);
+      DONE;
+    }
+})
+
+(define_expand "floatuns<IEEE128:mode>2"
+  [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
+       (unsigned_float:IEEE128 (match_operand:SI 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128_TYPE"
+{
+  rtx op0 = operands[0];
+  rtx op1 = operands[1];
+
+  if (TARGET_FLOAT128_HW)
+    emit_insn (gen_floatuns_<IEEE128:mode>si2_hw (op0, op1));
+  else
+    rs6000_expand_float128_convert (op0, op1, true);
   DONE;
 })
 
   [(set_attr "type" "vecfloat")
    (set_attr "length" "8")])
 
-;; At present SImode is not allowed in VSX registers at all, and DImode is only
-;; allowed in the traditional floating point registers. Use V2DImode so that
-;; we can get a value in an Altivec register.
+;; Conversion between IEEE 128-bit and integer types
+(define_insn "fix_<mode>di2_hw"
+  [(set (match_operand:DI 0 "altivec_register_operand" "=v")
+       (fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
+  "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+  "xscvqpsdz %0,%1"
+  [(set_attr "type" "vecfloat")
+   (set_attr "size" "128")])
 
-(define_insn_and_split "fix<uns>_<mode>si2_hw"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,Z")
-       (any_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v,v")))
-   (clobber (match_scratch:V2DI 2 "=v,v"))]
+(define_insn "fixuns_<mode>di2_hw"
+  [(set (match_operand:DI 0 "altivec_register_operand" "=v")
+       (unsigned_fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
   "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
-  "#"
-  "&& 1"
-  [(pc)]
-{
-  convert_float128_to_int (operands, <CODE>);
-  DONE;
-}
-  [(set_attr "length" "8")
-   (set_attr "type" "mftgpr,fpstore")])
+  "xscvqpudz %0,%1"
+  [(set_attr "type" "vecfloat")
+   (set_attr "size" "128")])
 
-(define_insn_and_split "fix<uns>_<mode>di2_hw"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=wr,wi,Z")
-       (any_fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v,v,v")))
-   (clobber (match_scratch:V2DI 2 "=v,v,v"))]
+(define_insn "fix_<mode>si2_hw"
+  [(set (match_operand:SI 0 "altivec_register_operand" "=v")
+       (fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
   "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
-  "#"
-  "&& 1"
-  [(pc)]
-{
-  convert_float128_to_int (operands, <CODE>);
-  DONE;
-}
-  [(set_attr "length" "8")
-   (set_attr "type" "mftgpr,vecsimple,fpstore")])
+  "xscvqpswz %0,%1"
+  [(set_attr "type" "vecfloat")
+   (set_attr "size" "128")])
 
-(define_insn_and_split "float<uns>_<mode>si2_hw"
-  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v,v")
-       (any_float:IEEE128 (match_operand:SI 1 "nonimmediate_operand" "r,Z")))
-   (clobber (match_scratch:V2DI 2 "=v,v"))]
+(define_insn "fixuns_<mode>si2_hw"
+  [(set (match_operand:SI 0 "altivec_register_operand" "=v")
+       (unsigned_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
   "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
-  "#"
-  "&& 1"
-  [(pc)]
-{
-  convert_int_to_float128 (operands, <CODE>);
-  DONE;
-}
-  [(set_attr "length" "8")
-   (set_attr "type" "vecfloat")])
+  "xscvqpuwz %0,%1"
+  [(set_attr "type" "vecfloat")
+   (set_attr "size" "128")])
 
-(define_insn_and_split "float<uns>_<mode>di2_hw"
-  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v,v,v")
-       (any_float:IEEE128 (match_operand:DI 1 "nonimmediate_operand" "wi,wr,Z")))
-   (clobber (match_scratch:V2DI 2 "=v,v,v"))]
+;; Combiner pattern to prevent moving the result of converting an IEEE 128-bit
+;; floating point value to 32-bit integer to GPR in order to save it.
+(define_insn_and_split "*fix<uns>_<mode>_mem"
+  [(set (match_operand:SI 0 "memory_operand" "=Z")
+       (any_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))
+   (clobber (match_scratch:SI 2 "=v"))]
   "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
-  "&& 1"
-  [(pc)]
-{
-  convert_int_to_float128 (operands, <CODE>);
-  DONE;
-}
-  [(set_attr "length" "8")
-   (set_attr "type" "vecfloat")])
-
-;; Integer conversion instructions, using V2DImode to get an Altivec register
-(define_insn "*xscvqp<su>wz_<mode>"
-  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
-       (unspec:V2DI
-        [(any_fix:SI
-          (match_operand:IEEE128 1 "altivec_register_operand" "v"))]
-        UNSPEC_IEEE128_CONVERT))]
+  "&& reload_completed"
+  [(set (match_dup 2)
+       (any_fix:SI (match_dup 1)))
+   (set (match_dup 0)
+       (match_dup 2))])
+
+(define_insn "float_<mode>di2_hw"
+  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+       (float:IEEE128 (match_operand:DI 1 "altivec_register_operand" "v")))]
   "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
-  "xscvqp<su>wz %0,%1"
+  "xscvsdqp %0,%1"
   [(set_attr "type" "vecfloat")
    (set_attr "size" "128")])
 
-(define_insn "*xscvqp<su>dz_<mode>"
-  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
-       (unspec:V2DI
-        [(any_fix:DI
-          (match_operand:IEEE128 1 "altivec_register_operand" "v"))]
-        UNSPEC_IEEE128_CONVERT))]
+(define_insn_and_split "float_<mode>si2_hw"
+  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+       (float:IEEE128 (match_operand:SI 1 "nonimmediate_operand" "vrZ")))
+   (clobber (match_scratch:DI 2 "=v"))]
   "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
-  "xscvqp<su>dz %0,%1"
-  [(set_attr "type" "vecfloat")
-   (set_attr "size" "128")])
+  "#"
+  "&& 1"
+  [(set (match_dup 2)
+       (sign_extend:DI (match_dup 1)))
+   (set (match_dup 0)
+       (float:IEEE128 (match_dup 2)))]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (DImode);
+})
 
-(define_insn "*xscv<su>dqp_<mode>"
+(define_insn "floatuns_<mode>di2_hw"
   [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
-       (any_float:IEEE128
-        (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v")]
-                   UNSPEC_IEEE128_CONVERT)))]
+       (unsigned_float:IEEE128
+        (match_operand:DI 1 "altivec_register_operand" "v")))]
   "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
-  "xscv<su>dqp %0,%1"
+  "xscvudqp %0,%1"
   [(set_attr "type" "vecfloat")
    (set_attr "size" "128")])
 
-(define_insn "*ieee128_mfvsrd_64bit"
-  [(set (match_operand:DI 0 "reg_or_indexed_operand" "=wr,Z,wi")
-       (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v,v,v")]
-                  UNSPEC_IEEE128_MOVE))]
-  "TARGET_FLOAT128_HW && TARGET_POWERPC64"
-  "@
-   mfvsrd %0,%x1
-   stxsdx %x1,%y0
-   xxlor %x0,%x1,%x1"
-  [(set_attr "type" "mftgpr,fpstore,veclogical")])
-
-
-(define_insn "*ieee128_mfvsrd_32bit"
-  [(set (match_operand:DI 0 "reg_or_indexed_operand" "=Z,wi")
-       (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v,v")]
-                  UNSPEC_IEEE128_MOVE))]
-  "TARGET_FLOAT128_HW && !TARGET_POWERPC64"
-  "@
-   stxsdx %x1,%y0
-   xxlor %x0,%x1,%x1"
-  [(set_attr "type" "fpstore,veclogical")])
-
-(define_insn "*ieee128_mfvsrwz"
-  [(set (match_operand:SI 0 "reg_or_indexed_operand" "=r,Z")
-       (unspec:SI [(match_operand:V2DI 1 "altivec_register_operand" "v,v")]
-                  UNSPEC_IEEE128_MOVE))]
-  "TARGET_FLOAT128_HW"
-  "@
-   mfvsrwz %0,%x1
-   stxsiwx %x1,%y0"
-  [(set_attr "type" "mftgpr,fpstore")])
-
-;; 0 says do sign-extension, 1 says zero-extension
-(define_insn "*ieee128_mtvsrw"
-  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v,v,v,v")
-       (unspec:V2DI [(match_operand:SI 1 "nonimmediate_operand" "r,Z,r,Z")
-                     (match_operand:SI 2 "const_0_to_1_operand" "O,O,n,n")]
-                    UNSPEC_IEEE128_MOVE))]
-  "TARGET_FLOAT128_HW"
-  "@
-   mtvsrwa %x0,%1
-   lxsiwax %x0,%y1
-   mtvsrwz %x0,%1
-   lxsiwzx %x0,%y1"
-  [(set_attr "type" "mffgpr,fpload,mffgpr,fpload")])
-
-
-(define_insn "*ieee128_mtvsrd_64bit"
-  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v,v,v")
-       (unspec:V2DI [(match_operand:DI 1 "nonimmediate_operand" "wr,Z,wi")]
-                    UNSPEC_IEEE128_MOVE))]
-  "TARGET_FLOAT128_HW && TARGET_POWERPC64"
-  "@
-   mtvsrd %x0,%1
-   lxsdx %x0,%y1
-   xxlor %x0,%x1,%x1"
-  [(set_attr "type" "mffgpr,fpload,veclogical")])
-
-(define_insn "*ieee128_mtvsrd_32bit"
-  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v,v")
-       (unspec:V2DI [(match_operand:DI 1 "nonimmediate_operand" "Z,wi")]
-                    UNSPEC_IEEE128_MOVE))]
-  "TARGET_FLOAT128_HW && !TARGET_POWERPC64"
-  "@
-   lxsdx %x0,%y1
-   xxlor %x0,%x1,%x1"
-  [(set_attr "type" "fpload,veclogical")])
+(define_insn_and_split "floatuns_<mode>si2_hw"
+  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+       (unsigned_float:IEEE128
+        (match_operand:SI 1 "nonimmediate_operand" "vrZ")))
+   (clobber (match_scratch:DI 2 "=v"))]
+  "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(set (match_dup 2)
+       (zero_extend:DI (match_dup 1)))
+   (set (match_dup 0)
+       (float:IEEE128 (match_dup 2)))]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (DImode);
+})
 
 ;; IEEE 128-bit instructions with round to odd semantics
 (define_insn "*trunc<mode>df2_odd"