diff options
author | DJ Delorie <dj@redhat.com> | 2004-03-24 08:05:40 -0500 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2004-03-24 13:05:40 +0000 |
commit | c235ddf27585e26c1e86bfec25e72bfef0debba0 (patch) | |
tree | d684b4f746c0f54995bb8c16528a406782106323 | |
parent | cf768d70b2beb8d16e558094ed518405b3046661 (diff) | |
download | gcc-c235ddf27585e26c1e86bfec25e72bfef0debba0.zip gcc-c235ddf27585e26c1e86bfec25e72bfef0debba0.tar.gz gcc-c235ddf27585e26c1e86bfec25e72bfef0debba0.tar.bz2 |
mips.h (MASK_FIX_VR4122, [...]): New macros.
* config/mips/mips.h (MASK_FIX_VR4122, TARGET_FIX_VR4122): New macros.
(TARGET_SWITCHES): Add -mfix-vr4122-bugs and -mno-fix-vr4122-bugs.
(ASM_SPEC): Pass down -mfix-vr4122-bugs.
* config/mips/mips.c (mips_avoid_hazards): Don't emit whole functions
in .set noreorder and .set nomacro if TARGET_FIX_VR4122.
(mips_init_libfuncs): Use special functions for divsi3 and modsi3
if TARGET_FIX_VR4122.
* config/mips/mips.md (define_attr length): Account for nops inserted
after macc and dmult when using -mfix-vr4122-bugs.
(umuldi3_highpart, divmodsi4, divmoddi4): Disable if TARGET_FIX_VR4122.
* config/mips/t-vr (LIB2FUNCS_STATIC_EXTRA): Define instead of
LIB2FUNCS_EXTRA. Add config/mips/vr4122-div.S.
* config/mips/vr4122-div.S: New file.
* doc/invoke.texi: Document -mfix-vr4122-bugs.
Co-Authored-By: Richard Sandiford <rsandifo@redhat.com>
From-SVN: r79912
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 19 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 7 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 25 | ||||
-rw-r--r-- | gcc/config/mips/t-vr | 3 | ||||
-rw-r--r-- | gcc/config/mips/vr4122-div.S | 75 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 20 |
7 files changed, 158 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 985a742..80a7cd1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2004-03-24 DJ Delorie <dj@redhat.com> + Richard Sandiford <rsandifo@redhat.com> + + * config/mips/mips.h (MASK_FIX_VR4122, TARGET_FIX_VR4122): New macros. + (TARGET_SWITCHES): Add -mfix-vr4122-bugs and -mno-fix-vr4122-bugs. + (ASM_SPEC): Pass down -mfix-vr4122-bugs. + * config/mips/mips.c (mips_avoid_hazards): Don't emit whole functions + in .set noreorder and .set nomacro if TARGET_FIX_VR4122. + (mips_init_libfuncs): Use special functions for divsi3 and modsi3 + if TARGET_FIX_VR4122. + * config/mips/mips.md (define_attr length): Account for nops inserted + after macc and dmult when using -mfix-vr4122-bugs. + (umuldi3_highpart, divmodsi4, divmoddi4): Disable if TARGET_FIX_VR4122. + * config/mips/t-vr (LIB2FUNCS_STATIC_EXTRA): Define instead of + LIB2FUNCS_EXTRA. Add config/mips/vr4122-div.S. + * config/mips/vr4122-div.S: New file. + * doc/invoke.texi: Document -mfix-vr4122-bugs. + 2004-03-24 Richard Sandiford <rsandifo@redhat.com> * config/mips/mips.h (PROCESSOR_R4130): New processor_type. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 5c1ce71..cbd248e 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -8721,8 +8721,10 @@ mips_avoid_hazards (void) cfun->machine->ignore_hazard_length_p = true; shorten_branches (get_insns ()); - /* The profiler code uses assembler macros. */ - cfun->machine->all_noreorder_p = !current_function_profile; + /* The profiler code uses assembler macros. -mfix-vr4122-bugs + relies on assembler nop insertion. */ + cfun->machine->all_noreorder_p = (!current_function_profile + && !TARGET_FIX_VR4122); last_insn = 0; hilo_delay = 2; @@ -8760,14 +8762,23 @@ mips_reorg (void) } } -/* We need to use a special set of functions to handle hard floating - point code in mips16 mode. Also, allow for --enable-gofast. */ +/* This function does three things: + + - Register the special divsi3 and modsi3 functions if -mfix-vr4122-bugs. + - Register the mips16 hardware floating point stubs. + - Register the gofast functions if selected using --enable-gofast. */ #include "config/gofast.h" static void mips_init_libfuncs (void) { + if (TARGET_FIX_VR4122) + { + set_optab_libfunc (sdiv_optab, SImode, "__vr4122_divsi3"); + set_optab_libfunc (smod_optab, SImode, "__vr4122_modsi3"); + } + if (TARGET_MIPS16 && mips16_hard_float) { set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3"); diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 7b079d8..c47637c 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -173,6 +173,7 @@ extern const struct mips_cpu_info *mips_tune_info; #define MASK_FIX_R4000 0x01000000 /* Work around R4000 errata. */ #define MASK_FIX_R4400 0x02000000 /* Work around R4400 errata. */ #define MASK_FIX_SB1 0x04000000 /* Work around SB-1 errata. */ +#define MASK_FIX_VR4122 0x08000000 /* Work-around VR4122 errata. */ /* Debug switches, not documented */ #define MASK_DEBUG 0 /* unused */ @@ -256,6 +257,7 @@ extern const struct mips_cpu_info *mips_tune_info; /* Work around R4400 errata. */ #define TARGET_FIX_R4400 (target_flags & MASK_FIX_R4400) +#define TARGET_FIX_VR4122 (target_flags & MASK_FIX_VR4122) /* True if we should use NewABI-style relocation operators for symbolic addresses. This is never true for mips16 code, @@ -606,6 +608,10 @@ extern const struct mips_cpu_info *mips_tune_info; N_("Work around R4400 errata")}, \ {"no-fix-r4400", -MASK_FIX_R4400, \ N_("Don't work around R4400 errata")}, \ + {"fix-vr4122-bugs", MASK_FIX_VR4122, \ + N_("Work around certain VR4122 errata")}, \ + {"no-fix-vr4122-bugs", -MASK_FIX_VR4122, \ + N_("Don't work around certain VR4122 errata")}, \ {"check-zero-division",-MASK_NO_CHECK_ZERO_DIV, \ N_("Trap on integer divide by zero")}, \ {"no-check-zero-division", MASK_NO_CHECK_ZERO_DIV, \ @@ -1109,6 +1115,7 @@ extern const struct mips_cpu_info *mips_tune_info; %{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \ %{mips32} %{mips32r2} %{mips64} \ %{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \ +%{mfix-vr4122-bugs} \ %(subtarget_asm_optimizing_spec) \ %(subtarget_asm_debugging_spec) \ %{membedded-pic} \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 45a106a..21b8277 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -212,6 +212,21 @@ (ne (symbol_ref "TARGET_MIPS16") (const_int 0))) (const_int 8) + ;; Various VR4122 errata require a nop to be inserted after a macc + ;; instruction. The assembler does this for us, so account for + ;; the worst-case length here. + (and (eq_attr "type" "imadd") + (ne (symbol_ref "TARGET_FIX_VR4122") (const_int 0))) + (const_int 8) + + ;; VR4122 errata MD(4): if there are consecutive dmult instructions, + ;; the result of the second one is missed. The assembler should work + ;; around this by inserting a nop after the first dmult. + (and (eq_attr "type" "imul") + (and (eq_attr "mode" "DI") + (ne (symbol_ref "TARGET_FIX_VR4122") (const_int 0)))) + (const_int 8) + (eq_attr "type" "idiv") (symbol_ref "mips_idiv_insns () * 4") ] (const_int 4))) @@ -2300,6 +2315,8 @@ [(set_attr "type" "imul") (set_attr "mode" "DI")]) +;; Disable this pattern for -mfix-vr4122-bugs. This is for VR4122 errata +;; MD(0), which says that dmultu does not always produce the correct result. (define_insn "umuldi3_highpart" [(set (match_operand:DI 0 "register_operand" "=h") (truncate:DI @@ -2309,7 +2326,7 @@ (zero_extend:TI (match_operand:DI 2 "register_operand" "d"))) (const_int 64)))) (clobber (match_scratch:DI 3 "=l"))] - "TARGET_64BIT && !TARGET_FIX_R4000" + "TARGET_64BIT && !TARGET_FIX_R4000 && !TARGET_FIX_VR4122" "dmultu\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "DI")]) @@ -2583,6 +2600,8 @@ (const_int 8) (const_int 4)))]) +;; VR4122 errata MD(A1): signed division instructions do not work correctly +;; with negative operands. We use special libgcc functions instead. (define_insn "divmodsi4" [(set (match_operand:SI 0 "register_operand" "=l") (div:SI (match_operand:SI 1 "register_operand" "d") @@ -2590,7 +2609,7 @@ (set (match_operand:SI 3 "register_operand" "=h") (mod:SI (match_dup 1) (match_dup 2)))] - "" + "!TARGET_FIX_VR4122" { return mips_output_division ("div\t$0,%1,%2", operands); } [(set_attr "type" "idiv") (set_attr "mode" "SI")]) @@ -2602,7 +2621,7 @@ (set (match_operand:DI 3 "register_operand" "=h") (mod:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT" + "TARGET_64BIT && !TARGET_FIX_VR4122" { return mips_output_division ("ddiv\t$0,%1,%2", operands); } [(set_attr "type" "idiv") (set_attr "mode" "DI")]) diff --git a/gcc/config/mips/t-vr b/gcc/config/mips/t-vr index 68daad8..2f0aef4 100644 --- a/gcc/config/mips/t-vr +++ b/gcc/config/mips/t-vr @@ -7,7 +7,8 @@ CRTSTUFF_T_CFLAGS = -G 0 # without the $gp register. TARGET_LIBGCC2_CFLAGS = -G 0 -LIB2FUNCS_EXTRA = $(srcdir)/config/mips/mips16.S +LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/mips16.S \ + $(srcdir)/config/mips/vr4122-div.S EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o # Assemble startup files. diff --git a/gcc/config/mips/vr4122-div.S b/gcc/config/mips/vr4122-div.S new file mode 100644 index 0000000..8936af1 --- /dev/null +++ b/gcc/config/mips/vr4122-div.S @@ -0,0 +1,75 @@ +/* Support file for -mfix-vr4122-bugs. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file contains functions which implement divsi3 and modsi3 for + -mfix-vr4122-bugs. div and ddiv do not give the correct result + when one of the operands is negative. */ + + .set nomips16 + +#define DIV \ + xor $3,$4,$5 /* t = x ^ y */ ; \ + li $2,0x80000000; \ + .set noreorder; \ + bgez $4,1f /* x >= 0 */; \ + and $3,$3,$2 /* t = (x ^ y) & 0x80000000 in delay slot */ ;\ + .set reorder; \ + subu $4,$0,$4 /* x = -x */ ; \ +1:; \ + .set noreorder; \ + bgez $5,2f /* y >= 0 */ ; \ + nop; \ + subu $5,$0,$5 /* y = -y */ ; \ + .set reorder; \ +2:; \ + divu $0,$4,$5; /* we use divu because of INT_MIN */ \ + .set noreorder; \ + bne $5,$0,3f; \ + nop; \ + break 7 /* division on zero y */ ; \ +3:; \ + .set reorder; \ + mflo $2 /* r = x / y */ ; \ + .set noreorder; \ + beq $3,$0,4f /* t == 0 */ ; \ + nop; \ + subu $2,$0,$2 /* r = -r */ ; \ + .set reorder; \ +4: + + .globl __vr4122_divsi3 + .ent __vr4122_divsi3 +__vr4122_divsi3: + DIV + j $31 + .end __vr4122_divsi3 + + .globl __vr4122_modsi3 + .ent __vr4122_modsi3 +__vr4122_modsi3: + move $6,$4 # x1 = x + move $7,$5 # y1 = y + DIV + mult $2,$7 # r = r * y1 + mflo $2 + .set noreorder + j $31 + subu $2,$6,$2 # r = x1 - r in delay slot + .end __vr4122_modsi3 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 59e02a0..8c6e440 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -479,7 +479,7 @@ in the following sections. -mmemcpy -mno-memcpy -mlong-calls -mno-long-calls @gol -mmad -mno-mad -mfused-madd -mno-fused-madd -nocpp @gol -mfix-r4000 -mno-fix-r4000 -mfix-r4400 -mno-fix-r4400 @gol --mfix-sb1 -mno-fix-sb1 @gol +-mfix-vr4122-bugs -mno-fix-vr4122-bugs -mfix-sb1 -mno-fix-sb1 @gol -mflush-func=@var{func} -mno-flush-func @gol -mbranch-likely -mno-branch-likely} @@ -8092,6 +8092,24 @@ A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division. @end itemize +@item -mfix-vr4122-bugs +@itemx -mno-fix-vr4122-bugs +@opindex mfix-vr4122-bugs +Work around certain VR4122 errata: +@itemize @minus +@item +@code{dmultu} does not always produce the correct result. +@item +@code{div} and @code{ddiv} do not always produce the correct result if one +of the operands is negative. +@end itemize +The workarounds for the division errata rely on special functions in +@file{libgcc.a}. At present, these functions are only provided by +the @code{mips64vr*-elf} configurations. + +Other VR4122 errata require a nop to be inserted between certain pairs of +instructions. These errata are handled by the assembler, not by GCC itself. + @item -mfix-sb1 @itemx -mno-fix-sb1 @opindex mfix-sb1 |