OSDN Git Service

* config/ia64/ia64.md (divsf3): New.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Sep 2000 21:30:55 +0000 (21:30 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Sep 2000 21:30:55 +0000 (21:30 +0000)
        (divsf3_internal_lat, divsf3_internal_thr): New.
        (divdf3, divdf3_internal_lat, divdf3_internal_thr): New.
        (divtf3, divtf3_internal_lat, divtf3_internal_thr): New.
        (adddf3_trunc, subdf3_trunc, muldf3_trunc): New.
        (madddf4_trunc, msubdf4_trunc, nmuldf3_trunc): New.
        (nmadddf4_alts, nmadddf4_trunc): New.
        (addtf3_truncsf, addtf3_truncdf, subtf3_truncsf): New.
        (subtf3_truncdf, multf3_truncsf, multf3_truncdf): New.
        (multf3_truncsf_alts, multf3_truncdf_alts): New.
        (maddtf4_truncsf, maddtf4_truncdf, maddtf4_alts_truncdf): New.
        (msubtf4_truncsf, msubtf4_truncdf, nmultf3_truncsf): New.
        (nmultf3_truncdf, nmaddtf4_truncsf, nmaddtf4_truncdf): New.
        (nmaddtf4_truncdf_alts): New.
        (recip_approx): Don't predicate.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36396 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/ia64/ia64.md

index 8ea0314..3eca11e 100644 (file)
@@ -1,5 +1,23 @@
 2000-09-13  Richard Henderson  <rth@cygnus.com>
 
+       * config/ia64/ia64.md (divsf3): New.
+       (divsf3_internal_lat, divsf3_internal_thr): New.
+       (divdf3, divdf3_internal_lat, divdf3_internal_thr): New.
+       (divtf3, divtf3_internal_lat, divtf3_internal_thr): New.
+       (adddf3_trunc, subdf3_trunc, muldf3_trunc): New.
+       (madddf4_trunc, msubdf4_trunc, nmuldf3_trunc): New.
+       (nmadddf4_alts, nmadddf4_trunc): New.
+       (addtf3_truncsf, addtf3_truncdf, subtf3_truncsf): New.
+       (subtf3_truncdf, multf3_truncsf, multf3_truncdf): New.
+       (multf3_truncsf_alts, multf3_truncdf_alts): New.
+       (maddtf4_truncsf, maddtf4_truncdf, maddtf4_alts_truncdf): New.
+       (msubtf4_truncsf, msubtf4_truncdf, nmultf3_truncsf): New.
+       (nmultf3_truncdf, nmaddtf4_truncsf, nmaddtf4_truncdf): New.
+       (nmaddtf4_truncdf_alts): New.
+       (recip_approx): Don't predicate.
+
+2000-09-13  Richard Henderson  <rth@cygnus.com>
+
        * config/ia64/lib1funcs.asm (__divsf3): Protect fnorm.s with p6.
 
 2000-09-13  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
index 8593bf6..7049592 100644 (file)
@@ -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:
 
 (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")])
 \f
 ;; ::::::::::::::::::::
 ;; ::
   "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")
   "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")
   "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")))]
   "fma.d %0 = %1, %2, %F3%B0"
   [(set_attr "type" "F")])
 
+(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")
   "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")
   "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 "*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")])
 \f
 ;; ::::::::::::::::::::
 ;; ::
   "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")
   "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")
   "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")
   "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")))]
   "fma %0 = %F1, %F2, %F3%B0"
   [(set_attr "type" "F")])
 
+(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")
   "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")
   "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")
   "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 "*nmaddtf4"
   "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
   "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)
    (use (match_operand:SI 4 "const_int_operand" ""))]
   ""
   "frcpa.s%4 %0, %1 = %2, %3"
-  [(set_attr "type" "F")])
+  [(set_attr "type" "F")
+   (set_attr "predicable" "no")])
 \f
 ;; ::::::::::::::::::::
 ;; ::