;; %%% Kill these when call knows how to work out a DFmode push earlier.
(define_insn "*dummy_extendsfdf2"
[(set (match_operand:DF 0 "push_operand" "=<")
- (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f")))]
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY")))]
"0"
"#")
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
+ "TARGET_80387 || TARGET_SSE2"
"
{
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
}")
(define_insn "*extendsfdf2_1"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
- (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
- "TARGET_80387
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,mf#Y,Y#f,Ym#f")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm#Y,f#Y,mY#f,Y#f")))]
+ "(TARGET_80387 || TARGET_SSE2)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"*
{
else
return \"fst%z0\\t%y0\";
+ case 2:
+ case 3:
+ return \"cvtss2sd\\t{%1, %0|%0, %1}\";
default:
abort ();
}
}"
- [(set_attr "type" "fmov")
- (set_attr "mode" "SF,XF")])
+ [(set_attr "type" "fmov,fmov,sse,sse")
+ (set_attr "mode" "SF,XF,DF,DF")])
+
+(define_insn "*extendsfdf2_1_sse_only"
+ [(set (match_operand:DF 0 "register_operand" "=Y")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "mY")))]
+ "!TARGET_80387 && TARGET_SSE2
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "cvtss2sd\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "DF")])
(define_expand "extendsfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "")
(float_truncate:SF
(match_operand:DF 1 "register_operand" "")))
(clobber (match_dup 2))])]
- "TARGET_80387"
- "operands[2] = assign_386_stack_local (SFmode, 0);")
+ "TARGET_80387 || TARGET_SSE2"
+ "
+ if (TARGET_80387)
+ operands[2] = assign_386_stack_local (SFmode, 0);
+ else
+ {
+ emit_insn (gen_truncdfsf2_sse_only (operands[0], operands[1]));
+ DONE;
+ }
+")
(define_insn "*truncdfsf2_1"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f")
(float_truncate:SF
(match_operand:DF 1 "register_operand" "f,0")))
- (clobber (match_operand:SF 2 "memory_operand" "=m,m"))]
- "TARGET_80387"
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m"))]
+ "TARGET_80387 && !TARGET_SSE2"
"*
{
switch (which_alternative)
abort ();
}"
[(set_attr "type" "fmov,multi")
- (set_attr "mode" "SF")])
+ (set_attr "mode" "SF,SF")])
+
+(define_insn "*truncdfsf2_1_sse"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,Y")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "f,0,mY")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m,X"))]
+ "TARGET_80387 && TARGET_SSE2"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return \"fstp%z0\\t%y0\";
+ else
+ return \"fst%z0\\t%y0\";
+ case 1:
+ return \"fstp%z2\\t%y2\;fld%z2\\t%y2\";
+ case 2:
+ case 3:
+ return \"cvtsd2ss\\t{%1, %0|%0, %1}\";
+ }
+ abort ();
+}"
+ [(set_attr "type" "fmov,multi,sse")
+ (set_attr "mode" "SF,SF,DF")])
(define_insn "*truncdfsf2_2"
- [(set (match_operand:SF 0 "memory_operand" "=m")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,Y")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "f,mY")))]
+ "TARGET_80387 && TARGET_SSE2"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return \"fstp%z0\\t%y0\";
+ else
+ return \"fst%z0\\t%y0\";
+ case 1:
+ case 2:
+ return \"cvtsd2ss\\t{%1, %0|%0, %1}\";
+ }
+}"
+ [(set_attr "type" "fmov,sse")
+ (set_attr "mode" "SF,DF")])
+
+(define_insn "truncdfsf2_3"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m")
(float_truncate:SF
(match_operand:DF 1 "register_operand" "f")))]
"TARGET_80387"
[(set_attr "type" "fmov")
(set_attr "mode" "SF")])
+(define_insn "truncdfsf2_sse_only"
+ [(set (match_operand:SF 0 "register_operand" "=Y")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "mY")))]
+ "!TARGET_80387 && TARGET_SSE2"
+ "cvtsd2ss\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "DF")])
+
(define_split
[(set (match_operand:SF 0 "memory_operand" "")
(float_truncate:SF
[(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
"")
+(define_split
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "")))
+ (clobber (match_operand 2 "" ""))]
+ "TARGET_80387 && !FP_REG_P (operands[0]) && !FP_REG_P (operands[1])"
+ [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
+ "")
+
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
(match_operand:DF 1 "register_operand" "")))
(clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed"
+ "TARGET_80387 && reload_completed
+ && FP_REG_P (operands[0])"
[(set (match_dup 2) (float_truncate:SF (match_dup 1)))
(set (match_dup 0) (match_dup 2))]
"")
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_scratch:SI 4 ""))])]
- "TARGET_80387"
- "operands[2] = assign_386_stack_local (SImode, 0);
- operands[3] = assign_386_stack_local (SImode, 1);")
+ "TARGET_80387 || TARGET_SSE2"
+ "
+{
+ if (TARGET_SSE2)
+ {
+ emit_insn (gen_fix_truncdfsi_sse (operands[0], operands[1]));
+ DONE;
+ }
+ else
+ {
+ operands[2] = assign_386_stack_local (SImode, 0);
+ operands[3] = assign_386_stack_local (SImode, 1);
+ }
+}")
(define_expand "fix_truncsfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_scratch:SI 4 ""))])]
- "TARGET_80387"
- "operands[2] = assign_386_stack_local (SImode, 0);
- operands[3] = assign_386_stack_local (SImode, 1);")
+ "TARGET_80387 || TARGET_SSE"
+ "
+{
+ if (TARGET_SSE2)
+ {
+ emit_insn (gen_fix_truncsfsi_sse (operands[0], operands[1]));
+ DONE;
+ }
+ else
+ {
+ operands[2] = assign_386_stack_local (SImode, 0);
+ operands[3] = assign_386_stack_local (SImode, 1);
+ }
+}")
(define_insn "*fix_truncsi_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r")
(clobber (match_operand:SI 2 "memory_operand" "=o,o"))
(clobber (match_operand:SI 3 "memory_operand" "=m,m"))
(clobber (match_scratch:SI 4 "=&r,r"))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))"
+ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && (!TARGET_SSE2 || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "multi")])
+;; When SSE available, it is always faster to use it!
+(define_insn "fix_truncsfsi_sse"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (match_operand:SF 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE"
+ "cvttss2si\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")])
+
+(define_insn "fix_truncdfsi_sse"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
+ "TARGET_SSE2"
+ "cvttsd2si\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")])
+
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(fix:SI (match_operand 1 "register_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_scratch:SI 4 ""))])]
- "TARGET_80387"
+ "TARGET_80387 && !TARGET_SSE2"
"operands[2] = assign_386_stack_local (SImode, 0);
operands[3] = assign_386_stack_local (HImode, 1);")
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_scratch:SI 4 ""))])]
- "TARGET_80387"
+ "TARGET_80387 && !TARGET_SSE"
"operands[2] = assign_386_stack_local (SImode, 0);
operands[3] = assign_386_stack_local (HImode, 1);")
(clobber (match_operand:SI 2 "memory_operand" "=o,o"))
(clobber (match_operand:HI 3 "memory_operand" "=m,m"))
(clobber (match_scratch:SI 4 "=&r,r"))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))"
+ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && (TARGET_SSE2 || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "multi")])
(set (match_dup 0) (match_dup 3))]
"")
+;; %%% Kill these when reload knows how to do it.
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (fix (match_operand 1 "register_operand" "")))]
+ "reload_completed && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && FP_REG_P (operands[1])"
+ [(const_int 0)]
+ "
+{
+ operands[2] = ix86_force_to_memory (GET_MODE (operands[0]), operands[0]);
+ operands[2] = gen_rtx_FIX (GET_MODE (operands[2]), operands[1]);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[2], operands[1]));
+ emit_move_insn (operands[0], operands[2]);
+ ix86_free_from_memory (GET_MODE (operands[0]));
+ DONE;
+}")
+
;; %% Not used yet.
(define_insn "x86_fnstcw_1"
[(set (match_operand:HI 0 "memory_operand" "=m")
(define_insn "floathisf2"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(float:SF (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387"
+ "TARGET_80387 && !TARGET_SSE"
"@
fild%z1\\t%1
#"
(set_attr "mode" "SF")
(set_attr "fp_int_src" "true")])
-(define_insn "floatsisf2"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387"
+(define_expand "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
+ "TARGET_SSE || TARGET_80387"
+ "")
+
+(define_insn "*floatsisf2_i387"
+ [(set (match_operand:SF 0 "register_operand" "=f,?f,x")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,mr")))]
+ "TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)"
"@
fild%z1\\t%1
- #"
- [(set_attr "type" "fmov,multi")
+ #
+ cvtsi2ss\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "fmov,multi,sse")
+ (set_attr "mode" "SF")
+ (set_attr "fp_int_src" "true")])
+
+(define_insn "*floatsisf2_sse"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "mr")))]
+ "TARGET_80387 && TARGET_SSE"
+ "cvtsi2ss\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
(set_attr "mode" "SF")
(set_attr "fp_int_src" "true")])
(define_insn "floathidf2"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(float:DF (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387"
+ "TARGET_80387 && !TARGET_SSE2"
"@
fild%z1\\t%1
#"
(set_attr "mode" "DF")
(set_attr "fp_int_src" "true")])
-(define_insn "floatsidf2"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387"
+(define_expand "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
+ ""
+ "")
+
+(define_insn "*floatsidf2_i387"
+ [(set (match_operand:DF 0 "register_operand" "=f,?f,Y")
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,mr")))]
+ "TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)"
"@
fild%z1\\t%1
- #"
- [(set_attr "type" "fmov,multi")
+ #
+ cvtsi2sd\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "fmov,multi,sse")
+ (set_attr "mode" "DF")
+ (set_attr "fp_int_src" "true")])
+
+(define_insn "*floatsidf2_sse"
+ [(set (match_operand:DF 0 "register_operand" "=Y")
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "mr")))]
+ "TARGET_SSE2"
+ "cvtsi2sd\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
(set_attr "mode" "DF")
(set_attr "fp_int_src" "true")])
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387"
+ "TARGET_80387 && TARGET_SSE2"
"@
fild%z1\\t%1
#"