#define TARGET_SSE ((target_flags & (MASK_SSE | MASK_SSE2)) != 0)
#define TARGET_SSE2 ((target_flags & MASK_SSE2) != 0)
-#define TARGET_MIX_SSE_I387 ((target_flags & MASK_MIX_SSE_I387) != 0)
+#define TARGET_SSE_MATH ((ix86_fpmath & FPMATH_SSE) != 0)
+#define TARGET_MIX_SSE_I387 ((ix86_fpmath & FPMATH_SSE) \
+ && (ix86_fpmath & FPMATH_387))
#define TARGET_MMX ((target_flags & MASK_MMX) != 0)
#define TARGET_3DNOW ((target_flags & MASK_3DNOW) != 0)
#define TARGET_3DNOW_A ((target_flags & MASK_3DNOW_A) != 0)
{ "no-sse2", -MASK_SSE2, N_("") }, \
{ "no-sse2", MASK_SSE2_SET, \
N_("Do not support MMX, SSE and SSE2 builtins and code generation") }, \
- { "mix-sse-i387", MASK_MIX_SSE_I387, \
- N_("Use both SSE and i387 instruction sets for floating point arithmetics") },\
- { "no-mix-sse-i387", -MASK_MIX_SSE_I387, \
- N_("Do not use both SSE and i387 instruction sets for floating point arithmetics") },\
{ "128bit-long-double", MASK_128BIT_LONG_DOUBLE, \
N_("sizeof(long double) is 16") }, \
{ "96bit-long-double", -MASK_128BIT_LONG_DOUBLE, \
PROCESSOR_PENTIUM4,
PROCESSOR_max
};
+enum fpmath_unit
+{
+ FPMATH_387 = 1,
+ FPMATH_SSE = 2
+};
extern enum processor_type ix86_cpu;
+extern enum fpmath_unit ix86_fpmath;
extern int ix86_arch;
#define TARGET_OPTIONS \
{ { "cpu=", &ix86_cpu_string, \
N_("Schedule code for given CPU")}, \
+ { "fpmath=", &ix86_fpmath_string, \
+ N_("Generate floating point mathematics using given instruction set")},\
{ "arch=", &ix86_arch_string, \
N_("Generate code for given CPU")}, \
{ "regparm=", &ix86_regparm_string, \
#define SSE_REG_P(n) (REG_P (n) && SSE_REGNO_P (REGNO (n)))
#define SSE_FLOAT_MODE_P(m) \
- ((TARGET_SSE && (m) == SFmode) || (TARGET_SSE2 && (m) == DFmode))
+ ((TARGET_SSE_MATH && (m) == SFmode) || (TARGET_SSE2 && (m) == DFmode))
#define MMX_REGNO_P(n) ((n) >= FIRST_MMX_REG && (n) <= LAST_MMX_REG)
#define MMX_REG_P(xop) (REG_P (xop) && MMX_REGNO_P (REGNO (xop)))
/* Variables in i386.c */
extern const char *ix86_cpu_string; /* for -mcpu=<xxx> */
extern const char *ix86_arch_string; /* for -march=<xxx> */
+extern const char *ix86_fpmath_string; /* for -mfpmath=<xxx> */
extern const char *ix86_regparm_string; /* # registers to use to pass args */
extern const char *ix86_align_loops_string; /* power of two alignment for loops */
extern const char *ix86_align_jumps_string; /* power of two alignment for non-loop jumps */
(match_operand:SF 1 "register_operand" "+f"))
(set (match_dup 1)
(match_dup 0))]
- "reload_completed || !TARGET_SSE2"
+ "reload_completed || !TARGET_SSE"
{
if (STACK_TOP_P (operands[0]))
return "fxch\t%1";
[(set (match_operand:DF 0 "register_operand" "")
(plus:DF (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE2"
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
"")
(define_expand "addsf3"
[(set (match_operand:SF 0 "register_operand" "")
(plus:SF (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"")
\f
;; Subtract instructions
[(set (match_operand:DF 0 "register_operand" "")
(minus:DF (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE2"
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
"")
(define_expand "subsf3"
[(set (match_operand:SF 0 "register_operand" "")
(minus:SF (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"")
\f
;; Multiply instructions
[(set (match_operand:DF 0 "register_operand" "")
(mult:DF (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE2"
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
"")
(define_expand "mulsf3"
[(set (match_operand:SF 0 "register_operand" "")
(mult:SF (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"")
\f
;; Divide instructions
[(set (match_operand:DF 0 "register_operand" "")
(div:DF (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE2"
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
"")
(define_expand "divsf3"
[(set (match_operand:SF 0 "register_operand" "")
(div:SF (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"")
\f
;; Remainder instructions.
;; Gcc is slightly more smart about handling normal two address instructions
;; so use special patterns for add and mull.
+(define_insn "*fop_sf_comm_nosse"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (match_operator:SF 3 "binary_fp_operator"
+ [(match_operand:SF 1 "register_operand" "%0")
+ (match_operand:SF 2 "nonimmediate_operand" "fm")]))]
+ "TARGET_80387 && !TARGET_SSE_MATH
+ && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (const_string "fmul")
+ (const_string "fop")))
+ (set_attr "mode" "SF")])
+
(define_insn "*fop_sf_comm"
[(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "register_operand" "%0,0")
(match_operand:SF 2 "nonimmediate_operand" "fm#x,xm#f")]))]
- "TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)
+ "TARGET_80387 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
&& GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "register_operand" "%0")
(match_operand:SF 2 "nonimmediate_operand" "xm")]))]
- "TARGET_SSE && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
+ "TARGET_SSE_MATH && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
"* return output_387_binary_op (insn, operands);"
[(set_attr "type" "sse")
(set_attr "mode" "SF")])
+(define_insn "*fop_df_comm_nosse"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (match_operator:DF 3 "binary_fp_operator"
+ [(match_operand:DF 1 "register_operand" "%0")
+ (match_operand:DF 2 "nonimmediate_operand" "fm")]))]
+ "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH)
+ && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (const_string "fmul")
+ (const_string "fop")))
+ (set_attr "mode" "DF")])
+
(define_insn "*fop_df_comm"
[(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "register_operand" "%0,0")
(match_operand:DF 2 "nonimmediate_operand" "fm#Y,Ym#f")]))]
- "TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)
+ "TARGET_80387 && TARGET_SSE_MATH && TARGET_SSE2 && TARGET_MIX_SSE_I387
&& GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "register_operand" "%0")
(match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
- "TARGET_SSE2
+ "TARGET_SSE2 && TARGET_SSE_MATH
&& GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
"* return output_387_binary_op (insn, operands);"
[(set_attr "type" "sse")
(const_string "fop")))
(set_attr "mode" "XF")])
+(define_insn "*fop_sf_1_nosse"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (match_operator:SF 3 "binary_fp_operator"
+ [(match_operand:SF 1 "nonimmediate_operand" "0,fm")
+ (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
+ "TARGET_80387 && !TARGET_SSE_MATH
+ && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (cond [(match_operand:SF 3 "mult_operator" "")
+ (const_string "fmul")
+ (match_operand:SF 3 "div_operator" "")
+ (const_string "fdiv")
+ ]
+ (const_string "fop")))
+ (set_attr "mode" "SF")])
+
(define_insn "*fop_sf_1"
[(set (match_operand:SF 0 "register_operand" "=f,f,x")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
(match_operand:SF 2 "nonimmediate_operand" "fm,0,xm#f")]))]
- "TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)
+ "TARGET_80387 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
&& GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonimmediate_operand" "xm")]))]
- "TARGET_SSE
+ "TARGET_SSE_MATH
&& GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'"
"* return output_387_binary_op (insn, operands);"
[(set_attr "type" "sse")
(match_operator:SF 3 "binary_fp_operator"
[(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r"))
(match_operand:SF 2 "register_operand" "0,0")]))]
- "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE"
+ "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE_MATH"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:SF 3 "mult_operator" "")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "register_operand" "0,0")
(float:SF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))]
- "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE"
+ "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE_MATH"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:SF 3 "mult_operator" "")
(set_attr "ppro_uops" "many")
(set_attr "mode" "SI")])
+(define_insn "*fop_df_1_nosse"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (match_operator:DF 3 "binary_fp_operator"
+ [(match_operand:DF 1 "nonimmediate_operand" "0,fm")
+ (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
+ "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH)
+ && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (cond [(match_operand:DF 3 "mult_operator" "")
+ (const_string "fmul")
+ (match_operand:DF 3 "div_operator" "")
+ (const_string "fdiv")
+ ]
+ (const_string "fop")))
+ (set_attr "mode" "DF")])
+
+
(define_insn "*fop_df_1"
[(set (match_operand:DF 0 "register_operand" "=f#Y,f#Y,Y#f")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
(match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym#f")]))]
- "TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)
+ "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
&& GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
- "TARGET_SSE
+ "TARGET_SSE2 && TARGET_SSE_MATH
&& GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'"
"* return output_387_binary_op (insn, operands);"
[(set_attr "type" "sse")])
(match_operator:DF 3 "binary_fp_operator"
[(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r"))
(match_operand:DF 2 "register_operand" "0,0")]))]
- "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE2"
+ "TARGET_80387 && TARGET_USE_FIOP && !(TARGET_SSE2 && TARGET_SSE_MATH)"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:DF 3 "mult_operator" "")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "register_operand" "0,0")
(float:DF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))]
- "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE2"
+ "TARGET_80387 && TARGET_USE_FIOP && !(TARGET_SSE2 && TARGET_SSE_MATH)"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:DF 3 "mult_operator" "")
[(match_operand:DF 1 "register_operand" "0,f")
(float_extend:DF
(match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
- "TARGET_80387 && !TARGET_SSE2"
+ "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:DF 3 "mult_operator" "")
(define_expand "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "")
(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
- "(! TARGET_NO_FANCY_MATH_387 && TARGET_80387) || TARGET_SSE2"
+ "(! TARGET_NO_FANCY_MATH_387 && TARGET_80387)
+ || (TARGET_SSE2 && TARGET_SSE_MATH)"
{
- if (!TARGET_SSE2)
+ if (!TARGET_SSE2 || !TARGET_SSE_MATH)
operands[1] = force_reg (DFmode, operands[1]);
})
[(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0#Y,Ym#f")))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (TARGET_SSE2 && TARGET_MIX_SSE_I387)"
+ && (TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387)"
"@
fsqrt
sqrtsd\t{%1, %0|%0, %1}"
(define_insn "sqrtdf2_1_sse_only"
[(set (match_operand:DF 0 "register_operand" "=Y")
(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
- "TARGET_SSE2 && (!TARGET_80387 || !TARGET_MIX_SSE_I387)"
+ "TARGET_SSE2 && TARGET_SSE_MATH && (!TARGET_80387 || !TARGET_MIX_SSE_I387)"
"sqrtsd\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
(set_attr "mode" "DF")
[(set (match_operand:DF 0 "register_operand" "=f")
(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (!TARGET_SSE2 && !TARGET_MIX_SSE_I387)"
+ && (!TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387)"
"fsqrt"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")
[(set (match_operand:DF 0 "register_operand" "=f")
(sqrt:DF (float_extend:DF
(match_operand:SF 1 "register_operand" "0"))))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && !TARGET_SSE2"
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ && !(TARGET_SSE2 && TARGET_SSE_MATH)"
"fsqrt"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC 17))])]
- "TARGET_SSE2"
+ "TARGET_SSE2 && TARGET_SSE_MATH"
"#")
(define_insn "*mindf"
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC 17))]
- "TARGET_SSE2 && TARGET_IEEE_FP"
+ "TARGET_SSE2 && TARGET_IEEE_FP && TARGET_SSE_MATH"
"#")
(define_insn "*mindf_nonieee"
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC 17))]
- "TARGET_SSE2 && !TARGET_IEEE_FP"
+ "TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_IEEE_FP"
"#")
(define_split
(match_operand:DF 2 "nonimmediate_operand" "Ym"))
(match_dup 1)
(match_dup 2)))]
- "TARGET_SSE2 && reload_completed"
+ "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
"minsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")
(set_attr "mode" "DF")])
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC 17))])]
- "TARGET_SSE2"
+ "TARGET_SSE2 && TARGET_SSE_MATH"
"#")
(define_insn "*maxdf"
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC 17))]
- "TARGET_SSE2 && TARGET_IEEE_FP"
+ "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_IEEE_FP"
"#")
(define_insn "*maxdf_nonieee"
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC 17))]
- "TARGET_SSE2 && !TARGET_IEEE_FP"
+ "TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_IEEE_FP"
"#")
(define_split
(match_operand:DF 2 "nonimmediate_operand" "Ym"))
(match_dup 1)
(match_dup 2)))]
- "TARGET_SSE2 && reload_completed"
+ "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
"maxsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")
(set_attr "mode" "DF")])