aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/ia64/ia64.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/ia64/ia64.md')
-rw-r--r--gcc/config/ia64/ia64.md1228
1 files changed, 1194 insertions, 34 deletions
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index 129ce240316..704959222d2 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -50,6 +50,8 @@
;; would be better if rtx_needs_barrier took care of this, but this is
;; something that can be fixed later.
+;; ??? Need a better way to describe alternate fp status registers.
+
;; Unspec usage:
;;
;; unspec:
@@ -57,6 +59,7 @@
;; 2 gr_restore
;; 3 fr_spill
;; 4 fr_restore
+;; 5 recip_approx
;; 8 popcnt
;; 12 mf
;; 13 cmpxchg_acq
@@ -950,8 +953,8 @@
[(set_attr "type" "I")])
(define_insn "extendsidi2"
- [(set (match_operand:DI 0 "grfr_register_operand" "=r,*f")
- (sign_extend:DI (match_operand:SI 1 "grfr_register_operand" "r,*f")))]
+ [(set (match_operand:DI 0 "grfr_register_operand" "=r,?f")
+ (sign_extend:DI (match_operand:SI 1 "grfr_register_operand" "r,f")))]
""
"@
sxt4 %0 = %1
@@ -979,14 +982,14 @@
[(set_attr "type" "I,M")])
(define_insn "zero_extendsidi2"
- [(set (match_operand:DI 0 "grfr_register_operand" "=r,r,*f")
+ [(set (match_operand:DI 0 "grfr_register_operand" "=r,r,?f")
(zero_extend:DI
- (match_operand:SI 1 "grfr_nonimmediate_operand" "r,m,*f")))]
+ (match_operand:SI 1 "grfr_nonimmediate_operand" "r,m,f")))]
""
"@
zxt4 %0 = %1
ld4%O1 %0 = %1%P1
- fsxt.r %0 = f1, %1%B0"
+ fmix.r %0 = f0, %1%B0"
[(set_attr "type" "I,M,F")])
;; Convert between floating point types of different sizes.
@@ -997,34 +1000,53 @@
;; would let combine merge the thing into adjacent insns.
(define_insn_and_split "extendsfdf2"
- [(set (match_operand:DF 0 "fr_register_operand" "=f,f")
- (float_extend:DF (match_operand:SF 1 "fr_register_operand" "0,f")))]
+ [(set (match_operand:DF 0 "grfr_nonimmediate_operand" "=f,f,f,f,m,*r")
+ (float_extend:DF
+ (match_operand:SF 1 "grfr_nonimmediate_operand" "0,f,m,*r,f,f")))]
""
- "mov %0 = %1"
+ "@
+ mov %0 = %1
+ mov %0 = %1
+ ldfs %0 = %1%P1
+ setf.s %0 = %1
+ stfd %0 = %1%P0
+ getf.d %0 = %1"
"reload_completed"
[(set (match_dup 0) (float_extend:DF (match_dup 1)))]
"if (true_regnum (operands[0]) == true_regnum (operands[1])) DONE;"
- [(set_attr "type" "F")])
+ [(set_attr "type" "F,F,M,M,M,M")])
(define_insn_and_split "extendsftf2"
- [(set (match_operand:TF 0 "fr_register_operand" "=f,f")
- (float_extend:TF (match_operand:SF 1 "fr_register_operand" "0,f")))]
+ [(set (match_operand:TF 0 "fr_nonimmediate_operand" "=f,f,f,f,Q")
+ (float_extend:TF
+ (match_operand:SF 1 "grfr_nonimmediate_operand" "0,f,Q,*r,f")))]
""
- "mov %0 = %1"
+ "@
+ mov %0 = %1
+ mov %0 = %1
+ ldfs %0 = %1%P1
+ setf.s %0 = %1
+ stfe %0 = %1%P0"
"reload_completed"
[(set (match_dup 0) (float_extend:TF (match_dup 1)))]
"if (true_regnum (operands[0]) == true_regnum (operands[1])) DONE;"
- [(set_attr "type" "F")])
+ [(set_attr "type" "F,F,M,M,M")])
(define_insn_and_split "extenddftf2"
- [(set (match_operand:TF 0 "fr_register_operand" "=f,f")
- (float_extend:TF (match_operand:DF 1 "fr_register_operand" "0,f")))]
+ [(set (match_operand:TF 0 "fr_nonimmediate_operand" "=f,f,f,f,Q")
+ (float_extend:TF
+ (match_operand:DF 1 "grfr_nonimmediate_operand" "0,f,Q,*r,f")))]
""
- "mov %0 = %1"
+ "@
+ mov %0 = %1
+ mov %0 = %1
+ ldfd %0 = %1%P1
+ setf.d %0 = %1
+ stfe %0 = %1%P0"
"reload_completed"
[(set (match_dup 0) (float_extend:TF (match_dup 1)))]
"if (true_regnum (operands[0]) == true_regnum (operands[1])) DONE;"
- [(set_attr "type" "F")])
+ [(set_attr "type" "F,F,M,M,M")])
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
@@ -1077,6 +1099,14 @@
"fcvt.fx.trunc %0 = %1%B0"
[(set_attr "type" "F")])
+(define_insn "fix_trunctfdi2_alts"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (fix:DI (match_operand:TF 1 "fr_register_operand" "f")))
+ (use (match_operand:SI 2 "const_int_operand" ""))]
+ ""
+ "fcvt.fx.trunc.s%2 %0 = %1%B0"
+ [(set_attr "type" "F")])
+
;; Convert between unsigned integer types and floating point.
(define_insn "floatunsdisf2"
@@ -1120,6 +1150,14 @@
""
"fcvt.fxu.trunc %0 = %1%B0"
[(set_attr "type" "F")])
+
+(define_insn "fixuns_trunctfdi2_alts"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (unsigned_fix:DI (match_operand:TF 1 "fr_register_operand" "f")))
+ (use (match_operand:SI 2 "const_int_operand" ""))]
+ ""
+ "fcvt.fxu.trunc.s%2 %0 = %1%B0"
+ [(set_attr "type" "F")])
;; ::::::::::::::::::::
;; ::
@@ -1400,7 +1438,7 @@
"xma.l %0 = %1, %2, f0%B0"
[(set_attr "type" "F")])
-(define_insn "*maddsi3"
+(define_insn "maddsi4"
[(set (match_operand:SI 0 "fr_register_operand" "=f")
(plus:SI (mult:SI (match_operand:SI 1 "grfr_register_operand" "f")
(match_operand:SI 2 "grfr_register_operand" "f"))
@@ -1481,6 +1519,172 @@
operands[3] = gen_reg_rtx (CCmode);
}")
+(define_expand "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (div:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
+
+ op0_tf = gen_reg_rtx (TFmode);
+ op0_di = gen_reg_rtx (DImode);
+
+ if (CONSTANT_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
+ op1_tf = gen_reg_rtx (TFmode);
+ expand_float (op1_tf, operands[1], 0);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_reg (SImode, operands[2]);
+ op2_tf = gen_reg_rtx (TFmode);
+ expand_float (op2_tf, operands[2], 0);
+
+ /* 2^-34 */
+#if 0
+ twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
+ (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
+ twon34 = force_reg (TFmode, twon34);
+#else
+ twon34 = gen_reg_rtx (TFmode);
+ convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
+#endif
+
+ emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
+
+ emit_insn (gen_fix_trunctfdi2_alts (op0_di, op0_tf, const1_rtx));
+ emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
+ DONE;
+}")
+
+(define_expand "modsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mod:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx op2_neg, op1_di, div;
+
+ div = gen_reg_rtx (SImode);
+ emit_insn (gen_divsi3 (div, operands[1], operands[2]));
+
+ op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
+
+ /* This is a trick to get us to reuse the value that we're sure to
+ have already copied to the FP regs. */
+ op1_di = gen_reg_rtx (DImode);
+ convert_move (op1_di, operands[1], 0);
+
+ emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
+ gen_lowpart (SImode, op1_di)));
+ DONE;
+}")
+
+(define_expand "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (udiv:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
+
+ op0_tf = gen_reg_rtx (TFmode);
+ op0_di = gen_reg_rtx (DImode);
+
+ if (CONSTANT_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
+ op1_tf = gen_reg_rtx (TFmode);
+ expand_float (op1_tf, operands[1], 1);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_reg (SImode, operands[2]);
+ op2_tf = gen_reg_rtx (TFmode);
+ expand_float (op2_tf, operands[2], 1);
+
+ /* 2^-34 */
+#if 0
+ twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
+ (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
+ twon34 = force_reg (TFmode, twon34);
+#else
+ twon34 = gen_reg_rtx (TFmode);
+ convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
+#endif
+
+ emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
+
+ emit_insn (gen_fixuns_trunctfdi2_alts (op0_di, op0_tf, const1_rtx));
+ emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
+ DONE;
+}")
+
+(define_expand "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (umod:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx op2_neg, op1_di, div;
+
+ div = gen_reg_rtx (SImode);
+ emit_insn (gen_udivsi3 (div, operands[1], operands[2]));
+
+ op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
+
+ /* This is a trick to get us to reuse the value that we're sure to
+ have already copied to the FP regs. */
+ op1_di = gen_reg_rtx (DImode);
+ convert_move (op1_di, operands[1], 1);
+
+ emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
+ gen_lowpart (SImode, op1_di)));
+ DONE;
+}")
+
+(define_insn_and_split "divsi3_internal"
+ [(set (match_operand:TF 0 "fr_register_operand" "=&f")
+ (float:TF (div:SI (match_operand:TF 1 "fr_register_operand" "f")
+ (match_operand:TF 2 "fr_register_operand" "f"))))
+ (clobber (match_scratch:TF 4 "=&f"))
+ (clobber (match_scratch:TF 5 "=&f"))
+ (clobber (match_scratch:CC 6 "=c"))
+ (use (match_operand:TF 3 "fr_register_operand" "f"))]
+ "TARGET_INLINE_DIV"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
+ (set (match_dup 6) (unspec:CC [(match_dup 1) (match_dup 2)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 4) (mult:TF (match_dup 1) (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 5)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 0)))
+ (match_dup 7)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 4))
+ (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 5)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 5))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 4))
+ (match_dup 4)))
+ (use (const_int 1))]))
+ ]
+ "operands[7] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -1557,7 +1761,7 @@
;; ??? Maybe we should change how adds are canonicalized.
-(define_insn "*madddi3"
+(define_insn "madddi4"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
(plus:DI (mult:DI (match_operand:DI 1 "grfr_register_operand" "f")
(match_operand:DI 2 "grfr_register_operand" "f"))
@@ -1572,10 +1776,10 @@
;; We have to use nonmemory_operand for operand 4, to ensure that the
;; validate_changes call inside eliminate_regs will always succeed. If it
-;; doesn't succeed, then this remain a madddi3 pattern, and will be reloaded
+;; doesn't succeed, then this remain a madddi4 pattern, and will be reloaded
;; incorrectly.
-(define_insn "*madddi3_elim"
+(define_insn "*madddi4_elim"
[(set (match_operand:DI 0 "register_operand" "=&r")
(plus:DI (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "f")
(match_operand:DI 2 "register_operand" "f"))
@@ -1734,6 +1938,208 @@
"popcnt %0 = %1"
[(set_attr "type" "I")])
+(define_expand "divdi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (div:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx op1_tf, op2_tf, op0_tf;
+
+ op0_tf = gen_reg_rtx (TFmode);
+
+ if (CONSTANT_P (operands[1]))
+ operands[1] = force_reg (DImode, operands[1]);
+ op1_tf = gen_reg_rtx (TFmode);
+ expand_float (op1_tf, operands[1], 0);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_reg (DImode, operands[2]);
+ op2_tf = gen_reg_rtx (TFmode);
+ expand_float (op2_tf, operands[2], 0);
+
+ if (TARGET_INLINE_DIV_LAT)
+ emit_insn (gen_divdi3_internal_lat (op0_tf, op1_tf, op2_tf));
+ else
+ emit_insn (gen_divdi3_internal_thr (op0_tf, op1_tf, op2_tf));
+
+ emit_insn (gen_fix_trunctfdi2_alts (operands[0], op0_tf, const1_rtx));
+ DONE;
+}")
+
+(define_expand "moddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mod:SI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx op2_neg, div;
+
+ div = gen_reg_rtx (DImode);
+ emit_insn (gen_divdi3 (div, operands[1], operands[2]));
+
+ op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
+
+ emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
+ DONE;
+}")
+
+(define_expand "udivdi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (udiv:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx op1_tf, op2_tf, op0_tf;
+
+ op0_tf = gen_reg_rtx (TFmode);
+
+ if (CONSTANT_P (operands[1]))
+ operands[1] = force_reg (DImode, operands[1]);
+ op1_tf = gen_reg_rtx (TFmode);
+ expand_float (op1_tf, operands[1], 1);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_reg (DImode, operands[2]);
+ op2_tf = gen_reg_rtx (TFmode);
+ expand_float (op2_tf, operands[2], 1);
+
+ if (TARGET_INLINE_DIV_LAT)
+ emit_insn (gen_divdi3_internal_lat (op0_tf, op1_tf, op2_tf));
+ else
+ emit_insn (gen_divdi3_internal_thr (op0_tf, op1_tf, op2_tf));
+
+ emit_insn (gen_fixuns_trunctfdi2_alts (operands[0], op0_tf, const1_rtx));
+ DONE;
+}")
+
+(define_expand "umoddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (umod:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx op2_neg, div;
+
+ div = gen_reg_rtx (DImode);
+ emit_insn (gen_udivdi3 (div, operands[1], operands[2]));
+
+ op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
+
+ emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
+ DONE;
+}")
+
+(define_insn_and_split "divdi3_internal_lat"
+ [(set (match_operand:TF 0 "fr_register_operand" "=&f")
+ (float:TF (div:SI (match_operand:TF 1 "fr_register_operand" "f")
+ (match_operand:TF 2 "fr_register_operand" "f"))))
+ (clobber (match_scratch:TF 3 "=&f"))
+ (clobber (match_scratch:TF 4 "=&f"))
+ (clobber (match_scratch:TF 5 "=&f"))
+ (clobber (match_scratch:CC 6 "=c"))]
+ "TARGET_INLINE_DIV_LAT"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
+ (set (match_dup 6) (unspec:CC [(match_dup 1) (match_dup 2)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 0)))
+ (match_dup 7)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 4) (mult:TF (match_dup 1) (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 5) (mult:TF (match_dup 3) (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 4))
+ (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 0))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 4))
+ (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 0))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 3)))
+ (match_dup 1)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 0))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ ]
+ "operands[7] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
+
+(define_insn_and_split "divdi3_internal_thr"
+ [(set (match_operand:TF 0 "fr_register_operand" "=&f")
+ (float:TF (div:SI (match_operand:TF 1 "fr_register_operand" "f")
+ (match_operand:TF 2 "fr_register_operand" "f"))))
+ (clobber (match_scratch:TF 3 "=&f"))
+ (clobber (match_scratch:TF 4 "=f"))
+ (clobber (match_scratch:CC 5 "=c"))]
+ "TARGET_INLINE_DIV_THR"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
+ (set (match_dup 5) (unspec:CC [(match_dup 1) (match_dup 2)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 0)))
+ (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 0))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3) (mult:TF (match_dup 3) (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 0))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3) (mult:TF (match_dup 0) (match_dup 1)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 3)))
+ (match_dup 1)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 0))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ ]
+ "operands[6] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -1802,7 +2208,7 @@
"fmax %0 = %1, %F2%B0"
[(set_attr "type" "F")])
-(define_insn "*maddsf3"
+(define_insn "*maddsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(plus:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_register_operand" "f"))
@@ -1811,7 +2217,7 @@
"fma.s %0 = %1, %2, %F3%B0"
[(set_attr "type" "F")])
-(define_insn "*msubsf3"
+(define_insn "*msubsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(minus:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_register_operand" "f"))
@@ -1830,15 +2236,136 @@
;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-(define_insn "*nmaddsf3"
+(define_insn "*nmaddsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
- (plus:SF (neg:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
- (match_operand:SF 2 "fr_register_operand" "f")))
+ (plus:SF (neg:SF (mult:SF
+ (match_operand:SF 1 "fr_register_operand" "f")
+ (match_operand:SF 2 "fr_register_operand" "f")))
(match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
""
"fnma.s %0 = %1, %2, %F3%B0"
[(set_attr "type" "F")])
+(define_expand "divsf3"
+ [(set (match_operand:SF 0 "fr_register_operand" "")
+ (div:SF (match_operand:SF 1 "fr_register_operand" "")
+ (match_operand:SF 2 "fr_register_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx insn;
+ if (TARGET_INLINE_DIV_LAT)
+ insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
+ else
+ insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
+ emit_insn (insn);
+ DONE;
+}")
+
+(define_insn_and_split "divsf3_internal_lat"
+ [(set (match_operand:SF 0 "fr_register_operand" "=&f")
+ (div:SF (match_operand:SF 1 "fr_register_operand" "f")
+ (match_operand:SF 2 "fr_register_operand" "f")))
+ (clobber (match_scratch:TF 3 "=&f"))
+ (clobber (match_scratch:TF 4 "=f"))
+ (clobber (match_scratch:CC 5 "=c"))]
+ "TARGET_INLINE_DIV_LAT"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
+ (set (match_dup 5) (unspec:CC [(match_dup 7) (match_dup 8)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3) (mult:TF (match_dup 7) (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 8) (match_dup 6)))
+ (match_dup 10)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 3))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4) (mult:TF (match_dup 4) (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 3))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4) (mult:TF (match_dup 4) (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 9)
+ (float_truncate:DF
+ (plus:TF (mult:TF (match_dup 4) (match_dup 3))
+ (match_dup 3))))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (set (match_dup 0)
+ (float_truncate:SF (match_dup 6))))
+ ]
+ "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (DFmode, REGNO (operands[0]));
+ operands[10] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
+
+(define_insn_and_split "divsf3_internal_thr"
+ [(set (match_operand:SF 0 "fr_register_operand" "=&f")
+ (div:SF (match_operand:SF 1 "fr_register_operand" "f")
+ (match_operand:SF 2 "fr_register_operand" "f")))
+ (clobber (match_scratch:TF 3 "=&f"))
+ (clobber (match_scratch:TF 4 "=f"))
+ (clobber (match_scratch:CC 5 "=c"))]
+ "TARGET_INLINE_DIV_THR"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
+ (set (match_dup 5) (unspec:CC [(match_dup 7) (match_dup 8)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (neg:TF (mult:TF (match_dup 8) (match_dup 6)))
+ (match_dup 10)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 3))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 6)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 6))
+ (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 9)
+ (float_truncate:SF
+ (mult:TF (match_dup 7) (match_dup 6))))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 8) (match_dup 3)))
+ (match_dup 7)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (set (match_dup 0)
+ (float_truncate:SF
+ (plus:TF (mult:TF (match_dup 4) (match_dup 6))
+ (match_dup 3)))))
+ ]
+ "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (SFmode, REGNO (operands[3]));
+ operands[10] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -1854,6 +2381,15 @@
"fadd.d %0 = %1, %F2%B0"
[(set_attr "type" "F")])
+(define_insn "*adddf3_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (plus:DF (match_operand:DF 1 "fr_register_operand" "%f")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fadd.s %0 = %1, %F2%B0"
+ [(set_attr "type" "F")])
+
(define_insn "subdf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(minus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
@@ -1862,6 +2398,15 @@
"fsub.d %0 = %F1, %F2%B0"
[(set_attr "type" "F")])
+(define_insn "*subdf3_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fsub.s %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
(define_insn "muldf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(mult:DF (match_operand:DF 1 "fr_register_operand" "f")
@@ -1870,6 +2415,15 @@
"fmpy.d %0 = %1, %2%B0"
[(set_attr "type" "F")])
+(define_insn "*muldf3_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f"))))]
+ ""
+ "fmpy.s %0 = %1, %2%B0"
+ [(set_attr "type" "F")])
+
(define_insn "absdf2"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(abs:DF (match_operand:DF 1 "fr_register_operand" "f")))]
@@ -1907,7 +2461,7 @@
"fmax %0 = %1, %F2%B0"
[(set_attr "type" "F")])
-(define_insn "*madddf3"
+(define_insn "*madddf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(plus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f"))
@@ -1916,7 +2470,17 @@
"fma.d %0 = %1, %2, %F3%B0"
[(set_attr "type" "F")])
-(define_insn "*msubdf3"
+(define_insn "*madddf4_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (plus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f"))
+ (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fma.s %0 = %1, %2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*msubdf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(minus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f"))
@@ -1925,6 +2489,16 @@
"fms.d %0 = %1, %2, %F3%B0"
[(set_attr "type" "F")])
+(define_insn "*msubdf4_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f"))
+ (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fms.s %0 = %1, %2, %F3%B0"
+ [(set_attr "type" "F")])
+
(define_insn "*nmuldf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(neg:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
@@ -1933,16 +2507,205 @@
"fnmpy.d %0 = %1, %2%B0"
[(set_attr "type" "F")])
+(define_insn "*nmuldf3_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (neg:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))))]
+ ""
+ "fnmpy.s %0 = %1, %2%B0"
+ [(set_attr "type" "F")])
+
;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-(define_insn "*nmadddf3"
+(define_insn "*nmadddf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
- (plus:DF (neg:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
- (match_operand:DF 2 "fr_register_operand" "f")))
+ (plus:DF (neg:DF (mult:DF
+ (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
""
"fnma.d %0 = %1, %2, %F3%B0"
[(set_attr "type" "F")])
+
+(define_insn "*nmadddf4_alts"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (plus:DF (neg:DF (mult:DF
+ (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))
+ (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.d.s%4 %0 = %1, %2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*nmadddf4_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (plus:DF (neg:DF (mult:DF
+ (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))
+ (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fnma.s %0 = %1, %2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_expand "divdf3"
+ [(set (match_operand:DF 0 "fr_register_operand" "")
+ (div:DF (match_operand:DF 1 "fr_register_operand" "")
+ (match_operand:DF 2 "fr_register_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx insn;
+ if (TARGET_INLINE_DIV_LAT)
+ insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
+ else
+ insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
+ emit_insn (insn);
+ DONE;
+}")
+
+(define_insn_and_split "divdf3_internal_lat"
+ [(set (match_operand:DF 0 "fr_register_operand" "=&f")
+ (div:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))
+ (clobber (match_scratch:TF 3 "=&f"))
+ (clobber (match_scratch:TF 4 "=&f"))
+ (clobber (match_scratch:TF 5 "=&f"))
+ (clobber (match_scratch:CC 6 "=c"))]
+ "TARGET_INLINE_DIV_LAT"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 7) (div:TF (const_int 1) (match_dup 9)))
+ (set (match_dup 6) (unspec:CC [(match_dup 8) (match_dup 9)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 3) (mult:TF (match_dup 8) (match_dup 7)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 9) (match_dup 7)))
+ (match_dup 12)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 3))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 5) (mult:TF (match_dup 4) (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 7)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 7))
+ (match_dup 7)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 3))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 4) (mult:TF (match_dup 5) (match_dup 5)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 7)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 7))
+ (match_dup 7)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 10)
+ (float_truncate:DF
+ (plus:TF (mult:TF (match_dup 4) (match_dup 3))
+ (match_dup 3))))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 7)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 7))
+ (match_dup 7)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (parallel [(set (match_dup 11)
+ (float_truncate:DF
+ (plus:TF (neg:TF (mult:TF (match_dup 9) (match_dup 3)))
+ (match_dup 8))))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 6) (const_int 0))
+ (set (match_dup 0)
+ (float_truncate:DF (plus:TF (mult:TF (match_dup 5) (match_dup 7))
+ (match_dup 3)))))
+ ]
+ "operands[7] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[9] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[10] = gen_rtx_REG (DFmode, REGNO (operands[3]));
+ operands[11] = gen_rtx_REG (DFmode, REGNO (operands[5]));
+ operands[12] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
+
+(define_insn_and_split "divdf3_internal_thr"
+ [(set (match_operand:DF 0 "fr_register_operand" "=&f")
+ (div:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))
+ (clobber (match_scratch:TF 3 "=&f"))
+ (clobber (match_scratch:DF 4 "=f"))
+ (clobber (match_scratch:CC 5 "=c"))]
+ "TARGET_INLINE_DIV_THR"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
+ (set (match_dup 5) (unspec:CC [(match_dup 7) (match_dup 8)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (neg:TF (mult:TF (match_dup 8) (match_dup 6)))
+ (match_dup 10)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 6)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 6))
+ (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (mult:TF (match_dup 3) (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 6)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 6))
+ (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (mult:TF (match_dup 3) (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 6)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 6))
+ (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 9)
+ (float_truncate:DF
+ (mult:TF (match_dup 7) (match_dup 3))))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:DF (neg:DF (mult:DF (match_dup 2) (match_dup 9)))
+ (match_dup 1)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (set (match_dup 0)
+ (plus:DF (mult:DF (match_dup 4) (match_dup 0))
+ (match_dup 9))))
+ ]
+ "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (DFmode, REGNO (operands[3]));
+ operands[10] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -1958,6 +2721,24 @@
"fadd %0 = %F1, %F2%B0"
[(set_attr "type" "F")])
+(define_insn "*addtf3_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (plus:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fadd.s %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*addtf3_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (plus:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fadd.d %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
(define_insn "subtf3"
[(set (match_operand:TF 0 "fr_register_operand" "=f")
(minus:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
@@ -1966,6 +2747,24 @@
"fsub %0 = %F1, %F2%B0"
[(set_attr "type" "F")])
+(define_insn "*subtf3_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fsub.s %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*subtf3_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (minus:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fsub.d %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
(define_insn "multf3"
[(set (match_operand:TF 0 "fr_register_operand" "=f")
(mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
@@ -1974,6 +2773,53 @@
"fmpy %0 = %F1, %F2%B0"
[(set_attr "type" "F")])
+(define_insn "*multf3_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fmpy.s %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*multf3_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fmpy.d %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*multf3_alts"
+ [(set (match_operand:TF 0 "fr_register_operand" "=f")
+ (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG")))
+ (use (match_operand:SI 3 "const_int_operand" ""))]
+ ""
+ "fmpy.s%3 %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*multf3_truncsf_alts"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))))
+ (use (match_operand:SI 3 "const_int_operand" ""))]
+ ""
+ "fmpy.s.s%3 %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*multf3_truncdf_alts"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))))
+ (use (match_operand:SI 3 "const_int_operand" ""))]
+ ""
+ "fmpy.d.s%3 %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
(define_insn "abstf2"
[(set (match_operand:TF 0 "fr_register_operand" "=f")
(abs:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")))]
@@ -2011,7 +2857,7 @@
"fmax %0 = %F1, %F2%B0"
[(set_attr "type" "F")])
-(define_insn "*maddtf3"
+(define_insn "*maddtf4"
[(set (match_operand:TF 0 "fr_register_operand" "=f")
(plus:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
(match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))
@@ -2020,7 +2866,48 @@
"fma %0 = %F1, %F2, %F3%B0"
[(set_attr "type" "F")])
-(define_insn "*msubtf3"
+(define_insn "*maddtf4_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (plus:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fma.s %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*maddtf4_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (plus:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fma.d %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*maddtf4_alts"
+ [(set (match_operand:TF 0 "fr_register_operand" "=f")
+ (plus:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG")))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fma.s%4 %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*maddtf4_alts_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (plus:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG"))))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fma.d.s%4 %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*msubtf4"
[(set (match_operand:TF 0 "fr_register_operand" "=f")
(minus:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
(match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))
@@ -2029,6 +2916,26 @@
"fms %0 = %F1, %F2, %F3%B0"
[(set_attr "type" "F")])
+(define_insn "*msubtf4_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fms.s %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*msubtf4_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (minus:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG"))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fms.d %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
(define_insn "*nmultf3"
[(set (match_operand:TF 0 "fr_register_operand" "=f")
(neg:TF (mult:TF (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
@@ -2037,9 +2944,29 @@
"fnmpy %0 = %F1, %F2%B0"
[(set_attr "type" "F")])
+(define_insn "*nmultf3_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (neg:TF (mult:TF
+ (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG")))))]
+ ""
+ "fnmpy.s %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*nmultf3_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (neg:TF (mult:TF
+ (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG")))))]
+ ""
+ "fnmpy.d %0 = %F1, %F2%B0"
+ [(set_attr "type" "F")])
+
;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-(define_insn "*nmaddtf3"
+(define_insn "*nmaddtf4"
[(set (match_operand:TF 0 "fr_register_operand" "=f")
(plus:TF (neg:TF (mult:TF
(match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
@@ -2048,6 +2975,239 @@
""
"fnma %0 = %F1, %F2, %F3%B0"
[(set_attr "type" "F")])
+
+(define_insn "*nmaddtf4_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (plus:TF (neg:TF (mult:TF
+ (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG")))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fnma.s %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*nmaddtf4_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (plus:TF (neg:TF (mult:TF
+ (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG")))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fnma.d %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*nmaddtf4_alts"
+ [(set (match_operand:TF 0 "fr_register_operand" "=f")
+ (plus:TF (neg:TF (mult:TF
+ (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG")))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG")))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.s%4 %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_insn "*nmaddtf4_truncdf_alts"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (plus:TF (neg:TF
+ (mult:TF
+ (match_operand:TF 1 "tfreg_or_fp01_operand" "fG")
+ (match_operand:TF 2 "tfreg_or_fp01_operand" "fG")))
+ (match_operand:TF 3 "tfreg_or_fp01_operand" "fG"))))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.d.s%4 %0 = %F1, %F2, %F3%B0"
+ [(set_attr "type" "F")])
+
+(define_expand "divtf3"
+ [(set (match_operand:TF 0 "fr_register_operand" "")
+ (div:TF (match_operand:TF 1 "fr_register_operand" "")
+ (match_operand:TF 2 "fr_register_operand" "")))]
+ "TARGET_INLINE_DIV"
+ "
+{
+ rtx insn;
+ if (TARGET_INLINE_DIV_LAT)
+ insn = gen_divtf3_internal_lat (operands[0], operands[1], operands[2]);
+ else
+ insn = gen_divtf3_internal_thr (operands[0], operands[1], operands[2]);
+ emit_insn (insn);
+ DONE;
+}")
+
+(define_insn_and_split "divtf3_internal_lat"
+ [(set (match_operand:TF 0 "fr_register_operand" "=&f")
+ (div:TF (match_operand:TF 1 "fr_register_operand" "f")
+ (match_operand:TF 2 "fr_register_operand" "f")))
+ (clobber (match_scratch:TF 3 "=&f"))
+ (clobber (match_scratch:TF 4 "=&f"))
+ (clobber (match_scratch:TF 5 "=&f"))
+ (clobber (match_scratch:TF 6 "=&f"))
+ (clobber (match_scratch:CC 7 "=c"))]
+ "TARGET_INLINE_DIV_LAT"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
+ (set (match_dup 7) (unspec:CC [(match_dup 1) (match_dup 2)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 0)))
+ (match_dup 8)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 4) (mult:TF (match_dup 1) (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 5) (mult:TF (match_dup 3) (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 6)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 3))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 5))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 5)
+ (plus:TF (mult:TF (match_dup 6) (match_dup 0))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 5) (match_dup 3))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 4)))
+ (match_dup 1)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 0))
+ (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 5)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 0)))
+ (match_dup 8)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 0))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 3)))
+ (match_dup 1)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 7) (const_int 0))
+ (set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 0))
+ (match_dup 3))))
+ ]
+ "operands[8] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
+
+(define_insn_and_split "divtf3_internal_thr"
+ [(set (match_operand:TF 0 "fr_register_operand" "=&f")
+ (div:TF (match_operand:TF 1 "fr_register_operand" "f")
+ (match_operand:TF 2 "fr_register_operand" "f")))
+ (clobber (match_scratch:TF 3 "=&f"))
+ (clobber (match_scratch:TF 4 "=&f"))
+ (clobber (match_scratch:CC 5 "=c"))]
+ "TARGET_INLINE_DIV_THR"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
+ (set (match_dup 5) (unspec:CC [(match_dup 1) (match_dup 2)] 5))
+ (use (const_int 1))])
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 0)))
+ (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 0))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3) (mult:TF (match_dup 3) (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 4))
+ (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4) (mult:TF (match_dup 1) (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 3)))
+ (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 0) (match_dup 3))
+ (match_dup 3)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 4)))
+ (match_dup 1)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 3)
+ (plus:TF (mult:TF (match_dup 3) (match_dup 0))
+ (match_dup 4)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 0)))
+ (match_dup 6)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 0))
+ (match_dup 0)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (parallel [(set (match_dup 4)
+ (plus:TF (neg:TF (mult:TF (match_dup 2) (match_dup 3)))
+ (match_dup 1)))
+ (use (const_int 1))]))
+ (cond_exec (ne (match_dup 5) (const_int 0))
+ (set (match_dup 0)
+ (plus:TF (mult:TF (match_dup 4) (match_dup 0))
+ (match_dup 3))))
+ ]
+ "operands[6] = CONST1_RTX (TFmode);"
+ [(set_attr "predicable" "no")])
+
+;; ??? frcpa works like cmp.foo.unc.
+
+(define_insn "*recip_approx"
+ [(set (match_operand:TF 0 "fr_register_operand" "=f")
+ (div:TF (const_int 1)
+ (match_operand:TF 3 "fr_register_operand" "f")))
+ (set (match_operand:CC 1 "register_operand" "=c")
+ (unspec:CC [(match_operand:TF 2 "fr_register_operand" "f")
+ (match_dup 3)] 5))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "frcpa.s%4 %0, %1 = %2, %3"
+ [(set_attr "type" "F")
+ (set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::