From 520b7351be5faa46c4df91b47eaa7bf9196a6aef Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Thu, 26 Feb 2004 18:40:41 +0000 Subject: [PATCH] * config/sparc/sparc-protos.h (sparc_emit_floatunsdi): Add 'mode'. (sparc_emit_fixunsdi): New prototype. * config/sparc/sparc.c (sparc_emit_floatunsdi): Use 'mode' argument. (sparc_emit_fixunsdi): New function. * config/sparc/sparc.md (floatunsdisf2): Use 'general_operand' for operand 1. Pass SFmode to sparc_emit_floatunsdi. (floatunsdidf2): Use 'general_operand' for operand 1. Pass DFmode to sparc_emit_floatunsdi. (fixuns_truncsfdi2): New expander. (fixuns_truncdfdi2): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@78511 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 13 ++++++++++ gcc/config/sparc/sparc-protos.h | 3 ++- gcc/config/sparc/sparc.c | 45 ++++++++++++++++++++++++++++++++--- gcc/config/sparc/sparc.md | 20 ++++++++++++---- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/fixuns-trunc-1.c | 31 ++++++++++++++++++++++++ 6 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/fixuns-trunc-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0ae22cb8a01..7818fed3841 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2004-02-26 Eric Botcazou + + * config/sparc/sparc-protos.h (sparc_emit_floatunsdi): Add 'mode'. + (sparc_emit_fixunsdi): New prototype. + * config/sparc/sparc.c (sparc_emit_floatunsdi): Use 'mode' argument. + (sparc_emit_fixunsdi): New function. + * config/sparc/sparc.md (floatunsdisf2): Use 'general_operand' for + operand 1. Pass SFmode to sparc_emit_floatunsdi. + (floatunsdidf2): Use 'general_operand' for operand 1. Pass DFmode + to sparc_emit_floatunsdi. + (fixuns_truncsfdi2): New expander. + (fixuns_truncdfdi2): Likewise. + 2004-02-26 Alan Modra * gcse.c (delete_null_pointer_checks_1): Do not delete CC setter diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index cc164df2d78..0908aaa5ea5 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -63,7 +63,8 @@ extern enum machine_mode select_cc_mode (enum rtx_code, rtx, rtx); /* Define the function that build the compare insn for scc and bcc. */ extern rtx gen_compare_reg (enum rtx_code code, rtx, rtx); extern void sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code); -extern void sparc_emit_floatunsdi (rtx [2]); +extern void sparc_emit_floatunsdi (rtx [2], enum machine_mode); +extern void sparc_emit_fixunsdi (rtx [2], enum machine_mode); extern void emit_tfmode_binop (enum rtx_code, rtx *); extern void emit_tfmode_unop (enum rtx_code, rtx *); extern void emit_tfmode_cvt (enum rtx_code, rtx *); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 258dfc2d81e..079ed5d9d16 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -6419,14 +6419,12 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) optabs would emit if we didn't have TFmode patterns. */ void -sparc_emit_floatunsdi (rtx *operands) +sparc_emit_floatunsdi (rtx *operands, enum machine_mode mode) { rtx neglab, donelab, i0, i1, f0, in, out; - enum machine_mode mode; out = operands[0]; in = force_reg (DImode, operands[1]); - mode = GET_MODE (out); neglab = gen_label_rtx (); donelab = gen_label_rtx (); i0 = gen_reg_rtx (DImode); @@ -6450,6 +6448,47 @@ sparc_emit_floatunsdi (rtx *operands) emit_label (donelab); } +/* Generate an FP to unsigned DImode conversion. This is the same code + optabs would emit if we didn't have TFmode patterns. */ + +void +sparc_emit_fixunsdi (rtx *operands, enum machine_mode mode) +{ + rtx neglab, donelab, i0, i1, f0, in, out, limit; + + out = operands[0]; + in = force_reg (mode, operands[1]); + neglab = gen_label_rtx (); + donelab = gen_label_rtx (); + i0 = gen_reg_rtx (DImode); + i1 = gen_reg_rtx (DImode); + limit = gen_reg_rtx (mode); + f0 = gen_reg_rtx (mode); + + emit_move_insn (limit, + CONST_DOUBLE_FROM_REAL_VALUE ( + REAL_VALUE_ATOF ("9223372036854775808.0", mode), mode)); + emit_cmp_and_jump_insns (in, limit, GE, NULL_RTX, mode, 0, neglab); + + emit_insn (gen_rtx_SET (VOIDmode, + out, + gen_rtx_FIX (DImode, gen_rtx_FIX (mode, in)))); + emit_jump_insn (gen_jump (donelab)); + emit_barrier (); + + emit_label (neglab); + + emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_MINUS (mode, in, limit))); + emit_insn (gen_rtx_SET (VOIDmode, + i0, + gen_rtx_FIX (DImode, gen_rtx_FIX (mode, f0)))); + emit_insn (gen_movdi (i1, const1_rtx)); + emit_insn (gen_ashldi3 (i1, i1, GEN_INT (63))); + emit_insn (gen_xordi3 (out, i0, i1)); + + emit_label (donelab); +} + /* Return the string to output a conditional branch to LABEL, testing register REG. LABEL is the operand number of the label; REG is the operand number of the reg. OP is the conditional expression. The mode diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 2a060b85be9..f0e69b17358 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -4662,9 +4662,9 @@ (define_expand "floatunsdisf2" [(use (match_operand:SF 0 "register_operand" "")) - (use (match_operand:DI 1 "register_operand" ""))] + (use (match_operand:DI 1 "general_operand" ""))] "TARGET_ARCH64 && TARGET_FPU" - "sparc_emit_floatunsdi (operands); DONE;") + "sparc_emit_floatunsdi (operands, SFmode); DONE;") (define_insn "floatdidf2" [(set (match_operand:DF 0 "register_operand" "=e") @@ -4676,9 +4676,9 @@ (define_expand "floatunsdidf2" [(use (match_operand:DF 0 "register_operand" "")) - (use (match_operand:DI 1 "register_operand" ""))] + (use (match_operand:DI 1 "general_operand" ""))] "TARGET_ARCH64 && TARGET_FPU" - "sparc_emit_floatunsdi (operands); DONE;") + "sparc_emit_floatunsdi (operands, DFmode); DONE;") (define_expand "floatditf2" [(set (match_operand:TF 0 "nonimmediate_operand" "") @@ -4747,6 +4747,12 @@ [(set_attr "type" "fp") (set_attr "fptype" "double")]) +(define_expand "fixuns_truncsfdi2" + [(use (match_operand:DI 0 "register_operand" "")) + (use (match_operand:SF 1 "general_operand" ""))] + "TARGET_ARCH64 && TARGET_FPU" + "sparc_emit_fixunsdi (operands, SFmode); DONE;") + (define_insn "fix_truncdfdi2" [(set (match_operand:DI 0 "register_operand" "=e") (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))] @@ -4755,6 +4761,12 @@ [(set_attr "type" "fp") (set_attr "fptype" "double")]) +(define_expand "fixuns_truncdfdi2" + [(use (match_operand:DI 0 "register_operand" "")) + (use (match_operand:DF 1 "general_operand" ""))] + "TARGET_ARCH64 && TARGET_FPU" + "sparc_emit_fixunsdi (operands, DFmode); DONE;") + (define_expand "fix_trunctfdi2" [(set (match_operand:DI 0 "register_operand" "") (fix:DI (match_operand:TF 1 "general_operand" "")))] diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e86d65422cd..508a19247d5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-02-26 Eric Botcazou + + * gcc.dg/fixuns-trunc-1.c: New test. + 2004-02-26 John David Anglin * gcc.dg/builtins-config.h: Use #elif. diff --git a/gcc/testsuite/gcc.dg/fixuns-trunc-1.c b/gcc/testsuite/gcc.dg/fixuns-trunc-1.c new file mode 100644 index 00000000000..0d094295249 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fixuns-trunc-1.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-options "-std=c99" } */ + +unsigned long foo(double d) +{ + return (unsigned long) d; +} + +extern void abort(void); + +int main(void) +{ + double d; + unsigned long l; + +#ifdef __LP64__ + d = 9223372036854775808.7; + l = 1LL << 63; + + if (foo(d) != l) + abort(); +#endif + + d = 122485.2; + l = 122485; + + if (foo(d) != l) + abort(); + + return 0; +} -- 2.11.4.GIT