i386.md (*fyl2x_sfxf3, [...]): Remove insn definition.
[gcc.git] / gcc / config / i386 / i386.md
index e4f2cce5fbef4209bffdd4912b4cbc0d4551be37..26132f1f5c91a2ef452ada33e60d0f5250eb56df 100644 (file)
    ; x87 Floating point
    (UNSPEC_FPATAN              65)
    (UNSPEC_FYL2X               66)
-   (UNSPEC_FSCALE              67)
    (UNSPEC_FRNDINT             68)
    (UNSPEC_F2XM1               69)
 
    (UNSPEC_SINCOS_SIN          81)
    (UNSPEC_TAN_ONE             82)
    (UNSPEC_TAN_TAN             83)
+   (UNSPEC_XTRACT_FRACT                84)
+   (UNSPEC_XTRACT_EXP          85)
+   (UNSPEC_FSCALE_FRACT                86)
+   (UNSPEC_FSCALE_EXP          87)
 
    ; REP instruction
    (UNSPEC_REP                 75)
 ;; With sincos pattern defined, sin and cos builtin function will be
 ;; expanded to sincos pattern with one of its outputs left unused. 
 ;; Cse pass  will detected, if two sincos patterns can be combined,
-;; otherwise sincos pattern will be splitted back to sin or cos pattern,
+;; otherwise sincos pattern will be split back to sin or cos pattern,
 ;; depending on the unused output.
 
 (define_insn "sincosdf3"
   DONE;
 })
 
