diff mbox

, PowerPC IEEE 128-bit patch #5

Message ID 20150814154603.GA20847@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Aug. 14, 2015, 3:46 p.m. UTC
There are 3 patches left in the basic IEEE 128-bit floating point support for
the compiler. I will submit these at the same time. They are split to make the
review process similar.  Patch #5 and #6 are indpendent of each other and can
be applied in either order. Patch #7 assumes that patches 1-6 have been
applied.

Patch #5 adds the following:
 * Support for the reload handlers that will be enabled in patch #7.
 * Adds IFmode/KFmode to other iterators as appropriate.
 * Adds the basic negate, absolute value, and negative absolute value support.
 * Adds the insns for the 128-bit pack/unpack routines.

Patch #6 adds the following:
 * Adds support for comparisons.
 * Updates the cannot change mode support.

Patch #7 finishes up the initial basic support.
 * It defines macros for IEEE 128-bit floating point users.
 * It defines the basic move support.
 * It sets up the calling sequence.
 * It registers the __float128 and __ibm128 keywords.
 * It sets up the various handler functions.
 * It adds 'q' and 'Q' as the suffix for IEEE 128-bit floating point.
 * It adds target attribute/pragma support for the IEEE 128-bit options.
 * It treats IEEE 128-bit in VSX register modes as vector.
 * It uses a unique mangling for IEEE 128-bit in VSX registers.
 * It moves vector modes tieable above scalar floating point.
 * It adds a simple minded test to make sure IEEE args are passed as vectors.

Things to be done:
 * Work with GDB to add debug support.
 * Work with GLIBC to add basic software emulation support.
 * Work with GLIBC on other IEEE 128-bit support.
 * Look into Complex support.
 * Look into libquadmath support.
 * Enable -mfloat128-software if -mvsx.
 * Add more tests.
 * Fix bugs that show up if -mabi=ieeelongdouble is used.

Each patch bootstraps without error and has no regressions. Are they ok to
install in the trunk?

This is patch #5:

