aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r--gcc/config/rs6000/rs6000.md411
1 files changed, 397 insertions, 14 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 49c5c98..1fdc7bb 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -143,6 +143,9 @@
UNSPEC_STACK_CHECK
UNSPEC_FUSION_P9
UNSPEC_FUSION_ADDIS
+ UNSPEC_ROUND_TO_ODD
+ UNSPEC_IEEE128_MOVE
+ UNSPEC_IEEE128_CONVERT
])
;;
@@ -381,6 +384,8 @@
(V2SF "TARGET_PAIRED_FLOAT")
(V4SF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)")
(V2DF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)")
+ (KF "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (KFmode)")
+ (TF "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (TFmode)")
])
; Floating point move iterators to combine binary and decimal moves
@@ -485,10 +490,10 @@
(define_mode_attr Fvsx [(SF "sp") (DF "dp")])
; SF/DF constraint for arithmetic on traditional floating point registers
-(define_mode_attr Ff [(SF "f") (DF "d")])
+(define_mode_attr Ff [(SF "f") (DF "d") (DI "d")])
; SF/DF constraint for arithmetic on VSX registers
-(define_mode_attr Fv [(SF "wy") (DF "ws")])
+(define_mode_attr Fv [(SF "wy") (DF "ws") (DI "wi")])
; SF/DF constraint for arithmetic on altivec registers
(define_mode_attr Fa [(SF "wu") (DF "wv")])
@@ -510,9 +515,31 @@
(define_code_iterator iorxor [ior xor])
; Signed/unsigned variants of ops.
-(define_code_iterator any_extend [sign_extend zero_extend])
-(define_code_attr u [(sign_extend "") (zero_extend "u")])
-(define_code_attr su [(sign_extend "s") (zero_extend "u")])
+(define_code_iterator any_extend [sign_extend zero_extend])
+(define_code_iterator any_fix [fix unsigned_fix])
+(define_code_iterator any_float [float unsigned_float])
+
+(define_code_attr u [(sign_extend "")
+ (zero_extend "u")])
+
+(define_code_attr su [(sign_extend "s")
+ (zero_extend "u")
+ (fix "s")
+ (unsigned_fix "s")
+ (float "s")
+ (unsigned_float "u")])
+
+(define_code_attr az [(sign_extend "a")
+ (zero_extend "z")
+ (fix "a")
+ (unsigned_fix "z")
+ (float "a")
+ (unsigned_float "z")])
+
+(define_code_attr uns [(fix "")
+ (unsigned_fix "uns")
+ (float "")
+ (unsigned_float "uns")])
; Various instructions that come in SI and DI forms.
; A generic w/d attribute, for things like cmpw/cmpd.
@@ -2815,6 +2842,14 @@
DONE;
})
+(define_insn "*maddld4"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (plus:DI (mult:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (match_operand:DI 3 "gpc_reg_operand" "r")))]
+ "TARGET_MADDLD"
+ "maddld %0,%1,%2,%3"
+ [(set_attr "type" "mul")])
(define_insn "udiv<mode>3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
@@ -7003,7 +7038,16 @@
{
if (FLOAT128_IEEE_P (<MODE>mode))
{
- if (TARGET_FLOAT128)
+ if (TARGET_FLOAT128_HW)
+ {
+ if (<MODE>mode == TFmode)
+ emit_insn (gen_negtf2_hw (operands[0], operands[1]));
+ else if (<MODE>mode == KFmode)
+ emit_insn (gen_negkf2_hw (operands[0], operands[1]));
+ else
+ gcc_unreachable ();
+ }
+ else if (TARGET_FLOAT128)
{
if (<MODE>mode == TFmode)
emit_insn (gen_ieee_128bit_vsx_negtf2 (operands[0], operands[1]));
@@ -7053,7 +7097,17 @@
if (FLOAT128_IEEE_P (<MODE>mode))
{
- if (TARGET_FLOAT128)
+ if (TARGET_FLOAT128_HW)
+ {
+ if (<MODE>mode == TFmode)
+ emit_insn (gen_abstf2_hw (operands[0], operands[1]));
+ else if (<MODE>mode == KFmode)
+ emit_insn (gen_abskf2_hw (operands[0], operands[1]));
+ else
+ FAIL;
+ DONE;
+ }
+ else if (TARGET_FLOAT128)
{
if (<MODE>mode == TFmode)
emit_insn (gen_ieee_128bit_vsx_abstf2 (operands[0], operands[1]));
@@ -7140,7 +7194,7 @@
[(set (match_operand:IEEE128 0 "register_operand" "=wa")
(neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
(clobber (match_scratch:V16QI 2 "=v"))]
- "TARGET_FLOAT128"
+ "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
"#"
"&& 1"
[(parallel [(set (match_dup 0)
@@ -7160,7 +7214,7 @@
[(set (match_operand:IEEE128 0 "register_operand" "=wa")
(neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
(use (match_operand:V16QI 2 "register_operand" "=v"))]
- "TARGET_FLOAT128"
+ "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
"xxlxor %x0,%x1,%x2"
[(set_attr "type" "vecsimple")])
@@ -7169,7 +7223,7 @@
[(set (match_operand:IEEE128 0 "register_operand" "=wa")
(abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
(clobber (match_scratch:V16QI 2 "=v"))]
- "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+ "TARGET_FLOAT128 && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"#"
"&& 1"
[(parallel [(set (match_dup 0)
@@ -7189,7 +7243,7 @@
[(set (match_operand:IEEE128 0 "register_operand" "=wa")
(abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
(use (match_operand:V16QI 2 "register_operand" "=v"))]
- "TARGET_FLOAT128"
+ "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
"xxlandc %x0,%x1,%x2"
[(set_attr "type" "vecsimple")])
@@ -7200,7 +7254,7 @@
(abs:IEEE128
(match_operand:IEEE128 1 "register_operand" "wa"))))
(clobber (match_scratch:V16QI 2 "=v"))]
- "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+ "TARGET_FLOAT128 && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"#"
"&& 1"
[(parallel [(set (match_dup 0)
@@ -7222,7 +7276,7 @@
(abs:IEEE128
(match_operand:IEEE128 1 "register_operand" "wa"))))
(use (match_operand:V16QI 2 "register_operand" "=v"))]
- "TARGET_FLOAT128"
+ "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
"xxlor %x0,%x1,%x2"
[(set_attr "type" "vecsimple")])
@@ -7480,7 +7534,10 @@
(match_operand:FMOVE128_GPR 1 "input_operand" ""))]
"reload_completed
&& (int_reg_operand (operands[0], <MODE>mode)
- || int_reg_operand (operands[1], <MODE>mode))"
+ || int_reg_operand (operands[1], <MODE>mode))
+ && (!TARGET_DIRECT_MOVE_128
+ || (!vsx_register_operand (operands[0], <MODE>mode)
+ && !vsx_register_operand (operands[1], <MODE>mode)))"
[(pc)]
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
@@ -12998,6 +13055,332 @@
+;; ISA 2.08 IEEE 128-bit floating point support.
+
+(define_insn "add<mode>3"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (plus:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsaddqp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "sub<mode>3"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (minus:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xssubqp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "mul<mode>3"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (mult:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsmulqp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "div<mode>3"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (div:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsdivqp %0,%1,%2"
+ [(set_attr "type" "vecdiv")])
+
+(define_insn "sqrt<mode>2"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (sqrt:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xssqrtqp %0,%1"
+ [(set_attr "type" "vecdiv")])
+
+(define_insn "copysign<mode>3"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (unspec:IEEE128
+ [(match_operand:IEEE128 1 "altivec_register_operand" "v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")]
+ UNSPEC_COPYSIGN))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xscpsgnqp %0,%2,%1"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "neg<mode>2_hw"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (neg:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsnegqp %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+
+(define_insn "abs<mode>2_hw"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (abs:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsabsqp %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+
+(define_insn "*nabs<mode>2_hw"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (neg:IEEE128
+ (abs:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "v"))))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsnabsqp %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+;; Initially don't worry about doing fusion
+(define_insn "*fma<mode>4_hw"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (fma:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "%v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")
+ (match_operand:IEEE128 3 "altivec_register_operand" "0")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsmaddqp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "*fms<mode>4_hw"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (fma:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "%v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")
+ (neg:IEEE128
+ (match_operand:IEEE128 3 "altivec_register_operand" "0"))))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsmsubqp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "*nfma<mode>4_hw"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (neg:IEEE128
+ (fma:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "%v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")
+ (match_operand:IEEE128 3 "altivec_register_operand" "0"))))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsnmaddqp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "*nfms<mode>4_hw"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (neg:IEEE128
+ (fma:IEEE128
+ (match_operand:IEEE128 1 "altivec_register_operand" "%v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")
+ (neg:IEEE128
+ (match_operand:IEEE128 3 "altivec_register_operand" "0")))))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xsnmsubqp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "extend<SFDF:mode><IEEE128:mode>2_hw"
+ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+ (float_extend:IEEE128
+ (match_operand:SFDF 1 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<IEEE128:MODE>mode)"
+ "xscvdpqp %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "trunc<mode>df2_hw"
+ [(set (match_operand:DF 0 "altivec_register_operand" "=v")
+ (float_truncate:DF
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xscvqpdp %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+;; There is no KFmode -> SFmode instruction. Preserve the accuracy by doing
+;; the KFmode -> DFmode conversion using round to odd rather than the normal
+;; conversion
+(define_insn_and_split "trunc<mode>sf2_hw"
+ [(set (match_operand:SF 0 "vsx_register_operand" "=wy")
+ (float_truncate:SF
+ (match_operand:IEEE128 1 "altivec_register_operand" "v")))
+ (clobber (match_scratch:DF 2 "=v"))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "#"
+ "&& 1"
+ [(set (match_dup 2)
+ (unspec:DF [(match_dup 1)] UNSPEC_ROUND_TO_ODD))
+ (set (match_dup 0)
+ (float_truncate:SF (match_dup 2)))]
+{
+ if (GET_CODE (operands[2]) == SCRATCH)
+ operands[2] = gen_reg_rtx (DFmode);
+}
+ [(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.
+
+(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"))]
+ "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")])
+
+(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"))]
+ "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")])
+
+(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"))]
+ "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")])
+
+(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"))]
+ "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))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xscvqp<su>wz %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+(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))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xscvqp<su>dz %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "*xscv<su>dqp_<mode>"
+ [(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)))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xscv<su>dqp %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "*ieee128_mfvsrd"
+ [(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,vecsimple,fpstore")])
+
+(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"
+ [(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"
+ "@
+ mtvsrd %x0,%1
+ lxsdx %x0,%y1
+ xxlor %x0,%x1,%x1"
+ [(set_attr "type" "mffgpr,fpload,vecsimple")])
+
+;; IEEE 128-bit instructions with round to odd semantics
+(define_insn "*trunc<mode>df2_odd"
+ [(set (match_operand:DF 0 "vsx_register_operand" "=v")
+ (unspec:DF [(match_operand:IEEE128 1 "altivec_register_operand" "v")]
+ UNSPEC_ROUND_TO_ODD))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xscvqpdpo %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+;; IEEE 128-bit comparisons
+(define_insn "*cmp<mode>_hw"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (compare:CCFP (match_operand:IEEE128 1 "altivec_register_operand" "v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xscmpuqp %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
+
(include "sync.md")
(include "vector.md")