; Iterator for just SF/DF
(define_mode_iterator SFDF [SF DF])
+; SF/DF suffix for traditional floating instructions
+(define_mode_attr Ftrad [(SF "s") (DF "")])
+
+; SF/DF suffix for VSX instructions
+(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")])
+
+; SF/DF constraint for arithmetic on VSX registers
+(define_mode_attr Fv [(SF "wy") (DF "ws")])
+
+; s/d suffix for things like fp_addsub_s/fp_addsub_d
+(define_mode_attr Fs [(SF "s") (DF "d")])
+
+; FRE/FRES support
+(define_mode_attr Ffre [(SF "fres") (DF "fre")])
+(define_mode_attr FFRE [(SF "FRES") (DF "FRE")])
+
; Conditional returns.
(define_code_iterator any_return [return simple_return])
(define_code_attr return_pred [(return "direct_return ()")
(const_int 0)))]
"")
-;; Floating-point insns, excluding normal data motion.
-;;
-;; PowerPC has a full set of single-precision floating point instructions.
-;;
-;; For the POWER architecture, we pretend that we have both SFmode and
-;; DFmode insns, while, in fact, all fp insns are actually done in double.
-;; The only conversions we will do will be when storing to memory. In that
-;; case, we will use the "frsp" instruction before storing.
-;;
-;; Note that when we store into a single-precision memory location, we need to
-;; use the frsp insn first. If the register being stored isn't dead, we
-;; need a scratch register for the frsp. But this is difficult when the store
-;; is done by reload. It is not incorrect to do the frsp on the register in
-;; this case, we just lose precision that we would have otherwise gotten but
-;; is not guaranteed. Perhaps this should be tightened up at some point.
+\f
+;; Floating-point insns, excluding normal data motion. We combine the SF/DF
+;; modes here, and also add in conditional vsx/power8-vector support to access
+;; values in the traditional Altivec registers if the appropriate
+;; -mupper-regs-{df,sf} option is enabled.
+
+(define_expand "abs<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(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>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fabs %0,%1
+ xsabsdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_insn "*nabs<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (neg:SFDF
+ (abs:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnabs %0,%1
+ xsnabsdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "neg<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(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>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fneg %0,%1
+ xsnegdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "add<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*add<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fadd<Ftrad> %0,%1,%2
+ xsadd<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "sub<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+(define_insn "*sub<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fsub<Ftrad> %0,%1,%2
+ xssub<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "mul<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*mul<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmul<Ftrad> %0,%1,%2
+ xsmul<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "dmul")
+ (set_attr "fp_type" "fp_mul_<Fs>")])
+
+(define_expand "div<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN && !TARGET_SIMPLE_FPU"
+ "")
+
+(define_insn "*div<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU"
+ "@
+ fdiv<Ftrad> %0,%1,%2
+ xsdiv<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "<Fs>div")
+ (set_attr "fp_type" "fp_div_<Fs>")])
+
+(define_insn "sqrt<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
+ && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
+ "@
+ fsqrt<Ftrad> %0,%1
+ xssqrt<Fvsx> %x0,%x1"
+ [(set_attr "type" "<Fs>sqrt")
+ (set_attr "fp_type" "fp_sqrt_<Fs>")])
+
+;; Floating point reciprocal approximation
+(define_insn "fre<Fs>"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ UNSPEC_FRES))]
+ "TARGET_<FFRE>"
+ "@
+ fre<Ftrad> %0,%1
+ xsre<Fvsx> %x0,%x1"
+ [(set_attr "type" "fp")])
+
+(define_insn "*rsqrt<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ UNSPEC_RSQRT))]
+ "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
+ "@
+ frsqrte<Ftrad> %0,%1
+ xsrsqrte<Fvsx> %x0,%x1"
+ [(set_attr "type" "fp")])
+
+;; Floating point comparisons
+(define_insn "*cmp<mode>_fpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
+ (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fcmpu %0,%1,%2
+ xscmpudp %x0,%x1,%x2"
+ [(set_attr "type" "fpcompare")])
+
+;; Floating point conversions
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))]
"frsp %0,%1"
[(set_attr "type" "fp")])
-(define_expand "negsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (neg:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn "*negsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fneg %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "abssf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn "*abssf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "addsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (plus:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (plus:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fadds %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_s")])
-
-(define_expand "subsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (minus:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fsubs %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_s")])
-
-(define_expand "mulsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (mult:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmuls %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_mul_s")])
-
-(define_expand "divsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (div:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (div:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "fdivs %0,%1,%2"
- [(set_attr "type" "sdiv")])
-
-(define_insn "fres"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
- "TARGET_FRES"
- "fres %0,%1"
- [(set_attr "type" "fp")])
-
-; builtin fmaf support
-(define_insn "*fmasf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmadds %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*fmssf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmsubs %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*nfmasf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnmadds %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*nfmssf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f")))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnmsubs %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_expand "sqrtsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "(TARGET_PPC_GPOPT || TARGET_XILINX_FPU)
- && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
- && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "(TARGET_PPC_GPOPT || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT
- && TARGET_FPRS && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "fsqrts %0,%1"
- [(set_attr "type" "ssqrt")])
-
-(define_insn "*rsqrtsf_internal1"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")]
- UNSPEC_RSQRT))]
- "TARGET_FRSQRTES"
- "frsqrtes %0,%1"
- [(set_attr "type" "fp")])
-
;; 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.
;; 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" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<rreg2>")]
+ [(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>")]
UNSPEC_COPYSIGN))]
- "TARGET_CMPB && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "fcpsgn %0,%2,%1"
+ "TARGET_<MODE>_FPR && TARGET_CMPB"
+ "@
+ fcpsgn %0,%2,%1
+ xscpsgn<VSs> %x0,%x2,%x1"
[(set_attr "type" "fp")])
;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
;; fsel instruction and some auxiliary computations. Then we just have a
;; single DEFINE_INSN for fsel and the define_splits to make them if made by
;; combine.
-(define_expand "smaxsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" ""))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
+;; For MIN, MAX on non-VSX machines, and conditional move all of the time, we
+;; use DEFINE_EXPAND's that involve a fsel instruction and some auxiliary
+;; computations. Then we just have a single DEFINE_INSN for fsel and the
+;; define_splits to make them if made by combine. On VSX machines we have the
+;; min/max instructions.
+;;
+;; On VSX, we only check for TARGET_VSX instead of checking for a vsx/p8 vector
+;; to allow either DF/SF to use only traditional registers.
-(define_expand "sminsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" ""))
- (match_dup 2)
- (match_dup 1)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
+(define_expand "smax<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" ""))
+ (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
+{
+ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
+ DONE;
+})
+
+(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>")))]
+ "TARGET_<MODE>_FPR && TARGET_VSX"
+ "xsmaxdp %x0,%x1,%x2"
+ [(set_attr "type" "fp")])
+
+(define_expand "smin<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" ""))
+ (match_dup 2)
+ (match_dup 1)))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
+{
+ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
+ DONE;
+})
+
+(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>")))]
+ "TARGET_<MODE>_FPR && TARGET_VSX"
+ "xsmindp %x0,%x1,%x2"
+ [(set_attr "type" "fp")])
+
+(define_split
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (match_operator:SFDF 3 "min_max_operator"
+ [(match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")]))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math
+ && !TARGET_VSX"
+ [(const_int 0)]
+{
+ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]), operands[1],
+ operands[2]);
+ DONE;
+})
(define_split
[(set (match_operand:SF 0 "gpc_reg_operand" "")
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
-(define_expand "negdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (neg:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*negdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fneg %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "absdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*absdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn "*nabsdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fnabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "adddf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (plus:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*adddf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fadd %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_expand "subdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*subdf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fsub %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_expand "muldf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*muldf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fmul %0,%1,%2"
- [(set_attr "type" "dmul")
- (set_attr "fp_type" "fp_mul_d")])
-
-(define_expand "divdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (div:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT
- && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)
- && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn "*divdf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (div:DF (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fdiv %0,%1,%2"
- [(set_attr "type" "ddiv")])
-
-(define_insn "*fred_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
- "TARGET_FRE && !VECTOR_UNIT_VSX_P (DFmode)"
- "fre %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn "*rsqrtdf_internal1"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")]
- UNSPEC_RSQRT))]
- "TARGET_FRSQRTE && !VECTOR_UNIT_VSX_P (DFmode)"
- "frsqrte %0,%1"
- [(set_attr "type" "fp")])
-
-; builtin fma support
-(define_insn "*fmadf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (match_operand:DF 3 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*fmsdf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*nfmadf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fnmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*nfmsdf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f")))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fnmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_expand "sqrtdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
- "")
-
-(define_insn "*sqrtdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fsqrt %0,%1"
- [(set_attr "type" "dsqrt")])
-
;; The conditional move instructions allow us to perform max and min
;; operations even when
-(define_expand "smaxdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" ""))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
-
-(define_expand "smindf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" ""))
- (match_dup 2)
- (match_dup 1)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
-
(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(match_operator:DF 3 "min_max_operator"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FCTID))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
"fctid %0,%1"
[(set_attr "type" "fp")])
-(define_expand "btrunc<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
- UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
-
-(define_insn "*btrunc<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+(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>")]
UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "friz %0,%1"
- [(set_attr "type" "fp")])
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ friz %0,%1
+ xsrdpiz %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
-(define_expand "ceil<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
+(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>")]
UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
-
-(define_insn "*ceil<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
- UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "frip %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "floor<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
- UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ frip %0,%1
+ xsrdpip %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
-(define_insn "*floor<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+(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>")]
UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "frim %0,%1"
- [(set_attr "type" "fp")])
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ frim %0,%1
+ xsrdpim %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
;; No VSX equivalent to frin
(define_insn "round<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FRIN))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
"frin %0,%1"
- [(set_attr "type" "fp")])
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
; An UNSPEC is used so we don't have to support SImode in FP registers.
(define_insn "stfiwx"
[(set (match_dup 3) (compare:CCUNS (match_dup 1) (match_dup 2)))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
-(define_insn "*cmpsf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fcmpu %0,%1,%2"
- [(set_attr "type" "fpcompare")])
-
-(define_insn "*cmpdf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fcmpu %0,%1,%2"
- [(set_attr "type" "fpcompare")])
-
;; Only need to compare second words if first words equal
(define_insn "*cmptf_internal1"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
""
"")
+(define_insn "*fma<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmadd<Ftrad> %0,%1,%2,%3
+ xsmadda<Fvsx> %x0,%x1,%x2
+ xsmaddm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
; Altivec only has fma and nfms.
(define_expand "fms<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
"!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
"")
+(define_insn "*fms<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmsub<Ftrad> %0,%1,%2,%3
+ xsmsuba<Fvsx> %x0,%x1,%x2
+ xsmsubm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
;; If signed zeros are ignored, -(a * b - c) = -a * b + c.
(define_expand "fnma<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
"!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
"")
+(define_insn "*nfma<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (neg:SFDF
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnmadd<Ftrad> %0,%1,%2,%3
+ xsnmadda<Fvsx> %x0,%x1,%x2
+ xsnmaddm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
; Not an official optab name, but used from builtins.
(define_expand "nfms<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
""
"")
+(define_insn "*nfmssf4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (neg:SFDF
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (neg:SFDF
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>")))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnmsub<Ftrad> %0,%1,%2,%3
+ xsnmsuba<Fvsx> %x0,%x1,%x2
+ xsnmsubm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
+\f
(define_expand "rs6000_get_timebase"
[(use (match_operand:DI 0 "gpc_reg_operand" ""))]
""
"")
\f
-;; VSX scalar and vector floating point arithmetic instructions
+;; VSX vector floating point arithmetic instructions. The VSX scalar
+;; instructions are now combined with the insn for the traditional floating
+;; point unit.
(define_insn "*vsx_add<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>add<VSs> %x0,%x1,%x2"
+ "xvadd<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_sub<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>sub<VSs> %x0,%x1,%x2"
+ "xvsub<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_mul<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>mul<VSs> %x0,%x1,%x2"
- [(set_attr "type" "<VStype_mul>")
+ "xvmul<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_mul>")])
(define_insn "*vsx_div<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>div<VSs> %x0,%x1,%x2"
+ "xvdiv<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_div>")
(set_attr "fp_type" "<VSfptype_div>")])
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_fre<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRES))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>re<VSs> %x0,%x1"
+ "xvre<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_neg<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>neg<VSs> %x0,%x1"
+ "xvneg<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_abs<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>abs<VSs> %x0,%x1"
+ "xvabs<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_nabs<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (neg:VSX_B
- (abs:VSX_B
- (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (neg:VSX_F
+ (abs:VSX_F
+ (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>nabs<VSs> %x0,%x1"
+ "xvnabs<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_smax<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>max<VSs> %x0,%x1,%x2"
+ "xvmax<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_smin<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>min<VSs> %x0,%x1,%x2"
+ "xvmin<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Special VSX version of smin/smax for single precision floating point. Since
-;; both numbers are rounded to single precision, we can just use the DP version
-;; of the instruction.
-
-(define_insn "*vsx_smaxsf3"
- [(set (match_operand:SF 0 "vsx_register_operand" "=f")
- (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
- (match_operand:SF 2 "vsx_register_operand" "f")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "xsmaxdp %x0,%x1,%x2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_insn "*vsx_sminsf3"
- [(set (match_operand:SF 0 "vsx_register_operand" "=f")
- (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
- (match_operand:SF 2 "vsx_register_operand" "f")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "xsmindp %x0,%x1,%x2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
(define_insn "*vsx_sqrt<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>sqrt<VSs> %x0,%x1"
+ "xvsqrt<VSs> %x0,%x1"
[(set_attr "type" "<VStype_sqrt>")
(set_attr "fp_type" "<VSfptype_sqrt>")])
(define_insn "*vsx_rsqrte<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_RSQRT))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>rsqrte<VSs> %x0,%x1"
+ "xvrsqrte<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Fused vector multiply/add instructions Support the classical DF versions of
-;; fma, which allows the target to be a separate register from the 3 inputs.
-;; Under VSX, the target must be either the addend or the first multiply.
-;; Where we can, also do the same for the Altivec V4SF fmas.
-
-(define_insn "*vsx_fmadf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsmaddadp %x0,%x1,%x2
- xsmaddmdp %x0,%x1,%x3
- xsmaddadp %x0,%x1,%x2
- xsmaddmdp %x0,%x1,%x3
- fmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
+;; Fused vector multiply/add instructions. Support the classical Altivec
+;; versions of fma, which allows the target to be a separate register from the
+;; 3 inputs. Under VSX, the target must be either the addend or the first
+;; multiply.
(define_insn "*vsx_fmav4sf4"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v")
xvmaddmdp %x0,%x1,%x3"
[(set_attr "type" "vecdouble")])
-(define_insn "*vsx_fmsdf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (neg:DF
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsmsubadp %x0,%x1,%x2
- xsmsubmdp %x0,%x1,%x3
- xsmsubadp %x0,%x1,%x2
- xsmsubmdp %x0,%x1,%x3
- fmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_fms<mode>4"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
(fma:VSX_F
(match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"@
- x<VSv>msuba<VSs> %x0,%x1,%x2
- x<VSv>msubm<VSs> %x0,%x1,%x3
- x<VSv>msuba<VSs> %x0,%x1,%x2
- x<VSv>msubm<VSs> %x0,%x1,%x3"
+ xvmsuba<VSs> %x0,%x1,%x2
+ xvmsubm<VSs> %x0,%x1,%x3
+ xvmsuba<VSs> %x0,%x1,%x2
+ xvmsubm<VSs> %x0,%x1,%x3"
[(set_attr "type" "<VStype_mul>")])
-(define_insn "*vsx_nfmadf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (neg:DF
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsnmaddadp %x0,%x1,%x2
- xsnmaddmdp %x0,%x1,%x3
- xsnmaddadp %x0,%x1,%x2
- xsnmaddmdp %x0,%x1,%x3
- fnmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_nfma<mode>4"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
(neg:VSX_F
(match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"@
- x<VSv>nmadda<VSs> %x0,%x1,%x2
- x<VSv>nmaddm<VSs> %x0,%x1,%x3
- x<VSv>nmadda<VSs> %x0,%x1,%x2
- x<VSv>nmaddm<VSs> %x0,%x1,%x3"
+ xvnmadda<VSs> %x0,%x1,%x2
+ xvnmaddm<VSs> %x0,%x1,%x3
+ xvnmadda<VSs> %x0,%x1,%x2
+ xvnmaddm<VSs> %x0,%x1,%x3"
[(set_attr "type" "<VStype_mul>")
(set_attr "fp_type" "<VSfptype_mul>")])
-(define_insn "*vsx_nfmsdf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (neg:DF
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (neg:DF
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsnmsubadp %x0,%x1,%x2
- xsnmsubmdp %x0,%x1,%x3
- xsnmsubadp %x0,%x1,%x2
- xsnmsubmdp %x0,%x1,%x3
- fnmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_nfmsv4sf4"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
(neg:V4SF
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Floating point scalar compare
-(define_insn "*vsx_cmpdf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
- (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
- (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_VSX_P (DFmode)"
- "xscmpudp %0,%x1,%x2"
- [(set_attr "type" "fpcompare")])
-
;; Compare vectors producing a vector result and a predicate, setting CR6 to
;; indicate a combined status
(define_insn "*vsx_eq_<mode>_p"
;; Copy sign
(define_insn "vsx_copysign<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B
- [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F
+ [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_COPYSIGN))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
+ "xvcpsgn<VSs> %x0,%x2,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_btrunc<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>iz %x0,%x1"
+ "xvr<VSs>iz %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_floor<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRIM))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>im %x0,%x1"
+ "xvr<VSs>im %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_ceil<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRIP))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>ip %x0,%x1"
+ "xvr<VSs>ip %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])