(UNSPEC_BPERM 51)
(UNSPEC_COPYSIGN 52)
(UNSPEC_PARITY 53)
+ (UNSPEC_FCTIW 54)
+ (UNSPEC_FCTID 55)
+ (UNSPEC_LFIWAX 56)
+ (UNSPEC_LFIWZX 57)
+ (UNSPEC_FCTIWUZ 58)
])
;;
(DI "di")])
(define_mode_attr rreg [(SF "f")
- (DF "Ws")
- (V4SF "Wf")
- (V2DF "Wd")])
+ (DF "ws")
+ (V4SF "wf")
+ (V2DF "wd")])
(define_mode_attr rreg2 [(SF "f")
(DF "d")])
+(define_mode_attr SI_CONVERT_FP [(SF "TARGET_FCFIDS")
+ (DF "TARGET_FCFID")])
+
+(define_mode_attr E500_CONVERT [(SF "!TARGET_FPRS")
+ (DF "TARGET_E500_DOUBLE")])
+
(define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT")
(DF "TARGET_DOUBLE_FLOAT")])
\f
\f
;; Conversions to and from floating-point.
-(define_expand "fixuns_truncsfsi2"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (unsigned_fix:SI (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "")
+; We don't define lfiwax/lfiwzx with the normal definition, because we
+; don't want to support putting SImode in FPR registers.
+(define_insn "lfiwax"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+ (unspec:DI [(match_operand:SI 1 "indexed_or_indirect_operand" "Z")]
+ UNSPEC_LFIWAX))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX"
+ "lfiwax %0,%y1"
+ [(set_attr "type" "fpload")])
+
+(define_insn_and_split "floatsi<mode>2_lfiwax"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>,<rreg2>")
+ (float:SFDF (match_operand:SI 1 "nonimmediate_operand" "Z,r")))
+ (clobber (match_operand:SI 2 "indexed_or_indirect_operand" "=Z,Z"))
+ (clobber (match_operand:DI 3 "gpc_reg_operand" "=d,d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
+ && <SI_CONVERT_FP>"
+ "#"
+ "MEM_P (operands[1]) || reload_completed"
+ [(pc)]
+ "
+{
+ if (MEM_P (operands[1]))
+ {
+ operands[1] = rs6000_address_for_fpconvert (operands[1]);
+ emit_insn (gen_lfiwax (operands[3], operands[1]));
+ }
+ else
+ {
+ emit_move_insn (operands[2], operands[1]);
+ emit_insn (gen_lfiwax (operands[3], operands[2]));
+ }
+ emit_insn (gen_floatdi<mode>2 (operands[0], operands[3]));
+ DONE;
+}"
+ [(set_attr "length" "8,12")])
-(define_expand "fix_truncsfsi2"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (fix:SI (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "")
+(define_insn_and_split "floatsi<mode>2_lfiwax_mem"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (float:SFDF (match_operand:SI 1 "memory_operand" "Z")))
+ (clobber (match_scratch:DI 2 "=d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
+ && <SI_CONVERT_FP>"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_insn (gen_lfiwax (operands[2], operands[1]));
+ emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
+ DONE;
+}"
+ [(set_attr "length" "8")])
-(define_expand "fixuns_truncdfsi2"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
- "")
+(define_insn_and_split "floatsi<mode>2_lfiwax_mem2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (float:SFDF
+ (sign_extend:DI
+ (match_operand:SI 1 "memory_operand" "Z"))))
+ (clobber (match_scratch:DI 2 "=d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
+ && <SI_CONVERT_FP>"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_insn (gen_lfiwax (operands[2], operands[1]));
+ emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
+ DONE;
+}"
+ [(set_attr "length" "8")])
-(define_expand "fixuns_truncdfdi2"
- [(set (match_operand:DI 0 "register_operand" "")
- (unsigned_fix:DI (match_operand:DF 1 "register_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_VSX"
- "")
+(define_insn "lfiwzx"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+ (unspec:DI [(match_operand:SI 1 "indexed_or_indirect_operand" "Z")]
+ UNSPEC_LFIWZX))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX"
+ "lfiwzx %0,%y1"
+ [(set_attr "type" "fpload")])
+
+(define_insn_and_split "floatunssi<mode>2_lfiwzx"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>,<rreg2>")
+ (unsigned_float:SFDF (match_operand:SI 1 "gpc_reg_operand" "Z,r")))
+ (clobber (match_operand:SI 2 "indexed_or_indirect_operand" "=Z,Z"))
+ (clobber (match_operand:DI 3 "gpc_reg_operand" "=d,d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
+ && <SI_CONVERT_FP>"
+ "#"
+ "MEM_P (operands[1]) || reload_completed"
+ [(pc)]
+ "
+{
+ if (MEM_P (operands[1]))
+ {
+ operands[1] = rs6000_address_for_fpconvert (operands[1]);
+ emit_insn (gen_lfiwzx (operands[3], operands[1]));
+ }
+ else
+ {
+ emit_move_insn (operands[2], operands[1]);
+ emit_insn (gen_lfiwzx (operands[3], operands[2]));
+ }
+ emit_insn (gen_floatdi<mode>2 (operands[0], operands[3]));
+ DONE;
+}"
+ [(set_attr "length" "8,12")])
+
+(define_insn_and_split "floatunssi<mode>2_lfiwzx_mem"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (unsigned_float:SFDF (match_operand:SI 1 "memory_operand" "Z")))
+ (clobber (match_scratch:DI 2 "=d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
+ && <SI_CONVERT_FP>"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_insn (gen_lfiwzx (operands[2], operands[1]));
+ emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
+ DONE;
+}"
+ [(set_attr "length" "8")])
+
+(define_insn_and_split "floatunssi<mode>2_lfiwzx_mem2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (unsigned_float:SFDF
+ (zero_extend:DI
+ (match_operand:SI 1 "memory_operand" "Z"))))
+ (clobber (match_scratch:DI 2 "=d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
+ && <SI_CONVERT_FP>"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_insn (gen_lfiwzx (operands[2], operands[1]));
+ emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
+ DONE;
+}"
+ [(set_attr "length" "8")])
; For each of these conversions, there is a define_expand, a define_insn
; with a '#' template, and a define_split (with C code). The idea is
(define_expand "floatsidf2"
[(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
(use (match_dup 2))
(use (match_dup 3))
(clobber (match_dup 4))
{
if (TARGET_E500_DOUBLE)
{
+ if (!REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
DONE;
}
- if (TARGET_POWERPC64)
+ else if (TARGET_LFIWAX && TARGET_FCFID)
+ {
+ rs6000_expand_convert_si_to_sfdf (operands[0], operands[1], false);
+ DONE;
+ }
+ else if (TARGET_FCFID)
{
- rtx x = convert_to_mode (DImode, operands[1], 0);
- emit_insn (gen_floatdidf2 (operands[0], x));
+ rtx dreg = operands[1];
+ if (!REG_P (dreg))
+ dreg = force_reg (SImode, dreg);
+ dreg = convert_to_mode (DImode, dreg, false);
+ emit_insn (gen_floatdidf2 (operands[0], dreg));
DONE;
}
+ if (!REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
operands[2] = force_reg (SImode, GEN_INT (0x43300000));
operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503601774854144\", DFmode));
- operands[4] = assign_stack_temp (DFmode, GET_MODE_SIZE (DFmode), 0);
+ operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
operands[5] = gen_reg_rtx (DFmode);
operands[6] = gen_reg_rtx (SImode);
}")
(clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
(clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))
(clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "! TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"#"
""
[(pc)]
}"
[(set_attr "length" "24")])
+;; If we don't have a direct conversion to single precision, don't enable this
+;; conversion for 32-bit without fast math, because we don't have the insn to
+;; generate the fixup swizzle to avoid double rounding problems.
(define_expand "floatunssisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
- (unsigned_float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "")
+ (unsigned_float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
+ && (!TARGET_FPRS
+ || (TARGET_FPRS
+ && ((TARGET_FCFIDUS && TARGET_LFIWZX)
+ || (TARGET_DOUBLE_FLOAT && TARGET_FCFID
+ && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
+ "
+{
+ if (!TARGET_FPRS)
+ {
+ if (!REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
+ }
+ else if (TARGET_LFIWZX && TARGET_FCFIDUS)
+ {
+ rs6000_expand_convert_si_to_sfdf (operands[0], operands[1], true);
+ DONE;
+ }
+ else
+ {
+ rtx dreg = operands[1];
+ if (!REG_P (dreg))
+ dreg = force_reg (SImode, dreg);
+ dreg = convert_to_mode (DImode, dreg, true);
+ emit_insn (gen_floatdisf2 (operands[0], dreg));
+ DONE;
+ }
+}")
(define_expand "floatunssidf2"
[(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
+ (unsigned_float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
(use (match_dup 2))
(use (match_dup 3))
(clobber (match_dup 4))
(clobber (match_dup 5))])]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
+ "TARGET_HARD_FLOAT
+ && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
"
{
if (TARGET_E500_DOUBLE)
{
+ if (!REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
emit_insn (gen_spe_floatunssidf2 (operands[0], operands[1]));
DONE;
}
- if (TARGET_POWERPC64)
+ else if (TARGET_LFIWZX && TARGET_FCFID)
{
- rtx x = convert_to_mode (DImode, operands[1], 1);
- emit_insn (gen_floatdidf2 (operands[0], x));
+ rs6000_expand_convert_si_to_sfdf (operands[0], operands[1], true);
+ DONE;
+ }
+ else if (TARGET_FCFID)
+ {
+ rtx dreg = operands[1];
+ if (!REG_P (dreg))
+ dreg = force_reg (SImode, dreg);
+ dreg = convert_to_mode (DImode, dreg, true);
+ emit_insn (gen_floatdidf2 (operands[0], dreg));
DONE;
}
+ if (!REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
operands[2] = force_reg (SImode, GEN_INT (0x43300000));
operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503599627370496\", DFmode));
- operands[4] = assign_stack_temp (DFmode, GET_MODE_SIZE (DFmode), 0);
+ operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
operands[5] = gen_reg_rtx (DFmode);
}")
(use (match_operand:DF 3 "gpc_reg_operand" "d"))
(clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
(clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "! TARGET_FCFIDU && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !(TARGET_FCFID && TARGET_POWERPC64)"
"#"
""
[(pc)]
}"
[(set_attr "length" "20")])
-(define_expand "fix_truncdfsi2"
- [(parallel [(set (match_operand:SI 0 "fix_trunc_dest_operand" "")
- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
- (clobber (match_dup 2))
- (clobber (match_dup 3))])]
- "(TARGET_POWER2 || TARGET_POWERPC)
- && TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
+(define_expand "fix_trunc<mode>si2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT
+ && ((TARGET_FPRS && <TARGET_FLOAT>) || <E500_CONVERT>)"
"
{
- if (TARGET_E500_DOUBLE)
+ if (!<E500_CONVERT>)
{
- emit_insn (gen_spe_fix_truncdfsi2 (operands[0], operands[1]));
- DONE;
+ rtx tmp, stack;
+
+ if (TARGET_STFIWX)
+ {
+ tmp = gen_reg_rtx (DImode);
+ stack = rs6000_allocate_stack_temp (SImode, false, true);
+ emit_insn (gen_fix_trunc<mode>si2_stfiwx (operands[0], operands[1],
+ tmp, stack));
+ }
+ else
+ {
+ tmp = gen_reg_rtx (DImode);
+ stack = rs6000_allocate_stack_temp (DImode, true, false);
+ emit_insn (gen_fix_trunc<mode>si2_internal (operands[0], operands[1],
+ tmp, stack));
+ }
+ DONE;
}
- operands[2] = gen_reg_rtx (DImode);
- if (TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
- && gpc_reg_operand(operands[0], GET_MODE (operands[0])))
+}")
+
+(define_insn_and_split "fix_trunc<mode>si2_stfiwx"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")))
+ (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
+ (clobber (match_operand:SI 3 "indexed_or_indirect_operand" "=Z"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
+ && TARGET_STFIWX"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
+ if (TARGET_MFPGPR && TARGET_POWERPC64 && REG_P (operands[0])
+ && INT_REGNO_P (REGNO (operands[0])))
{
- operands[3] = gen_reg_rtx (DImode);
- emit_insn (gen_fix_truncdfsi2_mfpgpr (operands[0], operands[1],
- operands[2], operands[3]));
- DONE;
+ rtx reg = gen_lowpart (DImode, operands[0]);
+ emit_move_insn (reg, operands[2]);
}
- if (TARGET_PPC_GFXOPT)
+ else
{
- rtx orig_dest = operands[0];
- if (! memory_operand (orig_dest, GET_MODE (orig_dest)))
- operands[0] = assign_stack_temp (SImode, GET_MODE_SIZE (SImode), 0);
- emit_insn (gen_fix_truncdfsi2_internal_gfxopt (operands[0], operands[1],
- operands[2]));
- if (operands[0] != orig_dest)
- emit_move_insn (orig_dest, operands[0]);
- DONE;
+ emit_insn (gen_stfiwx (operands[3], operands[2]));
+ emit_move_insn (operands[0], operands[3]);
}
- operands[3] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
-}")
+ DONE;
+}"
+ [(set_attr "length" "12")])
+
+(define_insn_and_split "*fix_trunc<mode>si2_mem"
+ [(set (match_operand:SI 0 "memory_operand" "=Z")
+ (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")))
+ (clobber (match_scratch:DI 2 "=d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
+ && TARGET_STFIWX"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
+ emit_insn (gen_stfiwx (operands[0], operands[2]));
+ DONE;
+}"
+ [(set_attr "length" "8")])
-(define_insn_and_split "*fix_truncdfsi2_internal"
+(define_insn_and_split "fix_trunc<mode>si2_internal"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
+ (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<rreg>")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
(clobber (match_operand:DI 3 "offsettable_mem_operand" "=o"))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
gcc_assert (MEM_P (operands[3]));
lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
- emit_insn (gen_fctiwz (operands[2], operands[1]));
+ emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
emit_move_insn (operands[3], operands[2]);
emit_move_insn (operands[0], lowword);
DONE;
}"
[(set_attr "length" "16")])
-(define_insn_and_split "fix_truncdfsi2_internal_gfxopt"
+(define_expand "fix_trunc<mode>di2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+ && TARGET_FCFID"
+ "")
+
+(define_insn "*fix_trunc<mode>di2_fctidz"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+ (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+ && TARGET_FCFID && !VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "fctidz %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_expand "fixuns_trunc<mode>si2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT
+ && ((TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ && TARGET_STFIWX)
+ || <E500_CONVERT>)"
+ "
+{
+ if (!<E500_CONVERT>)
+ {
+ rtx tmp = gen_reg_rtx (DImode);
+ rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
+ emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1],
+ tmp, stack));
+ DONE;
+ }
+}")
+
+(define_insn_and_split "fixuns_trunc<mode>si2_stfiwx"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unsigned_fix:SI
+ (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")))
+ (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
+ (clobber (match_operand:SI 3 "indexed_or_indirect_operand" "=Z"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
+ && TARGET_STFIWX"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_insn (gen_fctiwuz_<mode> (operands[2], operands[1]));
+ if (TARGET_MFPGPR && TARGET_POWERPC64 && REG_P (operands[0])
+ && INT_REGNO_P (REGNO (operands[0])))
+ {
+ rtx reg = gen_lowpart (DImode, operands[0]);
+ emit_move_insn (reg, operands[2]);
+ }
+ else
+ {
+ emit_insn (gen_stfiwx (operands[3], operands[2]));
+ emit_move_insn (operands[0], operands[3]);
+ }
+ DONE;
+}"
+ [(set_attr "length" "12")])
+
+(define_insn_and_split "*fixuns_trunc<mode>si2_mem"
[(set (match_operand:SI 0 "memory_operand" "=Z")
- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
- (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))]
- "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_DOUBLE_FLOAT
- && TARGET_PPC_GFXOPT"
+ (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")))
+ (clobber (match_scratch:DI 2 "=d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
+ && TARGET_STFIWX"
"#"
- "&& 1"
+ "&& reload_completed"
[(pc)]
"
{
- emit_insn (gen_fctiwz (operands[2], operands[1]));
+ emit_insn (gen_fctiwuz_<mode> (operands[2], operands[1]));
emit_insn (gen_stfiwx (operands[0], operands[2]));
DONE;
}"
- [(set_attr "length" "16")])
+ [(set_attr "length" "8")])
-(define_insn_and_split "fix_truncdfsi2_mfpgpr"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
- (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
- (clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))]
- "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_DOUBLE_FLOAT"
- "#"
- "&& 1"
- [(set (match_dup 2) (unspec:DI [(fix:SI (match_dup 1))] UNSPEC_FCTIWZ))
- (set (match_dup 3) (match_dup 2))
- (set (match_dup 0) (subreg:SI (match_dup 3) 4))]
- ""
- [(set_attr "length" "12")])
+(define_expand "fixuns_trunc<mode>di2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unsigned_fix:DI (match_operand:SFDF 1 "register_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FCTIDUZ || VECTOR_UNIT_VSX_P (<MODE>mode))"
+ "")
+
+(define_insn "*fixuns_trunc<mode>di2_fctiduz"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+ (unsigned_fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+ && TARGET_FCTIDUZ && !VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "fctiduz %0,%1"
+ [(set_attr "type" "fp")])
; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
; rather than (set (subreg:SI (reg)) (fix:SI ...))
; because the first makes it clear that operand 0 is not live
; before the instruction.
-(define_insn "fctiwz"
+(define_insn "fctiwz_<mode>"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
- (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))]
+ (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))]
UNSPEC_FCTIWZ))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
&& TARGET_DOUBLE_FLOAT"
"{fcirz|fctiwz} %0,%1"
[(set_attr "type" "fp")])
-(define_expand "btruncdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
- "")
-
-(define_insn "*btruncdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "friz %0,%1"
+(define_insn "fctiwuz_<mode>"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+ (unspec:DI [(unsigned_fix:SI
+ (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>"))]
+ UNSPEC_FCTIWUZ))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ"
+ "fctiwuz %0,%1"
[(set_attr "type" "fp")])
-(define_insn "btruncsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "friz %0,%1"
+;; No VSX equivalent to fctid
+(define_insn "lrint<mode>di2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+ (unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+ UNSPEC_FCTID))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
+ "fctid %0,%1"
[(set_attr "type" "fp")])
-(define_expand "ceildf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+(define_expand "btrunc<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
+ UNSPEC_FRIZ))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
"")
-(define_insn "*ceildf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "frip %0,%1"
+(define_insn "*btrunc<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+ UNSPEC_FRIZ))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
+ && !VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "friz %0,%1"
[(set_attr "type" "fp")])
-(define_insn "ceilsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
+(define_expand "ceil<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
+ UNSPEC_FRIP))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
+ "")
+
+(define_insn "*ceil<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+ UNSPEC_FRIP))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
+ && !VECTOR_UNIT_VSX_P (<MODE>mode)"
"frip %0,%1"
[(set_attr "type" "fp")])
-(define_expand "floordf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+(define_expand "floor<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
+ UNSPEC_FRIM))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
"")
-(define_insn "*floordf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "frim %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn "floorsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
+(define_insn "*floor<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+ UNSPEC_FRIM))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
+ && !VECTOR_UNIT_VSX_P (<MODE>mode)"
"frim %0,%1"
[(set_attr "type" "fp")])
;; No VSX equivalent to frin
-(define_insn "rounddf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIN))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
- "frin %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn "roundsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
+(define_insn "round<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+ UNSPEC_FRIN))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
"frin %0,%1"
[(set_attr "type" "fp")])
-(define_expand "ftruncdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (fix:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "")
-
; An UNSPEC is used so we don't have to support SImode in FP registers.
(define_insn "stfiwx"
[(set (match_operand:SI 0 "memory_operand" "=Z")
"stfiwx %1,%y0"
[(set_attr "type" "fpstore")])
+;; If we don't have a direct conversion to single precision, don't enable this
+;; conversion for 32-bit without fast math, because we don't have the insn to
+;; generate the fixup swizzle to avoid double rounding problems.
(define_expand "floatsisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
- (float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && !TARGET_FPRS"
- "")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
+ && (!TARGET_FPRS
+ || (TARGET_FPRS
+ && ((TARGET_FCFIDS && TARGET_LFIWAX)
+ || (TARGET_DOUBLE_FLOAT && TARGET_FCFID
+ && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
+ "
+{
+ if (!TARGET_FPRS)
+ {
+ if (!REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
+ }
+ else if (TARGET_FCFIDS && TARGET_LFIWAX)
+ {
+ rs6000_expand_convert_si_to_sfdf (operands[0], operands[1], false);
+ DONE;
+ }
+ else
+ {
+ rtx dreg = operands[1];
+ if (!REG_P (dreg))
+ dreg = force_reg (SImode, dreg);
+ dreg = convert_to_mode (DImode, dreg, false);
+ emit_insn (gen_floatdisf2 (operands[0], dreg));
+ DONE;
+ }
+}")
(define_expand "floatdidf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
- "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
- && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
"")
(define_insn "*floatdidf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (float:DF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))]
- "(TARGET_POWERPC64 || TARGET_XILINX_FPU)
- && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+ (float:DF (match_operand:DI 1 "gpc_reg_operand" "d")))]
+ "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
&& !VECTOR_UNIT_VSX_P (DFmode)"
"fcfid %0,%1"
[(set_attr "type" "fp")])
+; Allow the combiner to merge source memory operands to the conversion so that
+; the optimizer/register allocator doesn't try to load the value too early in a
+; GPR and then use store/load to move it to a FPR and suffer from a store-load
+; hit. We will split after reload to avoid the trip through the GPRs
+
+(define_insn_and_split "*floatdidf2_mem"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (float:DF (match_operand:DI 1 "memory_operand" "m")))
+ (clobber (match_scratch:DI 2 "=d"))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS && TARGET_FCFID"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (float:DF (match_dup 2)))]
+ ""
+ [(set_attr "length" "8")])
+
(define_expand "floatunsdidf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
- (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
- "TARGET_VSX"
+ (unsigned_float:DF
+ (match_operand:DI 1 "gpc_reg_operand" "")))]
+ "TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode)"
"")
-(define_expand "fix_truncdfdi2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (fix:DI (match_operand:DF 1 "gpc_reg_operand" "")))]
- "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
- && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
- "")
+(define_insn "*floatunsdidf2_fcfidu"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "d")))]
+ "TARGET_FCFIDU && !VECTOR_UNIT_VSX_P (DFmode)"
+ "fcfidu %0,%1"
+ [(set_attr "type" "fp")
+ (set_attr "length" "4")])
-(define_insn "*fix_truncdfdi2_fpr"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r")
- (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "(TARGET_POWERPC64 || TARGET_XILINX_FPU)
- && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fctidz %0,%1"
- [(set_attr "type" "fp")])
+(define_insn_and_split "*floatunsdidf2_mem"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (unsigned_float:DF (match_operand:DI 1 "memory_operand" "m")))
+ (clobber (match_scratch:DI 2 "=d"))]
+ "TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode)"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (unsigned_float:DF (match_dup 2)))]
+ ""
+ [(set_attr "length" "8")])
(define_expand "floatdisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
- "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
+ "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && (TARGET_FCFIDS || TARGET_POWERPC64 || flag_unsafe_math_optimizations)"
"
{
- rtx val = operands[1];
- if (!flag_unsafe_math_optimizations)
+ if (!TARGET_FCFIDS)
{
- rtx label = gen_label_rtx ();
- val = gen_reg_rtx (DImode);
- emit_insn (gen_floatdisf2_internal2 (val, operands[1], label));
- emit_label (label);
+ rtx val = operands[1];
+ if (!flag_unsafe_math_optimizations)
+ {
+ rtx label = gen_label_rtx ();
+ val = gen_reg_rtx (DImode);
+ emit_insn (gen_floatdisf2_internal2 (val, operands[1], label));
+ emit_label (label);
+ }
+ emit_insn (gen_floatdisf2_internal1 (operands[0], val));
+ DONE;
}
- emit_insn (gen_floatdisf2_internal1 (operands[0], val));
- DONE;
}")
+(define_insn "floatdisf2_fcfids"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
+ "fcfids %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn_and_split "*floatdisf2_mem"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (float:SF (match_operand:DI 1 "memory_operand" "m")))
+ (clobber (match_scratch:DI 2 "=f"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_move_insn (operands[2], operands[1]);
+ emit_insn (gen_floatdisf2_fcfids (operands[0], operands[2]));
+ DONE;
+}"
+ [(set_attr "length" "8")])
+
;; This is not IEEE compliant if rounding mode is "round to nearest".
;; If the DI->DF conversion is inexact, then it's possible to suffer
;; from double rounding.
(define_insn_and_split "floatdisf2_internal1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (float:SF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))
+ (float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))
(clobber (match_scratch:DF 2 "=d"))]
- "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
+ "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
"#"
"&& reload_completed"
[(set (match_dup 2)
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (CCUNSmode);
}")
+
+(define_expand "floatunsdisf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
+ "")
+
+(define_insn "floatunsdisf2_fcfidus"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
+ "fcfidus %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn_and_split "*floatunsdisf2_mem"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (unsigned_float:SF (match_operand:DI 1 "memory_operand" "m")))
+ (clobber (match_scratch:DI 2 "=f"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+ "
+{
+ emit_move_insn (operands[2], operands[1]);
+ emit_insn (gen_floatunsdisf2_fcfidus (operands[0], operands[2]));
+ DONE;
+}"
+ [(set_attr "length" "8")])
\f
;; Define the DImode operations that can be done in a small number
;; of instructions. The & constraints are to prevent the register
gcc_assert (MEM_P (operands[5]));
lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
- emit_insn (gen_fctiwz (operands[4], operands[2]));
+ emit_insn (gen_fctiwz_df (operands[4], operands[2]));
emit_move_insn (operands[5], operands[4]);
emit_move_insn (operands[0], lowword);
DONE;