(UNSPEC_FPREM1_F 90)
(UNSPEC_FPREM1_U 91)
+ ; x87 Rounding
+ (UNSPEC_FRNDINT_FLOOR 96)
+ (UNSPEC_FRNDINT_CEIL 97)
+ (UNSPEC_FRNDINT_TRUNC 98)
+ (UNSPEC_FRNDINT_MASK_PM 99)
+
; REP instruction
(UNSPEC_REP 75)
icmp,test,ibr,setcc,icmov,
push,pop,call,callv,leave,
str,cld,
- fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,
+ fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,frndint,
sselog,sseiadd,sseishft,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,
mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
;; The CPU unit operations uses.
(define_attr "unit" "integer,i387,sse,mmx,unknown"
- (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp")
+ (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,frndint")
(const_string "i387")
(eq_attr "type" "sselog,sseiadd,sseishft,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv")
(const_int 1)))
;; The (bounding maximum) length of an instruction in bytes.
-;; ??? fistp is in fact fldcw/fistp/fldcw sequence. Later we may want
-;; to split it and compute proper length as for other insns.
+;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences.
+;; Later we may want to split them and compute proper length as for
+;; other insns.
(define_attr "length" ""
- (cond [(eq_attr "type" "other,multi,fistp")
+ (cond [(eq_attr "type" "other,multi,fistp,frndint")
(const_int 16)
(eq_attr "type" "fcmp")
(const_int 4)
(const_string "none")
(eq_attr "type" "fistp,leave")
(const_string "both")
+ (eq_attr "type" "frndint")
+ (const_string "load")
(eq_attr "type" "push")
(if_then_else (match_operand 1 "memory_operand" "")
(const_string "both")
(define_attr "fp_int_src" "false,true"
(const_string "false"))
+;; Defines rounding mode of an FP operation.
+
+(define_attr "i387_cw" "floor,ceil,trunc,mask_pm,any"
+ (const_string "any"))
+
;; Describe a user's asm statement.
(define_asm_attributes
[(set_attr "length" "128")
DONE;
}
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "DI")])
(define_insn "fix_truncdi_nomemory"
&& (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
"#"
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "DI")])
(define_insn "fix_truncdi_memory"
&& (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
"* operands[5] = operands[4]; return output_fix_trunc (insn, operands);"
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "DI")])
(define_split
DONE;
}
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "SI")])
(define_insn "fix_truncsi_nomemory"
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"#"
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "SI")])
(define_insn "fix_truncsi_memory"
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "SI")])
;; When SSE available, it is always faster to use it!
DONE;
}
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "HI")])
(define_insn "fix_trunchi_nomemory"
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"#"
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "HI")])
(define_insn "fix_trunchi_memory"
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
(set_attr "mode" "HI")])
(define_split
(set (match_dup 0) (match_dup 4))]
"")
-;; %% Not used yet.
(define_insn "x86_fnstcw_1"
[(set (match_operand:HI 0 "memory_operand" "=m")
(unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))]
operands[3] = gen_reg_rtx (XFmode);
})
-(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")]
emit_move_insn (operands[2], temp);
emit_move_insn (operands[9], CONST1_RTX (XFmode)); /* fld1 */
})
+\f
+
+(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_expand "rintdf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2 (op0, op1));
+
+ emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "rintsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2 (op0, op1));
+
+ emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "rintxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ emit_insn (gen_frndintxf2 (operands[0], operands[1]));
+ DONE;
+})
+
+(define_insn "frndintxf2_floor"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "XF")])
+
+(define_expand "floordf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3));
+
+ emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "floorsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3));
+
+ emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "floorxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_frndintxf2_floor (operands[0], operands[1], op2, op3));
+ DONE;
+})
+
+(define_insn "frndintxf2_ceil"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_CEIL))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "XF")])
+
+(define_expand "ceildf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3));
+
+ emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "ceilsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3));
+
+ emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "ceilxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_frndintxf2_ceil (operands[0], operands[1], op2, op3));
+ DONE;
+})
+
+(define_insn "frndintxf2_trunc"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_TRUNC))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "XF")])
+
+(define_expand "btruncdf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3));
+
+ emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "btruncsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3));
+
+ emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "btruncxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_frndintxf2_trunc (operands[0], operands[1], op2, op3));
+ DONE;
+})
+
+(define_insn "frndintxf2_mask_pm"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_MASK_PM))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+ "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "mask_pm")
+ (set_attr "mode" "XF")])
+
+(define_expand "nearbyintdf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_mask_pm (op0, op1, op2, op3));
+
+ emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "nearbyintsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_mask_pm (op0, op1, op2, op3));
+
+ emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "nearbyintxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && flag_unsafe_math_optimizations"
+{
+ rtx op2 = assign_386_stack_local (HImode, 1);
+ rtx op3 = assign_386_stack_local (HImode, 2);
+
+ ix86_optimize_mode_switching = 1;
+
+ emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1],
+ op2, op3));
+ DONE;
+})
+
\f
;; Block operation instructions