diff options
author | Martynas Venckus <martynas@cvs.openbsd.org> | 2009-02-11 09:00:28 +0000 |
---|---|---|
committer | Martynas Venckus <martynas@cvs.openbsd.org> | 2009-02-11 09:00:28 +0000 |
commit | 580c7b022fa4569bf05dc252ae51284071a7dcb3 (patch) | |
tree | 9b1daa794c5822882720cc0cc4b88ffd77ba6b6a /gnu/usr.bin/gcc | |
parent | 2da7579abfe44e4309adedc035de2a831086b3ee (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.h | 4 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config/sparc/sparc.c | 46 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config/sparc/sparc.md | 80 |
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 |