+(define_expand "atandf2"
+  [(parallel [(set (match_operand:DF 0 "register_operand" "")
+                  (unspec:DF [(match_dup 2)
+                              (match_operand:DF 1 "register_operand" "")]
+                   UNSPEC_FPATAN))
+             (clobber (match_scratch:DF 3 ""))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  operands[2] = gen_reg_rtx (DFmode);
+  emit_move_insn (operands[2], CONST1_RTX (DFmode));  /* fld1 */
+})
+
 (define_insn "atan2sf3_1"
   [(set (match_operand:SF 0 "register_operand" "=f")
         (unspec:SF [(match_operand:SF 2 "register_operand" "0")
   DONE;
 })
 
+(define_expand "atansf2"
+  [(parallel [(set (match_operand:SF 0 "register_operand" "")
+                  (unspec:SF [(match_dup 2)
+                              (match_operand:SF 1 "register_operand" "")]
+                   UNSPEC_FPATAN))
+             (clobber (match_scratch:SF 3 ""))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  operands[2] = gen_reg_rtx (SFmode);
+  emit_move_insn (operands[2], CONST1_RTX (SFmode));  /* fld1 */
+})
+
 (define_insn "atan2xf3_1"
   [(set (match_operand:XF 0 "register_operand" "=f")
         (unspec:XF [(match_operand:XF 2 "register_operand" "0")
   DONE;
 })
 
-(define_insn "*fyl2x_sfxf3"
-  [(set (match_operand:SF 0 "register_operand" "=f")
-         (unspec:SF [(match_operand:SF 2 "register_operand" "0")
-                    (match_operand:XF 1 "register_operand" "u")]
-                   UNSPEC_FYL2X))
-   (clobber (match_scratch:SF 3 "=1"))]
+(define_expand "atanxf2"
+  [(parallel [(set (match_operand:XF 0 "register_operand" "")
+                  (unspec:XF [(match_dup 2)
+                              (match_operand:XF 1 "register_operand" "")]
+                   UNSPEC_FPATAN))
+             (clobber (match_scratch:XF 3 ""))])]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
-  "fyl2x"
-  [(set_attr "type" "fpspc")
-   (set_attr "mode" "SF")])
+{
+  operands[2] = gen_reg_rtx (XFmode);
+  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
+})
 
-(define_insn "*fyl2x_dfxf3"
-  [(set (match_operand:DF 0 "register_operand" "=f")
-         (unspec:DF [(match_operand:DF 2 "register_operand" "0")
-                    (match_operand:XF 1 "register_operand" "u")]
-                   UNSPEC_FYL2X))
-   (clobber (match_scratch:DF 3 "=1"))]
+(define_expand "asindf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
+   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
+   (set (match_dup 6) (sqrt:XF (match_dup 5)))
+   (parallel [(set (match_dup 7)
+                  (unspec:XF [(match_dup 6) (match_dup 2)]
+                             UNSPEC_FPATAN))
+             (clobber (match_scratch:XF 8 ""))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 7)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
-  "fyl2x"
-  [(set_attr "type" "fpspc")
-   (set_attr "mode" "DF")])
+{
+  int i;
+
+  for (i=2; i<8; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+
+  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
+})
+
+(define_expand "asinsf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
+   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
+   (set (match_dup 6) (sqrt:XF (match_dup 5)))
+   (parallel [(set (match_dup 7)
+                  (unspec:XF [(match_dup 6) (match_dup 2)]
+                             UNSPEC_FPATAN))
+             (clobber (match_scratch:XF 8 ""))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 7)))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  int i;
+
+  for (i=2; i<8; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+
+  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
+})
+
+(define_expand "asinxf2"
+  [(set (match_dup 2)
+       (mult:XF (match_operand:XF 1 "register_operand" "")
+                (match_dup 1)))
+   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
+   (set (match_dup 5) (sqrt:XF (match_dup 4)))
+   (parallel [(set (match_operand:XF 0 "register_operand" "")
+                  (unspec:XF [(match_dup 5) (match_dup 1)]
+                             UNSPEC_FPATAN))
+             (clobber (match_scratch:XF 6 ""))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  int i;
+
+  for (i=2; i<6; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+
+  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
+})
+
+(define_expand "acosdf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
+   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
+   (set (match_dup 6) (sqrt:XF (match_dup 5)))
+   (parallel [(set (match_dup 7)
+                  (unspec:XF [(match_dup 2) (match_dup 6)]
+                             UNSPEC_FPATAN))
+             (clobber (match_scratch:XF 8 ""))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 7)))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  int i;
+
+  for (i=2; i<8; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+
+  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
+})
+
+(define_expand "acossf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
+   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
+   (set (match_dup 6) (sqrt:XF (match_dup 5)))
+   (parallel [(set (match_dup 7)
+                  (unspec:XF [(match_dup 2) (match_dup 6)]
+                             UNSPEC_FPATAN))
+             (clobber (match_scratch:XF 8 ""))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 7)))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  int i;
+
+  for (i=2; i<8; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+
+  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
+})
+
+(define_expand "acosxf2"
+  [(set (match_dup 2)
+       (mult:XF (match_operand:XF 1 "register_operand" "")
+                (match_dup 1)))
+   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
+   (set (match_dup 5) (sqrt:XF (match_dup 4)))
+   (parallel [(set (match_operand:XF 0 "register_operand" "")
+                  (unspec:XF [(match_dup 1) (match_dup 5)]
+                             UNSPEC_FPATAN))
+             (clobber (match_scratch:XF 6 ""))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  int i;
+
+  for (i=2; i<6; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+
+  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
+})
 
 (define_insn "*fyl2x_xf3"
   [(set (match_operand:XF 0 "register_operand" "=f")
    (set_attr "mode" "XF")])
 
 (define_expand "logsf2"
-  [(parallel [(set (match_operand:SF 0 "register_operand" "")
-                  (unspec:SF [(match_operand:SF 1 "register_operand" "")
-                              (match_dup 2)] UNSPEC_FYL2X))
-             (clobber (match_scratch:SF 3 ""))])]
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (parallel [(set (match_dup 4)
+                  (unspec:XF [(match_dup 2)
+                              (match_dup 3)] UNSPEC_FYL2X))
+             (clobber (match_scratch:XF 5 ""))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 4)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
 
   operands[2] = gen_reg_rtx (XFmode);
+  operands[3] = gen_reg_rtx (XFmode);
+  operands[4] = gen_reg_rtx (XFmode);
+
   temp = standard_80387_constant_rtx (4); /* fldln2 */
-  emit_move_insn (operands[2], temp);
+  emit_move_insn (operands[3], temp);
 })
 
 (define_expand "logdf2"
-  [(parallel [(set (match_operand:DF 0 "register_operand" "")
-                  (unspec:DF [(match_operand:DF 1 "register_operand" "")
-                              (match_dup 2)] UNSPEC_FYL2X))
-             (clobber (match_scratch:DF 3 ""))])]
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (parallel [(set (match_dup 4)
+                  (unspec:XF [(match_dup 2)
+                              (match_dup 3)] UNSPEC_FYL2X))
+             (clobber (match_scratch:XF 5 ""))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 4)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
 
   operands[2] = gen_reg_rtx (XFmode);
+  operands[3] = gen_reg_rtx (XFmode);
+  operands[4] = gen_reg_rtx (XFmode);
+
   temp = standard_80387_constant_rtx (4); /* fldln2 */
-  emit_move_insn (operands[2], temp);
+  emit_move_insn (operands[3], temp);
 })
 
 (define_expand "logxf2"
 })
 
 (define_expand "log10sf2"
-  [(parallel [(set (match_operand:SF 0 "register_operand" "")
-                  (unspec:SF [(match_operand:SF 1 "register_operand" "")
-                              (match_dup 2)] UNSPEC_FYL2X))
-             (clobber (match_scratch:SF 3 ""))])]
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (parallel [(set (match_dup 4)
+                  (unspec:XF [(match_dup 2)
+                              (match_dup 3)] UNSPEC_FYL2X))
+             (clobber (match_scratch:XF 5 ""))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 4)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
 
   operands[2] = gen_reg_rtx (XFmode);
+  operands[3] = gen_reg_rtx (XFmode);
+  operands[4] = gen_reg_rtx (XFmode);
+
   temp = standard_80387_constant_rtx (3); /* fldlg2 */
-  emit_move_insn (operands[2], temp);
+  emit_move_insn (operands[3], temp);
 })
 
 (define_expand "log10df2"
-  [(parallel [(set (match_operand:DF 0 "register_operand" "")
-                  (unspec:DF [(match_operand:DF 1 "register_operand" "")
-                              (match_dup 2)] UNSPEC_FYL2X))
-             (clobber (match_scratch:DF 3 ""))])]
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (parallel [(set (match_dup 4)
+                  (unspec:XF [(match_dup 2)
+                              (match_dup 3)] UNSPEC_FYL2X))
+             (clobber (match_scratch:XF 5 ""))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 4)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
 
   operands[2] = gen_reg_rtx (XFmode);
+  operands[3] = gen_reg_rtx (XFmode);
+  operands[4] = gen_reg_rtx (XFmode);
+
   temp = standard_80387_constant_rtx (3); /* fldlg2 */
-  emit_move_insn (operands[2], temp);
+  emit_move_insn (operands[3], temp);
 })
 
 (define_expand "log10xf2"
 })
 
 (define_expand "log2sf2"
-  [(parallel [(set (match_operand:SF 0 "register_operand" "")
-                  (unspec:SF [(match_operand:SF 1 "register_operand" "")
-                              (match_dup 2)] UNSPEC_FYL2X))
-             (clobber (match_scratch:SF 3 ""))])]
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (parallel [(set (match_dup 4)
+                  (unspec:XF [(match_dup 2)
+                              (match_dup 3)] UNSPEC_FYL2X))
+             (clobber (match_scratch:XF 5 ""))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 4)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   operands[2] = gen_reg_rtx (XFmode);
-  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
+  operands[3] = gen_reg_rtx (XFmode);
+  operands[4] = gen_reg_rtx (XFmode);
 
+  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
 })
 
 (define_expand "log2df2"
-  [(parallel [(set (match_operand:DF 0 "register_operand" "")
-                  (unspec:DF [(match_operand:DF 1 "register_operand" "")
-                              (match_dup 2)] UNSPEC_FYL2X))
-             (clobber (match_scratch:DF 3 ""))])]
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (parallel [(set (match_dup 4)
+                  (unspec:XF [(match_dup 2)
+                              (match_dup 3)] UNSPEC_FYL2X))
+             (clobber (match_scratch:XF 5 ""))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 4)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   operands[2] = gen_reg_rtx (XFmode);
-  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
+  operands[3] = gen_reg_rtx (XFmode);
+  operands[4] = gen_reg_rtx (XFmode);
+
+  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
 })
 
 (define_expand "log2xf2"
   emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
 })
 
-(define_insn "*fscale_sfxf3"
-  [(set (match_operand:SF 0 "register_operand" "=f")
-        (unspec:SF [(match_operand:XF 2 "register_operand" "0")
-                    (match_operand:XF 1 "register_operand" "u")]
-                   UNSPEC_FSCALE))
-   (clobber (match_scratch:SF 3 "=1"))]
-  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_insn "*fxtractxf3"
+  [(set (match_operand:XF 0 "register_operand" "=f")
+       (unspec:XF [(match_operand:XF 2 "register_operand" "0")]
+                  UNSPEC_XTRACT_FRACT))
+   (set (match_operand:XF 1 "register_operand" "=u")
+        (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
    && flag_unsafe_math_optimizations"
-  "fscale\;fstp\t%y1"
+  "fxtract"
   [(set_attr "type" "fpspc")
-   (set_attr "mode" "SF")])
+   (set_attr "mode" "XF")])
 
-(define_insn "*fscale_dfxf3"
-  [(set (match_operand:DF 0 "register_operand" "=f")
-        (unspec:DF [(match_operand:XF 2 "register_operand" "0")
-                    (match_operand:XF 1 "register_operand" "u")]
-                   UNSPEC_FSCALE))
-   (clobber (match_scratch:DF 3 "=1"))]
-  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_expand "logbsf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (parallel [(set (match_dup 3)
+                  (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
+             (set (match_dup 4)
+                  (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 4)))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
    && flag_unsafe_math_optimizations"
-  "fscale\;fstp\t%y1"
-  [(set_attr "type" "fpspc")
-   (set_attr "mode" "DF")])
+{
+  operands[2] = gen_reg_rtx (XFmode);
+  operands[3] = gen_reg_rtx (XFmode);
+  operands[4] = gen_reg_rtx (XFmode);
+})
 
-(define_insn "*fscale_xf3"
-  [(set (match_operand:XF 0 "register_operand" "=f")
-       (unspec:XF [(match_operand:XF 2 "register_operand" "0")
-                   (match_operand:XF 1 "register_operand" "u")]
-                  UNSPEC_FSCALE))
-   (clobber (match_scratch:XF 3 "=1"))]
-  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_expand "logbdf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (parallel [(set (match_dup 3)
+                  (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
+             (set (match_dup 4)
+                  (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 4)))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
    && flag_unsafe_math_optimizations"
-  "fscale\;fstp\t%y1"
-  [(set_attr "type" "fpspc")
-   (set_attr "mode" "XF")])
+{
+  operands[2] = gen_reg_rtx (XFmode);
+  operands[3] = gen_reg_rtx (XFmode);
+  operands[4] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "logbxf2"
+  [(parallel [(set (match_dup 2)
+                  (unspec:XF [(match_operand:XF 1 "register_operand" "")]
+                             UNSPEC_XTRACT_FRACT))
+             (set (match_operand:XF 0 "register_operand" "")
+                  (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
+   && flag_unsafe_math_optimizations"
+{
+  operands[2] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "ilogbsi2"
+  [(parallel [(set (match_dup 2)
+                  (unspec:XF [(match_operand:XF 1 "register_operand" "")]
+                             UNSPEC_XTRACT_FRACT))
+             (set (match_operand:XF 3 "register_operand" "")
+                  (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])
+   (parallel [(set (match_operand:SI 0 "register_operand" "")
+                  (fix:SI (match_dup 3)))
+             (clobber (reg:CC 17))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
+   && flag_unsafe_math_optimizations"
+{
+  operands[2] = gen_reg_rtx (XFmode);
+  operands[3] = gen_reg_rtx (XFmode);
+})
 
 (define_insn "*frndintxf2"
   [(set (match_operand:XF 0 "register_operand" "=f")
   [(set_attr "type" "fpspc")
    (set_attr "mode" "XF")])
 
+(define_insn "*fscalexf4"
+  [(set (match_operand:XF 0 "register_operand" "=f")
+       (unspec:XF [(match_operand:XF 2 "register_operand" "0")
+                   (match_operand:XF 3 "register_operand" "1")]
+                  UNSPEC_FSCALE_FRACT))
+   (set (match_operand:XF 1 "register_operand" "=u")
+       (unspec:XF [(match_dup 2) (match_dup 3)]
+                  UNSPEC_FSCALE_EXP))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
+   && flag_unsafe_math_optimizations"
+  "fscale"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "DF")])
+
 (define_expand "expsf2"
   [(set (match_dup 2)
        (float_extend:XF (match_operand:SF 1 "register_operand" "")))
    (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
    (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
    (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
-   (parallel [(set (match_operand:SF 0 "register_operand" "")
-                  (unspec:SF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE))
-             (clobber (match_scratch:SF 5 ""))])]
+   (parallel [(set (match_dup 10)
+                  (unspec:XF [(match_dup 9) (match_dup 5)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 11)
+                  (unspec:XF [(match_dup 9) (match_dup 5)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 10)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
   int i;
 
-  for (i=2; i<10; i++)
+  for (i=2; i<12; i++)
     operands[i] = gen_reg_rtx (XFmode);
   temp = standard_80387_constant_rtx (5); /* fldl2e */
   emit_move_insn (operands[3], temp);
    (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
    (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
    (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
-
    (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
    (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
-   (parallel [(set (match_operand:DF 0 "register_operand" "")
-                  (unspec:DF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE))
-             (clobber (match_scratch:DF 5 ""))])]
+   (parallel [(set (match_dup 10)
+                  (unspec:XF [(match_dup 9) (match_dup 5)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 11)
+                  (unspec:XF [(match_dup 9) (match_dup 5)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 10)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
   int i;
 
-  for (i=2; i<10; i++)
+  for (i=2; i<12; i++)
     operands[i] = gen_reg_rtx (XFmode);
   temp = standard_80387_constant_rtx (5); /* fldl2e */
   emit_move_insn (operands[3], temp);
    (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
    (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
    (parallel [(set (match_operand:XF 0 "register_operand" "")
-                  (unspec:XF [(match_dup 8) (match_dup 4)] UNSPEC_FSCALE))
-             (clobber (match_scratch:XF 5 ""))])]
+                  (unspec:XF [(match_dup 8) (match_dup 4)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 9)
+                  (unspec:XF [(match_dup 8) (match_dup 4)]
+                             UNSPEC_FSCALE_EXP))])]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
   int i;
 
-  for (i=2; i<9; i++)
+  for (i=2; i<10; i++)
     operands[i] = gen_reg_rtx (XFmode);
   temp = standard_80387_constant_rtx (5); /* fldl2e */
   emit_move_insn (operands[2], temp);
    (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
    (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
    (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
-   (parallel [(set (match_operand:SF 0 "register_operand" "")
-                  (unspec:SF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE))
-             (clobber (match_scratch:SF 5 ""))])]
+   (parallel [(set (match_dup 10)
+                  (unspec:XF [(match_dup 9) (match_dup 5)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 11)
+                  (unspec:XF [(match_dup 9) (match_dup 5)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 10)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
   int i;
 
-  for (i=2; i<10; i++)
+  for (i=2; i<12; i++)
     operands[i] = gen_reg_rtx (XFmode);
   temp = standard_80387_constant_rtx (6); /* fldl2t */
   emit_move_insn (operands[3], temp);
    (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
    (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
    (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
-   (parallel [(set (match_operand:DF 0 "register_operand" "")
-                  (unspec:DF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE))
-             (clobber (match_scratch:DF 5 ""))])]
+   (parallel [(set (match_dup 10)
+                  (unspec:XF [(match_dup 9) (match_dup 5)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 11)
+                  (unspec:XF [(match_dup 9) (match_dup 5)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 10)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
   int i;
 
-  for (i=2; i<10; i++)
+  for (i=2; i<12; i++)
     operands[i] = gen_reg_rtx (XFmode);
   temp = standard_80387_constant_rtx (6); /* fldl2t */
   emit_move_insn (operands[3], temp);
    (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
    (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
    (parallel [(set (match_operand:XF 0 "register_operand" "")
-                  (unspec:XF [(match_dup 8) (match_dup 4)] UNSPEC_FSCALE))
-             (clobber (match_scratch:XF 5 ""))])]
+                  (unspec:XF [(match_dup 8) (match_dup 4)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 9)
+                  (unspec:XF [(match_dup 8) (match_dup 4)]
+                             UNSPEC_FSCALE_EXP))])]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   rtx temp;
   int i;
 
-  for (i=2; i<9; i++)
+  for (i=2; i<10; i++)
     operands[i] = gen_reg_rtx (XFmode);
   temp = standard_80387_constant_rtx (6); /* fldl2t */
   emit_move_insn (operands[2], temp);
    (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
    (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
    (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
-   (parallel [(set (match_operand:SF 0 "register_operand" "")
-                  (unspec:SF [(match_dup 7) (match_dup 3)] UNSPEC_FSCALE))
-             (clobber (match_scratch:SF 3 ""))])]
+   (parallel [(set (match_dup 8)
+                  (unspec:XF [(match_dup 7) (match_dup 3)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 9)
+                  (unspec:XF [(match_dup 7) (match_dup 3)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 8)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   int i;
 
-  for (i=2; i<8; i++)
+  for (i=2; i<10; i++)
     operands[i] = gen_reg_rtx (XFmode);
   emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
 })
    (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
    (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
    (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
-   (parallel [(set (match_operand:DF 0 "register_operand" "")
-                  (unspec:DF [(match_dup 7) (match_dup 3)] UNSPEC_FSCALE))
-             (clobber (match_scratch:DF 3 ""))])]
+   (parallel [(set (match_dup 8)
+                  (unspec:XF [(match_dup 7) (match_dup 3)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 9)
+                  (unspec:XF [(match_dup 7) (match_dup 3)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 8)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   int i;
 
-  for (i=2; i<8; i++)
+  for (i=2; i<10; i++)
     operands[i] = gen_reg_rtx (XFmode);
   emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
 })
    (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
    (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
    (parallel [(set (match_operand:XF 0 "register_operand" "")
-                  (unspec:XF [(match_dup 7) (match_dup 3)] UNSPEC_FSCALE))
-             (clobber (match_scratch:XF 3 ""))])]
+                  (unspec:XF [(match_dup 7) (match_dup 3)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 8)
+                  (unspec:XF [(match_dup 7) (match_dup 3)]
+                             UNSPEC_FSCALE_EXP))])]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
   int i;
 
-  for (i=2; i<8; i++)
+  for (i=2; i<9; i++)
     operands[i] = gen_reg_rtx (XFmode);
   emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
 })
 
-(define_expand "atansf2"
-  [(parallel [(set (match_operand:SF 0 "register_operand" "")
-                  (unspec:SF [(match_dup 2)
-                              (match_operand:SF 1 "register_operand" "")]
-                   UNSPEC_FPATAN))
-             (clobber (match_scratch:SF 3 ""))])]
+(define_expand "expm1df2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
+   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
+   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
+   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
+   (parallel [(set (match_dup 8)
+                  (unspec:XF [(match_dup 7) (match_dup 5)]
+                             UNSPEC_FSCALE_FRACT))
+                  (set (match_dup 9)
+                  (unspec:XF [(match_dup 7) (match_dup 5)]
+                             UNSPEC_FSCALE_EXP))])
+   (parallel [(set (match_dup 11)
+                  (unspec:XF [(match_dup 10) (match_dup 9)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 12)
+                  (unspec:XF [(match_dup 10) (match_dup 9)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
+   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
+   (set (match_operand:DF 0 "register_operand" "")
+       (float_truncate:DF (match_dup 14)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
-  operands[2] = gen_reg_rtx (SFmode);
-  emit_move_insn (operands[2], CONST1_RTX (SFmode));  /* fld1 */
+  rtx temp;
+  int i;
+
+  for (i=2; i<15; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+  temp = standard_80387_constant_rtx (5); /* fldl2e */
+  emit_move_insn (operands[3], temp);
+  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
 })
 
-(define_expand "atandf2"
-  [(parallel [(set (match_operand:DF 0 "register_operand" "")
-                  (unspec:DF [(match_dup 2)
-                              (match_operand:DF 1 "register_operand" "")]
-                   UNSPEC_FPATAN))
-             (clobber (match_scratch:DF 3 ""))])]
+(define_expand "expm1sf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
+   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
+   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
+   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
+   (parallel [(set (match_dup 8)
+                  (unspec:XF [(match_dup 7) (match_dup 5)]
+                             UNSPEC_FSCALE_FRACT))
+                  (set (match_dup 9)
+                  (unspec:XF [(match_dup 7) (match_dup 5)]
+                             UNSPEC_FSCALE_EXP))])
+   (parallel [(set (match_dup 11)
+                  (unspec:XF [(match_dup 10) (match_dup 9)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 12)
+                  (unspec:XF [(match_dup 10) (match_dup 9)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
+   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
+   (set (match_operand:SF 0 "register_operand" "")
+       (float_truncate:SF (match_dup 14)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
-  operands[2] = gen_reg_rtx (DFmode);
-  emit_move_insn (operands[2], CONST1_RTX (DFmode));  /* fld1 */
+  rtx temp;
+  int i;
+
+  for (i=2; i<15; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+  temp = standard_80387_constant_rtx (5); /* fldl2e */
+  emit_move_insn (operands[3], temp);
+  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
 })
 
-(define_expand "atanxf2"
-  [(parallel [(set (match_operand:XF 0 "register_operand" "")
-                  (unspec:XF [(match_dup 2)
-                              (match_operand:XF 1 "register_operand" "")]
-                   UNSPEC_FPATAN))
-             (clobber (match_scratch:XF 3 ""))])]
+(define_expand "expm1xf2"
+  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
+                              (match_dup 2)))
+   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
+   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
+   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
+   (parallel [(set (match_dup 7)
+                  (unspec:XF [(match_dup 6) (match_dup 4)]
+                             UNSPEC_FSCALE_FRACT))
+                  (set (match_dup 8)
+                  (unspec:XF [(match_dup 6) (match_dup 4)]
+                             UNSPEC_FSCALE_EXP))])
+   (parallel [(set (match_dup 10)
+                  (unspec:XF [(match_dup 9) (match_dup 8)]
+                             UNSPEC_FSCALE_FRACT))
+             (set (match_dup 11)
+                  (unspec:XF [(match_dup 9) (match_dup 8)]
+                             UNSPEC_FSCALE_EXP))])
+   (set (match_dup 12) (minus:XF (match_dup 10) (match_dup 9)))
+   (set (match_operand:XF 0 "register_operand" "")
+       (plus:XF (match_dup 12) (match_dup 7)))]
   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
    && flag_unsafe_math_optimizations"
 {
-  operands[2] = gen_reg_rtx (XFmode);
-  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
+  rtx temp;
+  int i;
+
+  for (i=2; i<13; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+  temp = standard_80387_constant_rtx (5); /* fldl2e */
+  emit_move_insn (operands[2], temp);
+  emit_move_insn (operands[9], CONST1_RTX (XFmode));  /* fld1 */
 })
 \f
 ;; Block operation instructions