+(define_expand "floatsi<mode>2"
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SI 1 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
+ "
+ /* When we use vector converts, we can't have input in memory. */
+ if (GET_MODE (operands[0]) == DFmode
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size && TARGET_SSE_MATH
+ && SSE_FLOAT_MODE_P (DFmode))
+ operands[1] = force_reg (SImode, operands[1]);
+ else if (GET_MODE (operands[0]) == SFmode
+ && !optimize_size && TARGET_USE_VECTOR_CONVERTS && TARGET_SSE_MATH
+ && SSE_FLOAT_MODE_P (SFmode))
+ {
+ /* When !flag_trapping_math, we handle SImode->SFmode vector
+ conversions same way as SImode->DFmode.
+
+ For flat_trapping_math we can't safely use vector conversion without
+ clearing upper half, otherwise precision exception might occur.
+ However we can still generate the common sequence converting value
+ from general register to XMM register as:
+
+ mov reg32, mem32
+ movd mem32, xmm
+ cvtdq2pd xmm,xmm
+
+ because we know that movd clears the upper half.
+
+ Sadly in this case we can't rely on reload moving the value to XMM
+ register, since we need to know if upper half is OK, so we need
+ to do reloading by hand. We force operand to memory unless target
+ supports inter unit moves. */
+ if (!flag_trapping_math)
+ operands[1] = force_reg (SImode, operands[1]);
+ else if (!MEM_P (operands[1]))
+ {
+ rtx tmp = assign_386_stack_local (SImode, SLOT_VIRTUAL);
+ emit_move_insn (tmp, operands[1]);
+ operands[1] = tmp;
+ }
+ }
+ /* Offload operand of cvtsi2ss and cvtsi2sd into memory for
+ !TARGET_INTER_UNIT_CONVERSIONS
+ It is neccesary for the patterns to not accept nonemmory operands
+ as we would optimize out later. */
+ else if (!TARGET_INTER_UNIT_CONVERSIONS
+ && TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
+ && !optimize_size
+ && !MEM_P (operands[1]))
+ {
+ rtx tmp = assign_386_stack_local (GET_MODE (operands[1]), SLOT_VIRTUAL);
+ emit_move_insn (tmp, operands[1]);
+ operands[1] = tmp;
+ }
+ ")
+
+(define_insn "*floatsisf2_mixed_vector"
+ [(set (match_operand:SF 0 "register_operand" "=x,f,?f")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "x,m,r")))]
+ "TARGET_MIX_SSE_I387 && !flag_trapping_math
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size"
+ "@
+ cvtdq2ps\t{%1, %0|%0, %1}
+ fild%z1\t%1
+ #"
+ [(set_attr "type" "sseicvt,fmov,multi")
+ (set_attr "mode" "SF")
+ (set_attr "unit" "*,i387,*")
+ (set_attr "athlon_decode" "double,*,*")
+ (set_attr "amdfam10_decode" "double,*,*")
+ (set_attr "fp_int_src" "false,true,true")])