2015-08-13  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/predicates.md (int_reg_operand_not_pseudo): New
	predicate for only GPR hard registers.

	* config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point
	modes to iterators. Add new iterators for moving 128-bit values in
	scalar FPR registers and VSX registers.
	(FMOVE128): Likewise.
	(FMOVE128_FPR): Likewise.
	(FMOVE128_GPR): Likewise.
	(FMOVE128_VSX): Likewise.
	(FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point
	in VSX registers.
	(IFKF): Likewise.
	(IBM128): Likewise.
	(TFIFKF): Likewise.
	(RELOAD): Add IEEE 128-bit floating point modes.
	(signbittf2): Convert TF insns to add support for new IEEE 128-bit
	floating point in VSX registers modes.
	(signbit<mode>2, IBM128 iterator): Likewise.
	(mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise.
	(mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.
	(negtf2): Likewise.
	(neg<mode>2, TFIFKF iterator): Likewise.
	(negtf2_internal): Likewise.
	(abstf2): Likewise.
	(abs<mode>2, TFIFKF iterator): Likewise.
	(ieee_128bit_negative_zero): New IEEE 128-bit floating point in
	VSX insn support for negate, absolute value, and negative absolute
	value.
	(ieee_128bit_vsx_neg<mode>2): Likewise.
	(ieee_128bit_vsx_neg<mode>2_internal): Likewise.
	(ieee_128bit_vsx_abs<mode>2): Likewise.
	(ieee_128bit_vsx_abs<mode>2_internal): Likewise.
	(ieee_128bit_vsx_nabs<mode>2): Likewise.
	(ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
	(FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit
	floating point in VSX registers.
	(unpack<mode>_dm): Likewise.
	(unpack<mode>_nodm): Likewise.
	(pack<mode>): Likewise.
	(unpackv1ti): Likewise.
	(unpack<mode>, FMOVE128_VSX iterator): Likewise.
	(packv1ti): Likewise.
	(pack<mode>, FMOVE128_VSX iterator): Likewise.

Comments

Segher Boessenkool Aug. 19, 2015, 12:41 p.m. UTC | #1
On Fri, Aug 14, 2015 at 11:46:03AM -0400, Michael Meissner wrote:
> +;; Like int_reg_operand, but don't return true for pseudo registers
> +(define_predicate "int_reg_operand_not_pseudo"
> +  (match_operand 0 "register_operand")
> +{
> +  if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
> +    return 0;
> +
> +  if (GET_CODE (op) == SUBREG)
> +    op = SUBREG_REG (op);
> +
> +  if (!REG_P (op))
> +    return 0;
> +
> +  if (REGNO (op) >= FIRST_PSEUDO_REGISTER)
> +    return 0;
> +
> +  return INT_REGNO_P (REGNO (op));
> +})

Since you use this only once, maybe it is easier (to read, etc.) if you
just test it there?  Hard regs do not get subregs.

> +(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
> +  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
> +	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
> +   (clobber (match_scratch:V16QI 2 "=v"))]
> +  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
> +  "#"
> +  "&& 1"
> +  [(parallel [(set (match_dup 0)
> +		   (neg:TFIFKF (match_dup 1)))
> +	      (use (match_dup 2))])]
> +{
> +  if (GET_CODE (operands[2]) == SCRATCH)
> +    operands[2] = gen_reg_rtx (V16QImode);
> +
> +  operands[3] = gen_reg_rtx (V16QImode);
> +  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
> +}
> +  [(set_attr "length" "8")
> +   (set_attr "type" "vecsimple")])

Where is operands[3] used?  I guess that whole line should be deleted?

> +(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
> +  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
> +	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
> +   (use (match_operand:V16QI 2 "register_operand" "=v"))]
> +  "TARGET_FLOAT128"
> +  "xxlxor %x0,%x1,%x2"
> +  [(set_attr "length" "4")
> +   (set_attr "type" "vecsimple")])

Length 4 is default, you can just leave it out (like we do for most
machine insns already).


Segher
diff mbox

Patch

Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 226869)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -239,6 +239,25 @@  (define_predicate "int_reg_operand"
   return INT_REGNO_P (REGNO (op));
 })
 
+;; Like int_reg_operand, but don't return true for pseudo registers
+(define_predicate "int_reg_operand_not_pseudo"
+  (match_operand 0 "register_operand")
+{
+  if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
+    return 0;
+
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (!REG_P (op))
+    return 0;
+
+  if (REGNO (op) >= FIRST_PSEUDO_REGISTER)
+    return 0;
+
+  return INT_REGNO_P (REGNO (op));
+})
+
 ;; Like int_reg_operand, but only return true for base registers
 (define_predicate "base_reg_operand"
   (match_operand 0 "int_reg_operand")
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 226869)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -348,6 +348,8 @@  (define_mode_iterator FP [
    && TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128")
+  (IF "TARGET_FLOAT128")
+  (KF "TARGET_FLOAT128")
   (DD "TARGET_DFP")
   (TD "TARGET_DFP")])
 
@@ -365,9 +367,14 @@  (define_mode_iterator FMA_F [
 (define_mode_iterator FMOVE32 [SF SD])
 (define_mode_iterator FMOVE64 [DF DD])
 (define_mode_iterator FMOVE64X [DI DF DD])
-(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128")
+(define_mode_iterator FMOVE128 [(TF "TARGET_LONG_DOUBLE_128")
+				(IF "TARGET_LONG_DOUBLE_128")
 				(TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
 
+(define_mode_iterator FMOVE128_FPR [(TF "FLOAT128_2REG_P (TFmode)")
+				    (IF "FLOAT128_2REG_P (IFmode)")
+				    (TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
+
 ; Iterators for 128 bit types for direct move
 (define_mode_iterator FMOVE128_GPR [(TI    "TARGET_VSX_TIMODE")
 				    (V16QI "")
@@ -376,7 +383,13 @@  (define_mode_iterator FMOVE128_GPR [(TI 
 				    (V4SF  "")
 				    (V2DI  "")
 				    (V2DF  "")
-				    (V1TI  "")])
+				    (V1TI  "")
+				    (KF    "")
+				    (TF    "")
+				    (IF    "")])
+
+; Iterator for 128-bit VSX types for pack/unpack
+(define_mode_iterator FMOVE128_VSX [V1TI KF])
 
 ; Whether a floating point move is ok, don't allow SD without hardware FP
 (define_mode_attr fmove_ok [(SF "")
@@ -432,6 +445,25 @@  (define_mode_iterator RECIPF [SF DF V4SF
 ; Iterator for just SF/DF
 (define_mode_iterator SFDF [SF DF])
 
+; Iterator for float128 floating conversions
+(define_mode_iterator FLOAT128_SFDFTF [
+    (SF "TARGET_FLOAT128")
+    (DF "TARGET_FLOAT128")
+    (TF "FLOAT128_IBM_P (TFmode)")
+    (IF "TARGET_FLOAT128")])
+
+; Iterator for special 128-bit floating point.  This is for non-default
+; conversions, so TFmode is not used here.
+(define_mode_iterator IFKF [IF KF])
+
+; Iterator for 128-bit floating point that uses the IBM double-double format
+(define_mode_iterator IBM128 [IF TF])
+
+; Iterator for 128-bit floating point
+(define_mode_iterator TFIFKF [(KF "TARGET_FLOAT128")
+			      (IF "TARGET_FLOAT128")
+			      (TF "TARGET_LONG_DOUBLE_128")])
+
 ; SF/DF suffix for traditional floating instructions
 (define_mode_attr Ftrad		[(SF "s") (DF "")])
 
@@ -596,7 +628,7 @@  (define_mode_attr BOOL_REGS_UNARY	[(TI	"
 ;; Reload iterator for creating the function to allocate a base register to
 ;; supplement addressing modes.
 (define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI
-			      SF SD SI DF DD DI TI PTI])
+			      SF SD SI DF DD DI TI PTI KF IF TF])
 
 
 ;; Start with fixed-point load and store insns.  Here we put only the more
@@ -4216,19 +4248,18 @@  (define_insn "*truncdfsf2_fpr"
 ;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
 ;; builtins.c and optabs.c that are not correct for IBM long double
 ;; when little-endian.
-(define_expand "signbittf2"
+(define_expand "signbit<mode>2"
   [(set (match_dup 2)
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
+	(float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "")))
    (set (match_dup 3)
    	(subreg:DI (match_dup 2) 0))
    (set (match_dup 4)
    	(match_dup 5))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
   	(match_dup 6))]
-  "!TARGET_IEEEQUAD
+  "FLOAT128_IBM_P (<MODE>mode)
    && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)"
 {
   operands[2] = gen_reg_rtx (DFmode);
   operands[3] = gen_reg_rtx (DImode);
@@ -6402,9 +6433,10 @@  (define_expand "mov<mode>"
 ;; problematical.  Don't allow direct move for this case.
 
 (define_insn_and_split "*mov<mode>_64bit_dm"
-  [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
-	(match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
+  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
+   && FLOAT128_2REG_P (<MODE>mode)
    && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
@@ -6427,9 +6459,12 @@  (define_insn_and_split "*movtd_64bit_nod
   [(set_attr "length" "8,8,8,8,12,12,8")])
 
 (define_insn_and_split "*mov<mode>_32bit"
-  [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
-	(match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r"))]
+  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64
+   && (FLOAT128_2REG_P (<MODE>mode)
+       || int_reg_operand_not_pseudo (operands[0], <MODE>mode)
+       || int_reg_operand_not_pseudo (operands[1], <MODE>mode))
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
   "#"
@@ -6663,20 +6698,37 @@  (define_insn_and_split "*fix_trunctfsi2_
   DONE;
 })
 
-(define_expand "negtf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(neg:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
-  "")
+(define_expand "neg<mode>2"
+  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  "FLOAT128_IEEE_P (<MODE>mode)
+   || (FLOAT128_IBM_P (<MODE>mode)
+       && TARGET_HARD_FLOAT
+       && (TARGET_FPRS || TARGET_E500_DOUBLE))"
+  "
+{
+  if (FLOAT128_IEEE_P (<MODE>mode))
+    {
+      if (TARGET_FLOAT128)
+	emit_insn (gen_ieee_128bit_vsx_neg<mode>2 (operands[0], operands[1]));
+      else
+	{
+	  rtx libfunc = optab_libfunc (neg_optab, <MODE>mode);
+	  rtx target = emit_library_call_value (libfunc, operands[0], LCT_CONST,
+						<MODE>mode, 1,
+						operands[1], <MODE>mode);
+
+	  if (target && !rtx_equal_p (target, operands[0]))
+	    emit_move_insn (operands[0], target);
+	}
+      DONE;
+    }
+}")
 
 (define_insn "negtf2_internal"
   [(set (match_operand:TF 0 "gpc_reg_operand" "=d")
 	(neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)"
   "*
 {
   if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
@@ -6687,16 +6739,29 @@  (define_insn "negtf2_internal"
   [(set_attr "type" "fp")
    (set_attr "length" "8")])
 
-(define_expand "abstf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(abs:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
+(define_expand "abs<mode>2"
+  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  "FLOAT128_IEEE_P (<MODE>mode)
+   || (FLOAT128_IBM_P (<MODE>mode)
+       && TARGET_HARD_FLOAT
+       && (TARGET_FPRS || TARGET_E500_DOUBLE))"
   "
 {
-  rtx label = gen_label_rtx ();
+  rtx label;
+
+  if (FLOAT128_IEEE_P (<MODE>mode))
+    {
+      if (TARGET_FLOAT128)
+	{
+	  emit_insn (gen_ieee_128bit_vsx_abs<mode>2 (operands[0], operands[1]));
+	  DONE;
+	}
+      else
+	FAIL;
+    }
+
+  label = gen_label_rtx ();
   if (TARGET_E500_DOUBLE)
     {
       if (flag_finite_math_only && !flag_trapping_math)
@@ -6732,6 +6797,129 @@  (define_expand "abstf2_internal"
   operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
   operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
 }")
+
+
+;; Generate IEEE 128-bit -0.0 (0x80000000000000000000000000000000) in a vector
+;; register
+
+(define_expand "ieee_128bit_negative_zero"
+  [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))]
+  "TARGET_FLOAT128"
+{
+  rtvec v = rtvec_alloc (16);
+  int i, high;
+
+  for (i = 0; i < 16; i++)
+    RTVEC_ELT (v, i) = const0_rtx;
+
+  high = (BYTES_BIG_ENDIAN) ? 0 : 15;
+  RTVEC_ELT (v, high) = GEN_INT (0x80);
+
+  rs6000_expand_vector_init (operands[0], gen_rtx_PARALLEL (V16QImode, v));
+  DONE;
+})
+
+;; IEEE 128-bit negate
+
+;; We have 2 insns here for negate and absolute value.  The first uses
+;; match_scratch so that phases like combine can recognize neg/abs as generic
+;; insns, and second insn after the first split pass loads up the bit to
+;; twiddle the sign bit.  Later GCSE passes can then combine multiple uses of
+;; neg/abs to create the constant just once.
+
+(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (neg:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlxor %x0,%x1,%x2"
+  [(set_attr "length" "4")
+   (set_attr "type" "vecsimple")])
+
+;; IEEE 128-bit absolute value
+(define_insn_and_split "ieee_128bit_vsx_abs<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (abs:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_abs<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlandc %x0,%x1,%x2"
+  [(set_attr "length" "4")
+   (set_attr "type" "vecsimple")])
+
+;; IEEE 128-bit negative absolute value
+(define_insn_and_split "*ieee_128bit_vsx_nabs<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF
+	 (abs:TFIFKF
+	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (abs:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_nabs<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF
+	 (abs:TFIFKF
+	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlor %x0,%x1,%x2"
+  [(set_attr "length" "4")
+   (set_attr "type" "vecsimple")])
+
 
 ;; Reload helper functions used by rs6000_secondary_reload.  The patterns all
 ;; must have 3 arguments, and scratch register constraint must be a single
@@ -12134,7 +12322,10 @@  (define_insn "div<div_extend>_<mode>"
 ;; Pack/unpack 128-bit floating point types that take 2 scalar registers
 
 ; Type of the 64-bit part when packing/unpacking 128-bit floating point types
-(define_mode_attr FP128_64 [(TF "DF") (TD "DI")])
+(define_mode_attr FP128_64 [(TF "DF")
+			    (IF "DF")
+			    (TD "DI")
+			    (KF "DI")])
 
 (define_expand "unpack<mode>"
   [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
@@ -12142,7 +12333,7 @@  (define_expand "unpack<mode>"
 	 [(match_operand:FMOVE128 1 "register_operand" "")
 	  (match_operand:QI 2 "const_0_to_1_operand" "")]
 	 UNSPEC_UNPACK_128BIT))]
-  ""
+  "FLOAT128_2REG_P (<MODE>mode)"
   "")
 
 (define_insn_and_split "unpack<mode>_dm"
@@ -12151,7 +12342,7 @@  (define_insn_and_split "unpack<mode>_dm"
 	 [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+  "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 0) (match_dup 3))]
@@ -12175,7 +12366,7 @@  (define_insn_and_split "unpack<mode>_nod
 	 [(match_operand:FMOVE128 1 "register_operand" "d,d")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE"
+  "(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 0) (match_dup 3))]
@@ -12199,7 +12390,7 @@  (define_insn_and_split "pack<mode>"
 	 [(match_operand:<FP128_64> 1 "register_operand" "0,d")
 	  (match_operand:<FP128_64> 2 "register_operand" "d,d")]
 	 UNSPEC_PACK_128BIT))]
-  ""
+  "FLOAT128_2REG_P (<MODE>mode)"
   "@
    fmr %L0,%2
    #"
@@ -12219,12 +12410,12 @@  (define_insn_and_split "pack<mode>"
   [(set_attr "type" "fp,fp")
    (set_attr "length" "4,8")])
 
-(define_insn "unpackv1ti"
+(define_insn "unpack<mode>"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
-	(unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa")
+	(unspec:DI [(match_operand:FMOVE128_VSX 1 "register_operand" "0,wa")
 		    (match_operand:QI 2 "const_0_to_1_operand" "O,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "TARGET_VSX"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
 {
   if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0)
     return ASM_COMMENT_START " xxpermdi to same register";
@@ -12235,9 +12426,9 @@  (define_insn "unpackv1ti"
   [(set_attr "type" "vecperm")
    (set_attr "length" "4")])
 
-(define_insn "packv1ti"
-  [(set (match_operand:V1TI 0 "register_operand" "=wa")
-	(unspec:V1TI
+(define_insn "pack<mode>"
+  [(set (match_operand:FMOVE128_VSX 0 "register_operand" "=wa")
+	(unspec:FMOVE128_VSX
 	 [(match_operand:DI 1 "register_operand" "d")
 	  (match_operand:DI 2 "register_operand" "d")]
 	 UNSPEC_PACK_128BIT))]