+2003-06-15 Roger Sayle <roger@eyesopen.com>
+
+ * config/i386/i386.md (expsf2, expdf2, expxf2): New patterns to
+ implement exp, expf and expl built-ins as inline x87 intrinsics.
+ (UNSPEC_FSCALE, UNSPEC_FRNDINT, UNSPEC_F2XM1): New unspecs to
+ represent x87's fscale, frndint and f2xm1 insns respectively.
+ (*fscale_sfxf3, *fscale_dfxf3, *fscale_xf3): New insn patterns
+ to encode x87's "fscale" instruction followed by a pop.
+ (*frndintxf2): New insn pattern for "frndint".
+ (*f2xm1xf2): New insn pattern for "f2xm1".
+
+ * reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_FRNDINT and
+ UNSPEC_F2XM1 like UNSPEC_{SIN,COS} and handle UNSPEC_FSCALE like
+ UNSPEC_FPATAN.
+
2003-06-15 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* Makefile.in (stagefeedback-start): Use $(SUBDIRS) instead of
; x87 Floating point
(UNSPEC_FPATAN 65)
(UNSPEC_FYL2X 66)
+ (UNSPEC_FSCALE 67)
+ (UNSPEC_FRNDINT 68)
+ (UNSPEC_F2XM1 69)
; REP instruction
- (UNSPEC_REP 67)
+ (UNSPEC_REP 75)
])
(define_constants
temp = standard_80387_constant_rtx (4); /* fldln2 */
emit_move_insn (operands[2], temp);
})
+
+(define_insn "*fscale_sfxf3"
+ [(parallel [(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_dup 1))])]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "fscale\;fstp\t%y1"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "SF")])
+
+(define_insn "*fscale_dfxf3"
+ [(parallel [(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_dup 1))])]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "fscale\;fstp\t%y1"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DF")])
+
+(define_insn "*fscale_xf3"
+ [(parallel [(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_dup 1))])]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "fscale\;fstp\t%y1"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
+(define_insn "*frndintxf2"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "frndint"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
+(define_insn "*f2xm1xf2"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_F2XM1))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "f2xm1"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
+(define_expand "expsf2"
+ [(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))
+ (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_dup 5))])]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx temp;
+ int i;
+
+ for (i=2; i<10; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (5); /* fldl2e */
+ emit_move_insn (operands[3], temp);
+ emit_move_insn (operands[8], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "expdf2"
+ [(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))
+ (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_dup 5))])]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx temp;
+ int i;
+
+ for (i=2; i<10; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (5); /* fldl2e */
+ emit_move_insn (operands[3], temp);
+ emit_move_insn (operands[8], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "expxf2"
+ [(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))
+ (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_dup 4))])]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx temp;
+ int i;
+
+ for (i=2; i<9; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (5); /* fldl2e */
+ emit_move_insn (operands[2], temp);
+ emit_move_insn (operands[7], CONST1_RTX (XFmode)); /* fld1 */
+})
\f
;; Block operation instructions