===================================================================
@@ -77,6 +77,7 @@ (define_c_enum "unspec"
UNSPEC_FRIN
UNSPEC_FRIP
UNSPEC_FRIZ
+ UNSPEC_XSRDPI
UNSPEC_LD_MPIC ; load_macho_picbase
UNSPEC_RELD_MPIC ; re-load_macho_picbase
UNSPEC_MPIC_CORRECT ; macho_correct_pic
@@ -491,9 +492,17 @@ (define_mode_attr Fvsx [(SF "sp") (DF "
; SF/DF constraint for arithmetic on traditional floating point registers
(define_mode_attr Ff [(SF "f") (DF "d") (DI "d")])
-; SF/DF constraint for arithmetic on VSX registers
+; SF/DF constraint for arithmetic on VSX registers. This is intended to be
+; used for DFmode instructions added in ISA 2.06 (power7) and SFmode
+; instructions added in ISA 2.07 (power8)
(define_mode_attr Fv [(SF "wy") (DF "ws") (DI "wi")])
+; SF/DF constraint for arithmetic on VSX registers using instructions added in
+; ISA 2.06 (power7). This includes instructions that normally target DF mode,
+; but are used on SFmode, since internally SFmode values are kept in the DFmode
+; format.
+(define_mode_attr Fv2 [(SF "ww") (DF "ws") (DI "wi")])
+
; SF/DF constraint for arithmetic on altivec registers
(define_mode_attr Fa [(SF "wu") (DF "wv")])
@@ -4299,8 +4308,8 @@ (define_expand "abs<mode>2"
"")
(define_insn "*abs<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
- (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
+ (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")))]
"TARGET_<MODE>_FPR"
"@
fabs %0,%1
@@ -4309,10 +4318,10 @@ (define_insn "*abs<mode>2_fpr"
(set_attr "fp_type" "fp_addsub_<Fs>")])
(define_insn "*nabs<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
(neg:SFDF
(abs:SFDF
- (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))))]
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>"))))]
"TARGET_<MODE>_FPR"
"@
fnabs %0,%1
@@ -4327,8 +4336,8 @@ (define_expand "neg<mode>2"
"")
(define_insn "*neg<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
- (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
+ (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")))]
"TARGET_<MODE>_FPR"
"@
fneg %0,%1
@@ -4557,9 +4566,9 @@ (define_expand "copysign<mode>3"
;; Use an unspec rather providing an if-then-else in RTL, to prevent the
;; compiler from optimizing -0.0
(define_insn "copysign<mode>3_fcpsgn"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")]
UNSPEC_COPYSIGN))]
"TARGET_<MODE>_FPR && TARGET_CMPB"
"@
@@ -4593,9 +4602,9 @@ (define_expand "smax<mode>3"
})
(define_insn "*smax<mode>3_vsx"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
- (smax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
+ (smax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
"TARGET_<MODE>_FPR && TARGET_VSX"
"xsmaxdp %x0,%x1,%x2"
[(set_attr "type" "fp")])
@@ -4613,9 +4622,9 @@ (define_expand "smin<mode>3"
})
(define_insn "*smin<mode>3_vsx"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
- (smin:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
+ (smin:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
"TARGET_<MODE>_FPR && TARGET_VSX"
"xsmindp %x0,%x1,%x2"
[(set_attr "type" "fp")])
@@ -4836,7 +4845,7 @@ (define_insn "lfiwax"
; not be needed and also in case the insns are deleted as dead code.
(define_insn_and_split "floatsi<mode>2_lfiwax"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv2>")
(float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
(clobber (match_scratch:DI 2 "=wj"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
@@ -4911,7 +4920,7 @@ (define_insn "lfiwzx"
[(set_attr "type" "fpload,fpload,mftgpr")])
(define_insn_and_split "floatunssi<mode>2_lfiwzx"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv2>")
(unsigned_float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
(clobber (match_scratch:DI 2 "=wj"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
@@ -5346,7 +5355,7 @@ (define_insn "*fixuns_trunc<mode>di2_fct
; before the instruction.
(define_insn "fctiwz_<mode>"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
- (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
+ (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>"))]
UNSPEC_FCTIWZ))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"@
@@ -5357,7 +5366,7 @@ (define_insn "fctiwz_<mode>"
(define_insn "fctiwuz_<mode>"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
(unspec:DI [(unsigned_fix:SI
- (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>"))]
UNSPEC_FCTIWUZ))]
"TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ"
"@
@@ -5458,8 +5467,8 @@ (define_insn "lrint<mode>di2"
[(set_attr "type" "fp")])
(define_insn "btrunc<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")]
UNSPEC_FRIZ))]
"TARGET_<MODE>_FPR && TARGET_FPRND"
"@
@@ -5469,8 +5478,8 @@ (define_insn "btrunc<mode>2"
(set_attr "fp_type" "fp_addsub_<Fs>")])
(define_insn "ceil<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")]
UNSPEC_FRIP))]
"TARGET_<MODE>_FPR && TARGET_FPRND"
"@
@@ -5480,8 +5489,8 @@ (define_insn "ceil<mode>2"
(set_attr "fp_type" "fp_addsub_<Fs>")])
(define_insn "floor<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")]
UNSPEC_FRIM))]
"TARGET_<MODE>_FPR && TARGET_FPRND"
"@
@@ -5500,6 +5509,27 @@ (define_insn "round<mode>2"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_addsub_<Fs>")])
+(define_insn "*xsrdpi<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Fv2>")]
+ UNSPEC_XSRDPI))]
+ "TARGET_<MODE>_FPR && TARGET_VSX"
+ "xsrdpi %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "lround<mode>di2"
+ [(set (match_dup 2)
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "wa")]
+ UNSPEC_XSRDPI))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=d")
+ (unspec:DI [(match_dup 2)]
+ UNSPEC_FCTID))]
+ "TARGET_<MODE>_FPR && TARGET_VSX"
+{
+ operands[2] = gen_reg_rtx (<MODE>mode);
+})
+
; An UNSPEC is used so we don't have to support SImode in FP registers.
(define_insn "stfiwx"
[(set (match_operand:SI 0 "memory_operand" "=Z")