]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
sparc-protos.h (sparc_emit_floatunsdi): Add 'mode'.
authorEric Botcazou <ebotcazou@act-europe.fr>
Thu, 26 Feb 2004 18:40:41 +0000 (19:40 +0100)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Thu, 26 Feb 2004 18:40:41 +0000 (18:40 +0000)
* 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

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/fixuns-trunc-1.c [new file with mode: 0644]

index 0ae22cb8a01fd33b361694e0b0c17d0015604de6..7818fed3841370c692006fc7157182670467492a 100644 (file)
@@ -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
index cc164df2d78b2196730ef74b9579313b65f855e8..0908aaa5ea58f53ffbbfa0c8ad01c31ec539b4e2 100644 (file)
@@ -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 *);
index 258dfc2d81e545d39f246a28ab5498f9de7a2706..079ed5d9d164a39078ef05efb7066f9e5abeb24c 100644 (file)
@@ -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
index 2a060b85be9cb421209aa922529c23eb7d9934ff..f0e69b173589ad458e2b6ad3a34b3851081241ce 100644 (file)
 
 (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")
 
 (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" "")
   [(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"))))]
   [(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" "")))]
index e86d65422cdd2486bb16e60a1f37a701c5c3404a..508a19247d5b49b86010bae2103d7a1fe3fa1cb1 100644 (file)
@@ -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 (file)
index 0000000..0d09429
--- /dev/null
@@ -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;
+}