aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@act-europe.fr>2004-02-26 19:40:41 +0100
committerEric Botcazou <ebotcazou@gcc.gnu.org>2004-02-26 18:40:41 +0000
commitb178305dfd934a716c1175039bec2f5f73215fc1 (patch)
treed6f5e3147f395bd8303240d39b62e901c7e3b6d4 /gcc
parent413580dc797ecbbf4246f19f53ba1aa0bd9fcfdf (diff)
downloadgcc-b178305dfd934a716c1175039bec2f5f73215fc1.zip
gcc-b178305dfd934a716c1175039bec2f5f73215fc1.tar.gz
gcc-b178305dfd934a716c1175039bec2f5f73215fc1.tar.bz2
sparc-protos.h (sparc_emit_floatunsdi): Add 'mode'.
* 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. From-SVN: r78511
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/sparc/sparc-protos.h3
-rw-r--r--gcc/config/sparc/sparc.c45
-rw-r--r--gcc/config/sparc/sparc.md20
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/fixuns-trunc-1.c31
6 files changed, 108 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0ae22cb..7818fed 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2004-02-26 Eric Botcazou <ebotcazou@act-europe.fr>
+
+ * 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 <amodra@bigpond.net.au>
* 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 cc164df..0908aaa 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 258dfc2..079ed5d 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 2a060b8..f0e69b1 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 e86d654..508a192 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-02-26 Eric Botcazou <ebotcazou@act-europe.fr>
+
+ * gcc.dg/fixuns-trunc-1.c: New test.
+
2004-02-26 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* 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 0000000..0d09429
--- /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;
+}