diff options
Diffstat (limited to 'gcc/config/ia64/ia64.md')
-rw-r--r-- | gcc/config/ia64/ia64.md | 1228 |
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")]) ;; :::::::::::::::::::: ;; :: |