summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/gcc
diff options
context:
space:
mode:
authorMartynas Venckus <martynas@cvs.openbsd.org>2009-02-11 09:00:28 +0000
committerMartynas Venckus <martynas@cvs.openbsd.org>2009-02-11 09:00:28 +0000
commit580c7b022fa4569bf05dc252ae51284071a7dcb3 (patch)
tree9b1daa794c5822882720cc0cc4b88ffd77ba6b6a /gnu/usr.bin/gcc
parent2da7579abfe44e4309adedc035de2a831086b3ee (diff)
fix gcc bug that broke double -> unsigned long conversions on sparc64
(TF floats between conversions). also fixes perl. reported and tested by naddy@. been in snaps for months. go ahead miod@
Diffstat (limited to 'gnu/usr.bin/gcc')
-rw-r--r--gnu/usr.bin/gcc/gcc/config/sparc/sparc-protos.h4
-rw-r--r--gnu/usr.bin/gcc/gcc/config/sparc/sparc.c46
-rw-r--r--gnu/usr.bin/gcc/gcc/config/sparc/sparc.md80
3 files changed, 75 insertions, 55 deletions
diff --git a/gnu/usr.bin/gcc/gcc/config/sparc/sparc-protos.h b/gnu/usr.bin/gcc/gcc/config/sparc/sparc-protos.h
index 0aa6e58f7da..43e705a0a6e 100644
--- a/gnu/usr.bin/gcc/gcc/config/sparc/sparc-protos.h
+++ b/gnu/usr.bin/gcc/gcc/config/sparc/sparc-protos.h
@@ -73,7 +73,8 @@ extern enum machine_mode select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
/* Define the function that build the compare insn for scc and bcc. */
extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx));
extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code));
-extern void sparc_emit_floatunsdi PARAMS ((rtx [2]));
+extern void sparc_emit_floatunsdi PARAMS ((rtx [2], enum machine_mode));
+extern void sparc_emit_fixunsdi PARAMS ((rtx [2], enum machine_mode));
extern void emit_tfmode_binop PARAMS ((enum rtx_code, rtx *));
extern void emit_tfmode_unop PARAMS ((enum rtx_code, rtx *));
extern void emit_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
@@ -88,6 +89,7 @@ extern void sparc_emit_set_const64 PARAMS ((rtx, rtx));
extern void sparc_emit_set_symbolic_const64 PARAMS ((rtx, rtx, rtx));
extern int sparc_splitdi_legitimate PARAMS ((rtx, rtx));
extern int sparc_absnegfloat_split_legitimate PARAMS ((rtx, rtx));
+extern const char *output_ubranch PARAMS ((rtx, int, rtx));
extern char *output_cbranch PARAMS ((rtx, rtx, int, int, int, int, rtx));
extern const char *output_sibcall PARAMS ((rtx, rtx));
extern char *output_v9branch PARAMS ((rtx, rtx, int, int, int, int, int,
diff --git a/gnu/usr.bin/gcc/gcc/config/sparc/sparc.c b/gnu/usr.bin/gcc/gcc/config/sparc/sparc.c
index eafc24a3c0e..4216416529a 100644
--- a/gnu/usr.bin/gcc/gcc/config/sparc/sparc.c
+++ b/gnu/usr.bin/gcc/gcc/config/sparc/sparc.c
@@ -5910,15 +5910,14 @@ sparc_emit_float_lib_cmp (x, y, comparison)
optabs would emit if we didn't have TFmode patterns. */
void
-sparc_emit_floatunsdi (operands)
+sparc_emit_floatunsdi (operands, mode)
rtx operands[2];
+ 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);
@@ -5942,6 +5941,47 @@ sparc_emit_floatunsdi (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/gnu/usr.bin/gcc/gcc/config/sparc/sparc.md b/gnu/usr.bin/gcc/gcc/config/sparc/sparc.md
index b53013ec397..2d149a3f3a8 100644
--- a/gnu/usr.bin/gcc/gcc/config/sparc/sparc.md
+++ b/gnu/usr.bin/gcc/gcc/config/sparc/sparc.md
@@ -1,8 +1,8 @@
;; Machine description for SPARC chip for GNU C compiler
;; Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@cygnus.com)
-;; 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
+;; 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
;; at Cygnus Support.
;; This file is part of GNU CC.
@@ -120,6 +120,8 @@
(symbol_ref "TARGET_FLAT != 0"))
;; Length (in # of insns).
+;; Beware that setting a length greater or equal to 3 for conditional branches
+;; has a side-effect (see output_cbranch and output_v9branch).
(define_attr "length" ""
(cond [(eq_attr "type" "uncond_branch,call,sibcall")
(if_then_else (eq_attr "empty_delay_slot" "true")
@@ -290,10 +292,13 @@
(define_expand "cmpsi"
[(set (reg:CC 100)
- (compare:CC (match_operand:SI 0 "register_operand" "")
+ (compare:CC (match_operand:SI 0 "compare_operand" "")
(match_operand:SI 1 "arith_operand" "")))]
""
{
+ if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
+ operands[0] = force_reg (SImode, operands[0]);
+
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
@@ -301,10 +306,13 @@
(define_expand "cmpdi"
[(set (reg:CCX 100)
- (compare:CCX (match_operand:DI 0 "register_operand" "")
+ (compare:CCX (match_operand:DI 0 "compare_operand" "")
(match_operand:DI 1 "arith_double_operand" "")))]
"TARGET_ARCH64"
{
+ if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
+ operands[0] = force_reg (DImode, operands[0]);
+
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
@@ -4637,9 +4645,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")
@@ -4651,9 +4659,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" "")
@@ -4722,6 +4730,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"))))]
@@ -4730,6 +4744,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" "")))]
@@ -7212,27 +7232,10 @@
[(set_attr "type" "shift")])
;; Unconditional and other jump instructions
-;; On the SPARC, by setting the annul bit on an unconditional branch, the
-;; following insn is never executed. This saves us a nop. Dbx does not
-;; handle such branches though, so we only use them when optimizing.
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
-{
- /* TurboSPARC is reported to have problems with
- with
- foo: b,a foo
- i.e. an empty loop with the annul bit set. The workaround is to use
- foo: b foo; nop
- instead. */
-
- if (! TARGET_V9 && flag_delayed_branch
- && (INSN_ADDRESSES (INSN_UID (operands[0]))
- == INSN_ADDRESSES (INSN_UID (insn))))
- return "b\t%l0%#";
- else
- return TARGET_V9 ? "ba%*,pt\t%%xcc, %l0%(" : "b%*\t%l0%(";
-}
+ "* return output_ubranch (operands[0], 0, insn);"
[(set_attr "type" "uncond_branch")])
(define_expand "tablejump"
@@ -8239,31 +8242,6 @@
[(set_attr "type" "multi")
(set_attr "length" "2")])
-;; Now peepholes to do a call followed by a jump.
-
-(define_peephole
- [(parallel [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
- (match_operand 2 "" "")))
- (clobber (reg:SI 15))])
- (set (pc) (label_ref (match_operand 3 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
- && sparc_cpu != PROCESSOR_ULTRASPARC
- && sparc_cpu != PROCESSOR_ULTRASPARC3"
- "call\t%a1, %2\n\tadd\t%%o7, (%l3-.-4), %%o7")
-
-(define_peephole
- [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
- (match_operand 1 "" ""))
- (clobber (reg:SI 15))])
- (set (pc) (label_ref (match_operand 2 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
- && sparc_cpu != PROCESSOR_ULTRASPARC
- && sparc_cpu != PROCESSOR_ULTRASPARC3"
- "call\t%a0, %1\n\tadd\t%%o7, (%l2-.-4), %%o7")
-
;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
;; ??? operations. With DFA we might be able to model this, but it requires a lot of